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

📄 scp.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		fname = scp_sftp_remotepath;		must_free_fname = 0;		scp_sftp_donethistarget = 1;	    } else {		/*		 * Even simpler case: one file _which we've done_.		 * Return 1 (finished).		 */		return 1;	    }	} else {	    /*	     * We're now in the middle of stepping through a list	     * of names returned from fxp_readdir(); so let's carry	     * on.	     */	    struct scp_sftp_dirstack *head = scp_sftp_dirstack_head;	    while (head->namepos < head->namelen &&		   (is_dots(head->names[head->namepos].filename) ||		    (head->wildcard &&		     !wc_match(head->wildcard,			       head->names[head->namepos].filename))))		head->namepos++;       /* skip . and .. */	    if (head->namepos < head->namelen) {		head->matched_something = 1;		fname = dupcat(head->dirpath, "/",			       head->names[head->namepos++].filename,			       NULL);		must_free_fname = 1;	    } else {		/*		 * We've come to the end of the list; pop it off		 * the stack and return an ENDDIR action (or RETRY		 * if this was a wildcard match).		 */		if (head->wildcard) {		    act->action = SCP_SINK_RETRY;		    if (!head->matched_something) {			tell_user(stderr, "pscp: wildcard '%s' matched "				  "no files", head->wildcard);			errs++;		    }		    sfree(head->wildcard);		} else {		    act->action = SCP_SINK_ENDDIR;		}		sfree(head->dirpath);		sfree(head->names);		scp_sftp_dirstack_head = head->next;		sfree(head);		return 0;	    }	}	/*	 * Now we have a filename. Stat it, and see if it's a file	 * or a directory.	 */	sftp_register(req = fxp_stat_send(fname));	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)) {	    tell_user(stderr, "unable to identify %s: %s", fname,		      ret ? "file type not supplied" : fxp_error());	    errs++;	    return 1;	}	if (attrs.permissions & 0040000) {	    struct scp_sftp_dirstack *newitem;	    struct fxp_handle *dirhandle;	    int nnames, namesize;	    struct fxp_name *ournames;	    struct fxp_names *names;	    /*	     * It's a directory. If we're not in recursive mode,	     * this merits a complaint (which is fatal if the name	     * was specified directly, but not if it was matched by	     * a wildcard).	     * 	     * We skip this complaint completely if	     * scp_sftp_wildcard is set, because that's an	     * indication that we're not actually supposed to	     * _recursively_ transfer the dir, just scan it for	     * things matching the wildcard.	     */	    if (!scp_sftp_recursive && !scp_sftp_wildcard) {		tell_user(stderr, "pscp: %s: is a directory", fname);		errs++;		if (must_free_fname) sfree(fname);		if (scp_sftp_dirstack_head) {		    act->action = SCP_SINK_RETRY;		    return 0;		} else {		    return 1;		}	    }	    /*	     * Otherwise, the fun begins. We must fxp_opendir() the	     * directory, slurp the filenames into memory, return	     * SCP_SINK_DIR (unless this is a wildcard match), and	     * set targetisdir. The next time we're called, we will	     * run through the list of filenames one by one,	     * matching them against a wildcard if present.	     * 	     * If targetisdir is _already_ set (meaning we're	     * already in the middle of going through another such	     * list), we must push the other (target,namelist) pair	     * on a stack.	     */	    sftp_register(req = fxp_opendir_send(fname));	    rreq = sftp_find_request(pktin = sftp_recv());	    assert(rreq == req);	    dirhandle = fxp_opendir_recv(pktin, rreq);	    if (!dirhandle) {		tell_user(stderr, "scp: unable to open directory %s: %s",			  fname, fxp_error());		if (must_free_fname) sfree(fname);		errs++;		return 1;	    }	    nnames = namesize = 0;	    ournames = NULL;	    while (1) {		int i;		sftp_register(req = fxp_readdir_send(dirhandle));		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;		    tell_user(stderr, "scp: reading directory %s: %s\n",			      fname, fxp_error());		    if (must_free_fname) sfree(fname);		    sfree(ournames);		    errs++;		    return 1;		}		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(dirhandle));	    rreq = sftp_find_request(pktin = sftp_recv());	    assert(rreq == req);	    fxp_close_recv(pktin, rreq);	    newitem = snew(struct scp_sftp_dirstack);	    newitem->next = scp_sftp_dirstack_head;	    newitem->names = ournames;	    newitem->namepos = 0;	    newitem->namelen = nnames;	    if (must_free_fname)		newitem->dirpath = fname;	    else		newitem->dirpath = dupstr(fname);	    if (scp_sftp_wildcard) {		newitem->wildcard = scp_sftp_wildcard;		newitem->matched_something = 0;		scp_sftp_wildcard = NULL;	    } else {		newitem->wildcard = NULL;	    }	    scp_sftp_dirstack_head = newitem;	    if (newitem->wildcard) {		act->action = SCP_SINK_RETRY;	    } else {		act->action = SCP_SINK_DIR;		act->buf = dupstr(stripslashes(fname, 0));		act->name = act->buf;		act->size = 0;	       /* duhh, it's a directory */		act->mode = 07777 & attrs.permissions;		if (scp_sftp_preserve &&		    (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {		    act->atime = attrs.atime;		    act->mtime = attrs.mtime;		    act->settime = 1;		} else		    act->settime = 0;	    }	    return 0;	} else {	    /*	     * It's a file. Return SCP_SINK_FILE.	     */	    act->action = SCP_SINK_FILE;	    act->buf = dupstr(stripslashes(fname, 0));	    act->name = act->buf;	    if (attrs.flags & SSH_FILEXFER_ATTR_SIZE) {		if (uint64_compare(attrs.size,				   uint64_make(0, ULONG_MAX)) > 0) {		    act->size = ULONG_MAX;   /* *boggle* */		} else		    act->size = attrs.size.lo;	    } else		act->size = ULONG_MAX;   /* no idea */	    act->mode = 07777 & attrs.permissions;	    if (scp_sftp_preserve &&		(attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME)) {		act->atime = attrs.atime;		act->mtime = attrs.mtime;		act->settime = 1;	    } else		act->settime = 0;	    if (must_free_fname)		scp_sftp_currentname = fname;	    else		scp_sftp_currentname = dupstr(fname);	    return 0;	}    } else {	int done = 0;	int i, bufsize;	int action;	char ch;	act->settime = 0;	act->buf = NULL;	bufsize = 0;	while (!done) {	    if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)		return 1;	    if (ch == '\n')		bump("Protocol error: Unexpected newline");	    i = 0;	    action = ch;	    do {		if (ssh_scp_recv((unsigned char *) &ch, 1) <= 0)		    bump("Lost connection");		if (i >= bufsize) {		    bufsize = i + 128;		    act->buf = sresize(act->buf, bufsize, char);		}		act->buf[i++] = ch;	    } while (ch != '\n');	    act->buf[i - 1] = '\0';	    switch (action) {	      case '\01':		       /* error */		tell_user(stderr, "%s\n", act->buf);		errs++;		continue;		       /* go round again */	      case '\02':		       /* fatal error */		bump("%s", act->buf);	      case 'E':		back->send(backhandle, "", 1);		act->action = SCP_SINK_ENDDIR;		return 0;	      case 'T':		if (sscanf(act->buf, "%ld %*d %ld %*d",			   &act->mtime, &act->atime) == 2) {		    act->settime = 1;		    back->send(backhandle, "", 1);		    continue;	       /* go round again */		}		bump("Protocol error: Illegal time format");	      case 'C':	      case 'D':		act->action = (action == 'C' ? SCP_SINK_FILE : SCP_SINK_DIR);		break;	      default:		bump("Protocol error: Expected control record");	    }	    /*	     * We will go round this loop only once, unless we hit	     * `continue' above.	     */	    done = 1;	}	/*	 * If we get here, we must have seen SCP_SINK_FILE or	 * SCP_SINK_DIR.	 */	if (sscanf(act->buf, "%o %lu %n", &act->mode, &act->size, &i) != 2)	    bump("Protocol error: Illegal file descriptor format");	act->name = act->buf + i;	return 0;    }}int scp_accept_filexfer(void){    if (using_sftp) {	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	sftp_register(req = fxp_open_send(scp_sftp_currentname, SSH_FXF_READ));	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",		      scp_sftp_currentname, fxp_error());	    errs++;	    return 1;	}	scp_sftp_fileoffset = uint64_make(0, 0);	scp_sftp_xfer = xfer_download_init(scp_sftp_filehandle,					   scp_sftp_fileoffset);	sfree(scp_sftp_currentname);	return 0;    } else {	back->send(backhandle, "", 1);	return 0;		       /* can't fail */    }}int scp_recv_filedata(char *data, int len){    if (using_sftp) {	struct sftp_packet *pktin;	int ret, actuallen;	void *vbuf;	xfer_download_queue(scp_sftp_xfer);	pktin = sftp_recv();	ret = xfer_download_gotpkt(scp_sftp_xfer, pktin);	if (ret < 0) {	    tell_user(stderr, "pscp: error while reading: %s", fxp_error());	    errs++;	    return -1;	}	if (xfer_download_data(scp_sftp_xfer, &vbuf, &actuallen)) {	    /*	     * This assertion relies on the fact that the natural	     * block size used in the xfer manager is at most that	     * used in this module. I don't like crossing layers in	     * this way, but it'll do for now.	     */	    assert(actuallen <= len);	    memcpy(data, vbuf, actuallen);	    sfree(vbuf);	} else	    actuallen = 0;	scp_sftp_fileoffset = uint64_add32(scp_sftp_fileoffset, actuallen);	return actuallen;    } else {	return ssh_scp_recv((unsigned char *) data, len);    }}int scp_finish_filerecv(void){    if (using_sftp) {	struct sftp_packet *pktin;	struct sftp_request *req, *rreq;	/*	 * Ensure that xfer_done() will work correctly, so we can	 * clean up any outstanding requests from the file	 * transfer.	 */	xfer_set_error(scp_sftp_xfer);	while (!xfer_done(scp_sftp_xfer)) {	    void *vbuf;	    int len;	    pktin = sftp_recv();	    xfer_download_gotpkt(scp_sftp_xfer, pktin);	    if (xfer_download_data(scp_sftp_xfer, &vbuf, &len))		sfree(vbuf);	}	xfer_cleanup(scp_sftp_xfer);	sftp_register(req = fxp_close_send(scp_sftp_filehandle));	rreq = sftp_find_request(pktin = sftp_recv());	assert(rreq == req);	fxp_close_recv(pktin, rreq);	return 0;    } else {	back->send(backhandle, "", 1);	return response();    }}/* ---------------------------------------------------------------------- *  Send an error message to the other side and to the screen. *  Increment error counter. */static void run_err(const char *fmt, ...){    char *str, *str2;    va_list ap;    va_start(ap, fmt);    errs++;    str = dupvprintf(fmt, ap);    str2 = dupcat("scp: ", str, "\n", NULL);    sfree(str);    scp_send_errmsg(str2);    tell_user(stderr, "%s", str2);    va_end(ap);    sfree(str2);}/* *  Execute the source part of the SCP protocol. */static void source(char *src){    unsigned long size;    unsigned long mtime, atime;    char *last;    RFile *f;    int attr;    unsigned long i;    unsigned long stat_bytes;    time_t stat_starttime, stat_lasttime;    attr = file_type(src);    if (attr == FILE_TYPE_NONEXISTENT ||	attr == FILE_TYPE_WEIRD) {	run_err("%s: %s file or directory", src,		(attr == FILE_TYPE_WEIRD ? "Not a" : "No such"));	return;    }    if (attr == FILE_TYPE_DIRECTORY) {	if (recursive) {	    /*	     * Avoid . and .. directories.	     */	    char *p;	    p = strrchr(src, '/');	    if (!p)		p = strrchr(src, '\\');	    if (!p)		p = src;	    else		p++;	    if (!strcmp(p, ".") || !strcmp(p, ".."))		/* skip . and .. */ ;	    else		rsource(src);	} else {	    run_err("%s: not a regular file", src);	}	return;    }    if ((last = strrchr(src, '/')) == NULL)	last = src;    else	last++;    if (strrchr(last, '\\') != NULL)	last = strrchr(last, '\\') + 1;    if (last == src && strchr(src, ':') != NULL)	last = strchr(src, ':') + 1;    f = open_existing_file(src, &size, &mtime, &atime);    if (f == NULL) {	run_err("%s: Cannot open file", src);	return;    }    if (preserve) {	if (scp_send_filetimes(mtime, atime))	    return;    }    if (verbose)	tell_user(stderr, "Sending file %s, size=%lu", last, size);    if (scp_send_filename(last, size, 0644))	return;    stat_bytes = 0;    stat_starttime = time(NULL);    stat_lasttime = 0;    for (i = 0; i < size; i += 4096) {	char transbuf[4096];	int j, k = 4096;	if (i + k > size)	    k = size - i;	if ((j = read_from_file(f, transbuf, k)) != k) {	    if (statistics)		printf("\n");	    bump("%s: Read error", src);	}	if (scp_send_filedata(transbuf, k))	    bump("%s: Network error occurred", src);	if (statistics) {	    stat_bytes += k;	    if (time(NULL) != stat_lasttime || i + k == size) {		stat_lasttime = time(NULL);		print_stats(last, size, stat_bytes,			    stat_starttime, stat_lasttime);	    }	}    }    close_rfile(f);    (void) scp_send_finish();}/* *  Recursively send the contents of a directory. */static void rsource(char *src){    char *last;    char *save_target;    DirHandle *dir;    if ((last = strrchr(src, '/')) == NULL)	last = src;    else	last++;    if (strrchr(last, '\\') != NULL)	last = strrchr(last, '\\') + 1;    if (last == src && strchr(src, ':') != NULL)	last = strchr(src, ':') + 1;    /* maybe send filetime */    save_target = scp_save_remotepath();    if (verbose)	tell_user(stderr, "Entering directory: %s", last);    if (scp_send_dirname(last, 0755))	return;    dir = open_directory(src);    if (dir != NULL) {	char *filename;	while ((filename = read_filename(dir)) != NULL) {	    char *foundfile = dupcat(src, "/", filename, NULL);	    source(foundfile);	    sfree(foundfile);	    sfree(filename);	}    }    close_directory(dir);    (void) scp_send_enddir();    scp_restore_remotepath(save_target);

⌨️ 快捷键说明

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