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

📄 scp.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (last == 0)		last = name;	else		last++;	if (pflag) {		(void) snprintf(path, sizeof(path), "T%lu 0 %lu 0\n",		    (u_long) statp->st_mtime,		    (u_long) statp->st_atime);		(void) atomicio(write, remout, path, strlen(path));		if (response() < 0) {			closedir(dirp);			return;		}	}	(void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",	    (u_int) (statp->st_mode & FILEMODEMASK), 0, last);	if (verbose_mode)		fprintf(stderr, "Entering directory: %s", path);	(void) atomicio(write, remout, path, strlen(path));	if (response() < 0) {		closedir(dirp);		return;	}	while ((dp = readdir(dirp)) != NULL) {		if (dp->d_ino == 0)			continue;		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))			continue;		if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {			run_err("%s/%s: name too long", name, dp->d_name);			continue;		}		(void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);		vect[0] = path;		source(1, vect);	}	(void) closedir(dirp);	(void) atomicio(write, remout, "E\n", 2);	(void) response();}voidsink(argc, argv)	int argc;	char *argv[];{	static BUF buffer;	struct stat stb;	enum {		YES, NO, DISPLAYED	} wrerr;	BUF *bp;	off_t i, j;	int amt, count, exists, first, mask, mode, ofd, omode;	off_t size;	int setimes, targisdir, wrerrno = 0;	char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];	struct timeval tv[2];#define	atime	tv[0]#define	mtime	tv[1]#define	SCREWUP(str)	do { why = str; goto screwup; } while (0)	setimes = targisdir = 0;	mask = umask(0);	if (!pflag)		(void) umask(mask);	if (argc != 1) {		run_err("ambiguous target");		exit(1);	}	targ = *argv;	if (targetshouldbedirectory)		verifydir(targ);	(void) atomicio(write, remout, "", 1);	if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))		targisdir = 1;	for (first = 1;; first = 0) {		cp = buf;		if (atomicio(read, remin, cp, 1) <= 0)			return;		if (*cp++ == '\n')			SCREWUP("unexpected <newline>");		do {			if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))				SCREWUP("lost connection");			*cp++ = ch;		} while (cp < &buf[sizeof(buf) - 1] && ch != '\n');		*cp = 0;		if (buf[0] == '\01' || buf[0] == '\02') {			if (iamremote == 0)				(void) atomicio(write, STDERR_FILENO,				    buf + 1, strlen(buf + 1));			if (buf[0] == '\02')				exit(1);			++errs;			continue;		}		if (buf[0] == 'E') {			(void) atomicio(write, remout, "", 1);			return;		}		if (ch == '\n')			*--cp = 0;		cp = buf;		if (*cp == 'T') {			setimes++;			cp++;			mtime.tv_sec = strtol(cp, &cp, 10);			if (!cp || *cp++ != ' ')				SCREWUP("mtime.sec not delimited");			mtime.tv_usec = strtol(cp, &cp, 10);			if (!cp || *cp++ != ' ')				SCREWUP("mtime.usec not delimited");			atime.tv_sec = strtol(cp, &cp, 10);			if (!cp || *cp++ != ' ')				SCREWUP("atime.sec not delimited");			atime.tv_usec = strtol(cp, &cp, 10);			if (!cp || *cp++ != '\0')				SCREWUP("atime.usec not delimited");			(void) atomicio(write, remout, "", 1);			continue;		}		if (*cp != 'C' && *cp != 'D') {			/*			 * Check for the case "rcp remote:foo\* local:bar".			 * In this case, the line "No match." can be returned			 * by the shell before the rcp command on the remote is			 * executed so the ^Aerror_message convention isn't			 * followed.			 */			if (first) {				run_err("%s", cp);				exit(1);			}			SCREWUP("expected control record");		}		mode = 0;		for (++cp; cp < buf + 5; cp++) {			if (*cp < '0' || *cp > '7')				SCREWUP("bad mode");			mode = (mode << 3) | (*cp - '0');		}		if (*cp++ != ' ')			SCREWUP("mode not delimited");		for (size = 0; isdigit(*cp);)			size = size * 10 + (*cp++ - '0');		if (*cp++ != ' ')			SCREWUP("size not delimited");		if (targisdir) {			static char *namebuf;			static int cursize;			size_t need;			need = strlen(targ) + strlen(cp) + 250;			if (need > cursize) {				if (namebuf)					xfree(namebuf);				namebuf = xmalloc(need);				cursize = need;			}			(void) snprintf(namebuf, need, "%s%s%s", targ,			    strcmp(targ, "/") ? "/" : "", cp);			np = namebuf;		} else			np = targ;		curfile = cp;		exists = stat(np, &stb) == 0;		if (buf[0] == 'D') {			int mod_flag = pflag;			if (exists) {				if (!S_ISDIR(stb.st_mode)) {					errno = ENOTDIR;					goto bad;				}				if (pflag)					(void) chmod(np, mode);			} else {				/* Handle copying from a read-only				   directory */				mod_flag = 1;				if (mkdir(np, mode | S_IRWXU) < 0)					goto bad;			}			vect[0] = xstrdup(np);			sink(1, vect);			if (setimes) {				setimes = 0;				if (utimes(vect[0], tv) < 0)					run_err("%s: set times: %s",					    vect[0], strerror(errno));			}			if (mod_flag)				(void) chmod(vect[0], mode);			if (vect[0])				xfree(vect[0]);			continue;		}		omode = mode;		mode |= S_IWRITE;		if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {bad:			run_err("%s: %s", np, strerror(errno));			continue;		}		(void) atomicio(write, remout, "", 1);		if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {			(void) close(ofd);			continue;		}		cp = bp->buf;		wrerr = NO;		if (showprogress) {			totalbytes = size;			progressmeter(-1);		}		statbytes = 0;		for (count = i = 0; i < size; i += 4096) {			amt = 4096;			if (i + amt > size)				amt = size - i;			count += amt;			do {				j = read(remin, cp, amt);				if (j == -1 && (errno == EINTR ||				    errno == EAGAIN)) {					continue;				} else if (j <= 0) {					run_err("%s", j ? strerror(errno) :					    "dropped connection");					exit(1);				}				amt -= j;				cp += j;				statbytes += j;			} while (amt > 0);			if (count == bp->cnt) {				/* Keep reading so we stay sync'd up. */				if (wrerr == NO) {					j = atomicio(write, ofd, bp->buf, count);					if (j != count) {						wrerr = YES;						wrerrno = j >= 0 ? EIO : errno;					}				}				count = 0;				cp = bp->buf;			}		}		if (showprogress)			progressmeter(1);		if (count != 0 && wrerr == NO &&		    (j = atomicio(write, ofd, bp->buf, count)) != count) {			wrerr = YES;			wrerrno = j >= 0 ? EIO : errno;		}		if (ftruncate(ofd, size)) {			run_err("%s: truncate: %s", np, strerror(errno));			wrerr = DISPLAYED;		}		if (pflag) {			if (exists || omode != mode)#ifdef HAVE_FCHMOD				if (fchmod(ofd, omode))#else /* HAVE_FCHMOD */				if (chmod(np, omode))#endif /* HAVE_FCHMOD */					run_err("%s: set mode: %s",					    np, strerror(errno));		} else {			if (!exists && omode != mode)#ifdef HAVE_FCHMOD				if (fchmod(ofd, omode & ~mask))#else /* HAVE_FCHMOD */				if (chmod(np, omode & ~mask))#endif /* HAVE_FCHMOD */					run_err("%s: set mode: %s",					    np, strerror(errno));		}		if (close(ofd) == -1) {			wrerr = YES;			wrerrno = errno;		}		(void) response();		if (setimes && wrerr == NO) {			setimes = 0;			if (utimes(np, tv) < 0) {				run_err("%s: set times: %s",				    np, strerror(errno));				wrerr = DISPLAYED;			}		}		switch (wrerr) {		case YES:			run_err("%s: %s", np, strerror(wrerrno));			break;		case NO:			(void) atomicio(write, remout, "", 1);			break;		case DISPLAYED:			break;		}	}screwup:	run_err("protocol error: %s", why);	exit(1);}intresponse(void){	char ch, *cp, resp, rbuf[2048];	if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))		lostconn(0);	cp = rbuf;	switch (resp) {	case 0:		/* ok */		return (0);	default:		*cp++ = resp;		/* FALLTHROUGH */	case 1:		/* error, followed by error msg */	case 2:		/* fatal error, "" */		do {			if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))				lostconn(0);			*cp++ = ch;		} while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');		if (!iamremote)			(void) atomicio(write, STDERR_FILENO, rbuf, cp - rbuf);		++errs;		if (resp == 1)			return (-1);		exit(1);	}	/* NOTREACHED */}voidusage(void){	(void) fprintf(stderr,	    "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"	    "           [-c cipher] [-i identity] [-o option]\n"	    "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");	exit(1);}voidrun_err(const char *fmt,...){	static FILE *fp;	va_list ap;	++errs;	if (fp == NULL && !(fp = fdopen(remout, "w")))		return;	(void) fprintf(fp, "%c", 0x01);	(void) fprintf(fp, "scp: ");	va_start(ap, fmt);	(void) vfprintf(fp, fmt, ap);	va_end(ap);	(void) fprintf(fp, "\n");	(void) fflush(fp);	if (!iamremote) {		va_start(ap, fmt);		vfprintf(stderr, fmt, ap);		va_end(ap);		fprintf(stderr, "\n");	}}voidverifydir(cp)	char *cp;{	struct stat stb;	if (!stat(cp, &stb)) {		if (S_ISDIR(stb.st_mode))			return;		errno = ENOTDIR;	}	run_err("%s: %s", cp, strerror(errno));	exit(1);}intokname(cp0)	char *cp0;{	int c;	char *cp;	cp = cp0;	do {		c = (int)*cp;		if (c & 0200)			goto bad;		if (!isalpha(c) && !isdigit(c) &&		    c != '_' && c != '-' && c != '.' && c != '+')			goto bad;	} while (*++cp);	return (1);bad:	fprintf(stderr, "%s: invalid user name\n", cp0);	return (0);}BUF *allocbuf(bp, fd, blksize)	BUF *bp;	int fd, blksize;{	size_t size;#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE	struct stat stb;	if (fstat(fd, &stb) < 0) {		run_err("fstat: %s", strerror(errno));		return (0);	}	if (stb.st_blksize == 0)		size = blksize;	else		size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %		    stb.st_blksize;#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */	size = blksize;#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */	if (bp->cnt >= size)		return (bp);	if (bp->buf == NULL)		bp->buf = xmalloc(size);	else		bp->buf = xrealloc(bp->buf, size);	memset(bp->buf, 0, size);	bp->cnt = size;	return (bp);}voidlostconn(signo)	int signo;{	if (!iamremote)		write(STDERR_FILENO, "lost connection\n", 16);	if (signo)		_exit(1);	else		exit(1);}static voidupdateprogressmeter(int ignore){	int save_errno = errno;	progressmeter(0);	signal(SIGALRM, updateprogressmeter);	alarm(PROGRESSTIME);	errno = save_errno;}static intforegroundproc(void){	static pid_t pgrp = -1;	int ctty_pgrp;	if (pgrp == -1)		pgrp = getpgrp();#ifdef HAVE_TCGETPGRP	return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 &&		ctty_pgrp == pgrp);#else	return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&		 ctty_pgrp == pgrp));#endif}voidprogressmeter(int flag){	static const char prefixes[] = " KMGTP";	static struct timeval lastupdate;	static off_t lastsize;	struct timeval now, td, wait;	off_t cursize, abbrevsize;	double elapsed;	int ratio, barlength, i, remaining;	char buf[512];	if (flag == -1) {		(void) gettimeofday(&start, (struct timezone *) 0);		lastupdate = start;		lastsize = 0;	}	if (foregroundproc() == 0)		return;	(void) gettimeofday(&now, (struct timezone *) 0);	cursize = statbytes;	if (totalbytes != 0) {		ratio = 100.0 * cursize / totalbytes;		ratio = MAX(ratio, 0);		ratio = MIN(ratio, 100);	} else		ratio = 100;	snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);	barlength = getttywidth() - 51;	if (barlength > 0) {		i = barlength * ratio / 100;		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),		    "|%.*s%*s|", i,		    "*******************************************************"		    "*******************************************************"		    "*******************************************************"		    "*******************************************************"		    "*******************************************************"		    "*******************************************************"		    "*******************************************************",		    barlength - i, "");	}	i = 0;	abbrevsize = cursize;	while (abbrevsize >= 100000 && i < sizeof(prefixes)) {		i++;		abbrevsize >>= 10;	}	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5lu %c%c ",	    (unsigned long) abbrevsize, prefixes[i],	    prefixes[i] == ' ' ? ' ' : 'B');	timersub(&now, &lastupdate, &wait);	if (cursize > lastsize) {		lastupdate = now;		lastsize = cursize;		if (wait.tv_sec >= STALLTIME) {			start.tv_sec += wait.tv_sec;			start.tv_usec += wait.tv_usec;		}		wait.tv_sec = 0;	}	timersub(&now, &start, &td);	elapsed = td.tv_sec + (td.tv_usec / 1000000.0);	if (flag != 1 &&	    (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),		    "   --:-- ETA");	} else if (wait.tv_sec >= STALLTIME) {		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),		    " - stalled -");	} else {		if (flag != 1)			remaining = (int)(totalbytes / (statbytes / elapsed) -			    elapsed);		else			remaining = elapsed;		i = remaining / 3600;		if (i)			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),			    "%2d:", i);		else			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),			    "   ");		i = remaining % 3600;		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),		    "%02d:%02d%s", i / 60, i % 60,		    (flag != 1) ? " ETA" : "    ");	}	atomicio(write, fileno(stdout), buf, strlen(buf));	if (flag == -1) {		mysignal(SIGALRM, updateprogressmeter);		alarm(PROGRESSTIME);	} else if (flag == 1) {		alarm(0);		atomicio(write, fileno(stdout), "\n", 1);		statbytes = 0;	}}intgetttywidth(void){	struct winsize winsize;	if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)		return (winsize.ws_col ? winsize.ws_col : 80);	else		return (80);}

⌨️ 快捷键说明

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