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

📄 server.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (lp == NULL)		log(lfp, "out of memory, link information lost\n");	else {		lp->nextp = ihead;		ihead = lp;		lp->inum = stp->st_ino;		lp->devnum = stp->st_dev;		lp->count = stp->st_nlink - 1;		strcpy(lp->pathname, target);		if (Tdest)			strcpy(lp->target, Tdest);		else			*lp->target = 0;	}	return(NULL);}/* * Check to see if file needs to be updated on the remote machine. * Returns 0 if no update, 1 if remote doesn't exist, 2 if out of date * and 3 if comparing binaries to determine if out of date. */static intupdate(rname, opts, stp)	char *rname;	int opts;	struct stat *stp;{	register char *cp, *s;	register off_t size;	register time_t mtime;	if (debug) 		printf("update(%s, %x, %x)\n", rname, opts, stp);	/*	 * Check to see if the file exists on the remote machine.	 */	(void) sprintf(buf, "Q%s\n", rname);	if (debug)		printf("buf = %s", buf);	(void) write(rem, buf, strlen(buf));again:	cp = s = buf;	do {		if (read(rem, cp, 1) != 1)			lostconn(0);	} while (*cp++ != '\n' && cp < &buf[BUFSIZ]);	switch (*s++) {	case 'Y':		break;	case 'N':  /* file doesn't exist so install it */		return(1);	case '\1':		nerrs++;		if (*s != '\n') {			if (!iamremote) {				fflush(stdout);				(void) write(2, s, cp - s);			}			if (lfp != NULL)				(void) fwrite(s, 1, cp - s, lfp);		}		return(0);	case '\3':		*--cp = '\0';		if (lfp != NULL) 			log(lfp, "update: note: %s\n", s);		goto again;	default:		*--cp = '\0';		error("update: unexpected response '%s'\n", s);		return(0);	}	if (*s == '\n')		return(2);	if (opts & COMPARE)		return(3);	size = 0;	while (isdigit(*s))		size = size * 10 + (*s++ - '0');	if (*s++ != ' ') {		error("update: size not delimited\n");		return(0);	}	mtime = 0;	while (isdigit(*s))		mtime = mtime * 10 + (*s++ - '0');	if (*s != '\n') {		error("update: mtime not delimited\n");		return(0);	}	/*	 * File needs to be updated?	 */	if (opts & YOUNGER) {		if (stp->st_mtime == mtime)			return(0);		if (stp->st_mtime < mtime) {			log(lfp, "Warning: %s: remote copy is newer\n", target);			return(0);		}	} else if (stp->st_mtime == mtime && stp->st_size == size)		return(0);	return(2);}/* * Query. Check to see if file exists. Return one of the following: *	N\n		- doesn't exist *	Ysize mtime\n	- exists and its a regular file (size & mtime of file) *	Y\n		- exists and its a directory or symbolic link *	^Aerror message\n */static voidquery(name)	char *name;{	struct stat stb;	if (catname)		(void) sprintf(tp, "/%s", name);	if (lstat(target, &stb) < 0) {		if (errno == ENOENT)			(void) write(rem, "N\n", 2);		else			error("%s:%s: %s\n", host, target, strerror(errno));		*tp = '\0';		return;	}	switch (stb.st_mode & S_IFMT) {	case S_IFREG:		(void) sprintf(buf, "Y%qd %ld\n", stb.st_size, stb.st_mtime);		(void) write(rem, buf, strlen(buf));		break;	case S_IFLNK:	case S_IFDIR:		(void) write(rem, "Y\n", 2);		break;	default:		error("%s: not a file or directory\n", name);		break;	}	*tp = '\0';}static voidrecvf(cmd, type)	char *cmd;	int type;{	register char *cp;	int f, mode, opts, wrerr, olderrno;	off_t i, size;	time_t mtime;	struct stat stb;	struct timeval tvp[2];	char *owner, *group;	char new[BUFSIZ];	extern char *tempname;	cp = cmd;	opts = 0;	while (*cp >= '0' && *cp <= '7')		opts = (opts << 3) | (*cp++ - '0');	if (*cp++ != ' ') {		error("recvf: options not delimited\n");		return;	}	mode = 0;	while (*cp >= '0' && *cp <= '7')		mode = (mode << 3) | (*cp++ - '0');	if (*cp++ != ' ') {		error("recvf: mode not delimited\n");		return;	}	size = 0;	while (isdigit(*cp))		size = size * 10 + (*cp++ - '0');	if (*cp++ != ' ') {		error("recvf: size not delimited\n");		return;	}	mtime = 0;	while (isdigit(*cp))		mtime = mtime * 10 + (*cp++ - '0');	if (*cp++ != ' ') {		error("recvf: mtime not delimited\n");		return;	}	owner = cp;	while (*cp && *cp != ' ')		cp++;	if (*cp != ' ') {		error("recvf: owner name not delimited\n");		return;	}	*cp++ = '\0';	group = cp;	while (*cp && *cp != ' ')		cp++;	if (*cp != ' ') {		error("recvf: group name not delimited\n");		return;	}	*cp++ = '\0';	if (type == S_IFDIR) {		if (catname >= sizeof(stp)) {			error("%s:%s: too many directory levels\n",				host, target);			return;		}		stp[catname] = tp;		if (catname++) {			*tp++ = '/';			while (*tp++ = *cp++)				;			tp--;		}		if (opts & VERIFY) {			ack();			return;		}		if (lstat(target, &stb) == 0) {			if (ISDIR(stb.st_mode)) {				if ((stb.st_mode & 07777) == mode) {					ack();					return;				}				buf[0] = '\0';				(void) sprintf(buf + 1,					"%s: Warning: remote mode %o != local mode %o\n",					target, stb.st_mode & 07777, mode);				(void) write(rem, buf, strlen(buf + 1) + 1);				return;			}			errno = ENOTDIR;		} else if (errno == ENOENT && (mkdir(target, mode) == 0 ||		    chkparent(target) == 0 && mkdir(target, mode) == 0)) {			if (fchog(-1, target, owner, group, mode) == 0)				ack();			return;		}		error("%s:%s: %s\n", host, target, strerror(errno));		tp = stp[--catname];		*tp = '\0';		return;	}	if (catname)		(void) sprintf(tp, "/%s", cp);	cp = rindex(target, '/');	if (cp == NULL)		strcpy(new, tempname);	else if (cp == target)		(void) sprintf(new, "/%s", tempname);	else {		*cp = '\0';		(void) sprintf(new, "%s/%s", target, tempname);		*cp = '/';	}	if (type == S_IFLNK) {		int j;		ack();		cp = buf;		for (i = 0; i < size; i += j) {			if ((j = read(rem, cp, size - i)) <= 0)				cleanup(0);			cp += j;		}		*cp = '\0';		if (response() < 0) {			err();			return;		}		if (symlink(buf, new) < 0) {			if (errno != ENOENT || chkparent(new) < 0 ||			    symlink(buf, new) < 0)				goto badnew1;		}		mode &= 0777;		if (opts & COMPARE) {			char tbuf[BUFSIZ];			if ((i = readlink(target, tbuf, BUFSIZ)) >= 0 &&			    i == size && strncmp(buf, tbuf, size) == 0) {				(void) unlink(new);				ack();				return;			}			if (opts & VERIFY)				goto differ;		}		goto fixup;	}	if ((f = creat(new, mode)) < 0) {		if (errno != ENOENT || chkparent(new) < 0 ||		    (f = creat(new, mode)) < 0)			goto badnew1;	}	ack();	wrerr = 0;	for (i = 0; i < size; i += BUFSIZ) {		int amt = BUFSIZ;		cp = buf;		if (i + amt > size)			amt = size - i;		do {			int j = read(rem, cp, amt);			if (j <= 0) {				(void) close(f);				(void) unlink(new);				cleanup(0);			}			amt -= j;			cp += j;		} while (amt > 0);		amt = BUFSIZ;		if (i + amt > size)			amt = size - i;		if (wrerr == 0 && write(f, buf, amt) != amt) {			olderrno = errno;			wrerr++;		}	}	if (response() < 0) {		err();		goto badnew2;	}	if (wrerr)		goto badnew1;	if (opts & COMPARE) {		FILE *f1, *f2;		int c;		if ((f1 = fopen(target, "r")) == NULL)			goto badtarget;		if ((f2 = fopen(new, "r")) == NULL) {badnew1:		error("%s:%s: %s\n", host, new, strerror(errno));			goto badnew2;		}		while ((c = getc(f1)) == getc(f2))			if (c == EOF) {				(void) fclose(f1);				(void) fclose(f2);				ack();				goto badnew2;			}		(void) fclose(f1);		(void) fclose(f2);		if (opts & VERIFY) {differ:			buf[0] = '\0';			(void) sprintf(buf + 1, "need to update: %s\n",target);			(void) write(rem, buf, strlen(buf + 1) + 1);			goto badnew2;		}	}	/*	 * Set last modified time	 */	tvp[0].tv_sec = time(0);	tvp[0].tv_usec = 0;	tvp[1].tv_sec = mtime;	tvp[1].tv_usec = 0;	if (utimes(new, tvp) < 0)		note("%s: utimes failed %s: %s\n", host, new, strerror(errno));	if (fchog(f, new, owner, group, mode) < 0) {badnew2:	(void) close(f);		(void) unlink(new);		return;	}	(void) close(f);fixup:	if (rename(new, target) < 0) {badtarget:	error("%s:%s: %s\n", host, target, strerror(errno));		(void) unlink(new);		return;	}	if (opts & COMPARE) {		buf[0] = '\0';		(void) sprintf(buf + 1, "updated %s\n", target);		(void) write(rem, buf, strlen(buf + 1) + 1);	} else		ack();}/* * Creat a hard link to existing file. */static voidhardlink(cmd)	char *cmd;{	register char *cp;	struct stat stb;	char *oldname;	int opts, exists = 0;	cp = cmd;	opts = 0;	while (*cp >= '0' && *cp <= '7')		opts = (opts << 3) | (*cp++ - '0');	if (*cp++ != ' ') {		error("hardlink: options not delimited\n");		return;	}	oldname = cp;	while (*cp && *cp != ' ')		cp++;	if (*cp != ' ') {		error("hardlink: oldname name not delimited\n");		return;	}	*cp++ = '\0';	if (catname) {		(void) sprintf(tp, "/%s", cp);	}	if (lstat(target, &stb) == 0) {		int mode = stb.st_mode & S_IFMT;		if (mode != S_IFREG && mode != S_IFLNK) {			error("%s:%s: not a regular file\n", host, target);			return;		}		exists = 1;	}	if (chkparent(target) < 0 ) {		error("%s:%s: %s (no parent)\n",			host, target, strerror(errno));		return;	}	if (exists && (unlink(target) < 0)) {		error("%s:%s: %s (unlink)\n",			host, target, strerror(errno));		return;	}	if (link(oldname, target) < 0) {		error("%s:can't link %s to %s\n",			host, target, oldname);		return;	}	ack();}/* * Check to see if parent directory exists and create one if not. */static intchkparent(name)	char *name;{	register char *cp;	struct stat stb;	cp = rindex(name, '/');	if (cp == NULL || cp == name)		return(0);	*cp = '\0';	if (lstat(name, &stb) < 0) {		if (errno == ENOENT && chkparent(name) >= 0 &&		    mkdir(name, 0777 & ~oumask) >= 0) {			*cp = '/';			return(0);		}	} else if (ISDIR(stb.st_mode)) {		*cp = '/';		return(0);	}	*cp = '/';	return(-1);}/* * Change owner, group and mode of file. */static intfchog(fd, file, owner, group, mode)	int fd;	char *file, *owner, *group;	int mode;{	register int i;	int uid, gid;	extern char user[];	extern int userid;	uid = userid;	if (userid == 0) {		if (*owner == ':') {			uid = atoi(owner + 1);		} else if (pw == NULL || strcmp(owner, pw->pw_name) != 0) {			if ((pw = getpwnam(owner)) == NULL) {				if (mode & 04000) {					note("%s:%s: unknown login name, clearing setuid",						host, owner);					mode &= ~04000;					uid = 0;				}			} else				uid = pw->pw_uid;		} else			uid = pw->pw_uid;		if (*group == ':') {			gid = atoi(group + 1);			goto ok;		}	} else if ((mode & 04000) && strcmp(user, owner) != 0)

⌨️ 快捷键说明

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