📄 psftp.c
字号:
unwcdir = snewn(1 + strlen(dir), char);
if (wc_unescape(unwcdir, dir)) {
dir = unwcdir;
wildcard = NULL;
} else {
char *tmpdir;
int len, check;
wildcard = stripslashes(dir, 0);
unwcdir = dupstr(dir);
len = wildcard - dir;
unwcdir[len] = '\0';
if (len > 0 && unwcdir[len-1] == '/')
unwcdir[len-1] = '\0';
tmpdir = snewn(1 + len, char);
check = wc_unescape(tmpdir, unwcdir);
sfree(tmpdir);
if (!check) {
printf("Multiple-level wildcards are not supported\n");
sfree(unwcdir);
return 0;
}
dir = unwcdir;
}
cdir = canonify(dir);
if (!cdir) {
printf("%s: canonify: %s\n", dir, fxp_error());
sfree(unwcdir);
return 0;
}
printf("Listing directory %s\n", cdir);
sftp_register(req = fxp_opendir_send(cdir));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
dirh = fxp_opendir_recv(pktin, rreq);
if (dirh == NULL) {
printf("Unable to open %s: %s\n", dir, fxp_error());
} else {
nnames = namesize = 0;
ournames = NULL;
while (1) {
sftp_register(req = fxp_readdir_send(dirh));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
names = fxp_readdir_recv(pktin, rreq);
if (names == NULL) {
if (fxp_error_type() == SSH_FX_EOF)
break;
printf("Reading directory %s: %s\n", dir, fxp_error());
break;
}
if (names->nnames == 0) {
fxp_free_names(names);
break;
}
if (nnames + names->nnames >= namesize) {
namesize += names->nnames + 128;
ournames = sresize(ournames, namesize, struct fxp_name *);
}
for (i = 0; i < names->nnames; i++)
if (!wildcard || wc_match(wildcard, names->names[i].filename))
ournames[nnames++] = fxp_dup_name(&names->names[i]);
fxp_free_names(names);
}
sftp_register(req = fxp_close_send(dirh));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
fxp_close_recv(pktin, rreq);
/*
* Now we have our filenames. Sort them by actual file
* name, and then output the longname parts.
*/
qsort(ournames, nnames, sizeof(*ournames), sftp_name_compare);
/*
* And print them.
*/
for (i = 0; i < nnames; i++) {
printf("%s\n", ournames[i]->longname);
fxp_free_name(ournames[i]);
}
sfree(ournames);
}
sfree(cdir);
sfree(unwcdir);
return 1;
}
/*
* Change directories. We do this by canonifying the new name, then
* trying to OPENDIR it. Only if that succeeds do we set the new pwd.
*/
int sftp_cmd_cd(struct sftp_command *cmd)
{
struct fxp_handle *dirh;
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
char *dir;
if (back == NULL) {
not_connected();
return 0;
}
if (cmd->nwords < 2)
dir = dupstr(homedir);
else
dir = canonify(cmd->words[1]);
if (!dir) {
printf("%s: canonify: %s\n", dir, fxp_error());
return 0;
}
sftp_register(req = fxp_opendir_send(dir));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
dirh = fxp_opendir_recv(pktin, rreq);
if (!dirh) {
printf("Directory %s: %s\n", dir, fxp_error());
sfree(dir);
return 0;
}
sftp_register(req = fxp_close_send(dirh));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
fxp_close_recv(pktin, rreq);
sfree(pwd);
pwd = dir;
printf("Remote directory is now %s\n", pwd);
return 1;
}
/*
* Print current directory. Easy as pie.
*/
int sftp_cmd_pwd(struct sftp_command *cmd)
{
if (back == NULL) {
not_connected();
return 0;
}
printf("Remote directory is %s\n", pwd);
return 1;
}
/*
* Get a file and save it at the local end. We have three very
* similar commands here. The basic one is `get'; `reget' differs
* in that it checks for the existence of the destination file and
* starts from where a previous aborted transfer left off; `mget'
* differs in that it interprets all its arguments as files to
* transfer (never as a different local name for a remote file) and
* can handle wildcards.
*/
int sftp_general_get(struct sftp_command *cmd, int restart, int multiple)
{
char *fname, *unwcfname, *origfname, *origwfname, *outfname;
int i, ret;
int recurse = FALSE;
if (back == NULL) {
not_connected();
return 0;
}
i = 1;
while (i < cmd->nwords && cmd->words[i][0] == '-') {
if (!strcmp(cmd->words[i], "--")) {
/* finish processing options */
i++;
break;
} else if (!strcmp(cmd->words[i], "-r")) {
recurse = TRUE;
} else {
printf("%s: unrecognised option '%s'\n", cmd->words[0], cmd->words[i]);
return 0;
}
i++;
}
if (i >= cmd->nwords) {
printf("%s: expects a filename\n", cmd->words[0]);
return 0;
}
ret = 1;
do {
SftpWildcardMatcher *swcm;
origfname = cmd->words[i++];
unwcfname = snewn(strlen(origfname)+1, char);
if (multiple && !wc_unescape(unwcfname, origfname)) {
swcm = sftp_begin_wildcard_matching(origfname);
if (!swcm) {
sfree(unwcfname);
continue;
}
origwfname = sftp_wildcard_get_filename(swcm);
if (!origwfname) {
/* Politely warn the user that nothing matched. */
printf("%s: nothing matched\n", origfname);
sftp_finish_wildcard_matching(swcm);
sfree(unwcfname);
continue;
}
} else {
origwfname = origfname;
swcm = NULL;
}
while (origwfname) {
fname = canonify(origwfname);
if (!fname) {
printf("%s: canonify: %s\n", origwfname, fxp_error());
sfree(unwcfname);
return 0;
}
if (!multiple && i < cmd->nwords)
outfname = cmd->words[i++];
else
outfname = stripslashes(origwfname, 0);
ret = sftp_get_file(fname, outfname, recurse, restart);
sfree(fname);
if (swcm) {
sfree(origwfname);
origwfname = sftp_wildcard_get_filename(swcm);
} else {
origwfname = NULL;
}
}
sfree(unwcfname);
if (swcm)
sftp_finish_wildcard_matching(swcm);
if (!ret)
return ret;
} while (multiple && i < cmd->nwords);
return ret;
}
int sftp_cmd_get(struct sftp_command *cmd)
{
return sftp_general_get(cmd, 0, 0);
}
int sftp_cmd_mget(struct sftp_command *cmd)
{
return sftp_general_get(cmd, 0, 1);
}
int sftp_cmd_reget(struct sftp_command *cmd)
{
return sftp_general_get(cmd, 1, 0);
}
/*
* Send a file and store it at the remote end. We have three very
* similar commands here. The basic one is `put'; `reput' differs
* in that it checks for the existence of the destination file and
* starts from where a previous aborted transfer left off; `mput'
* differs in that it interprets all its arguments as files to
* transfer (never as a different remote name for a local file) and
* can handle wildcards.
*/
int sftp_general_put(struct sftp_command *cmd, int restart, int multiple)
{
char *fname, *wfname, *origoutfname, *outfname;
int i, ret;
int recurse = FALSE;
if (back == NULL) {
not_connected();
return 0;
}
i = 1;
while (i < cmd->nwords && cmd->words[i][0] == '-') {
if (!strcmp(cmd->words[i], "--")) {
/* finish processing options */
i++;
break;
} else if (!strcmp(cmd->words[i], "-r")) {
recurse = TRUE;
} else {
printf("%s: unrecognised option '%s'\n", cmd->words[0], cmd->words[i]);
return 0;
}
i++;
}
if (i >= cmd->nwords) {
printf("%s: expects a filename\n", cmd->words[0]);
return 0;
}
ret = 1;
do {
WildcardMatcher *wcm;
fname = cmd->words[i++];
if (multiple && test_wildcard(fname, FALSE) == WCTYPE_WILDCARD) {
wcm = begin_wildcard_matching(fname);
wfname = wildcard_get_filename(wcm);
if (!wfname) {
/* Politely warn the user that nothing matched. */
printf("%s: nothing matched\n", fname);
finish_wildcard_matching(wcm);
continue;
}
} else {
wfname = fname;
wcm = NULL;
}
while (wfname) {
if (!multiple && i < cmd->nwords)
origoutfname = cmd->words[i++];
else
origoutfname = stripslashes(wfname, 1);
outfname = canonify(origoutfname);
if (!outfname) {
printf("%s: canonify: %s\n", origoutfname, fxp_error());
if (wcm) {
sfree(wfname);
finish_wildcard_matching(wcm);
}
return 0;
}
ret = sftp_put_file(wfname, outfname, recurse, restart);
sfree(outfname);
if (wcm) {
sfree(wfname);
wfname = wildcard_get_filename(wcm);
} else {
wfname = NULL;
}
}
if (wcm)
finish_wildcard_matching(wcm);
if (!ret)
return ret;
} while (multiple && i < cmd->nwords);
return ret;
}
int sftp_cmd_put(struct sftp_command *cmd)
{
return sftp_general_put(cmd, 0, 0);
}
int sftp_cmd_mput(struct sftp_command *cmd)
{
return sftp_general_put(cmd, 0, 1);
}
int sftp_cmd_reput(struct sftp_command *cmd)
{
return sftp_general_put(cmd, 1, 0);
}
int sftp_cmd_mkdir(struct sftp_command *cmd)
{
char *dir;
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
int result;
int i, ret;
if (back == NULL) {
not_connected();
return 0;
}
if (cmd->nwords < 2) {
printf("mkdir: expects a directory\n");
return 0;
}
ret = 1;
for (i = 1; i < cmd->nwords; i++) {
dir = canonify(cmd->words[i]);
if (!dir) {
printf("%s: canonify: %s\n", dir, fxp_error());
return 0;
}
sftp_register(req = fxp_mkdir_send(dir));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
result = fxp_mkdir_recv(pktin, rreq);
if (!result) {
printf("mkdir %s: %s\n", dir, fxp_error());
ret = 0;
} else
printf("mkdir %s: OK\n", dir);
sfree(dir);
}
return ret;
}
static int sftp_action_rmdir(void *vctx, char *dir)
{
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
int result;
sftp_register(req = fxp_rmdir_send(dir));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
result = fxp_rmdir_recv(pktin, rreq);
if (!result) {
printf("rmdir %s: %s\n", dir, fxp_error());
return 0;
}
printf("rmdir %s: OK\n", dir);
return 1;
}
int sftp_cmd_rmdir(struct sftp_command *cmd)
{
int i, ret;
if (back == NULL) {
not_connected();
return 0;
}
if (cmd->nwords < 2) {
printf("rmdir: expects a directory\n");
return 0;
}
ret = 1;
for (i = 1; i < cmd->nwords; i++)
ret &= wildcard_iterate(cmd->words[i], sftp_action_rmdir, NULL);
return ret;
}
static int sftp_action_rm(void *vctx, char *fname)
{
struct sftp_packet *pktin;
struct sftp_request *req, *rreq;
int result;
sftp_register(req = fxp_remove_send(fname));
rreq = sftp_find_request(pktin = sftp_recv());
assert(rreq == req);
result = fxp_remove_recv(pktin, rreq);
if (!result) {
printf("rm %s: %s\n", fname, fxp_error());
return 0;
}
printf("rm %s: OK\n", fname);
return 1;
}
int sftp_cmd_rm(struct sftp_command *cmd)
{
int i, ret;
if (back == NULL) {
not_connected();
return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -