📄 server.c
字号:
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 + -