Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/replica/applychanges.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * push changes from client to server.
3
 */
4
#include "all.h"
5
 
6
int douid;
7
Db *db;
8
char **x;
9
int nx;
10
int justshow;
11
int verbose;
12
int conflicts;
13
char newpath[10000];
14
char oldpath[10000];
15
char *clientroot;
16
char *serverroot;
17
int copyfile(char*, char*, Dir*, int);
18
int metafile(char*, Dir*);
19
char **match;
20
int nmatch;
21
 
22
int
23
ismatch(char *s)
24
{
25
	int i, len;
26
 
27
	if(nmatch == 0)
28
		return 1;
29
	for(i=0; i<nmatch; i++){
30
		if(strcmp(s, match[i]) == 0)
31
			return 1;
32
		len = strlen(match[i]);
33
		if(strncmp(s, match[i], len) == 0 && s[len]=='/')
34
			return 1;
35
	}
36
	return 0;
37
}
38
 
39
void
40
xlog(char c, char *path, Dir *d)
41
{
42
	if(!verbose)
43
		return;
44
	print("%c %s %luo %s %s %lud\n", c, path, d->mode, d->uid, d->gid, d->mtime);
45
}
46
 
47
void
48
walk(char *new, char *old, Dir *pd, void*)
49
{
50
	int i, len;
51
	Dir od, d;
52
	static Dir *xd;
53
 
54
	new = unroot(new, "/");
55
	old = unroot(old, serverroot);
56
 
57
	if(!ismatch(new))
58
		return;
59
	if(xd != nil){
60
		free(xd);
61
		xd = nil;
62
	}
63
 
64
	for(i=0; i<nx; i++){
65
		if(strcmp(new, x[i]) == 0)
66
			return;
67
		len = strlen(x[i]);
68
		if(strncmp(new, x[i], len)==0 && new[len]=='/')
69
			return;
70
	}
71
 
72
	d = *pd;
73
	d.name = old;
74
	memset(&od, 0, sizeof od);
75
	snprint(newpath, sizeof newpath, "%s/%s", clientroot, new);
76
	snprint(oldpath, sizeof oldpath, "%s/%s", serverroot, old);
77
 
78
	xd = dirstat(oldpath);
79
	if(markdb(db, new, &od) < 0){
80
		if(xd != nil){
81
			print("x %s create/create conflict\n", new);
82
			conflicts = 1;
83
			return;
84
		}
85
		xlog('a', new, &d);
86
		d.muid = "mark";	/* mark bit */
87
		if(!justshow){
88
			if(copyfile(newpath, oldpath, &d, 1) == 0)
89
				insertdb(db, new, &d);
90
		}
91
	}else{
92
		if((d.mode&DMDIR)==0 && od.mtime!=d.mtime){
93
			if(xd==nil){
94
				print("%s update/remove conflict\n", new);
95
				conflicts = 1;
96
				return;
97
			}
98
			if(xd->mtime != od.mtime){
99
				print("%s update/update conflict\n", new);
100
				conflicts = 1;
101
				return;
102
			}
103
			od.mtime = d.mtime;
104
			od.muid = "mark";
105
			xlog('c', new, &od);
106
			if(!justshow){
107
				if(copyfile(newpath, oldpath, &od, 0) == 0)
108
					insertdb(db, new, &od);
109
			}
110
		}
111
		if((douid&&strcmp(od.uid,d.uid)!=0)
112
		|| strcmp(od.gid,d.gid)!=0 
113
		|| od.mode!=d.mode){
114
			if(xd==nil){
115
				print("%s metaupdate/remove conflict\n", new);
116
				conflicts = 1;
117
				return;
118
			}
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);
123
				conflicts = 1;
124
				return;
125
			}
126
			if(douid)
127
				od.uid = d.uid;
128
			od.gid = d.gid;
129
			od.mode = d.mode;
130
			od.muid = "mark";
131
			xlog('m', new, &od);
132
			if(!justshow){
133
				if(metafile(oldpath, &od) == 0)
134
					insertdb(db, new, &od);
135
			}
136
		}
137
	}
138
}
139
 
140
void
141
usage(void)
142
{
143
	fprint(2, "usage: replica/applychanges [-nuv] [-p proto] [-x path]... clientdb clientroot serverroot [path ...]\n");
144
	exits("usage");
145
}
146
 
147
void
148
main(int argc, char **argv)
149
{
150
	char *proto;
151
	Avlwalk *w;
152
	Dir *xd, d;
153
	Entry *e;
154
 
155
	quotefmtinstall();
156
	proto = "/sys/lib/sysconfig/proto/allproto";
157
	ARGBEGIN{
158
	case 'n':
159
		justshow = 1;
160
		verbose = 1;
161
		break;
162
	case 'p':
163
		proto = EARGF(usage());
164
		break;
165
	case 'u':
166
		douid = 1;
167
		break;
168
	case 'v':
169
		verbose = 1;
170
		break;
171
	case 'x':
172
		if(nx%16 == 0)
173
			x = erealloc(x, (nx+16)*sizeof(x[0]));
174
		x[nx++] = EARGF(usage());
175
		break;
176
	default:
177
		usage();
178
	}ARGEND
179
 
180
	if(argc < 3)
181
		usage();
182
 
183
	db = opendb(argv[0]);
184
	clientroot = argv[1];
185
	serverroot = argv[2];
186
	match = argv+3;
187
	nmatch = argc-3;
188
 
189
 
190
	if(revrdproto(proto, clientroot, serverroot, walk, nil, nil) < 0)
191
		sysfatal("rdproto: %r");
192
 
193
	w = avlwalk(db->avl);
194
	while(e = (Entry*)avlprev(w)){
195
		if(!ismatch(e->name))
196
			continue;
197
		if(!e->d.mark){		/* not visited during walk */
198
			snprint(newpath, sizeof newpath, "%s/%s", clientroot, e->name);
199
			snprint(oldpath, sizeof oldpath, "%s/%s", serverroot, e->d.name);
200
			xd = dirstat(oldpath);
201
			if(xd == nil){
202
				removedb(db, e->name);
203
				continue;
204
			}
205
			if(xd->mtime != e->d.mtime && (e->d.mode&xd->mode&DMDIR)==0){
206
				print("x %q remove/update conflict\n", e->name);
207
				free(xd);
208
				continue;
209
			}
210
			memset(&d, 0, sizeof d);
211
			d.name = e->d.name;
212
			d.uid = e->d.uid;
213
			d.gid = e->d.gid;
214
			d.mtime = e->d.mtime;
215
			d.mode = e->d.mode;
216
			xlog('d', e->name, &d);
217
			if(!justshow){
218
				if(remove(oldpath) == 0)
219
					removedb(db, e->name);
220
			}
221
			free(xd);
222
		}
223
	}
224
 
225
	if(conflicts)
226
		exits("conflicts");
227
	exits(nil);
228
}
229
 
230
enum { DEFB = 8192 };
231
 
232
static int
233
copy1(int fdf, int fdt, char *from, char *to)
234
{
235
	char buf[DEFB];
236
	long n, n1, rcount;
237
	int rv;
238
	char err[ERRMAX];
239
 
240
	/* clear any residual error */
241
	err[0] = '\0';
242
	errstr(err, ERRMAX);
243
	rv = 0;
244
	for(rcount=0;; rcount++) {
245
		n = read(fdf, buf, DEFB);
246
		if(n <= 0)
247
			break;
248
		n1 = write(fdt, buf, n);
249
		if(n1 != n) {
250
			fprint(2, "error writing %q: %r\n", to);
251
			rv = -1;
252
			break;
253
		}
254
	}
255
	if(n < 0) {
256
		fprint(2, "error reading %q: %r\n", from);
257
		rv = -1;
258
	}
259
	return rv;
260
}
261
 
262
int
263
copyfile(char *from, char *to, Dir *d, int dowstat)
264
{
265
	Dir nd;
266
	int rfd, wfd, didcreate;
267
 
268
	if((rfd = open(from, OREAD)) < 0)
269
		return -1;
270
 
271
	didcreate = 0;
272
	if(d->mode&DMDIR){
273
		if((wfd = create(to, OREAD, DMDIR)) < 0){
274
			fprint(2, "mkdir %q: %r\n", to);
275
			close(rfd);
276
			return -1;
277
		}
278
	}else{
279
		if((wfd = open(to, OTRUNC|OWRITE)) < 0){
280
			if((wfd = create(to, OWRITE, 0)) < 0){
281
				close(rfd);
282
				return -1;
283
			}
284
			didcreate = 1;
285
		}
286
		if(copy1(rfd, wfd, from, to) < 0){
287
			close(rfd);
288
			close(wfd);
289
			return -1;
290
		}
291
	}
292
	close(rfd);
293
	if(didcreate || dowstat){
294
		nulldir(&nd);
295
		nd.mode = d->mode;
296
		if(dirfwstat(wfd, &nd) < 0)
297
			fprint(2, "warning: cannot set mode on %q\n", to);
298
		nulldir(&nd);
299
		nd.gid = d->gid;
300
		if(dirfwstat(wfd, &nd) < 0)
301
			fprint(2, "warning: cannot set gid on %q\n", to);
302
		if(douid){
303
			nulldir(&nd);
304
			nd.uid = d->uid;
305
			if(dirfwstat(wfd, &nd) < 0)
306
				fprint(2, "warning: cannot set uid on %q\n", to);
307
		}
308
	}
309
	nulldir(&nd);
310
	nd.mtime = d->mtime;
311
	if(dirfwstat(wfd, &nd) < 0)
312
		fprint(2, "warning: cannot set mtime on %q\n", to);
313
	close(wfd);
314
	return 0;
315
}
316
 
317
int
318
metafile(char *path, Dir *d)
319
{
320
	Dir nd;
321
 
322
	nulldir(&nd);
323
	nd.gid = d->gid;
324
	nd.mode = d->mode;
325
	if(douid)
326
		nd.uid = d->uid;
327
	if(dirwstat(path, &nd) < 0){
328
		fprint(2, "dirwstat %q: %r\n", path);
329
		return -1;
330
	}
331
	return 0;
332
}