📄 ftp.c.orig
字号:
if(ftp->ssh_pid) return ssh_chmod(path, mode); if(ftp->has_site_chmod_command) { ftp_set_tmp_verbosity(vbNone); ftp_cmd("SITE CHMOD %s %s", mode, path); if(ftp->fullcode == 502) ftp->has_site_chmod_command = false; if(ftp->code == ctComplete) { ftp_cache_flush_mark_for(path); return 0; } } else ftp_err(_("Server doesn't support SITE CHMOD\n")); return -1;}void ftp_reply_timeout(unsigned int secs){ ftp->reply_timeout = secs;}int ftp_idle(const char *idletime){ if(ftp->ssh_pid) return ssh_idle(idletime); if(!ftp->has_site_idle_command) { ftp_err(_("Server doesn't support SITE IDLE\n")); return -1; } ftp_set_tmp_verbosity(vbCommand); if(idletime) ftp_cmd("SITE IDLE %s", idletime); else ftp_cmd("SITE IDLE"); if(ftp->fullcode == 502) ftp->has_site_idle_command = false; return ftp->code == ctComplete ? 0 : -1;}int ftp_noop(void){ if(ftp->ssh_pid) return ssh_noop(); ftp_set_tmp_verbosity(vbCommand); ftp_cmd("NOOP"); return ftp->code == ctComplete ? 0 : -1;}int ftp_help(const char *arg){ if(ftp->ssh_pid) return ssh_help(arg); ftp_set_tmp_verbosity(vbCommand); if(arg) ftp_cmd("HELP %s", arg); else ftp_cmd("HELP"); return ftp->code == ctComplete ? 0 : -1;}unsigned long long ftp_filesize(const char *path){ unsigned long long ret; if(ftp->ssh_pid) return ssh_filesize(path); if(!ftp->has_size_command) return -1; if(ftp_type(tmBinary) != 0) return -1; ftp_set_tmp_verbosity(vbError); ftp_cmd("SIZE %s", path); if(ftp->fullcode == 502) { ftp->has_size_command = false; return -1; } if(ftp->code == ctComplete) { sscanf(ftp->reply, "%*s %llu", &ret); return ret; } return -1;}rdirectory *ftp_read_directory(const char *path){ FILE *fp = 0; rdirectory *rdir; bool is_curdir = false; char *tmpfilename, *e; bool _failed = false; char *dir; bool is_mlsd = false; if(ftp->ssh_pid) return ssh_read_directory(path); dir = ftp_path_absolute(path); stripslash(dir); is_curdir = (strcmp(dir, ftp->curdir) == 0); asprintf(&e, "%s/yafclist.tmp", gvWorkingDirectory); tmpfilename = make_unique_filename(e); free(e); fp = fopen(tmpfilename, "w+"); if(fp == 0) { /* can't create a tmpfile in ~/.yafc, try in /tmp/ */ tmpfilename = make_unique_filename("/tmp/yafclist.tmp"); fp = fopen(tmpfilename, "w+"); if(fp == 0) { ftp_err("%s: %s\n", tmpfilename, strerror(errno)); free(dir); free(tmpfilename); return 0; } } fchmod(fileno(fp), S_IRUSR | S_IWUSR); /* we do a "CWD" before the listing, because: we want a listing of * the directory contents, not the directory itself, and some * servers misunderstand this. If the target is a link to a * directory, we have to do this. */ if(!is_curdir) { ftp_cmd("CWD %s", dir); if(ftp->code != ctComplete) goto failed; } if(ftp->has_mlsd_command) { is_mlsd = true;#if 0 /* PureFTPd (1.0.11) doesn't recognize directory arguments * with spaces, not even quoted, it just chops the argument * string after the first space, duh... so we have to CWD to * the directory... */ char *asdf; asprintf(&asdf, "%s/", dir); /* Hack to get around issue in PureFTPd (up to version 0.98.2): * doing a 'MLSD link-to-dir' on PureFTPd closes the control * connection, however, 'MLSD link-to-dir/' works fine. */ _failed = (ftp_list("MLSD", asdf, fp) != 0); free(asdf);#else _failed = (ftp_list("MLSD", 0, fp) != 0);#endif if(_failed && ftp->code == ctError) ftp->has_mlsd_command = false; } if(!ftp->has_mlsd_command) { _failed = (ftp_list("LIST", 0, fp) != 0); is_mlsd = false; } if(!is_curdir) ftp_cmd("CWD %s", ftp->curdir); if(_failed) goto failed; rewind(fp); rdir = rdir_create(); if(rdir_parse(rdir, fp, dir, is_mlsd) != 0) { rdir_destroy(rdir); goto failed; } fclose(fp); ftp_trace("added directory '%s' to cache\n", dir); list_additem(ftp->cache, rdir); free(dir); unlink(tmpfilename); free(tmpfilename); return rdir; failed: /* forgive me father, for I have goto'ed */ free(dir); if(fp) fclose(fp); unlink(tmpfilename); free(tmpfilename); return 0;}rdirectory *ftp_get_directory(const char *path){ rdirectory *rdir; char *ap; ap = ftp_path_absolute(path); stripslash(ap); rdir = ftp_cache_get_directory(ap); if(!rdir) rdir = ftp_read_directory(ap); free(ap); return rdir;}/* returns the rfile at PATH * if it's not in the cache, reads the directory * returns 0 if not found */rfile *ftp_get_file(const char *path){ rfile *f; char *ap; if(!path) return 0; ap = ftp_path_absolute(path); stripslash(ap); f = ftp_cache_get_file(ap); if(!f) { char *p = base_dir_xptr(ap); rdirectory *rdir = ftp_get_directory(p); free(p); if(rdir) f = rdir_get_file(rdir, base_name_ptr(ap)); } free(ap); return f;}/* returns true if path A is part of path B */static bool ftp_path_part_of(const char *a, const char *b){ size_t alen; if(!a || !b) return false; alen = strlen(a); /* see if a and b are equal to the length of a */ if(strncmp(a, b, alen) == 0) { /* see if the last directory in b is complete */ if(strlen(b) >= alen) { char c = b[alen]; if(c == 0 || c == '/') {/* ftp_trace("directory %s already created\n", a);*/ return true; } } } return false;}/* creates path (and all elements in path) * PATH should be an absolute path * returns -1 on error, 0 if no directories created, else 1 */int ftp_mkpath(const char *path){ bool one_created = false; char *p, *orgp, *e = 0; if(!path) return 0; /* check if we already has created this path */ if(ftp_path_part_of(path, ftp->last_mkpath)) return 0; /* check if this path is a part of current directory */ if(ftp_path_part_of(path, ftp->curdir)) return 0; orgp = p = xstrdup(path); path_collapse(p); unquote(p); if(*p == '/') { e = (char *)xmalloc(1); *e = 0; } while(true) { char *tmp, *foo; tmp = strqsep(&p, '/'); if(!tmp) break; if(e) asprintf(&foo, "%s/%s", e, tmp); else foo = xstrdup(tmp); free(e); e = foo; /* check if we already has created this path */ if(ftp_path_part_of(e, ftp->last_mkpath)) continue; /* check if this path is a part of current directory */ if(ftp_path_part_of(e, ftp->curdir)) continue; if(strcmp(e, ".") != 0) { ftp_mkdir_verb(e, vbNone); one_created = (ftp->code == ctComplete); } } free(ftp->last_mkpath); ftp->last_mkpath = path_absolute(path, ftp->curdir, ftp->homedir); free(e); free(orgp); return one_created;}char *ftp_path_absolute(const char *path){ return path_absolute(path, ftp->curdir, ftp->homedir);}void ftp_flush_reply(void){ fd_set ready; struct timeval poll; if(!ftp_connected()) return; if(ftp->ssh_pid) return;/* 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); FD_SET(ftp->ctrl->handle, &ready); if(select(ftp->ctrl->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();}int ftp_rename(const char *oldname, const char *newname){ char *on; char *nn; if(ftp->ssh_pid) return ssh_rename(oldname, newname); on = xstrdup(oldname); stripslash(on); ftp_cmd("RNFR %s", on); if(ftp->code != ctContinue) { free(on); return -1; } nn = xstrdup(newname); stripslash(nn); ftp_cmd("RNTO %s", nn); if(ftp->code != ctComplete) { free(on); free(nn); return -1; } ftp_cache_flush_mark_for(on); ftp_cache_flush_mark_for(nn); return 0;}/*** Function: bool isLeapYear(int y)**** Description: Local routine used by gmt_mktime() below to determine** which years are leap years.**** Returns; true or false.*/static bool isLeapYear(int y){ return (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0));}/*** Function: time_t gmt_mktime(const struct tm *ts)**** Description: Local routine used by ftp_filetime to convert a struct tm** to a GMT time_t. mktime() is useless since it assumes** struct tm is a local time.**** Returns; Either -1 upon failure or the GMT time_t** time upon success.*//* contributed by Charles Box */time_t gmt_mktime(const struct tm *ts){ const int SECS_MIN = 60; const int SECS_HOUR = SECS_MIN * 60; const int SECS_DAY = SECS_HOUR * 24; const int SECS_YEAR = SECS_DAY * 365; const int daysPerMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const int leapDaysPerMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; const int *maxDaysInMonth = daysPerMonth; time_t gmt = -1; int y, m; /* watch out for bogus date!!! */ if (!ts) return gmt; else if (ts->tm_year < 70 || ts->tm_year > 138) return gmt; else if (ts->tm_mon < 0 || ts->tm_mon > 11) return gmt; if (isLeapYear(ts->tm_year + 1900)) maxDaysInMonth = leapDaysPerMonth; if (ts->tm_mday < 1 || ts->tm_mday > maxDaysInMonth[ts->tm_mon]) return gmt; else if (ts->tm_hour < 0 || ts->tm_hour > 23) return gmt; else if (ts->tm_min < 0 || ts->tm_min > 59) return gmt; else if (ts->tm_sec < 0 || ts->tm_sec > 59) return gmt; /* add in # secs for years past */ gmt = (ts->tm_year - 70) * SECS_YEAR; /* add in # leap year days not including this year! */ for (y = 1970; y < (ts->tm_year + 1900); ++y) { if (isLeapYear(y)) gmt += SECS_DAY; } /* add in secs for all months this year excluding this month */ for (m = 0; m < ts->tm_mon; ++m) gmt += maxDaysInMonth[m] * SECS_DAY; /* add in secs for all days this month excluding today */ gmt += (ts->tm_mday - 1) * SECS_DAY; /* add in hours today */ gmt += ts->tm_hour * SECS_HOUR; /* add in minutes today */ gmt += ts->tm_min * SECS_MIN; /* add in secs today */ gmt += ts->tm_sec; return gmt;}/*** Function: time_t ftp_filetime(const char *filename)**** Description: User routine for attempting to obtain a remote file's** modification time in Universal Coordinated Time (GMT).**** Returns; Either -1 upon failure or the time_t file modification** time upon success.*/time_t ftp_filetime(const char *filename){ struct tm ts; if(!ftp_connected()) return -1; if(ftp->ssh_pid) return ssh_filetime(filename); if(!ftp->has_mdtm_command) return -1; memset(&ts, 0, sizeof(ts)); ftp_set_tmp_verbosity(vbNone); ftp_cmd("MDTM %s", filename); if (ftp->fullcode == 202) { ftp->has_mdtm_command = false; return -1; } if (ftp->fullcode != 213) return -1; /* time is Universal Coordinated Time */ sscanf(ftp->reply, "%*s %04d%02d%02d%02d%02d%02d", &ts.tm_year, &ts.tm_mon, &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); ts.tm_year -= 1900; ts.tm_mon--; return gmt_mktime(&ts);}int ftp_maybe_isdir(rfile *fp){ if(risdir(fp)) return 1; if(rislink(fp)) { /* found a link; if the link is in the cache, * check if it's a directory, else we don't * read the directory just to check if it's a * directory */ char *adir = base_dir_xptr(fp->path); char *ap = path_absolute(fp->link, adir, ftp->homedir); rfile *lnfp = ftp_cache_get_file(ap); free(adir); free(ap); if(lnfp) return risdir(lnfp) ? 1 : 0; else /* return maybe ;-) */ return 2; } return 0;}void ftp_pwd(void){ if(ftp->ssh_pid) { ssh_pwd(); return; } ftp_set_tmp_verbosity(vbCommand); ftp_cmd("PWD");}char *perm2string(int perm){ char *attr = (char *)xmalloc(11); strcpy(attr, "----------"); if(S_ISDIR(perm)) attr[0] = 'd'; else if(S_ISLNK(perm)) attr[0] = 'l'; else if(S_ISCHR(perm)) attr[0] = 'c'; else if(S_ISBLK(perm)) attr[0] = 'b'; else if(S_ISFIFO(perm)) attr[0] = 'p'; else if(S_ISSOCK(perm)) attr[0] = 's'; if(test(perm, S_IRUSR)) attr[1] = 'r'; if(test(perm, S_IWUSR)) attr[2] = 'w'; if(test(perm, S_IXUSR)) { if(test(perm, S_ISUID)) attr[3] = 's'; else attr[3] = 'x'; } else if(test(perm, S_ISUID)) attr[3] = 'S'; if(test(perm, S_IRGRP)) attr[4] = 'r'; if(test(perm, S_IWGRP)) attr[5] = 'w'; if(test(perm, S_IXGRP)) { if(test(perm, S_ISGID)) attr[6] = 's'; else attr[6] = 'x'; } else if(test(perm, S_ISGID)) attr[6] = 'S'; if(test(perm, S_IROTH)) attr[7] = 'r'; if(test(perm, S_IWOTH)) attr[8] = 'w'; if(test(perm, S_IXOTH)) { if(test(perm, S_ISVTX)) attr[9] = 't'; else attr[9] = 'x'; } else if(test(perm, S_ISVTX)) attr[9] = 'T'; return attr;}void ftp_get_feat(void){/* ftp_cmd("FEAT");*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -