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

📄 scp.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    }    return str;}/* * Determine whether a string is entirely composed of dots. */static int is_dots(char *str){    return str[strspn(str, ".")] == '\0';}/* *  Wait for a response from the other side. *  Return 0 if ok, -1 if error. */static int response(void){    char ch, resp, rbuf[2048];    int p;    if (ssh_scp_recv((unsigned char *) &resp, 1) <= 0)	bump("Lost connection");    p = 0;    switch (resp) {      case 0:			       /* ok */	return (0);      default:	rbuf[p++] = resp;	/* fallthrough */      case 1:			       /* error */      case 2:			       /* fatal error */	do {	    if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)		bump("Protocol error: Lost connection");	    rbuf[p++] = ch;	} while (p < sizeof(rbuf) && ch != '\n');	rbuf[p - 1] = '\0';	if (resp == 1)	    tell_user(stderr, "%s\n", rbuf);	else	    bump("%s", rbuf);	errs++;	return (-1);    }}int sftp_recvdata(char *buf, int len){    return ssh_scp_recv((unsigned char *) buf, len);}int sftp_senddata(char *buf, int len){    back->send(backhandle, buf, len);    return 1;}/* ---------------------------------------------------------------------- * sftp-based replacement for the hacky `pscp -ls'. */static int sftp_ls_compare(const void *av, const void *bv){    const struct fxp_name *a = (const struct fxp_name *) av;    const struct fxp_name *b = (const struct fxp_name *) bv;    return strcmp(a->filename, b->filename);}void scp_sftp_listdir(char *dirname){    struct fxp_handle *dirh;    struct fxp_names *names;    struct fxp_name *ournames;    struct sftp_packet *pktin;    struct sftp_request *req, *rreq;    int nnames, namesize;    int i;    if (!fxp_init()) {	tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());	errs++;	return;    }    printf("Listing directory %s\n", dirname);    sftp_register(req = fxp_opendir_send(dirname));    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", dirname, 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", dirname, 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++)		ournames[nnames++] = names->names[i];	    names->nnames = 0;	       /* prevent free_names */	    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_ls_compare);	/*	 * And print them.	 */	for (i = 0; i < nnames; i++)	    printf("%s\n", ournames[i].longname);    }}/* ---------------------------------------------------------------------- * Helper routines that contain the actual SCP protocol elements, * implemented both as SCP1 and SFTP. */static struct scp_sftp_dirstack {    struct scp_sftp_dirstack *next;    struct fxp_name *names;    int namepos, namelen;    char *dirpath;    char *wildcard;    int matched_something;	       /* wildcard match set was non-empty */} *scp_sftp_dirstack_head;static char *scp_sftp_remotepath, *scp_sftp_currentname;static char *scp_sftp_wildcard;static int scp_sftp_targetisdir, scp_sftp_donethistarget;static int scp_sftp_preserve, scp_sftp_recursive;static unsigned long scp_sftp_mtime, scp_sftp_atime;static int scp_has_times;static struct fxp_handle *scp_sftp_filehandle;static struct fxp_xfer *scp_sftp_xfer;static uint64 scp_sftp_fileoffset;void scp_source_setup(char *target, int shouldbedir){    if (using_sftp) {	/*	 * Find out whether the target filespec is in fact a	 * directory.	 */	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	struct fxp_attrs attrs;	int ret;	if (!fxp_init()) {	    tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());	    errs++;	    return;	}	sftp_register(req = fxp_stat_send(target));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	ret = fxp_stat_recv(pktin, rreq, &attrs);	if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS))	    scp_sftp_targetisdir = 0;	else	    scp_sftp_targetisdir = (attrs.permissions & 0040000) != 0;	if (shouldbedir && !scp_sftp_targetisdir) {	    bump("pscp: remote filespec %s: not a directory\n", target);	}	scp_sftp_remotepath = dupstr(target);	scp_has_times = 0;    } else {	(void) response();    }}int scp_send_errmsg(char *str){    if (using_sftp) {	/* do nothing; we never need to send our errors to the server */    } else {	back->send(backhandle, "\001", 1);/* scp protocol error prefix */	back->send(backhandle, str, strlen(str));    }    return 0;			       /* can't fail */}int scp_send_filetimes(unsigned long mtime, unsigned long atime){    if (using_sftp) {	scp_sftp_mtime = mtime;	scp_sftp_atime = atime;	scp_has_times = 1;	return 0;    } else {	char buf[80];	sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);	back->send(backhandle, buf, strlen(buf));	return response();    }}int scp_send_filename(char *name, unsigned long size, int modes){    if (using_sftp) {	char *fullname;	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	if (scp_sftp_targetisdir) {	    fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);	} else {	    fullname = dupstr(scp_sftp_remotepath);	}	sftp_register(req = fxp_open_send(fullname, SSH_FXF_WRITE |					  SSH_FXF_CREAT | SSH_FXF_TRUNC));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	scp_sftp_filehandle = fxp_open_recv(pktin, rreq);	if (!scp_sftp_filehandle) {	    tell_user(stderr, "pscp: unable to open %s: %s",		      fullname, fxp_error());	    errs++;	    return 1;	}	scp_sftp_fileoffset = uint64_make(0, 0);	scp_sftp_xfer = xfer_upload_init(scp_sftp_filehandle,					 scp_sftp_fileoffset);	sfree(fullname);	return 0;    } else {	char buf[40];	sprintf(buf, "C%04o %lu ", modes, size);	back->send(backhandle, buf, strlen(buf));	back->send(backhandle, name, strlen(name));	back->send(backhandle, "\n", 1);	return response();    }}int scp_send_filedata(char *data, int len){    if (using_sftp) {	int ret;	struct sftp_packet *pktin;	if (!scp_sftp_filehandle) {	    return 1;	}	while (!xfer_upload_ready(scp_sftp_xfer)) {	    pktin = sftp_recv();	    ret = xfer_upload_gotpkt(scp_sftp_xfer, pktin);	    if (!ret) {		tell_user(stderr, "error while writing: %s\n", fxp_error());		errs++;		return 1;	    }	}	xfer_upload_data(scp_sftp_xfer, data, len);	scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, len);	return 0;    } else {	int bufsize = back->send(backhandle, data, len);	/*	 * If the network transfer is backing up - that is, the	 * remote site is not accepting data as fast as we can	 * produce it - then we must loop on network events until	 * we have space in the buffer again.	 */	while (bufsize > MAX_SCP_BUFSIZE) {	    if (ssh_sftp_loop_iteration() < 0)		return 1;	    bufsize = back->sendbuffer(backhandle);	}	return 0;    }}int scp_send_finish(void){    if (using_sftp) {	struct fxp_attrs attrs;	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	int ret;	while (!xfer_done(scp_sftp_xfer)) {	    pktin = sftp_recv();	    xfer_upload_gotpkt(scp_sftp_xfer, pktin);	}	xfer_cleanup(scp_sftp_xfer);	if (!scp_sftp_filehandle) {	    return 1;	}	if (scp_has_times) {	    attrs.flags = SSH_FILEXFER_ATTR_ACMODTIME;	    attrs.atime = scp_sftp_atime;	    attrs.mtime = scp_sftp_mtime;	    sftp_register(req = fxp_fsetstat_send(scp_sftp_filehandle, attrs));	    rreq = sftp_find_request(pktin = sftp_recv());	    assert(rreq == req);	    ret = fxp_fsetstat_recv(pktin, rreq);	    if (!ret) {		tell_user(stderr, "unable to set file times: %s\n", fxp_error());		errs++;	    }	}	sftp_register(req = fxp_close_send(scp_sftp_filehandle));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	fxp_close_recv(pktin, rreq);	scp_has_times = 0;	return 0;    } else {	back->send(backhandle, "", 1);	return response();    }}char *scp_save_remotepath(void){    if (using_sftp)	return scp_sftp_remotepath;    else	return NULL;}void scp_restore_remotepath(char *data){    if (using_sftp)	scp_sftp_remotepath = data;}int scp_send_dirname(char *name, int modes){    if (using_sftp) {	char *fullname;	char const *err;	struct fxp_attrs attrs;	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	int ret;	if (scp_sftp_targetisdir) {	    fullname = dupcat(scp_sftp_remotepath, "/", name, NULL);	} else {	    fullname = dupstr(scp_sftp_remotepath);	}	/*	 * We don't worry about whether we managed to create the	 * directory, because if it exists already it's OK just to	 * use it. Instead, we will stat it afterwards, and if it	 * exists and is a directory we will assume we were either	 * successful or it didn't matter.	 */	sftp_register(req = fxp_mkdir_send(fullname));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	ret = fxp_mkdir_recv(pktin, rreq);	if (!ret)	    err = fxp_error();	else	    err = "server reported no error";	sftp_register(req = fxp_stat_send(fullname));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	ret = fxp_stat_recv(pktin, rreq, &attrs);	if (!ret || !(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) ||	    !(attrs.permissions & 0040000)) {	    tell_user(stderr, "unable to create directory %s: %s",		      fullname, err);	    errs++;	    return 1;	}	scp_sftp_remotepath = fullname;	return 0;    } else {	char buf[40];	sprintf(buf, "D%04o 0 ", modes);	back->send(backhandle, buf, strlen(buf));	back->send(backhandle, name, strlen(name));	back->send(backhandle, "\n", 1);	return response();    }}int scp_send_enddir(void){    if (using_sftp) {	sfree(scp_sftp_remotepath);	return 0;    } else {	back->send(backhandle, "E\n", 2);	return response();    }}/* * Yes, I know; I have an scp_sink_setup _and_ an scp_sink_init. * That's bad. The difference is that scp_sink_setup is called once * right at the start, whereas scp_sink_init is called to * initialise every level of recursion in the protocol. */int scp_sink_setup(char *source, int preserve, int recursive){    if (using_sftp) {	char *newsource;	if (!fxp_init()) {	    tell_user(stderr, "unable to initialise SFTP: %s", fxp_error());	    errs++;	    return 1;	}	/*	 * It's possible that the source string we've been given	 * contains a wildcard. If so, we must split the directory	 * away from the wildcard itself (throwing an error if any	 * wildcardness comes before the final slash) and arrange	 * things so that a dirstack entry will be set up.	 */	newsource = snewn(1+strlen(source), char);	if (!wc_unescape(newsource, source)) {	    /* Yes, here we go; it's a wildcard. Bah. */	    char *dupsource, *lastpart, *dirpart, *wildcard;	    dupsource = dupstr(source);	    lastpart = stripslashes(dupsource, 0);	    wildcard = dupstr(lastpart);	    *lastpart = '\0';	    if (*dupsource && dupsource[1]) {		/*		 * The remains of dupsource are at least two		 * characters long, meaning the pathname wasn't		 * empty or just `/'. Hence, we remove the trailing		 * slash.		 */		lastpart[-1] = '\0';	    } else if (!*dupsource) {		/*		 * The remains of dupsource are _empty_ - the whole		 * pathname was a wildcard. Hence we need to		 * replace it with ".".		 */		sfree(dupsource);		dupsource = dupstr(".");	    }	    /*	     * Now we have separated our string into dupsource (the	     * directory part) and wildcard. Both of these will	     * need freeing at some point. Next step is to remove	     * wildcard escapes from the directory part, throwing	     * an error if it contains a real wildcard.	     */	    dirpart = snewn(1+strlen(dupsource), char);	    if (!wc_unescape(dirpart, dupsource)) {		tell_user(stderr, "%s: multiple-level wildcards unsupported",			  source);		errs++;		sfree(dirpart);		sfree(wildcard);		sfree(dupsource);		return 1;	    }	    /*	     * Now we have dirpart (unescaped, ie a valid remote	     * path), and wildcard (a wildcard). This will be	     * sufficient to arrange a dirstack entry.	     */	    scp_sftp_remotepath = dirpart;	    scp_sftp_wildcard = wildcard;	    sfree(dupsource);	} else {	    scp_sftp_remotepath = newsource;	    scp_sftp_wildcard = NULL;	}	scp_sftp_preserve = preserve;	scp_sftp_recursive = recursive;	scp_sftp_donethistarget = 0;	scp_sftp_dirstack_head = NULL;    }    return 0;}int scp_sink_init(void){    if (!using_sftp) {	back->send(backhandle, "", 1);    }    return 0;}#define SCP_SINK_FILE   1#define SCP_SINK_DIR    2#define SCP_SINK_ENDDIR 3#define SCP_SINK_RETRY  4	       /* not an action; just try again */struct scp_sink_action {    int action;			       /* FILE, DIR, ENDDIR */    char *buf;			       /* will need freeing after use */    char *name;			       /* filename or dirname (not ENDDIR) */    int mode;			       /* access mode (not ENDDIR) */    unsigned long size;		       /* file size (not ENDDIR) */    int settime;		       /* 1 if atime and mtime are filled */    unsigned long atime, mtime;	       /* access times for the file */};int scp_get_sink_action(struct scp_sink_action *act){    if (using_sftp) {	char *fname;	int must_free_fname;	struct fxp_attrs attrs;	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	int ret;	if (!scp_sftp_dirstack_head) {	    if (!scp_sftp_donethistarget) {		/*		 * Simple case: we are only dealing with one file.		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -