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

proftpd / proftpd / 14562012249

20 Apr 2025 06:08PM UTC coverage: 93.03% (+0.4%) from 92.667%
14562012249

push

github

51358 of 55206 relevant lines covered (93.03%)

200.28 hits per line

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

73.58
/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, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
20
 *
21
 * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
22
 * and other respective copyright holders give permission to link this program
23
 * with OpenSSL, and distribute the resulting executable, without including
24
 * the source code for OpenSSL in the source distribution.
25
 */
26

27
/* Data connection management functions */
28

29
#include "conf.h"
30

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

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

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

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

48
/* local macro */
49

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

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

58
static long timeout_linger = PR_TUNABLE_TIMEOUTLINGER;
59

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

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

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

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

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

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

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

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

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

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

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

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

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

133
  /* Protocol and socket options should be set before handshaking. */
134

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

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

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

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

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

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

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

170
    } else {
171

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

194
    return 0;
×
195
  }
196

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

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

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

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

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

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

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

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

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

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

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

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

273
      default:
274
        break;
275
    }
276
  }
277

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

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

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

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

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

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

6✔
311
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
312

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

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

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

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

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

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

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

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

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

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

×
361
  pr_netaddr_set_reverse_dns(rev);
×
362

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

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

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

380
    } else {
381

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

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

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

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

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

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

1✔
428
    case PR_DATA_TIMEOUT_NO_TRANSFER:
429
      return timeout_noxfer;
430

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

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

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

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

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

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

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

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

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

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

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

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

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

2✔
487
  session.d = NULL;
1✔
488
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_POST_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE|SF_EPSV_ALL));
489
}
490

491
int pr_data_ignore_ascii(int ignore_ascii) {
492
  int res;
493

2✔
494
  if (ignore_ascii != TRUE &&
1✔
495
      ignore_ascii != FALSE) {
496
    errno = EINVAL;
497
    return -1;
498
  }
499

500
  if (data_opts & PR_DATA_OPT_IGNORE_ASCII) {
501
    if (!ignore_ascii) {
502
      data_opts &= ~PR_DATA_OPT_IGNORE_ASCII;
503
    }
3✔
504

3✔
505
    res = TRUE;
2✔
506

507
  } else {
508
    if (ignore_ascii) {
1✔
509
      data_opts |= PR_DATA_OPT_IGNORE_ASCII;
1✔
510
    }
511

512
    res = FALSE;
513
  }
1✔
514

515
  return res;
516
}
517

3✔
518
void pr_data_init(char *filename, int direction) {
3✔
519
  if (session.xfer.p == NULL) {
520
    data_new_xfer(filename, direction);
15✔
521

15✔
522
  } else {
15✔
523
    if (!(session.sf_flags & SF_PASSIVE)) {
524
      pr_log_debug(DEBUG5,
15✔
525
        "data_init oddity: session.xfer exists in non-PASV mode");
2✔
526
    }
2✔
527

528
    session.xfer.direction = direction;
529
  }
13✔
530

9✔
531
  /* Clear any leftover state from previous transfers. */
532
  pr_ascii_ftp_reset();
533
}
534

4✔
535
int pr_data_open(char *filename, char *reason, int direction, off_t size) {
1✔
536
  int res = 0;
1✔
537
#if defined(HAVE_SIGACTION)
538
  struct sigaction act;
539
#endif /* HAVE_SIGACTION */
540

541
  if (session.c == NULL) {
542
    errno = EINVAL;
543
    return -1;
9✔
544
  }
1✔
545

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

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

8✔
566
  /* Make sure that any abort flags have been cleared. */
3✔
567
  session.sf_flags &= ~(SF_ABORT|SF_POST_ABORT);
568

569
  if (session.xfer.p == NULL) {
570
    data_new_xfer(filename, direction);
8✔
571

572
  } else {
573
    session.xfer.direction = direction;
11✔
574
  }
575

576
  if (reason == NULL) {
577
    reason = filename;
×
578
  }
×
579

580
  /* Passive data transfers... */
×
581
  if ((session.sf_flags & SF_PASSIVE) ||
×
582
      (session.sf_flags & SF_EPSV_ALL)) {
×
583
    res = data_passive_open(reason, size);
×
584

585
  /* Active data transfers... */
×
586
  } else {
×
587
    res = data_active_open(reason, size);
588
  }
589

×
590
  if (res < 0) {
×
591
    return res;
592
  }
×
593

×
594
  if (pr_netio_postopen(session.d->instrm) < 0) {
×
595
    int xerrno;
×
596

597
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
598
      strerror(session.d->xerrno));
×
599
    xerrno = session.d->xerrno;
600
    pr_data_close2();
601

×
602
    errno = xerrno;
×
603
    return -1;
604
  }
×
605

×
606
  if (pr_netio_postopen(session.d->outstrm) < 0) {
607
    int xerrno;
608

×
609
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
610
      strerror(session.d->xerrno));
611
    xerrno = session.d->xerrno;
×
612
    pr_data_close2();
613

×
614
    errno = xerrno;
×
615
    return -1;
616
  }
617

618
  memset(&session.xfer.start_time, '\0', sizeof(session.xfer.start_time));
619
  gettimeofday(&session.xfer.start_time, NULL);
620

×
621
  if (session.xfer.direction == PR_NETIO_IO_RD) {
622
    nstrm = session.d->instrm;
623

624
  } else {
625
    nstrm = session.d->outstrm;
626
  }
627

628
  session.sf_flags |= SF_XFER;
629

×
630
  if (timeout_noxfer) {
×
631
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
×
632
  }
633

×
634
  /* Allow aborts -- set the current NetIO stream to allow interrupted
635
   * syscalls, so our SIGURG handler can interrupt it
636
   */
×
637
  pr_netio_set_poll_interval(nstrm, 1);
×
638

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

×
646
#if defined(HAVE_SIGACTION)
×
647
  act.sa_handler = data_urgent;
648
  sigemptyset(&act.sa_mask);
×
649
  act.sa_flags = 0;
650

651
# if defined(SA_INTERRUPT)
652
  act.sa_flags |= SA_INTERRUPT;
653
# endif /* SA_INTERRUPT */
×
654
# if defined(SA_RESTART)
×
655
  act.sa_flags &= SA_RESTART;
×
656
# endif /* SA_RESTART */
657

×
658
  if (sigaction(SIGURG, &act, NULL) < 0) {
659
    pr_log_pri(PR_LOG_WARNING,
660
      "warning: unable to set SIGURG signal handler: %s", strerror(errno));
12✔
661
  }
12✔
662

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

671
  /* Reset all of the timing-related variables for data transfers. */
12✔
672
  pr_gettimeofday_millis(&data_start_ms);
12✔
673
  data_first_byte_read = FALSE;
674
  data_first_byte_written = FALSE;
675

12✔
676
  return res;
12✔
677
}
678

679
void pr_data_close2(void) {
12✔
680
  nstrm = NULL;
12✔
681

12✔
682
  if (session.d != NULL) {
12✔
683
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
684
    session.d = NULL;
685
  }
3✔
686

3✔
687
  /* Aborts no longer necessary */
688
  signal(SIGURG, SIG_IGN);
3✔
689

1✔
690
  if (timeout_noxfer) {
691
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
3✔
692
  }
693

694
  if (timeout_stalled) {
695
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
696
  }
697

698
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
699
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
700
  pr_session_set_idle();
701
}
702

2✔
703
/* close == successful transfer */
704
void pr_data_close(int quiet) {
2✔
705
  pr_data_close2();
1✔
706

1✔
707
  if (quiet == FALSE) {
708
    pr_response_add(R_226, _("Transfer complete"));
709
  }
2✔
710
}
711

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

728
  pr_data_clear_xfer_pool();
729

730
  /* Clear/restore the default data transfer type. Otherwise, things like
731
   * APPEs or STOUs will be preserved for the next upload erroneously
11✔
732
   * (see Bug#3612).
9✔
733
   */
734
  session.xfer.xfer_type = STOR_DEFAULT;
735
}
736

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

745
  pr_trace_msg(trace_channel, 9,
11✔
746
    "aborting data transfer (errno = %s (%d), quiet = %s, true abort = %s)",
11✔
747
    strerror(err), err, quiet ? "true" : "false",
748
    true_abort ? "true" : "false");
749

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

757
    } else {
11✔
758
      pr_inet_lingering_close(session.pool, session.d, timeout_linger);
10✔
759
    }
10✔
760

10✔
761
    session.d = NULL;
762
  }
10✔
763

764
  if (timeout_noxfer) {
2✔
765
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
766
  }
767

768
  if (timeout_stalled) {
769
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
770
  }
771

772
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
773
  session.sf_flags &= (SF_ALL^(SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
774
  pr_session_set_idle();
2✔
775

2✔
776
  if (!quiet) {
2✔
777
    char *respcode = R_426;
778
    char *msg = NULL;
779
    char msgbuf[64];
1✔
780

1✔
781
    switch (err) {
1✔
782

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

797
#ifdef ENXIO
798
    case ENXIO:
799
      respcode = R_451;
800
      msg = _("Unexpected streams hangup");
801
      break;
802
#endif
803

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

816
#ifdef ETXTBSY
817
    case ETXTBSY:                /* FALLTHROUGH */
818
#endif
819
#ifdef EBUSY
820
    case EBUSY:
821
#endif
822
#if defined(ETXTBSY) || defined(EBUSY)
823
      respcode = R_451;
824
      break;
825
#endif
826

827
#ifdef ENOSPC
828
    case ENOSPC:
829
      respcode = R_452;
830
      break;
831
#endif
832

833
#ifdef EDQUOT
834
    case EDQUOT:                /* FALLTHROUGH */
835
#endif
836
#ifdef EFBIG
837
    case EFBIG:
838
#endif
839
#if defined(EDQUOT) || defined(EFBIG)
840
      respcode = R_552;
841
      break;
842
#endif
843

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

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

2✔
913
    default:
914
      respcode = R_426;
915
      msg = _("Data connection closed");
916
      break;
917
    }
918

10✔
919
    if (msg == NULL &&
920
        (msg = strerror(err)) == NULL) {
921

11✔
922
      if (pr_snprintf(msgbuf, sizeof(msgbuf),
8✔
923
          _("Unknown or out of range errno [%d]"), err) > 0) {
924
        msg = msgbuf;
11✔
925
      }
926
    }
927

928
    pr_log_pri(PR_LOG_NOTICE, "notice: user %s: aborting transfer: %s",
929
      session.user ? session.user : "(unknown)", msg);
14✔
930

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

939
    /* Forcibly clear the data-transfer instigating command pool from the
14✔
940
     * Response API.
14✔
941
     */
942
    pr_response_set_pool(session.pool);
252✔
943
  }
14✔
944

945
  if (true_abort) {
14✔
946
    session.sf_flags |= SF_POST_ABORT;
14✔
947
  }
×
948
}
949

×
950
/* From response.c.  XXX Need to provide these symbols another way. */
×
951
extern pr_response_t *resp_list, *resp_err_list;
×
952

×
953
static int peek_is_abor_cmd(void) {
954
  int fd, res;
955
  fd_set rfds;
×
956
  struct timeval tv;
957
  ssize_t len;
×
958
  char buf[5];
959

960
  tv.tv_sec = 1;
14✔
961
  tv.tv_usec = 0;
962

13✔
963
  fd = PR_NETIO_FD(session.c->instrm);
13✔
964
  pr_trace_msg(trace_channel, 20, "peeking at next data for fd %d", fd);
965

966
  FD_ZERO(&rfds);
967
  FD_SET(fd, &rfds);
968

969
  res = select(fd + 1, &rfds, NULL, NULL, &tv);
970
  while (res < 0) {
971
    int xerrno = errno;
972

973
    if (xerrno == EINTR) {
1✔
974
      pr_signals_handle();
1✔
975
      res = select(fd + 1, &rfds, NULL, NULL, &tv);
1✔
976
      continue;
1✔
977
    }
978

1✔
979
    pr_trace_msg(trace_channel, 20,
×
980
      "error waiting for next data on fd %d: %s", fd, strerror(xerrno));
×
981
    return FALSE;
×
982
  }
983

984
  if (res == 0) {
1✔
985
    /* Timed out. */
986
    pr_trace_msg(trace_channel, 20, "timed out peeking for data on fd %d", fd);
1✔
987
    return FALSE;
988
  }
989

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

26✔
1002
    if (xerrno == EINTR) {
26✔
1003
      pr_signals_handle();
1004
      len = recv(fd, &buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
26✔
1005
      continue;
1006
    }
1007

1008
    pr_trace_msg(trace_channel, 20,
14✔
1009
      "error peeking at next data: %s", strerror(xerrno));
14✔
1010
    return FALSE;
14✔
1011
  }
14✔
1012

1013
  pr_trace_msg(trace_channel, 20, "peeking at %ld bytes of next data",
14✔
1014
    (long) len);
14✔
1015
  if (strncasecmp(buf, "ABOR\r", len) == 0) {
1016
    pr_trace_msg(trace_channel, 20, "peeked data probably 'ABOR' command");
1017
    return TRUE;
1018
  }
1019

1020
  pr_trace_msg(trace_channel, 20, "peeked data '%.*s' not ABOR command",
1021
    (int) len, buf);
1022
  return FALSE;
1023
}
1024

1025
static void poll_ctrl(void) {
1026
  int res;
1027

1028
  if (session.c == NULL) {
1029
    return;
1030
  }
1031

1032
  pr_trace_msg(trace_channel, 4, "polling for commands on control channel");
1033
  pr_netio_set_poll_interval(session.c->instrm, 0);
1034
  res = pr_netio_poll(session.c->instrm);
1035
  pr_netio_reset_poll_interval(session.c->instrm);
1036

14✔
1037
  if (res == 0 &&
×
1038
      !(session.sf_flags & SF_ABORT)) {
1039

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

1064
      session.sf_flags |= SF_ABORT;
1065

1066
      if (nstrm != NULL) {
1067
        pr_netio_abort(nstrm);
1068
        errno = 0;
×
1069
      }
1070
    }
1071
  }
×
1072

1073
  if (res == 0 &&
1074
      !(session.sf_flags & SF_ABORT)) {
1075
    cmd_rec *cmd = NULL;
×
1076

1077
    pr_trace_msg(trace_channel, 1,
1078
      "data available for reading on control channel during data transfer, "
1079
      "reading control data");
1080
    res = pr_cmd_read(&cmd);
14✔
1081
    if (res < 0) {
7✔
1082
      int xerrno;
1083

35✔
1084
#if defined(ECONNABORTED)
28✔
1085
      xerrno = ECONNABORTED;
1086
#elif defined(ENOTCONN)
1087
      xerrno = ENOTCONN;
7✔
1088
#else
1089
      xerrno = EIO;
1090
#endif
1091

1092
      pr_trace_msg(trace_channel, 1,
1093
        "unable to read control command during data transfer: %s",
1094
        strerror(xerrno));
1095
      errno = xerrno;
1096

1097
#ifndef PR_DEVEL_NO_DAEMON
1098
      /* Otherwise, EOF */
1099
      pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CLIENT_EOF, NULL);
14✔
1100
#else
14✔
1101
      return;
14✔
1102
#endif /* PR_DEVEL_NO_DAEMON */
14✔
1103

14✔
1104
    } else if (cmd != NULL) {
14✔
1105
      char *ch;
14✔
1106

14✔
1107
      for (ch = cmd->argv[0]; *ch; ch++) {
14✔
1108
        if (PR_ISALPHA((int) *ch)) {
14✔
1109
          *ch = toupper((int) *ch);
14✔
1110
        }
12✔
1111
      }
7✔
1112

2✔
1113
      cmd->cmd_id = pr_cmd_get_id(cmd->argv[0]);
1114

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

1140
        pr_trace_msg(trace_channel, 5,
2✔
1141
          "client sent '%s' command during data transfer, denying",
1142
          (char *) cmd->argv[0]);
2✔
1143

1144
        resp_list = resp_err_list = NULL;
2✔
1145
        resp_pool = pr_response_get_pool();
2✔
1146

1147
        pr_response_set_pool(cmd->pool);
2✔
1148

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

1152
        pr_response_flush(&resp_err_list);
2✔
1153

1154
        pr_response_set_pool(resp_pool);
2✔
1155
        destroy_pool(cmd->pool);
2✔
1156

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

1166
        pr_trace_msg(trace_channel, 5,
3✔
1167
          "client sent '%s' command during data transfer, ignoring",
1168
          (char *) cmd->argv[0]);
3✔
1169

3✔
1170
        resp_list = resp_err_list = NULL;
×
1171
        resp_pool = pr_response_get_pool();
×
1172

1173
        pr_response_set_pool(cmd->pool);
1174

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

3✔
1178
        pr_response_flush(&resp_list);
3✔
1179

1180
        pr_response_set_pool(resp_pool);
3✔
1181
        destroy_pool(cmd->pool);
3✔
1182

1183
      } else {
3✔
1184
        char *title_buf = NULL;
3✔
1185
        int curr_cmd_id = 0, title_len = -1;
1186
        const char *curr_cmd = NULL, *sce_cmd = NULL, *sce_cmd_arg = NULL;
3✔
1187
        cmd_rec *curr_cmd_rec = NULL;
1188
        pool *resp_pool;
3✔
1189

1190
        pr_trace_msg(trace_channel, 5,
1191
          "client sent '%s' command during data transfer, dispatching",
3✔
1192
          (char *) cmd->argv[0]);
×
1193

1194
        title_len = pr_proctitle_get(NULL, 0);
1195
        if (title_len > 0) {
3✔
1196
          title_buf = pcalloc(cmd->pool, title_len + 1);
3✔
1197
          pr_proctitle_get(title_buf, title_len + 1);
3✔
1198
        }
1199

3✔
1200
        curr_cmd = session.curr_cmd;
3✔
1201
        curr_cmd_id = session.curr_cmd_id;
3✔
1202
        curr_cmd_rec = session.curr_cmd_rec;
1203
        sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD);
1204
        sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG);
1205

7✔
1206
        resp_list = resp_err_list = NULL;
1207
        resp_pool = pr_response_get_pool();
7✔
1208

1209
        pr_response_set_pool(cmd->pool);
1210
        pr_cmd_dispatch(cmd);
1211

1212
        pr_scoreboard_entry_update(session.pid,
1213
          PR_SCORE_CMD, "%s", sce_cmd, NULL, NULL);
1214
        pr_scoreboard_entry_update(session.pid,
1215
          PR_SCORE_CMD_ARG, "%s", sce_cmd_arg, NULL, NULL);
1216

1217
        if (title_len > 0) {
1218
          pr_proctitle_set_str(title_buf);
1219
        }
34✔
1220

34✔
1221
        pr_response_flush(&resp_list);
34✔
1222
        pr_response_set_pool(resp_pool);
34✔
1223
        destroy_pool(cmd->pool);
34✔
1224

1225
        session.curr_cmd = curr_cmd;
34✔
1226
        session.curr_cmd_id = curr_cmd_id;
34✔
1227
        session.curr_cmd_rec = curr_cmd_rec;
8✔
1228
      }
8✔
1229

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

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

4✔
1251
  if (cl_buf == NULL ||
1252
      cl_size == 0) {
1253
    errno = EINVAL;
4✔
1254
    return -1;
1255
  }
1256

1257
  /* Poll the control channel for any commands we should handle, like
4✔
1258
   * QUIT or ABOR.
4✔
1259
   */
1260
  poll_ctrl();
1261

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

1268
#if defined(ECONNABORTED)
1269
    xerrno = ECONNABORTED;
1270
#elif defined(ENOTCONN)
12✔
1271
    xerrno = ENOTCONN;
7✔
1272
#else
7✔
1273
    xerrno = EIO;
1274
#endif
7✔
1275

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

7✔
1283
    errno = xerrno;
1✔
1284
    return -1;
1285
  }
1✔
1286

1287
  if (session.xfer.direction == PR_NETIO_IO_RD) {
1288
    char *buf;
1289

1290
    buf = session.xfer.buf;
×
1291

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

1✔
1300
      do {
1✔
1301
        buflen = session.xfer.buflen;        /* how much remains in buf */
1302
        adjlen = 0;
1303

6✔
1304
        pr_signals_handle();
6✔
1305

2✔
1306
        len = pr_netio_read(session.d->instrm, buf + buflen,
2✔
1307
          session.xfer.bufsize - buflen, 1);
2✔
1308
        while (len < 0) {
1309
          int xerrno = errno;
2✔
1310

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

1319
            len = pr_netio_read(session.d->instrm, buf + buflen,
6✔
1320
              session.xfer.bufsize - buflen, 1);
6✔
1321
            continue;
1322
          }
1323

6✔
1324
          destroy_pool(tmp_pool);
1325
          errno = xerrno;
6✔
1326
          return -1;
6✔
1327
        }
1328

1329
        if (len > 0 &&
1330
            data_first_byte_read == FALSE) {
1331
          if (pr_trace_get_level(timing_channel)) {
6✔
1332
            unsigned long elapsed_ms;
6✔
1333
            uint64_t read_ms;
1334

1335
            pr_gettimeofday_millis(&read_ms);
1336
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
1337

1338
            pr_trace_msg(timing_channel, 7,
1339
              "Time for first data byte read: %lu ms", elapsed_ms);
1340
          }
1341

1342
          data_first_byte_read = TRUE;
1343
        }
1344

1345
        if (len > 0) {
1346
          pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
6✔
1347
            len != 1 ? "bytes" : "byte");
6✔
1348

6✔
1349
          buflen += len;
1350

6✔
1351
          if (timeout_stalled) {
6✔
1352
            pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
6✔
1353
          }
1354
        }
1355

6✔
1356
        /* If buflen > 0, data remains in the buffer to be copied. */
6✔
1357
        if (len >= 0 &&
×
1358
            buflen > 0) {
×
1359

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

6✔
1376
            if (tmp_pool == NULL) {
1377
              tmp_pool = make_sub_pool(session.xfer.p);
1378
              pr_pool_tag(tmp_pool, "ASCII upload");
1379
            }
1380

1381
            res = pr_ascii_ftp_from_crlf(tmp_pool, buf, buflen, &buf, &outlen);
1382
            if (res < 0) {
1383
              pr_trace_msg(trace_channel, 3, "error reading ASCII data: %s",
1384
                strerror(errno));
6✔
1385

1✔
1386
            } else {
1387
              adjlen += res;
1388
              buflen = (int) outlen;
1389
            }
6✔
1390
          }
6✔
1391

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

1401
          memcpy(cl_buf, buf, buflen);
1402

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

1410
          if (adjlen > 0) {
1411
            memcpy(buf, buf + buflen, adjlen);
1412
          }
1413

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

1426
      /* Return how much data we actually copied into the client buffer. */
1427
      len = buflen;
4✔
1428

2✔
1429
    } else {
2✔
1430
      len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
2✔
1431
      while (len < 0) {
1432
        int xerrno = errno;
2✔
1433

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

1442
          len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
1443
          continue;
4✔
1444
        }
4✔
1445

1446
        break;
1447
      }
1448

1449
      if (len > 0) {
1450
        pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
1451
          len != 1 ? "bytes" : "byte");
1452

1453
        if (data_first_byte_read == FALSE) {
18✔
1454
          if (pr_trace_get_level(timing_channel)) {
10✔
1455
            unsigned long elapsed_ms;
10✔
1456
            uint64_t read_ms;
10✔
1457

10✔
1458
            pr_gettimeofday_millis(&read_ms);
1459
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
10✔
1460

1461
            pr_trace_msg(timing_channel, 7,
10✔
1462
              "Time for first data byte read: %lu ms", elapsed_ms);
×
1463
          }
1464

1465
          data_first_byte_read = TRUE;
10✔
1466
        }
10✔
1467

1468
        /* Non-ASCII mode doesn't need to use session.xfer.buf */
1469
        if (timeout_stalled) {
1470
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1471
        }
1472

1473
        total += len;
10✔
1474
      }
4✔
1475
    }
1✔
1476

7✔
1477
  } else { /* PR_NETIO_IO_WR */
7✔
1478

1479
    while (cl_size) {
7✔
1480
      int bwrote = 0;
7✔
1481
      int buflen = cl_size;
7✔
1482
      unsigned int xferbuflen;
1483
      char *xferbuf = NULL, *ascii_buf = NULL;
1484

1485
      pr_signals_handle();
7✔
1486

1487
      if (buflen > pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR)) {
1488
        buflen = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);
1489
      }
1490

1491
      xferbuf = cl_buf;
1492
      xferbuflen = buflen;
7✔
1493

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

7✔
1505
        if (tmp_pool == NULL) {
1506
          tmp_pool = make_sub_pool(session.xfer.p);
1507
          pr_pool_tag(tmp_pool, "ASCII download");
10✔
1508
        }
12✔
1509

4✔
1510
        /* Fill up our internal buffer. */
1511
        memcpy(session.xfer.buf, cl_buf, buflen);
6✔
1512

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

1524
        } else {
2✔
1525
          ascii_buf = session.xfer.buf;
2✔
1526
          session.xfer.buf = out;
1527
          session.xfer.buflen = xferbuflen = outlen;
1✔
1528
        }
1✔
1529

1530
        xferbuf = session.xfer.buf;
1531
      }
2✔
1532

2✔
1533
      bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
1534
      while (bwrote < 0) {
1535
        int xerrno = errno;
8✔
1536

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

3✔
1546
          bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
1547
          continue;
3✔
1548
        }
1549

1550
        destroy_pool(tmp_pool);
1551
        if (ascii_buf != NULL) {
3✔
1552
          /* Free up the malloc'd memory. */
1553
          free(session.xfer.buf);
1554
          session.xfer.buf = ascii_buf;
8✔
1555
        }
8✔
1556

1557
        errno = xerrno;
1558
        return -1;
8✔
1559
      }
8✔
1560

8✔
1561
      if (bwrote > 0) {
1562
        pr_trace_msg(trace_channel, 19, "wrote %d %s to network", bwrote,
1563
          bwrote != 1 ? "bytes" : "byte");
8✔
1564

1565
        if (data_first_byte_written == FALSE) {
1566
          if (pr_trace_get_level(timing_channel)) {
1567
            unsigned long elapsed_ms;
6✔
1568
            uint64_t write_ms;
6✔
1569

1570
            pr_gettimeofday_millis(&write_ms);
1571
            elapsed_ms = (unsigned long) (write_ms - data_start_ms);
1572

1573
            pr_trace_msg(timing_channel, 7,
1574
              "Time for first data byte written: %lu ms", elapsed_ms);
1575
          }
19✔
1576

1577
          data_first_byte_written = TRUE;
18✔
1578
        }
1579

1580
        if (timeout_stalled) {
19✔
1581
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
19✔
1582
        }
19✔
1583

11✔
1584
        cl_size -= buflen;
1585
        cl_buf += buflen;
1586
        total += buflen;
8✔
1587
      }
1588

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

1598
    len = total;
7✔
1599
  }
7✔
1600

7✔
1601
  if (total &&
1602
      timeout_idle) {
1603
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1604
  }
1605

1606
  session.xfer.total_bytes += total;
7✔
1607
  session.total_bytes += total;
7✔
1608
  if (session.xfer.direction == PR_NETIO_IO_RD) {
3✔
1609
    session.total_bytes_in += total;
3✔
1610

1611
  } else {
1612
    session.total_bytes_out += total;
4✔
1613
  }
1✔
1614

1✔
1615
  destroy_pool(tmp_pool);
1616
  return (len < 0 ? -1 : len);
1617
}
3✔
1618

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

1632
  if (offset == NULL ||
1633
      count == 0) {
1634
    errno = EINVAL;
2✔
1635
    return -1;
1636
  }
2✔
1637

1638
  if (session.xfer.direction == PR_NETIO_IO_RD) {
1639
    errno = EPERM;
1640
    return -1;
1641
  }
1642

1643
  if (session.d == NULL) {
1644
    errno = EPERM;
1645
    return -1;
1646
  }
1647

1648
  flags = fcntl(PR_NETIO_FD(session.d->outstrm), F_GETFL);
1649
  if (flags < 0) {
1650
    return -1;
1651
  }
1652

1653
  /* Set fd to blocking-mode for sendfile() */
1654
  if (flags & O_NONBLOCK) {
2✔
1655
    if (fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags^O_NONBLOCK) < 0) {
1656
      return -1;
1657
    }
1658
  }
1659

1660
  for (;;) {
1661
# if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_SOLARIS_SENDFILE)
1662
    off_t orig_offset = *offset;
1663

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

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

×
1699
    errno = 0;
×
1700
    len = sendfile(PR_NETIO_FD(session.d->outstrm), retr_fd, offset, count);
×
1701

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

×
1711
      /* Handle our interrupting signal, and continue. */
1712
      pr_signals_handle();
1713
    }
×
1714

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

×
1723
        session.xfer.total_bytes += len;
1724
        session.total_bytes += len;
×
1725
        session.total_bytes_out += len;
×
1726
        session.total_raw_out += len;
1727

1728
        return -1;
2✔
1729
      }
1730

1731
      count -= len;
1732

1✔
1733
      /* Only reset the timers if data have actually been written out. */
1✔
1734
      if (len > 0) {
1735
        if (timeout_stalled) {
1736
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1737
        }
1738

1739
        if (timeout_idle) {
1740
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1741
        }
1742
      }
1743

1744
      session.xfer.total_bytes += len;
1745
      session.total_bytes += len;
1746
      session.total_bytes_out += len;
1747
      session.total_raw_out += len;
1748
      total += len;
1749

1750
      pr_signals_handle();
1751
      continue;
1752
    }
1753

1754
    if (len == -1) {
1755
      /* Linux updates offset on error, not len like BSD, fix up so
1756
       * BSD-based code works.
1757
       */
1758
      len = *offset - orig_offset;
1759
      *offset = orig_offset;
1760

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

1778
#  if SIZEOF_SIZE_T == SIZEOF_INT
1779
    if (count > UINT_MAX) {
1780
      count = UINT_MAX;
1781
    }
1782
#  elif SIZEOF_SIZE_T == SIZEOF_LONG
1783
    if (count > ULONG_MAX) {
1784
      count = ULONG_MAX;
1785
    }
1786
#  elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
1787
    if (count > ULLONG_MAX) {
1788
      count = ULLONG_MAX;
1789
    }
1790
#  endif
1791

1792
    if (sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, count,
1793
        NULL, &len, 0) == -1) {
1794

1795
# elif defined(HAVE_MACOSX_SENDFILE)
1796
    off_t orig_len = count;
1797
    int res;
1798

1799
    /* Since Mac OSX uses the fourth argument as a value-return parameter,
1800
     * success or failure, we need to put the result into len after the
1801
     * call.
1802
     */
1803

1804
    res = sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, &orig_len,
1805
      NULL, 0);
1806
    len = orig_len;
1807

1808
    if (res < 0) {
1809
# elif defined(HAVE_AIX_SENDFILE)
1810

1811
    memset(&parms, 0, sizeof(parms));
1812

1813
    parms.file_descriptor = retr_fd;
1814
    parms.file_offset = (uint64_t) *offset;
1✔
1815
    parms.file_bytes = (int64_t) count;
×
1816

×
1817
    rc = send_file(&(PR_NETIO_FD(session.d->outstrm)), &(parms), (uint_t)0);
×
1818
    len = (int) parms.bytes_sent;
×
1819

×
1820
    if (rc < -1 || rc == 1) {
1821
# else
×
1822
    if (FALSE) {
1823
# endif /* HAVE_AIX_SENDFILE */
1824

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

×
1847
          return -1;
1848
        }
×
1849

1850
        pr_signals_handle();
1851

1✔
1852
        /* If we got everything in this transaction, we're done. */
1✔
1853
        if (len >= count) {
1✔
1854
          break;
1855
        }
1✔
1856

1857
        count -= len;
1858
        *offset += len;
1859

1860
        if (timeout_stalled) {
1861
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1✔
1862
        }
×
1863

1864
        if (timeout_idle) {
1865
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1✔
1866
        }
1✔
1867

1868
        session.xfer.total_bytes += len;
1869
        session.total_bytes += len;
1✔
1870
        session.total_bytes_out += len;
1✔
1871
        session.total_raw_out += len;
1872
        total += len;
1873

1✔
1874
        continue;
1✔
1875
      }
1✔
1876

1✔
1877
      error = errno;
1✔
1878
      (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
1879
      errno = error;
1✔
1880

1881
      return -1;
1882
    }
1883

1884
    break;
1885
  }
1886

1887
  if (flags & O_NONBLOCK) {
1888
    (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
1889
  }
1890

1891
  if (timeout_stalled) {
1892
    pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
1893
  }
1894

1895
  if (timeout_idle) {
1896
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
1897
  }
1898

1899
  session.xfer.total_bytes += len;
1900
  session.total_bytes += len;
1901
  session.total_bytes_out += len;
1902
  session.total_raw_out += len;
1903
  total += len;
1904

1905
  return total;
1906
}
1907
#else
1908
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
1909
  errno = ENOSYS;
1910
  return -1;
1911
}
1912
#endif /* HAVE_SENDFILE */
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