2 * push changes from client to server.
17 int copyfile(char*, char*, Dir*, int);
18 int metafile(char*, Dir*);
29 for(i=0; i<nmatch; i++){
30 if(strcmp(s, match[i]) == 0)
32 len = strlen(match[i]);
33 if(strncmp(s, match[i], len) == 0 && s[len]=='/')
40 xlog(char c, char *path, Dir *d)
44 print("%c %s %luo %s %s %lud\n", c, path, d->mode, d->uid, d->gid, d->mtime);
48 walk(char *new, char *old, Dir *pd, void*)
54 new = unroot(new, "/");
55 old = unroot(old, serverroot);
65 if(strcmp(new, x[i]) == 0)
68 if(strncmp(new, x[i], len)==0 && new[len]=='/')
74 memset(&od, 0, sizeof od);
75 snprint(newpath, sizeof newpath, "%s/%s", clientroot, new);
76 snprint(oldpath, sizeof oldpath, "%s/%s", serverroot, old);
78 xd = dirstat(oldpath);
79 if(markdb(db, new, &od) < 0){
81 print("x %s create/create conflict\n", new);
86 d.muid = "mark"; /* mark bit */
88 if(copyfile(newpath, oldpath, &d, 1) == 0)
89 insertdb(db, new, &d);
92 if((d.mode&DMDIR)==0 && od.mtime!=d.mtime){
94 print("%s update/remove conflict\n", new);
98 if(xd->mtime != od.mtime){
99 print("%s update/update conflict\n", new);
107 if(copyfile(newpath, oldpath, &od, 0) == 0)
108 insertdb(db, new, &od);
111 if((douid&&strcmp(od.uid,d.uid)!=0)
112 || strcmp(od.gid,d.gid)!=0
115 print("%s metaupdate/remove conflict\n", new);
119 if((douid&&strcmp(od.uid,xd->uid)!=0)
120 || strcmp(od.uid,xd->gid)!=0
121 || od.mode!=xd->mode){
122 print("%s metaupdate/metaupdate conflict\n", new);
133 if(metafile(oldpath, &od) == 0)
134 insertdb(db, new, &od);
143 fprint(2, "usage: replica/applychanges [-nuv] [-p proto] [-x path]... clientdb clientroot serverroot [path ...]\n");
148 main(int argc, char **argv)
155 proto = "/sys/lib/sysconfig/proto/allproto";
162 proto = EARGF(usage());
172 x = erealloc(x, (nx+16)*sizeof(x[0]));
173 x[nx++] = EARGF(usage());
182 db = opendb(argv[0]);
183 clientroot = argv[1];
184 serverroot = argv[2];
189 if(revrdproto(proto, clientroot, serverroot, walk, nil, nil) < 0)
190 sysfatal("rdproto: %r");
192 for(e = (Entry*)avlmax(db->avl); e != nil; e = (Entry*)avlprev(e)){
193 if(!ismatch(e->name))
195 if(!e->d.mark){ /* not visited during walk */
196 snprint(newpath, sizeof newpath, "%s/%s", clientroot, e->name);
197 snprint(oldpath, sizeof oldpath, "%s/%s", serverroot, e->d.name);
198 xd = dirstat(oldpath);
200 removedb(db, e->name);
203 if(xd->mtime != e->d.mtime && (e->d.mode&xd->mode&DMDIR)==0){
204 print("x %q remove/update conflict\n", e->name);
208 memset(&d, 0, sizeof d);
212 d.mtime = e->d.mtime;
214 xlog('d', e->name, &d);
216 if(remove(oldpath) == 0)
217 removedb(db, e->name);
228 enum { DEFB = 8192 };
231 copy1(int fdf, int fdt, char *from, char *to)
238 /* clear any residual error */
242 for(rcount=0;; rcount++) {
243 n = read(fdf, buf, DEFB);
246 n1 = write(fdt, buf, n);
248 fprint(2, "error writing %q: %r\n", to);
254 fprint(2, "error reading %q: %r\n", from);
261 copyfile(char *from, char *to, Dir *d, int dowstat)
264 int rfd, wfd, didcreate;
266 if((rfd = open(from, OREAD)) < 0)
271 if((wfd = create(to, OREAD, DMDIR)) < 0){
272 fprint(2, "mkdir %q: %r\n", to);
277 if((wfd = open(to, OTRUNC|OWRITE)) < 0){
278 if((wfd = create(to, OWRITE, 0)) < 0){
284 if(copy1(rfd, wfd, from, to) < 0){
291 if(didcreate || dowstat){
294 if(dirfwstat(wfd, &nd) < 0)
295 fprint(2, "warning: cannot set mode on %q\n", to);
298 if(dirfwstat(wfd, &nd) < 0)
299 fprint(2, "warning: cannot set gid on %q\n", to);
303 if(dirfwstat(wfd, &nd) < 0)
304 fprint(2, "warning: cannot set uid on %q\n", to);
309 if(dirfwstat(wfd, &nd) < 0)
310 fprint(2, "warning: cannot set mtime on %q\n", to);
316 metafile(char *path, Dir *d)
325 if(dirwstat(path, &nd) < 0){
326 fprint(2, "dirwstat %q: %r\n", path);