static bool ftp_pasv(bool ipv6, unsigned char* result, unsigned short* ipv6_port) { if (!ftp->has_pasv_command) { ftp_err(_("Host doesn't support passive mode\n")); return false; } ftp_set_tmp_verbosity(vbNone); /* request passive mode */ if (!ipv6) ftp_cmd("PASV"); #ifdef HAVE_IPV6 else if (ipv6) ftp_cmd("EPSV"); #endif else return false; if (!ftp_connected()) return false; if (ftp->code != ctComplete) { ftp_err(_("Unable to enter passive mode\n")); if(ftp->code == ctError) /* no use try it again */ ftp->has_pasv_command = false; return false; } const char* e = ftp_getreply(false); while (e && !isdigit((int)*e)) e++; if (!e) { ftp_err(_("Error parsing EPSV/PASV reply: '%s'\n"), ftp_getreply(false)); return false; } if (!ipv6) { if (sscanf(e, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", &result[0], &result[1], &result[2], &result[3], &result[4], &result[5]) != 6) { ftp_err(_("Error parsing PASV reply: '%s'\n"), ftp_getreply(false)); return false; } } #ifdef HAVE_IPV6 else { if (sscanf(e, "%hu", ipv6_port) != 1) { ftp_err(_("Error parsing EPSV reply: '%s'\n"), ftp_getreply(false)); return false; } } #endif return true; }
void cmd_chmod(int argc, char **argv) { int i; list *gl; listitem *li; OPT_HELP("Change permissions on remote file. Usage:\n" " chmod [options] <mode> <file>\n" "Options:\n" " -h, --help show this help\n" "<mode> is the permission mode, in octal (ex 644)\n"); minargs(optind + 1); need_connected(); need_loggedin(); gl = rglob_create(); for(i=optind+1; i<argc; i++) { stripslash(argv[i]); rglob_glob(gl, argv[i], true, true, NODOTDIRS); } for(li=gl->first; li; li=li->next) { if(ftp_chmod(((rfile *)li->data)->path, argv[optind]) != 0) printf("%s: %s\n", ((rfile *)li->data)->path, ftp_getreply(false)); } rglob_destroy(gl); }
static void ftp_print_reply(void) { verbose_t v = ftp_get_verbosity(); ftp_trace("<-- [%s] %s\n", ftp->url ? ftp->url->hostname : host_getname(ftp->host), ftp_getreply(true)); if(v >= vbCommand || (ftp->code >= ctTransient && v == vbError)) { if(v == vbDebug) fprintf(stderr, "<-- [%s] %s\n", ftp->url ? ftp->url->hostname : host_getname(ftp->host), ftp_getreply(true)); else fprintf(stderr, "%s\n", ftp_getreply(false)); } }
/* just gets the file SRC and store in local file DEST * doesn't parse any LIST output * returns 0 on success, else -1 */ static int do_the_get(const char *src, const char *dest, putmode_t how, unsigned opt) { char *fulldest; char *tmp; transfer_mode_t type; type = ascii_transfer(src) ? tmAscii : gvDefaultType; if(test(opt, GET_ASCII)) type = tmAscii; else if(test(opt, GET_BINARY)) type = tmBinary; tmp = getcwd(NULL, 0); if (tmp == (char *)NULL) return -1; fulldest = path_absolute(dest, tmp, 0); #if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux)) if(gvUseEnvString && ftp_connected()) setproctitle("%s, get %s", ftp->url->hostname, src); #endif int r = ftp_getfile(src, dest, how, type, test(opt, GET_VERBOSE) && !gvSighupReceived && !test(opt, GET_NOHUP) ? transfer : 0); if(r == 0 && (test(opt, GET_NOHUP) || gvSighupReceived)) { fprintf(stderr, "%s [%sb of ", src, human_size(ftp->ti.size)); fprintf(stderr, "%sb]\n", human_size(ftp->ti.total_size)); } if(test(opt, GET_NOHUP)) { if(r == 0) transfer_mail_msg(_("received %s\n"), src); else transfer_mail_msg(_("failed to receive %s: %s\n"), src, ftp_getreply(false)); } free(fulldest); #if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux)) if(gvUseEnvString && ftp_connected()) setproctitle("%s", ftp->url->hostname); #endif free(tmp); return r; }
void cmd_filetime(int argc, char **argv) { int i; OPT_HELP_NEW(_("Show modification time of remote file."), "filetime [options] <file>...", NULL); minargs(optind); need_connected(); need_loggedin(); for(i=optind;i<argc;i++) { time_t t = ftp_filetime(argv[i], true); if(t != (time_t) -1) printf("%s: %s", argv[i], ctime(&t)); else printf("%s\n", ftp_getreply(false)); } }
void cmd_filetime(int argc, char **argv) { int i; OPT_HELP("Show modification time of remote file. Usage:\n" " filetime [options] <file>...\n" "Options:\n" " -h, --help show this help\n"); minargs(optind); need_connected(); need_loggedin(); for(i=optind;i<argc;i++) { time_t t = ftp_filetime(argv[i]); if(t != (time_t) -1) printf("%s: %s", argv[i], ctime(&t)); else printf("%s\n", ftp_getreply(false)); } }
static int ftp_pasv(unsigned char result[6]) { int pa[6]; char *e; int i; if(!ftp->has_pasv_command) { ftp_err(_("Host doesn't support passive mode\n")); return -1; } ftp_set_tmp_verbosity(vbNone); /* request passive mode */ ftp_cmd("PASV"); if(!ftp_connected()) return -1; if(ftp->code != ctComplete) { ftp_err(_("Unable to enter passive mode\n")); if(ftp->code == ctError) /* no use try it again */ ftp->has_pasv_command = false; return -1; } e = ftp->reply + 4; while(!isdigit((int)*e)) e++; if(sscanf(e, "%d,%d,%d,%d,%d,%d", &pa[0], &pa[1], &pa[2], &pa[3], &pa[4], &pa[5]) != 6) { ftp_err(_("Error parsing PASV reply: '%s'\n"), ftp_getreply(false)); return -1; } for(i=0; i<6; i++) result[i] = (unsigned char)(pa[i] & 0xFF); return 0; }
static int do_the_fxp(Ftp *srcftp, const char *src, Ftp *destftp, const char *dest, fxpmode_t how, unsigned opt) { transfer_mode_t type; if(test(opt, FXP_NOHUP)) fprintf(stderr, "%s\n", src); type = ascii_transfer(src) ? tmAscii : gvDefaultType; if(test(opt, FXP_ASCII)) type = tmAscii; else if(test(opt, FXP_BINARY)) type = tmBinary; #if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux)) if(gvUseEnvString && ftp_connected()) setproctitle("%s, fxp %s", srcftp->url->hostname, src); #endif if(test(opt, FXP_VERBOSE)) { printf("%s\n", src); } const int r = ftp_fxpfile(srcftp, src, destftp, dest, how, type); #if 0 && (defined(HAVE_SETPROCTITLE) || defined(linux)) if(gvUseEnvString && ftp_connected()) setproctitle("%s", srcftp->url->hostname); #endif if(test(opt, FXP_NOHUP)) { if(r == 0) transfer_mail_msg(_("sent %s\n"), src); else transfer_mail_msg(_("failed to send %s: %s\n"), src, ftp_getreply(false)); } return r; }
/* returns: * 0 ok, remove file from list * -1 failure */ static int getfile(const rfile *fi, unsigned int opt, const char *output, const char *destname) { struct stat sb; char* dest = NULL; getmode_t how = getNormal; bool mkunique = false; int r, ret = -1; if((get_glob_mask && fnmatch(get_glob_mask, base_name_ptr(fi->path), FNM_EXTMATCH) == FNM_NOMATCH) #ifdef HAVE_REGEX || (get_rx_mask_set && regexec(&get_rx_mask, base_name_ptr(fi->path), 0, 0, 0) == REG_NOMATCH) #endif ) { return 0; } if(!output) output = "."; if(test(opt, GET_PARENTS)) { char *apath = base_dir_xptr(fi->path); if (asprintf(&dest, "%s%s/%s", output, apath, destname) == -1) { free(apath); fprintf(stderr, _("Failed to allocate memory.\n")); return -1; } free(apath); } else { /* check if -o option is given, if GET_OUTPUT_FILE is set, we only * transfer one file and output is set to the filename. However, if * the destination already exists and is a directory, we assume * that the user meant a directory */ int dest_is_file = test(opt, GET_OUTPUT_FILE); if(stat(output, &sb) == 0) { if(S_ISDIR(sb.st_mode)) { dest_is_file = false; } } if(dest_is_file) dest = xstrdup(output); else if (asprintf(&dest, "%s/%s", output, destname) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); return -1; } } /* make sure destination directory exists */ { char *destdir = base_dir_xptr(dest); if(destdir) { bool r = make_path(destdir); if(!r) { if (errno == EEXIST) ftp_err("`%s' exists but is not a directory\n", destdir); else ftp_err("%s: %s\n", destdir, strerror(errno)); transfer_mail_msg(_("Couldn't create directory: %s\n"), destdir); free(destdir); return -1; } /* change permission and group, if requested */ if(test(opt, GET_CHMOD)) { if(stat(destdir, &sb) == 0) { mode_t m = sb.st_mode; m = mode_adjust(m, cmod); if(chmod(destdir, m) != 0) perror(destdir); } } if(test(opt, GET_CHGRP)) { if(chown(destdir, -1, group_change) != 0) perror(dest); } free(destdir); } } /* check if destination file exists */ if(stat(dest, &sb) == 0) { if(test(opt, GET_SKIP_EXISTING)) { if(test(opt, GET_VERBOSE)) { char* sp = shortpath(dest, 42, gvLocalHomeDir); fprintf(stderr, _("Local file '%s' exists, skipping...\n"), sp); stats_file(STATS_SKIP, 0); free(sp); } return 0; } if(test(opt, GET_UNIQUE)) mkunique = true; else if(test(opt, GET_APPEND)) how = getAppend; else if(test(opt, GET_NEWER)) { struct tm *fan = gmtime(&sb.st_mtime); time_t ft = ftp_filetime(fi->path, test(opt, GET_FORCE_NEWER)); sb.st_mtime = gmt_mktime(fan); ftp_trace("get -n: remote file: %s", ctime(&ft)); ftp_trace("get -n: local file: %s\n", ctime(&sb.st_mtime)); if(sb.st_mtime >= ft && ft != (time_t)-1) { if(test(opt, GET_VERBOSE)) { char* sp = shortpath(dest, 30, gvLocalHomeDir); ftp_err(_( "Local file '%s' is newer than remote, skipping...\n"), sp); stats_file(STATS_SKIP, 0); free(sp); } return 0; } } else if(!test(opt, GET_RESUME)) { if(!get_owbatch && !gvSighupReceived) { struct tm *fan = gmtime(&sb.st_mtime); time_t ft = ftp_filetime(fi->path, test(opt, GET_FORCE_NEWER)); int a; char *e; sb.st_mtime = gmt_mktime(fan); e = xstrdup(ctime(&sb.st_mtime)); char* sp = shortpath(dest, 42, gvLocalHomeDir); a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME, ASKRESUME, _("Local file '%s' exists\nLocal: %lld bytes, %sRemote: %lld bytes, %sOverwrite?"), sp, (unsigned long long) sb.st_size, e ? e : "unknown date\n", ftp_filesize(fi->path), ctime(&ft)); free(sp); free(e); if(a == ASKCANCEL) { get_quit = true; return 0; } else if(a == ASKNO) return 0; else if(a == ASKUNIQUE) mkunique = true; else if(a == ASKALL) { get_owbatch = true; } else if(a == ASKRESUME) opt |= GET_RESUME; /* for this file only */ /* else a == ASKYES */ } } if(test(opt, GET_RESUME)) how = getResume; } if(mkunique) { char* newdest = make_unique_filename(dest); free(dest); dest = newdest; } /* the file doesn't exist or we choosed to overwrite it, or changed dest */ if(rislink(fi) && test(opt, GET_NO_DEREFERENCE)) { /* remove any existing destination */ unlink(dest); ftp_err(_("symlinking '%s' to '%s'\n"), dest, fi->link); if(symlink(fi->link, dest) != 0) perror(dest); ret = 0; } else { r = do_the_get(fi->path, dest, how, opt); if(r == 0) { stats_file(STATS_SUCCESS, ftp->ti.total_size); ret = 0; if(test(opt, GET_PRESERVE)) get_preserve_attribs(fi, dest); if(test(opt, GET_CHMOD)) { mode_t m = rfile_getmode(fi); m = mode_adjust(m, cmod); if(chmod(dest, m) != 0) perror(dest); } if(test(opt, GET_CHGRP)) { if(chown(dest, -1, group_change) != 0) perror(dest); } if(test(opt, GET_DELETE_AFTER)) { bool dodel = false; char* sp = shortpath(fi->path, 42, ftp->homedir); if(!test(opt, GET_FORCE) && !get_delbatch && !gvSighupReceived) { int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES, _("Delete remote file '%s'?"), sp); if(a == ASKALL) { get_delbatch = true; dodel = true; } else if(a == ASKCANCEL) get_quit = true; else if(a != ASKNO) dodel = true; } else dodel = true; if(dodel) { ftp_unlink(fi->path); if(ftp->code == ctComplete) fprintf(stderr, _("%s: deleted\n"), sp); else fprintf(stderr, _("error deleting '%s': %s\n"), sp, ftp_getreply(false)); } free(sp); } } else { stats_file(STATS_FAIL, 0); ret = -1; } } free(dest); return ret; }
static int fxpfile(const rfile *fi, unsigned int opt, const char *output, const char *destname) { fxpmode_t how = fxpNormal; bool file_exists = false; char *dest, *dpath; bool dir_created; char *dest_dir, *q_dest_dir; Ftp *thisftp = ftp; if((fxp_glob_mask && fnmatch(fxp_glob_mask, base_name_ptr(fi->path), 0) == FNM_NOMATCH) #ifdef HAVE_REGEX || (fxp_rx_mask_set && regexec(&fxp_rx_mask, base_name_ptr(fi->path), 0, 0, 0) == REG_NOMATCH) #endif ) return 0; if(!output) output = "."; if(test(opt, FXP_PARENTS)) { char *p = base_dir_xptr(fi->path); if (asprintf(&dest, "%s/%s/%s", output, p, base_name_ptr(fi->path)) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); free(p); return -1; } free(p); } else if(test(opt, FXP_OUTPUT_FILE)) dest = xstrdup(output); else if (asprintf(&dest, "%s/%s", output, base_name_ptr(fi->path)) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); return -1; } path_collapse(dest); ftp_use(fxp_target); /* make sure destination directory exists */ dpath = base_dir_xptr(dest); dest_dir = ftp_path_absolute(dpath); q_dest_dir = backslash_quote(dest_dir); int r = ftp_mkpath(q_dest_dir); free(q_dest_dir); free(dest_dir); if(r == -1) { transfer_mail_msg(_("Couldn't create directory: %s\n"), dest_dir); free(dpath); free(dest); ftp_use(thisftp); return -1; } dir_created = (r == 1); if(!dir_created && !test(opt, FXP_UNIQUE) && !test(opt, FXP_FORCE)) { rfile *f; f = ftp_get_file(dest); file_exists = (f != 0); if(f && risdir(f)) { /* can't overwrite a directory */ printf(_("%s: is a directory\n"), dest); free(dest); return 0; } } if(test(opt, FXP_APPEND)) { how = fxpAppend; } else if(file_exists) { if(test(opt, FXP_SKIP_EXISTING)) { char* sp = shortpath(dest, 42, ftp->homedir); printf(_("Remote file '%s' exists, skipping...\n"), sp); free(sp); free(dest); ftp_use(thisftp); return 0; } else if(test(opt, FXP_NEWER)) { time_t src_ft; time_t dst_ft; ftp_use(thisftp); src_ft = ftp_filetime(fi->path, test(opt, FXP_FORCE_NEWER)); ftp_use(fxp_target); dst_ft = ftp_filetime(dest, test(opt, FXP_FORCE_NEWER)); if(src_ft != (time_t)-1 && dst_ft != (time_t)-1 && dst_ft >= src_ft) { char* sp = shortpath(dest, 42, ftp->homedir); printf(_("Remote file '%s' is newer than local, skipping...\n"), sp); free(sp); free(dest); ftp_use(thisftp); return 0; } } else if(!test(opt, FXP_RESUME)) { if(!fxp_owbatch) { char* sp = shortpath(dest, 42, ftp->homedir); int a = ask(ASKYES|ASKNO|ASKUNIQUE|ASKCANCEL|ASKALL|ASKRESUME, ASKRESUME, _("File '%s' exists, overwrite?"), sp); free(sp); if(a == ASKCANCEL) { fxp_quit = true; free(dest); ftp_use(thisftp); return 0; } else if(a == ASKNO) { free(dest); ftp_use(thisftp); return 0; } else if(a == ASKUNIQUE) opt |= FXP_UNIQUE; /* for this file only */ else if(a == ASKALL) fxp_owbatch = true; else if(a == ASKRESUME) opt |= FXP_RESUME; /* for this file only */ /* else a == ASKYES */ } } } if(test(opt, FXP_RESUME)) how = fxpResume; if(test(opt, FXP_UNIQUE)) how = fxpUnique; r = do_the_fxp(thisftp, fi->path, fxp_target, dest, how, opt); free(dest); if(r != 0) { ftp_use(thisftp); return -1; } if(test(opt, FXP_PRESERVE)) fxp_preserve_attribs(fi, dest); if(test(opt, FXP_DELETE_AFTER)) { bool dodel = false; ftp_use(thisftp); if(!test(opt, FXP_FORCE) && !fxp_delbatch && !gvSighupReceived) { char* sp = shortpath(fi->path, 42, ftp->homedir); int a = ask(ASKYES|ASKNO|ASKCANCEL|ASKALL, ASKYES, _("Delete remote file '%s'?"), sp); free(sp); if(a == ASKALL) { fxp_delbatch = true; dodel = true; } else if(a == ASKCANCEL) fxp_quit = true; else if(a != ASKNO) dodel = true; } else dodel = true; if(dodel) { ftp_unlink(fi->path); char* sp = shortpath(fi->path, 42, ftp->homedir); if(ftp->code == ctComplete) fprintf(stderr, _("%s: deleted\n"), sp); else fprintf(stderr, _("error deleting '%s': %s\n"), sp, ftp_getreply(false)); free(sp); } } ftp_use(thisftp); return 0; }