/* 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; }
uint32_t proto_finish(proto_t* p) { if(p == NULL || p->target == NULL) return 0; sock_bookmark_write(p->target, p->bookmark, &p->prefix.length, sizeof(p->prefix.length)); return sock_flush(p->target); }
uint32_t proto_send(uint16_t header, sock_t* s) { prefix_t prefix; prefix.header = (header | MAGIC); prefix.length = 0; sock_write(s, &prefix, sizeof(prefix.header)); sock_write(s, &prefix.length, sizeof(prefix.length)); return sock_flush(s); }
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); }
/* 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; }
/* reads one line from server into ftp->reply * returns 0 on success or -1 on failure */ static int ftp_gets(void) { int c, i=0; ftp->reply[0] = 0; if(!sock_connected(ftp->ctrl)) { ftp_err(_("No control connection\n")); return -1; } while(true) { c = sock_get(ftp->ctrl); if(c == EOF) { ftp_err(_("Server has closed control connection\n")); ftp_close(); return -1; } else if(c == 255/*IAC*/) { /* handle telnet commands */ switch(c = sock_get(ftp->ctrl)) { case 251/*WILL*/: case 252/*WONT*/: c = sock_get(ftp->ctrl); sock_printf(ftp->ctrl, "%c%c%c", 255/*IAC*/, 254/*DONT*/, c); sock_flush(ftp->ctrl); break; case 253/*DO*/: case 254/*DONT*/: c = sock_get(ftp->ctrl); sock_printf(ftp->ctrl, "%c%c%c", 255/*IAC*/, 252/*WONT*/, c); sock_flush(ftp->ctrl); break; default: break; } continue; } else if(c == '\r') { c = sock_get(ftp->ctrl); if(c == 0) c = '\r'; else if(c == '\n') { ftp->reply[i++] = (char)c; break; } else if(c == EOF) /* do nothing */ ; else { /* telnet protocol violation, hmpf... */ sock_unget(ftp->ctrl, c); continue; } } else if(c == '\n') break; if(i < MAXREPLY) ftp->reply[i++] = (char)c; } if(i >= MAXREPLY) { ftp_err(_("Reply too long (truncated)\n")); i = MAXREPLY; } ftp->reply[i] = '\0'; ftp->fullcode = atoi(ftp->reply); #ifdef SECFTP { int r = 0; switch(ftp->fullcode) { /* handle protected responses 6xx */ case 631: r = sec_read_msg(ftp->reply, prot_safe); break; case 632: r = sec_read_msg(ftp->reply, prot_private); break; case 633: r = sec_read_msg(ftp->reply, prot_confidential); break; } if(r == -1) { ftp->fullcode = 0; ftp->code = vbNone; return 0; } else ftp->fullcode = atoi(ftp->reply); } #endif strip_trailing_chars(ftp->reply, "\n\r"); ftp->code = ftp->fullcode / 100; return ftp->fullcode; }
int fflush_net(SOCKET *s) { sock_flush(s); iferror return EOF; return 0; }
static int ftp_send(const char *path, FILE *fp, putmode_t how, transfer_mode_t mode, ftp_transfer_func hookf) { int r; long rp = ftp->restart_offset; ftp->restart_offset = 0L; if(how == putUnique && !ftp->has_stou_command) return -1; if (how == putTryUnique && !ftp->has_stou_command) how = putNormal; reset_transfer_info(); ftp->ti.transfer_is_put = true; if(ftp_init_transfer() != 0) return -1; ftp_type(mode); if(rp > 0) { /* fp is assumed to be fseek'd already */ ftp_cmd("REST %ld", rp); if(ftp->code != ctContinue) return -1; ftp->ti.size = rp; ftp->ti.restart_size = rp; } ftp_set_tmp_verbosity(vbError); switch (how) { case putAppend: ftp_cmd("APPE %s", path); break; case putTryUnique: case putUnique: ftp_cmd("STOU %s", path); if (ftp->fullcode == 502 || ftp->fullcode == 504) { ftp->has_stou_command = false; if (how == putTryUnique) how = putNormal; else break; } else break; default: ftp_cmd("STOR %s", path); break; } if(ftp->code != ctPrelim) return -1; if(how == putUnique) { /* try to figure out remote filename */ char *e = strstr(ftp->reply, " for "); if(e) { int l; e += 5; l = strlen(e); if(l) { free(ftp->ti.local_name); if(*e == '\'') ftp->ti.local_name = xstrndup(e+1, l-3); else ftp->ti.local_name = xstrndup(e, l-1); ftp_trace("parsed unique filename as '%s'\n", ftp->ti.local_name); } } } if(!sock_accept(ftp->data, "w", ftp_is_passive())) { ftp_err(_("data connection not accepted\n")); return -1; } ftp_cache_flush_mark_for(path); if(mode == tmBinary) r = FILE_send_binary(fp, ftp->data); else r = FILE_send_ascii(fp, ftp->data); sock_flush(ftp->data); sock_destroy(ftp->data); ftp->data = 0; if(r == 0) { transfer_finished(); ftp_read_reply(); ftp->ti.ioerror = (ftp->code != ctComplete); if(ftp->code != ctComplete) { ftp_trace("transfer failed\n"); return -1; } } else transfer_finished(); return 0; }
/* 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; }