static int wait_for_data(Socket* fp, bool wait_for_read) { errno = 0; const int r = sock_check_pending(fp, !wait_for_read); #if 0 if(r < 0 && errno == EINTR && gvSigStopReceived && ftp_sigints() == 0) { gvSigStopReceived = false; r = 0; } #endif if(r < 0) { /* perror("\nselect");*/ if(errno == EINTR) { if(gvSighupReceived) return 1; if(gvInterrupted) return -1; if(ftp_sigints() == 0) /* assume it is a SIGSTOP/SIGCONT signal */ return 0; } return -1; } if(r) ftp->ti.stalled = 0; else ftp->ti.stalled++; return r; }
static int maybe_abort(FILE *in, FILE *out) { unsigned i; i = ftp_sigints(); ftp_set_close_handler(); ftp->ti.finished = true; if(ftp->ti.interrupted) i++; if(i > 0 || ferror(in) || ferror(out)) { if(ferror(in)) { ftp_err(_("read error: %s\n"), strerror(errno)); ftp->ti.ioerror = true; } else if(ferror(out)) { ftp_err(_("write error: %s\n"), strerror(errno)); ftp->ti.ioerror = true; } return ftp_abort(ftp->ti.transfer_is_put ? out : in); } return 0; }
static int wait_for_data(FILE *fd, bool wait_for_read) { fd_set fds; struct timeval tv; int r; /* watch fd to see if it has input */ FD_ZERO(&fds); FD_SET(fileno(fd), &fds); /* wait max 1 second */ tv.tv_sec = 10; tv.tv_usec = 0; if(wait_for_read) r = select(fileno(fd)+1, &fds, 0, 0, &tv); else /* wait for write */ r = select(fileno(fd)+1, 0, &fds, 0, &tv); #if 0 if(r < 0 && errno == EINTR && gvSigStopReceived && ftp_sigints() == 0) { gvSigStopReceived = false; r = 0; } #endif if(r < 0) { /* perror("\nselect");*/ if(errno == EINTR) { if(gvSighupReceived) return 1; if(gvInterrupted) return -1; if(ftp_sigints() == 0) /* assume it is a SIGSTOP/SIGCONT signal */ return 0; } return -1; } if(r) ftp->ti.stalled = 0; else ftp->ti.stalled++; return r; }
static int FILE_recv_binary(FILE *in, FILE *out) { size_t n; char *buf; time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; clearerr(in); clearerr(out); buf = (char *)xmalloc(FTP_BUFSIZ); while(!feof(in)) { if(wait_for_input() != 0) { ftp_trace("wait_for_input() returned non-zero\n"); break; } #ifdef SECFTP n = sec_read(fileno(in), buf, FTP_BUFSIZ); #else n = fread(buf, sizeof(char), FTP_BUFSIZ, in); #endif if(n <= 0) break; if(ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } if(fwrite(buf, sizeof(char), n, out) != n) break; ftp->ti.size += n; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } free(buf); ftp_set_close_handler(); return maybe_abort(in, out); }
static int FILE_recv_ascii(FILE *in, FILE *out) { char *buf = (char *)xmalloc(FTP_BUFSIZ); int c; time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; clearerr(in); clearerr(out); while((c = krb_getc(in)) != EOF) { if(ftp_sigints() > 0) break; if(wait_for_input() != 0) break; if(c == '\n') ftp->ti.barelfs++; else if(c == '\r') { c = krb_getc(in); if(c == EOF) break; if(c != '\n') { ungetc(c, in); c = '\r'; } } if(fputc(c, out) == EOF) break; ftp->ti.size++; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } free(buf); return maybe_abort(in, out); }
static int FILE_send_binary(FILE *in, FILE *out) { size_t n; char *buf; time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; clearerr(in); clearerr(out); buf = (char *)xmalloc(FTP_BUFSIZ); while(!feof(in)) { n = fread(buf, sizeof(char), FTP_BUFSIZ, in); if(n <= 0) break; if(ftp_sigints() > 0) break; if(wait_for_output() != 0) break; #ifdef SECFTP if(sec_write(fileno(out), buf, n) != n) break; #else if(fwrite(buf, sizeof(char), n, out) != n) break; #endif ftp->ti.size += n; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } #ifdef SECFTP sec_fflush(out); #endif free(buf); return maybe_abort(in, out); }
static int FILE_recv_binary(Socket* in, FILE *out) { time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; sock_clearerr_in(in); clearerr(out); char* buf = xmalloc(FTP_BUFSIZ); while (!sock_eof(in)) { if(wait_for_input() != 0) { ftp_trace("wait_for_input() returned non-zero\n"); break; } const ssize_t n = sock_read(in, buf, FTP_BUFSIZ); if (n <= 0) break; if(ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } if(fwrite(buf, sizeof(char), n, out) != n) break; ftp->ti.size += n; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } free(buf); ftp_set_close_handler(); return maybe_abort_in(in, out); }
static int FILE_send_binary(FILE *in, Socket *out) { time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; clearerr(in); sock_clearerr_out(out); char* buf = xmalloc(FTP_BUFSIZ); while(!feof(in)) { ssize_t n = fread(buf, sizeof(char), FTP_BUFSIZ, in); if(n <= 0) break; if(ftp_sigints() > 0) break; if(wait_for_output() != 0) break; if (sock_write(out, buf, n) != n) break; ftp->ti.size += n; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } sock_flush(out); free(buf); return maybe_abort_out(in, out); }
static int FILE_send_ascii(FILE* in, Socket* out) { time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; clearerr(in); sock_clearerr_out(out); int c; while((c = fgetc(in)) != EOF) { if(ftp_sigints() > 0) break; if(wait_for_output() != 0) break; if(c == '\n') { if(sock_put(out, '\r') == EOF) break; ftp->ti.size++; } if(sock_put(out, c) == EOF) break; ftp->ti.size++; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } return maybe_abort_out(in, out); }
static int maybe_abort_out(FILE *in, Socket *out) { unsigned int i = ftp_sigints(); ftp_set_close_handler(); ftp->ti.finished = true; if(ftp->ti.interrupted) i++; if(i > 0 || ferror(in) || sock_error_out(out)) { if(ferror(in)) { ftp_err(_("read error: %s\n"), strerror(errno)); ftp->ti.ioerror = true; } else if (sock_error_out(out)) { ftp_err(_("write error: %s\n"), strerror(errno)); ftp->ti.ioerror = true; } return ftp_abort(out); } return 0; }
static int do_write(const char* path, FILE* fp, ftp_transfer_func hookf, uint64_t offset) { /* try to set up a scp connection */ if (gvSSHTrySCP && !offset) { ssh_scp scp = ssh_scp_new(ftp->session, SSH_SCP_WRITE, path); if (scp != NULL) { int rc = ssh_scp_init(scp); if (rc == SSH_OK) return do_scp_write(scp, path, fp, hookf); ssh_scp_free(scp); } } time_t then = time(NULL) - 1; ftp_set_close_handler(); if (hookf) hookf(&ftp->ti); ftp->ti.begin = false; struct stat sb; errno = 0; if (fstat(fileno(fp), &sb) == -1) { ftp_err(_("Couldn't fstat local file: %s\n"), strerror(errno)); return -1; } /* open remote file */ sftp_file file = sftp_open(ftp->sftp_session, path, O_WRONLY | O_CREAT | (offset == 0u ? O_TRUNC : 0), sb.st_mode); if (!file) { ftp_err(_("Cannot open file for writing: %s\n"), ssh_get_error(ftp->session)); return -1; } /* seek to offset */ int r = sftp_seek64(file, offset); if (r != SSH_OK) { ftp_err(_("Failed to seek: %s\n"), ssh_get_error(ftp->session)); sftp_close(file); return -1; } /* read file */ char buffer[SSH_BUFSIZ]; ssize_t nbytes = 0; errno = 0; while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) > 0) { if (ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } ssize_t nwritten = sftp_write(file, buffer, nbytes); if (nwritten != nbytes) { ftp_err(_("Error while writing to file: %s\n"), ssh_get_error(ftp->session)); sftp_close(file); return -1; } ftp->ti.size += nbytes; if (hookf) { time_t now = time(NULL); if (now > then) { hookf(&ftp->ti); then = now; } } errno = 0; } if (ferror(fp)) { ftp_err(_("Failed to read from file: %s\n"), strerror(errno)); r = -1; } sftp_close(file); return r; }
static int do_scp_write(ssh_scp scp, const char* path, FILE* fp, ftp_transfer_func hookf) { time_t then = time(NULL) - 1; ftp_set_close_handler(); if (hookf) hookf(&ftp->ti); ftp->ti.begin = false; struct stat sb; errno = 0; if (fstat(fileno(fp), &sb) == -1) { ftp_err(_("Couldn't fstat local file: %s\n"), strerror(errno)); ssh_scp_free(scp); return -1; } int rc = ssh_scp_push_file(scp, path, sb.st_size, sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); if (rc != SSH_OK) { ftp_err(_("Failed to start scp upload: %s\n"), ssh_get_error(ftp->session)); ssh_scp_close(scp); ssh_scp_free(scp); return -1; } /* read file */ char buffer[SSH_BUFSIZ]; ssize_t nbytes = 0; errno = 0; while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp)) > 0) { if (ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } rc = ssh_scp_write(scp, buffer, nbytes); if (rc != SSH_OK) { ftp_err(_("Error while writing to file: %s\n"), ssh_get_error(ftp->session)); ssh_scp_close(scp); ssh_scp_free(scp); return -1; } ftp->ti.size += nbytes; if (hookf) { time_t now = time(NULL); if (now > then) { hookf(&ftp->ti); then = now; } } errno = 0; } if (ferror(fp)) { ftp_err(_("Failed to read from file: %s\n"), strerror(errno)); rc = -1; } ssh_scp_close(scp); ssh_scp_free(scp); return rc; }
static int do_read(const char* infile, FILE* fp, getmode_t mode, ftp_transfer_func hookf, uint64_t offset) { if (gvSSHTrySCP && !offset) { char* escaped = bash_backslash_quote(infile); /* try to set up a scp connection */ ssh_scp scp = ssh_scp_new(ftp->session, SSH_SCP_READ, escaped); free(escaped); if (scp != NULL) { int rc = ssh_scp_init(scp); if (rc == SSH_OK) return do_scp_read(scp, infile, fp, mode, hookf); ssh_scp_free(scp); } } time_t then = time(NULL) - 1; ftp_set_close_handler(); if (hookf) hookf(&ftp->ti); ftp->ti.begin = false; /* check if remote file is not a directory */ sftp_attributes attrib = sftp_stat(ftp->sftp_session, infile); if (!attrib) return -1; if (S_ISDIR(attrib->permissions)) { ftp_err(_("Cannot download a directory: %s\n"), infile); sftp_attributes_free(attrib); return -1; } sftp_attributes_free(attrib); /* open remote file */ sftp_file file = sftp_open(ftp->sftp_session, infile, O_RDONLY, 0); if (!file) { ftp_err(_("Cannot open file for reading: %s\n"), ssh_get_error(ftp->session)); return -1; } /* seek to offset */ int r = sftp_seek64(file, offset); if (r != SSH_OK) { ftp_err(_("Failed to seek: %s\n"), ssh_get_error(ftp->session)); sftp_close(file); return -1; } /* read file */ char buffer[SSH_BUFSIZ]; ssize_t nbytes = 0; while ((nbytes = sftp_read(file, buffer, sizeof(buffer))) > 0) { if (ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } errno = 0; if (fwrite(buffer, nbytes, 1, fp) != 1) { ftp_err(_("Error while writing to file: %s\n"), strerror(errno)); ftp->ti.ioerror = true; sftp_close(file); return -1; } ftp->ti.size += nbytes; if (hookf) { time_t now = time(NULL); if (now > then) { hookf(&ftp->ti); then = now; } } } if (nbytes < 0) { ftp_err(_("Error while reading from file: %s\n"), ssh_get_error(ftp->session)); r = -1; } sftp_close(file); return r; }
static int do_scp_read(ssh_scp scp, const char* infile, FILE* fp, getmode_t mode, ftp_transfer_func hookf) { time_t then = time(NULL) - 1; ftp_set_close_handler(); if (hookf) hookf(&ftp->ti); ftp->ti.begin = false; int rc = ssh_scp_pull_request(scp); if (rc != SSH_SCP_REQUEST_NEWFILE) { ftp_err(_("Failed to start scp download: %s\n"), ssh_get_error(ftp->session)); ssh_scp_close(scp); ssh_scp_free(scp); return -1; } size_t size = ssh_scp_request_get_size(scp); ssh_scp_accept_request(scp); /* read file */ char buffer[SSH_BUFSIZ]; int r = 0; while (size && (r = ssh_scp_read(scp, buffer, MIN(SSH_BUFSIZ, size))) != SSH_ERROR) { if (ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } errno = 0; if (fwrite(buffer, r, 1, fp) != 1) { ftp_err(_("Error while writing to file: %s\n"), strerror(errno)); ssh_scp_close(scp); ssh_scp_free(scp); return -1; } ftp->ti.size += r; if (hookf) { time_t now = time(NULL); if (now > then) { hookf(&ftp->ti); then = now; } } size -= r; } if (r == SSH_ERROR) { ftp_err(_("Error while reading from file: %s\n"), ssh_get_error(ftp->session)); r = -1; } else { r = ssh_scp_pull_request(scp); if (r != SSH_SCP_REQUEST_EOF) ftp_err(_("Unexpected request: %s %lu\n"), ssh_get_error(ftp->session), size); else r = 0; } ssh_scp_close(scp); ssh_scp_free(scp); return r; }
static int FILE_recv_ascii(Socket* in, FILE *out) { time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; sock_clearerr_in(in); clearerr(out); bool next = true; int nc = 0; while (true) { int c = 0; if (next) { c = sock_get(in); if (c == EOF) break; } else { c = nc; next = true; } if (ftp_sigints() > 0 || wait_for_input() != 0) break; if (c == '\n') ftp->ti.barelfs++; else if (c == '\r') { nc = sock_get(in); if (nc == EOF) break; if (nc != '\n') next = false; else c = nc; } if (fputc(c, out) == EOF) break; ftp->ti.size++; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } return maybe_abort_in(in, out); }