ref: 743124504e1558d594b2d9a3d0d329cc540435ed
dir: /union.c/
#include <u.h> #include <libc.h> int fatal = 1; void usage(void) { fprint(2, "%s: [-abcr] path [...] mtpt\n", argv0); exits("usage"); } void error(char *fmt, ...) { va_list arg; va_start(arg, fmt); vfprint(2, fmt, arg); va_end(arg); if(fatal) exits("fatal"); } int same(char *p, char *q) { int r; Dir *dp, *dq; r = 0; if((dp = dirstat(p)) == nil) error("dirstat: %r\n"); if((dq = dirstat(q)) == nil) error("dirstat: %r\n"); if(dp->type==dq->type && dp->dev==dq->dev && dp->qid.path==dq->qid.path && dp->qid.vers==dq->qid.vers && dp->qid.type==dq->qid.type) r = 1; free(dp); free(dq); return r; } void replace(char *p, char *q) { if((bind(p, q, MREPL)) < 0) error("bind %s %s: %r\n", p, q); } void after(char *p, char *q) { int fd; long n; char np[1024], nq[1024]; Dir *dir, *d; if(same(p, q) == 0) if((bind(p, q, MAFTER)) < 0) error("bind %s %s: %r\n", p, q); if((fd = open(p, OREAD)) < 0) sysfatal("open: %r"); if((n = dirreadall(fd, &dir)) < 0) error("dirreadall: %r\n"); close(fd); for(d = dir; n > 0; n--, d++){ if((d->mode&DMDIR) == 0) continue; snprint(np, sizeof np, "%s/%s", p, d->name); snprint(nq, sizeof nq, "%s/%s", q, d->name); after(np, nq); } } void before(char *p, char *q) { char *t; t = "/mnt/temp"; replace(p, t); after(q, t); replace(t, q); unmount(nil, t); } void main(int argc, char *argv[]) { int i; char *mtpt; int op; enum {After, Before, Replace}; op = After; ARGBEGIN{ default: usage(); case 'a': op = After; break; case 'b': op = Before; break; case 'r': op = Replace; break; case 'q': fatal = 0; break; }ARGEND; if(argc < 2) usage(); mtpt = argv[argc-1]; for(i = 0; i < argc-1; i++) switch(op){ default: usage(); case After: after(argv[i], mtpt); break; case Before: before(argv[i], mtpt); break; case Replace: replace(argv[i], mtpt); break; } }