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

proftpd / proftpd / 29772954074

20 Jul 2026 07:52PM UTC coverage: 93.032% (+0.6%) from 92.427%
29772954074

push

github

51363 of 55210 relevant lines covered (93.03%)

226.61 hits per line

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

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

26
/* Data connection management functions */
27

28
#include "conf.h"
29

30
#ifdef HAVE_SYS_SENDFILE_H
31
#include <sys/sendfile.h>
32
#endif /* HAVE_SYS_SENDFILE_H */
33

34
#ifdef HAVE_SYS_UIO_H
35
#include <sys/uio.h>
36
#endif /* HAVE_SYS_UIO_H */
37

38
static const char *trace_channel = "data";
39
static const char *timing_channel = "timing";
40

41
#define PR_DATA_OPT_IGNORE_ASCII        0x0001
42
static unsigned long data_opts = 0UL;
43
static uint64_t data_start_ms = 0L;
44
static int data_first_byte_read = FALSE;
45
static int data_first_byte_written = FALSE;
46

47
/* local macro */
48

49
#define MODE_STRING        (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE) ? \
50
                         "ASCII" : "BINARY")
51

52
/* Internal usage: pointer to current data connection stream in use (may be
53
 * in either read or write mode)
54
 */
55
static pr_netio_stream_t *nstrm = NULL;
56

57
static long timeout_linger = PR_TUNABLE_TIMEOUTLINGER;
58

59
static int timeout_idle = PR_TUNABLE_TIMEOUTIDLE;
60
static int timeout_noxfer = PR_TUNABLE_TIMEOUTNOXFER;
61
static int timeout_stalled = PR_TUNABLE_TIMEOUTSTALLED;
62

63
/* Called if the "Stalled" timer goes off
64
 */
65
static int stalled_timeout_cb(CALLBACK_FRAME) {
66
  pr_event_generate("core.timeout-stalled", NULL);
×
67
  pr_log_pri(PR_LOG_NOTICE, "Data transfer stall timeout: %d %s",
×
68
    timeout_stalled, timeout_stalled != 1 ? "seconds" : "second");
×
69
  pr_session_disconnect(NULL, PR_SESS_DISCONNECT_TIMEOUT,
×
70
    "TimeoutStalled during data transfer");
×
71

72
  /* Prevent compiler warning. */
73
  return 0;
74
}
×
75

76
/* This signal is raised if we get OOB data on the control connection, and
77
 * a data transfer is in progress.
78
 */
79
static RETSIGTYPE data_urgent(int signo) {
80
  if (session.sf_flags & SF_XFER) {
×
81
    pr_trace_msg(trace_channel, 5, "received SIGURG signal (signal %d), "
×
82
      "setting 'aborted' session flag", signo);
×
83
    session.sf_flags |= SF_ABORT;
84

×
85
    if (nstrm) {
86
      pr_netio_abort(nstrm);
×
87
    }
×
88
  }
89

90
  signal(SIGURG, data_urgent);
91
}
×
92

×
93
static void data_new_xfer(char *filename, int direction) {
94
  pr_data_clear_xfer_pool();
7✔
95

7✔
96
  session.xfer.p = make_sub_pool(session.pool);
97
  pr_pool_tag(session.xfer.p, "Data Transfer pool");
7✔
98

7✔
99
  session.xfer.filename = pstrdup(session.xfer.p, filename);
100
  session.xfer.direction = direction;
7✔
101
  session.xfer.bufsize = pr_config_get_server_xfer_bufsz(direction);
7✔
102
  session.xfer.buf = pcalloc(session.xfer.p, session.xfer.bufsize + 1);
7✔
103
  pr_trace_msg(trace_channel, 8, "allocated data transfer buffer of %lu bytes",
7✔
104
    (unsigned long) session.xfer.bufsize);
7✔
105
  session.xfer.buf++;        /* leave room for ascii translation */
7✔
106
  session.xfer.buflen = 0;
7✔
107
}
7✔
108

7✔
109
static int data_passive_open(const char *reason, off_t size) {
110
  conn_t *c;
3✔
111
  int rev, xerrno = 0;
3✔
112

3✔
113
  if (reason == NULL &&
114
      session.xfer.filename != NULL) {
3✔
115
    reason = session.xfer.filename;
3✔
116
  }
×
117

118
  /* Set the "stalled" timer, if any, to prevent the connection
119
   * open from taking too long
120
   */
121
  if (timeout_stalled) {
122
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
3✔
123
      "TimeoutStalled");
3✔
124
  }
125

126
  /* We save the state of our current disposition for doing reverse
127
   * lookups, and then set it to what the configuration wants it to
128
   * be.
129
   */
130
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
131

3✔
132
  /* Protocol and socket options should be set before handshaking. */
133

134
  if (session.xfer.direction == PR_NETIO_IO_RD) {
135
    pr_inet_set_socket_opts2(session.d->pool, session.d,
3✔
136
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
2✔
137
      main_server->tcp_keepalive, 0);
2✔
138

2✔
139
  } else {
140
    pr_inet_set_socket_opts2(session.d->pool, session.d,
141
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
1✔
142
      main_server->tcp_keepalive, 0);
1✔
143
  }
1✔
144

145
  c = pr_inet_accept(session.pool, session.d, session.c, -1, -1, TRUE);
146
  pr_netaddr_set_reverse_dns(rev);
3✔
147

3✔
148
  if (c && c->mode != CM_ERROR) {
149
    pr_inet_close(session.pool, session.d);
3✔
150
    (void) pr_inet_set_nonblock(session.pool, c);
×
151
    session.d = c;
×
152

×
153
    pr_log_debug(DEBUG4, "passive data connection opened - local  : %s:%d",
154
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
×
155
    pr_log_debug(DEBUG4, "passive data connection opened - remote : %s:%d",
156
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);
×
157

×
158
    if (session.xfer.xfer_type != STOR_UNIQUE) {
159
      if (size) {
×
160
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
×
161
          "(%" PR_LU " %s)"), MODE_STRING, reason, (pr_off_t) size,
×
162
          size != 1 ? "bytes" : "byte");
×
163

164
      } else {
165
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
166
          MODE_STRING, reason);
×
167
      }
×
168

169
    } else {
170

171
      /* Format of 150 responses for STOU is explicitly dictated by
172
       * RFC 1123:
173
       *
174
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
175
       *
176
       *    The STOU command stores into a uniquely named file.  When it
177
       *    receives an STOU command, a Server-FTP MUST return the
178
       *    actual file name in the "125 Transfer Starting" or the "150
179
       *    Opening Data Connection" message that precedes the transfer
180
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
181
       *    exact format of these messages is hereby defined to be as
182
       *    follows:
183
       *
184
       *        125 FILE: pppp
185
       *        150 FILE: pppp
186
       *
187
       *    where pppp represents the unique pathname of the file that
188
       *    will be written.
189
       */
190
      pr_response_send(R_150, "FILE: %s", reason);
191
    }
×
192

193
    return 0;
194
  }
×
195

196
  /* Check for error conditions. */
197
  if (c != NULL &&
198
      c->mode == CM_ERROR) {
3✔
199
    pr_log_pri(PR_LOG_ERR, "error: unable to accept an incoming data "
×
200
      "connection: %s", strerror(c->xerrno));
×
201
  }
202

203
  xerrno = session.d->xerrno;
204
  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
3✔
205
    strerror(xerrno));
3✔
206
  pr_data_close2();
207

3✔
208
  errno = xerrno;
209
  return -1;
3✔
210
}
3✔
211

212
static int data_active_open(const char *reason, off_t size) {
213
  conn_t *conn;
8✔
214
  config_rec *c;
8✔
215
  int bind_port, rev, *root_revoke = NULL, tcp_nodelay = 1, xerrno;
8✔
216
  const pr_netaddr_t *bind_addr = NULL;
8✔
217

218
  if (session.c->remote_addr == NULL) {
8✔
219
    /* An opened but unconnected connection? */
220
    errno = EINVAL;
1✔
221
    return -1;
1✔
222
  }
223

224
  if (reason == NULL &&
7✔
225
      session.xfer.filename != NULL) {
7✔
226
    reason = session.xfer.filename;
4✔
227
  }
228

229
  if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
7✔
230
    bind_addr = session.c->local_addr;
7✔
231

232
  } else {
233
    /* In this scenario, the server has an IPv6 socket, but the remote client
234
     * is an IPv4 (or IPv4-mapped IPv6) peer.
235
     */
236
    bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr);
×
237
  }
238

239
  /* Default source port to which to bind for the active transfer, as
240
   * per RFC959.
241
   */
242
  bind_port = session.c->local_port-1;
7✔
243

244
  root_revoke = get_param_ptr(TOPLEVEL_CONF, "RootRevoke", FALSE);
7✔
245
  if (root_revoke == NULL) {
7✔
246
    /* In the absence of any explicit RootRevoke, the default behavior is to
247
     * change the source port.  This means we are technically noncompliant,
248
     * but most clients do not enforce this behavior.
249
     */
250
    bind_port = INPORT_ANY;
251

252
  } else {
253
    /* A RootRevoke value of 0 indicates 'false', 1 indicates 'true', and
254
     * 2 indicates 'NonCompliantActiveTransfer'.  We change the source port for
255
     * a RootRevoke value of 2, and for a value of 1, we make sure that
256
     * that the port is not a privileged port.
257
     */
258
    switch (*root_revoke) {
4✔
259
      case 1:
2✔
260
        if (bind_port < 1024) {
2✔
261
          pr_log_debug(DEBUG0, "RootRevoke in effect, unable to bind to local "
1✔
262
            "port %d for active transfer", bind_port);
263
          errno = EPERM;
1✔
264
          return -1;
1✔
265
        }
266
        break;
267

268
      case 2:
1✔
269
        bind_port = INPORT_ANY;
1✔
270
        break;
1✔
271

272
      default:
273
        break;
274
    }
275
  }
276

277
  session.d = pr_inet_create_conn2(session.pool, -1, bind_addr, bind_port,
6✔
278
    PR_INET_CREATE_CONN_FL_RETRY_BIND);
6✔
279
  if (session.d == NULL) {
×
280
    xerrno = errno;
281

×
282
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
283
      strerror(xerrno));
284

×
285
    errno = xerrno;
×
286
    return -1;
287
  }
288

289
  /* Default remote address to which to connect for an active transfer,
290
   * if the client has not specified a different address via PORT/EPRT,
291
   * as per RFC 959.
292
   */
6✔
293
  if (pr_netaddr_get_family(&session.data_addr) == AF_UNSPEC) {
2✔
294
    pr_log_debug(DEBUG6, "Client has not sent previous PORT/EPRT command, "
295
      "defaulting to %s#%u for active transfer",
2✔
296
      pr_netaddr_get_ipstr(session.c->remote_addr), session.c->remote_port);
297

2✔
298
    pr_netaddr_set_family(&session.data_addr, pr_netaddr_get_family(session.c->remote_addr));
2✔
299
    pr_netaddr_set_sockaddr(&session.data_addr, pr_netaddr_get_sockaddr(session.c->remote_addr));
300
  }
301

302
  /* Set the "stalled" timer, if any, to prevent the connection
303
   * open from taking too long
304
   */
6✔
305
  if (timeout_stalled > 0) {
6✔
306
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
307
      "TimeoutStalled");
308
  }
309

6✔
310
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
311

312
  /* Protocol and socket options should be set before handshaking. */
313

6✔
314
  if (session.xfer.direction == PR_NETIO_IO_RD) {
4✔
315
    pr_inet_set_socket_opts2(session.d->pool, session.d,
4✔
316
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
4✔
317
      main_server->tcp_keepalive, 1);
318

319
  } else {
2✔
320
    pr_inet_set_socket_opts2(session.d->pool, session.d,
2✔
321
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
2✔
322
      main_server->tcp_keepalive, 1);
323
  }
324

325
  c = find_config(main_server->conf, CONF_PARAM, "TCPNoDelay", FALSE);
326
  if (c != NULL) {
327
    int data_use_nodelay;
6✔
328

329
    data_use_nodelay = *((int *) c->argv[1]);
6✔
330
    if (data_use_nodelay == FALSE) {
6✔
331
      tcp_nodelay = 0;
332
    }
6✔
333
  }
6✔
334

6✔
335
  session.d->use_nodelay = tcp_nodelay;
336
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len,
12✔
337
    tcp_nodelay, IPTOS_THROUGHPUT, 1);
338
  pr_inet_generate_socket_event("core.data-connect", main_server,
6✔
339
    session.d->local_addr, session.d->listen_fd);
340

6✔
341
  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
342
      session.data_port) < 0) {
6✔
343
    xerrno = session.d->xerrno;
344

6✔
345
    pr_log_debug(DEBUG6,
6✔
346
      "Error connecting to %s#%u for active data transfer: %s",
347
      pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
348
      strerror(xerrno));
×
349
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
350
      strerror(xerrno));
351
    pr_data_close2();
×
352

353
    errno = xerrno;
×
354
    return -1;
×
355
  }
×
356

×
357
  conn = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
×
358
    session.d->listen_fd, -1, -1, TRUE);
359

×
360
  pr_netaddr_set_reverse_dns(rev);
×
361

×
362
  if (conn != NULL) {
×
363
    pr_log_debug(DEBUG4, "active data connection opened - local  : %s:%d",
364
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
365
    pr_log_debug(DEBUG4, "active data connection opened - remote : %s:%d",
366
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);
×
367

×
368
    if (session.xfer.xfer_type != STOR_UNIQUE) {
369
      if (size) {
370
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
371
          "(%" PR_LU " %s)"), MODE_STRING, reason, (pr_off_t) size,
372
          size != 1 ? "bytes" : "byte");
373

374
      } else {
375
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
376
          MODE_STRING, reason);
377
      }
378

379
    } else {
380

381
      /* Format of 150 responses for STOU is explicitly dictated by
382
       * RFC 1123:
383
       *
384
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
385
       *
386
       *    The STOU command stores into a uniquely named file.  When it
387
       *    receives an STOU command, a Server-FTP MUST return the
388
       *    actual file name in the "125 Transfer Starting" or the "150
389
       *    Opening Data Connection" message that precedes the transfer
390
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
391
       *    exact format of these messages is hereby defined to be as
×
392
       *    follows:
393
       *
394
       *        125 FILE: pppp
×
395
       *        150 FILE: pppp
×
396
       *
×
397
       *    where pppp represents the unique pathname of the file that
×
398
       *    will be written.
399
       */
400
      pr_response_send(R_150, "FILE: %s", reason);
×
401
    }
×
402

×
403
    (void) pr_inet_set_nonblock(session.pool, session.d);
×
404
    pr_inet_close(session.pool, session.d);
405
    session.d = conn;
×
406
    return 0;
×
407
  }
408

409
  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
1✔
410
    strerror(session.d->xerrno));
1✔
411
  xerrno = session.d->xerrno;
1✔
412
  pr_data_close2();
413

7✔
414
  errno = xerrno;
7✔
415
  return -1;
2✔
416
}
2✔
417

418
void pr_data_set_linger(long linger) {
2✔
419
  timeout_linger = linger;
2✔
420
}
421

2✔
422
int pr_data_get_timeout(int id) {
2✔
423
  switch (id) {
424
    case PR_DATA_TIMEOUT_IDLE:
425
      return timeout_idle;
1✔
426

1✔
427
    case PR_DATA_TIMEOUT_NO_TRANSFER:
428
      return timeout_noxfer;
429

3✔
430
    case PR_DATA_TIMEOUT_STALLED:
3✔
431
      return timeout_stalled;
1✔
432

1✔
433
    default:
1✔
434
      break;
435
  }
1✔
436

1✔
437
  errno = EINVAL;
1✔
438
  return -1;
439
}
1✔
440

1✔
441
void pr_data_set_timeout(int id, int timeout) {
1✔
442
  switch (id) {
443
    case PR_DATA_TIMEOUT_IDLE:
3✔
444
      timeout_idle = timeout;
445
      break;
19✔
446

19✔
447
    case PR_DATA_TIMEOUT_NO_TRANSFER:
448
      timeout_noxfer = timeout;
19✔
449
      break;
2✔
450

451
    case PR_DATA_TIMEOUT_STALLED:
452
      timeout_stalled = timeout;
453
      break;
454

455
    default:
456
      break;
19✔
457
  }
458
}
19✔
459

19✔
460
void pr_data_clear_xfer_pool(void) {
19✔
461
  int xfer_type;
462

9✔
463
  if (session.xfer.p != NULL) {
464
    destroy_pool(session.xfer.p);
9✔
465
  }
466

9✔
467
  /* Note that session.xfer.xfer_type may have been set already, e.g.
1✔
468
   * for STOR_UNIQUE uploads.  To support this, we need to preserve that
1✔
469
   * value.
470
   */
471
  xfer_type = session.xfer.xfer_type;
9✔
472

9✔
473
  memset(&session.xfer, 0, sizeof(session.xfer));
9✔
474
  session.xfer.xfer_type = xfer_type;
475
}
5✔
476

5✔
477
void pr_data_reset(void) {
478
  /* Clear any leftover state from previous transfers. */
5✔
479
  pr_ascii_ftp_reset();
480

1✔
481
  if (session.d != NULL &&
1✔
482
      session.d->pool != NULL) {
483
    destroy_pool(session.d->pool);
484
  }
4✔
485

2✔
486
  session.d = NULL;
1✔
487

488
  /* Note that we deliberately omit the SF_EPSV_ALL flag from here.  Once that
489
   * session flag has been requested/set, it persists for the rest of the
490
   * session, regardless of data transfer successs or failure (Issue #2255).
491
   */
492
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_POST_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
2✔
493
}
1✔
494

495
int pr_data_ignore_ascii(int ignore_ascii) {
496
  int res;
497

498
  if (ignore_ascii != TRUE &&
499
      ignore_ascii != FALSE) {
500
    errno = EINVAL;
501
    return -1;
502
  }
3✔
503

3✔
504
  if (data_opts & PR_DATA_OPT_IGNORE_ASCII) {
2✔
505
    if (!ignore_ascii) {
506
      data_opts &= ~PR_DATA_OPT_IGNORE_ASCII;
507
    }
1✔
508

1✔
509
    res = TRUE;
510

511
  } else {
512
    if (ignore_ascii) {
1✔
513
      data_opts |= PR_DATA_OPT_IGNORE_ASCII;
514
    }
515

516
    res = FALSE;
3✔
517
  }
3✔
518

519
  return res;
15✔
520
}
15✔
521

15✔
522
void pr_data_init(char *filename, int direction) {
523
  if (session.xfer.p == NULL) {
15✔
524
    data_new_xfer(filename, direction);
2✔
525

2✔
526
  } else {
527
    if (!(session.sf_flags & SF_PASSIVE)) {
528
      pr_log_debug(DEBUG5,
13✔
529
        "data_init oddity: session.xfer exists in non-PASV mode");
9✔
530
    }
531

532
    session.xfer.direction = direction;
533
  }
4✔
534

1✔
535
  /* Clear any leftover state from previous transfers. */
1✔
536
  pr_ascii_ftp_reset();
537
}
538

539
int pr_data_open(char *filename, char *reason, int direction, off_t size) {
540
  int res = 0;
541
#if defined(HAVE_SIGACTION)
542
  struct sigaction act;
9✔
543
#endif /* HAVE_SIGACTION */
1✔
544

1✔
545
  if (session.c == NULL) {
546
    errno = EINVAL;
547
    return -1;
548
  }
549

11✔
550
  if ((session.sf_flags & SF_PASSIVE) ||
551
      (session.sf_flags & SF_EPSV_ALL)) {
11✔
552
    /* For passive transfers, we expect there to already be an existing
5✔
553
     * data connection...
554
     */
555
    if (session.d == NULL) {
6✔
556
      errno = EINVAL;
557
      return -1;
558
    }
11✔
559

11✔
560
  } else {
561
    /* ...but for active transfers, we expect there to NOT be an existing
562
     * data connection.
563
     */
11✔
564
    if (session.d != NULL) {
8✔
565
      errno = session.d->xerrno = EINVAL;
3✔
566
      return -1;
567
    }
568
  }
569

8✔
570
  /* Make sure that any abort flags have been cleared. */
571
  session.sf_flags &= ~(SF_ABORT|SF_POST_ABORT);
572

11✔
573
  if (session.xfer.p == NULL) {
574
    data_new_xfer(filename, direction);
575

576
  } else {
×
577
    session.xfer.direction = direction;
×
578
  }
579

×
580
  if (reason == NULL) {
×
581
    reason = filename;
×
582
  }
×
583

584
  /* Passive data transfers... */
×
585
  if ((session.sf_flags & SF_PASSIVE) ||
×
586
      (session.sf_flags & SF_EPSV_ALL)) {
587
    res = data_passive_open(reason, size);
588

×
589
  /* Active data transfers... */
×
590
  } else {
591
    res = data_active_open(reason, size);
×
592
  }
×
593

×
594
  if (res < 0) {
×
595
    return res;
596
  }
×
597

×
598
  if (pr_netio_postopen(session.d->instrm) < 0) {
599
    int xerrno;
600

×
601
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
602
      strerror(session.d->xerrno));
603
    xerrno = session.d->xerrno;
×
604
    pr_data_close2();
×
605

606
    errno = xerrno;
607
    return -1;
×
608
  }
609

610
  if (pr_netio_postopen(session.d->outstrm) < 0) {
×
611
    int xerrno;
612

×
613
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
614
      strerror(session.d->xerrno));
615
    xerrno = session.d->xerrno;
616
    pr_data_close2();
617

618
    errno = xerrno;
619
    return -1;
×
620
  }
621

622
  memset(&session.xfer.start_time, '\0', sizeof(session.xfer.start_time));
623
  gettimeofday(&session.xfer.start_time, NULL);
624

625
  if (session.xfer.direction == PR_NETIO_IO_RD) {
626
    nstrm = session.d->instrm;
627

628
  } else {
×
629
    nstrm = session.d->outstrm;
×
630
  }
×
631

632
  session.sf_flags |= SF_XFER;
×
633

634
  if (timeout_noxfer) {
635
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
×
636
  }
×
637

×
638
  /* Allow aborts -- set the current NetIO stream to allow interrupted
639
   * syscalls, so our SIGURG handler can interrupt it
640
   */
641
  pr_netio_set_poll_interval(nstrm, 1);
642

643
  /* PORTABILITY: sigaction is used here to allow us to indicate
644
   * (w/ POSIX at least) that we want SIGURG to interrupt syscalls.  Put
×
645
   * in whatever is necessary for your arch here; probably not necessary
×
646
   * as the only _important_ interrupted syscall is select(), which on
647
   * any sensible system is interrupted.
×
648
   */
649

650
#if defined(HAVE_SIGACTION)
651
  act.sa_handler = data_urgent;
652
  sigemptyset(&act.sa_mask);
×
653
  act.sa_flags = 0;
×
654

×
655
# if defined(SA_INTERRUPT)
656
  act.sa_flags |= SA_INTERRUPT;
×
657
# endif /* SA_INTERRUPT */
658
# if defined(SA_RESTART)
659
  act.sa_flags &= SA_RESTART;
12✔
660
# endif /* SA_RESTART */
12✔
661

662
  if (sigaction(SIGURG, &act, NULL) < 0) {
12✔
663
    pr_log_pri(PR_LOG_WARNING,
10✔
664
      "warning: unable to set SIGURG signal handler: %s", strerror(errno));
10✔
665
  }
666

667
#elif defined(HAVE_SIGINTERRUPT)
668
  if (siginterrupt(SIGURG, 1) < 0) {
12✔
669
    pr_log_pri(PR_LOG_WARNING,
670
      "warning: unable to make SIGURG interrupt system calls: %s",
12✔
671
      strerror(errno));
12✔
672
  }
673
#endif /* HAVE_SIGACTION or HAVE_SIGINTERRUPT */
674

12✔
675
  /* Reset all of the timing-related variables for data transfers. */
12✔
676
  pr_gettimeofday_millis(&data_start_ms);
677
  data_first_byte_read = FALSE;
678
  data_first_byte_written = FALSE;
12✔
679

12✔
680
  return res;
12✔
681
}
12✔
682

683
void pr_data_close2(void) {
684
  nstrm = NULL;
3✔
685

3✔
686
  if (session.d != NULL) {
687
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
3✔
688
    session.d = NULL;
1✔
689
  }
690

3✔
691
  /* Aborts no longer necessary */
692
  signal(SIGURG, SIG_IGN);
693

694
  if (timeout_noxfer) {
695
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
696
  }
697

698
  if (timeout_stalled) {
699
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
700
  }
701

2✔
702
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
703
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
2✔
704
  pr_session_set_idle();
1✔
705
}
1✔
706

707
/* close == successful transfer */
708
void pr_data_close(int quiet) {
2✔
709
  pr_data_close2();
710

711
  if (quiet == FALSE) {
712
    pr_response_add(R_226, _("Transfer complete"));
713
  }
714
}
2✔
715

2✔
716
/* Note: true_abort may be false in real abort situations, because
717
 * some ftp clients close the data connection at the same time as they
718
 * send the OOB byte (which results in a broken pipe on our
719
 * end).  Thus, it's a race between the OOB data and the tcp close
720
 * finishing.  Either way, it's ok (client will see either "Broken pipe"
721
 * error or "Aborted").  xfer_abor() in mod_xfer cleans up the session
11✔
722
 * flags in any case.  session flags will end up have SF_POST_ABORT
11✔
723
 * set if the OOB byte won the race.
11✔
724
 */
725
void pr_data_cleanup(void) {
24✔
726
  /* sanity check */
727
  if (session.d != NULL) {
728
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
729
    session.d = NULL;
730
  }
11✔
731

9✔
732
  pr_data_clear_xfer_pool();
733

734
  /* Clear/restore the default data transfer type. Otherwise, things like
735
   * APPEs or STOUs will be preserved for the next upload erroneously
8✔
736
   * (see Bug#3612).
737
   */
738
  session.xfer.xfer_type = STOR_DEFAULT;
1✔
739
}
740

741
/* In order to avoid clearing the transfer counters in session.xfer, we don't
9✔
742
 * clear session.xfer here, it should be handled by the appropriate
743
 * LOG_CMD/LOG_CMD_ERR handler calling pr_data_cleanup().
744
 */
11✔
745
void pr_data_abort(int err, int quiet) {
11✔
746
  int true_abort = XFER_ABORTED;
747
  nstrm = NULL;
748

11✔
749
  pr_trace_msg(trace_channel, 9,
11✔
750
    "aborting data transfer (errno = %s (%d), quiet = %s, true abort = %s)",
751
    strerror(err), err, quiet ? "true" : "false",
752
    true_abort ? "true" : "false");
11✔
753

11✔
754
  if (session.d != NULL) {
11✔
755
    if (true_abort) {
756
      /* For "true" aborts, we also asynchronously send a 426 response
11✔
757
       * message via the "lingering abort" functions.
10✔
758
       */
10✔
759
      pr_inet_lingering_abort(session.pool, session.d, timeout_linger);
10✔
760

761
    } else {
10✔
762
      pr_inet_lingering_close(session.pool, session.d, timeout_linger);
763
    }
2✔
764

765
    session.d = NULL;
766
  }
767

768
  if (timeout_noxfer) {
769
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
770
  }
771

772
  if (timeout_stalled) {
773
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
2✔
774
  }
2✔
775

2✔
776
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
777
  session.sf_flags &= (SF_ALL^(SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
778
  pr_session_set_idle();
1✔
779

1✔
780
  if (!quiet) {
1✔
781
    char *respcode = R_426;
1✔
782
    char *msg = NULL;
783
    char msgbuf[64];
784

785
    switch (err) {
1✔
786

787
    case 0:
788
#ifdef ECONNABORTED
789
    case ECONNABORTED:        /* FALLTHROUGH */
790
#endif
791
#ifdef ECONNRESET
1✔
792
    case ECONNRESET:        /* FALLTHROUGH */
1✔
793
#endif
1✔
794
#ifdef EPIPE
795
    case EPIPE:
796
#endif
797
      respcode = R_426;
798
      msg = _("Data connection closed");
799
      break;
800

801
#ifdef ENXIO
802
    case ENXIO:
803
      respcode = R_451;
804
      msg = _("Unexpected streams hangup");
805
      break;
806
#endif
807

808
#ifdef EAGAIN
809
    case EAGAIN:                /* FALLTHROUGH */
810
#endif
811
#ifdef ENOMEM
812
    case ENOMEM:
813
#endif
814
#if defined(EAGAIN) || defined(ENOMEM)
815
      respcode = R_451;
816
      msg = _("Insufficient memory or file locked");
817
      break;
818
#endif
819

820
#ifdef ETXTBSY
821
    case ETXTBSY:                /* FALLTHROUGH */
822
#endif
823
#ifdef EBUSY
824
    case EBUSY:
825
#endif
826
#if defined(ETXTBSY) || defined(EBUSY)
827
      respcode = R_451;
828
      break;
829
#endif
830

831
#ifdef ENOSPC
832
    case ENOSPC:
833
      respcode = R_452;
834
      break;
835
#endif
836

837
#ifdef EDQUOT
838
    case EDQUOT:                /* FALLTHROUGH */
839
#endif
840
#ifdef EFBIG
841
    case EFBIG:
842
#endif
843
#if defined(EDQUOT) || defined(EFBIG)
844
      respcode = R_552;
845
      break;
846
#endif
847

848
#ifdef ECOMM
849
    case ECOMM:                /* FALLTHROUGH */
850
#endif
851
#ifdef EDEADLK
852
    case EDEADLK:                /* FALLTHROUGH */
853
#endif
854
#ifdef EDEADLOCK
855
# if !defined(EDEADLK) || (EDEADLOCK != EDEADLK)
856
    case EDEADLOCK:                /* FALLTHROUGH */
857
# endif
858
#endif
859
#ifdef EXFULL
860
    case EXFULL:                /* FALLTHROUGH */
861
#endif
862
#ifdef ENOSR
863
    case ENOSR:                /* FALLTHROUGH */
864
#endif
865
#ifdef EPROTO
×
866
    case EPROTO:                /* FALLTHROUGH */
867
#endif
868
#ifdef ETIME
869
    case ETIME:                /* FALLTHROUGH */
870
#endif
871
#ifdef EIO
872
    case EIO:                /* FALLTHROUGH */
873
#endif
874
#ifdef EFAULT
875
    case EFAULT:                /* FALLTHROUGH */
876
#endif
877
#ifdef ESPIPE
878
    case ESPIPE:                /* FALLTHROUGH */
879
#endif
880
#if defined(ECOMM) || defined(EDEADLK) ||  defined(EDEADLOCK) || \
881
    defined(EXFULL) || defined(ENOSR) || defined(EPROTO) || \
882
    defined(ETIME) || defined(EIO) || defined(EFAULT) || \
883
    defined(ESPIPE) || defined(EPIPE)
884
      respcode = R_451;
885
      break;
886
#endif
887

888
#ifdef EREMCHG
×
889
    case EREMCHG:                /* FALLTHROUGH */
×
890
#endif
×
891
#ifdef ESRMNT
892
    case ESRMNT:                /* FALLTHROUGH */
893
#endif
894
#ifdef ESTALE
4✔
895
    case ESTALE:                /* FALLTHROUGH */
6✔
896
#endif
897
#ifdef ENOLINK
×
898
    case ENOLINK:                /* FALLTHROUGH */
×
899
#endif
×
900
#ifdef ENOLCK
901
    case ENOLCK:                /* FALLTHROUGH */
902
#endif
903
#ifdef ENETRESET
10✔
904
    case ENETRESET:                /* FALLTHROUGH */
10✔
905
#endif
906
#ifdef ETIMEDOUT
907
    case ETIMEDOUT:
908
#endif
909
#if defined(EREMCHG) || defined(ESRMNT) ||  defined(ESTALE) || \
910
    defined(ENOLINK) || defined(ENOLCK) || defined(ENETRESET) || \
10✔
911
    defined(ECONNABORTED) || defined(ECONNRESET) || defined(ETIMEDOUT)
2✔
912
      respcode = R_450;
913
      msg = _("Link to file server lost");
914
      break;
915
#endif
916

917
    default:
10✔
918
      respcode = R_426;
919
      msg = _("Data connection closed");
920
      break;
11✔
921
    }
8✔
922

923
    if (msg == NULL &&
11✔
924
        (msg = strerror(err)) == NULL) {
925

926
      if (pr_snprintf(msgbuf, sizeof(msgbuf),
927
          _("Unknown or out of range errno [%d]"), err) > 0) {
928
        msg = msgbuf;
14✔
929
      }
14✔
930
    }
14✔
931

14✔
932
    pr_log_pri(PR_LOG_NOTICE, "notice: user %s: aborting transfer: %s",
14✔
933
      session.user ? session.user : "(unknown)", msg);
14✔
934

935
    /* If we are aborting, then a 426 response has already been sent via
14✔
936
     * pr_inet_lingering_abort(), and we don't want to add another to the
14✔
937
     * error queue.
938
     */
14✔
939
    if (true_abort == FALSE) {
14✔
940
      pr_response_add_err(respcode, _("Transfer aborted. %s"), msg ? msg : "");
941
    }
252✔
942

14✔
943
    /* Forcibly clear the data-transfer instigating command pool from the
944
     * Response API.
14✔
945
     */
14✔
946
    pr_response_set_pool(session.pool);
×
947
  }
948

×
949
  if (true_abort) {
×
950
    session.sf_flags |= SF_POST_ABORT;
×
951
  }
×
952
}
953

954
/* From response.c.  XXX Need to provide these symbols another way. */
×
955
extern pr_response_t *resp_list, *resp_err_list;
956

×
957
static int peek_is_abor_cmd(void) {
958
  int fd, res;
959
  fd_set rfds;
14✔
960
  struct timeval tv;
961
  ssize_t len;
13✔
962
  char buf[5];
13✔
963

964
  tv.tv_sec = 1;
965
  tv.tv_usec = 0;
966

967
  fd = PR_NETIO_FD(session.c->instrm);
968
  pr_trace_msg(trace_channel, 20, "peeking at next data for fd %d", fd);
969

970
  FD_ZERO(&rfds);
971
  FD_SET(fd, &rfds);
972

1✔
973
  res = select(fd + 1, &rfds, NULL, NULL, &tv);
1✔
974
  while (res < 0) {
1✔
975
    int xerrno = errno;
1✔
976

977
    if (xerrno == EINTR) {
1✔
978
      pr_signals_handle();
×
979
      res = select(fd + 1, &rfds, NULL, NULL, &tv);
×
980
      continue;
×
981
    }
982

983
    pr_trace_msg(trace_channel, 20,
1✔
984
      "error waiting for next data on fd %d: %s", fd, strerror(xerrno));
985
    return FALSE;
1✔
986
  }
987

988
  if (res == 0) {
×
989
    /* Timed out. */
990
    pr_trace_msg(trace_channel, 20, "timed out peeking for data on fd %d", fd);
×
991
    return FALSE;
×
992
  }
×
993

994
  /* If we reach here, the peer must have sent something.  Let's see what it
995
   * might be.  Chances are that we received at least 5 bytes, but to be
×
996
   * defensive, we use MSG_WAITALL anyway.  TCP allows for sending one byte
997
   * at time, if need be.  The shortest FTP command is 5 bytes, e.g. "CCC\r\n".
×
998
   * ABOR would be 6 bytes, but we do not want to block until we see 6 bytes;
999
   * we're peeking opportunistically, and optimistically.
1000
   */
26✔
1001
  memset(&buf, 0, sizeof(buf));
26✔
1002
  len = recv(fd, buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
1003
  while (len < 0) {
26✔
1004
    int xerrno = errno;
1005

1006
    if (xerrno == EINTR) {
1007
      pr_signals_handle();
14✔
1008
      len = recv(fd, &buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
14✔
1009
      continue;
14✔
1010
    }
14✔
1011

1012
    pr_trace_msg(trace_channel, 20,
14✔
1013
      "error peeking at next data: %s", strerror(xerrno));
14✔
1014
    return FALSE;
1015
  }
1016

1017
  pr_trace_msg(trace_channel, 20, "peeking at %ld bytes of next data",
1018
    (long) len);
1019
  if (strncasecmp(buf, "ABOR\r", len) == 0) {
1020
    pr_trace_msg(trace_channel, 20, "peeked data probably 'ABOR' command");
1021
    return TRUE;
1022
  }
1023

1024
  pr_trace_msg(trace_channel, 20, "peeked data '%.*s' not ABOR command",
1025
    (int) len, buf);
1026
  return FALSE;
1027
}
1028

1029
static void poll_ctrl(void) {
1030
  int res;
1031

1032
  if (session.c == NULL) {
1033
    return;
1034
  }
1035

14✔
1036
  pr_trace_msg(trace_channel, 4, "polling for commands on control channel");
×
1037
  pr_netio_set_poll_interval(session.c->instrm, 0);
1038
  res = pr_netio_poll(session.c->instrm);
1039
  pr_netio_reset_poll_interval(session.c->instrm);
×
1040

1041
  if (res == 0 &&
×
1042
      !(session.sf_flags & SF_ABORT)) {
×
1043

×
1044
    /* First, we peek at the data, to see if it is an ABOR command.  Why?
1045
     *
1046
     * Consider the case where a client uses the TCP OOB mechanism and
1047
     * marks the ABOR command with the marker.  In that case, a SIGURG signal
1048
     * will have been raised, and the SF_ABORT flag set.  The actual "ABOR"
14✔
1049
     * data on the control connection will be read only AFTER the data transfer
14✔
1050
     * has been failed.  This leads the proper ordering of multiple responses
14✔
1051
     * (first for failed transfer, second for successful ABOR) in such cases.
1052
     *
14✔
1053
     * Now consider the case where a client does NOT use the TCP OOB mechanism,
1054
     * and only sends the ABOR command.  We want the same behavior in this case
1055
     * as for the TCP OOB case, BUT now, the SF_ABORT flag has NOT been set at
14✔
1056
     * this point in the flow.  Which means that we might read that "ABOR" text
14✔
1057
     * from the control connection _in the middle_ of the data transfer, which
×
1058
     * leads to different behavior, different ordering of responses.
1059
     *
1060
     * Thus we cheat here, and only peek at the control connection data.  IFF
×
1061
     * it is the "ABOR\r\n" text, then we set the SF_ABORT flag ourselves
1062
     * here, and preserve the expected semantics (Bug #4402).
1063
     */
1064
    if (peek_is_abor_cmd() == TRUE) {
1065
      pr_trace_msg(trace_channel, 5, "client sent 'ABOR' command during data "
1066
        "transfer, setting 'aborted' session flag");
1067

×
1068
      session.sf_flags |= SF_ABORT;
1069

1070
      if (nstrm != NULL) {
×
1071
        pr_netio_abort(nstrm);
1072
        errno = 0;
1073
      }
1074
    }
×
1075
  }
1076

1077
  if (res == 0 &&
1078
      !(session.sf_flags & SF_ABORT)) {
1079
    cmd_rec *cmd = NULL;
14✔
1080

7✔
1081
    pr_trace_msg(trace_channel, 1,
1082
      "data available for reading on control channel during data transfer, "
35✔
1083
      "reading control data");
28✔
1084
    res = pr_cmd_read(&cmd);
28✔
1085
    if (res < 0) {
1086
      int xerrno;
1087

1088
#if defined(ECONNABORTED)
7✔
1089
      xerrno = ECONNABORTED;
1090
#elif defined(ENOTCONN)
1091
      xerrno = ENOTCONN;
1092
#else
1093
      xerrno = EIO;
1094
#endif
1095

1096
      pr_trace_msg(trace_channel, 1,
1097
        "unable to read control command during data transfer: %s",
1098
        strerror(xerrno));
1099
      errno = xerrno;
1100

14✔
1101
#ifndef PR_DEVEL_NO_DAEMON
14✔
1102
      /* Otherwise, EOF */
14✔
1103
      pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CLIENT_EOF, NULL);
14✔
1104
#else
14✔
1105
      return;
14✔
1106
#endif /* PR_DEVEL_NO_DAEMON */
14✔
1107

14✔
1108
    } else if (cmd != NULL) {
14✔
1109
      char *ch;
14✔
1110

14✔
1111
      for (ch = cmd->argv[0]; *ch; ch++) {
12✔
1112
        if (PR_ISALPHA((int) *ch)) {
7✔
1113
          *ch = toupper((int) *ch);
2✔
1114
        }
1115
      }
2✔
1116

1117
      cmd->cmd_id = pr_cmd_get_id(cmd->argv[0]);
2✔
1118

1119
      /* Only handle commands which do not involve data transfers; we
2✔
1120
       * already have a data transfer in progress.  For any data transfer
2✔
1121
       * command, send a 450 ("busy") reply.  Looks like almost all of the
1122
       * data transfer commands accept that response, as per RFC959.
2✔
1123
       *
1124
       * We also prevent the EPRT, EPSV, PASV, and PORT commands, since
2✔
1125
       * they will also interfere with the current data transfer.  In doing
2✔
1126
       * so, we break RFC compliance a little; RFC959 does not allow a
1127
       * response code of 450 for those commands (although it should).
2✔
1128
       */
1129
      if (pr_cmd_cmp(cmd, PR_CMD_APPE_ID) == 0 ||
2✔
1130
          pr_cmd_cmp(cmd, PR_CMD_LIST_ID) == 0 ||
2✔
1131
          pr_cmd_cmp(cmd, PR_CMD_MLSD_ID) == 0 ||
1132
          pr_cmd_cmp(cmd, PR_CMD_NLST_ID) == 0 ||
1133
          pr_cmd_cmp(cmd, PR_CMD_RETR_ID) == 0 ||
1134
          pr_cmd_cmp(cmd, PR_CMD_STOR_ID) == 0 ||
1135
          pr_cmd_cmp(cmd, PR_CMD_STOU_ID) == 0 ||
1136
          pr_cmd_cmp(cmd, PR_CMD_RNFR_ID) == 0 ||
1137
          pr_cmd_cmp(cmd, PR_CMD_RNTO_ID) == 0 ||
1138
          pr_cmd_cmp(cmd, PR_CMD_PORT_ID) == 0 ||
5✔
1139
          pr_cmd_cmp(cmd, PR_CMD_EPRT_ID) == 0 ||
2✔
1140
          pr_cmd_cmp(cmd, PR_CMD_PASV_ID) == 0 ||
1141
          pr_cmd_cmp(cmd, PR_CMD_EPSV_ID) == 0) {
2✔
1142
        pool *resp_pool;
1143

2✔
1144
        pr_trace_msg(trace_channel, 5,
1145
          "client sent '%s' command during data transfer, denying",
2✔
1146
          (char *) cmd->argv[0]);
2✔
1147

1148
        resp_list = resp_err_list = NULL;
2✔
1149
        resp_pool = pr_response_get_pool();
1150

2✔
1151
        pr_response_set_pool(cmd->pool);
2✔
1152

1153
        pr_response_add_err(R_450, _("%s: data transfer in progress"),
2✔
1154
          (char *) cmd->argv[0]);
1155

2✔
1156
        pr_response_flush(&resp_err_list);
2✔
1157

1158
        pr_response_set_pool(resp_pool);
1159
        destroy_pool(cmd->pool);
3✔
1160

3✔
1161
      /* We don't want to actually dispatch the NOOP command, since that
3✔
1162
       * would overwrite the scoreboard with the NOOP state; admins probably
3✔
1163
       * want to see the command that caused the data transfer.  And since
3✔
1164
       * NOOP doesn't take a 450 response (as per RFC959), we will simply
1165
       * return 200.
3✔
1166
       */
1167
      } else if (pr_cmd_cmp(cmd, PR_CMD_NOOP_ID) == 0) {
3✔
1168
        pool *resp_pool;
1169

3✔
1170
        pr_trace_msg(trace_channel, 5,
3✔
1171
          "client sent '%s' command during data transfer, ignoring",
×
1172
          (char *) cmd->argv[0]);
×
1173

1174
        resp_list = resp_err_list = NULL;
1175
        resp_pool = pr_response_get_pool();
3✔
1176

3✔
1177
        pr_response_set_pool(cmd->pool);
3✔
1178

3✔
1179
        pr_response_add(R_200, _("%s: data transfer in progress"),
3✔
1180
          (char *) cmd->argv[0]);
1181

3✔
1182
        pr_response_flush(&resp_list);
3✔
1183

1184
        pr_response_set_pool(resp_pool);
3✔
1185
        destroy_pool(cmd->pool);
3✔
1186

1187
      } else {
3✔
1188
        char *title_buf = NULL;
1189
        int curr_cmd_id = 0, title_len = -1;
3✔
1190
        const char *curr_cmd = NULL, *sce_cmd = NULL, *sce_cmd_arg = NULL;
1191
        cmd_rec *curr_cmd_rec = NULL;
1192
        pool *resp_pool;
3✔
1193

×
1194
        pr_trace_msg(trace_channel, 5,
1195
          "client sent '%s' command during data transfer, dispatching",
1196
          (char *) cmd->argv[0]);
3✔
1197

3✔
1198
        title_len = pr_proctitle_get(NULL, 0);
3✔
1199
        if (title_len > 0) {
1200
          title_buf = pcalloc(cmd->pool, title_len + 1);
3✔
1201
          pr_proctitle_get(title_buf, title_len + 1);
3✔
1202
        }
3✔
1203

1204
        curr_cmd = session.curr_cmd;
1205
        curr_cmd_id = session.curr_cmd_id;
1206
        curr_cmd_rec = session.curr_cmd_rec;
7✔
1207
        sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD);
1208
        sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG);
7✔
1209

1210
        resp_list = resp_err_list = NULL;
1211
        resp_pool = pr_response_get_pool();
1212

1213
        pr_response_set_pool(cmd->pool);
1214
        pr_cmd_dispatch(cmd);
1215

1216
        pr_scoreboard_entry_update(session.pid,
1217
          PR_SCORE_CMD, "%s", sce_cmd, NULL, NULL);
1218
        pr_scoreboard_entry_update(session.pid,
1219
          PR_SCORE_CMD_ARG, "%s", sce_cmd_arg, NULL, NULL);
1220

34✔
1221
        if (title_len > 0) {
34✔
1222
          pr_proctitle_set_str(title_buf);
34✔
1223
        }
34✔
1224

34✔
1225
        pr_response_flush(&resp_list);
1226
        pr_response_set_pool(resp_pool);
34✔
1227
        destroy_pool(cmd->pool);
34✔
1228

8✔
1229
        session.curr_cmd = curr_cmd;
8✔
1230
        session.curr_cmd_id = curr_cmd_id;
1231
        session.curr_cmd_rec = curr_cmd_rec;
1232
      }
1233

1234
    } else {
1235
      pr_trace_msg(trace_channel, 3,
26✔
1236
        "invalid command sent, sending error response");
1237
      pr_response_send(R_500, _("Invalid command: try being more creative"));
1238
    }
1239
  }
1240
}
26✔
1241

4✔
1242
/* pr_data_xfer() actually transfers the data on the data connection.  ASCII
1243
 * translation is performed if necessary.  `direction' is set when the data
1244
 * connection was opened.
4✔
1245
 *
1246
 * We determine if the client buffer is read from or written to.  Returns 0 if
1247
 * reading and data connection closes, or -1 if error (with errno set).
1248
 */
1249
int pr_data_xfer(char *cl_buf, size_t cl_size) {
1250
  int len = 0;
1251
  int total = 0;
4✔
1252
  int res = 0;
1253
  pool *tmp_pool = NULL;
1254

4✔
1255
  if (cl_buf == NULL ||
1256
      cl_size == 0) {
1257
    errno = EINVAL;
1258
    return -1;
4✔
1259
  }
4✔
1260

1261
  /* Poll the control channel for any commands we should handle, like
1262
   * QUIT or ABOR.
22✔
1263
   */
12✔
1264
  poll_ctrl();
1265

12✔
1266
  /* If we don't have a data connection here (e.g. might have been closed
1267
   * by an ABOR), then return zero (no data transferred).
1268
   */
1269
  if (session.d == NULL) {
1270
    int xerrno;
1271

12✔
1272
#if defined(ECONNABORTED)
7✔
1273
    xerrno = ECONNABORTED;
7✔
1274
#elif defined(ENOTCONN)
1275
    xerrno = ENOTCONN;
7✔
1276
#else
7✔
1277
    xerrno = EIO;
7✔
1278
#endif
1279

7✔
1280
    pr_trace_msg(trace_channel, 1,
1281
      "data connection is null prior to data transfer (possibly from "
7✔
1282
      "aborted transfer), returning '%s' error", strerror(xerrno));
7✔
1283
    pr_log_debug(DEBUG5,
7✔
1284
      "data connection is null prior to data transfer (possibly from "
1✔
1285
       "aborted transfer), returning '%s' error", strerror(xerrno));
1286

1✔
1287
    errno = xerrno;
1288
    return -1;
1289
  }
1290

1291
  if (session.xfer.direction == PR_NETIO_IO_RD) {
×
1292
    char *buf;
×
1293

1294
    buf = session.xfer.buf;
×
1295

×
1296
    /* We use ASCII translation if:
×
1297
     *
1298
     * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
1299
     */
1✔
1300
    if (((session.sf_flags & SF_ASCII) &&
1✔
1301
        !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
1✔
1302
      int adjlen, buflen;
1303

1304
      do {
6✔
1305
        buflen = session.xfer.buflen;        /* how much remains in buf */
6✔
1306
        adjlen = 0;
2✔
1307

2✔
1308
        pr_signals_handle();
2✔
1309

1310
        len = pr_netio_read(session.d->instrm, buf + buflen,
2✔
1311
          session.xfer.bufsize - buflen, 1);
2✔
1312
        while (len < 0) {
1313
          int xerrno = errno;
2✔
1314

1315
          if (xerrno == EAGAIN || xerrno == EINTR) {
1316
            /* Since our socket is in non-blocking mode, read(2) can return
1317
             * EAGAIN if there is no data yet for us.  Handle this by
2✔
1318
             * delaying temporarily, then trying again.
1319
             */
1320
            errno = EINTR;
6✔
1321
            pr_signals_handle();
6✔
1322

1323
            len = pr_netio_read(session.d->instrm, buf + buflen,
1324
              session.xfer.bufsize - buflen, 1);
6✔
1325
            continue;
1326
          }
6✔
1327

6✔
1328
          destroy_pool(tmp_pool);
1329
          errno = xerrno;
1330
          return -1;
1331
        }
1332

6✔
1333
        if (len > 0 &&
6✔
1334
            data_first_byte_read == FALSE) {
1335
          if (pr_trace_get_level(timing_channel)) {
1336
            unsigned long elapsed_ms;
1337
            uint64_t read_ms;
1338

1339
            pr_gettimeofday_millis(&read_ms);
1340
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
1341

1342
            pr_trace_msg(timing_channel, 7,
1343
              "Time for first data byte read: %lu ms", elapsed_ms);
1344
          }
1345

1346
          data_first_byte_read = TRUE;
1347
        }
6✔
1348

6✔
1349
        if (len > 0) {
6✔
1350
          pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
1351
            len != 1 ? "bytes" : "byte");
6✔
1352

6✔
1353
          buflen += len;
6✔
1354

1355
          if (timeout_stalled) {
1356
            pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
6✔
1357
          }
6✔
1358
        }
×
1359

×
1360
        /* If buflen > 0, data remains in the buffer to be copied. */
1361
        if (len >= 0 &&
1362
            buflen > 0) {
6✔
1363

6✔
1364
          /* Perform ASCII translation:
1365
           *
1366
           * buflen: is returned as the modified buffer length after
1367
           *         translation
1368
           * res:    is returned as the number of characters unprocessed in
6✔
1369
           *         the buffer (to be dealt with later)
1370
           *
1371
           * We skip the call to pr_ascii_ftp_from_crlf() in one case:
1372
           * when we have one character in the buffer and have reached
×
1373
           * end of data, this is so that pr_ascii_ftp_from_crlf() won't sit
×
1374
           * forever waiting for the next character after a final '\r'.
1375
           */
1376
          if (len > 0 ||
6✔
1377
              buflen > 1) {
1378
            size_t outlen = 0;
1379

1380
            if (tmp_pool == NULL) {
1381
              tmp_pool = make_sub_pool(session.xfer.p);
1382
              pr_pool_tag(tmp_pool, "ASCII upload");
1383
            }
1384

1385
            res = pr_ascii_ftp_from_crlf(tmp_pool, buf, buflen, &buf, &outlen);
6✔
1386
            if (res < 0) {
1✔
1387
              pr_trace_msg(trace_channel, 3, "error reading ASCII data: %s",
1388
                strerror(errno));
1389

1390
            } else {
6✔
1391
              adjlen += res;
6✔
1392
              buflen = (int) outlen;
1393
            }
1394
          }
1395

1396
          /* Now copy everything we can into cl_buf */
1397
          if ((size_t) buflen > cl_size) {
1398
            /* Because we have to cut our buffer short, make sure this
1399
             * is made up for later by increasing adjlen.
6✔
1400
             */
1401
            adjlen += (buflen - cl_size);
1402
            buflen = cl_size;
1403
          }
1404

1405
          memcpy(cl_buf, buf, buflen);
5✔
1406

5✔
1407
          /* Copy whatever remains at the end of session.xfer.buf to the
1✔
1408
           * head of the buffer and adjust buf accordingly.
1409
           *
1✔
1410
           * adjlen is now the total bytes still waiting in buf, if
1411
           * anything remains, copy it to the start of the buffer.
1412
           */
1413

1414
          if (adjlen > 0) {
×
1415
            memcpy(buf, buf + buflen, adjlen);
×
1416
          }
1417

×
1418
          /* Store everything back in session.xfer. */
×
1419
          session.xfer.buflen = adjlen;
1420
          total += buflen;
1421
        }
1422
        
1423
        /* Restart if data was returned by pr_netio_read() (len > 0) but no
1424
         * data was copied to the client buffer (buflen = 0).  This indicates
5✔
1425
         * that pr_ascii_ftp_from_crlf() needs more data in order to
4✔
1426
         * translate, so we need to call pr_netio_read() again.
1427
         */
1428
      } while (len > 0 && buflen == 0);
4✔
1429

2✔
1430
      /* Return how much data we actually copied into the client buffer. */
2✔
1431
      len = buflen;
2✔
1432

1433
    } else {
2✔
1434
      len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
2✔
1435
      while (len < 0) {
1436
        int xerrno = errno;
2✔
1437

1438
        if (xerrno == EAGAIN || xerrno == EINTR) {
1439
          /* Since our socket is in non-blocking mode, read(2) can return
1440
           * EAGAIN if there is no data yet for us.  Handle this by
2✔
1441
           * delaying temporarily, then trying again.
1442
           */
1443
          errno = EINTR;
1444
          pr_signals_handle();
4✔
1445

4✔
1446
          len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
1447
          continue;
1448
        }
1449

1450
        break;
1451
      }
1452

1453
      if (len > 0) {
1454
        pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
18✔
1455
          len != 1 ? "bytes" : "byte");
10✔
1456

10✔
1457
        if (data_first_byte_read == FALSE) {
10✔
1458
          if (pr_trace_get_level(timing_channel)) {
10✔
1459
            unsigned long elapsed_ms;
1460
            uint64_t read_ms;
10✔
1461

1462
            pr_gettimeofday_millis(&read_ms);
10✔
1463
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
×
1464

1465
            pr_trace_msg(timing_channel, 7,
1466
              "Time for first data byte read: %lu ms", elapsed_ms);
10✔
1467
          }
10✔
1468

1469
          data_first_byte_read = TRUE;
1470
        }
1471

1472
        /* Non-ASCII mode doesn't need to use session.xfer.buf */
1473
        if (timeout_stalled) {
1474
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
10✔
1475
        }
4✔
1476

1✔
1477
        total += len;
7✔
1478
      }
7✔
1479
    }
1480

7✔
1481
  } else { /* PR_NETIO_IO_WR */
7✔
1482

7✔
1483
    while (cl_size) {
1484
      int bwrote = 0;
1485
      int buflen = cl_size;
1486
      unsigned int xferbuflen;
7✔
1487
      char *xferbuf = NULL, *ascii_buf = NULL;
1488

1489
      pr_signals_handle();
1490

1491
      if (buflen > pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR)) {
1492
        buflen = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);
1493
      }
7✔
1494

1495
      xferbuf = cl_buf;
7✔
1496
      xferbuflen = buflen;
×
1497

×
1498
      /* We use ASCII translation if:
1499
       *
1500
       * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST)
7✔
1501
       * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
7✔
1502
       */
7✔
1503
      if ((session.sf_flags & SF_ASCII_OVERRIDE) ||
1504
          ((session.sf_flags & SF_ASCII) &&
1505
           !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
7✔
1506
        char *out = NULL;
1507
        size_t outlen = 0;
1508

10✔
1509
        if (tmp_pool == NULL) {
12✔
1510
          tmp_pool = make_sub_pool(session.xfer.p);
4✔
1511
          pr_pool_tag(tmp_pool, "ASCII download");
1512
        }
6✔
1513

4✔
1514
        /* Fill up our internal buffer. */
1515
        memcpy(session.xfer.buf, cl_buf, buflen);
1516

1517
        /* Scan the internal buffer, looking for LFs with no preceding CRs.
1518
         * Add CRs (and expand the internal buffer) as necessary. xferbuflen
2✔
1519
         * will be adjusted so that it contains the length of data in
2✔
1520
         * the internal buffer, including any added CRs.
1521
         */
2✔
1522
        res = pr_ascii_ftp_to_crlf(tmp_pool, session.xfer.buf, xferbuflen,
2✔
1523
          &out, &outlen);
1524
        if (res < 0) {
1525
          pr_trace_msg(trace_channel, 1, "error writing ASCII data: %s",
2✔
1526
            strerror(errno));
2✔
1527

1528
        } else {
1✔
1529
          ascii_buf = session.xfer.buf;
1✔
1530
          session.xfer.buf = out;
1531
          session.xfer.buflen = xferbuflen = outlen;
1532
        }
2✔
1533

2✔
1534
        xferbuf = session.xfer.buf;
1535
      }
1536

8✔
1537
      bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
8✔
1538
      while (bwrote < 0) {
1539
        int xerrno = errno;
1540

8✔
1541
        if (xerrno == EAGAIN ||
3✔
1542
            xerrno == EINTR) {
3✔
1543
          /* Since our socket may be in non-blocking mode, write(2) can return
3✔
1544
           * EAGAIN if there is not enough from for our data yet.  Handle
1545
           * this by delaying temporarily, then trying again.
3✔
1546
           */
3✔
1547
          errno = EINTR;
1548
          pr_signals_handle();
3✔
1549

1550
          bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
1551
          continue;
1552
        }
3✔
1553

1554
        destroy_pool(tmp_pool);
1555
        if (ascii_buf != NULL) {
8✔
1556
          /* Free up the malloc'd memory. */
8✔
1557
          free(session.xfer.buf);
1558
          session.xfer.buf = ascii_buf;
1559
        }
8✔
1560

8✔
1561
        errno = xerrno;
8✔
1562
        return -1;
1563
      }
1564

8✔
1565
      if (bwrote > 0) {
1566
        pr_trace_msg(trace_channel, 19, "wrote %d %s to network", bwrote,
1567
          bwrote != 1 ? "bytes" : "byte");
1568

6✔
1569
        if (data_first_byte_written == FALSE) {
6✔
1570
          if (pr_trace_get_level(timing_channel)) {
1571
            unsigned long elapsed_ms;
1572
            uint64_t write_ms;
1573

1574
            pr_gettimeofday_millis(&write_ms);
1575
            elapsed_ms = (unsigned long) (write_ms - data_start_ms);
1576

19✔
1577
            pr_trace_msg(timing_channel, 7,
1578
              "Time for first data byte written: %lu ms", elapsed_ms);
18✔
1579
          }
1580

1581
          data_first_byte_written = TRUE;
19✔
1582
        }
19✔
1583

19✔
1584
        if (timeout_stalled) {
11✔
1585
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1586
        }
1587

8✔
1588
        cl_size -= buflen;
1589
        cl_buf += buflen;
1590
        total += buflen;
19✔
1591
      }
19✔
1592

1593
      if (ascii_buf != NULL) {
1594
        /* Yes, we are using malloc et al here, rather than the memory pools.
1595
         * See Bug#4352 for details.
1596
         */
1597
        free(session.xfer.buf);
1598
        session.xfer.buf = ascii_buf;
1599
      }
7✔
1600
    }
7✔
1601

7✔
1602
    len = total;
1603
  }
1604

1605
  if (total &&
1606
      timeout_idle) {
1607
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
7✔
1608
  }
7✔
1609

3✔
1610
  session.xfer.total_bytes += total;
3✔
1611
  session.total_bytes += total;
1612
  if (session.xfer.direction == PR_NETIO_IO_RD) {
1613
    session.total_bytes_in += total;
4✔
1614

1✔
1615
  } else {
1✔
1616
    session.total_bytes_out += total;
1617
  }
1618

3✔
1619
  destroy_pool(tmp_pool);
1✔
1620
  return (len < 0 ? -1 : len);
1✔
1621
}
1622

1623
#if defined(HAVE_SENDFILE)
2✔
1624
/* pr_data_sendfile() actually transfers the data on the data connection.
2✔
1625
 * ASCII translation is not performed.
1626
 * return 0 if reading and data connection closes, or -1 if error
1627
 */
1628
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
1629
  int flags, error;
2✔
1630
  pr_sendfile_t len = 0, total = 0;
×
1631
# if defined(HAVE_AIX_SENDFILE)
1632
  struct sf_parms parms;
1633
  int rc;
1634
# endif /* HAVE_AIX_SENDFILE */
1635

2✔
1636
  if (offset == NULL ||
1637
      count == 0) {
2✔
1638
    errno = EINVAL;
1639
    return -1;
1640
  }
1641

1642
  if (session.xfer.direction == PR_NETIO_IO_RD) {
1643
    errno = EPERM;
1644
    return -1;
1645
  }
1646

1647
  if (session.d == NULL) {
1648
    errno = EPERM;
1649
    return -1;
1650
  }
1651

1652
  flags = fcntl(PR_NETIO_FD(session.d->outstrm), F_GETFL);
1653
  if (flags < 0) {
1654
    return -1;
1655
  }
2✔
1656

1657
  /* Set fd to blocking-mode for sendfile() */
1658
  if (flags & O_NONBLOCK) {
1659
    if (fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags^O_NONBLOCK) < 0) {
1660
      return -1;
1661
    }
1662
  }
1663

1664
  for (;;) {
1665
# if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_SOLARIS_SENDFILE)
1666
    off_t orig_offset = *offset;
1667

1668
    /* Linux semantics are fairly straightforward in a glibc 2.x world:
1669
     *
1670
     *   #include <sys/sendfile.h>
1671
     *
1672
     *   ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
1673
     *
1674
     * Unfortunately, this API does not allow for an off_t number of bytes
2✔
1675
     * to be sent, only a size_t.  This means we need to make sure that
2✔
1676
     * the given count does not exceed the maximum value for a size_t.  Even
1677
     * worse, the return value is a ssize_t, not a size_t, which means
1678
     * the maximum value used can only be of the maximum _signed_ value,
1679
     * not the maximum unsigned value.  This means calling sendfile() more
1680
     * times.  How annoying.
2✔
1681
     */
×
1682

1683
#  if defined(HAVE_LINUX_SENDFILE)
1684
    if (count > INT_MAX) {
1685
      count = INT_MAX;
1686
    }
1687
#  elif defined(HAVE_SOLARIS_SENDFILE)
×
1688
#   if SIZEOF_SIZE_T == SIZEOF_INT
1689
    if (count > INT_MAX) {
1690
      count = INT_MAX;
2✔
1691
    }
2✔
1692
#   elif SIZEOF_SIZE_T == SIZEOF_LONG
1693
    if (count > LONG_MAX) {
1694
      count = LONG_MAX;
1695
    }
×
1696
#   elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
×
1697
    if (count > LLONG_MAX) {
1698
      count = LLONG_MAX;
×
1699
    }
×
1700
#   endif
×
1701
#  endif /* !HAVE_SOLARIS_SENDFILE */
×
1702

1703
    errno = 0;
×
1704
    len = sendfile(PR_NETIO_FD(session.d->outstrm), retr_fd, offset, count);
1705

1706
    /* If no data could be written (e.g. the file was truncated), we're
×
1707
     * done (Bug#4318).
1708
     */
1709
    if (len == 0) {
×
1710
      if (errno != EINTR &&
×
1711
          errno != EAGAIN) {
×
1712
        break;
1713
      }
1714

×
1715
      /* Handle our interrupting signal, and continue. */
×
1716
      pr_signals_handle();
1717
    }
1718

1719
    if (len != -1 &&
×
1720
        len < count) {
×
1721
      /* Under Linux semantics, this occurs when a signal has interrupted
×
1722
       * sendfile().
×
1723
       */
×
1724
      if (XFER_ABORTED) {
1725
        errno = EINTR;
×
1726

×
1727
        session.xfer.total_bytes += len;
1728
        session.total_bytes += len;
1729
        session.total_bytes_out += len;
2✔
1730
        session.total_raw_out += len;
1731

1732
        return -1;
1733
      }
1✔
1734

1✔
1735
      count -= len;
1736

1737
      /* Only reset the timers if data have actually been written out. */
1738
      if (len > 0) {
1739
        if (timeout_stalled) {
1740
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1741
        }
1742

1743
        if (timeout_idle) {
1744
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1745
        }
1746
      }
1747

1748
      session.xfer.total_bytes += len;
1749
      session.total_bytes += len;
1750
      session.total_bytes_out += len;
1751
      session.total_raw_out += len;
1752
      total += len;
1753

1754
      pr_signals_handle();
1755
      continue;
1756
    }
1757

1758
    if (len == -1) {
1759
      /* Linux updates offset on error, not len like BSD, fix up so
1760
       * BSD-based code works.
1761
       */
1762
      len = *offset - orig_offset;
1763
      *offset = orig_offset;
1764

1765
# elif defined(HAVE_BSD_SENDFILE)
1766
    /* BSD semantics for sendfile are flexible...it'd be nice if we could
1767
     * standardize on something like it.  The semantics are:
1768
     *
1769
     *   #include <sys/types.h>
1770
     *   #include <sys/socket.h>
1771
     *   #include <sys/uio.h>
1772
     *
1773
     *   int sendfile(int in_fd, int out_fd, off_t offset, size_t count,
1774
     *                struct sf_hdtr *hdtr, off_t *len, int flags)
1775
     *
1776
     *  The comments above, about size_t versus off_t, apply here as
1777
     *  well.  Except that BSD's sendfile() uses an off_t * for returning
1778
     *  the number of bytes sent, so we can use the maximum unsigned
1779
     *  value.
1780
     */
1781

1782
#  if SIZEOF_SIZE_T == SIZEOF_INT
1783
    if (count > UINT_MAX) {
1784
      count = UINT_MAX;
1785
    }
1786
#  elif SIZEOF_SIZE_T == SIZEOF_LONG
1787
    if (count > ULONG_MAX) {
1788
      count = ULONG_MAX;
1789
    }
1790
#  elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
1791
    if (count > ULLONG_MAX) {
1792
      count = ULLONG_MAX;
1793
    }
1794
#  endif
1795

1796
    if (sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, count,
1797
        NULL, &len, 0) == -1) {
1798

1799
# elif defined(HAVE_MACOSX_SENDFILE)
1800
    off_t orig_len = count;
1801
    int res;
1802

1803
    /* Since Mac OSX uses the fourth argument as a value-return parameter,
1804
     * success or failure, we need to put the result into len after the
1805
     * call.
1806
     */
1807

1808
    res = sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, &orig_len,
1809
      NULL, 0);
1810
    len = orig_len;
1811

1812
    if (res < 0) {
1813
# elif defined(HAVE_AIX_SENDFILE)
1814

1815
    memset(&parms, 0, sizeof(parms));
1✔
1816

×
1817
    parms.file_descriptor = retr_fd;
×
1818
    parms.file_offset = (uint64_t) *offset;
×
1819
    parms.file_bytes = (int64_t) count;
×
1820

×
1821
    rc = send_file(&(PR_NETIO_FD(session.d->outstrm)), &(parms), (uint_t)0);
1822
    len = (int) parms.bytes_sent;
×
1823

1824
    if (rc < -1 || rc == 1) {
1825
# else
×
1826
    if (FALSE) {
1827
# endif /* HAVE_AIX_SENDFILE */
1828

×
1829
      /* IMO, BSD's semantics are warped.  Apparently, since we have our
1830
       * alarms tagged SA_INTERRUPT (allowing system calls to be
1831
       * interrupted - primarily for select), BSD will interrupt a
1832
       * sendfile operation as well, so we have to catch and handle this
×
1833
       * case specially.  It should also be noted that the sendfile(2) man
×
1834
       * page doesn't state any of this.
1835
       *
×
1836
       * HP/UX has the same semantics, however, EINTR is well documented
×
1837
       * as a side effect in the sendfile(2) man page.  HP/UX, however,
1838
       * is implemented horribly wrong.  If a signal would result in
1839
       * -1 being returned and EINTR being set, what ACTUALLY happens is
×
1840
       * that errno is cleared and the number of bytes written is returned.
×
1841
       *
1842
       * For obvious reasons, HP/UX sendfile is not supported yet.
1843
       */
×
1844
      if (errno == EINTR) {
×
1845
        if (XFER_ABORTED) {
×
1846
          session.xfer.total_bytes += len;
×
1847
          session.total_bytes += len;
×
1848
          session.total_bytes_out += len;
1849
          session.total_raw_out += len;
×
1850

1851
          return -1;
1852
        }
1✔
1853

1✔
1854
        pr_signals_handle();
1✔
1855

1856
        /* If we got everything in this transaction, we're done. */
1✔
1857
        if (len >= count) {
1858
          break;
1859
        }
1860

1861
        count -= len;
1862
        *offset += len;
1✔
1863

×
1864
        if (timeout_stalled) {
1865
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1866
        }
1✔
1867

1✔
1868
        if (timeout_idle) {
1869
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1870
        }
1✔
1871

1✔
1872
        session.xfer.total_bytes += len;
1873
        session.total_bytes += len;
1874
        session.total_bytes_out += len;
1✔
1875
        session.total_raw_out += len;
1✔
1876
        total += len;
1✔
1877

1✔
1878
        continue;
1✔
1879
      }
1880

1✔
1881
      error = errno;
1882
      (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
1883
      errno = error;
1884

1885
      return -1;
1886
    }
1887

1888
    break;
1889
  }
1890

1891
  if (flags & O_NONBLOCK) {
1892
    (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
1893
  }
1894

1895
  if (timeout_stalled) {
1896
    pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1897
  }
1898

1899
  if (timeout_idle) {
1900
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1901
  }
1902

1903
  session.xfer.total_bytes += len;
1904
  session.total_bytes += len;
1905
  session.total_bytes_out += len;
1906
  session.total_raw_out += len;
1907
  total += len;
1908

1909
  return total;
1910
}
1911
#else
1912
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
1913
  errno = ENOSYS;
1914
  return -1;
1915
}
1916
#endif /* HAVE_SENDFILE */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc