📄 applylog.c
字号:
fprint(2, "stopped updating log apply time because of %s\n", name); skip = 1; continue; } SET(checkedmatch4); if(resolve1 == 's'){ USED(checkedmatch4); SET(checkedmatch2); goto DoCreate; } else if(resolve1 == 'c') break; conflict(name, "locally removed; will not update metadata"); skip = 1; continue; } if(!(dbd.mode&DMDIR) && (dbd.mtime != ld.mtime || dbd.length != ld.length)){ /* this check might be overkill */ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ if(!skip) fprint(2, "stopped updating log apply time because of %s\n", name); skip = 1; continue; } SET(checkedmatch4); if(resolve1 == 's') goto DoMeta; else if(resolve1 == 'c') break; conflict(name, "contents locally modified (%s); will not update metadata to %s %s %luo", dbd.mtime != ld.mtime ? "mtime" : dbd.length != ld.length ? "length" : "unknown", rd.uid, rd.gid, rd.mode); skip = 1; continue; } if((douid && strcmp(ld.uid, dbd.uid)!=0) || strcmp(ld.gid, dbd.gid)!=0 || ld.mode!=dbd.mode){ if(notexists(remote)){ addce(local); /* no skip=1 */ break; } if(!ismatch(name)){ if(!skip) fprint(2, "stopped updating log apply time because of %s\n", name); skip = 1; continue; } SET(checkedmatch4); if(resolve1 == 's') goto DoMeta; else if(resolve1 == 'c') break; conflict(name, "metadata locally changed; will not update metadata to %s %s %luo", rd.uid, rd.gid, rd.mode); skip = 1; continue; } if(!ismatch(name)){ if(!skip) fprint(2, "stopped updating log apply time because of %s\n", name); skip = 1; continue; } SET(checkedmatch4); DoMeta: USED(checkedmatch4); assert(ismatch(name)); if(notexists(remote)){ addce(local); /* no skip=1 */ break; } chat("m %q %luo %q %q %lud\n", name, rd.mode, rd.uid, rd.gid, rd.mtime); if(donothing) break; nulldir(&nd); nd.gid = rd.gid; nd.mode = rd.mode; if(douid) nd.uid = rd.uid; if(dirwstat(local, &nd) < 0){ error("dirwstat %q: %r", name); skip = 1; continue; } DoMetaDb: USED(checkedmatch4); assert(ismatch(name)); if(!havedb){ if(havelocal) dbd = ld; else dbd = rd; } if(dbd.mode&DMDIR) dbd.mtime = now; dbd.gid = rd.gid; dbd.mode = rd.mode; if(douid) dbd.uid = rd.uid; insertdb(clientdb, name, &dbd); break; } if(!skip && !donothing){ maxnow = now; maxn = n; } } w = avlwalk(copyerr->avl); while(e = (Entry*)avlnext(w)) error("copying %q: %s\n", e->name, e->d.name); if(timefile) writetimefile(); if(nconf) exits("conflicts"); if(errors) exits("errors"); exits(nil);}char*mkname(char *buf, int nbuf, char *a, char *b){ if(strlen(a)+strlen(b)+2 > nbuf) sysfatal("name too long"); strcpy(buf, a); if(a[strlen(a)-1] != '/') strcat(buf, "/"); strcat(buf, b); return buf;}intisdir(char *s){ ulong m; Dir *d; if((d = dirstat(s)) == nil) return 0; m = d->mode; free(d); return (m&DMDIR) != 0;}voidconflict(char *name, char *f, ...){ char *s; va_list arg; va_start(arg, f); s = vsmprint(f, arg); va_end(arg); fprint(2, "%s: %s\n", name, s); free(s); nconf++;// if(nconf%16 == 0)// conf = erealloc(conf, (nconf+16)*sizeof(conf[0]));// conf[nconf++] = estrdup(name);}voiderror(char *f, ...){ char *s; va_list arg; va_start(arg, f); s = vsmprint(f, arg); va_end(arg); fprint(2, "error: %s\n", s); free(s); errors = 1;}intismatch(char *s){ int i, len; if(nmatch == 0) return 1; for(i=0; i<nmatch; i++){ len = strlen(match[i]); if(len == 0) return 1; if(strncmp(s, match[i], len) == 0 && (s[len]=='/' || s[len] == 0)) return 1; } return 0;}intlocaldirstat(char *name, Dir *d){ static Dir *d2; free(d2); if((d2 = dirstat(name)) == nil) return -1; *d = *d2; return 0;}enum { DEFB = 8192 };static intcopy1(int fdf, int fdt, char *from, char *to){ int i, n, rv, pid[Nwork]; Waitmsg *w; n = 0; off = 0; for(i=0; i<Nwork; i++){ switch(pid[n] = rfork(RFPROC|RFMEM)){ case 0: notify(failure); worker(fdf, fdt, from, to); case -1: break; default: n++; break; } } if(n == 0){ fprint(2, "cp: rfork: %r\n"); return -1; } rv = 0; while((w = wait()) != nil){ if(w->msg[0]){ rv = -1; for(i=0; i<n; i++) if(pid[i] > 0) postnote(PNPROC, pid[i], "failure"); } free(w); } return rv;}voidworker(int fdf, int fdt, char *from, char *to){ char buf[DEFB], *bp; long len, n; vlong o; len = sizeof(buf); bp = buf; o = nextoff(); while(n = pread(fdf, bp, len, o)){ if(n < 0){ fprint(2, "reading %s: %r\n", from); _exits("bad"); } if(pwrite(fdt, buf, n, o) != n){ fprint(2, "writing %s: %r\n", to); _exits("bad"); } bp += n; o += n; len -= n; if(len == 0){ len = sizeof buf; bp = buf; o = nextoff(); } } _exits(nil);}vlongnextoff(void){ vlong o; qlock(&lk); o = off; off += DEFB; qunlock(&lk); return o;}voidfailure(void*, char *note){ if(strcmp(note, "failure") == 0) _exits(nil); noted(NDFLT);}static intopentemp(char *template){ int fd, i; char *p; p = estrdup(template); fd = -1; for(i=0; i<10; i++){ mktemp(p); if((fd=create(p, ORDWR|OEXCL|ORCLOSE, 0000)) >= 0) break; strcpy(p, template); } if(fd < 0) return -1; strcpy(template, p); free(p); return fd;}intcopyfile(char *local, char *remote, char *name, Dir *d, int dowstat, int *printerror){ Dir *d0, *d1, *dl; Dir nd; int rfd, tfd, wfd, didcreate; char tmp[32], *p, *safe; char err[ERRMAX];Again: *printerror = 0; if((rfd = open(remote, OREAD)) < 0) return -1; d0 = dirfstat(rfd); if(d0 == nil){ close(rfd); return -1; } *printerror = 1; if(!tempspool){ tfd = rfd; goto DoCopy; } strcpy(tmp, "/tmp/replicaXXXXXXXX"); tfd = opentemp(tmp); if(tfd < 0){ close(rfd); free(d0); return -1; } if(copy1(rfd, tfd, remote, tmp) < 0 || (d1 = dirfstat(rfd)) == nil){ close(rfd); close(tfd); free(d0); return -1; } close(rfd); if(d0->qid.path != d1->qid.path || d0->qid.vers != d1->qid.vers || d0->mtime != d1->mtime || d0->length != d1->length){ /* file changed underfoot; go around again */ close(tfd); free(d0); free(d1); goto Again; } free(d1); if(seek(tfd, 0, 0) != 0){ close(tfd); free(d0); return -1; }DoCopy: /* * clumsy but important hack to do safeinstall-like installs. */ p = strchr(name, '/'); if(safeinstall && p && strncmp(p, "/bin/", 5) == 0 && access(local, AEXIST) >= 0){ /* * remove bin/_targ */ safe = emalloc(strlen(local)+2); strcpy(safe, local); p = strrchr(safe, '/')+1; memmove(p+1, p, strlen(p)+1); p[0] = '_'; remove(safe); /* ignore failure */ /* * rename bin/targ to bin/_targ */ nulldir(&nd); nd.name = p; if(dirwstat(local, &nd) < 0) fprint(2, "warning: rename %s to %s: %r\n", local, p); } didcreate = 0; if((dl = dirstat(local)) == nil){ if((wfd = create(local, OWRITE, 0)) >= 0){ didcreate = 1; goto okay; } goto err; }else{ if((wfd = open(local, OTRUNC|OWRITE)) >= 0) goto okay; rerrstr(err, sizeof err); if(strstr(err, "permission") == nil) goto err; nulldir(&nd); /* * Assume the person running pull is in the appropriate * groups. We could set 0666 instead, but I'm worried * about leaving the file world-readable or world-writable * when it shouldn't be. */ nd.mode = dl->mode | 0660; if(nd.mode == dl->mode) goto err; if(dirwstat(local, &nd) < 0) goto err; if((wfd = open(local, OTRUNC|OWRITE)) >= 0){ nd.mode = dl->mode; if(dirfwstat(wfd, &nd) < 0) fprint(2, "warning: set mode on %s to 0660 to open; cannot set back to %luo: %r\n", local, nd.mode); goto okay; } nd.mode = dl->mode; if(dirwstat(local, &nd) < 0) fprint(2, "warning: set mode on %s to %luo to open; open failed; cannot set mode back to %luo: %r\n", local, nd.mode|0660, nd.mode); goto err; } err: close(tfd); free(d0); free(dl); return -1;okay: free(dl); if(copy1(tfd, wfd, tmp, local) < 0){ close(tfd); close(wfd); free(d0); return -1; } close(tfd); if(didcreate || dowstat){ nulldir(&nd); nd.mode = d->mode; if(dirfwstat(wfd, &nd) < 0) fprint(2, "warning: cannot set mode on %s\n", local); nulldir(&nd); nd.gid = d->gid; if(dirfwstat(wfd, &nd) < 0) fprint(2, "warning: cannot set gid on %s\n", local); if(douid){ nulldir(&nd); nd.uid = d->uid; if(dirfwstat(wfd, &nd) < 0) fprint(2, "warning: cannot set uid on %s\n", local); } } d->mtime = d0->mtime; d->length = d0->length; nulldir(&nd); nd.mtime = d->mtime; if(dirfwstat(wfd, &nd) < 0) fprint(2, "warning: cannot set mtime on %s\n", local); free(d0); close(wfd); return 0;}/* * Applylog might try to overwrite itself. * To avoid problems with this, we copy ourselves * into /tmp and then re-exec. */char *rmargv0;static voidrmself(void){ remove(rmargv0);}static intgenopentemp(char *template, int mode, int perm){ int fd, i; char *p; p = estrdup(template); fd = -1; for(i=0; i<10; i++){ mktemp(p); if(access(p, 0) < 0 && (fd=create(p, mode, perm)) >= 0) break; strcpy(p, template); } if(fd < 0) sysfatal("could not create temporary file"); strcpy(template, p); free(p); return fd;}static voidmembogus(char **argv){ int n, fd, wfd; char template[50], buf[1024]; if(strncmp(argv[0], "/tmp/_applylog_", 1+3+1+1+8+1)==0) { rmargv0 = argv[0]; atexit(rmself); return; } if((fd = open(argv[0], OREAD)) < 0) return; strcpy(template, "/tmp/_applylog_XXXXXX"); if((wfd = genopentemp(template, OWRITE, 0700)) < 0) return; while((n = read(fd, buf, sizeof buf)) > 0) if(write(wfd, buf, n) != n) goto Error; if(n != 0) goto Error; close(fd); close(wfd); argv[0] = template; exec(template, argv); fprint(2, "exec error %r\n");Error: close(fd); close(wfd); remove(template); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -