⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c.orig

📁 UNIX环境下命令行FTP/SFTP工具源代码
💻 ORIG
📖 第 1 页 / 共 3 页
字号:
    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 + -