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_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); }
void ftp_flush_reply(void) { if(!ftp_connected()) return; #ifdef HAVE_LIBSSH if (ftp->session) return; #endif /* ftp_set_signal(SIGINT, SIG_IGN);*/ fprintf(stderr, "flushing replies...\r"); /* ftp_reply_timeout(10);*/ while(ftp_connected()) { if (sock_check_pending(ftp->ctrl, false) == 1) ftp_read_reply(); else break; } #if 0 if(ftp_loggedin()) ftp_chdir(ftp->curdir); #endif ftp_set_close_handler(); }
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; }
void ftp_flush_reply(void) { fd_set ready; struct timeval poll; if(!ftp_connected()) return; #ifdef HAVE_LIBSSH if (ftp->session) return; #endif /* ftp_set_signal(SIGINT, SIG_IGN);*/ fprintf(stderr, "flushing replies...\r"); /* ftp_reply_timeout(10);*/ while(ftp_connected()) { poll.tv_sec = 1; poll.tv_usec = 0; FD_ZERO(&ready); int handle = sock_handle(ftp->ctrl); FD_SET(handle, &ready); if(select(handle+1, &ready, 0, 0, &poll) == 1) ftp_read_reply(); else break; } #if 0 if(ftp_loggedin()) ftp_chdir(ftp->curdir); #endif ftp_set_close_handler(); }
/* abort routine originally from Cftp by Dieter Baron */ int ftp_abort(Socket* fp) { char buf[4096]; #ifdef HAVE_LIBSSH if(ftp->session) /* FIXME: what? */ return 0; #endif if(!ftp_connected()) return -1; ftp_set_close_handler(); if (sock_check_pending(fp, false) == 1) { ftp_trace("There is data on the control channel, won't send ABOR\n"); /* read remaining bytes from connection */ while(fp && sock_read(fp, buf, sizeof(buf)) > 0) /* LOOP */ ; return 0; } ftp->ti.interrupted = true; ftp_err(_("Waiting for remote to finish abort...\n")); ftp_trace("--> telnet interrupt\n"); if(sock_telnet_interrupt(ftp->ctrl) != 0) ftp_err("telnet interrupt: %s\n", strerror(errno)); /* ftp_cmd("ABOR") won't work here, * we must flush data between the ABOR command and ftp_read_reply() */ sock_krb_printf(ftp->ctrl, "ABOR"); sock_printf(ftp->ctrl, "\r\n"); sock_flush(ftp->ctrl); if(ftp_get_verbosity() == vbDebug) ftp_err("--> [%s] ABOR\n", ftp->url->hostname); else ftp_trace("--> [%s] ABOR\n", ftp->url->hostname); /* read remaining bytes from connection */ while(fp && sock_read(fp, buf, sizeof(buf)) > 0) /* LOOP */ ; /* we expect a 426 or 226 reply here... */ ftp_read_reply(); if(ftp->fullcode != 426 && ftp->fullcode != 226) ftp_trace("Huh!? Expected a 426 or 226 reply\n"); /* ... and a 226 or 225 reply here, respectively */ /* FIXME: should skip this reply if prev. reply wasn't 426 or 226 ? */ ftp_read_reply(); if(ftp->fullcode != 226 && ftp->fullcode != 225) ftp_trace("Huh!? Expected a 226 or 225 reply\n"); return -1; }
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_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); }
/* sends an FTP command on the control channel * returns reply status code on success or -1 on error */ int ftp_cmd(const char *cmd, ...) { va_list ap; int resp; bool recon = false; if(!sock_connected(ftp->ctrl)) { ftp_err(_("No control connection\n")); ftp->code = ctNone; ftp->fullcode = -1; return -1; } ftp_set_abort_handler(); ugly: va_start(ap, cmd); sock_krb_vprintf(ftp->ctrl, cmd, ap); sock_printf(ftp->ctrl, "\r\n"); sock_flush(ftp->ctrl); va_end(ap); if(ferror(sock_sout(ftp->ctrl))) { ftp_err(_("error writing command")); ftp_err(" ("); va_start(ap, cmd); vfprintf(stderr, cmd, ap); va_end(ap); va_start(ap, cmd); ftp_vtrace(cmd, ap); va_end(ap); ftp_err(")\n"); ftp->code = ctNone; ftp->fullcode = -1; return -1; } va_start(ap, cmd); ftp_print_cmd(cmd, ap); va_end(ap); resp = ftp_read_reply(); ftp_set_close_handler(); if(resp == 421) { /* server is closing control connection! */ ftp_err(_("Server closed control connection\n")); if(gvAutoReconnect && ftp_loggedin() && strcasecmp(cmd, "QUIT") != 0) { if(recon) { ftp_err(_("Reconnect failed\n")); } else { ftp_err(_("Automatic reconnect...\n")); ftp_reopen(); recon = true; goto ugly; } } else { /* ftp_close();*/ ftp->fullcode = 421; ftp->code = 4; return -1; } } return resp; }
/* abort routine originally from Cftp by Dieter Baron */ int ftp_abort(FILE *fp) { char buf[4096]; fd_set ready; struct timeval poll; if(ftp->ssh_pid) /* FIXME: what? */ return 0; if(!ftp_connected()) return -1; ftp_set_close_handler(); poll.tv_sec = poll.tv_usec = 0; FD_ZERO(&ready); FD_SET(ftp->ctrl->handle, &ready); if(select(ftp->ctrl->handle+1, &ready, 0, 0, &poll) == 1) { ftp_trace("There is data on the control channel, won't send ABOR\n"); /* read remaining bytes from connection */ while(fp && fread(buf, 1, 4096, fp) > 0) /* LOOP */ ; return 0; } ftp->ti.interrupted = true; ftp_err(_("Waiting for remote to finish abort...\n")); ftp_trace("--> telnet interrupt\n"); if(sock_telnet_interrupt(ftp->ctrl) != 0) ftp_err("telnet interrupt: %s\n", strerror(errno)); /* ftp_cmd("ABOR") won't work here, * we must flush data between the ABOR command and ftp_read_reply() */ sock_krb_printf(ftp->ctrl, "ABOR"); sock_printf(ftp->ctrl, "\r\n"); sock_flush(ftp->ctrl); if(ftp_get_verbosity() == vbDebug) ftp_err("--> [%s] ABOR\n", ftp->url->hostname); else ftp_trace("--> [%s] ABOR\n", ftp->url->hostname); /* read remaining bytes from connection */ while(fp && fread(buf, 1, 4096, fp) > 0) /* LOOP */ ; /* we expect a 426 or 226 reply here... */ ftp_read_reply(); if(ftp->fullcode != 426 && ftp->fullcode != 226) ftp_trace("Huh!? Expected a 426 or 226 reply\n"); /* ... and a 226 or 225 reply here, respectively */ /* FIXME: should skip this reply if prev. reply wasn't 426 or 226 ? */ ftp_read_reply(); if(ftp->fullcode != 226 && ftp->fullcode != 225) ftp_trace("Huh!? Expected a 226 or 225 reply\n"); return -1; }