📄 ftpsend.c
字号:
if(!ftp->ti.remote_name) ftp->ti.remote_name = xstrdup("remote");}int ftp_list(const char *cmd, const char *param, FILE *fp){ if(!cmd || !fp || !ftp_connected()) return -1; if(ftp->ssh_pid) return ssh_list(cmd, param, fp); reset_transfer_info(); foo_hookf = 0;#if 0 /* don't care about transfer type, binary should work well... */ ftp_type(tmAscii);#endif if(ftp_init_transfer() != 0) return -1; ftp_set_tmp_verbosity(vbNone); if(param) ftp_cmd("%s %s", cmd, param); else ftp_cmd("%s", cmd); if(ftp->code != ctPrelim) return -1; if(sock_accept(ftp->data, "r", ftp_is_passive()) != 0) { perror("accept()"); return -1; } if(FILE_recv_ascii(ftp->data->sin, fp) != 0) return -1; sock_destroy(ftp->data); ftp_read_reply(); ftp->data = 0; return ftp->code == ctComplete ? 0 : -1;}void transfer_finished(void){ ftp->ti.finished = true; if(foo_hookf) foo_hookf(&ftp->ti);}static int ftp_init_receive(const char *path, transfer_mode_t mode, ftp_transfer_func hookf){ long rp = ftp->restart_offset; char *e; ftp->restart_offset = 0L; foo_hookf = hookf; reset_transfer_info(); 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_cmd("RETR %s", path); if(ftp->code != ctPrelim) return -1; if(sock_accept(ftp->data, "r", ftp_is_passive()) != 0) { ftp_err(_("data connection not accepted\n")); return -1; } /* try to get the total file size */ { /* see if we have cached this directory/file */ rfile *f = ftp_cache_get_file(path); if(f) ftp->ti.total_size = f->size; else { /* try to figure out file size from RETR reply * Opening BINARY mode data connection for foo.mp3 (14429793 bytes) * ^^^^^^^^ aha! * * note: this might not be the _total_ filesize if we are RESTarting */ e = strstr(ftp->reply, " bytes"); if(e != 0) { while((e > ftp->reply) && isdigit((int)e[-1])) e--; ftp->ti.total_size = strtoul(e,NULL,10); } /* else we don't bother */ } } return 0;}static int ftp_do_receive(FILE *fp, transfer_mode_t mode, ftp_transfer_func hookf){ int r; if(mode == tmBinary) r = FILE_recv_binary(ftp->data->sin, fp); else r = FILE_recv_ascii(ftp->data->sin, fp); 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 (r == 0 && !ftp->ti.ioerror && !ftp->ti.interrupted) ? 0 : -1;}int ftp_receive(const char *path, FILE *fp, transfer_mode_t mode, ftp_transfer_func hookf){ if(ftp->ssh_pid) return ssh_do_receive(path, fp, mode, hookf); if(ftp_init_receive(path, mode, hookf) != 0) return -1; return ftp_do_receive(fp, mode, hookf);}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; 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 putUnique: ftp_cmd("STOU %s", path); if(ftp->fullcode == 502) ftp->has_stou_command = false; break; case putAppend: ftp_cmd("APPE %s", path); break; case putNormal: 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()) != 0) { 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->sin); else r = FILE_send_ascii(fp, ftp->data->sin); 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;}/* transfers SRCFILE on SRCFTP to DESTFILE on DESTFTP * using pasv mode on SRCFTP and port mode on DESTFTP * */int ftp_fxpfile(Ftp *srcftp, const char *srcfile, Ftp *destftp, const char *destfile, fxpmode_t how, transfer_mode_t mode){ int r; unsigned int old_reply_timeout; Ftp *thisftp; unsigned char addr[6];/* printf("FxP: %s -> %s\n", srcftp->url->hostname, destftp->url->hostname);*/ if(srcftp == destftp) { ftp_err(_("FxP between same hosts\n")); return -1; } if(ftp->ssh_pid) { ftp_err("FxP with SSH not implemented\n"); return -1; } thisftp = ftp; /* save currently active connection */ /* setup source side */ ftp_use(srcftp); ftp_type(mode); if(ftp_pasv(addr) != 0) { ftp_use(thisftp); return -1; } ftp->ti.total_size = -1; /* setup destination side */ ftp_use(destftp); ftp_type(mode); ftp_cmd("PORT %d,%d,%d,%d,%d,%d", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); if(ftp->code != ctComplete) { ftp_use(thisftp); return -1; } ftp->ti.total_size = -1; ftp_use(destftp); if(how == fxpResume) { rfile *f; f = ftp_get_file(destfile); if(f && f->size != (unsigned long long)-1) ftp->restart_offset = f->size; else { ftp->restart_offset = ftp_filesize(destfile); if(ftp->restart_offset == (unsigned long long)-1) { ftp_err(_("unable to get remote filesize of '%s'," " unable to resume\n"), destfile); ftp->restart_offset = 0L; } } } else ftp->restart_offset = 0L; if(ftp->restart_offset) { /* RESTart on destftp */ ftp_cmd("REST %ld", ftp->restart_offset); if(ftp->code != ctContinue) return -1; ftp_use(srcftp); ftp_cmd("REST %ld", ftp->restart_offset); if(ftp->code != ctContinue) return -1; } /* issue a STOR command on DESTFTP */ ftp_use(destftp); switch(how) { case fxpUnique: if(ftp->has_stou_command) { ftp_cmd("STOU %s", destfile); if(ftp->fullcode == 502) ftp->has_stou_command = false; } else { ftp->code = ctError; ftp->fullcode = 502; } break; case fxpAppend: ftp_cmd("APPE %s", destfile); break; case fxpNormal: default: ftp_cmd("STOR %s", destfile); break; } ftp_cache_flush_mark_for(destfile); if(ftp->code != ctPrelim) { ftp_use(thisftp); return -1; } /* issue a RETR command on SRCFTP */ ftp_use(srcftp); ftp_cmd("RETR %s", srcfile); if(ftp->code != ctPrelim) { ftp_use(destftp); ftp_abort(0); ftp_use(thisftp); return -1; } ftp_use(destftp); old_reply_timeout = ftp->reply_timeout; ftp_reply_timeout(0); ftp_read_reply(); ftp_reply_timeout(old_reply_timeout); r = (ftp->code == ctComplete ? 0 : -1); ftp_use(srcftp); old_reply_timeout = ftp->reply_timeout; ftp_reply_timeout(0); ftp_read_reply(); ftp_reply_timeout(old_reply_timeout); ftp_use(thisftp); return r;}int ftp_getfile(const char *infile, const char *outfile, getmode_t how, transfer_mode_t mode, ftp_transfer_func hookf){ FILE *fp; int r; struct stat statbuf; long rp = 0; int (*close_func)(FILE *fp); if(stat(outfile, &statbuf) == 0) { if(S_ISDIR(statbuf.st_mode)) { ftp_err(_("%s: is a directory\n"), outfile); return -1; } if(!(statbuf.st_mode & S_IWRITE)) { ftp_err(_("%s: permission denied\n"), outfile); return -1; } if(how == getResume) ftp->restart_offset = statbuf.st_size; } else ftp->restart_offset = 0L; ftp->ti.total_size = -1; /* we need to save this, because ftp_init_receive() sets it to zero */ rp = ftp->restart_offset; reset_transfer_info(); if(ftp->ssh_pid) { /* we need to stat the remote file, so we are sure we can read it * this needs to be done before we call ssh_do_receive, because by * then, the file is created, and would leave a zero-size file opon * failure */ Attrib *a = ssh_stat(infile); if(a == 0) { ftp_err(_("Unable to stat file '%s'\n"), infile); return -1; } /* FIXME: how can we check if it will be possible to transfer * the specified file? */ } else if(ftp_init_receive(infile, mode, hookf) != 0) return -1; if(how == getPipe) { fp = popen(outfile, "w"); close_func = pclose; } else { fp = fopen(outfile, (rp > 0L || (how == getAppend)) ? "a" : "w"); close_func = fclose; } if(!fp) { ftp_err("%s: %s\n", outfile, strerror(errno)); ftp->restart_offset = 0L; return -1; } if(rp > 0L) { if(fseeko(fp, rp, SEEK_SET) != 0) { ftp_err(_("%s: %s, transfer cancelled\n"), outfile, strerror(errno)); close_func(fp); ftp->restart_offset = 0L; return -1; } } free(ftp->ti.remote_name); free(ftp->ti.local_name); ftp->ti.remote_name = xstrdup(infile); ftp->ti.local_name = xstrdup(outfile); foo_hookf = hookf; if(ftp->ssh_pid) r = ssh_do_receive(infile, fp, mode, hookf); else r = ftp_do_receive(fp, mode, hookf); close_func(fp); return r;}int ftp_putfile(const char *infile, const char *outfile, putmode_t how, transfer_mode_t mode, ftp_transfer_func hookf){ FILE *fp; int r; struct stat statbuf; if(stat(infile, &statbuf) != 0) { perror(infile); return -1; } if(S_ISDIR(statbuf.st_mode)) { ftp_err(_("%s: is a directory\n"), infile); return -1; } fp = fopen(infile, "r"); if(fp == 0) { perror(infile); return -1; } ftp->ti.total_size = statbuf.st_size; free(ftp->ti.remote_name); free(ftp->ti.local_name); ftp->ti.remote_name = xstrdup(infile); /* actually local file, or _target_ */ ftp->ti.local_name = xstrdup(outfile); /* actually remote file, or _source_ */ if(how == putResume) { rfile *f; f = ftp_get_file(outfile); if(f && f->size != (unsigned long long)-1) ftp->restart_offset = f->size; else { ftp->restart_offset = ftp_filesize(outfile); if(ftp->restart_offset == (unsigned long long)-1) { ftp_err(_("unable to get remote filesize of '%s'," " unable to resume\n"), outfile); ftp->restart_offset = 0L; } } } else ftp->restart_offset = 0L; if(ftp->restart_offset > 0L) { if(fseeko(fp, ftp->restart_offset, SEEK_SET) != 0) { ftp_err(_("%s: %s, transfer cancelled\n"), outfile, strerror(errno)); fclose(fp); return -1; } } foo_hookf = hookf; if(ftp->ssh_pid) r = ssh_send(outfile, fp, how, mode, hookf); else r = ftp_send(outfile, fp, how, mode, hookf); fclose(fp); return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -