updater.c revision 190406
1/*-
2 * Copyright (c) 2003-2006, Maxime Henrion <mux@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/contrib/csup/updater.c 190406 2009-03-25 07:01:45Z lulf $
27 */
28
29#include <sys/types.h>
30#include <sys/stat.h>
31
32#include <assert.h>
33#include <err.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <stddef.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include "config.h"
43#include "diff.h"
44#include "fattr.h"
45#include "fixups.h"
46#include "keyword.h"
47#include "updater.h"
48#include "misc.h"
49#include "mux.h"
50#include "proto.h"
51#include "rcsfile.h"
52#include "status.h"
53#include "stream.h"
54
55/* Internal error codes. */
56#define	UPDATER_ERR_PROTO	(-1)	/* Protocol error. */
57#define	UPDATER_ERR_MSG		(-2)	/* Error is in updater->errmsg. */
58#define	UPDATER_ERR_READ	(-3)	/* Error reading from server. */
59#define	UPDATER_ERR_DELETELIM	(-4)	/* File deletion limit exceeded. */
60
61#define BUFSIZE 4096
62
63/* Everything needed to update a file. */
64struct file_update {
65	struct statusrec srbuf;
66	char *destpath;
67	char *temppath;
68	char *origpath;
69	char *coname;		/* Points somewhere in destpath. */
70	char *wantmd5;
71	struct coll *coll;
72	struct status *st;
73	/* Those are only used for diff updating. */
74	char *author;
75	struct stream *orig;
76	struct stream *to;
77	int attic;
78	int expand;
79};
80
81struct updater {
82	struct config *config;
83	struct stream *rd;
84	char *errmsg;
85	int deletecount;
86};
87
88static struct file_update	*fup_new(struct coll *, struct status *);
89static int	 fup_prepare(struct file_update *, char *, int);
90static void	 fup_cleanup(struct file_update *);
91static void	 fup_free(struct file_update *);
92
93static void	 updater_prunedirs(char *, char *);
94static int	 updater_batch(struct updater *, int);
95static int	 updater_docoll(struct updater *, struct file_update *, int);
96static int	 updater_delete(struct updater *, struct file_update *);
97static void	 updater_deletefile(const char *);
98static int	 updater_checkout(struct updater *, struct file_update *, int);
99static int	 updater_addfile(struct updater *, struct file_update *,
100		     char *, int);
101int		 updater_addelta(struct rcsfile *, struct stream *, char *);
102static int	 updater_setattrs(struct updater *, struct file_update *,
103		     char *, char *, char *, char *, char *, struct fattr *);
104static int	updater_setdirattrs(struct updater *, struct coll *,
105		     struct file_update *, char *, char *);
106static int	 updater_updatefile(struct updater *, struct file_update *fup,
107		     const char *, int);
108static int	 updater_updatenode(struct updater *, struct coll *,
109		     struct file_update *, char *, char *);
110static int	 updater_diff(struct updater *, struct file_update *);
111static int	 updater_diff_batch(struct updater *, struct file_update *);
112static int	 updater_diff_apply(struct updater *, struct file_update *,
113		     char *);
114static int	 updater_rcsedit(struct updater *, struct file_update *, char *,
115		     char *);
116int		 updater_append_file(struct updater *, struct file_update *,
117		     off_t);
118static int	 updater_rsync(struct updater *, struct file_update *, size_t);
119static int	 updater_read_checkout(struct stream *, struct stream *);
120
121static struct file_update *
122fup_new(struct coll *coll, struct status *st)
123{
124	struct file_update *fup;
125
126	fup = xmalloc(sizeof(struct file_update));
127	memset(fup, 0, sizeof(*fup));
128	fup->coll = coll;
129	fup->st = st;
130	return (fup);
131}
132
133static int
134fup_prepare(struct file_update *fup, char *name, int attic)
135{
136	struct coll *coll;
137
138	coll = fup->coll;
139	fup->attic = 0;
140	fup->origpath = NULL;
141
142	if (coll->co_options & CO_CHECKOUTMODE)
143		fup->destpath = checkoutpath(coll->co_prefix, name);
144	else {
145		fup->destpath = cvspath(coll->co_prefix, name, attic);
146		fup->origpath = atticpath(coll->co_prefix, name);
147		/* If they're equal, we don't need special care. */
148		if (fup->origpath != NULL &&
149		    strcmp(fup->origpath, fup->destpath) == 0) {
150			free(fup->origpath);
151			fup->origpath = NULL;
152		}
153		fup->attic = attic;
154	}
155	if (fup->destpath == NULL)
156		return (-1);
157	fup->coname = fup->destpath + coll->co_prefixlen + 1;
158	return (0);
159}
160
161/* Called after each file update to reinit the structure. */
162static void
163fup_cleanup(struct file_update *fup)
164{
165	struct statusrec *sr;
166
167	sr = &fup->srbuf;
168
169	if (fup->destpath != NULL) {
170		free(fup->destpath);
171		fup->destpath = NULL;
172	}
173	if (fup->temppath != NULL) {
174		free(fup->temppath);
175		fup->temppath = NULL;
176	}
177	if (fup->origpath != NULL) {
178		free(fup->origpath);
179		fup->origpath = NULL;
180	}
181	fup->coname = NULL;
182	if (fup->author != NULL) {
183		free(fup->author);
184		fup->author = NULL;
185	}
186	fup->expand = 0;
187	if (fup->wantmd5 != NULL) {
188		free(fup->wantmd5);
189		fup->wantmd5 = NULL;
190	}
191	if (fup->orig != NULL) {
192		stream_close(fup->orig);
193		fup->orig = NULL;
194	}
195	if (fup->to != NULL) {
196		stream_close(fup->to);
197		fup->to = NULL;
198	}
199	if (sr->sr_file != NULL)
200		free(sr->sr_file);
201	if (sr->sr_tag != NULL)
202		free(sr->sr_tag);
203	if (sr->sr_date != NULL)
204		free(sr->sr_date);
205	if (sr->sr_revnum != NULL)
206		free(sr->sr_revnum);
207	if (sr->sr_revdate != NULL)
208		free(sr->sr_revdate);
209	fattr_free(sr->sr_clientattr);
210	fattr_free(sr->sr_serverattr);
211	memset(sr, 0, sizeof(*sr));
212}
213
214static void
215fup_free(struct file_update *fup)
216{
217
218	fup_cleanup(fup);
219	free(fup);
220}
221
222void *
223updater(void *arg)
224{
225	struct thread_args *args;
226	struct updater upbuf, *up;
227	int error;
228
229	args = arg;
230
231	up = &upbuf;
232	up->config = args->config;
233	up->rd = args->rd;
234	up->errmsg = NULL;
235	up->deletecount = 0;
236
237	error = updater_batch(up, 0);
238
239	/*
240	 * Make sure to close the fixups even in case of an error,
241	 * so that the lister thread doesn't block indefinitely.
242	 */
243	fixups_close(up->config->fixups);
244	if (!error)
245		error = updater_batch(up, 1);
246	switch (error) {
247	case UPDATER_ERR_PROTO:
248		xasprintf(&args->errmsg, "Updater failed: Protocol error");
249		args->status = STATUS_FAILURE;
250		break;
251	case UPDATER_ERR_MSG:
252		xasprintf(&args->errmsg, "Updater failed: %s", up->errmsg);
253		free(up->errmsg);
254		args->status = STATUS_FAILURE;
255		break;
256	case UPDATER_ERR_READ:
257		if (stream_eof(up->rd)) {
258			xasprintf(&args->errmsg, "Updater failed: "
259			    "Premature EOF from server");
260		} else {
261			xasprintf(&args->errmsg, "Updater failed: "
262			    "Network read failure: %s", strerror(errno));
263		}
264		args->status = STATUS_TRANSIENTFAILURE;
265		break;
266	case UPDATER_ERR_DELETELIM:
267		xasprintf(&args->errmsg, "Updater failed: "
268		    "File deletion limit exceeded");
269		args->status = STATUS_FAILURE;
270		break;
271	default:
272		assert(error == 0);
273		args->status = STATUS_SUCCESS;
274	};
275	return (NULL);
276}
277
278static int
279updater_batch(struct updater *up, int isfixups)
280{
281	struct stream *rd;
282	struct coll *coll;
283	struct status *st;
284	struct file_update *fup;
285	char *line, *cmd, *errmsg, *collname, *release;
286	int error;
287
288	rd = up->rd;
289	STAILQ_FOREACH(coll, &up->config->colls, co_next) {
290		if (coll->co_options & CO_SKIP)
291			continue;
292		umask(coll->co_umask);
293		line = stream_getln(rd, NULL);
294		if (line == NULL)
295			return (UPDATER_ERR_READ);
296		cmd = proto_get_ascii(&line);
297		collname = proto_get_ascii(&line);
298		release = proto_get_ascii(&line);
299		if (release == NULL || line != NULL)
300			return (UPDATER_ERR_PROTO);
301		if (strcmp(cmd, "COLL") != 0 ||
302		    strcmp(collname, coll->co_name) != 0 ||
303		    strcmp(release, coll->co_release) != 0)
304			return (UPDATER_ERR_PROTO);
305
306		if (!isfixups)
307			lprintf(1, "Updating collection %s/%s\n", coll->co_name,
308			    coll->co_release);
309
310		if (coll->co_options & CO_COMPRESS)
311			stream_filter_start(rd, STREAM_FILTER_ZLIB, NULL);
312
313		st = status_open(coll, coll->co_scantime, &errmsg);
314		if (st == NULL) {
315			up->errmsg = errmsg;
316			return (UPDATER_ERR_MSG);
317		}
318		fup = fup_new(coll, st);
319		error = updater_docoll(up, fup, isfixups);
320		status_close(st, &errmsg);
321		fup_free(fup);
322		if (errmsg != NULL) {
323			/* Discard previous error. */
324			if (up->errmsg != NULL)
325				free(up->errmsg);
326			up->errmsg = errmsg;
327			return (UPDATER_ERR_MSG);
328		}
329		if (error)
330			return (error);
331
332		if (coll->co_options & CO_COMPRESS)
333			stream_filter_stop(rd);
334	}
335	line = stream_getln(rd, NULL);
336	if (line == NULL)
337		return (UPDATER_ERR_READ);
338	if (strcmp(line, ".") != 0)
339		return (UPDATER_ERR_PROTO);
340	return (0);
341}
342
343static int
344updater_docoll(struct updater *up, struct file_update *fup, int isfixups)
345{
346	struct stream *rd;
347	struct coll *coll;
348	struct statusrec srbuf, *sr;
349	struct fattr *rcsattr, *tmp;
350	char *attr, *cmd, *blocksize, *line, *msg;
351	char *name, *tag, *date, *revdate;
352	char *expand, *wantmd5, *revnum;
353	char *optstr, *rcsopt, *pos;
354	time_t t;
355	off_t position;
356	int attic, error, needfixupmsg;
357
358	error = 0;
359	rd = up->rd;
360	coll = fup->coll;
361	needfixupmsg = isfixups;
362	while ((line = stream_getln(rd, NULL)) != NULL) {
363		if (strcmp(line, ".") == 0)
364			break;
365		memset(&srbuf, 0, sizeof(srbuf));
366		if (needfixupmsg) {
367			lprintf(1, "Applying fixups for collection %s/%s\n",
368			    coll->co_name, coll->co_release);
369			needfixupmsg = 0;
370		}
371		cmd = proto_get_ascii(&line);
372		if (cmd == NULL || strlen(cmd) != 1)
373			return (UPDATER_ERR_PROTO);
374		switch (cmd[0]) {
375		case 'T':
376			/* Update recorded information for checked-out file. */
377			name = proto_get_ascii(&line);
378			tag = proto_get_ascii(&line);
379			date = proto_get_ascii(&line);
380			revnum = proto_get_ascii(&line);
381			revdate = proto_get_ascii(&line);
382			attr = proto_get_ascii(&line);
383			if (attr == NULL || line != NULL)
384				return (UPDATER_ERR_PROTO);
385
386			rcsattr = fattr_decode(attr);
387			if (rcsattr == NULL)
388				return (UPDATER_ERR_PROTO);
389
390			error = fup_prepare(fup, name, 0);
391			if (error)
392				return (UPDATER_ERR_PROTO);
393			error = updater_setattrs(up, fup, name, tag, date,
394			    revnum, revdate, rcsattr);
395			fattr_free(rcsattr);
396			if (error)
397				return (error);
398			break;
399		case 'c':
400			/* Checkout dead file. */
401			name = proto_get_ascii(&line);
402			tag = proto_get_ascii(&line);
403			date = proto_get_ascii(&line);
404			attr = proto_get_ascii(&line);
405			if (attr == NULL || line != NULL)
406				return (UPDATER_ERR_PROTO);
407
408			error = fup_prepare(fup, name, 0);
409			if (error)
410				return (UPDATER_ERR_PROTO);
411			/* Theoritically, the file does not exist on the client.
412			   Just to make sure, we'll delete it here, if it
413			   exists. */
414			if (access(fup->destpath, F_OK) == 0) {
415				error = updater_delete(up, fup);
416				if (error)
417					return (error);
418			}
419
420			sr = &srbuf;
421			sr->sr_type = SR_CHECKOUTDEAD;
422			sr->sr_file = name;
423			sr->sr_tag = tag;
424			sr->sr_date = date;
425			sr->sr_serverattr = fattr_decode(attr);
426			if (sr->sr_serverattr == NULL)
427				return (UPDATER_ERR_PROTO);
428
429			error = status_put(fup->st, sr);
430			fattr_free(sr->sr_serverattr);
431			if (error) {
432				up->errmsg = status_errmsg(fup->st);
433				return (UPDATER_ERR_MSG);
434			}
435			break;
436		case 'U':
437			/* Update live checked-out file. */
438			name = proto_get_ascii(&line);
439			tag = proto_get_ascii(&line);
440			date = proto_get_ascii(&line);
441			proto_get_ascii(&line);	/* XXX - oldRevNum */
442			proto_get_ascii(&line);	/* XXX - fromAttic */
443			proto_get_ascii(&line);	/* XXX - logLines */
444			expand = proto_get_ascii(&line);
445			attr = proto_get_ascii(&line);
446			wantmd5 = proto_get_ascii(&line);
447			if (wantmd5 == NULL || line != NULL)
448				return (UPDATER_ERR_PROTO);
449
450			sr = &fup->srbuf;
451			sr->sr_type = SR_CHECKOUTLIVE;
452			sr->sr_file = xstrdup(name);
453			sr->sr_date = xstrdup(date);
454			sr->sr_tag = xstrdup(tag);
455			sr->sr_serverattr = fattr_decode(attr);
456			if (sr->sr_serverattr == NULL)
457				return (UPDATER_ERR_PROTO);
458
459			fup->expand = keyword_decode_expand(expand);
460			if (fup->expand == -1)
461				return (UPDATER_ERR_PROTO);
462			error = fup_prepare(fup, name, 0);
463			if (error)
464				return (UPDATER_ERR_PROTO);
465
466			fup->wantmd5 = xstrdup(wantmd5);
467			fup->temppath = tempname(fup->destpath);
468			error = updater_diff(up, fup);
469			if (error)
470				return (error);
471			break;
472		case 'u':
473			/* Update dead checked-out file. */
474			name = proto_get_ascii(&line);
475			tag = proto_get_ascii(&line);
476			date = proto_get_ascii(&line);
477			attr = proto_get_ascii(&line);
478			if (attr == NULL || line != NULL)
479				return (UPDATER_ERR_PROTO);
480
481			error = fup_prepare(fup, name, 0);
482			if (error)
483				return (UPDATER_ERR_PROTO);
484			error = updater_delete(up, fup);
485			if (error)
486				return (error);
487			sr = &srbuf;
488			sr->sr_type = SR_CHECKOUTDEAD;
489			sr->sr_file = name;
490			sr->sr_tag = tag;
491			sr->sr_date = date;
492			sr->sr_serverattr = fattr_decode(attr);
493			if (sr->sr_serverattr == NULL)
494				return (UPDATER_ERR_PROTO);
495			error = status_put(fup->st, sr);
496			fattr_free(sr->sr_serverattr);
497			if (error) {
498				up->errmsg = status_errmsg(fup->st);
499				return (UPDATER_ERR_MSG);
500			}
501			break;
502		case 'C':
503		case 'Y':
504			/* Checkout file. */
505			name = proto_get_ascii(&line);
506			tag = proto_get_ascii(&line);
507			date = proto_get_ascii(&line);
508			revnum = proto_get_ascii(&line);
509			revdate = proto_get_ascii(&line);
510			attr = proto_get_ascii(&line);
511			if (attr == NULL || line != NULL)
512				return (UPDATER_ERR_PROTO);
513
514			sr = &fup->srbuf;
515			sr->sr_type = SR_CHECKOUTLIVE;
516			sr->sr_file = xstrdup(name);
517			sr->sr_tag = xstrdup(tag);
518			sr->sr_date = xstrdup(date);
519			sr->sr_revnum = xstrdup(revnum);
520			sr->sr_revdate = xstrdup(revdate);
521			sr->sr_serverattr = fattr_decode(attr);
522			if (sr->sr_serverattr == NULL)
523				return (UPDATER_ERR_PROTO);
524
525			t = rcsdatetotime(revdate);
526			if (t == -1)
527				return (UPDATER_ERR_PROTO);
528
529			sr->sr_clientattr = fattr_new(FT_FILE, t);
530			tmp = fattr_forcheckout(sr->sr_serverattr,
531			    coll->co_umask);
532			fattr_override(sr->sr_clientattr, tmp, FA_MASK);
533			fattr_free(tmp);
534			fattr_mergedefault(sr->sr_clientattr);
535			error = fup_prepare(fup, name, 0);
536			if (error)
537				return (UPDATER_ERR_PROTO);
538			fup->temppath = tempname(fup->destpath);
539			if (*cmd == 'Y')
540				error = updater_checkout(up, fup, 1);
541			else
542				error = updater_checkout(up, fup, 0);
543			if (error)
544				return (error);
545			break;
546		case 'D':
547			/* Delete file. */
548			name = proto_get_ascii(&line);
549			if (name == NULL || line != NULL)
550				return (UPDATER_ERR_PROTO);
551			error = fup_prepare(fup, name, 0);
552			if (error)
553				return (UPDATER_ERR_PROTO);
554			error = updater_delete(up, fup);
555			if (error)
556				return (error);
557			error = status_delete(fup->st, name, 0);
558			if (error) {
559				up->errmsg = status_errmsg(fup->st);
560				return (UPDATER_ERR_MSG);
561			}
562			break;
563		case 'A':
564		case 'a':
565		case 'R':
566			name = proto_get_ascii(&line);
567			attr = proto_get_ascii(&line);
568			if (name == NULL || attr == NULL || line != NULL)
569				return (UPDATER_ERR_PROTO);
570			attic = (cmd[0] == 'a');
571			error = fup_prepare(fup, name, attic);
572			if (error)
573				return (UPDATER_ERR_PROTO);
574
575			fup->temppath = tempname(fup->destpath);
576			sr = &fup->srbuf;
577			sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE;
578			sr->sr_file = xstrdup(name);
579			sr->sr_serverattr = fattr_decode(attr);
580			if (sr->sr_serverattr == NULL)
581				return (UPDATER_ERR_PROTO);
582			if (attic)
583				lprintf(1, " Create %s -> Attic\n", name);
584			else
585				lprintf(1, " Create %s\n", name);
586			error = updater_addfile(up, fup, attr, 0);
587			if (error)
588				return (error);
589			break;
590		case 'r':
591			name = proto_get_ascii(&line);
592			attr = proto_get_ascii(&line);
593			blocksize = proto_get_ascii(&line);
594			wantmd5 = proto_get_ascii(&line);
595			if (name == NULL || attr == NULL || blocksize == NULL ||
596			    wantmd5 == NULL) {
597				return (UPDATER_ERR_PROTO);
598			}
599			error = fup_prepare(fup, name, 0);
600			if (error)
601				return (UPDATER_ERR_PROTO);
602			fup->wantmd5 = xstrdup(wantmd5);
603			fup->temppath = tempname(fup->destpath);
604			sr = &fup->srbuf;
605			sr->sr_file = xstrdup(name);
606			sr->sr_serverattr = fattr_decode(attr);
607			sr->sr_type = SR_FILELIVE;
608			if (sr->sr_serverattr == NULL)
609				return (UPDATER_ERR_PROTO);
610			error = updater_rsync(up, fup, strtol(blocksize, NULL,
611			    10));
612			if (error)
613				return (error);
614			break;
615		case 'I':
616			/*
617			 * Create directory and add DirDown entry in status
618			 * file.
619			 */
620			name = proto_get_ascii(&line);
621			if (name == NULL || line != NULL)
622				return (UPDATER_ERR_PROTO);
623			error = fup_prepare(fup, name, 0);
624			if (error)
625				return (UPDATER_ERR_PROTO);
626			sr = &fup->srbuf;
627			sr->sr_type = SR_DIRDOWN;
628			sr->sr_file = xstrdup(name);
629			sr->sr_serverattr = NULL;
630			sr->sr_clientattr = fattr_new(FT_DIRECTORY, -1);
631			fattr_mergedefault(sr->sr_clientattr);
632
633			error = mkdirhier(fup->destpath, coll->co_umask);
634			if (error)
635				return (UPDATER_ERR_PROTO);
636			if (access(fup->destpath, F_OK) != 0) {
637				lprintf(1, " Mkdir %s\n", name);
638				error = fattr_makenode(sr->sr_clientattr,
639				    fup->destpath);
640				if (error)
641					return (UPDATER_ERR_PROTO);
642			}
643			error = status_put(fup->st, sr);
644			if (error) {
645				up->errmsg = status_errmsg(fup->st);
646				return (UPDATER_ERR_MSG);
647			}
648			break;
649		case 'i':
650			/* Remove DirDown entry in status file. */
651			name = proto_get_ascii(&line);
652			if (name == NULL || line != NULL)
653				return (UPDATER_ERR_PROTO);
654			error = fup_prepare(fup, name, 0);
655			if (error)
656				return (UPDATER_ERR_PROTO);
657			error = status_delete(fup->st, name, 0);
658			if (error) {
659				up->errmsg = status_errmsg(fup->st);
660				return (UPDATER_ERR_MSG);
661			}
662			break;
663		case 'J':
664			/*
665			 * Set attributes of directory and update DirUp entry in
666			 * status file.
667			 */
668			name = proto_get_ascii(&line);
669			if (name == NULL)
670				return (UPDATER_ERR_PROTO);
671			attr = proto_get_ascii(&line);
672			if (attr == NULL || line != NULL)
673				return (UPDATER_ERR_PROTO);
674			error = fup_prepare(fup, name, 0);
675			if (error)
676				return (UPDATER_ERR_PROTO);
677			error = updater_setdirattrs(up, coll, fup, name, attr);
678			if (error)
679				return (error);
680			break;
681		case 'j':
682			/*
683			 * Remove directory and delete its DirUp entry in status
684			 * file.
685			 */
686			name = proto_get_ascii(&line);
687			if (name == NULL || line != NULL)
688				return (UPDATER_ERR_PROTO);
689			error = fup_prepare(fup, name, 0);
690			if (error)
691				return (UPDATER_ERR_PROTO);
692			lprintf(1, " Rmdir %s\n", name);
693			updater_deletefile(fup->destpath);
694			error = status_delete(fup->st, name, 0);
695			if (error) {
696				up->errmsg = status_errmsg(fup->st);
697				return (UPDATER_ERR_MSG);
698			}
699			break;
700		case 'L':
701		case 'l':
702			name = proto_get_ascii(&line);
703			if (name == NULL)
704				return (UPDATER_ERR_PROTO);
705			attr = proto_get_ascii(&line);
706			if (attr == NULL || line != NULL)
707				return (UPDATER_ERR_PROTO);
708			attic = (cmd[0] == 'l');
709			sr = &fup->srbuf;
710			sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE;
711			sr->sr_file = xstrdup(name);
712			sr->sr_serverattr = fattr_decode(attr);
713			sr->sr_clientattr = fattr_decode(attr);
714			if (sr->sr_serverattr == NULL ||
715			    sr->sr_clientattr == NULL)
716				return (UPDATER_ERR_PROTO);
717
718			/* Save space. Described in detail in updatefile. */
719			if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT)
720			    || fattr_getlinkcount(sr->sr_clientattr) <= 1)
721				fattr_maskout(sr->sr_clientattr,
722				    FA_DEV | FA_INODE);
723			fattr_maskout(sr->sr_clientattr, FA_FLAGS);
724			error = status_put(fup->st, sr);
725			if (error) {
726				up->errmsg = status_errmsg(fup->st);
727				return (UPDATER_ERR_MSG);
728			}
729			break;
730		case 'N':
731		case 'n':
732			name = proto_get_ascii(&line);
733			attr = proto_get_ascii(&line);
734			if (name == NULL || attr == NULL || line != NULL)
735				return (UPDATER_ERR_PROTO);
736			attic = (cmd[0] == 'n');
737			error = fup_prepare(fup, name, attic);
738			if (error)
739				return (UPDATER_ERR_PROTO);
740			sr = &fup->srbuf;
741			sr->sr_type = (attic ? SR_FILEDEAD : SR_FILELIVE);
742			sr->sr_file = xstrdup(name);
743			sr->sr_serverattr = fattr_decode(attr);
744			sr->sr_clientattr = fattr_new(FT_SYMLINK, -1);
745			fattr_mergedefault(sr->sr_clientattr);
746			fattr_maskout(sr->sr_clientattr, FA_FLAGS);
747			error = updater_updatenode(up, coll, fup, name, attr);
748			if (error)
749				return (error);
750			break;
751		case 'V':
752		case 'v':
753			name = proto_get_ascii(&line);
754			attr = proto_get_ascii(&line);
755			optstr = proto_get_ascii(&line);
756			wantmd5 = proto_get_ascii(&line);
757			rcsopt = NULL; /* XXX: Not supported. */
758			if (attr == NULL || line != NULL || wantmd5 == NULL)
759				return (UPDATER_ERR_PROTO);
760			attic = (cmd[0] == 'v');
761			error = fup_prepare(fup, name, attic);
762			if (error)
763				return (UPDATER_ERR_PROTO);
764			fup->temppath = tempname(fup->destpath);
765			fup->wantmd5 = xstrdup(wantmd5);
766			sr = &fup->srbuf;
767			sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE;
768			sr->sr_file = xstrdup(name);
769			sr->sr_serverattr = fattr_decode(attr);
770			if (sr->sr_serverattr == NULL)
771				return (UPDATER_ERR_PROTO);
772
773			error = 0;
774			error = updater_rcsedit(up, fup, name, rcsopt);
775			if (error)
776				return (error);
777			break;
778		case 'X':
779		case 'x':
780			name = proto_get_ascii(&line);
781			attr = proto_get_ascii(&line);
782			if (name == NULL || attr == NULL || line != NULL)
783				return (UPDATER_ERR_PROTO);
784			attic = (cmd[0] == 'x');
785			error = fup_prepare(fup, name, attic);
786			if (error)
787				return (UPDATER_ERR_PROTO);
788
789			fup->temppath = tempname(fup->destpath);
790			sr = &fup->srbuf;
791			sr->sr_type = attic ? SR_FILEDEAD : SR_FILELIVE;
792			sr->sr_file = xstrdup(name);
793			sr->sr_serverattr = fattr_decode(attr);
794			if (sr->sr_serverattr == NULL)
795				return (UPDATER_ERR_PROTO);
796			lprintf(1, " Fixup %s\n", name);
797			error = updater_addfile(up, fup, attr, 1);
798			if (error)
799				return (error);
800			break;
801		case 'Z':
802			name = proto_get_ascii(&line);
803			attr = proto_get_ascii(&line);
804			pos  = proto_get_ascii(&line);
805			if (name == NULL || attr == NULL || pos == NULL ||
806			    line != NULL)
807				return (UPDATER_ERR_PROTO);
808			error = fup_prepare(fup, name, 0);
809			fup->temppath = tempname(fup->destpath);
810			sr = &fup->srbuf;
811			sr->sr_type = SR_FILELIVE;
812			sr->sr_file = xstrdup(name);
813			sr->sr_serverattr = fattr_decode(attr);
814			if (sr->sr_serverattr == NULL)
815				return (UPDATER_ERR_PROTO);
816			position = strtol(pos, NULL, 10);
817			lprintf(1, " Append to %s\n", name);
818			error = updater_append_file(up, fup, position);
819			if (error)
820				return (error);
821			break;
822		case '!':
823			/* Warning from server. */
824			msg = proto_get_rest(&line);
825			if (msg == NULL)
826				return (UPDATER_ERR_PROTO);
827			lprintf(-1, "Server warning: %s\n", msg);
828			break;
829		default:
830			return (UPDATER_ERR_PROTO);
831		}
832		fup_cleanup(fup);
833	}
834	if (line == NULL)
835		return (UPDATER_ERR_READ);
836	return (0);
837}
838
839/* Delete file. */
840static int
841updater_delete(struct updater *up, struct file_update *fup)
842{
843	struct config *config;
844	struct coll *coll;
845
846	config = up->config;
847	coll = fup->coll;
848	if (coll->co_options & CO_DELETE) {
849		lprintf(1, " Delete %s\n", fup->coname);
850		if (config->deletelim >= 0 &&
851		    up->deletecount >= config->deletelim)
852			return (UPDATER_ERR_DELETELIM);
853		up->deletecount++;
854		updater_deletefile(fup->destpath);
855		if (coll->co_options & CO_CHECKOUTMODE)
856			updater_prunedirs(coll->co_prefix, fup->destpath);
857	} else {
858		lprintf(1," NoDelete %s\n", fup->coname);
859	}
860	return (0);
861}
862
863static void
864updater_deletefile(const char *path)
865{
866	int error;
867
868	error = fattr_delete(path);
869	if (error && errno != ENOENT) {
870		lprintf(-1, "Cannot delete \"%s\": %s\n",
871		    path, strerror(errno));
872	}
873}
874
875static int
876updater_setattrs(struct updater *up, struct file_update *fup, char *name,
877    char *tag, char *date, char *revnum, char *revdate, struct fattr *rcsattr)
878{
879	struct statusrec sr;
880	struct status *st;
881	struct coll *coll;
882	struct fattr *fileattr, *fa;
883	char *path;
884	int error, rv;
885
886	coll = fup->coll;
887	st = fup->st;
888	path = fup->destpath;
889
890	fileattr = fattr_frompath(path, FATTR_NOFOLLOW);
891	if (fileattr == NULL) {
892		/* The file has vanished. */
893		error = status_delete(st, name, 0);
894		if (error) {
895			up->errmsg = status_errmsg(st);
896			return (UPDATER_ERR_MSG);
897		}
898		return (0);
899	}
900	fa = fattr_forcheckout(rcsattr, coll->co_umask);
901	fattr_override(fileattr, fa, FA_MASK);
902	fattr_free(fa);
903
904	rv = fattr_install(fileattr, path, NULL);
905	if (rv == -1) {
906		lprintf(1, " SetAttrs %s\n", fup->coname);
907		fattr_free(fileattr);
908		xasprintf(&up->errmsg, "Cannot set attributes for \"%s\": %s",
909		    path, strerror(errno));
910		return (UPDATER_ERR_MSG);
911	}
912	if (rv == 1) {
913		lprintf(1, " SetAttrs %s\n", fup->coname);
914		fattr_free(fileattr);
915		fileattr = fattr_frompath(path, FATTR_NOFOLLOW);
916		if (fileattr == NULL) {
917			/* We're being very unlucky. */
918			error = status_delete(st, name, 0);
919			if (error) {
920				up->errmsg = status_errmsg(st);
921				return (UPDATER_ERR_MSG);
922			}
923			return (0);
924		}
925	}
926
927	fattr_maskout(fileattr, FA_COIGNORE);
928
929	sr.sr_type = SR_CHECKOUTLIVE;
930	sr.sr_file = name;
931	sr.sr_tag = tag;
932	sr.sr_date = date;
933	sr.sr_revnum = revnum;
934	sr.sr_revdate = revdate;
935	sr.sr_clientattr = fileattr;
936	sr.sr_serverattr = rcsattr;
937
938	error = status_put(st, &sr);
939	fattr_free(fileattr);
940	if (error) {
941		up->errmsg = status_errmsg(st);
942		return (UPDATER_ERR_MSG);
943	}
944	return (0);
945}
946
947static int
948updater_updatefile(struct updater *up, struct file_update *fup,
949    const char *md5, int isfixup)
950{
951	struct coll *coll;
952	struct status *st;
953	struct statusrec *sr;
954	struct fattr *fileattr;
955	int error, rv;
956
957	coll = fup->coll;
958	sr = &fup->srbuf;
959	st = fup->st;
960
961	if (strcmp(fup->wantmd5, md5) != 0) {
962		if (isfixup) {
963			lprintf(-1, "%s: Checksum mismatch -- "
964			    "file not updated\n", fup->destpath);
965		} else {
966			lprintf(-1, "%s: Checksum mismatch -- "
967			    "will transfer entire file\n", fup->destpath);
968			fixups_put(up->config->fixups, fup->coll, sr->sr_file);
969		}
970		if (coll->co_options & CO_KEEPBADFILES)
971			lprintf(-1, "Bad version saved in %s\n", fup->temppath);
972		else
973			updater_deletefile(fup->temppath);
974		return (0);
975	}
976
977	fattr_umask(sr->sr_clientattr, coll->co_umask);
978	rv = fattr_install(sr->sr_clientattr, fup->destpath, fup->temppath);
979	if (rv == -1) {
980		xasprintf(&up->errmsg, "Cannot install \"%s\" to \"%s\": %s",
981		    fup->temppath, fup->destpath, strerror(errno));
982		return (UPDATER_ERR_MSG);
983	}
984
985	/* XXX Executes */
986	/*
987	 * We weren't necessarily able to set all the file attributes to the
988	 * desired values, and any executes may have altered the attributes.
989	 * To make sure we record the actual attribute values, we fetch
990	 * them from the file.
991	 *
992	 * However, we preserve the link count as received from the
993	 * server.  This is important for preserving hard links in mirror
994	 * mode.
995	 */
996	fileattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW);
997	if (fileattr == NULL) {
998		xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", fup->destpath,
999		    strerror(errno));
1000		return (UPDATER_ERR_MSG);
1001	}
1002	fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT);
1003	fattr_free(sr->sr_clientattr);
1004	sr->sr_clientattr = fileattr;
1005
1006	/*
1007	 * To save space, don't write out the device and inode unless
1008	 * the link count is greater than 1.  These attributes are used
1009	 * only for detecting hard links.  If the link count is 1 then we
1010	 * know there aren't any hard links.
1011	 */
1012	if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) ||
1013	    fattr_getlinkcount(sr->sr_clientattr) <= 1)
1014		fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE);
1015
1016	if (coll->co_options & CO_CHECKOUTMODE)
1017		fattr_maskout(sr->sr_clientattr, FA_COIGNORE);
1018
1019	error = status_put(st, sr);
1020	if (error) {
1021		up->errmsg = status_errmsg(st);
1022		return (UPDATER_ERR_MSG);
1023	}
1024	return (0);
1025}
1026
1027/*
1028 * Update attributes of a directory.
1029 */
1030static int
1031updater_setdirattrs(struct updater *up, struct coll *coll,
1032    struct file_update *fup, char *name, char *attr)
1033{
1034	struct statusrec *sr;
1035	struct fattr *fa;
1036	int error, rv;
1037
1038	sr = &fup->srbuf;
1039	sr->sr_type = SR_DIRUP;
1040	sr->sr_file = xstrdup(name);
1041	sr->sr_clientattr = fattr_decode(attr);
1042	sr->sr_serverattr = fattr_decode(attr);
1043	if (sr->sr_clientattr == NULL || sr->sr_serverattr == NULL)
1044		return (UPDATER_ERR_PROTO);
1045	fattr_mergedefault(sr->sr_clientattr);
1046	fattr_umask(sr->sr_clientattr, coll->co_umask);
1047	rv = fattr_install(sr->sr_clientattr, fup->destpath, NULL);
1048	lprintf(1, " SetAttrs %s\n", name);
1049	if (rv == -1) {
1050		xasprintf(&up->errmsg, "Cannot install \"%s\" to \"%s\": %s",
1051		    fup->temppath, fup->destpath, strerror(errno));
1052		return (UPDATER_ERR_MSG);
1053	}
1054	/*
1055	 * Now, make sure they were set and record what was set in the status
1056	 * file.
1057	 */
1058	fa = fattr_frompath(fup->destpath, FATTR_NOFOLLOW);
1059	if (fa == NULL) {
1060		xasprintf(&up->errmsg, "Cannot open \%s\": %s", fup->destpath,
1061		    strerror(errno));
1062		return (UPDATER_ERR_MSG);
1063	}
1064	fattr_free(sr->sr_clientattr);
1065	fattr_maskout(fa, FA_FLAGS);
1066	sr->sr_clientattr = fa;
1067	error = status_put(fup->st, sr);
1068	if (error) {
1069		up->errmsg = status_errmsg(fup->st);
1070		return (UPDATER_ERR_MSG);
1071	}
1072
1073	return (0);
1074}
1075
1076static int
1077updater_diff(struct updater *up, struct file_update *fup)
1078{
1079	char md5[MD5_DIGEST_SIZE];
1080	struct coll *coll;
1081	struct statusrec *sr;
1082	struct fattr *fa, *tmp;
1083	char *author, *path, *revnum, *revdate;
1084	char *line, *cmd;
1085	int error;
1086
1087	coll = fup->coll;
1088	sr = &fup->srbuf;
1089	path = fup->destpath;
1090
1091	lprintf(1, " Edit %s\n", fup->coname);
1092	while ((line = stream_getln(up->rd, NULL)) != NULL) {
1093		if (strcmp(line, ".") == 0)
1094			break;
1095		cmd = proto_get_ascii(&line);
1096		if (cmd == NULL || strcmp(cmd, "D") != 0)
1097			return (UPDATER_ERR_PROTO);
1098		revnum = proto_get_ascii(&line);
1099		proto_get_ascii(&line); /* XXX - diffbase */
1100		revdate = proto_get_ascii(&line);
1101		author = proto_get_ascii(&line);
1102		if (author == NULL || line != NULL)
1103			return (UPDATER_ERR_PROTO);
1104		if (sr->sr_revnum != NULL)
1105			free(sr->sr_revnum);
1106		if (sr->sr_revdate != NULL)
1107			free(sr->sr_revdate);
1108		if (fup->author != NULL)
1109			free(fup->author);
1110		sr->sr_revnum = xstrdup(revnum);
1111		sr->sr_revdate = xstrdup(revdate);
1112		fup->author = xstrdup(author);
1113		if (fup->orig == NULL) {
1114			/* First patch, the "origin" file is the one we have. */
1115			fup->orig = stream_open_file(path, O_RDONLY);
1116			if (fup->orig == NULL) {
1117				xasprintf(&up->errmsg, "%s: Cannot open: %s",
1118				    path, strerror(errno));
1119				return (UPDATER_ERR_MSG);
1120			}
1121		} else {
1122			/* Subsequent patches. */
1123			stream_close(fup->orig);
1124			fup->orig = fup->to;
1125			stream_rewind(fup->orig);
1126			unlink(fup->temppath);
1127			free(fup->temppath);
1128			fup->temppath = tempname(path);
1129		}
1130		fup->to = stream_open_file(fup->temppath,
1131		    O_RDWR | O_CREAT | O_TRUNC, 0600);
1132		if (fup->to == NULL) {
1133			xasprintf(&up->errmsg, "%s: Cannot open: %s",
1134			    fup->temppath, strerror(errno));
1135			return (UPDATER_ERR_MSG);
1136		}
1137		lprintf(2, "  Add delta %s %s %s\n", sr->sr_revnum,
1138		    sr->sr_revdate, fup->author);
1139		error = updater_diff_batch(up, fup);
1140		if (error)
1141			return (error);
1142	}
1143	if (line == NULL)
1144		return (UPDATER_ERR_READ);
1145
1146	fa = fattr_frompath(path, FATTR_FOLLOW);
1147	tmp = fattr_forcheckout(sr->sr_serverattr, coll->co_umask);
1148	fattr_override(fa, tmp, FA_MASK);
1149	fattr_free(tmp);
1150	fattr_maskout(fa, FA_MODTIME);
1151	sr->sr_clientattr = fa;
1152
1153	if (MD5_File(fup->temppath, md5) == -1) {
1154		xasprintf(&up->errmsg,
1155		    "Cannot calculate checksum for \"%s\": %s",
1156		    path, strerror(errno));
1157		return (UPDATER_ERR_MSG);
1158	}
1159	error = updater_updatefile(up, fup, md5, 0);
1160	return (error);
1161}
1162
1163/*
1164 * Edit a file and add delta.
1165 */
1166static int
1167updater_diff_batch(struct updater *up, struct file_update *fup)
1168{
1169	struct stream *rd;
1170	char *cmd, *line, *state, *tok;
1171	int error;
1172
1173	state = NULL;
1174	rd = up->rd;
1175	while ((line = stream_getln(rd, NULL)) != NULL) {
1176		if (strcmp(line, ".") == 0)
1177			break;
1178		cmd = proto_get_ascii(&line);
1179		if (cmd == NULL || strlen(cmd) != 1) {
1180			error = UPDATER_ERR_PROTO;
1181			goto bad;
1182		}
1183		switch (cmd[0]) {
1184		case 'L':
1185			line = stream_getln(rd, NULL);
1186			/* XXX - We're just eating the log for now. */
1187			while (line != NULL && strcmp(line, ".") != 0 &&
1188			    strcmp(line, ".+") != 0)
1189				line = stream_getln(rd, NULL);
1190			if (line == NULL) {
1191				error = UPDATER_ERR_READ;
1192				goto bad;
1193			}
1194			break;
1195		case 'S':
1196			tok = proto_get_ascii(&line);
1197			if (tok == NULL || line != NULL) {
1198				error = UPDATER_ERR_PROTO;
1199				goto bad;
1200			}
1201			if (state != NULL)
1202				free(state);
1203			state = xstrdup(tok);
1204			break;
1205		case 'T':
1206			error = updater_diff_apply(up, fup, state);
1207			if (error)
1208				goto bad;
1209			break;
1210		default:
1211			error = UPDATER_ERR_PROTO;
1212			goto bad;
1213		}
1214	}
1215	if (line == NULL) {
1216		error = UPDATER_ERR_READ;
1217		goto bad;
1218	}
1219	if (state != NULL)
1220		free(state);
1221	return (0);
1222bad:
1223	if (state != NULL)
1224		free(state);
1225	return (error);
1226}
1227
1228int
1229updater_diff_apply(struct updater *up, struct file_update *fup, char *state)
1230{
1231	struct diffinfo dibuf, *di;
1232	struct coll *coll;
1233	struct statusrec *sr;
1234	int error;
1235
1236	coll = fup->coll;
1237	sr = &fup->srbuf;
1238	di = &dibuf;
1239
1240	di->di_rcsfile = sr->sr_file;
1241	di->di_cvsroot = coll->co_cvsroot;
1242	di->di_revnum = sr->sr_revnum;
1243	di->di_revdate = sr->sr_revdate;
1244	di->di_author = fup->author;
1245	di->di_tag = sr->sr_tag;
1246	di->di_state = state;
1247	di->di_expand = fup->expand;
1248
1249	error = diff_apply(up->rd, fup->orig, fup->to, coll->co_keyword, di, 1);
1250	if (error) {
1251		/* XXX Bad error message */
1252		xasprintf(&up->errmsg, "Bad diff from server");
1253		return (UPDATER_ERR_MSG);
1254	}
1255	return (0);
1256}
1257
1258/* Update or create a node. */
1259static int
1260updater_updatenode(struct updater *up, struct coll *coll,
1261    struct file_update *fup, char *name, char *attr)
1262{
1263	struct fattr *fa, *fileattr;
1264	struct status *st;
1265	struct statusrec *sr;
1266	int error, rv;
1267
1268	sr = &fup->srbuf;
1269	st = fup->st;
1270	fa = fattr_decode(attr);
1271
1272	if (fattr_type(fa) == FT_SYMLINK) {
1273		lprintf(1, " Symlink %s -> %s\n", name,
1274		    fattr_getlinktarget(fa));
1275	} else {
1276		lprintf(1, " Mknod %s\n", name);
1277	}
1278
1279	/* Create directory. */
1280	error = mkdirhier(fup->destpath, coll->co_umask);
1281	if (error)
1282		return (UPDATER_ERR_PROTO);
1283
1284	/* If it does not exist, create it. */
1285	if (access(fup->destpath, F_OK) != 0)
1286		fattr_makenode(fa, fup->destpath);
1287
1288	/*
1289	 * Coming from attic? I don't think this is a problem since we have
1290	 * determined attic before we call this function (Look at UpdateNode in
1291	 * cvsup).
1292	 */
1293	fattr_umask(fa, coll->co_umask);
1294	rv = fattr_install(fa, fup->destpath, fup->temppath);
1295	if (rv == -1) {
1296		xasprintf(&up->errmsg, "Cannot update attributes on "
1297	    "\"%s\": %s", fup->destpath, strerror(errno));
1298		return (UPDATER_ERR_MSG);
1299	}
1300	/*
1301	 * XXX: Executes not implemented. Have not encountered much use for it
1302	 * yet.
1303	 */
1304	/*
1305	 * We weren't necessarily able to set all the file attributes to the
1306	 * desired values, and any executes may have altered the attributes.
1307	 * To make sure we record the actual attribute values, we fetch
1308	 * them from the file.
1309	 *
1310	 * However, we preserve the link count as received from the
1311	 * server.  This is important for preserving hard links in mirror
1312	 * mode.
1313	 */
1314	fileattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW);
1315	if (fileattr == NULL) {
1316		xasprintf(&up->errmsg, "Cannot stat \"%s\": %s", fup->destpath,
1317		    strerror(errno));
1318		return (UPDATER_ERR_MSG);
1319	}
1320	fattr_override(fileattr, sr->sr_clientattr, FA_LINKCOUNT);
1321	fattr_free(sr->sr_clientattr);
1322	sr->sr_clientattr = fileattr;
1323
1324	/*
1325	 * To save space, don't write out the device and inode unless
1326	 * the link count is greater than 1.  These attributes are used
1327	 * only for detecting hard links.  If the link count is 1 then we
1328	 * know there aren't any hard links.
1329	 */
1330	if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) ||
1331	    fattr_getlinkcount(sr->sr_clientattr) <= 1)
1332		fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE);
1333
1334	/* If it is a symlink, write only out it's path. */
1335	if (fattr_type(fa) == FT_SYMLINK) {
1336		fattr_maskout(sr->sr_clientattr, ~(FA_FILETYPE |
1337		    FA_LINKTARGET));
1338	}
1339	fattr_maskout(sr->sr_clientattr, FA_FLAGS);
1340	error = status_put(st, sr);
1341	if (error) {
1342		up->errmsg = status_errmsg(st);
1343		return (UPDATER_ERR_MSG);
1344	}
1345	fattr_free(fa);
1346
1347	return (0);
1348}
1349
1350/*
1351 * Fetches a new file in CVS mode.
1352 */
1353static int
1354updater_addfile(struct updater *up, struct file_update *fup, char *attr,
1355    int isfixup)
1356{
1357	struct coll *coll;
1358	struct stream *to;
1359	struct statusrec *sr;
1360	struct fattr *fa;
1361	char buf[BUFSIZE];
1362	char md5[MD5_DIGEST_SIZE];
1363	ssize_t nread;
1364	off_t fsize, remains;
1365	char *cmd, *line, *path;
1366	int error;
1367
1368	coll = fup->coll;
1369	path = fup->destpath;
1370	sr = &fup->srbuf;
1371	fa = fattr_decode(attr);
1372	fsize = fattr_filesize(fa);
1373
1374	error = mkdirhier(path, coll->co_umask);
1375	if (error)
1376		return (UPDATER_ERR_PROTO);
1377	to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC, 0755);
1378	if (to == NULL) {
1379		xasprintf(&up->errmsg, "%s: Cannot create: %s",
1380		    fup->temppath, strerror(errno));
1381		return (UPDATER_ERR_MSG);
1382	}
1383	stream_filter_start(to, STREAM_FILTER_MD5, md5);
1384	remains = fsize;
1385	do {
1386		nread = stream_read(up->rd, buf, (BUFSIZE > remains ?
1387		    remains : BUFSIZE));
1388		remains -= nread;
1389		stream_write(to, buf, nread);
1390	} while (remains > 0);
1391	stream_close(to);
1392	line = stream_getln(up->rd, NULL);
1393	if (line == NULL)
1394		return (UPDATER_ERR_PROTO);
1395	/* Check for EOF. */
1396	if (!(*line == '.' || (strncmp(line, ".<", 2) != 0)))
1397		return (UPDATER_ERR_PROTO);
1398	line = stream_getln(up->rd, NULL);
1399	if (line == NULL)
1400		return (UPDATER_ERR_PROTO);
1401
1402	cmd = proto_get_ascii(&line);
1403	fup->wantmd5 = proto_get_ascii(&line);
1404	if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0)
1405		return (UPDATER_ERR_PROTO);
1406
1407	sr->sr_clientattr = fattr_frompath(fup->temppath, FATTR_NOFOLLOW);
1408	if (sr->sr_clientattr == NULL)
1409		return (UPDATER_ERR_PROTO);
1410	fattr_override(sr->sr_clientattr, sr->sr_serverattr,
1411	    FA_MODTIME | FA_MASK);
1412	error = updater_updatefile(up, fup, md5, isfixup);
1413	fup->wantmd5 = NULL;	/* So that it doesn't get freed. */
1414	if (error)
1415		return (error);
1416	return (0);
1417}
1418
1419static int
1420updater_checkout(struct updater *up, struct file_update *fup, int isfixup)
1421{
1422	char md5[MD5_DIGEST_SIZE];
1423	struct statusrec *sr;
1424	struct coll *coll;
1425	struct stream *to;
1426	ssize_t nbytes;
1427	size_t size;
1428	char *cmd, *path, *line;
1429	int error, first;
1430
1431	coll = fup->coll;
1432	sr = &fup->srbuf;
1433	path = fup->destpath;
1434
1435	if (isfixup)
1436		lprintf(1, " Fixup %s\n", fup->coname);
1437	else
1438		lprintf(1, " Checkout %s\n", fup->coname);
1439	error = mkdirhier(path, coll->co_umask);
1440	if (error) {
1441		xasprintf(&up->errmsg,
1442		    "Cannot create directories leading to \"%s\": %s",
1443		    path, strerror(errno));
1444		return (UPDATER_ERR_MSG);
1445	}
1446
1447	to = stream_open_file(fup->temppath,
1448	    O_WRONLY | O_CREAT | O_TRUNC, 0600);
1449	if (to == NULL) {
1450		xasprintf(&up->errmsg, "%s: Cannot create: %s",
1451		    fup->temppath, strerror(errno));
1452		return (UPDATER_ERR_MSG);
1453	}
1454	stream_filter_start(to, STREAM_FILTER_MD5, md5);
1455	line = stream_getln(up->rd, &size);
1456	first = 1;
1457	while (line != NULL) {
1458		if (line[size - 1] == '\n')
1459			size--;
1460	       	if ((size == 1 && *line == '.') ||
1461		    (size == 2 && memcmp(line, ".+", 2) == 0))
1462			break;
1463		if (size >= 2 && memcmp(line, "..", 2) == 0) {
1464			size--;
1465			line++;
1466		}
1467		if (!first) {
1468			nbytes = stream_write(to, "\n", 1);
1469			if (nbytes == -1)
1470				goto bad;
1471		}
1472		stream_write(to, line, size);
1473		line = stream_getln(up->rd, &size);
1474		first = 0;
1475	}
1476	if (line == NULL) {
1477		stream_close(to);
1478		return (UPDATER_ERR_READ);
1479	}
1480	if (size == 1 && *line == '.') {
1481		nbytes = stream_write(to, "\n", 1);
1482		if (nbytes == -1)
1483			goto bad;
1484	}
1485	stream_close(to);
1486	/* Get the checksum line. */
1487	line = stream_getln(up->rd, NULL);
1488	if (line == NULL)
1489		return (UPDATER_ERR_READ);
1490	cmd = proto_get_ascii(&line);
1491	fup->wantmd5 = proto_get_ascii(&line);
1492	if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0)
1493		return (UPDATER_ERR_PROTO);
1494	error = updater_updatefile(up, fup, md5, isfixup);
1495	fup->wantmd5 = NULL;	/* So that it doesn't get freed. */
1496	if (error)
1497		return (error);
1498	return (0);
1499bad:
1500	xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath,
1501	    strerror(errno));
1502	return (UPDATER_ERR_MSG);
1503}
1504
1505/*
1506 * Remove all empty directories below file.
1507 * This function will trash the path passed to it.
1508 */
1509static void
1510updater_prunedirs(char *base, char *file)
1511{
1512	char *cp;
1513	int error;
1514
1515	while ((cp = strrchr(file, '/')) != NULL) {
1516		*cp = '\0';
1517		if (strcmp(base, file) == 0)
1518			return;
1519		error = rmdir(file);
1520		if (error)
1521			return;
1522	}
1523}
1524
1525/*
1526 * Edit an RCS file.
1527 */
1528static int
1529updater_rcsedit(struct updater *up, struct file_update *fup, char *name,
1530    char *rcsopt)
1531{
1532	struct coll *coll;
1533	struct stream *dest;
1534	struct statusrec *sr;
1535	struct status *st;
1536	struct rcsfile *rf;
1537	struct fattr *oldfattr;
1538	char md5[MD5_DIGEST_SIZE];
1539	char *branch, *cmd, *expand, *line, *path, *revnum, *tag, *temppath;
1540	int error;
1541
1542	coll = fup->coll;
1543	sr = &fup->srbuf;
1544	st = fup->st;
1545	temppath = fup->temppath;
1546	path = fup->origpath != NULL ? fup->origpath : fup->destpath;
1547	error = 0;
1548
1549	/* If the path is new, we must create the Attic dir if needed. */
1550	if (fup->origpath != NULL) {
1551		error = mkdirhier(fup->destpath, coll->co_umask);
1552		if (error) {
1553			xasprintf(&up->errmsg, "Unable to create Attic dir for "
1554			    "%s\n", fup->origpath);
1555			return (UPDATER_ERR_MSG);
1556		}
1557	}
1558	/*
1559	 * XXX: we could avoid parsing overhead if we're reading ahead before we
1560	 * parse the file.
1561	 */
1562	oldfattr = fattr_frompath(path, FATTR_NOFOLLOW);
1563	if (oldfattr == NULL) {
1564		xasprintf(&up->errmsg, "%s: Cannot get attributes: %s", path,
1565		    strerror(errno));
1566		return (UPDATER_ERR_MSG);
1567	}
1568	fattr_merge(sr->sr_serverattr, oldfattr);
1569	rf = NULL;
1570
1571	/* Macro for making touching an RCS file faster. */
1572#define UPDATER_OPENRCS(rf, up, path, name, cvsroot, tag) do {		\
1573	if ((rf) == NULL) {						\
1574		lprintf(1, " Edit %s", fup->coname);			\
1575		if (fup->attic)						\
1576			lprintf(1, " -> Attic");			\
1577		lprintf(1, "\n");					\
1578		(rf) = rcsfile_frompath((path), (name), (cvsroot),	\
1579		    (tag), 0);						\
1580		if ((rf) == NULL) {					\
1581			xasprintf(&(up)->errmsg,			\
1582			    "Error reading rcsfile %s\n", (name));	\
1583			return (UPDATER_ERR_MSG);			\
1584		}							\
1585	}								\
1586} while (0)
1587
1588	while ((line = stream_getln(up->rd, NULL)) != NULL) {
1589		if (strcmp(line, ".") == 0)
1590			break;
1591		cmd = proto_get_ascii(&line);
1592		if (cmd == NULL) {
1593			lprintf(-1, "Error editing %s\n", name);
1594			return (UPDATER_ERR_PROTO);
1595		}
1596		switch(cmd[0]) {
1597			case 'B':
1598				branch = proto_get_ascii(&line);
1599				if (branch == NULL || line != NULL)
1600					return (UPDATER_ERR_PROTO);
1601				UPDATER_OPENRCS(rf, up, path, name,
1602				    coll->co_cvsroot, coll->co_tag);
1603				break;
1604			case 'b':
1605				UPDATER_OPENRCS(rf, up, path, name,
1606				    coll->co_cvsroot, coll->co_tag);
1607				rcsfile_setval(rf, RCSFILE_BRANCH, NULL);
1608				break;
1609			case 'D':
1610				UPDATER_OPENRCS(rf, up, path, name,
1611				    coll->co_cvsroot, coll->co_tag);
1612				error = updater_addelta(rf, up->rd, line);
1613				if (error)
1614					return (error);
1615				break;
1616			case 'd':
1617				revnum = proto_get_ascii(&line);
1618				if (revnum == NULL || line != NULL)
1619					return (UPDATER_ERR_PROTO);
1620				UPDATER_OPENRCS(rf, up, path, name,
1621				    coll->co_cvsroot, coll->co_tag);
1622				rcsfile_deleterev(rf, revnum);
1623				break;
1624			case 'E':
1625				expand = proto_get_ascii(&line);
1626				if (expand == NULL || line != NULL)
1627					return (UPDATER_ERR_PROTO);
1628				UPDATER_OPENRCS(rf, up, path, name,
1629				    coll->co_cvsroot, coll->co_tag);
1630				rcsfile_setval(rf, RCSFILE_EXPAND, expand);
1631				break;
1632			case 'T':
1633				tag = proto_get_ascii(&line);
1634				revnum = proto_get_ascii(&line);
1635				if (tag == NULL || revnum == NULL ||
1636				    line != NULL)
1637					return (UPDATER_ERR_PROTO);
1638				UPDATER_OPENRCS(rf, up, path, name,
1639				    coll->co_cvsroot, coll->co_tag);
1640				rcsfile_addtag(rf, tag, revnum);
1641				break;
1642			case 't':
1643				tag = proto_get_ascii(&line);
1644				revnum = proto_get_ascii(&line);
1645				if (tag == NULL || revnum == NULL ||
1646				    line != NULL)
1647					return (UPDATER_ERR_PROTO);
1648				UPDATER_OPENRCS(rf, up, path, name,
1649				    coll->co_cvsroot, coll->co_tag);
1650				rcsfile_deletetag(rf, tag, revnum);
1651				break;
1652			default:
1653				return (UPDATER_ERR_PROTO);
1654		}
1655	}
1656
1657	if (rf == NULL) {
1658		fattr_maskout(oldfattr, ~FA_MODTIME);
1659		if (fattr_equal(oldfattr, sr->sr_serverattr))
1660		 	lprintf(1, " SetAttrs %s", fup->coname);
1661		else
1662			lprintf(1, " Touch %s", fup->coname);
1663		/* Install new attributes. */
1664		fattr_umask(sr->sr_serverattr, coll->co_umask);
1665		fattr_install(sr->sr_serverattr, fup->destpath, NULL);
1666		if (fup->attic)
1667			lprintf(1, " -> Attic");
1668		lprintf(1, "\n");
1669		fattr_free(oldfattr);
1670		goto finish;
1671	}
1672
1673	/* Write and rename temp file. */
1674	dest = stream_open_file(fup->temppath,
1675	    O_RDWR | O_CREAT | O_TRUNC, 0600);
1676	if (dest == NULL) {
1677		xasprintf(&up->errmsg, "Error opening file %s for writing: %s\n",
1678		    fup->temppath, strerror(errno));
1679		return (UPDATER_ERR_MSG);
1680	}
1681	stream_filter_start(dest, STREAM_FILTER_MD5RCS, md5);
1682	error = rcsfile_write(rf, dest);
1683	stream_close(dest);
1684	rcsfile_free(rf);
1685	if (error)
1686		lprintf(-1, "Error writing %s\n", name);
1687
1688finish:
1689	sr->sr_clientattr = fattr_frompath(path, FATTR_NOFOLLOW);
1690	if (sr->sr_clientattr == NULL) {
1691		xasprintf(&up->errmsg, "%s: Cannot get attributes: %s",
1692		    fup->destpath, strerror(errno));
1693		return (UPDATER_ERR_MSG);
1694	}
1695	fattr_override(sr->sr_clientattr, sr->sr_serverattr,
1696	    FA_MODTIME | FA_MASK);
1697	if (rf != NULL) {
1698		error = updater_updatefile(up, fup, md5, 0);
1699		fup->wantmd5 = NULL;	/* So that it doesn't get freed. */
1700		if (error)
1701			return (error);
1702	} else {
1703		/* Record its attributes since we touched it. */
1704		if (!(fattr_getmask(sr->sr_clientattr) & FA_LINKCOUNT) ||
1705		    fattr_getlinkcount(sr->sr_clientattr) <= 1)
1706		fattr_maskout(sr->sr_clientattr, FA_DEV | FA_INODE);
1707		error = status_put(st, sr);
1708		if (error) {
1709			up->errmsg = status_errmsg(st);
1710			return (UPDATER_ERR_MSG);
1711		}
1712	}
1713
1714	/* In this case, we need to remove the old file afterwards. */
1715	/* XXX: Can we be sure that a file not edited is moved? I don't think
1716	 * this is a problem, since if a file is moved, it should be edited to
1717	 * show if it's dead or not.
1718	 */
1719	if (fup->origpath != NULL)
1720		updater_deletefile(fup->origpath);
1721	return (0);
1722}
1723
1724/*
1725 * Add a delta to a RCS file.
1726 */
1727int
1728updater_addelta(struct rcsfile *rf, struct stream *rd, char *cmdline)
1729{
1730	struct delta *d;
1731	size_t size;
1732	char *author, *cmd, *diffbase, *line, *logline;
1733	char *revdate, *revnum, *state, *textline;
1734
1735	revnum = proto_get_ascii(&cmdline);
1736	diffbase = proto_get_ascii(&cmdline);
1737	revdate = proto_get_ascii(&cmdline);
1738	author = proto_get_ascii(&cmdline);
1739	size = 0;
1740
1741	if (revnum == NULL || revdate == NULL || author == NULL)
1742		return (UPDATER_ERR_PROTO);
1743
1744	/* First add the delta so we have it. */
1745	d = rcsfile_addelta(rf, revnum, revdate, author, diffbase);
1746	if (d == NULL) {
1747		lprintf(-1, "Error adding delta %s\n", revnum);
1748		return (UPDATER_ERR_READ);
1749	}
1750	while ((line = stream_getln(rd, NULL)) != NULL) {
1751		if (strcmp(line, ".") == 0)
1752			break;
1753		cmd = proto_get_ascii(&line);
1754		switch (cmd[0]) {
1755			case 'L':
1756				/* Do the same as in 'C' command. */
1757				logline = stream_getln(rd, &size);
1758				while (logline != NULL) {
1759					if (size == 2 && *logline == '.')
1760						break;
1761					if (size == 3 &&
1762					    memcmp(logline, ".+", 2) == 0) {
1763						rcsdelta_truncatelog(d, -1);
1764						break;
1765					}
1766					if (size >= 3 &&
1767					    memcmp(logline, "..", 2) == 0) {
1768						size--;
1769						logline++;
1770					}
1771					rcsdelta_appendlog(d, logline, size);
1772					logline = stream_getln(rd, &size);
1773				}
1774			break;
1775			case 'N':
1776			case 'n':
1777				/* XXX: Not supported. */
1778			break;
1779			case 'S':
1780				state = proto_get_ascii(&line);
1781				if (state == NULL)
1782					return (UPDATER_ERR_PROTO);
1783				rcsdelta_setstate(d, state);
1784			break;
1785			case 'T':
1786				/* Do the same as in 'C' command. */
1787				textline = stream_getln(rd, &size);
1788				while (textline != NULL) {
1789					if (size == 2 && *textline == '.')
1790						break;
1791					if (size == 3 &&
1792					    memcmp(textline, ".+", 2) == 0) {
1793						/* Truncate newline. */
1794						rcsdelta_truncatetext(d, -1);
1795						break;
1796					}
1797					if (size >= 3 &&
1798					    memcmp(textline, "..", 2) == 0) {
1799						size--;
1800						textline++;
1801					}
1802					rcsdelta_appendtext(d, textline, size);
1803					textline = stream_getln(rd, &size);
1804				}
1805			break;
1806		}
1807	}
1808
1809	return (0);
1810}
1811
1812int
1813updater_append_file(struct updater *up, struct file_update *fup, off_t pos)
1814{
1815	struct fattr *fa;
1816	struct stream *to;
1817	struct statusrec *sr;
1818	ssize_t nread;
1819	off_t bytes;
1820	char buf[BUFSIZE], md5[MD5_DIGEST_SIZE];
1821	char *line, *cmd;
1822	int error, fd;
1823
1824	sr = &fup->srbuf;
1825	fa = sr->sr_serverattr;
1826	to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC,
1827	    0755);
1828	if (to == NULL) {
1829		xasprintf(&up->errmsg, "%s: Cannot open: %s", fup->temppath,
1830		    strerror(errno));
1831		return (UPDATER_ERR_MSG);
1832	}
1833	fd = open(fup->destpath, O_RDONLY);
1834	if (fd < 0) {
1835		xasprintf(&up->errmsg, "%s: Cannot open: %s", fup->destpath,
1836		    strerror(errno));
1837		return (UPDATER_ERR_MSG);
1838	}
1839
1840	stream_filter_start(to, STREAM_FILTER_MD5, md5);
1841	/* First write the existing content. */
1842	while ((nread = read(fd, buf, BUFSIZE)) > 0)
1843		stream_write(to, buf, nread);
1844	close(fd);
1845
1846	bytes = fattr_filesize(fa) - pos;
1847	/* Append the new data. */
1848	do {
1849		nread = stream_read(up->rd, buf,
1850		    (BUFSIZE > bytes) ? bytes : BUFSIZE);
1851		bytes -= nread;
1852		stream_write(to, buf, nread);
1853	} while (bytes > 0);
1854	stream_close(to);
1855
1856	line = stream_getln(up->rd, NULL);
1857	if (line == NULL)
1858		return (UPDATER_ERR_PROTO);
1859	/* Check for EOF. */
1860	if (!(*line == '.' || (strncmp(line, ".<", 2) != 0)))
1861		return (UPDATER_ERR_PROTO);
1862	line = stream_getln(up->rd, NULL);
1863	if (line == NULL)
1864		return (UPDATER_ERR_PROTO);
1865
1866	cmd = proto_get_ascii(&line);
1867	fup->wantmd5 = proto_get_ascii(&line);
1868	if (fup->wantmd5 == NULL || line != NULL || strcmp(cmd, "5") != 0)
1869		return (UPDATER_ERR_PROTO);
1870
1871	sr->sr_clientattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW);
1872	if (sr->sr_clientattr == NULL)
1873		return (UPDATER_ERR_PROTO);
1874	fattr_override(sr->sr_clientattr, sr->sr_serverattr,
1875	    FA_MODTIME | FA_MASK);
1876	error = updater_updatefile(up, fup, md5, 0);
1877	fup->wantmd5 = NULL;	/* So that it doesn't get freed. */
1878	if (error)
1879		return (error);
1880	return (0);
1881}
1882
1883/*
1884 * Read file data from stream of checkout commands, and write it to the
1885 * destination.
1886 */
1887static int
1888updater_read_checkout(struct stream *src, struct stream *dest)
1889{
1890	ssize_t nbytes;
1891	size_t size;
1892	char *line;
1893	int first;
1894
1895	first = 1;
1896	line = stream_getln(src, &size);
1897	while (line != NULL) {
1898		if (line[size - 1] == '\n')
1899			size--;
1900		if ((size == 1 && *line == '.') ||
1901		    (size == 2 && strncmp(line, ".+", 2) == 0))
1902			break;
1903		if (size >= 2 && strncmp(line, "..", 2) == 0) {
1904			size--;
1905			line++;
1906		}
1907		if (!first) {
1908			nbytes = stream_write(dest, "\n", 1);
1909			if (nbytes == -1)
1910				return (UPDATER_ERR_MSG);
1911		}
1912		nbytes = stream_write(dest, line, size);
1913		if (nbytes == -1)
1914			return (UPDATER_ERR_MSG);
1915		line = stream_getln(src, &size);
1916		first = 0;
1917	}
1918	if (line == NULL)
1919		return (UPDATER_ERR_READ);
1920	if (size == 1 && *line == '.') {
1921		nbytes = stream_write(dest, "\n", 1);
1922		if (nbytes == -1)
1923			return (UPDATER_ERR_MSG);
1924	}
1925	return (0);
1926}
1927
1928/* Update file using the rsync protocol. */
1929static int
1930updater_rsync(struct updater *up, struct file_update *fup, size_t blocksize)
1931{
1932	struct statusrec *sr;
1933	struct stream *to;
1934	char md5[MD5_DIGEST_SIZE];
1935	ssize_t nbytes;
1936	size_t blocknum, blockstart, blockcount;
1937	char *buf, *line;
1938	int error, orig;
1939
1940	sr = &fup->srbuf;
1941
1942	lprintf(1, " Rsync %s\n", fup->coname);
1943	/* First open all files that we are going to work on. */
1944	to = stream_open_file(fup->temppath, O_WRONLY | O_CREAT | O_TRUNC,
1945	    0600);
1946	if (to == NULL) {
1947		xasprintf(&up->errmsg, "%s: Cannot create: %s",
1948		    fup->temppath, strerror(errno));
1949		return (UPDATER_ERR_MSG);
1950	}
1951	orig = open(fup->destpath, O_RDONLY);
1952	if (orig < 0) {
1953		xasprintf(&up->errmsg, "%s: Cannot open: %s",
1954		    fup->destpath, strerror(errno));
1955		return (UPDATER_ERR_MSG);
1956	}
1957	stream_filter_start(to, STREAM_FILTER_MD5, md5);
1958
1959	error = updater_read_checkout(up->rd, to);
1960	if (error) {
1961		xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath,
1962		    strerror(errno));
1963		return (error);
1964	}
1965
1966	/* Buffer must contain blocksize bytes. */
1967	buf = xmalloc(blocksize);
1968	/* Done with the initial text, read and write chunks. */
1969	line = stream_getln(up->rd, NULL);
1970	while (line != NULL) {
1971		if (strcmp(line, ".") == 0)
1972			break;
1973		error = UPDATER_ERR_PROTO;
1974		if (proto_get_sizet(&line, &blockstart, 10) != 0)
1975			goto bad;
1976		if (proto_get_sizet(&line, &blockcount, 10) != 0)
1977			goto bad;
1978		/* Read blocks from original file. */
1979		lseek(orig, (blocksize * blockstart), SEEK_SET);
1980		error = UPDATER_ERR_MSG;
1981		for (blocknum = 0; blocknum < blockcount; blocknum++) {
1982			nbytes = read(orig, buf, blocksize);
1983			if (nbytes < 0) {
1984				xasprintf(&up->errmsg, "%s: Cannot read: %s",
1985				    fup->destpath, strerror(errno));
1986				goto bad;
1987			}
1988			nbytes = stream_write(to, buf, nbytes);
1989			if (nbytes == -1) {
1990				xasprintf(&up->errmsg, "%s: Cannot write: %s",
1991				    fup->temppath, strerror(errno));
1992				goto bad;
1993			}
1994		}
1995		/* Get the remaining text from the server. */
1996		error = updater_read_checkout(up->rd, to);
1997		if (error) {
1998			xasprintf(&up->errmsg, "%s: Cannot write: %s",
1999			    fup->temppath, strerror(errno));
2000			goto bad;
2001		}
2002		line = stream_getln(up->rd, NULL);
2003	}
2004	stream_close(to);
2005	close(orig);
2006
2007	sr->sr_clientattr = fattr_frompath(fup->destpath, FATTR_NOFOLLOW);
2008	if (sr->sr_clientattr == NULL)
2009		return (UPDATER_ERR_PROTO);
2010	fattr_override(sr->sr_clientattr, sr->sr_serverattr,
2011	    FA_MODTIME | FA_MASK);
2012
2013	error = updater_updatefile(up, fup, md5, 0);
2014	fup->wantmd5 = NULL;	/* So that it doesn't get freed. */
2015bad:
2016	free(buf);
2017	return (error);
2018}
2019