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

proftpd / proftpd / 14503647505

16 Apr 2025 10:16PM UTC coverage: 92.665% (-0.4%) from 93.03%
14503647505

push

github

web-flow
The core API for doing RFC 1413-style lookup was moved into the `mod_ident` module, and removing from the core build, years ago. (#1925)

47162 of 50895 relevant lines covered (92.67%)

222.91 hits per line

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

72.88
/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-2023 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;
112
  int rev, xerrno = 0;
3✔
113

114
  if (reason == NULL &&
6✔
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,
4✔
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,
2✔
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 *c;
215
  int bind_port, rev, *root_revoke = NULL, 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 &&
14✔
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_conn(session.pool, -1, bind_addr, bind_port, TRUE);
6✔
278
  if (session.d == NULL) {
6✔
279
    xerrno = errno;
×
280

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

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

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

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

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

309
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
6✔
310

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

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

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

324
  /* Make sure that the necessary socket options are set on the socket prior
325
   * to the call to connect(2).
326
   */
327
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
6✔
328
    IPTOS_THROUGHPUT, 1);
329
  pr_inet_generate_socket_event("core.data-connect", main_server,
6✔
330
    session.d->local_addr, session.d->listen_fd);
6✔
331

332
  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
6✔
333
      session.data_port) < 0) {
6✔
334
    xerrno = session.d->xerrno;
6✔
335

336
    pr_log_debug(DEBUG6,
12✔
337
      "Error connecting to %s#%u for active data transfer: %s",
338
      pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
6✔
339
      strerror(xerrno));
340
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
6✔
341
      strerror(xerrno));
342
    pr_data_close2();
6✔
343

344
    errno = xerrno;
6✔
345
    return -1;
6✔
346
  }
347

348
  c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
×
349
    session.d->listen_fd, -1, -1, TRUE);
×
350

351
  pr_netaddr_set_reverse_dns(rev);
×
352

353
  if (c) {
×
354
    pr_log_debug(DEBUG4, "active data connection opened - local  : %s:%d",
×
355
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
×
356
    pr_log_debug(DEBUG4, "active data connection opened - remote : %s:%d",
×
357
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);
×
358

359
    if (session.xfer.xfer_type != STOR_UNIQUE) {
×
360
      if (size) {
×
361
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
×
362
          "(%" PR_LU " %s)"), MODE_STRING, reason, (pr_off_t) size,
×
363
          size != 1 ? "bytes" : "byte");
364

365
      } else {
366
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
×
367
          MODE_STRING, reason);
×
368
      }
369

370
    } else {
371

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

394
    pr_inet_close(session.pool, session.d);
×
395
    (void) pr_inet_set_nonblock(session.pool, session.d);
×
396
    session.d = c;
×
397
    return 0;
×
398
  }
399

400
  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
401
    strerror(session.d->xerrno));
×
402
  xerrno = session.d->xerrno;
×
403
  pr_data_close2();
×
404

405
  errno = xerrno;
×
406
  return -1;
×
407
}
408

409
void pr_data_set_linger(long linger) {
1✔
410
  timeout_linger = linger;
1✔
411
}
1✔
412

413
int pr_data_get_timeout(int id) {
7✔
414
  switch (id) {
7✔
415
    case PR_DATA_TIMEOUT_IDLE:
2✔
416
      return timeout_idle;
2✔
417

418
    case PR_DATA_TIMEOUT_NO_TRANSFER:
2✔
419
      return timeout_noxfer;
2✔
420

421
    case PR_DATA_TIMEOUT_STALLED:
2✔
422
      return timeout_stalled;
2✔
423
  }
424

425
  errno = EINVAL;
1✔
426
  return -1;
1✔
427
}
428

429
void pr_data_set_timeout(int id, int timeout) {
3✔
430
  switch (id) {
3✔
431
    case PR_DATA_TIMEOUT_IDLE:
1✔
432
      timeout_idle = timeout;
1✔
433
      break;
1✔
434

435
    case PR_DATA_TIMEOUT_NO_TRANSFER:
1✔
436
      timeout_noxfer = timeout;
1✔
437
      break;
1✔
438

439
    case PR_DATA_TIMEOUT_STALLED:
1✔
440
      timeout_stalled = timeout;
1✔
441
      break;
1✔
442
  }
443
}
3✔
444

445
void pr_data_clear_xfer_pool(void) {
19✔
446
  int xfer_type;
447

448
  if (session.xfer.p != NULL) {
19✔
449
    destroy_pool(session.xfer.p);
2✔
450
  }
451

452
  /* Note that session.xfer.xfer_type may have been set already, e.g.
453
   * for STOR_UNIQUE uploads.  To support this, we need to preserve that
454
   * value.
455
   */
456
  xfer_type = session.xfer.xfer_type;
19✔
457

458
  memset(&session.xfer, 0, sizeof(session.xfer));
19✔
459
  session.xfer.xfer_type = xfer_type;
19✔
460
}
19✔
461

462
void pr_data_reset(void) {
9✔
463
  /* Clear any leftover state from previous transfers. */
464
  pr_ascii_ftp_reset();
9✔
465

466
  if (session.d != NULL &&
10✔
467
      session.d->pool != NULL) {
1✔
468
    destroy_pool(session.d->pool);
1✔
469
  }
470

471
  session.d = NULL;
9✔
472
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_POST_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE|SF_EPSV_ALL));
9✔
473
}
9✔
474

475
int pr_data_ignore_ascii(int ignore_ascii) {
5✔
476
  int res;
477

478
  if (ignore_ascii != TRUE &&
5✔
479
      ignore_ascii != FALSE) {
480
    errno = EINVAL;
1✔
481
    return -1;
1✔
482
  }
483

484
  if (data_opts & PR_DATA_OPT_IGNORE_ASCII) {
4✔
485
    if (!ignore_ascii) {
2✔
486
      data_opts &= ~PR_DATA_OPT_IGNORE_ASCII;
1✔
487
    }
488

489
    res = TRUE;
490

491
  } else {
492
    if (ignore_ascii) {
2✔
493
      data_opts |= PR_DATA_OPT_IGNORE_ASCII;
1✔
494
    }
495

496
    res = FALSE;
497
  }
498

499
  return res;
500
}
501

502
void pr_data_init(char *filename, int direction) {
3✔
503
  if (session.xfer.p == NULL) {
3✔
504
    data_new_xfer(filename, direction);
2✔
505

506
  } else {
507
    if (!(session.sf_flags & SF_PASSIVE)) {
1✔
508
      pr_log_debug(DEBUG5,
1✔
509
        "data_init oddity: session.xfer exists in non-PASV mode");
510
    }
511

512
    session.xfer.direction = direction;
1✔
513
  }
514

515
  /* Clear any leftover state from previous transfers. */
516
  pr_ascii_ftp_reset();
3✔
517
}
3✔
518

519
int pr_data_open(char *filename, char *reason, int direction, off_t size) {
15✔
520
  int res = 0;
15✔
521
  struct sigaction act;
522

523
  if (session.c == NULL) {
15✔
524
    errno = EINVAL;
2✔
525
    return -1;
2✔
526
  }
527

528
  if ((session.sf_flags & SF_PASSIVE) ||
22✔
529
      (session.sf_flags & SF_EPSV_ALL)) {
9✔
530
    /* For passive transfers, we expect there to already be an existing
531
     * data connection...
532
     */
533
    if (session.d == NULL) {
4✔
534
      errno = EINVAL;
1✔
535
      return -1;
1✔
536
    }
537

538
  } else {
539
    /* ...but for active transfers, we expect there to NOT be an existing
540
     * data connection.
541
     */
542
    if (session.d != NULL) {
9✔
543
      errno = session.d->xerrno = EINVAL;
1✔
544
      return -1;
1✔
545
    }
546
  }
547

548
  /* Make sure that any abort flags have been cleared. */
549
  session.sf_flags &= ~(SF_ABORT|SF_POST_ABORT);
11✔
550

551
  if (session.xfer.p == NULL) {
11✔
552
    data_new_xfer(filename, direction);
5✔
553

554
  } else {
555
    session.xfer.direction = direction;
6✔
556
  }
557

558
  if (reason == NULL) {
11✔
559
    reason = filename;
11✔
560
  }
561

562
  /* Passive data transfers... */
563
  if ((session.sf_flags & SF_PASSIVE) ||
19✔
564
      (session.sf_flags & SF_EPSV_ALL)) {
8✔
565
    res = data_passive_open(reason, size);
3✔
566

567
  /* Active data transfers... */
568
  } else {
569
    res = data_active_open(reason, size);
8✔
570
  }
571

572
  if (res < 0) {
11✔
573
    return res;
574
  }
575

576
  if (pr_netio_postopen(session.d->instrm) < 0) {
×
577
    int xerrno;
578

579
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
580
      strerror(session.d->xerrno));
×
581
    xerrno = session.d->xerrno;
×
582
    pr_data_close2();
×
583

584
    errno = xerrno;
×
585
    return -1;
×
586
  }
587

588
  if (pr_netio_postopen(session.d->outstrm) < 0) {
×
589
    int xerrno;
590

591
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
×
592
      strerror(session.d->xerrno));
×
593
    xerrno = session.d->xerrno;
×
594
    pr_data_close2();
×
595

596
    errno = xerrno;
×
597
    return -1;
×
598
  }
599

600
  memset(&session.xfer.start_time, '\0', sizeof(session.xfer.start_time));
×
601
  gettimeofday(&session.xfer.start_time, NULL);
×
602

603
  if (session.xfer.direction == PR_NETIO_IO_RD) {
×
604
    nstrm = session.d->instrm;
×
605

606
  } else {
607
    nstrm = session.d->outstrm;
×
608
  }
609

610
  session.sf_flags |= SF_XFER;
×
611

612
  if (timeout_noxfer) {
×
613
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
×
614
  }
615

616
  /* Allow aborts -- set the current NetIO stream to allow interrupted
617
   * syscalls, so our SIGURG handler can interrupt it
618
   */
619
  pr_netio_set_poll_interval(nstrm, 1);
×
620

621
  /* PORTABILITY: sigaction is used here to allow us to indicate
622
   * (w/ POSIX at least) that we want SIGURG to interrupt syscalls.  Put
623
   * in whatever is necessary for your arch here; probably not necessary
624
   * as the only _important_ interrupted syscall is select(), which on
625
   * any sensible system is interrupted.
626
   */
627

628
  act.sa_handler = data_urgent;
×
629
  sigemptyset(&act.sa_mask);
×
630
  act.sa_flags = 0;
631
#ifdef SA_INTERRUPT
632
  act.sa_flags |= SA_INTERRUPT;
×
633
#endif
634

635
  if (sigaction(SIGURG, &act, NULL) < 0) {
×
636
    pr_log_pri(PR_LOG_WARNING,
×
637
      "warning: unable to set SIGURG signal handler: %s", strerror(errno));
×
638
  }
639

640
#ifdef HAVE_SIGINTERRUPT
641
  /* This is the BSD way of ensuring interruption.
642
   * Linux uses it too (??)
643
   */
644
  if (siginterrupt(SIGURG, 1) < 0) {
×
645
    pr_log_pri(PR_LOG_WARNING,
×
646
      "warning: unable to make SIGURG interrupt system calls: %s",
647
      strerror(errno));
×
648
  }
649
#endif
650

651
  /* Reset all of the timing-related variables for data transfers. */
652
  pr_gettimeofday_millis(&data_start_ms);
×
653
  data_first_byte_read = FALSE;
×
654
  data_first_byte_written = FALSE;
×
655

656
  return res;
×
657
}
658

659
void pr_data_close2(void) {
12✔
660
  nstrm = NULL;
12✔
661

662
  if (session.d != NULL) {
12✔
663
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
10✔
664
    session.d = NULL;
10✔
665
  }
666

667
  /* Aborts no longer necessary */
668
  signal(SIGURG, SIG_IGN);
12✔
669

670
  if (timeout_noxfer) {
12✔
671
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
12✔
672
  }
673

674
  if (timeout_stalled) {
12✔
675
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
12✔
676
  }
677

678
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
12✔
679
  session.sf_flags &= (SF_ALL^(SF_ABORT|SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
12✔
680
  pr_session_set_idle();
12✔
681
}
12✔
682

683
/* close == successful transfer */
684
void pr_data_close(int quiet) {
3✔
685
  pr_data_close2();
3✔
686

687
  if (quiet == FALSE) {
3✔
688
    pr_response_add(R_226, _("Transfer complete"));
1✔
689
  }
690
}
3✔
691

692
/* Note: true_abort may be false in real abort situations, because
693
 * some ftp clients close the data connection at the same time as they
694
 * send the OOB byte (which results in a broken pipe on our
695
 * end).  Thus, it's a race between the OOB data and the tcp close
696
 * finishing.  Either way, it's ok (client will see either "Broken pipe"
697
 * error or "Aborted").  xfer_abor() in mod_xfer cleans up the session
698
 * flags in any case.  session flags will end up have SF_POST_ABORT
699
 * set if the OOB byte won the race.
700
 */
701
void pr_data_cleanup(void) {
2✔
702
  /* sanity check */
703
  if (session.d != NULL) {
2✔
704
    pr_inet_lingering_close(session.pool, session.d, timeout_linger);
1✔
705
    session.d = NULL;
1✔
706
  }
707

708
  pr_data_clear_xfer_pool();
2✔
709

710
  /* Clear/restore the default data transfer type. Otherwise, things like
711
   * APPEs or STOUs will be preserved for the next upload erroneously
712
   * (see Bug#3612).
713
   */
714
  session.xfer.xfer_type = STOR_DEFAULT;
2✔
715
}
2✔
716

717
/* In order to avoid clearing the transfer counters in session.xfer, we don't
718
 * clear session.xfer here, it should be handled by the appropriate
719
 * LOG_CMD/LOG_CMD_ERR handler calling pr_data_cleanup().
720
 */
721
void pr_data_abort(int err, int quiet) {
11✔
722
  int true_abort = XFER_ABORTED;
11✔
723
  nstrm = NULL;
11✔
724

725
  pr_trace_msg(trace_channel, 9,
11✔
726
    "aborting data transfer (errno = %s (%d), quiet = %s, true abort = %s)",
727
    strerror(err), err, quiet ? "true" : "false",
728
    true_abort ? "true" : "false");
729

730
  if (session.d != NULL) {
11✔
731
    if (true_abort) {
9✔
732
      /* For "true" aborts, we also asynchronously send a 426 response
733
       * message via the "lingering abort" functions.
734
       */
735
      pr_inet_lingering_abort(session.pool, session.d, timeout_linger);
8✔
736

737
    } else {
738
      pr_inet_lingering_close(session.pool, session.d, timeout_linger);
1✔
739
    }
740

741
    session.d = NULL;
9✔
742
  }
743

744
  if (timeout_noxfer) {
11✔
745
    pr_timer_reset(PR_TIMER_NOXFER, ANY_MODULE);
11✔
746
  }
747

748
  if (timeout_stalled) {
11✔
749
    pr_timer_remove(PR_TIMER_STALLED, ANY_MODULE);
11✔
750
  }
751

752
  session.sf_flags &= (SF_ALL^SF_PASSIVE);
11✔
753
  session.sf_flags &= (SF_ALL^(SF_XFER|SF_PASSIVE|SF_ASCII_OVERRIDE));
11✔
754
  pr_session_set_idle();
11✔
755

756
  if (!quiet) {
11✔
757
    char *respcode = R_426;
10✔
758
    char *msg = NULL;
10✔
759
    char msgbuf[64];
760

761
    switch (err) {
10✔
762

763
    case 0:
2✔
764
#ifdef ECONNABORTED
765
    case ECONNABORTED:        /* FALLTHROUGH */
766
#endif
767
#ifdef ECONNRESET
768
    case ECONNRESET:        /* FALLTHROUGH */
769
#endif
770
#ifdef EPIPE
771
    case EPIPE:
772
#endif
773
      respcode = R_426;
2✔
774
      msg = _("Data connection closed");
2✔
775
      break;
2✔
776

777
#ifdef ENXIO
778
    case ENXIO:
1✔
779
      respcode = R_451;
1✔
780
      msg = _("Unexpected streams hangup");
1✔
781
      break;
1✔
782
#endif
783

784
#ifdef EAGAIN
785
    case EAGAIN:                /* FALLTHROUGH */
1✔
786
#endif
787
#ifdef ENOMEM
788
    case ENOMEM:
789
#endif
790
#if defined(EAGAIN) || defined(ENOMEM)
791
      respcode = R_451;
1✔
792
      msg = _("Insufficient memory or file locked");
1✔
793
      break;
1✔
794
#endif
795

796
#ifdef ETXTBSY
797
    case ETXTBSY:                /* FALLTHROUGH */
798
#endif
799
#ifdef EBUSY
800
    case EBUSY:
801
#endif
802
#if defined(ETXTBSY) || defined(EBUSY)
803
      respcode = R_451;
804
      break;
805
#endif
806

807
#ifdef ENOSPC
808
    case ENOSPC:
809
      respcode = R_452;
810
      break;
811
#endif
812

813
#ifdef EDQUOT
814
    case EDQUOT:                /* FALLTHROUGH */
815
#endif
816
#ifdef EFBIG
817
    case EFBIG:
818
#endif
819
#if defined(EDQUOT) || defined(EFBIG)
820
      respcode = R_552;
821
      break;
822
#endif
823

824
#ifdef ECOMM
825
    case ECOMM:                /* FALLTHROUGH */
826
#endif
827
#ifdef EDEADLK
828
    case EDEADLK:                /* FALLTHROUGH */
829
#endif
830
#ifdef EDEADLOCK
831
# if !defined(EDEADLK) || (EDEADLOCK != EDEADLK)
832
    case EDEADLOCK:                /* FALLTHROUGH */
833
# endif
834
#endif
835
#ifdef EXFULL
836
    case EXFULL:                /* FALLTHROUGH */
837
#endif
838
#ifdef ENOSR
839
    case ENOSR:                /* FALLTHROUGH */
840
#endif
841
#ifdef EPROTO
842
    case EPROTO:                /* FALLTHROUGH */
843
#endif
844
#ifdef ETIME
845
    case ETIME:                /* FALLTHROUGH */
846
#endif
847
#ifdef EIO
848
    case EIO:                /* FALLTHROUGH */
849
#endif
850
#ifdef EFAULT
851
    case EFAULT:                /* FALLTHROUGH */
852
#endif
853
#ifdef ESPIPE
854
    case ESPIPE:                /* FALLTHROUGH */
855
#endif
856
#if defined(ECOMM) || defined(EDEADLK) ||  defined(EDEADLOCK) || \
857
    defined(EXFULL) || defined(ENOSR) || defined(EPROTO) || \
858
    defined(ETIME) || defined(EIO) || defined(EFAULT) || \
859
    defined(ESPIPE) || defined(EPIPE)
860
      respcode = R_451;
861
      break;
862
#endif
863

864
#ifdef EREMCHG
865
    case EREMCHG:                /* FALLTHROUGH */
×
866
#endif
867
#ifdef ESRMNT
868
    case ESRMNT:                /* FALLTHROUGH */
869
#endif
870
#ifdef ESTALE
871
    case ESTALE:                /* FALLTHROUGH */
872
#endif
873
#ifdef ENOLINK
874
    case ENOLINK:                /* FALLTHROUGH */
875
#endif
876
#ifdef ENOLCK
877
    case ENOLCK:                /* FALLTHROUGH */
878
#endif
879
#ifdef ENETRESET
880
    case ENETRESET:                /* FALLTHROUGH */
881
#endif
882
#ifdef ETIMEDOUT
883
    case ETIMEDOUT:
884
#endif
885
#if defined(EREMCHG) || defined(ESRMNT) ||  defined(ESTALE) || \
886
    defined(ENOLINK) || defined(ENOLCK) || defined(ENETRESET) || \
887
    defined(ECONNABORTED) || defined(ECONNRESET) || defined(ETIMEDOUT)
888
      respcode = R_450;
×
889
      msg = _("Link to file server lost");
×
890
      break;
×
891
#endif
892
    }
893

894
    if (msg == NULL &&
4✔
895
        (msg = strerror(err)) == NULL) {
896

897
      if (pr_snprintf(msgbuf, sizeof(msgbuf),
×
898
          _("Unknown or out of range errno [%d]"), err) > 0) {
×
899
        msg = msgbuf;
×
900
      }
901
    }
902

903
    pr_log_pri(PR_LOG_NOTICE, "notice: user %s: aborting transfer: %s",
10✔
904
      session.user ? session.user : "(unknown)", msg);
10✔
905

906
    /* If we are aborting, then a 426 response has already been sent via
907
     * pr_inet_lingering_abort(), and we don't want to add another to the
908
     * error queue.
909
     */
910
    if (true_abort == FALSE) {
10✔
911
      pr_response_add_err(respcode, _("Transfer aborted. %s"), msg ? msg : "");
2✔
912
    }
913

914
    /* Forcibly clear the data-transfer instigating command pool from the
915
     * Response API.
916
     */
917
    pr_response_set_pool(session.pool);
10✔
918
  }
919

920
  if (true_abort) {
11✔
921
    session.sf_flags |= SF_POST_ABORT;
8✔
922
  }
923
}
11✔
924

925
/* From response.c.  XXX Need to provide these symbols another way. */
926
extern pr_response_t *resp_list, *resp_err_list;
927

928
static int peek_is_abor_cmd(void) {
14✔
929
  int fd, res;
930
  fd_set rfds;
931
  struct timeval tv;
932
  ssize_t len;
933
  char buf[5];
934

935
  tv.tv_sec = 1;
14✔
936
  tv.tv_usec = 0;
14✔
937

938
  fd = PR_NETIO_FD(session.c->instrm);
14✔
939
  pr_trace_msg(trace_channel, 20, "peeking at next data for fd %d", fd);
14✔
940

941
  FD_ZERO(&rfds);
14✔
942
  FD_SET(fd, &rfds);
14✔
943

944
  res = select(fd + 1, &rfds, NULL, NULL, &tv);
14✔
945
  while (res < 0) {
14✔
946
    int xerrno = errno;
×
947

948
    if (xerrno == EINTR) {
×
949
      pr_signals_handle();
×
950
      res = select(fd + 1, &rfds, NULL, NULL, &tv);
×
951
      continue;
×
952
    }
953

954
    pr_trace_msg(trace_channel, 20,
×
955
      "error waiting for next data on fd %d: %s", fd, strerror(xerrno));
956
    return FALSE;
×
957
  }
958

959
  if (res == 0) {
14✔
960
    /* Timed out. */
961
    pr_trace_msg(trace_channel, 20, "timed out peeking for data on fd %d", fd);
13✔
962
    return FALSE;
13✔
963
  }
964

965
  /* If we reach here, the peer must have sent something.  Let's see what it
966
   * might be.  Chances are that we received at least 5 bytes, but to be
967
   * defensive, we use MSG_WAITALL anyway.  TCP allows for sending one byte
968
   * at time, if need be.  The shortest FTP command is 5 bytes, e.g. "CCC\r\n".
969
   * ABOR would be 6 bytes, but we do not want to block until we see 6 bytes;
970
   * we're peeking opportunistically, and optimistically.
971
   */
972
  memset(&buf, 0, sizeof(buf));
1✔
973
  len = recv(fd, buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
1✔
974
  while (len < 0) {
1✔
975
    int xerrno = errno;
1✔
976

977
    if (xerrno == EINTR) {
1✔
978
      pr_signals_handle();
×
979
      len = recv(fd, &buf, sizeof(buf), MSG_PEEK|MSG_WAITALL);
×
980
      continue;
×
981
    }
982

983
    pr_trace_msg(trace_channel, 20,
1✔
984
      "error peeking at next data: %s", strerror(xerrno));
985
    return FALSE;
1✔
986
  }
987

988
  pr_trace_msg(trace_channel, 20, "peeking at %ld bytes of next data",
×
989
    (long) len);
990
  if (strncasecmp(buf, "ABOR\r", len) == 0) {
×
991
    pr_trace_msg(trace_channel, 20, "peeked data probably 'ABOR' command");
×
992
    return TRUE;
×
993
  }
994

995
  pr_trace_msg(trace_channel, 20, "peeked data '%.*s' not ABOR command",
×
996
    (int) len, buf);
997
  return FALSE;
×
998
}
999

1000
static void poll_ctrl(void) {
26✔
1001
  int res;
1002

1003
  if (session.c == NULL) {
26✔
1004
    return;
1005
  }
1006

1007
  pr_trace_msg(trace_channel, 4, "polling for commands on control channel");
14✔
1008
  pr_netio_set_poll_interval(session.c->instrm, 0);
14✔
1009
  res = pr_netio_poll(session.c->instrm);
14✔
1010
  pr_netio_reset_poll_interval(session.c->instrm);
14✔
1011

1012
  if (res == 0 &&
28✔
1013
      !(session.sf_flags & SF_ABORT)) {
14✔
1014

1015
    /* First, we peek at the data, to see if it is an ABOR command.  Why?
1016
     *
1017
     * Consider the case where a client uses the TCP OOB mechanism and
1018
     * marks the ABOR command with the marker.  In that case, a SIGURG signal
1019
     * will have been raised, and the SF_ABORT flag set.  The actual "ABOR"
1020
     * data on the control connection will be read only AFTER the data transfer
1021
     * has been failed.  This leads the proper ordering of multiple responses
1022
     * (first for failed transfer, second for successful ABOR) in such cases.
1023
     *
1024
     * Now consider the case where a client does NOT use the TCP OOB mechanism,
1025
     * and only sends the ABOR command.  We want the same behavior in this case
1026
     * as for the TCP OOB case, BUT now, the SF_ABORT flag has NOT been set at
1027
     * this point in the flow.  Which means that we might read that "ABOR" text
1028
     * from the control connection _in the middle_ of the data transfer, which
1029
     * leads to different behavior, different ordering of responses.
1030
     *
1031
     * Thus we cheat here, and only peek at the control connection data.  IFF
1032
     * it is the "ABOR\r\n" text, then we set the SF_ABORT flag ourselves
1033
     * here, and preserve the expected semantics (Bug #4402).
1034
     */
1035
    if (peek_is_abor_cmd() == TRUE) {
14✔
1036
      pr_trace_msg(trace_channel, 5, "client sent 'ABOR' command during data "
×
1037
        "transfer, setting 'aborted' session flag");
1038

1039
      session.sf_flags |= SF_ABORT;
×
1040

1041
      if (nstrm != NULL) {
×
1042
        pr_netio_abort(nstrm);
×
1043
        errno = 0;
×
1044
      }
1045
    }
1046
  }
1047

1048
  if (res == 0 &&
28✔
1049
      !(session.sf_flags & SF_ABORT)) {
14✔
1050
    cmd_rec *cmd = NULL;
14✔
1051

1052
    pr_trace_msg(trace_channel, 1,
14✔
1053
      "data available for reading on control channel during data transfer, "
1054
      "reading control data");
1055
    res = pr_cmd_read(&cmd);
14✔
1056
    if (res < 0) {
14✔
1057
      int xerrno;
1058

1059
#if defined(ECONNABORTED)
1060
      xerrno = ECONNABORTED;
×
1061
#elif defined(ENOTCONN)
1062
      xerrno = ENOTCONN;
1063
#else
1064
      xerrno = EIO;
1065
#endif
1066

1067
      pr_trace_msg(trace_channel, 1,
×
1068
        "unable to read control command during data transfer: %s",
1069
        strerror(xerrno));
1070
      errno = xerrno;
×
1071

1072
#ifndef PR_DEVEL_NO_DAEMON
1073
      /* Otherwise, EOF */
1074
      pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CLIENT_EOF, NULL);
×
1075
#else
1076
      return;
1077
#endif /* PR_DEVEL_NO_DAEMON */
1078

1079
    } else if (cmd != NULL) {
14✔
1080
      char *ch;
1081

1082
      for (ch = cmd->argv[0]; *ch; ch++) {
35✔
1083
        *ch = toupper((int) *ch);
56✔
1084
      }
1085

1086
      cmd->cmd_id = pr_cmd_get_id(cmd->argv[0]);
7✔
1087

1088
      /* Only handle commands which do not involve data transfers; we
1089
       * already have a data transfer in progress.  For any data transfer
1090
       * command, send a 450 ("busy") reply.  Looks like almost all of the
1091
       * data transfer commands accept that response, as per RFC959.
1092
       *
1093
       * We also prevent the EPRT, EPSV, PASV, and PORT commands, since
1094
       * they will also interfere with the current data transfer.  In doing
1095
       * so, we break RFC compliance a little; RFC959 does not allow a
1096
       * response code of 450 for those commands (although it should).
1097
       */
1098
      if (pr_cmd_cmp(cmd, PR_CMD_APPE_ID) == 0 ||
14✔
1099
          pr_cmd_cmp(cmd, PR_CMD_LIST_ID) == 0 ||
14✔
1100
          pr_cmd_cmp(cmd, PR_CMD_MLSD_ID) == 0 ||
14✔
1101
          pr_cmd_cmp(cmd, PR_CMD_NLST_ID) == 0 ||
14✔
1102
          pr_cmd_cmp(cmd, PR_CMD_RETR_ID) == 0 ||
14✔
1103
          pr_cmd_cmp(cmd, PR_CMD_STOR_ID) == 0 ||
14✔
1104
          pr_cmd_cmp(cmd, PR_CMD_STOU_ID) == 0 ||
14✔
1105
          pr_cmd_cmp(cmd, PR_CMD_RNFR_ID) == 0 ||
14✔
1106
          pr_cmd_cmp(cmd, PR_CMD_RNTO_ID) == 0 ||
14✔
1107
          pr_cmd_cmp(cmd, PR_CMD_PORT_ID) == 0 ||
14✔
1108
          pr_cmd_cmp(cmd, PR_CMD_EPRT_ID) == 0 ||
14✔
1109
          pr_cmd_cmp(cmd, PR_CMD_PASV_ID) == 0 ||
12✔
1110
          pr_cmd_cmp(cmd, PR_CMD_EPSV_ID) == 0) {
7✔
1111
        pool *resp_pool;
1112

1113
        pr_trace_msg(trace_channel, 5,
2✔
1114
          "client sent '%s' command during data transfer, denying",
1115
          (char *) cmd->argv[0]);
2✔
1116

1117
        resp_list = resp_err_list = NULL;
2✔
1118
        resp_pool = pr_response_get_pool();
2✔
1119

1120
        pr_response_set_pool(cmd->pool);
2✔
1121

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

1125
        pr_response_flush(&resp_err_list);
2✔
1126

1127
        pr_response_set_pool(resp_pool);
2✔
1128
        destroy_pool(cmd->pool);
2✔
1129

1130
      /* We don't want to actually dispatch the NOOP command, since that
1131
       * would overwrite the scoreboard with the NOOP state; admins probably
1132
       * want to see the command that caused the data transfer.  And since
1133
       * NOOP doesn't take a 450 response (as per RFC959), we will simply
1134
       * return 200.
1135
       */
1136
      } else if (pr_cmd_cmp(cmd, PR_CMD_NOOP_ID) == 0) {
5✔
1137
        pool *resp_pool;
1138

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

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

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

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

1151
        pr_response_flush(&resp_list);
2✔
1152

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

1156
      } else {
1157
        char *title_buf = NULL;
3✔
1158
        int curr_cmd_id = 0, title_len = -1;
3✔
1159
        const char *curr_cmd = NULL, *sce_cmd = NULL, *sce_cmd_arg = NULL;
3✔
1160
        cmd_rec *curr_cmd_rec = NULL;
3✔
1161
        pool *resp_pool;
1162

1163
        pr_trace_msg(trace_channel, 5,
3✔
1164
          "client sent '%s' command during data transfer, dispatching",
1165
          (char *) cmd->argv[0]);
3✔
1166

1167
        title_len = pr_proctitle_get(NULL, 0);
3✔
1168
        if (title_len > 0) {
3✔
1169
          title_buf = pcalloc(cmd->pool, title_len + 1);
×
1170
          pr_proctitle_get(title_buf, title_len + 1);
×
1171
        }
1172

1173
        curr_cmd = session.curr_cmd;
3✔
1174
        curr_cmd_id = session.curr_cmd_id;
3✔
1175
        curr_cmd_rec = session.curr_cmd_rec;
3✔
1176
        sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD);
3✔
1177
        sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG);
3✔
1178

1179
        resp_list = resp_err_list = NULL;
3✔
1180
        resp_pool = pr_response_get_pool();
3✔
1181

1182
        pr_response_set_pool(cmd->pool);
3✔
1183
        pr_cmd_dispatch(cmd);
3✔
1184

1185
        pr_scoreboard_entry_update(session.pid,
3✔
1186
          PR_SCORE_CMD, "%s", sce_cmd, NULL, NULL);
1187
        pr_scoreboard_entry_update(session.pid,
3✔
1188
          PR_SCORE_CMD_ARG, "%s", sce_cmd_arg, NULL, NULL);
1189

1190
        if (title_len > 0) {
3✔
1191
          pr_proctitle_set_str(title_buf);
×
1192
        }
1193

1194
        pr_response_flush(&resp_list);
3✔
1195
        pr_response_set_pool(resp_pool);
3✔
1196
        destroy_pool(cmd->pool);
3✔
1197

1198
        session.curr_cmd = curr_cmd;
3✔
1199
        session.curr_cmd_id = curr_cmd_id;
3✔
1200
        session.curr_cmd_rec = curr_cmd_rec;
3✔
1201
      }
1202

1203
    } else {
1204
      pr_trace_msg(trace_channel, 3,
7✔
1205
        "invalid command sent, sending error response");
1206
      pr_response_send(R_500, _("Invalid command: try being more creative"));
7✔
1207
    }
1208
  }
1209
}
1210

1211
/* pr_data_xfer() actually transfers the data on the data connection.  ASCII
1212
 * translation is performed if necessary.  `direction' is set when the data
1213
 * connection was opened.
1214
 *
1215
 * We determine if the client buffer is read from or written to.  Returns 0 if
1216
 * reading and data connection closes, or -1 if error (with errno set).
1217
 */
1218
int pr_data_xfer(char *cl_buf, size_t cl_size) {
34✔
1219
  int len = 0;
34✔
1220
  int total = 0;
34✔
1221
  int res = 0;
34✔
1222
  pool *tmp_pool = NULL;
34✔
1223

1224
  if (cl_buf == NULL ||
68✔
1225
      cl_size == 0) {
34✔
1226
    errno = EINVAL;
8✔
1227
    return -1;
8✔
1228
  }
1229

1230
  /* Poll the control channel for any commands we should handle, like
1231
   * QUIT or ABOR.
1232
   */
1233
  poll_ctrl();
26✔
1234

1235
  /* If we don't have a data connection here (e.g. might have been closed
1236
   * by an ABOR), then return zero (no data transferred).
1237
   */
1238
  if (session.d == NULL) {
26✔
1239
    int xerrno;
1240

1241
#if defined(ECONNABORTED)
1242
    xerrno = ECONNABORTED;
4✔
1243
#elif defined(ENOTCONN)
1244
    xerrno = ENOTCONN;
1245
#else
1246
    xerrno = EIO;
1247
#endif
1248

1249
    pr_trace_msg(trace_channel, 1,
4✔
1250
      "data connection is null prior to data transfer (possibly from "
1251
      "aborted transfer), returning '%s' error", strerror(xerrno));
1252
    pr_log_debug(DEBUG5,
4✔
1253
      "data connection is null prior to data transfer (possibly from "
1254
       "aborted transfer), returning '%s' error", strerror(xerrno));
1255

1256
    errno = xerrno;
4✔
1257
    return -1;
4✔
1258
  }
1259

1260
  if (session.xfer.direction == PR_NETIO_IO_RD) {
22✔
1261
    char *buf;
1262

1263
    buf = session.xfer.buf;
12✔
1264

1265
    /* We use ASCII translation if:
1266
     *
1267
     * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
1268
     */
1269
    if (((session.sf_flags & SF_ASCII) &&
19✔
1270
        !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
7✔
1271
      int adjlen, buflen;
1272

1273
      do {
1274
        buflen = session.xfer.buflen;        /* how much remains in buf */
7✔
1275
        adjlen = 0;
7✔
1276

1277
        pr_signals_handle();
7✔
1278

1279
        len = pr_netio_read(session.d->instrm, buf + buflen,
7✔
1280
          session.xfer.bufsize - buflen, 1);
7✔
1281
        while (len < 0) {
7✔
1282
          int xerrno = errno;
1✔
1283

1284
          if (xerrno == EAGAIN || xerrno == EINTR) {
1✔
1285
            /* Since our socket is in non-blocking mode, read(2) can return
1286
             * EAGAIN if there is no data yet for us.  Handle this by
1287
             * delaying temporarily, then trying again.
1288
             */
1289
            errno = EINTR;
×
1290
            pr_signals_handle();
×
1291

1292
            len = pr_netio_read(session.d->instrm, buf + buflen,
×
1293
              session.xfer.bufsize - buflen, 1);
×
1294
            continue;
×
1295
          }
1296

1297
          destroy_pool(tmp_pool);
1✔
1298
          errno = xerrno;
1✔
1299
          return -1;
1✔
1300
        }
1301

1302
        if (len > 0 &&
12✔
1303
            data_first_byte_read == FALSE) {
6✔
1304
          if (pr_trace_get_level(timing_channel)) {
2✔
1305
            unsigned long elapsed_ms;
1306
            uint64_t read_ms;
1307

1308
            pr_gettimeofday_millis(&read_ms);
2✔
1309
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
2✔
1310

1311
            pr_trace_msg(timing_channel, 7,
2✔
1312
              "Time for first data byte read: %lu ms", elapsed_ms);
1313
          }
1314

1315
          data_first_byte_read = TRUE;
2✔
1316
        }
1317

1318
        if (len > 0) {
6✔
1319
          pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
6✔
1320
            len != 1 ? "bytes" : "byte");
1321

1322
          buflen += len;
6✔
1323

1324
          if (timeout_stalled) {
6✔
1325
            pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
6✔
1326
          }
1327
        }
1328

1329
        /* If buflen > 0, data remains in the buffer to be copied. */
1330
        if (len >= 0 &&
6✔
1331
            buflen > 0) {
6✔
1332

1333
          /* Perform ASCII translation:
1334
           *
1335
           * buflen: is returned as the modified buffer length after
1336
           *         translation
1337
           * res:    is returned as the number of characters unprocessed in
1338
           *         the buffer (to be dealt with later)
1339
           *
1340
           * We skip the call to pr_ascii_ftp_from_crlf() in one case:
1341
           * when we have one character in the buffer and have reached
1342
           * end of data, this is so that pr_ascii_ftp_from_crlf() won't sit
1343
           * forever waiting for the next character after a final '\r'.
1344
           */
1345
          if (len > 0 ||
12✔
1346
              buflen > 1) {
6✔
1347
            size_t outlen = 0;
6✔
1348

1349
            if (tmp_pool == NULL) {
6✔
1350
              tmp_pool = make_sub_pool(session.xfer.p);
6✔
1351
              pr_pool_tag(tmp_pool, "ASCII upload");
6✔
1352
            }
1353

1354
            res = pr_ascii_ftp_from_crlf(tmp_pool, buf, buflen, &buf, &outlen);
6✔
1355
            if (res < 0) {
6✔
1356
              pr_trace_msg(trace_channel, 3, "error reading ASCII data: %s",
×
1357
                strerror(errno));
×
1358

1359
            } else {
1360
              adjlen += res;
6✔
1361
              buflen = (int) outlen;
6✔
1362
            }
1363
          }
1364

1365
          /* Now copy everything we can into cl_buf */
1366
          if ((size_t) buflen > cl_size) {
6✔
1367
            /* Because we have to cut our buffer short, make sure this
1368
             * is made up for later by increasing adjlen.
1369
             */
1370
            adjlen += (buflen - cl_size);
×
1371
            buflen = cl_size;
×
1372
          }
1373

1374
          memcpy(cl_buf, buf, buflen);
12✔
1375

1376
          /* Copy whatever remains at the end of session.xfer.buf to the
1377
           * head of the buffer and adjust buf accordingly.
1378
           *
1379
           * adjlen is now the total bytes still waiting in buf, if
1380
           * anything remains, copy it to the start of the buffer.
1381
           */
1382

1383
          if (adjlen > 0) {
6✔
1384
            memcpy(buf, buf + buflen, adjlen);
1✔
1385
          }
1386

1387
          /* Store everything back in session.xfer. */
1388
          session.xfer.buflen = adjlen;
6✔
1389
          total += buflen;
6✔
1390
        }
1391
        
1392
        /* Restart if data was returned by pr_netio_read() (len > 0) but no
1393
         * data was copied to the client buffer (buflen = 0).  This indicates
1394
         * that pr_ascii_ftp_from_crlf() needs more data in order to
1395
         * translate, so we need to call pr_netio_read() again.
1396
         */
1397
      } while (len > 0 && buflen == 0);
6✔
1398

1399
      /* Return how much data we actually copied into the client buffer. */
1400
      len = buflen;
1401

1402
    } else {
1403
      len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
5✔
1404
      while (len < 0) {
10✔
1405
        int xerrno = errno;
1✔
1406

1407
        if (xerrno == EAGAIN || xerrno == EINTR) {
1✔
1408
          /* Since our socket is in non-blocking mode, read(2) can return
1409
           * EAGAIN if there is no data yet for us.  Handle this by
1410
           * delaying temporarily, then trying again.
1411
           */
1412
          errno = EINTR;
×
1413
          pr_signals_handle();
×
1414

1415
          len = pr_netio_read(session.d->instrm, cl_buf, cl_size, 1);
×
1416
          continue;
×
1417
        }
1418

1419
        break;
1420
      }
1421

1422
      if (len > 0) {
5✔
1423
        pr_trace_msg(trace_channel, 19, "read %d %s from network", len,
4✔
1424
          len != 1 ? "bytes" : "byte");
1425

1426
        if (data_first_byte_read == FALSE) {
4✔
1427
          if (pr_trace_get_level(timing_channel)) {
2✔
1428
            unsigned long elapsed_ms;
1429
            uint64_t read_ms;
1430

1431
            pr_gettimeofday_millis(&read_ms);
2✔
1432
            elapsed_ms = (unsigned long) (read_ms - data_start_ms);
2✔
1433

1434
            pr_trace_msg(timing_channel, 7,
2✔
1435
              "Time for first data byte read: %lu ms", elapsed_ms);
1436
          }
1437

1438
          data_first_byte_read = TRUE;
2✔
1439
        }
1440

1441
        /* Non-ASCII mode doesn't need to use session.xfer.buf */
1442
        if (timeout_stalled) {
4✔
1443
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
4✔
1444
        }
1445

1446
        total += len;
1447
      }
1448
    }
1449

1450
  } else { /* PR_NETIO_IO_WR */
1451

1452
    while (cl_size) {
18✔
1453
      int bwrote = 0;
10✔
1454
      int buflen = cl_size;
10✔
1455
      unsigned int xferbuflen;
1456
      char *xferbuf = NULL, *ascii_buf = NULL;
10✔
1457

1458
      pr_signals_handle();
10✔
1459

1460
      if (buflen > pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR)) {
10✔
1461
        buflen = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);
×
1462
      }
1463

1464
      xferbuf = cl_buf;
10✔
1465
      xferbuflen = buflen;
10✔
1466

1467
      /* We use ASCII translation if:
1468
       *
1469
       * - SF_ASCII_OVERRIDE session flag is set (e.g. for LIST/NLST)
1470
       * - SF_ASCII session flag is set, AND IGNORE_ASCII data opt NOT set
1471
       */
1472
      if ((session.sf_flags & SF_ASCII_OVERRIDE) ||
14✔
1473
          ((session.sf_flags & SF_ASCII) &&
5✔
1474
           !(data_opts & PR_DATA_OPT_IGNORE_ASCII))) {
1✔
1475
        char *out = NULL;
7✔
1476
        size_t outlen = 0;
7✔
1477

1478
        if (tmp_pool == NULL) {
7✔
1479
          tmp_pool = make_sub_pool(session.xfer.p);
7✔
1480
          pr_pool_tag(tmp_pool, "ASCII download");
7✔
1481
        }
1482

1483
        /* Fill up our internal buffer. */
1484
        memcpy(session.xfer.buf, cl_buf, buflen);
14✔
1485

1486
        /* Scan the internal buffer, looking for LFs with no preceding CRs.
1487
         * Add CRs (and expand the internal buffer) as necessary. xferbuflen
1488
         * will be adjusted so that it contains the length of data in
1489
         * the internal buffer, including any added CRs.
1490
         */
1491
        res = pr_ascii_ftp_to_crlf(tmp_pool, session.xfer.buf, xferbuflen,
7✔
1492
          &out, &outlen);
1493
        if (res < 0) {
7✔
1494
          pr_trace_msg(trace_channel, 1, "error writing ASCII data: %s",
×
1495
            strerror(errno));
×
1496

1497
        } else {
1498
          ascii_buf = session.xfer.buf;
7✔
1499
          session.xfer.buf = out;
7✔
1500
          session.xfer.buflen = xferbuflen = outlen;
7✔
1501
        }
1502

1503
        xferbuf = session.xfer.buf;
7✔
1504
      }
1505

1506
      bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
10✔
1507
      while (bwrote < 0) {
10✔
1508
        int xerrno = errno;
4✔
1509

1510
        if (xerrno == EAGAIN ||
8✔
1511
            xerrno == EINTR) {
4✔
1512
          /* Since our socket may be in non-blocking mode, write(2) can return
1513
           * EAGAIN if there is not enough from for our data yet.  Handle
1514
           * this by delaying temporarily, then trying again.
1515
           */
1516
          errno = EINTR;
2✔
1517
          pr_signals_handle();
2✔
1518

1519
          bwrote = pr_netio_write(session.d->outstrm, xferbuf, xferbuflen);
2✔
1520
          continue;
2✔
1521
        }
1522

1523
        destroy_pool(tmp_pool);
2✔
1524
        if (ascii_buf != NULL) {
2✔
1525
          /* Free up the malloc'd memory. */
1526
          free(session.xfer.buf);
1✔
1527
          session.xfer.buf = ascii_buf;
1✔
1528
        }
1529

1530
        errno = xerrno;
2✔
1531
        return -1;
2✔
1532
      }
1533

1534
      if (bwrote > 0) {
8✔
1535
        pr_trace_msg(trace_channel, 19, "wrote %d %s to network", bwrote,
8✔
1536
          bwrote != 1 ? "bytes" : "byte");
1537

1538
        if (data_first_byte_written == FALSE) {
8✔
1539
          if (pr_trace_get_level(timing_channel)) {
3✔
1540
            unsigned long elapsed_ms;
1541
            uint64_t write_ms;
1542

1543
            pr_gettimeofday_millis(&write_ms);
3✔
1544
            elapsed_ms = (unsigned long) (write_ms - data_start_ms);
3✔
1545

1546
            pr_trace_msg(timing_channel, 7,
3✔
1547
              "Time for first data byte written: %lu ms", elapsed_ms);
1548
          }
1549

1550
          data_first_byte_written = TRUE;
3✔
1551
        }
1552

1553
        if (timeout_stalled) {
8✔
1554
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
8✔
1555
        }
1556

1557
        cl_size -= buflen;
8✔
1558
        cl_buf += buflen;
8✔
1559
        total += buflen;
8✔
1560
      }
1561

1562
      if (ascii_buf != NULL) {
8✔
1563
        /* Yes, we are using malloc et al here, rather than the memory pools.
1564
         * See Bug#4352 for details.
1565
         */
1566
        free(session.xfer.buf);
6✔
1567
        session.xfer.buf = ascii_buf;
6✔
1568
      }
1569
    }
1570

1571
    len = total;
1572
  }
1573

1574
  if (total &&
19✔
1575
      timeout_idle) {
1576
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
18✔
1577
  }
1578

1579
  session.xfer.total_bytes += total;
19✔
1580
  session.total_bytes += total;
19✔
1581
  if (session.xfer.direction == PR_NETIO_IO_RD) {
19✔
1582
    session.total_bytes_in += total;
11✔
1583

1584
  } else {
1585
    session.total_bytes_out += total;
8✔
1586
  }
1587

1588
  destroy_pool(tmp_pool);
19✔
1589
  return (len < 0 ? -1 : len);
19✔
1590
}
1591

1592
#if defined(HAVE_SENDFILE)
1593
/* pr_data_sendfile() actually transfers the data on the data connection.
1594
 * ASCII translation is not performed.
1595
 * return 0 if reading and data connection closes, or -1 if error
1596
 */
1597
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
7✔
1598
  int flags, error;
1599
  pr_sendfile_t len = 0, total = 0;
7✔
1600
# if defined(HAVE_AIX_SENDFILE)
1601
  struct sf_parms parms;
1602
  int rc;
1603
# endif /* HAVE_AIX_SENDFILE */
1604

1605
  if (offset == NULL ||
14✔
1606
      count == 0) {
7✔
1607
    errno = EINVAL;
3✔
1608
    return -1;
3✔
1609
  }
1610

1611
  if (session.xfer.direction == PR_NETIO_IO_RD) {
4✔
1612
    errno = EPERM;
1✔
1613
    return -1;
1✔
1614
  }
1615

1616
  if (session.d == NULL) {
3✔
1617
    errno = EPERM;
1✔
1618
    return -1;
1✔
1619
  }
1620

1621
  flags = fcntl(PR_NETIO_FD(session.d->outstrm), F_GETFL);
2✔
1622
  if (flags < 0) {
2✔
1623
    return -1;
1624
  }
1625

1626
  /* Set fd to blocking-mode for sendfile() */
1627
  if (flags & O_NONBLOCK) {
2✔
1628
    if (fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags^O_NONBLOCK) < 0) {
×
1629
      return -1;
1630
    }
1631
  }
1632

1633
  for (;;) {
1634
# if defined(HAVE_LINUX_SENDFILE) || defined(HAVE_SOLARIS_SENDFILE)
1635
    off_t orig_offset = *offset;
2✔
1636

1637
    /* Linux semantics are fairly straightforward in a glibc 2.x world:
1638
     *
1639
     *   #include <sys/sendfile.h>
1640
     *
1641
     *   ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
1642
     *
1643
     * Unfortunately, this API does not allow for an off_t number of bytes
1644
     * to be sent, only a size_t.  This means we need to make sure that
1645
     * the given count does not exceed the maximum value for a size_t.  Even
1646
     * worse, the return value is a ssize_t, not a size_t, which means
1647
     * the maximum value used can only be of the maximum _signed_ value,
1648
     * not the maximum unsigned value.  This means calling sendfile() more
1649
     * times.  How annoying.
1650
     */
1651

1652
#  if defined(HAVE_LINUX_SENDFILE)
1653
    if (count > INT_MAX) {
2✔
1654
      count = INT_MAX;
×
1655
    }
1656
#  elif defined(HAVE_SOLARIS_SENDFILE)
1657
#   if SIZEOF_SIZE_T == SIZEOF_INT
1658
    if (count > INT_MAX) {
1659
      count = INT_MAX;
1660
    }
1661
#   elif SIZEOF_SIZE_T == SIZEOF_LONG
1662
    if (count > LONG_MAX) {
1663
      count = LONG_MAX;
1664
    }
1665
#   elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
1666
    if (count > LLONG_MAX) {
1667
      count = LLONG_MAX;
1668
    }
1669
#   endif
1670
#  endif /* !HAVE_SOLARIS_SENDFILE */
1671

1672
    errno = 0;
2✔
1673
    len = sendfile(PR_NETIO_FD(session.d->outstrm), retr_fd, offset, count);
2✔
1674

1675
    /* If no data could be written (e.g. the file was truncated), we're
1676
     * done (Bug#4318).
1677
     */
1678
    if (len == 0) {
2✔
1679
      if (errno != EINTR &&
×
1680
          errno != EAGAIN) {
1681
        break;
1682
      }
1683

1684
      /* Handle our interrupting signal, and continue. */
1685
      pr_signals_handle();
×
1686
    }
1687

1688
    if (len != -1 &&
4✔
1689
        len < count) {
2✔
1690
      /* Under Linux semantics, this occurs when a signal has interrupted
1691
       * sendfile().
1692
       */
1693
      if (XFER_ABORTED) {
×
1694
        errno = EINTR;
×
1695

1696
        session.xfer.total_bytes += len;
×
1697
        session.total_bytes += len;
×
1698
        session.total_bytes_out += len;
×
1699
        session.total_raw_out += len;
×
1700

1701
        return -1;
×
1702
      }
1703

1704
      count -= len;
×
1705

1706
      /* Only reset the timers if data have actually been written out. */
1707
      if (len > 0) {
×
1708
        if (timeout_stalled) {
×
1709
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
×
1710
        }
1711

1712
        if (timeout_idle) {
×
1713
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
×
1714
        }
1715
      }
1716

1717
      session.xfer.total_bytes += len;
×
1718
      session.total_bytes += len;
×
1719
      session.total_bytes_out += len;
×
1720
      session.total_raw_out += len;
×
1721
      total += len;
×
1722

1723
      pr_signals_handle();
×
1724
      continue;
×
1725
    }
1726

1727
    if (len == -1) {
2✔
1728
      /* Linux updates offset on error, not len like BSD, fix up so
1729
       * BSD-based code works.
1730
       */
1731
      len = *offset - orig_offset;
1✔
1732
      *offset = orig_offset;
1✔
1733

1734
# elif defined(HAVE_BSD_SENDFILE)
1735
    /* BSD semantics for sendfile are flexible...it'd be nice if we could
1736
     * standardize on something like it.  The semantics are:
1737
     *
1738
     *   #include <sys/types.h>
1739
     *   #include <sys/socket.h>
1740
     *   #include <sys/uio.h>
1741
     *
1742
     *   int sendfile(int in_fd, int out_fd, off_t offset, size_t count,
1743
     *                struct sf_hdtr *hdtr, off_t *len, int flags)
1744
     *
1745
     *  The comments above, about size_t versus off_t, apply here as
1746
     *  well.  Except that BSD's sendfile() uses an off_t * for returning
1747
     *  the number of bytes sent, so we can use the maximum unsigned
1748
     *  value.
1749
     */
1750

1751
#  if SIZEOF_SIZE_T == SIZEOF_INT
1752
    if (count > UINT_MAX) {
1753
      count = UINT_MAX;
1754
    }
1755
#  elif SIZEOF_SIZE_T == SIZEOF_LONG
1756
    if (count > ULONG_MAX) {
1757
      count = ULONG_MAX;
1758
    }
1759
#  elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
1760
    if (count > ULLONG_MAX) {
1761
      count = ULLONG_MAX;
1762
    }
1763
#  endif
1764

1765
    if (sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, count,
1766
        NULL, &len, 0) == -1) {
1767

1768
# elif defined(HAVE_MACOSX_SENDFILE)
1769
    off_t orig_len = count;
1770
    int res;
1771

1772
    /* Since Mac OSX uses the fourth argument as a value-return parameter,
1773
     * success or failure, we need to put the result into len after the
1774
     * call.
1775
     */
1776

1777
    res = sendfile(retr_fd, PR_NETIO_FD(session.d->outstrm), *offset, &orig_len,
1778
      NULL, 0);
1779
    len = orig_len;
1780

1781
    if (res < 0) {
1782
# elif defined(HAVE_AIX_SENDFILE)
1783

1784
    memset(&parms, 0, sizeof(parms));
1785

1786
    parms.file_descriptor = retr_fd;
1787
    parms.file_offset = (uint64_t) *offset;
1788
    parms.file_bytes = (int64_t) count;
1789

1790
    rc = send_file(&(PR_NETIO_FD(session.d->outstrm)), &(parms), (uint_t)0);
1791
    len = (int) parms.bytes_sent;
1792

1793
    if (rc < -1 || rc == 1) {
1794
# else
1795
    if (FALSE) {
1796
# endif /* HAVE_AIX_SENDFILE */
1797

1798
      /* IMO, BSD's semantics are warped.  Apparently, since we have our
1799
       * alarms tagged SA_INTERRUPT (allowing system calls to be
1800
       * interrupted - primarily for select), BSD will interrupt a
1801
       * sendfile operation as well, so we have to catch and handle this
1802
       * case specially.  It should also be noted that the sendfile(2) man
1803
       * page doesn't state any of this.
1804
       *
1805
       * HP/UX has the same semantics, however, EINTR is well documented
1806
       * as a side effect in the sendfile(2) man page.  HP/UX, however,
1807
       * is implemented horribly wrong.  If a signal would result in
1808
       * -1 being returned and EINTR being set, what ACTUALLY happens is
1809
       * that errno is cleared and the number of bytes written is returned.
1810
       *
1811
       * For obvious reasons, HP/UX sendfile is not supported yet.
1812
       */
1813
      if (errno == EINTR) {
1✔
1814
        if (XFER_ABORTED) {
×
1815
          session.xfer.total_bytes += len;
×
1816
          session.total_bytes += len;
×
1817
          session.total_bytes_out += len;
×
1818
          session.total_raw_out += len;
×
1819

1820
          return -1;
×
1821
        }
1822

1823
        pr_signals_handle();
×
1824

1825
        /* If we got everything in this transaction, we're done. */
1826
        if (len >= count) {
×
1827
          break;
1828
        }
1829

1830
        count -= len;
×
1831
        *offset += len;
×
1832

1833
        if (timeout_stalled) {
×
1834
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
×
1835
        }
1836

1837
        if (timeout_idle) {
×
1838
          pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);
×
1839
        }
1840

1841
        session.xfer.total_bytes += len;
×
1842
        session.total_bytes += len;
×
1843
        session.total_bytes_out += len;
×
1844
        session.total_raw_out += len;
×
1845
        total += len;
×
1846

1847
        continue;
×
1848
      }
1849

1850
      error = errno;
1✔
1851
      (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
1✔
1852
      errno = error;
1✔
1853

1854
      return -1;
1✔
1855
    }
1856

1857
    break;
1858
  }
1859

1860
  if (flags & O_NONBLOCK) {
1✔
1861
    (void) fcntl(PR_NETIO_FD(session.d->outstrm), F_SETFL, flags);
×
1862
  }
1863

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

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

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

1878
  return total;
1✔
1879
}
1880
#else
1881
pr_sendfile_t pr_data_sendfile(int retr_fd, off_t *offset, off_t count) {
1882
  errno = ENOSYS;
1883
  return -1;
1884
}
1885
#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