📄 synctree.c
字号:
"%s: Master died prematurely.\n", arg0); exit(1); } bp= buf; } req= *bp++ & 0xFF; n--; if (req >= (int) ENTER) break; /* Master using slave to print to stdout: */ putchar(req); } DPRINTF("%s: request() == %s\n", ORDERS[req - (int) ENTER]); return (enum orders) req;}static void report(){ int r; DPRINTF("%s: reporting now!\n", 0); buckp= bucket; while (buckn > 0) { if ((r= write(chan[1], buckp, buckn)) < 0) perrx("report()"); buckp += r; buckn -= r; } buckp= bucket; buckn= 0;}static void inform(a) enum answers a;/* Slave replies to master. */{ DPRINTF("%s: inform(%s)\n", ANSWERS[(int) a - (int) PATH]); *buckp++ = (int) a; buckn++;}#define wwrite(buf, n) (memcpy(buckp, (buf), (n)), buckp+= (n), buckn+= (n))static void sendnum(n) long n;/* Send number from least to most significant byte. */{#if LITTLE_ENDIAN wwrite((char *) &n, sizeof(n));#else char buf[NUMBYTES]; buf[0]= (char) (n >> 0); buf[1]= (char) (n >> 8); buf[2]= (char) (n >> 16); buf[3]= (char) (n >> 24); wwrite(buf, sizeof(buf));#endif}static void send(buf, n) char *buf; int n;/* Slave sends size and contents of buf. */{ sendnum((long) n); if (n > 0) wwrite(buf, (size_t) n);}static void sendstat(stp) struct stat *stp;{ sendnum((long) stp->st_mode); sendnum((long) stp->st_uid); sendnum((long) stp->st_gid); sendnum((long) stp->st_rdev); sendnum((long) stp->st_size); sendnum((long) stp->st_mtime);}static int ask();static void slave()/* Carry out orders from the master, such as transmitting path names. * Note that the slave uses path, not Spath, the master uses Spath. */{ int f, n; char buf[CHUNK]; enum { run, done, die } state= run; do { switch (request()) { case ENTER: enter(); break; case ADVANCE: if (!advance() || state == done) { inform(DONE); state= done; } else { if (linkpath!=nil) { inform(LINK); send(linkpath, strlen(linkpath) + 1); } else if (S_ISLNK(st.st_mode)) { inform(SYMLINK); send(lnkpth, strlen(lnkpth) + 1); } else { inform(PATH); } send(path, strlen(path) + 1); sendstat(&st); } break; case CAT: if ((f= open(path, O_RDONLY))<0) { fprintf(stderr, "%s: Can't open %s", arg0, path); because(); inform(NODATA); break; } inform(DATA); do { n= read(f, buf, sizeof(buf)); if (n < 0) perr(path); send(buf, n); if (n > 0) report(); } while (n > 0); close(f); break; case CANCEL: cancellink(); break; case DIE_BAD: ex= 1; /*FALL THROUGH*/ case DIE: state= die; break; case POSITIVE: inform(ask('y') ? YES : NO); break; case NEGATIVE: inform(ask('n') ? YES : NO); break; case PASS_YES: inform(YES); break; case PASS_NO: inform(NO); break; default: fprintf(stderr, "%s: strange request\n", arg0); exit(1); } report(); } while (state != die);}static int execute(argv) char **argv;/* Execute a command and return its success or failure. */{ int pid, r, status; if ((pid= fork())<0) { perr("fork()"); return 0; } if (pid == 0) { execvp(argv[0], argv); perrx(argv[0]); } while ((r= wait(&status)) != pid) { if (r < 0) { perr(argv[0]); return 0; } } return status == 0;}static int removedir(dir) char *dir;/* Remove a directory and its contents. */{ static char *argv[] = { "rm", "-r", nil, nil }; printf("(rm -r %s)\n", dir); argv[2]= dir; return execute(argv);}static void order(o) enum orders o;/* Master tells slave what to do. */{ char c= (char) o; DPRINTF("%s: order(%s)\n", ORDERS[o - (int) ENTER]); if (write(chan[1], &c, 1) != 1) perrx("order()");}static void rread(buf, n) char *buf; int n;/* Master gets buf of size n from slave, doing multiple reads if needed. */{ int r; while (n > 0) { if (buckn == 0) { switch (buckn= read(chan[0], bucket, BUCKSIZE)) { case -1: perrx("reply channel from slave"); case 0: fprintf(stderr, "%s: slave died prematurely.\n", arg0); exit(1); } buckp= bucket; } r= n < buckn ? n : buckn; memcpy(buf, buckp, r); buckp+= r; buckn-= r; buf+= r; n-= r; }}static enum answers answer()/* Master reads slave's reply. */{ char c; int a; rread(&c, 1); a= c & 0xFF; DPRINTF("%s: answer() == %s\n", ANSWERS[a - (int) PATH]); return (enum answers) a;}static long recnum()/* Read number as pack of bytes from least to most significant. The data * is on the wire in little-endian format. (Mostly run on PC's). */{#if LITTLE_ENDIAN long n; rread((char *) &n, (int) sizeof(n)); return n;#else unsigned char buf[NUMBYTES]; rread(buf, sizeof(buf)); return buf[0] | ((unsigned) buf[1] << 8) | ((unsigned long) buf[2] << 16) | ((unsigned long) buf[3] << 24);#endif}static int receive(buf, max) char *buf; int max;/* Master get's data from slave, by first reading size, then data. */{ int n; n= recnum(); if (n > max) { fprintf(stderr, "%s: panic: Can't read %d bytes\n", arg0, n); exit(1); } if (n > 0) rread(buf, n); return n;}static void recstat(stp) struct stat *stp;{ stp->st_mode= recnum(); stp->st_uid= recnum(); stp->st_gid= recnum(); stp->st_rdev= recnum(); stp->st_size= recnum(); stp->st_mtime= recnum();}static int key(){ int c; static int tty= -1; if (tty < 0) tty= isatty(0); if (feof(stdin) || (c= getchar()) == EOF) { c= '\n'; if (tty) putchar('\n'); } if (!tty) putchar(c); return c;}static int ask(def) int def;/* Ask for a yes or no, anything else means choose def. */{ int y, c; if (chan[0] == 0) { /* I'm running remote, tell the slave to ask. */ fflush(stdout); order(def == 'y' ? POSITIVE : NEGATIVE); return answer() == YES; } printf("? (%c) ", def); fflush(stdout); do c= key(); while (c == ' ' || c == '\t'); y= c; while (c != '\n') c= key(); if (y != 'y' && y != 'Y' && y != 'n' && y != 'N') y= def; return y == 'y' || y == 'Y';}static void setmodes(silent) int silent;{ struct stat st; int change= 0; struct utimbuf tms; errno= 0; getstat(Spath, &st); if (backup && silent) { setstat(st.st_ino, &Sst); getstat(Spath, &st); } if (S_ISLNK(st.st_mode)) return; if (errno == 0 && st.st_mode != Sst.st_mode) { if (!backup) chmod(Spath, Sst.st_mode & 07777); change= 1; } if (errno == 0 && (st.st_uid != Sst.st_uid || st.st_gid != Sst.st_gid) && (backup || geteuid() == 0) ) { errno= 0; if (!backup) chown(Spath, Sst.st_uid, Sst.st_gid); change= 1; } if (backup && !silent) setstat(st.st_ino, &Sst); if (errno == 0 && S_ISREG(Sst.st_mode) && st.st_mtime != Sst.st_mtime) { time(&tms.actime); tms.modtime= Sst.st_mtime; errno= 0; utime(Spath, &tms); change= 1; } if (errno != 0) { fprintf(stderr, "%s: Can't set modes of %s", arg0, Spath); because(); } else if (change && !silent) { printf("Mode changed of %s\n", Spath); }}static void makeold(){ static struct utimbuf tms= { 0, 0 }; if (utime(Spath, &tms) < 0) { if (errno != ENOENT) { fprintf(stderr, "%s: can't make %s look old", arg0, Spath); because(); } } else { fprintf(stderr, "%s: made %s look old.\n", arg0, Spath); }}static int busy= 0;static void bail_out(sig) int sig;{ signal(sig, SIG_IGN); fprintf(stderr, "%s: Exiting after signal %d\n", arg0, sig); if (busy) { fprintf(stderr, "%s: was installing %s\n", arg0, Spath); makeold(); } order(DIE_BAD); exit(sig);}static int makenode(name, mode, addr, size) char *name; int mode; dev_t addr; off_t size;{ int r; if (!backup) { r= mknod(name, mode, addr); } else { if ((r= creat(name, 0644)) >= 0) close(r); } return r;}static void add(update) int update;/* Add Spath to the filesystem. */{ int f, n; char buf[CHUNK]; int forced_update= force && update; if (Slinkpath != nil && !S_ISLNK(Sst.st_mode)) { if (interact && !update) { printf("Link %s to %s", Spath, Slinkpath); if (!ask('n')) return; } if (link(Slinkpath, Spath) >= 0) { printf("Linked %s to %s\n", Spath, Slinkpath); return; } else { fprintf(stderr, "%s: Can't link %s to %s", arg0, Slinkpath, Spath); because(); /* Try to install instead. */ } } switch (Sst.st_mode & S_IFMT) { case S_IFDIR: if (!force) { printf("Add dir %s", Spath); if (!ask('n')) return; } if (mkdir(Spath, backup ? 0755 : Sst.st_mode) < 0) { perr(Spath); return; } printf("Directory %s created.\n", Spath); order(ENTER); break; case S_IFBLK: case S_IFCHR: case S_IFIFO: if (interact && !update) { printf("Create special file %s", Spath); if (!ask('n')) { order(CANCEL); return; } } if (makenode(Spath, Sst.st_mode, Sst.st_rdev, Sst.st_size)<0) { fprintf(stderr, "%s: Can't create special file %s",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -