Browse Source

Plan 9 from Bell Labs 2003-02-17

David du Colombier 21 years ago
parent
commit
15d26dde90

+ 23 - 0
dist/replica/inst

@@ -0,0 +1,23 @@
+#!/bin/rc
+
+# Generic plan9 installation template.
+# Assumes that distribution CD or sources
+# is mounted at /n/dist, and should be installed
+# to /n/inst.
+
+s=/n/dist/dist/replica
+serverroot=/n/dist
+serverlog=$s/plan9.log
+serverproto=$s/plan9.proto
+fn servermount { status='' } 
+fn serverupdate { status='' }
+
+fn clientmount { status='' }
+c=/n/inst/dist/replica
+clientroot=/n/inst
+clientproto=$c/plan9.proto
+clientdb=$c/client/plan9.db
+clientexclude=(dist/replica/client)
+clientlog=$c/client/plan9.log
+
+applyopt=(-t -u -T$c/client/plan9.time)

+ 11 - 11
dist/replica/plan9.db

@@ -125,7 +125,7 @@
 386/bin/aux/stub - 775 sys sys 1039758546 133120
 386/bin/aux/tcpostio - 775 sys sys 1038443105 199714
 386/bin/aux/text2post - 775 sys sys 1039758546 77253
-386/bin/aux/timesync - 775 sys sys 1039758546 125710
+386/bin/aux/timesync - 775 sys sys 1045435076 127693
 386/bin/aux/tr2post - 775 sys sys 1039758547 175495
 386/bin/aux/trampoline - 775 sys sys 1039758547 81154
 386/bin/aux/typepasswd - 775 sys sys 1039758547 68151
@@ -322,7 +322,7 @@
 386/bin/read - 775 sys sys 1039758585 56544
 386/bin/replica - 20000000775 sys sys 1018321168 0
 386/bin/replica/applychanges - 775 sys sys 1039758585 99044
-386/bin/replica/applylog - 775 sys sys 1039758585 98429
+386/bin/replica/applylog - 775 sys sys 1045407499 98978
 386/bin/replica/changes - 775 sys sys 1020319082 42
 386/bin/replica/compactdb - 775 sys sys 1039758586 77913
 386/bin/replica/pull - 775 sys sys 1020319083 39
@@ -3253,7 +3253,7 @@ sys/include/authsrv.h - 664 sys sys 1014929062 4542
 sys/include/bin.h - 664 sys sys 1014929062 215
 sys/include/bio.h - 664 sys sys 1014929062 1854
 sys/include/bootexec.h - 664 sys sys 1014929062 3144
-sys/include/control.h - 664 sys sys 1040451728 4829
+sys/include/control.h - 664 sys sys 1045419238 4801
 sys/include/ctype.h - 664 sys sys 1014929062 951
 sys/include/cursor.h - 664 sys sys 1014929062 102
 sys/include/disk.h - 664 sys sys 1014929063 1096
@@ -4367,7 +4367,7 @@ sys/lib/wiki/page.txt - 664 sys sys 1018580959 12
 sys/lib/wiki/sandbox - 664 sys sys 1018580959 102
 sys/lib/wiki/werror.html - 664 sys sys 1018580959 1234
 sys/lib/yaccpar - 664 sys sys 944956052 4588
-sys/lib/yaccpars - 664 sys sys 944956052 4673
+sys/lib/yaccpars - 664 sys sys 1045432683 4596
 sys/log - 20000000775 sys sys 984760091 0
 sys/log/aan - 10000000666 sys sys 1019856844 0
 sys/log/auth - 10000000666 sys sys 959261821 0
@@ -5029,7 +5029,7 @@ sys/src/9/ip/icmp6.c - 664 sys sys 1045063518 18086
 sys/src/9/ip/igmp.c - 664 sys sys 1026847566 5185
 sys/src/9/ip/il.c - 664 sys sys 1028566049 26975
 sys/src/9/ip/inferno.c - 664 sys sys 1022588098 517
-sys/src/9/ip/ip.c - 664 sys sys 1045063517 15146
+sys/src/9/ip/ip.c - 664 sys sys 1045432713 15274
 sys/src/9/ip/ip.h - 664 sys sys 1045063514 15846
 sys/src/9/ip/ipaux.c - 664 sys sys 1022588098 12656
 sys/src/9/ip/ipifc.c - 664 sys sys 1045063513 37702
@@ -5044,7 +5044,7 @@ sys/src/9/ip/nullmedium.c - 664 sys sys 1022588099 491
 sys/src/9/ip/pktmedium.c - 664 sys sys 1045063516 1355
 sys/src/9/ip/ptclbsum.c - 664 sys sys 1022588099 1243
 sys/src/9/ip/rudp.c - 664 sys sys 1026847569 21413
-sys/src/9/ip/tcp.c - 664 sys sys 1045063512 64964
+sys/src/9/ip/tcp.c - 664 sys sys 1045432714 65108
 sys/src/9/ip/tripmedium.c - 664 sys sys 1045063515 7136
 sys/src/9/ip/udp.c - 664 sys sys 1026847570 13046
 sys/src/9/mkfile - 664 sys sys 1017795039 191
@@ -6576,7 +6576,7 @@ sys/src/cmd/aux/rdwr.c - 664 sys sys 1016833876 811
 sys/src/cmd/aux/reboot.c - 664 sys sys 1014925091 1411
 sys/src/cmd/aux/searchfs.c - 664 sys sys 1014925091 18176
 sys/src/cmd/aux/stub.c - 664 sys sys 1032468954 2637
-sys/src/cmd/aux/timesync.c - 664 sys sys 1022590195 23211
+sys/src/cmd/aux/timesync.c - 664 sys sys 1045435060 24288
 sys/src/cmd/aux/trampoline.c - 664 sys sys 1034780422 3571
 sys/src/cmd/aux/typepasswd.c - 664 sys sys 1014925091 1761
 sys/src/cmd/aux/unlock - 664 sys sys 944960793 0
@@ -6978,10 +6978,10 @@ sys/src/cmd/exportfs/mkfile - 664 sys sys 1036979221 204
 sys/src/cmd/faces - 20000000775 sys sys 952888246 0
 sys/src/cmd/faces/dblook.c - 664 sys sys 944961084 359
 sys/src/cmd/faces/facedb.c - 664 sys sys 1021579994 8976
-sys/src/cmd/faces/faces.h - 664 sys sys 1035698248 1046
-sys/src/cmd/faces/main.c - 664 sys sys 1035698249 13402
+sys/src/cmd/faces/faces.h - 664 sys sys 1045419243 1071
+sys/src/cmd/faces/main.c - 664 sys sys 1045419249 13505
 sys/src/cmd/faces/mkfile - 664 sys sys 1035698248 378
-sys/src/cmd/faces/plumb.c - 664 sys sys 1035698249 6925
+sys/src/cmd/faces/plumb.c - 664 sys sys 1045419249 7132
 sys/src/cmd/faces/util.c - 664 sys sys 1035698250 569
 sys/src/cmd/factor.c - 664 sys sys 944961351 1348
 sys/src/cmd/fax - 20000000775 sys sys 954036333 0
@@ -9644,7 +9644,7 @@ sys/src/cmd/read.c - 664 sys sys 1022047660 1278
 sys/src/cmd/replica - 20000000775 sys sys 1018321113 0
 sys/src/cmd/replica/all.h - 664 sys sys 1018323474 1181
 sys/src/cmd/replica/applychanges.c - 664 sys sys 1032060505 5858
-sys/src/cmd/replica/applylog.c - 664 sys sys 1019525023 15879
+sys/src/cmd/replica/applylog.c - 664 sys sys 1045407499 16476
 sys/src/cmd/replica/avl.c - 664 sys sys 1018321111 6202
 sys/src/cmd/replica/compactdb.c - 664 sys sys 1018323475 652
 sys/src/cmd/replica/db.c - 664 sys sys 1019340165 2989

+ 11 - 0
dist/replica/plan9.log

@@ -17299,3 +17299,14 @@
 1045164780 1 a sys/lib/lp/process/psextract - 775 sys sys 1045164704 777
 1045236676 0 c sys/man/4/srv - 664 sys sys 1045236157 4649
 1045337480 0 a sys/src/libc/386/387/mkfile - 664 sys sys 1045336041 157
+1045407646 0 c 386/bin/replica/applylog - 775 sys sys 1045407499 98978
+1045407646 1 c sys/src/cmd/replica/applylog.c - 664 sys sys 1045407499 16476
+1045420251 0 c sys/include/control.h - 664 sys sys 1045419238 4801
+1045420251 1 c sys/src/cmd/faces/faces.h - 664 sys sys 1045419243 1071
+1045420251 2 c sys/src/cmd/faces/main.c - 664 sys sys 1045419249 13505
+1045420251 3 c sys/src/cmd/faces/plumb.c - 664 sys sys 1045419249 7132
+1045432863 0 c sys/lib/yaccpars - 664 sys sys 1045432683 4596
+1045432863 1 c sys/src/9/ip/ip.c - 664 sys sys 1045432713 15274
+1045432863 2 c sys/src/9/ip/tcp.c - 664 sys sys 1045432714 65108
+1045436465 0 c 386/bin/aux/timesync - 775 sys sys 1045435076 127693
+1045436465 1 c sys/src/cmd/aux/timesync.c - 664 sys sys 1045435060 24288

+ 1 - 2
sys/include/control.h

@@ -1,9 +1,8 @@
 #pragma src "/sys/src/libcontrol"
 #pragma lib "libcontrol.a"
 
-#pragma	varargck	type	"q"	char*
-#pragma	varargck	type	"Q"	Rune*
 #pragma	varargck	argpos	ctlprint	2
+#pragma varargck	argpos	_ctlprint	2
 
 typedef struct Control Control;
 typedef struct Controlset Controlset;

+ 4 - 7
sys/lib/yaccpars

@@ -18,9 +18,6 @@ char*	yystates[1];		/* for debugging */
 int	yynerrs = 0;		/* number of errors */
 int	yyerrflag = 0;		/* error recovery flag */
 
-extern	int	fprint(int, char*, ...);
-extern	int	sprint(char*, char*, ...);
-
 char*
 yytokname(int yyc)
 {
@@ -81,7 +78,7 @@ out:
 	if(c == 0)
 		c = yytok2[1];	/* unknown char */
 	if(yydebug >= 3)
-		printf("lex %.4X %s\n", yychar, yytokname(c));
+		printf("lex %.4lX %s\n", yychar, yytokname(c));
 	return c;
 }
 
@@ -132,9 +129,9 @@ yystack:
 		printf("char %s in %s", yytokname(yychar), yystatname(yystate));
 
 	yyp++;
-	if(yyp >= &yys[YYMAXDEPTH]) { 
-		yyerror("yacc stack overflow"); 
-		goto ret1; 
+	if(yyp >= &yys[YYMAXDEPTH]) {
+		yyerror("yacc stack overflow");
+		goto ret1;
 	}
 	yyp->yys = yystate;
 	yyp->yyv = yyval;

+ 7 - 1
sys/src/9/ip/ip.c

@@ -231,6 +231,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
 	int lid, len, seglen, chunk, dlen, blklen, offset, medialen;
 	Route *r, *sr;
 	IP *ip;
+	Proto *pr;
 
 	ip = f->ip;
 
@@ -262,6 +263,11 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos)
 	if(r == nil){
 		ip->stats[OutNoRoutes]++;
 		netlog(f, Logip, "no interface %V\n", eh->dst);
+		if(!gating){
+			freeblist(bp);
+print("ipoput4: no route\n");
+			error("no route");
+		}
 		goto free;
 	}
 
@@ -441,7 +447,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
 	h = (Ip4hdr*)(bp->rp);
 
 	/* dump anything that whose header doesn't checksum */
-	if(ipcsum(&h->vihl)) {
+	if((bp->flag & Bipck) == 0 && ipcsum(&h->vihl)) {
 		ip->stats[InHdrErrors]++;
 		netlog(f, Logip, "ip: checksum error %V\n", h->src);
 		freeblist(bp);

+ 34 - 24
sys/src/9/ip/tcp.c

@@ -1319,27 +1319,30 @@ tcphangup(Conv *s)
 	if(waserror())
 		return commonerror();
 	if(s->raddr != 0) {
-		seg.flags = RST | ACK;
-		seg.ack = tcb->rcv.nxt;
-		tcb->rcv.una = 0;
-		seg.seq = tcb->snd.ptr;
-		seg.wnd = 0;
-		seg.urg = 0;
-		seg.mss = 0;
-		seg.ws = 0;
-		switch(s->ipversion) {
-		case V4:
-			tcb->protohdr.tcp4hdr.vihl = IP_VER4;
-			hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
-			ipoput4(s->p->f, hbp, 0, s->ttl, s->tos);
-			break;
-		case V6:
-			tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
-			hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
-			ipoput6(s->p->f, hbp, 0, s->ttl, s->tos);
-			break;
-		default:
-			panic("tcphangup: version %d", s->ipversion);
+		if(!waserror()){
+			seg.flags = RST | ACK;
+			seg.ack = tcb->rcv.nxt;
+			tcb->rcv.una = 0;
+			seg.seq = tcb->snd.ptr;
+			seg.wnd = 0;
+			seg.urg = 0;
+			seg.mss = 0;
+			seg.ws = 0;
+			switch(s->ipversion) {
+			case V4:
+				tcb->protohdr.tcp4hdr.vihl = IP_VER4;
+				hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
+				ipoput4(s->p->f, hbp, 0, s->ttl, s->tos);
+				break;
+			case V6:
+				tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
+				hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
+				ipoput6(s->p->f, hbp, 0, s->ttl, s->tos);
+				break;
+			default:
+				panic("tcphangup: version %d", s->ipversion);
+			}
+			poperror();
 		}
 	}
 	localclose(s, nil);
@@ -2408,6 +2411,11 @@ tcpoutput(Conv *s)
 	tpriv = s->p->priv;
 	version = s->ipversion;
 
+	if(waserror()){
+		localclose(s, up->errstr);
+		return;
+	}
+
 	for(msgs = 0; msgs < 100; msgs++) {
 		tcb = (Tcpctl*)s->ptcl;
 	
@@ -2415,7 +2423,7 @@ tcpoutput(Conv *s)
 		case Listen:
 		case Closed:
 		case Finwait2:
-			return;
+			goto out;
 		}
 	
 		/* force an ack when a window has opened up */
@@ -2542,7 +2550,7 @@ tcpoutput(Conv *s)
 			hbp = htontcp4(&seg, bp, &tcb->protohdr.tcp4hdr, tcb);
 			if(hbp == nil) {
 				freeblist(bp);
-				return;
+				goto out;
 			}
 			break;
 		case V6:
@@ -2550,7 +2558,7 @@ tcpoutput(Conv *s)
 			hbp = htontcp6(&seg, bp, &tcb->protohdr.tcp6hdr, tcb);
 			if(hbp == nil) {
 				freeblist(bp);
-				return;
+				goto out;
 			}
 			break;
 		default:
@@ -2596,6 +2604,8 @@ tcpoutput(Conv *s)
 			qlock(s);
 		}
 	}
+out:
+	poperror();
 }
 
 /*

+ 75 - 12
sys/src/cmd/aux/timesync.c

@@ -14,6 +14,7 @@ enum {
 	Fs,
 	Rtc,
 	Ntp,
+	Utc,
 
 	HZAvgSecs=	3*60,	/* target averaging period for the frequency in seconds */
 	MinSampleSecs=	60,	/* minimum sampling time in seconds */
@@ -23,6 +24,8 @@ enum {
 char *dir = "/tmp";	// directory sample files live in
 char *logfile = "timesync";
 char *timeserver;
+char *Rootid;
+int utcfil;
 int debug;
 int impotent;
 int logging;
@@ -109,6 +112,7 @@ static vlong	sample(long (*get)(void));
 static void	setpriority(void);
 static void	setrootid(char *d);
 static void	settime(vlong now, uvlong hz, vlong delta, int n); // set time, hz, delta, period
+static vlong	utcsample(void);
 static uvlong	vabs(vlong);
 static uvlong	whatisthefrequencykenneth(uvlong hz, uvlong minhz, uvlong maxhz, vlong dt, vlong ticks, vlong period);
 static void	writefreqfile(int fd, vlong hz, int secs, vlong diff);
@@ -137,6 +141,7 @@ main(int argc, char **argv)
 	accuracy = 1000000LL;	// default accuracy is 1 millisecond
 	nservenet = 0;
 	tsecs = secs = MinSampleSecs;
+	timeserver = "";
 
 	ARGBEGIN{
 	case 'a':
@@ -155,6 +160,13 @@ main(int argc, char **argv)
 		type = Rtc;
 		stratum = 0;
 		break;
+	case 'U':
+		type = Utc;
+		stratum = 1;
+		timeserver = ARGF();
+		if (timeserver == nil)
+			sysfatal("bad time source");
+		break;
 	case 'n':
 		type = Ntp;
 		break;
@@ -196,6 +208,9 @@ main(int argc, char **argv)
 	case 'i':
 		impotent = 1;
 		break;
+	case 'I':
+		Rootid = ARGF();
+		break;
 	case 's':
 		if(nservenet >= nelem(servenet))
 			sysfatal("too many networks to serve on");
@@ -219,7 +234,6 @@ main(int argc, char **argv)
 	fmtinstall('I', eipfmt);
 	fmtinstall('V', eipfmt);
 	sysid = getenv("sysname");
-	timeserver = "";
 
 	switch(type){
 	case Fs:
@@ -283,6 +297,12 @@ main(int argc, char **argv)
 		if(access("/dev/rtc", AREAD) < 0)
 			sysfatal("accessing /dev/rtc: %r\n");
 		break;
+	case Utc:
+		fd = open(timeserver, OREAD);
+		if(fd < 0)
+			sysfatal("opening %s: %r\n", timeserver);
+		utcfil = fd;
+		break;
 	}
 
 	//
@@ -325,6 +345,17 @@ main(int argc, char **argv)
 		case Rtc:
 			s->stime = sample(rtctime);
 			break;
+		case Utc:
+			s->stime = utcsample();
+			if(s->stime == 0LL){
+				if(logging)
+					syslog(0, logfile, "no sample");
+				free(s);
+				if (secs > 60 * 15)
+					tsecs = 60*15;
+				continue;
+			}
+			break;
 		case Ntp:
 			diff = ntpsample();
 			if(diff == 0LL){
@@ -986,6 +1017,32 @@ if(debug) fprint(2, "ntp %s rootdelay %lld rootdisp %lld metric %lld\n", tns->na
 	return ns->dt;
 }
 
+//
+// sample the utc file
+//
+static vlong
+utcsample(void)
+{
+	vlong	s;
+	int	n;
+	char	*v[2], buf[128];
+
+	s = 0;
+	seek(utcfil, 0, 0);
+	n = read(utcfil, buf, sizeof buf - 1);
+	if (n <= 0)
+		return(0LL);
+	buf[n] = 0;
+	n = tokenize(buf, v, nelem(v));
+	if (strcmp(v[0], "0") == 0)
+		return(0LL);
+	if (n == 2) {
+		gettime(&s, nil, nil);
+		s -= atoll(v[1]);
+	}
+	return(atoll(v[0]) + s);
+}
+
 //
 //  sntp server
 //
@@ -1021,17 +1078,23 @@ ntpserver(char *servenet)
 
 	fd = openlisten(servenet);
 
-	switch(type){
-	case Fs:
-		memmove(rootid, "WWV", 3);
-		break;
-	case Rtc:
-		memmove(rootid, "LOCL", 3);
-		break;
-	case Ntp:
-		/* set by the ntp client */
-		break;
-	}
+	if (Rootid == nil)
+		switch(type){
+		case Fs:
+			Rootid = "WWV";
+			break;
+		case Rtc:
+			Rootid = "LOCL";
+			break;
+		case Utc:
+			Rootid = "UTC";
+			break;
+		case Ntp:
+			/* set by the ntp client */
+			break;
+		}
+	if (Rootid != nil)
+		memmove(rootid, Rootid, strlen(Rootid) > 4 ? 4 : strlen(Rootid));
 
 	for(;;){
 		n = read(fd, buf, sizeof(buf));

+ 1 - 0
sys/src/cmd/faces/faces.h

@@ -61,3 +61,4 @@ void		*emalloc(ulong);
 void		*erealloc(void*, ulong);
 char		*estrdup(char*);
 char		*findfile(Face*, char*, char*);
+void		addmaildir(char*);

+ 12 - 2
sys/src/cmd/faces/main.c

@@ -87,6 +87,7 @@ setdate(void)
 void
 init(void)
 {
+	addmaildir(maildir);
 	mousefd = open("/dev/mouse", OREAD);
 	if(mousefd < 0){
 		fprint(2, "faces: can't open mouse: %r\n");
@@ -669,6 +670,13 @@ startproc(void (*f)(void), int index)
 		pids[index] = pid;
 }
 
+void
+usage(void)
+{
+	fprint(2, "usage: faces [-hi]\n");
+	exits("usage");
+}
+
 void
 main(int argc, char *argv[])
 {
@@ -679,9 +687,11 @@ main(int argc, char *argv[])
 	case 'i':
 		initload++;
 		break;
+	case 'm':
+		addmaildir(EARGF(usage()));
+		break;
 	default:
-		fprint(2, "usage: faces [-hi]\n");
-		exits("usage");
+		usage();
 	}ARGEND
 
 	if(initdraw(nil, nil, "faces") < 0){

+ 17 - 4
sys/src/cmd/faces/plumb.c

@@ -11,6 +11,8 @@ static int		seefd = -1;
 static int		logfd = -1;
 static char	*user;
 static char	*logtag;
+static char	**maildirs;
+static int		nmaildirs;
 
 void
 initplumb(void)
@@ -31,6 +33,13 @@ initplumb(void)
 	}
 }
 
+void
+addmaildir(char *dir)
+{
+	maildirs = erealloc(maildirs, (nmaildirs+1)*sizeof(char*));
+	maildirs[nmaildirs++] = dir;
+}
+
 char*
 attr(Face *f)
 {
@@ -251,6 +260,7 @@ tweakdate(char *d)
 Face*
 nextface(void)
 {
+	int i;
 	Face *f;
 	Plumbmsg *m;
 	char *t, *senderp, *showmailp, *digestp;
@@ -273,10 +283,13 @@ nextface(void)
 				plumbfree(m);
 				continue;
 			}
-			if(strncmp(m->data, maildir, strlen(maildir)) != 0){	/* not about this mailbox */
-				plumbfree(m);
-				continue;
-			}
+			for(i=0; i<nmaildirs; i++)
+				if(strncmp(m->data, maildirs[i], strlen(maildirs[i])) != 0)
+					goto Found;
+			plumbfree(m);
+			continue;
+
+		Found:
 			xtime = parsedate(value(m->attr, "date", date));
 			digestp = value(m->attr, "digest", nil);
 			if(alreadyseen(digestp)){

+ 45 - 23
sys/src/cmd/replica/applylog.c

@@ -423,21 +423,6 @@ main(int argc, char **argv)
 				break;
 			if(havelocal && (!douid || strcmp(ld.uid, rd.uid)==0) && strcmp(ld.gid, rd.gid)==0 && ld.mode==rd.mode)	/* nothing to do */
 				goto DoMetaDb;
-			if(!(dbd.mode&DMDIR) && dbd.mtime < rd.mtime){	/* this check might be overkill */
-				if(notexists(remote)){
-					addce(local);
-					/* no skip=1 */
-					break;
-				}
-				if(resolve == 's')
-					goto DoMeta;
-				else if(resolve == 'c')
-					break;
-				conflict(name, "contents out of date; will not update metadata to %s %s %luo", 
-					rd.uid, rd.gid, rd.mode);
-				skip = 1;
-				continue;
-			}
 			if(!havelocal){
 				if(notexists(remote)){
 					addce(local);
@@ -675,10 +660,11 @@ opentemp(char *template)
 int
 copyfile(char *local, char *remote, Dir *d, int dowstat, int *printerror)
 {
-	Dir *d0, *d1;
+	Dir *d0, *d1, *dl;
 	Dir nd;
 	int rfd, tfd, wfd, didcreate;
 	char tmp[32];
+	char err[ERRMAX];
 
 Again:
 	*printerror = 0;
@@ -727,14 +713,50 @@ Again:
 	}
 DoCopy:
 	didcreate = 0;
-	if((wfd = open(local, OTRUNC|OWRITE)) < 0){
-		if((wfd = create(local, OWRITE, 0)) < 0){
-			close(tfd);
-			free(d0);
-			return -1;
+	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;
 		}
-		didcreate = 1;
+		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);
@@ -811,7 +833,7 @@ membogus(char **argv)
 	int n, fd, wfd;
 	char template[50], buf[1024];
 
-	if(strncmp(argv[0], "/tmp/_inst_", 1+3+1+6)==0) {
+	if(strncmp(argv[0], "/tmp/_applylog_", 1+3+1+1+8+1)==0) {
 		rmargv0 = argv[0];
 		atexit(rmself);
 		return;