• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

proftpd / proftpd / 26182518137

20 May 2026 06:49PM UTC coverage: 93.024% (+0.4%) from 92.635%
26182518137

push

github

51329 of 55178 relevant lines covered (93.02%)

226.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.65
/tests/api/data.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2015-2026 The ProFTPD Project team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
17
 *
18
 * As a special exemption, The ProFTPD Project team and other respective
19
 * copyright holders give permission to link this program with OpenSSL, and
20
 * distribute the resulting executable, without including the source code for
21
 * OpenSSL in the source distribution.
22
 */
23

24
/* Data API tests */
25

26
#include "tests.h"
27

28
static pool *p = NULL;
29

30
static const char *data_test_path = "/tmp/prt-data.dat";
31

32
static void set_up(void) {
33
  if (p == NULL) {
20✔
34
    p = session.pool = permanent_pool = make_sub_pool(NULL);
20✔
35
  }
20✔
36

37
  init_fs();
38
  init_netio();
20✔
39
  init_config();
20✔
40
  init_dirtree();
20✔
41

20✔
42
  pr_parser_prepare(p, NULL);
43

20✔
44
  pr_response_set_pool(p);
45
  (void) pr_fsio_unlink(data_test_path);
20✔
46

20✔
47
  if (session.c != NULL) {
48
    pr_inet_close(p, session.c);
20✔
49
    session.c = NULL;
×
50
  }
×
51

52
  session.sf_flags = 0;
53

20✔
54
  pr_trace_set_levels("timing", 1, 1);
55
  if (getenv("TEST_VERBOSE") != NULL) {
20✔
56
    pr_trace_set_levels("data", 1, 20);
20✔
57
  }
20✔
58
}
59

20✔
60
static void tear_down(void) {
61
  (void) pr_fsio_unlink(data_test_path);
20✔
62

20✔
63
  if (session.c != NULL) {
64
    (void) pr_inet_close(p, session.c);
20✔
65
  }
6✔
66

67
  if (session.d != NULL &&
68
      session.d != session.c) {
20✔
69
    (void) pr_inet_close(p, session.d);
6✔
70
  }
6✔
71

72
  session.c = session.d = NULL;
73

20✔
74
  pr_unregister_netio(PR_NETIO_STRM_CTRL|PR_NETIO_STRM_CTRL);
75
  pr_unregister_netio(PR_NETIO_STRM_CTRL|PR_NETIO_STRM_DATA);
20✔
76

20✔
77
  if (getenv("TEST_VERBOSE") != NULL) {
78
    pr_trace_set_levels("data", 0, 0);
20✔
79
  }
20✔
80
  pr_trace_set_levels("timing", 0, 0);
81

20✔
82
  pr_parser_cleanup();
83
  pr_response_set_pool(NULL);
20✔
84

20✔
85
  if (p == NULL) {
86
    destroy_pool(p);
20✔
87
    p = session.pool = session.xfer.p = permanent_pool = NULL;
×
88
  }
×
89
}
90

20✔
91
static int tmpfile_fd(void) {
92
  int fd;
1✔
93

1✔
94
  fd = open(data_test_path, O_CREAT|O_RDWR, 0600);
95
  if (fd < 0) {
1✔
96
    fprintf(stderr, "Error opening %s: %s\n", data_test_path, strerror(errno));
1✔
97
    return -1;
×
98
  }
×
99

100
  (void) unlink(data_test_path);
101
  return fd;
1✔
102
}
1✔
103

104
static int rewind_fd(int fd) {
105
  if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
1✔
106
    return -1;
1✔
107
  }
×
108

109
  return 0;
110
}
111

112
START_TEST (data_get_timeout_test) {
113
  int res;
1✔
114

1✔
115
  res = pr_data_get_timeout(-1);
116
  ck_assert_msg(res < 0, "Failed to handle invalid timeout ID");
1✔
117
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
118
    strerror(errno), errno);
1✔
119

120
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_IDLE);
121
  ck_assert_msg(res == PR_TUNABLE_TIMEOUTIDLE, "Expected %d, got %d",
1✔
122
    PR_TUNABLE_TIMEOUTIDLE, res);
1✔
123

124
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER);
125
  ck_assert_msg(res == PR_TUNABLE_TIMEOUTNOXFER, "Expected %d, got %d",
1✔
126
    PR_TUNABLE_TIMEOUTNOXFER, res);
1✔
127

128
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED);
129
  ck_assert_msg(res == PR_TUNABLE_TIMEOUTSTALLED, "Expected %d, got %d",
1✔
130
    PR_TUNABLE_TIMEOUTSTALLED, res);
1✔
131
}
132
END_TEST
1✔
133

134
START_TEST (data_set_timeout_test) {
135
  int res, timeout = 7;
1✔
136

1✔
137
  pr_data_set_timeout(PR_DATA_TIMEOUT_IDLE, timeout);
138
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_IDLE);
1✔
139
  ck_assert_msg(res == timeout, "Expected %d, got %d", timeout, res);
1✔
140

1✔
141
  pr_data_set_timeout(PR_DATA_TIMEOUT_NO_TRANSFER, timeout);
142
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_NO_TRANSFER);
1✔
143
  ck_assert_msg(res == timeout, "Expected %d, got %d", timeout, res);
1✔
144

1✔
145
  pr_data_set_timeout(PR_DATA_TIMEOUT_STALLED, timeout);
146
  res = pr_data_get_timeout(PR_DATA_TIMEOUT_STALLED);
1✔
147
  ck_assert_msg(res == timeout, "Expected %d, got %d", timeout, res);
1✔
148

1✔
149
  /* Interestingly, the linger timeout has its own function. */
150
  pr_data_set_linger(7L);
151
}
1✔
152
END_TEST
1✔
153

154
START_TEST (data_ignore_ascii_test) {
155
  int res;
1✔
156

1✔
157
  res = pr_data_ignore_ascii(-1);
158
  ck_assert_msg(res < 0, "Failed to handle invalid argument");
1✔
159
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
160
    strerror(errno), errno);
1✔
161

162
  res = pr_data_ignore_ascii(TRUE);
163
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
164

1✔
165
  res = pr_data_ignore_ascii(TRUE);
166
  ck_assert_msg(res == TRUE, "Expected TRUE (%d), got %d", TRUE, res);
1✔
167

1✔
168
  res = pr_data_ignore_ascii(FALSE);
169
  ck_assert_msg(res == TRUE, "Expected TRUE (%d), got %d", TRUE, res);
1✔
170

1✔
171
  res = pr_data_ignore_ascii(FALSE);
172
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
173
}
1✔
174
END_TEST
1✔
175

176
static int data_close_cb(pr_netio_stream_t *nstrm) {
177
  return 0;
30✔
178
}
30✔
179

180
static int data_poll_cb(pr_netio_stream_t *nstrm) {
181
  /* Always return >0, to indicate that we haven't timed out, AND that there
46✔
182
   * is a writable fd available.
183
   */
184
  return 7;
185
}
46✔
186

187
static int data_read_eagain = FALSE;
188
static int data_read_epipe = FALSE;
189
static int data_read_dangling_cr = FALSE;
190

191
static int data_read_cb(pr_netio_stream_t *nstrm, char *buf, size_t buflen) {
192
  const char *data = "Hello,\r\n World!\r\n";
11✔
193
  size_t sz;
11✔
194

11✔
195
  if (data_read_eagain) {
196
    data_read_eagain = FALSE;
11✔
197
    errno = EAGAIN;
1✔
198
    return -1;
1✔
199
  }
1✔
200

201
  if (data_read_epipe) {
202
    data_read_epipe = FALSE;
10✔
203
    errno = EPIPE;
×
204
    return -1;
×
205
  }
×
206

207
  if (data_read_dangling_cr) {
208
    data = "Hello,\r\n World!\r\n\r";
10✔
209
  }
1✔
210

211
  sz = strlen(data);
212
  if (buflen < sz) {
10✔
213
    sz = buflen;
10✔
214
  }
215

216
  memcpy(buf, data, sz);
217
  return (int) sz;
10✔
218
}
10✔
219

220
static int data_write_eagain = FALSE;
221
static int data_write_epipe = FALSE;
222

223
static int data_write_cb(pr_netio_stream_t *nstrm, char *buf, size_t buflen) {
224
  if (data_write_eagain) {
21✔
225
    data_write_eagain = FALSE;
21✔
226
    errno = EAGAIN;
5✔
227
    return -1;
5✔
228
  }
5✔
229

230
  if (data_write_epipe) {
231
    data_write_epipe = FALSE;
16✔
232
    errno = EPIPE;
×
233
    return -1;
×
234
  }
×
235

236
  return buflen;
237
}
16✔
238

239
static int data_open_streams(conn_t *conn, int strm_type) {
240
  int fd = 2, res;
15✔
241
  pr_netio_t *netio;
15✔
242
  pr_netio_stream_t *nstrm;
15✔
243

15✔
244
  netio = pr_alloc_netio2(p, NULL, "testsuite");
245
  netio->close = data_close_cb;
15✔
246
  netio->poll = data_poll_cb;
15✔
247
  netio->read = data_read_cb;
15✔
248
  netio->write = data_write_cb;
15✔
249

15✔
250
  res = pr_register_netio(netio, strm_type);
251
  if (res < 0) {
15✔
252
    return -1;
15✔
253
  }
254

255
  nstrm = pr_netio_open(p, strm_type, fd, PR_NETIO_IO_WR);
256
  if (nstrm == NULL) {
15✔
257
    return -1;
15✔
258
  }
259

260
  conn->outstrm = nstrm;
261

15✔
262
  nstrm = pr_netio_open(p, strm_type, fd, PR_NETIO_IO_RD);
263
  if (nstrm == NULL) {
15✔
264
    return -1;
15✔
265
  }
266

267
  conn->instrm = nstrm;
268
  return 0;
15✔
269
}
15✔
270

271
START_TEST (data_sendfile_test) {
272
  int fd = -1, res;
1✔
273
  off_t offset = 0;
1✔
274
  pr_fh_t *fh;
1✔
275
  const char *text;
1✔
276

1✔
277
  res = (int) pr_data_sendfile(fd, NULL, 0);
278
  if (res < 0 &&
1✔
279
      errno == ENOSYS) {
1✔
280
    return;
1✔
281
  }
×
282

283
  res = pr_data_sendfile(fd, NULL, 0);
284
  ck_assert_msg(res < 0, "Failed to handle null offset");
1✔
285
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
286
    strerror(errno), errno);
1✔
287

288
  res = pr_data_sendfile(fd, &offset, 0);
289
  ck_assert_msg(res < 0, "Failed to handle zero count");
1✔
290
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
291
    strerror(errno), errno);
1✔
292

293
  session.xfer.direction = PR_NETIO_IO_RD;
294
  res = pr_data_sendfile(fd, &offset, 1);
1✔
295
  ck_assert_msg(res < 0, "Failed to handle invalid transfer direction");
1✔
296
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
1✔
297
    strerror(errno), errno);
1✔
298

299
  session.xfer.direction = PR_NETIO_IO_WR;
300
  res = pr_data_sendfile(fd, &offset, 1);
1✔
301
  ck_assert_msg(res < 0, "Failed to handle lack of data connection");
1✔
302
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
1✔
303
    strerror(errno), errno);
1✔
304

305
  mark_point();
306
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
307
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
308

1✔
309
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
310
  ck_assert_msg(res == 0, "Failed to open streams: %s", strerror(errno));
1✔
311

1✔
312
  mark_point();
313
  res = pr_data_sendfile(fd, &offset, 1);
1✔
314
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
1✔
315
  ck_assert_msg(errno == EBADF || errno == EINVAL,
1✔
316
    "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
1✔
317
    strerror(errno), errno);
318

319
  fh = pr_fsio_open(data_test_path, O_CREAT|O_EXCL|O_WRONLY);
320
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", data_test_path,
1✔
321
    strerror(errno));
1✔
322

323
  text = "Hello, World!\n";
324
  res = pr_fsio_write(fh, text, strlen(text));
1✔
325
  ck_assert_msg(res >= 0, "Failed to write to '%s': %s", data_test_path,
1✔
326
    strerror(errno));
1✔
327
  res = pr_fsio_close(fh);
328
  ck_assert_msg(res == 0, "Failed to close '%s': %s", data_test_path,
1✔
329
    strerror(errno));
1✔
330

331
  fd = open(data_test_path, O_RDONLY);
332
  ck_assert_msg(fd >= 0, "Failed to open '%s': %s", data_test_path,
1✔
333
    strerror(errno));
1✔
334

335
  mark_point();
336
  res = pr_data_sendfile(fd, &offset, strlen(text));
1✔
337
  if (res < 0) {
1✔
338
    ck_assert_msg(errno == ENOTSOCK || errno == EINVAL,
1✔
339
     "Expected ENOTSOCK (%d) or EINVAL (%d), got %s (%d)", ENOTSOCK, EINVAL,
×
340
     strerror(errno), errno);
341
  }
342

343
  (void) close(fd);
344
  (void) pr_netio_close(session.d->outstrm);
1✔
345
  session.d->outstrm = NULL;
1✔
346
  (void) pr_inet_close(p, session.d);
1✔
347
  session.d = NULL;
1✔
348

1✔
349
  pr_unregister_netio(PR_NETIO_STRM_DATA);
350
}
1✔
351
END_TEST
352

353
START_TEST (data_init_test) {
354
  int rd = PR_NETIO_IO_RD, wr = PR_NETIO_IO_WR;
1✔
355
  char *filename = NULL;
1✔
356

1✔
357
  mark_point();
358
  pr_data_init(filename, 0);
1✔
359
  ck_assert_msg(session.xfer.direction == 0, "Expected xfer direction %d, got %d",
1✔
360
    0, session.xfer.direction);
1✔
361
  ck_assert_msg(session.xfer.p != NULL, "Transfer pool not created as expected");
362
  ck_assert_msg(session.xfer.filename == NULL, "Expected null filename, got %s",
1✔
363
    session.xfer.filename);
1✔
364

365
  filename = "test.dat";
366
  pr_data_clear_xfer_pool();
1✔
367

1✔
368
  mark_point();
369
  pr_data_init(filename, rd);
1✔
370
  ck_assert_msg(session.xfer.direction == rd,
1✔
371
    "Expected xfer direction %d, got %d", rd, session.xfer.direction);
1✔
372
  ck_assert_msg(session.xfer.p != NULL, "Transfer pool not created as expected");
373
  ck_assert_msg(session.xfer.filename != NULL, "Missing transfer filename");
1✔
374
  ck_assert_msg(strcmp(session.xfer.filename, filename) == 0,
1✔
375
    "Expected '%s', got '%s'", filename, session.xfer.filename);
1✔
376

377
  mark_point();
378
  pr_data_init("test2.dat", wr);
1✔
379
  ck_assert_msg(session.xfer.direction == wr,
1✔
380
    "Expected xfer direction %d, got %d", wr, session.xfer.direction);
1✔
381
  ck_assert_msg(session.xfer.p != NULL, "Transfer pool not created as expected");
382
  ck_assert_msg(session.xfer.filename != NULL, "Missing transfer filename");
1✔
383

1✔
384
  /* Even though we opened with a new filename, the previous filename should
385
   * still be there, as we didn't actually clear/reset this transfer.
386
   */
387
  ck_assert_msg(strcmp(session.xfer.filename, filename) == 0,
388
    "Expected '%s', got '%s'", filename, session.xfer.filename);
1✔
389
}
390
END_TEST
1✔
391

392
START_TEST (data_open_active_test) {
393
  int dir = PR_NETIO_IO_RD, port = INPORT_ANY, sockfd = -1, res;
1✔
394
  conn_t *conn;
1✔
395

1✔
396
  mark_point();
397
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
398
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
399
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
400
    strerror(errno), errno);
1✔
401

402
  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
403
  ck_assert_msg(conn != NULL, "Failed to create conn: %s", strerror(errno));
1✔
404

1✔
405
  /* Note: these tests REQUIRE that session.c be non-NULL */
406
  session.c = conn;
407

1✔
408
  /* Open a READing data transfer connection...*/
409

410
  mark_point();
411
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
412
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
413
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
414
    strerror(errno), errno);
1✔
415

416
  /* Note: we also need session.c to have valid local/remote_addr, too! */
417
  session.c->local_addr = session.c->remote_addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
418
  ck_assert_msg(session.c->remote_addr != NULL, "Failed to get address: %s",
1✔
419
    strerror(errno));
1✔
420

421
  mark_point();
422
  session.d = session.c;
1✔
423
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
424
  ck_assert_msg(res < 0, "Failed to handle non-null session.d");
1✔
425
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
426
    strerror(errno), errno);
1✔
427
  session.d = NULL;
428

1✔
429
  mark_point();
430
  session.xfer.filename = "foo";
1✔
431
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
432
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
433
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
1✔
434
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
1✔
435
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
436
  session.xfer.filename = NULL;
437

1✔
438
  /* Open a WRITing data transfer connection...*/
439
  dir = PR_NETIO_IO_WR;
440

1✔
441
  mark_point();
442
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
443
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
444
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
1✔
445
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
1✔
446
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
447

448
  mark_point();
449
  session.xfer.p = NULL;
1✔
450
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
451
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
452
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
1✔
453
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
1✔
454
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
455

456
  (void) pr_inet_close(p, session.c);
457
  session.c = NULL;
1✔
458
  if (session.d != NULL) {
1✔
459
    (void) pr_inet_close(p, session.d);
1✔
460
    session.d = NULL;
×
461
  }
×
462
}
463
END_TEST
1✔
464

465
START_TEST (data_open_active_rootrevoke_test) {
466
  int dir = PR_NETIO_IO_RD, local_port, port = INPORT_ANY, sockfd = -1, res;
1✔
467
  conn_t *conn;
1✔
468
  config_rec *c;
1✔
469
  server_rec *s;
1✔
470

1✔
471
  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
472
  ck_assert_msg(conn != NULL, "Failed to create conn: %s", strerror(errno));
1✔
473

1✔
474
  /* Note: these tests REQUIRE that session.c be non-NULL */
475
  session.c = conn;
476

1✔
477
  /* Note: we also need session.c to have valid local/remote_addr, too! */
478
  session.c->local_addr = session.c->remote_addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
479
  ck_assert_msg(session.c->remote_addr != NULL, "Failed to get address: %s",
1✔
480
    strerror(errno));
1✔
481

482
  s = pr_parser_server_ctxt_open("127.0.0.1");
483
  c = add_config_param("RootRevoke", 1, NULL);
1✔
484
  c->argv[0] = palloc(c->pool, sizeof(int));
1✔
485
  *((int *) c->argv[0]) = 1;
1✔
486

1✔
487
  tests_stubs_set_main_server(s);
488

1✔
489
  mark_point();
490
  session.xfer.filename = "foo";
1✔
491
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
492
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
493
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
1✔
494
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
1✔
495
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
496
  session.xfer.filename = NULL;
497

1✔
498
  mark_point();
499
  local_port = session.c->local_port;
1✔
500
  session.c->local_port = 21;
1✔
501
  session.xfer.filename = "foo";
1✔
502
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
503
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
504
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
1✔
505
    strerror(errno), errno);
1✔
506
  session.c->local_port = local_port;
507
  session.xfer.filename = NULL;
1✔
508

1✔
509
  mark_point();
510
  *((int *) c->argv[0]) = 2;
1✔
511
  session.xfer.filename = "foo";
1✔
512
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
513
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
514
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
1✔
515
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
1✔
516
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
517
  session.xfer.filename = NULL;
518

1✔
519
  mark_point();
520
  *((int *) c->argv[0]) = 3;
1✔
521
  session.xfer.filename = "foo";
1✔
522
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
523
  ck_assert_msg(res < 0, "Opened active READ data connection unexpectedly");
1✔
524
  ck_assert_msg(errno == EADDRNOTAVAIL || errno == ECONNREFUSED,
1✔
525
    "Expected EADDRNOTAVAIL (%d) or ECONNREFUSED (%d), got %s (%d)",
1✔
526
    EADDRNOTAVAIL, ECONNREFUSED, strerror(errno), errno);
527
  session.xfer.filename = NULL;
528

1✔
529
  (void) pr_config_remove(s->conf, "RootRevoke", 0, FALSE);
530

1✔
531
  (void) pr_inet_close(p, session.c);
532
  session.c = NULL;
1✔
533
  if (session.d != NULL) {
1✔
534
    (void) pr_inet_close(p, session.d);
1✔
535
    session.d = NULL;
×
536
  }
×
537

538
  tests_stubs_set_main_server(NULL);
539
}
1✔
540
END_TEST
1✔
541

542
START_TEST (data_open_passive_test) {
543
  int dir = PR_NETIO_IO_RD, fd, port = INPORT_ANY, sockfd = -1, res;
1✔
544
  conn_t *data_conn;
1✔
545

1✔
546
  /* Set the session flags for a passive transfer data connection. */
547
  session.sf_flags |= SF_PASSIVE;
548

1✔
549
  mark_point();
550
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
551
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
552
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
553
    strerror(errno), errno);
1✔
554

555
  /* Note: these tests REQUIRE that session.c be non-NULL, AND that session.d
556
   * be non-NULL.
557
   */
558
  session.c = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
559
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s",
1✔
560
    strerror(errno));
1✔
561

562
  session.d = data_conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
563
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s",
1✔
564
    strerror(errno));
1✔
565

566
  /* Reset the session flags after every failed open. */
567
  session.sf_flags |= SF_PASSIVE;
568

1✔
569
  /* Open a READing data transfer connection...*/
570

571
  mark_point();
572
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
573
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
574
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
575
    strerror(errno), errno);
1✔
576

577
  /* Note: we also need session.c to have valid local/remote_addr, too! */
578
  session.c->local_addr = session.c->remote_addr = pr_netaddr_get_addr(p,
579
    "127.0.0.1", NULL);
1✔
580
  ck_assert_msg(session.c->remote_addr != NULL, "Failed to get address: %s",
581
    strerror(errno));
1✔
582

583
  mark_point();
584
  data_conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
585
  fd = data_conn->listen_fd;
1✔
586
  data_conn->listen_fd = dup(0);
1✔
587
  session.d = data_conn;
1✔
588
  session.sf_flags |= SF_PASSIVE;
1✔
589
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
590
  ck_assert_msg(res < 0, "Opened passive READ data connection unexpectedly");
1✔
591
  ck_assert_msg(errno == ENOTSOCK, "Expected ENOTSOCK (%d), got %s (%d)",
1✔
592
    ENOTSOCK, strerror(errno), errno);
1✔
593
  (void) close(fd);
594

1✔
595
  /* Open a WRITing data transfer connection...*/
596
  dir = PR_NETIO_IO_WR;
597

1✔
598
  mark_point();
599
  data_conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
1✔
600
  fd = data_conn->listen_fd;
1✔
601
  data_conn->listen_fd = dup(1);
1✔
602
  session.d = data_conn;
1✔
603
  session.sf_flags |= SF_PASSIVE;
1✔
604
  session.xfer.p = NULL;
1✔
605
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
606
  ck_assert_msg(res < 0, "Opened passive WRITE data connection unexpectedly");
1✔
607
  ck_assert_msg(errno == ENOTSOCK, "Expected ENOTSOCK (%d), got %s (%d)",
1✔
608
    ENOTSOCK, strerror(errno), errno);
1✔
609
  (void) close(fd);
610

1✔
611
  mark_point();
612
  session.sf_flags |= SF_PASSIVE;
1✔
613
  session.xfer.p = NULL;
1✔
614
  res = pr_data_open(NULL, NULL, dir, 0);
1✔
615
  ck_assert_msg(res < 0, "Opened passive WRITE data connection unexpectedly");
1✔
616
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
617
    strerror(errno), errno);
1✔
618

619
  (void) pr_inet_close(p, session.c);
620
  session.c = NULL;
1✔
621
  if (session.d != NULL) {
1✔
622
    (void) pr_inet_close(p, session.d);
1✔
623
    session.d = NULL;
×
624
  }
×
625
}
626
END_TEST
1✔
627

628
START_TEST (data_close_test) {
629
  session.sf_flags |= SF_PASSIVE;
1✔
630
  pr_data_close(TRUE);
1✔
631
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
632
    "Failed to clear SF_PASSIVE session flag");
1✔
633

634
  session.sf_flags |= SF_PASSIVE;
635
  pr_data_close(FALSE);
1✔
636
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
637
    "Failed to clear SF_PASSIVE session flag");
1✔
638

639
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
640
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
641

1✔
642
  pr_data_close(TRUE);
643
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
644
}
1✔
645
END_TEST
1✔
646

647
START_TEST (data_abort_test) {
648
  mark_point();
1✔
649
  session.sf_flags |= SF_PASSIVE;
1✔
650
  pr_data_abort(EPERM, TRUE);
1✔
651
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
652
    "Failed to clear SF_PASSIVE session flag");
1✔
653

654
  session.sf_flags |= SF_PASSIVE;
655
  pr_data_abort(EPERM, FALSE);
1✔
656
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
657
    "Failed to clear SF_PASSIVE session flag");
1✔
658

659
  mark_point();
660
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
661
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
662

1✔
663
  pr_data_abort(ESPIPE, FALSE);
664
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
665

1✔
666
  mark_point();
667
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
668
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
669

1✔
670
  session.sf_flags = SF_ABORT;
671
  pr_data_abort(EPIPE, FALSE);
1✔
672
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
673
  session.sf_flags &= ~SF_POST_ABORT;
1✔
674

1✔
675
#if defined(ENXIO)
676
  mark_point();
677
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
678
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
679
  pr_data_abort(ENXIO, FALSE);
1✔
680
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
681
#endif /* ENXIO */
1✔
682

683
#if defined(ENOMEM)
684
  mark_point();
685
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
686
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
687
  pr_data_abort(ENOMEM, FALSE);
1✔
688
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
689
#endif /* ENOMEM */
1✔
690

691
#if defined(EBUSY)
692
  mark_point();
693
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
694
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
695
  pr_data_abort(EBUSY, FALSE);
1✔
696
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
697
#endif /* EBUSY */
1✔
698

699
#if defined(ENOSPC)
700
  mark_point();
701
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
702
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
703
  pr_data_abort(ENOSPC, FALSE);
1✔
704
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
705
#endif /* ENOSPC */
1✔
706

707
#if defined(EFBIG)
708
  mark_point();
709
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
710
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
711
  pr_data_abort(EFBIG, FALSE);
1✔
712
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
713
#endif /* EFBIG */
1✔
714

715
#if defined(ECONNRESET)
716
  mark_point();
717
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
718
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
719
  pr_data_abort(ECONNRESET, FALSE);
1✔
720
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
721
#endif /* ECONNRESET */
1✔
722

723
  mark_point();
724
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
725
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
726
  pr_data_abort(-5432, FALSE);
1✔
727
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
728
}
1✔
729
END_TEST
1✔
730

731
START_TEST (data_reset_test) {
732
  mark_point();
1✔
733

1✔
734
  /* Set a session flag, make sure it's cleared properly. */
735
  session.sf_flags |= SF_PASSIVE;
736
  pr_data_reset();
1✔
737
  ck_assert_msg(session.d == NULL, "Expected NULL session.d, got %p", session.d);
1✔
738
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
739
    "SF_PASSIVE session flag not cleared");
1✔
740

741
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
742
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
743

1✔
744
  pr_data_reset();
745
  ck_assert_msg(session.d == NULL, "Expected NULL session.d, got %p", session.d);
1✔
746
  ck_assert_msg(!(session.sf_flags & SF_PASSIVE),
1✔
747
    "SF_PASSIVE session flag not cleared");
1✔
748
}
749
END_TEST
1✔
750

751
START_TEST (data_cleanup_test) {
752
  mark_point();
1✔
753

1✔
754
  /* Set a session flag, make sure it's cleared properly. */
755
  session.sf_flags |= SF_PASSIVE;
756
  pr_data_cleanup();
1✔
757
  ck_assert_msg(session.d == NULL, "Expected NULL session.d, got %p", session.d);
1✔
758
  ck_assert_msg(session.sf_flags & SF_PASSIVE,
1✔
759
    "SF_PASSIVE session flag not preserved");
1✔
760
  ck_assert_msg(session.xfer.xfer_type == STOR_DEFAULT, "Expected %d, got %d",
761
    STOR_DEFAULT, session.xfer.xfer_type);
1✔
762

763
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
764
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
765

1✔
766
  pr_data_cleanup();
767
  ck_assert_msg(session.d == NULL, "Failed to close session.d");
1✔
768
}
1✔
769
END_TEST
1✔
770

771
START_TEST (data_clear_xfer_pool_test) {
772
  int xfer_type = 7;
1✔
773

1✔
774
  mark_point();
775
  pr_data_clear_xfer_pool();
1✔
776
  ck_assert_msg(session.xfer.p == NULL, "Failed to clear session.xfer.p");
1✔
777

1✔
778
  session.xfer.xfer_type = xfer_type;
779
  session.xfer.p = make_sub_pool(p);
1✔
780

1✔
781
  mark_point();
782
  pr_data_clear_xfer_pool();
1✔
783
  ck_assert_msg(session.xfer.p == NULL, "Failed to clear session.xfer.p");
1✔
784
  ck_assert_msg(session.xfer.xfer_type == xfer_type, "Expected %d, got %d",
1✔
785
    xfer_type, session.xfer.xfer_type);
1✔
786
}
787
END_TEST
1✔
788

789
START_TEST (data_xfer_read_binary_test) {
790
  int res;
1✔
791
  char *buf, *expected;
1✔
792
  size_t bufsz, expected_len;
1✔
793
  cmd_rec *cmd;
1✔
794

1✔
795
  pr_data_clear_xfer_pool();
796
  pr_data_reset();
1✔
797

1✔
798
  res = pr_data_xfer(NULL, 0);
799
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
800
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
801
    strerror(errno), errno);
1✔
802

803
  bufsz = 1024;
804
  buf = palloc(p, bufsz);
1✔
805

1✔
806
  res = pr_data_xfer(buf, 0);
807
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
808
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
809
    strerror(errno), errno);
1✔
810

811
  mark_point();
812
  res = pr_data_xfer(buf, bufsz);
1✔
813
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1✔
814
  ck_assert_msg(errno == ECONNABORTED,
1✔
815
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
1✔
816
    strerror(errno), errno);
817

818
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
819
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
820

1✔
821
  /* read binary data */
822
  session.xfer.direction = PR_NETIO_IO_RD;
823

1✔
824
  /* Note: this string comes from the data_read_cb() we register with our
825
   * DATA stream callback.
826
   */
827
  expected = "Hello,\r\n World!\r\n";
828
  expected_len = strlen(expected);
1✔
829

1✔
830
  mark_point();
831
  data_write_eagain = TRUE;
1✔
832
  session.xfer.buf = NULL;
1✔
833
  session.xfer.buflen = 0;
1✔
834

1✔
835
  res = pr_data_xfer(buf, bufsz);
836
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1✔
837
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
838
    strerror(errno), errno);
1✔
839

840
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
841
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
842
    strerror(errno));
1✔
843

844
  mark_point();
845
  session.xfer.buf = NULL;
1✔
846
  session.xfer.buflen = 0;
1✔
847

1✔
848
  res = pr_data_xfer(buf, bufsz);
849
  ck_assert_msg((size_t) res == expected_len, "Expected %lu, got %d",
1✔
850
    (unsigned long) expected_len, res);
1✔
851

852
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
853
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
854

1✔
855
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
856
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
857
    strerror(errno));
1✔
858

859
  mark_point();
860
  session.xfer.buf = NULL;
1✔
861
  session.xfer.buflen = 0;
1✔
862

1✔
863
  res = pr_data_xfer(buf, bufsz);
864
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1✔
865
    (unsigned long) expected_len, res);
1✔
866
  ck_assert_msg(session.xfer.buflen == 0,
867
    "Expected session.xfer.buflen 0, got %lu",
1✔
868
    (unsigned long) session.xfer.buflen);
869

870
  mark_point();
871
  session.xfer.buf = NULL;
1✔
872
  session.xfer.buflen = 0;
1✔
873
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "syst"));
1✔
874
  tests_stubs_set_next_cmd(cmd);
1✔
875
  data_read_eagain = TRUE;
1✔
876

1✔
877
  res = pr_data_xfer(buf, bufsz);
878
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1✔
879
    (unsigned long) expected_len, res);
1✔
880
  ck_assert_msg(session.xfer.buflen == 0,
881
    "Expected session.xfer.buflen 0, got %lu",
1✔
882
    (unsigned long) session.xfer.buflen);
883
}
884
END_TEST
1✔
885

886
START_TEST (data_xfer_write_binary_test) {
887
  int res;
1✔
888
  char *buf;
1✔
889
  size_t buflen;
1✔
890

1✔
891
  pr_data_clear_xfer_pool();
892
  pr_data_reset();
1✔
893

1✔
894
  res = pr_data_xfer(NULL, 0);
895
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
896
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
897
    strerror(errno), errno);
1✔
898

899
  buf = "Hello, World!\n";
900
  buflen = strlen(buf);
1✔
901

1✔
902
  res = pr_data_xfer(buf, 0);
903
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
904
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
905
    strerror(errno), errno);
1✔
906

907
  mark_point();
908
  res = pr_data_xfer(buf, buflen);
1✔
909
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1✔
910
  ck_assert_msg(errno == ECONNABORTED,
1✔
911
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
1✔
912
    strerror(errno), errno);
913

914
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
915
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
916

1✔
917
  /* write binary data */
918
  session.xfer.direction = PR_NETIO_IO_WR;
919
  session.xfer.p = make_sub_pool(p);
1✔
920
  session.xfer.buflen = 1024;
1✔
921
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
922

1✔
923
  mark_point();
924
  data_write_eagain = TRUE;
1✔
925
  res = pr_data_xfer(buf, buflen);
1✔
926
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1✔
927
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
928
    strerror(errno), errno);
1✔
929

930
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
931
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
932
    strerror(errno));
1✔
933

934
  mark_point();
935
  res = pr_data_xfer(buf, buflen);
1✔
936
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1✔
937
    (unsigned long) buflen, res);
1✔
938

939
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
940
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
941

1✔
942
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
943
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
944
    strerror(errno));
1✔
945

946
  mark_point();
947
  res = pr_data_xfer(buf, buflen);
1✔
948
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1✔
949
    (unsigned long) buflen, res);
1✔
950

951
  /* Now that we no longer do an egregious memcpy() into session.xfer.buf
952
   * for binary transfers, we cannot use the contents of session.xfer.buf
953
   * for additional assertions.  The integration tests can cover those
954
   * assertions.
955
   */
956
}
957
END_TEST
1✔
958

959
START_TEST (data_xfer_read_ascii_test) {
960
  int res;
1✔
961
  char *buf, *expected;
1✔
962
  size_t bufsz, expected_len;
1✔
963
  cmd_rec *cmd;
1✔
964

1✔
965
  pr_data_clear_xfer_pool();
966
  pr_data_reset();
1✔
967

1✔
968
  res = pr_data_xfer(NULL, 0);
969
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
970
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
971
    strerror(errno), errno);
1✔
972

973
  bufsz = 1024;
974
  buf = palloc(p, bufsz);
1✔
975

1✔
976
  res = pr_data_xfer(buf, 0);
977
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
978
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
979
    strerror(errno), errno);
1✔
980

981
  mark_point();
982
  res = pr_data_xfer(buf, bufsz);
1✔
983
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1✔
984
  ck_assert_msg(errno == ECONNABORTED,
1✔
985
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
1✔
986
    strerror(errno), errno);
987

988
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
989
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
990

1✔
991
  /* read ASCII data */
992
  session.xfer.direction = PR_NETIO_IO_RD;
993
  session.xfer.p = make_sub_pool(p);
1✔
994
  session.xfer.bufsize = 1024;
1✔
995

1✔
996
  /* Note: this string comes from the data_read_cb() we register with our
997
   * DATA stream callback.
998
   */
999
  expected = "Hello,\n World!\n";
1000
  expected_len = strlen(expected);
1✔
1001

1✔
1002
  mark_point();
1003
  data_write_eagain = TRUE;
1✔
1004
  pr_ascii_ftp_reset();
1✔
1005
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1006
  session.xfer.buflen = 0;
1✔
1007

1✔
1008
  session.sf_flags |= SF_ASCII;
1009
  res = pr_data_xfer(buf, bufsz);
1✔
1010
  session.sf_flags &= ~SF_ASCII;
1✔
1011

1✔
1012
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1013
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1014
    strerror(errno), errno);
1✔
1015

1016
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1017
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
1018
    strerror(errno));
1✔
1019

1020
  mark_point();
1021
  pr_ascii_ftp_reset();
1✔
1022
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1023
  session.xfer.buflen = 0;
1✔
1024

1✔
1025
  session.sf_flags |= SF_ASCII;
1026
  res = pr_data_xfer(buf, bufsz);
1✔
1027
  session.sf_flags &= ~SF_ASCII;
1✔
1028

1✔
1029
  ck_assert_msg((size_t) res == expected_len, "Expected %lu, got %d",
1030
    (unsigned long) expected_len, res);
1✔
1031

1032
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1033
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1034

1✔
1035
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1036
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
1037
    strerror(errno));
1✔
1038

1039
  mark_point();
1040
  pr_ascii_ftp_reset();
1✔
1041
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1042
  session.xfer.buflen = 0;
1✔
1043

1✔
1044
  session.sf_flags |= SF_ASCII;
1045
  res = pr_data_xfer(buf, bufsz);
1✔
1046
  session.sf_flags &= ~SF_ASCII;
1✔
1047

1✔
1048
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1049
    (unsigned long) expected_len, res);
1✔
1050
  ck_assert_msg(session.xfer.buflen == 0,
1051
    "Expected session.xfer.buflen 0, got %lu",
1✔
1052
    (unsigned long) session.xfer.buflen);
1053
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
1054
    "Expected '%s', got '%.100s'", expected, buf);
1✔
1055

1056
  mark_point();
1057
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "noop"));
1✔
1058
  tests_stubs_set_next_cmd(cmd);
1✔
1059
  pr_ascii_ftp_reset();
1✔
1060
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1061
  session.xfer.buflen = 0;
1✔
1062

1✔
1063
  session.sf_flags |= SF_ASCII;
1064
  res = pr_data_xfer(buf, bufsz);
1✔
1065
  session.sf_flags &= ~SF_ASCII;
1✔
1066

1✔
1067
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1068
    (unsigned long) expected_len, res);
1✔
1069
  ck_assert_msg(session.xfer.buflen == 0,
1070
    "Expected session.xfer.buflen 0, got %lu",
1✔
1071
    (unsigned long) session.xfer.buflen);
1072
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
1073
    "Expected '%s', got '%.100s'", expected, buf);
1✔
1074

1075
  mark_point();
1076
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "pasv"));
1✔
1077
  tests_stubs_set_next_cmd(cmd);
1✔
1078
  pr_ascii_ftp_reset();
1✔
1079
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1080
  session.xfer.buflen = 0;
1✔
1081

1✔
1082
  session.sf_flags |= SF_ASCII;
1083
  res = pr_data_xfer(buf, bufsz);
1✔
1084
  session.sf_flags &= ~SF_ASCII;
1✔
1085

1✔
1086
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1087
    (unsigned long) expected_len, res);
1✔
1088
  ck_assert_msg(session.xfer.buflen == 0,
1089
    "Expected session.xfer.buflen 0, got %lu",
1✔
1090
    (unsigned long) session.xfer.buflen);
1091
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
1092
    "Expected '%s', got '%.100s'", expected, buf);
1✔
1093

1094
  /* Bug#4237 happened because of insufficient testing of the edge case
1095
   * where the LAST character in the buffer is a CR.
1096
   *
1097
   * Note that to properly test this, we need to KEEP the same session.xfer.buf
1098
   * in place, and do the read TWICE (at least; maybe more).
1099
   */
1100

1101
  mark_point();
1102
  pr_ascii_ftp_reset();
1✔
1103
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1104
  session.xfer.buflen = 0;
1✔
1105
  data_read_dangling_cr = TRUE;
1✔
1106

1✔
1107
  session.sf_flags |= SF_ASCII;
1108
  res = pr_data_xfer(buf, bufsz);
1✔
1109
  session.sf_flags &= ~SF_ASCII;
1✔
1110

1✔
1111
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1112
    (unsigned long) expected_len, res);
1✔
1113
  ck_assert_msg(session.xfer.buflen == 1,
1114
    "Expected session.xfer.buflen 1, got %lu",
1✔
1115
    (unsigned long) session.xfer.buflen);
1116
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
1117
    "Expected '%s', got '%.100s'", expected, buf);
1✔
1118
}
1119
END_TEST
1✔
1120

1121
START_TEST (data_xfer_read_ascii_with_abor_test) {
1122
  int res;
1✔
1123
  char *buf, *expected;
1✔
1124
  size_t bufsz, expected_len;
1✔
1125
  cmd_rec *cmd;
1✔
1126

1✔
1127
  pr_data_clear_xfer_pool();
1128
  pr_data_reset();
1✔
1129

1✔
1130
  bufsz = 1024;
1131
  buf = palloc(p, bufsz);
1✔
1132

1✔
1133
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1134
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1135

1✔
1136
  /* read ASCII data */
1137
  session.xfer.direction = PR_NETIO_IO_RD;
1138
  session.xfer.p = make_sub_pool(p);
1✔
1139
  session.xfer.bufsize = 1024;
1✔
1140

1✔
1141
  /* Note: this string comes from the data_read_cb() we register with our
1142
   * DATA stream callback.
1143
   */
1144
  expected = "Hello,\n World!\n";
1145
  expected_len = strlen(expected);
1✔
1146

1✔
1147
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1148
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
1149
    strerror(errno));
1✔
1150

1151
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1152
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1153

1✔
1154
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1155
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
1156
    strerror(errno));
1✔
1157

1158
  mark_point();
1159
  pr_ascii_ftp_reset();
1✔
1160
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1161
  session.xfer.buflen = 0;
1✔
1162

1✔
1163
  mark_point();
1164

1✔
1165
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "abor"));
1166
  tests_stubs_set_next_cmd(cmd);
1✔
1167

1✔
1168
  pr_ascii_ftp_reset();
1169
  session.xfer.buf = pcalloc(p, session.xfer.bufsize);
1✔
1170
  session.xfer.buflen = 0;
1✔
1171

1✔
1172
  session.sf_flags |= SF_ASCII;
1173
  res = pr_data_xfer(buf, bufsz);
1✔
1174
  session.sf_flags &= ~SF_ASCII;
1✔
1175

1✔
1176
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1177
    (unsigned long) expected_len, res);
1✔
1178
  ck_assert_msg(session.xfer.buflen == 0,
1179
    "Expected session.xfer.buflen 0, got %lu",
1✔
1180
    (unsigned long) session.xfer.buflen);
1181
  ck_assert_msg(memcmp(buf, expected, expected_len) == 0,
1182
    "Expected '%s', got '%.100s'", expected, buf);
1✔
1183
}
1184
END_TEST
1✔
1185

1186
START_TEST (data_xfer_write_ascii_test) {
1187
  int res;
1✔
1188
  char *buf, *ascii_buf;
1✔
1189
  size_t buflen, ascii_buflen;
1✔
1190
  cmd_rec *cmd;
1✔
1191

1✔
1192
  pr_data_clear_xfer_pool();
1193
  pr_data_reset();
1✔
1194

1✔
1195
  res = pr_data_xfer(NULL, 0);
1196
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1197
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1198
    strerror(errno), errno);
1✔
1199

1200
  buf = "Hello,\n World\n";
1201
  buflen = strlen(buf);
1✔
1202

1✔
1203
  ascii_buf = "Hello,\r\n World\r\n";
1204
  ascii_buflen = strlen(ascii_buf);
1✔
1205

1✔
1206
  res = pr_data_xfer(buf, 0);
1207
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
1208
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1209
    strerror(errno), errno);
1✔
1210

1211
  mark_point();
1212
  res = pr_data_xfer(buf, buflen);
1✔
1213
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1✔
1214
  ck_assert_msg(errno == ECONNABORTED,
1✔
1215
    "Expected ECONNABORTED (%d), got %s (%d)", ECONNABORTED,
1✔
1216
    strerror(errno), errno);
1217

1218
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1219
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1220

1✔
1221
  /* write ASCII data */
1222
  session.xfer.direction = PR_NETIO_IO_WR;
1223
  session.xfer.p = make_sub_pool(p);
1✔
1224
  session.xfer.buflen = 1024;
1✔
1225
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1226

1✔
1227
  mark_point();
1228
  data_write_eagain = TRUE;
1✔
1229
  pr_ascii_ftp_reset();
1✔
1230
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1231
  res = pr_data_xfer(buf, buflen);
1✔
1232
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1233

1✔
1234
  ck_assert_msg(res < 0, "Transferred data unexpectedly");
1235
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1236
    strerror(errno), errno);
1✔
1237

1238
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1239
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
1240
    strerror(errno));
1✔
1241

1242
  mark_point();
1243
  pr_ascii_ftp_reset();
1✔
1244
  session.sf_flags |= SF_ASCII_OVERRIDE;
1✔
1245
  res = pr_data_xfer(buf, buflen);
1✔
1246
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1247

1✔
1248
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1249
    (unsigned long) buflen, res);
1✔
1250

1251
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1252
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1253

1✔
1254
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1255
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
1256
    strerror(errno));
1✔
1257

1258
  mark_point();
1259
  pr_ascii_ftp_reset();
1✔
1260
  session.xfer.buflen = 1024;
1✔
1261
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1262

1✔
1263
  session.sf_flags |= SF_ASCII_OVERRIDE;
1264
  res = pr_data_xfer(buf, buflen);
1✔
1265
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1266

1✔
1267
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1268
    (unsigned long) buflen, res);
1✔
1269
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
1270
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1✔
1271
    (unsigned long) session.xfer.buflen);
1272

1273
  mark_point();
1274
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "noop"));
1✔
1275
  tests_stubs_set_next_cmd(cmd);
1✔
1276
  pr_ascii_ftp_reset();
1✔
1277
  session.xfer.buflen = 1024;
1✔
1278
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1279

1✔
1280
  session.sf_flags |= SF_ASCII_OVERRIDE;
1281
  res = pr_data_xfer(buf, buflen);
1✔
1282
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1283

1✔
1284
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1285
    (unsigned long) buflen, res);
1✔
1286
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
1287
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1✔
1288
    (unsigned long) session.xfer.buflen);
1289

1290
  session.xfer.p = make_sub_pool(p);
1291
  mark_point();
1✔
1292
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "pasv"));
1✔
1293
  tests_stubs_set_next_cmd(cmd);
1✔
1294
  pr_ascii_ftp_reset();
1✔
1295
  session.xfer.buflen = 1024;
1✔
1296
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1297

1✔
1298
  session.sf_flags |= SF_ASCII_OVERRIDE;
1299
  res = pr_data_xfer(buf, buflen);
1✔
1300
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1301

1✔
1302
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1303
    (unsigned long) buflen, res);
1✔
1304
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
1305
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1✔
1306
    (unsigned long) session.xfer.buflen);
1307

1308
  mark_point();
1309
  pr_ascii_ftp_reset();
1✔
1310
  session.xfer.buflen = 1024;
1✔
1311
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1312

1✔
1313
  session.sf_flags |= SF_ASCII;
1314
  res = pr_data_xfer(buf, buflen);
1✔
1315
  session.sf_flags &= ~SF_ASCII;
1✔
1316

1✔
1317
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1318
    (unsigned long) buflen, res);
1✔
1319
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
1320
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1✔
1321
    (unsigned long) session.xfer.buflen);
1322
}
1323
END_TEST
1✔
1324

1325
START_TEST (data_xfer_write_ascii_with_abor_test) {
1326
  int res;
1✔
1327
  char *buf, *ascii_buf;
1✔
1328
  size_t buflen, ascii_buflen;
1✔
1329
  cmd_rec *cmd;
1✔
1330

1✔
1331
  pr_data_clear_xfer_pool();
1332
  pr_data_reset();
1✔
1333

1✔
1334
  buf = "Hello,\n World\n";
1335
  buflen = strlen(buf);
1✔
1336

1✔
1337
  ascii_buf = "Hello,\r\n World\r\n";
1338
  ascii_buflen = strlen(ascii_buf);
1✔
1339

1✔
1340
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1341
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1342

1✔
1343
  /* write ASCII data */
1344
  session.xfer.direction = PR_NETIO_IO_WR;
1345
  session.xfer.p = make_sub_pool(p);
1✔
1346
  session.xfer.buflen = 1024;
1✔
1347
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1348

1✔
1349
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1350
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
1351
    strerror(errno));
1✔
1352

1353
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1354
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1355

1✔
1356
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1357
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
1358
    strerror(errno));
1✔
1359

1360
  mark_point();
1361

1✔
1362
  cmd = pr_cmd_alloc(p, 1, pstrdup(p, "abor"));
1363
  tests_stubs_set_next_cmd(cmd);
1✔
1364

1✔
1365
  pr_ascii_ftp_reset();
1366
  session.xfer.buflen = 1024;
1✔
1367
  session.xfer.buf = pcalloc(p, session.xfer.buflen);
1✔
1368

1✔
1369
  session.sf_flags |= SF_ASCII_OVERRIDE;
1370
  res = pr_data_xfer(buf, buflen);
1✔
1371
  session.sf_flags &= ~SF_ASCII_OVERRIDE;
1✔
1372

1✔
1373
  ck_assert_msg(res == (int) buflen, "Expected %lu, got %d",
1374
    (unsigned long) buflen, res);
1✔
1375
  ck_assert_msg(session.xfer.buflen == ascii_buflen,
1376
    "Expected session.xfer.buflen %lu, got %lu", (unsigned long) ascii_buflen,
1✔
1377
    (unsigned long) session.xfer.buflen);
1378
}
1379
END_TEST
1✔
1380

1381
START_TEST (data_xfer_peek_nonsocket_test) {
1382
  int fd, res, strm_fd;
1✔
1383
  char *buf, *expected;
1✔
1384
  size_t bufsz, expected_len;
1✔
1385

1✔
1386
  pr_data_clear_xfer_pool();
1387
  pr_data_reset();
1✔
1388

1✔
1389
  mark_point();
1390
  bufsz = 1024;
1✔
1391
  buf = palloc(p, bufsz);
1✔
1392
  session.d = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1✔
1393
  ck_assert_msg(session.d != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1394

1✔
1395
  /* read binary data */
1396
  session.xfer.direction = PR_NETIO_IO_RD;
1397

1✔
1398
  /* Note: this string comes from the data_read_cb() we register with our
1399
   * DATA stream callback.
1400
   */
1401
  expected = "Hello,\r\n World!\r\n";
1402
  expected_len = strlen(expected);
1✔
1403

1✔
1404
  session.xfer.buf = NULL;
1405
  session.xfer.buflen = 0;
1✔
1406

1✔
1407
  res = data_open_streams(session.d, PR_NETIO_STRM_DATA);
1408
  ck_assert_msg(res == 0, "Failed to open streams on session.d: %s",
1✔
1409
    strerror(errno));
1✔
1410

1411
  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
1412
  ck_assert_msg(session.c != NULL, "Failed to create conn: %s", strerror(errno));
1✔
1413

1✔
1414
  res = data_open_streams(session.c, PR_NETIO_STRM_CTRL);
1415
  ck_assert_msg(res == 0, "Failed to open streams on session.c: %s",
1✔
1416
    strerror(errno));
1✔
1417

1418
  fd = tmpfile_fd();
1419
  if (fd < 0) {
1✔
1420
    return;
1✔
1421
  }
1422

1423
  strm_fd = PR_NETIO_FD(session.c->instrm);
1424
  PR_NETIO_FD(session.c->instrm) = fd;
1✔
1425

1✔
1426
  (void) write(fd, "FOO\r\n", 5);
1427
  rewind_fd(fd);
1✔
1428

1✔
1429
  mark_point();
1430
  session.xfer.buf = NULL;
1✔
1431
  session.xfer.buflen = 0;
1✔
1432
  data_write_eagain = TRUE;
1✔
1433

1✔
1434
  res = pr_data_xfer(buf, bufsz);
1435
  ck_assert_msg(res == (int) expected_len, "Expected %lu, got %d",
1✔
1436
    (unsigned long) expected_len, res);
1✔
1437
  ck_assert_msg(session.xfer.buflen == 0,
1438
    "Expected session.xfer.buflen 0, got %lu",
1✔
1439
    (unsigned long) session.xfer.buflen);
1440

1441
  (void) close(fd);
1442

1✔
1443
  PR_NETIO_FD(session.c->instrm) = strm_fd;
1444
  (void) pr_inet_close(p, session.c);
1✔
1445
  session.c = NULL;
1✔
1446
  if (session.d != NULL) {
1✔
1447
    (void) pr_inet_close(p, session.d);
1✔
1448
    session.d = NULL;
1✔
1449
  }
1✔
1450
}
1451
END_TEST
1452

1453
Suite *tests_get_data_suite(void) {
1454
  Suite *suite;
889✔
1455
  TCase *testcase;
889✔
1456

889✔
1457
  suite = suite_create("data");
1458

889✔
1459
  testcase = tcase_create("base");
1460
  tcase_add_checked_fixture(testcase, set_up, tear_down);
889✔
1461

889✔
1462
  tcase_add_test(testcase, data_get_timeout_test);
1463
  tcase_add_test(testcase, data_set_timeout_test);
889✔
1464
  tcase_add_test(testcase, data_ignore_ascii_test);
889✔
1465
  tcase_add_test(testcase, data_sendfile_test);
889✔
1466

889✔
1467
  tcase_add_test(testcase, data_init_test);
1468
  tcase_add_test(testcase, data_open_active_test);
889✔
1469
  tcase_add_test(testcase, data_open_active_rootrevoke_test);
889✔
1470
  tcase_add_test(testcase, data_open_passive_test);
889✔
1471
  tcase_add_test(testcase, data_close_test);
889✔
1472
  tcase_add_test(testcase, data_abort_test);
889✔
1473
  tcase_add_test(testcase, data_reset_test);
889✔
1474
  tcase_add_test(testcase, data_cleanup_test);
889✔
1475
  tcase_add_test(testcase, data_clear_xfer_pool_test);
889✔
1476
  tcase_add_test(testcase, data_xfer_read_binary_test);
889✔
1477
  tcase_add_test(testcase, data_xfer_write_binary_test);
889✔
1478
  tcase_add_test(testcase, data_xfer_read_ascii_test);
889✔
1479
  tcase_add_test(testcase, data_xfer_read_ascii_with_abor_test);
889✔
1480
  tcase_add_test(testcase, data_xfer_write_ascii_test);
889✔
1481
  tcase_add_test(testcase, data_xfer_write_ascii_with_abor_test);
889✔
1482
  tcase_add_test(testcase, data_xfer_peek_nonsocket_test);
889✔
1483

889✔
1484
  /* Allow a longer timeout on these tests, as they will need a second or
1485
   * two to actually run through the test itself, plus overhead.
1486
   */
1487
  tcase_set_timeout(testcase, 5);
1488

889✔
1489
  suite_add_tcase(suite, testcase);
1490
  return suite;
889✔
1491
}
889✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc