📄 cmdftp.c
字号:
return rv;}int local_file(char* name) { struct stat buf; if (stat(name, &buf) != 0) return FILE_NEXIST; return (S_ISREG(buf.st_mode) ? FILE_ISREG : S_ISDIR(buf.st_mode) ? FILE_ISDIR : FILE_OTHER);}int local_fetch_list(char* filemask, struct list_data* d) { char* fn_mask[3], *tmpmask; struct dirent* entry; DIR* dir; int rv = 0; if (*filemask == 0) tmpmask = my_strdup("*"); else tmpmask = my_strdup(filemask); canonized_fn(fn_mask, tmpmask); if (!(dir = opendir(filemask ? fn_mask[0] : "."))) goto end_proc; while ((entry = readdir(dir))) { if (fnmatch(fn_mask[1], entry->d_name, 0) == 0) { char* full_name = fullpath(fn_mask[0], entry->d_name); store_list(clean_fn(full_name), d); free(full_name); } } closedir(dir); rv = 1; end_proc: free(tmpmask); free_fn(fn_mask); return rv;}int local_fetch_pretty_list(struct list_data* d) { int pipe_fd[2]; FILE* target; char line[CMD_BUF_SIZE]; if (pipe(pipe_fd) < 0) return 0; if (!cmdftp_execute("/bin/ls -l", 0, -1, pipe_fd[1])) { close(pipe_fd[0]); close(pipe_fd[1]); return local_fetch_list("", d); } close(pipe_fd[1]); if (!(target = fdopen(pipe_fd[0], "r"))) { close(pipe_fd[0]); return 0; } while (fgets(line, CMD_BUF_SIZE, target)) { size_t len = strlen(line); if (line[len - 1] == '\n') line[len - 1] = 0; store_pretty_list(line, d); } fclose(target); return 1;}off_t local_size(FILE* f) { off_t rv; fseeko(f, 0, SEEK_END); rv = ftello(f); fseeko(f, 0, SEEK_SET); return rv;}int local_print(char* arg) { if (env[CMDFTP_ENV_PAGER]) return cmdftp_execute(env[CMDFTP_ENV_PAGER], arg, -1, -1); else { FILE* f; int c; if (!(f = fopen(arg, "r"))) { cmdftp_war(CMDFTP_WAR_OPEN, arg); return 0; } while ((c = getc(f)) != EOF) fputc(c, stdout); fputc('\n', stdout); fclose(f); } return 1;}int local_edit(char* arg) { return cmdftp_execute(env[CMDFTP_ENV_EDITOR], arg, -1, -1);}/***************************************************//* REMOTE MODE SPECIFIC UTILITY FUNCTIONS: remote_ *//***************************************************/int remote_chdir(char* arg) { return remote_chdir_aux(arg, 0);}int remote_chdir_aux(char* arg, char suppress_err) { /* watch the return value! */ int rv; snprintf(cmd_buffer, CMD_BUF_SIZE, "CWD %s", arg); if (!(rv = send_command(cmd_buffer, suppress_err))) return -2; /* bad err, intr */ if (rv == 250) return 0; /* ok */ return -1; /* fail */}int remote_mkdir(char* arg) { snprintf(cmd_buffer, CMD_BUF_SIZE, "MKD %s", arg); return (send_command(cmd_buffer, 0) == 257);}int remote_rmdir(char* arg) { snprintf(cmd_buffer, CMD_BUF_SIZE, "RMD %s", arg); return (send_command(cmd_buffer, 0) == 250);}char* remote_getcwd(void) { char* start, *end; if (!send_command("PWD", 1)) return 0; if ((end = strrchr(cmd_buffer, '"')) == 0 || (start = strchr(cmd_buffer, '"')) == 0) return 0; *end = 0; start++; return start;}int remote_copy(char* target, char* source) { FILE* t; char* t_fn; int rv = 0; if (!(t = cmdftp_temp(&t_fn))) { cmdftp_war(CMDFTP_WAR_TEMP, t_fn); return 0; } if (download(t, source) && upload(target, t)) rv = 1; fclose(t); unlink(t_fn); free(t_fn); return rv;}int remote_move(char* to, char* from) { snprintf(cmd_buffer, CMD_BUF_SIZE, "RNFR %s", from); if (send_command(cmd_buffer, 0) != 350) return 0; snprintf(cmd_buffer, CMD_BUF_SIZE, "RNTO %s", to); if (send_command(cmd_buffer, 0) != 250) return 0; return 1;}int remote_unlink(char* arg) { snprintf(cmd_buffer, CMD_BUF_SIZE, "DELE %s", arg); return (send_command(cmd_buffer, 0) == 250);}int remote_file(char* name) { off_t size; int rv; rv = remote_chdir_aux(name, 1); if (rv == 0) { /* ok */ return do_home(CMDFTP_REMOTE) ? FILE_ISDIR : -1; } else if (rv == -2) { /* bad err, intr */ do_home(CMDFTP_REMOTE); return -2; } else /* (rv == -1) */ if ((size = remote_size(name)) >= 0) { return FILE_ISREG; } else if (size == -1) { return FILE_NEXIST; } else /* (size == -2) */ { return -1; }}int remote_fetch_list(char* filemask, struct list_data* d) { return remote_fetch_list_aux(filemask, d, 0);}int remote_fetch_pretty_list(struct list_data* d) { return remote_fetch_list_aux(0, d, 1);}int remote_fetch_list_aux(char* filemask, struct list_data* d, char pretty) { char* tmpmask, *fn_mask[3], *line; int tmp, rv = 0;#ifdef CMDFTP_LIST_HACK int hack = 0;#endif int port; if (filemask) { if (*filemask == 0) tmpmask = my_strdup("*"); else tmpmask = my_strdup(filemask); canonized_fn(fn_mask, tmpmask); } start_transfer: if (!send_command("TYPE A", 0)) goto end_proc; if (!(port = getport())) goto end_proc; if (!(cmdftp_data = cmdftp_connect(port))) goto end_proc;#ifdef CMDFTP_LIST_HACK if (filemask) { hack = 1; if (remote_chdir(fn_mask[0]) != 0) goto end_proc; } sprintf(cmd_buffer, pretty ? "LIST" : "NLST");#else if (filemask) { snprintf(cmd_buffer, CMD_BUF_SIZE, pretty ? "LIST %s" : "NLST %s", fn_mask[0]); } else { sprintf(cmd_buffer, pretty ? "LIST" : "NLST"); }#endif /* CMDFTP_LIST_HACK */ if ((tmp = (send_command(cmd_buffer, 1))) != 150) { close(cmdftp_data); if (tmp == 450) rv = 1; goto end_proc; } reset_cmd_buffer(); transfer_interrupted = TRAN_INTR_NO; while ((line = recv_line(cmdftp_data))) { if (!pretty) { char* fn; if (!(fn = strrchr(line, '/'))) fn = line; else fn++; if (!filemask || fnmatch(fn_mask[1], fn, 0) == 0) { char* full_name = filemask ? fullpath(fn_mask[0], fn) : fn; store_list(clean_fn(full_name), d); if (filemask) free(full_name); } } else { store_pretty_list(line, d); } } close(cmdftp_data); if TRANSFER_INTERRUPTED_CHECK("data transfer", 1); else { if (!recv_confirm()) cmdftp_war(CMDFTP_WAR_NOCT, ""); else rv = 1; } end_proc: if (filemask) { free(tmpmask); free_fn(fn_mask); }#ifdef CMDFTP_LIST_HACK if (hack) { rv = (remote_chdir(cwd[CMDFTP_REMOTE]) == 0) && rv; }#endif return rv;} off_t remote_size(char* filename) { off_t size; int rv; snprintf(cmd_buffer, CMD_BUF_SIZE, "SIZE %s", filename); if (!(rv = send_command(cmd_buffer, 1))) return -2; else if (rv != 213) return -1; sscanf(cmd_buffer + 4, OFF_FMT, &size); return size;}int remote_print(char* arg) { int c; char* fn; FILE* f; int rv = 0; if (!(f = cmdftp_temp(&fn))) { cmdftp_war(CMDFTP_WAR_TEMP, fn); return 0; } if (download(f, arg)) { if (env[CMDFTP_ENV_PAGER]) { fclose(f); f = 0; rv = cmdftp_execute(env[CMDFTP_ENV_PAGER], fn, -1, -1); } else { fseeko(f, 0, SEEK_SET); while ((c = getc(f)) != EOF) fputc(c, stdout); fputc('\n', stdout); rv = 1; } } if (f) fclose(f); unlink(fn); free(fn); return rv;}int remote_edit(char* arg) { char* fn; FILE* f; int rv = 0; if (!(f = cmdftp_temp(&fn))) { cmdftp_war(CMDFTP_WAR_TEMP, fn); return 0; } if (download(f, arg)) { fclose(f); f = 0; if (cmdftp_execute(env[CMDFTP_ENV_EDITOR], fn, -1, -1)) { if ((f = fopen(fn, "r")) && upload(arg, f)) rv = 1; } } if (f) fclose(f); unlink(fn); free(fn); return rv;}/***********************************//* COMPOSITE ACTIONS: do_ *//***********************************/int do_home(int mode) { /* home to current directory of mode */ if (mf[mode][MODE_CHDIR](cwd[mode]) == 0) return 1; /* ok */ else if (mf[mode][MODE_CHDIR](cwd[mode]) == 0) return 0; /* ok, but stop current op */ else cmdftp_err(CMDFTP_ERR_PWD, ""); return 0; /* never reached */}int do_copy_dir(char* target_dir, char* source_mask) { struct list_data d; int i, rv; if ((rv = mf[mode][MODE_FILE](target_dir)) == FILE_NEXIST) { if (!mf[mode][MODE_MKDIR](target_dir)) return 0; } else if (rv != FILE_ISDIR) { return 0; } init_list(&d); if (!mf[mode][MODE_FETCH_LIST](source_mask, &d)) return 0; if (d.count == 0) return 1; /* nothing to do but ok */ rv = 1; for (i = 0; i < d.count; i++) { char* target; int st, tt; target = fullpath(target_dir, d.data[i].basename); if ((tt = mf[mode][MODE_FILE](target)) < 0 || (st = mf[mode][MODE_FILE](d.data[i].fullname)) < 0) { rv = 0; } else if (tt == FILE_OTHER || (st == FILE_ISDIR && tt == FILE_ISREG) || (st == FILE_ISREG && tt == FILE_ISDIR) || (st != FILE_ISREG && st != FILE_ISDIR)) { cmdftp_war(CMDFTP_WAR_SKIP, d.data[i].fullname); } else if (st == FILE_ISREG) { if (!(rv = mf[mode][MODE_COPY](target, d.data[i].fullname))) rv = 0; } else /* (st == FILE_ISDIR) */ { char* new_source = fullpath(d.data[i].fullname, "*"); if (!do_copy_dir(target, new_source)) rv = 0; free(new_source); } free(target); if (!rv) break; } free_list(&d); return rv;}int do_move_dir(char* target_dir, char* source_mask) { struct list_data d; int i, rv; init_list(&d); if (!mf[mode][MODE_FETCH_LIST](source_mask, &d)) return 0; if (d.count == 0) return 1; /* nothing to do but ok */ rv = 1; for (i = 0; i < d.count; i++) { char* target; int st, tt; target = fullpath(target_dir, d.data[i].basename); if ((tt = mf[mode][MODE_FILE](target)) < 0 || (st = mf[mode][MODE_FILE](d.data[i].fullname)) < 0) { rv = 0; } else if (tt == FILE_ISDIR || tt == FILE_OTHER || (st == FILE_ISDIR && tt == FILE_ISREG) || (st != FILE_ISREG && st != FILE_ISDIR)) { cmdftp_war(CMDFTP_WAR_SKIP, d.data[i].fullname); } else { if (!mf[mode][MODE_MOVE](target, d.data[i].fullname)) rv = 0; } free(target); if (!rv) break; } free_list(&d); return rv;}int cmd_cp(char** paths) { struct list_data ld; char* source[3]; char* target[3]; int source_type, target_type; int rv = 0; if (*paths[0] == 0 || *paths[1] == 0) { cmdftp_war(CMDFTP_WAR_MARG, ""); return 0; } canonized_fn(source, paths[0]); canonized_fn(target, paths[1]); init_list(&ld); if (!mf[mode][MODE_FETCH_LIST](source[2], &ld)) goto end_proc; if (ld.count == 0) { cmdftp_war(CMDFTP_WAR_MASK, paths[0]); rv = 1; goto end_proc; } if ((target_type = mf[mode][MODE_FILE](target[2])) < 0) goto end_proc; if (ld.count == 1) { if ((source_type = mf[mode][MODE_FILE](ld.data[0].fullname)) < 0) goto end_proc; else if (source_type == FILE_ISREG) { /* source is a single regular file */ if (target_type == FILE_NEXIST || target_type == FILE_ISREG) { rv = mf[mode][MODE_COPY](target[2], ld.data[0].fullname); } else if (target_type == FILE_ISDIR) { char* new_target = fullpath(target[2], ld.data[0].basename); free(target[2]); target[2] = new_target; rv = mf[mode][MODE_COPY](target[2], ld.data[0].fullname); } else { cmdftp_war(CMDFTP_WAR_TRG, "exists (not a regfile or a dir)"); } } else if (source_type == FILE_ISDIR) { /* source is a single directory */ if (target_type == FILE_ISDIR) { rv = do_copy_dir(target[2], ld.data[0].fullname); } else { char* new_source = fullpath(ld.data[0].fullname, "*"); rv = do_copy_dir(target[2], new_source); free(new_source); } } else { cmdftp_war(CMDFTP_WAR_SRC, "not a regular file or a dir"); } } else if (target_type == FILE_ISDIR) { /* source is multiple entries, target is an existing directory */ rv = do_copy_dir(target[2], source[2]); } else { cmdftp_war(CMDFTP_WAR_TRG, "multiple source needs a dir target"); } end_proc: free_list(&ld); free_fn(source); free_fn(target); return rv;}int cmd_mv(char** paths) { struct list_data ld; char* source[3]; char* target[3]; int source_type, target_type; int rv = 0; if (*paths[0] == 0 || *paths[1] == 0) { cmdftp_war(CMDFTP_WAR_MARG, ""); return 0; } canonized_fn(source, paths[0]); canonized_fn(target, paths[1]); init_list(&ld); if (!mf[mode][MODE_FETCH_LIST](source[2], &ld)) goto end_proc; if (ld.count == 0) { cmdftp_war(CMDFTP_WAR_MASK, paths[0]); rv = 1; goto end_proc; } if ((target_type = mf[mode][MODE_FILE](target[2])) < 0) goto end_proc; if (ld.count == 1) { if ((source_type = mf[mode][MODE_FILE](ld.data[0].fullname)) < 0) goto end_proc; else if (source_type == FILE_ISREG) { if (target_type == FILE_NEXIST || target_type == FILE_ISREG) { rv = mf[mode][MODE_MOVE](target[2], ld.data[0].fullname); } else if (target_type == FILE_ISDIR) { char* new_target = fullpath(target[2], ld.data[0].basename); free(target[2]); target[2] = new_target; rv = mf[mode][MODE_MOVE](target[2], ld.data[0].fullname); } else { cmdftp_war(CMDFTP_WAR_TRG, "exists (not a regfile or a dir)"); } } else if (source_type == FILE_ISDIR) { if (target_type == FILE_NEXIST) { rv = mf[mode][MODE_MOVE](target[2], ld.data[0].fullname); } else if (target_type == FILE_ISDIR) { rv = do_move_dir(target[2], ld.data[0].fullname); } else { cmdftp_war(CMDFTP_WAR_TRG, "exists (not a dir)"); } } else { cmdftp_war(CMDFTP_WAR_SRC, "not a regular file or a dir"); } } else if (target_type == FILE_ISDIR) { /* source is multiple entries, target is an existing directory */ rv = do_move_dir(target[2], source[2]); } else { cmdftp_war(CMDFTP_WAR_TRG, "multiple source needs a dir target"); } end_proc: free_list(&ld); free_fn(source); free_fn(target); return rv;}int do_ren(char* mask, char* from, char* to) { struct list_data ld; int i, rv; size_t len_from, len_to; len_from = strlen(from); len_to = strlen(to); init_list(&ld); if (!mf[mode][MODE_FETCH_LIST](mask, &ld)) return 0; if (ld.count == 0) { cmdftp_war(CMDFTP_WAR_MASK, mask); return 1; } rv = 1; for (i = 0; i < ld.count; i++) { char* match = strstr(ld.data[i].basename, from); if (match) { char* new_name; size_t new_len; new_len = strlen(ld.data[i].dirname) + 1 + strlen(ld.data[i].basename) - len_from + len_to; new_name = my_malloc(new_len + 1); *match = 0; sprintf(new_name, "%s/%s%s%s", ld.data[i].dirname, ld.data[i].basename, to, match + len_from); if (!mf[mode][MODE_MOVE](new_name, ld.data[i].fullname)) rv = 0; free(new_name); } if (!rv) break; } free_list(&ld); return rv;}void do_setcwd(int mode) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -