xref: /openbsd-src/gnu/usr.bin/cvs/src/update.c (revision 066e68fa4069b9d7197ac82bee5eb7d28b6f0aa2)
1 /*
2  * Copyright (c) 1992, Brian Berliner and Jeff Polk
3  * Copyright (c) 1989-1992, Brian Berliner
4  *
5  * You may distribute under the terms of the GNU General Public License as
6  * specified in the README file that comes with the CVS 1.4 kit.
7  *
8  * "update" updates the version in the present directory with respect to the RCS
9  * repository.  The present version must have been created by "checkout". The
10  * user can keep up-to-date by calling "update" whenever he feels like it.
11  *
12  * The present version can be committed by "commit", but this keeps the version
13  * in tact.
14  *
15  * Arguments following the options are taken to be file names to be updated,
16  * rather than updating the entire directory.
17  *
18  * Modified or non-existent RCS files are checked out and reported as U
19  * <user_file>
20  *
21  * Modified user files are reported as M <user_file>.  If both the RCS file and
22  * the user file have been modified, the user file is replaced by the result
23  * of rcsmerge, and a backup file is written for the user in .#file.version.
24  * If this throws up irreconcilable differences, the file is reported as C
25  * <user_file>, and as M <user_file> otherwise.
26  *
27  * Files added but not yet committed are reported as A <user_file>. Files
28  * removed but not yet committed are reported as R <user_file>.
29  *
30  * If the current directory contains subdirectories that hold concurrent
31  * versions, these are updated too.  If the -d option was specified, new
32  * directories added to the repository are automatically created and updated
33  * as well.
34  */
35 
36 #include "cvs.h"
37 #include "savecwd.h"
38 #ifdef SERVER_SUPPORT
39 #include "md5.h"
40 #endif
41 #include "watch.h"
42 #include "fileattr.h"
43 #include "edit.h"
44 #include "getline.h"
45 
46 static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts,
47 				 int adding));
48 #ifdef SERVER_SUPPORT
49 static int patch_file PROTO ((struct file_info *finfo,
50 			      Vers_TS *vers_ts,
51 			      int *docheckout, struct stat *file_info,
52 			      unsigned char *checksum));
53 static void patch_file_write PROTO ((void *, const char *, size_t));
54 #endif
55 static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
56 static int scratch_file PROTO((struct file_info *finfo));
57 static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir,
58 					char *repository, char *update_dir,
59 					List *entries));
60 static int update_dirleave_proc PROTO ((void *callerdat, char *dir,
61 					int err, char *update_dir,
62 					List *entries));
63 static int update_fileproc PROTO ((void *callerdat, struct file_info *));
64 static int update_filesdone_proc PROTO ((void *callerdat, int err,
65 					 char *repository, char *update_dir,
66 					 List *entries));
67 static int write_letter PROTO((char *file, int letter, char *update_dir));
68 #ifdef SERVER_SUPPORT
69 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts));
70 #else
71 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts));
72 #endif
73 
74 static char *options = NULL;
75 static char *tag = NULL;
76 static char *date = NULL;
77 /* This is a bit of a kludge.  We call WriteTag at the beginning
78    before we know whether nonbranch is set or not.  And then at the
79    end, once we have the right value for nonbranch, we call WriteTag
80    again.  I don't know whether the first call is necessary or not.
81    rewrite_tag is nonzero if we are going to have to make that second
82    call.  */
83 static int rewrite_tag;
84 static int nonbranch;
85 
86 static char *join_rev1, *date_rev1;
87 static char *join_rev2, *date_rev2;
88 static int aflag = 0;
89 static int force_tag_match = 1;
90 static int update_build_dirs = 0;
91 static int update_prune_dirs = 0;
92 static int pipeout = 0;
93 #ifdef SERVER_SUPPORT
94 static int patches = 0;
95 static int rcs_diff_patches = 0;
96 #endif
97 static List *ignlist = (List *) NULL;
98 static time_t last_register_time;
99 static const char *const update_usage[] =
100 {
101     "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n",
102     "    [-I ign] [-W spec] [files...]\n",
103     "\t-A\tReset any sticky tags/date/kopts.\n",
104     "\t-P\tPrune empty directories.\n",
105     "\t-d\tBuild directories, like checkout does.\n",
106     "\t-f\tForce a head revision match if tag/date not found.\n",
107     "\t-l\tLocal directory only, no recursion.\n",
108     "\t-R\tProcess directories recursively.\n",
109     "\t-p\tSend updates to standard output (avoids stickiness).\n",
110     "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
111     "\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
112     "\t-D date\tSet date to update from (is sticky).\n",
113     "\t-j rev\tMerge in changes made between current revision and rev.\n",
114     "\t-I ign\tMore files to ignore (! to reset).\n",
115     "\t-W spec\tWrappers specification line.\n",
116     NULL
117 };
118 
119 /*
120  * update is the argv,argc based front end for arg parsing
121  */
122 int
123 update (argc, argv)
124     int argc;
125     char **argv;
126 {
127     int c, err;
128     int local = 0;			/* recursive by default */
129     int which;				/* where to look for files and dirs */
130 
131     if (argc == -1)
132 	usage (update_usage);
133 
134     ign_setup ();
135     wrap_setup ();
136 
137     /* parse the args */
138     optind = 0;
139     while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1)
140     {
141 	switch (c)
142 	{
143 	    case 'A':
144 		aflag = 1;
145 		break;
146 	    case 'I':
147 		ign_add (optarg, 0);
148 		break;
149 	    case 'W':
150 		wrap_add (optarg, 0);
151 		break;
152 	    case 'k':
153 		if (options)
154 		    free (options);
155 		options = RCS_check_kflag (optarg);
156 		break;
157 	    case 'l':
158 		local = 1;
159 		break;
160 	    case 'R':
161 		local = 0;
162 		break;
163 	    case 'Q':
164 	    case 'q':
165 #ifdef SERVER_SUPPORT
166 		/* The CVS 1.5 client sends these options (in addition to
167 		   Global_option requests), so we must ignore them.  */
168 		if (!server_active)
169 #endif
170 		    error (1, 0,
171 			   "-q or -Q must be specified before \"%s\"",
172 			   command_name);
173 		break;
174 	    case 'd':
175 		update_build_dirs = 1;
176 		break;
177 	    case 'f':
178 		force_tag_match = 0;
179 		break;
180 	    case 'r':
181 		tag = optarg;
182 		break;
183 	    case 'D':
184 		date = Make_Date (optarg);
185 		break;
186 	    case 'P':
187 		update_prune_dirs = 1;
188 		break;
189 	    case 'p':
190 		pipeout = 1;
191 		noexec = 1;		/* so no locks will be created */
192 		break;
193 	    case 'j':
194 		if (join_rev2)
195 		    error (1, 0, "only two -j options can be specified");
196 		if (join_rev1)
197 		    join_rev2 = optarg;
198 		else
199 		    join_rev1 = optarg;
200 		break;
201 	    case 'u':
202 #ifdef SERVER_SUPPORT
203 		if (server_active)
204 		{
205 		    patches = 1;
206 		    rcs_diff_patches = server_use_rcs_diff ();
207 		}
208 		else
209 #endif
210 		    usage (update_usage);
211 		break;
212 	    case '?':
213 	    default:
214 		usage (update_usage);
215 		break;
216 	}
217     }
218     argc -= optind;
219     argv += optind;
220 
221 #ifdef CLIENT_SUPPORT
222     if (client_active)
223     {
224 	int pass;
225 
226 	/* The first pass does the regular update.  If we receive at least
227 	   one patch which failed, we do a second pass and just fetch
228 	   those files whose patches failed.  */
229 	pass = 1;
230 	do
231 	{
232 	    int status;
233 
234 	    start_server ();
235 
236 	    if (local)
237 		send_arg("-l");
238 	    if (update_build_dirs)
239 		send_arg("-d");
240 	    if (pipeout)
241 		send_arg("-p");
242 	    if (!force_tag_match)
243 		send_arg("-f");
244 	    if (aflag)
245 		send_arg("-A");
246 	    if (update_prune_dirs)
247 		send_arg("-P");
248 	    client_prune_dirs = update_prune_dirs;
249 	    option_with_arg ("-r", tag);
250 	    if (options && options[0] != '\0')
251 		send_arg (options);
252 	    if (date)
253 		client_senddate (date);
254 	    if (join_rev1)
255 		option_with_arg ("-j", join_rev1);
256 	    if (join_rev2)
257 		option_with_arg ("-j", join_rev2);
258 	    wrap_send ();
259 
260 	    /* If the server supports the command "update-patches", that means
261 	       that it knows how to handle the -u argument to update, which
262 	       means to send patches instead of complete files.  */
263 	    if (failed_patches == NULL)
264 	    {
265 #ifndef DONT_USE_PATCH
266 		/* Systems which don't have the patch program ported to them
267 		   will want to define DONT_USE_PATCH; then CVS won't try to
268 		   invoke patch.  */
269 		if (supported_request ("update-patches"))
270 		    send_arg ("-u");
271 #endif
272 	    }
273 
274 	    if (failed_patches == NULL)
275 	    {
276 		send_file_names (argc, argv, SEND_EXPAND_WILD);
277 		/* If noexec, probably could be setting SEND_NO_CONTENTS.
278 		   Same caveats as for "cvs status" apply.  */
279 		send_files (argc, argv, local, aflag,
280 			    update_build_dirs ? SEND_BUILD_DIRS : 0);
281 	    }
282 	    else
283 	    {
284 		int i;
285 
286 		(void) printf ("%s client: refetching unpatchable files\n",
287 			       program_name);
288 
289 		if (toplevel_wd != NULL
290 		    && CVS_CHDIR (toplevel_wd) < 0)
291 		{
292 		    error (1, errno, "could not chdir to %s", toplevel_wd);
293 		}
294 
295 		for (i = 0; i < failed_patches_count; i++)
296 		    (void) unlink_file (failed_patches[i]);
297 		send_file_names (failed_patches_count, failed_patches, 0);
298 		send_files (failed_patches_count, failed_patches, local,
299 			    aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
300 	    }
301 
302 	    failed_patches = NULL;
303 	    failed_patches_count = 0;
304 
305 	    send_to_server ("update\012", 0);
306 
307 	    status = get_responses_and_close ();
308 
309 	    /* If there are any conflicts, the server will return a
310                non-zero exit status.  If any patches failed, we still
311                want to run the update again.  We use a pass count to
312                avoid an endless loop.  */
313 
314 	    /* Notes: (1) assuming that status != 0 implies a
315 	       potential conflict is the best we can cleanly do given
316 	       the current protocol.  I suppose that trying to
317 	       re-fetch in cases where there was a more serious error
318 	       is probably more or less harmless, but it isn't really
319 	       ideal.  (2) it would be nice to have a testsuite case for the
320 	       conflict-and-patch-failed case.  */
321 
322 	    if (status != 0
323 		&& (failed_patches == NULL || pass > 1))
324 	    {
325 		return status;
326 	    }
327 
328 	    ++pass;
329 	} while (failed_patches != NULL);
330 
331 	return 0;
332     }
333 #endif
334 
335     if (tag != NULL)
336 	tag_check_valid (tag, argc, argv, local, aflag, "");
337     if (join_rev1 != NULL)
338         tag_check_valid_join (join_rev1, argc, argv, local, aflag, "");
339     if (join_rev2 != NULL)
340         tag_check_valid_join (join_rev2, argc, argv, local, aflag, "");
341 
342     /*
343      * If we are updating the entire directory (for real) and building dirs
344      * as we go, we make sure there is no static entries file and write the
345      * tag file as appropriate
346      */
347     if (argc <= 0 && !pipeout)
348     {
349 	if (update_build_dirs)
350 	{
351 	    if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
352 		error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
353 #ifdef SERVER_SUPPORT
354 	    if (server_active)
355 		server_clear_entstat (".", Name_Repository (NULL, NULL));
356 #endif
357 	}
358 
359 	/* keep the CVS/Tag file current with the specified arguments */
360 	if (aflag || tag || date)
361 	{
362 	    WriteTag ((char *) NULL, tag, date, 0,
363 		      ".", Name_Repository (NULL, NULL));
364 	    rewrite_tag = 1;
365 	    nonbranch = 0;
366 	}
367     }
368 
369     /* look for files/dirs locally and in the repository */
370     which = W_LOCAL | W_REPOS;
371 
372     /* look in the attic too if a tag or date is specified */
373     if (tag != NULL || date != NULL || joining())
374 	which |= W_ATTIC;
375 
376     /* call the command line interface */
377     err = do_update (argc, argv, options, tag, date, force_tag_match,
378 		     local, update_build_dirs, aflag, update_prune_dirs,
379 		     pipeout, which, join_rev1, join_rev2, (char *) NULL);
380 
381     /* free the space Make_Date allocated if necessary */
382     if (date != NULL)
383 	free (date);
384 
385     return (err);
386 }
387 
388 /*
389  * Command line interface to update (used by checkout)
390  */
391 int
392 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
393 	   xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir)
394     int argc;
395     char **argv;
396     char *xoptions;
397     char *xtag;
398     char *xdate;
399     int xforce;
400     int local;
401     int xbuild;
402     int xaflag;
403     int xprune;
404     int xpipeout;
405     int which;
406     char *xjoin_rev1;
407     char *xjoin_rev2;
408     char *preload_update_dir;
409 {
410     int err = 0;
411     char *cp;
412 
413     /* fill in the statics */
414     options = xoptions;
415     tag = xtag;
416     date = xdate;
417     force_tag_match = xforce;
418     update_build_dirs = xbuild;
419     aflag = xaflag;
420     update_prune_dirs = xprune;
421     pipeout = xpipeout;
422 
423     /* setup the join support */
424     join_rev1 = xjoin_rev1;
425     join_rev2 = xjoin_rev2;
426     if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL)
427     {
428 	*cp++ = '\0';
429 	date_rev1 = Make_Date (cp);
430     }
431     else
432 	date_rev1 = (char *) NULL;
433     if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL)
434     {
435 	*cp++ = '\0';
436 	date_rev2 = Make_Date (cp);
437     }
438     else
439 	date_rev2 = (char *) NULL;
440 
441     /* call the recursion processor */
442     err = start_recursion (update_fileproc, update_filesdone_proc,
443 			   update_dirent_proc, update_dirleave_proc, NULL,
444 			   argc, argv, local, which, aflag, 1,
445 			   preload_update_dir, 1);
446 
447     /* see if we need to sleep before returning */
448     if (last_register_time)
449     {
450 	time_t now;
451 
452 	(void) time (&now);
453 	if (now == last_register_time)
454 	    sleep (1);			/* to avoid time-stamp races */
455     }
456 
457     return (err);
458 }
459 
460 /*
461  * This is the callback proc for update.  It is called for each file in each
462  * directory by the recursion code.  The current directory is the local
463  * instantiation.  file is the file name we are to operate on. update_dir is
464  * set to the path relative to where we started (for pretty printing).
465  * repository is the repository. entries and srcfiles are the pre-parsed
466  * entries and source control files.
467  *
468  * This routine decides what needs to be done for each file and does the
469  * appropriate magic for checkout
470  */
471 static int
472 update_fileproc (callerdat, finfo)
473     void *callerdat;
474     struct file_info *finfo;
475 {
476     int retval;
477     Ctype status;
478     Vers_TS *vers;
479     int resurrecting;
480 
481     resurrecting = 0;
482 
483     status = Classify_File (finfo, tag, date, options, force_tag_match,
484 			    aflag, &vers, pipeout);
485 
486     /* Keep track of whether TAG is a branch tag.
487        Note that if it is a branch tag in some files and a nonbranch tag
488        in others, treat it as a nonbranch tag.  It is possible that case
489        should elicit a warning or an error.  */
490     if (rewrite_tag
491 	&& tag != NULL
492 	&& finfo->rcs != NULL)
493     {
494 	char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
495 	if (rev != NULL
496 	    && !RCS_nodeisbranch (finfo->rcs, tag))
497 	    nonbranch = 1;
498 	if (rev != NULL)
499 	    free (rev);
500     }
501 
502     if (pipeout)
503     {
504 	/*
505 	 * We just return success without doing anything if any of the really
506 	 * funky cases occur
507 	 *
508 	 * If there is still a valid RCS file, do a regular checkout type
509 	 * operation
510 	 */
511 	switch (status)
512 	{
513 	    case T_UNKNOWN:		/* unknown file was explicitly asked
514 					 * about */
515 	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
516 	    case T_ADDED:		/* added but not committed */
517 		retval = 0;
518 		break;
519 	    case T_CONFLICT:		/* old punt-type errors */
520 		retval = 1;
521 		break;
522 	    case T_UPTODATE:		/* file was already up-to-date */
523 	    case T_NEEDS_MERGE:		/* needs merging */
524 	    case T_MODIFIED:		/* locally modified */
525 	    case T_REMOVED:		/* removed but not committed */
526 	    case T_CHECKOUT:		/* needs checkout */
527 #ifdef SERVER_SUPPORT
528 	    case T_PATCH:		/* needs patch */
529 #endif
530 		retval = checkout_file (finfo, vers, 0);
531 		break;
532 
533 	    default:			/* can't ever happen :-) */
534 		error (0, 0,
535 		       "unknown file status %d for file %s", status, finfo->file);
536 		retval = 0;
537 		break;
538 	}
539     }
540     else
541     {
542 	switch (status)
543 	{
544 	    case T_UNKNOWN:		/* unknown file was explicitly asked
545 					 * about */
546 	    case T_UPTODATE:		/* file was already up-to-date */
547 		retval = 0;
548 		break;
549 	    case T_CONFLICT:		/* old punt-type errors */
550 		retval = 1;
551 		(void) write_letter (finfo->file, 'C', finfo->update_dir);
552 		break;
553 	    case T_NEEDS_MERGE:		/* needs merging */
554 		if (noexec)
555 		{
556 		    retval = 1;
557 		    (void) write_letter (finfo->file, 'C', finfo->update_dir);
558 		}
559 		else
560 		{
561 		    if (wrap_merge_is_copy (finfo->file))
562 #if 0
563 			/* Look, we can't clobber the user's file.  We
564 			   know it is modified and we're going to
565 			   overwrite their mod?  Puh-leeze.  The
566 			   correct behavior is probably something like
567 			   what merge_file does for -kb, which is to
568 			   give the users both files and tell them
569 			   what the two filenames are.  Of course, -m
570 			   in wrappers needs to be documented *much*
571 			   better.  Anyway, until then, make this a
572 			   fatal error.  */
573 
574 			/* Should we be warning the user that we are
575 			 * overwriting the user's copy of the file?  */
576 			retval =
577 			  checkout_file (finfo, vers, 0);
578 #else
579 		    {
580 		        error (0, 0, "A -m 'COPY' wrapper is specified");
581 			error (0, 0, "but file %s needs merge",
582 			       finfo->fullname);
583 			error (1, 0, "\
584 You probably want to avoid -m 'COPY' wrappers");
585 #endif
586 		    }
587 		    else
588 			retval = merge_file (finfo, vers);
589 		}
590 		break;
591 	    case T_MODIFIED:		/* locally modified */
592 		retval = 0;
593 		if (vers->ts_conflict)
594 		{
595 		    char *filestamp;
596 		    int retcode;
597 
598 		    /*
599 		     * If the timestamp has changed and no conflict indicators
600 		     * are found, it isn't a 'C' any more.
601 		     */
602 #ifdef SERVER_SUPPORT
603 		    if (server_active)
604 			retcode = vers->ts_conflict[0] != '=';
605 		    else {
606 			filestamp = time_stamp (finfo->file);
607 			retcode = strcmp (vers->ts_conflict, filestamp);
608 			free (filestamp);
609 		    }
610 #else
611 		    filestamp = time_stamp (finfo->file);
612 		    retcode = strcmp (vers->ts_conflict, filestamp);
613 		    free (filestamp);
614 #endif
615 
616 		    if (retcode)
617 		    {
618 			/* The timestamps differ.  But if there are conflict
619 			   markers print 'C' anyway.  */
620 			retcode = !file_has_markers (finfo);
621 		    }
622 
623 		    if (!retcode)
624 		    {
625 			(void) write_letter (finfo->file, 'C', finfo->update_dir);
626 			retval = 1;
627 		    }
628 		    else
629 		    {
630 			/* Reregister to clear conflict flag. */
631 			Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs,
632 				  vers->options, vers->tag,
633 				  vers->date, (char *)0);
634 		    }
635 		}
636 		if (!retval)
637 		    retval = write_letter (finfo->file, 'M', finfo->update_dir);
638 		break;
639 #ifdef SERVER_SUPPORT
640 	    case T_PATCH:		/* needs patch */
641 		if (patches)
642 		{
643 		    int docheckout;
644 		    struct stat file_info;
645 		    unsigned char checksum[16];
646 
647 		    retval = patch_file (finfo,
648 					 vers, &docheckout,
649 					 &file_info, checksum);
650 		    if (! docheckout)
651 		    {
652 		        if (server_active && retval == 0)
653 			    server_updated (finfo, vers,
654 					    (rcs_diff_patches
655 					     ? SERVER_RCS_DIFF
656 					     : SERVER_PATCHED),
657 					    &file_info, checksum);
658 			break;
659 		    }
660 		}
661 		/* Fall through.  */
662 		/* If we're not running as a server, just check the
663 		   file out.  It's simpler and faster than starting up
664 		   two new processes (diff and patch).  */
665 		/* Fall through.  */
666 #endif
667 	    case T_CHECKOUT:		/* needs checkout */
668 		retval = checkout_file (finfo, vers, 0);
669 #ifdef SERVER_SUPPORT
670 		if (server_active && retval == 0)
671 		    server_updated (finfo, vers,
672 				    SERVER_UPDATED, (struct stat *) NULL,
673 				    (unsigned char *) NULL);
674 #endif
675 		break;
676 	    case T_ADDED:		/* added but not committed */
677 		retval = write_letter (finfo->file, 'A', finfo->update_dir);
678 		break;
679 	    case T_REMOVED:		/* removed but not committed */
680 		retval = write_letter (finfo->file, 'R', finfo->update_dir);
681 		break;
682 	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
683 		retval = scratch_file (finfo);
684 #ifdef SERVER_SUPPORT
685 		if (server_active && retval == 0)
686 		{
687 		    if (vers->ts_user == NULL)
688 			server_scratch_entry_only ();
689 		    server_updated (finfo, vers,
690 				    SERVER_UPDATED, (struct stat *) NULL,
691 				    (unsigned char *) NULL);
692 		}
693 #endif
694 		break;
695 	    default:			/* can't ever happen :-) */
696 		error (0, 0,
697 		       "unknown file status %d for file %s", status, finfo->file);
698 		retval = 0;
699 		break;
700 	}
701     }
702 
703     /* only try to join if things have gone well thus far */
704     if (retval == 0 && join_rev1)
705 	join_file (finfo, vers);
706 
707     /* if this directory has an ignore list, add this file to it */
708     if (ignlist)
709     {
710 	Node *p;
711 
712 	p = getnode ();
713 	p->type = FILES;
714 	p->key = xstrdup (finfo->file);
715 	if (addnode (ignlist, p) != 0)
716 	    freenode (p);
717     }
718 
719     freevers_ts (&vers);
720     return (retval);
721 }
722 
723 static void update_ignproc PROTO ((char *, char *));
724 
725 static void
726 update_ignproc (file, dir)
727     char *file;
728     char *dir;
729 {
730     (void) write_letter (file, '?', dir);
731 }
732 
733 /* ARGSUSED */
734 static int
735 update_filesdone_proc (callerdat, err, repository, update_dir, entries)
736     void *callerdat;
737     int err;
738     char *repository;
739     char *update_dir;
740     List *entries;
741 {
742     if (rewrite_tag)
743     {
744 	WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
745 	rewrite_tag = 0;
746     }
747 
748     /* if this directory has an ignore list, process it then free it */
749     if (ignlist)
750     {
751 	ignore_files (ignlist, entries, update_dir, update_ignproc);
752 	dellist (&ignlist);
753     }
754 
755     /* Clean up CVS admin dirs if we are export */
756     if (strcmp (command_name, "export") == 0)
757     {
758 	/* I'm not sure the existence_error is actually possible (except
759 	   in cases where we really should print a message), but since
760 	   this code used to ignore all errors, I'll play it safe.  */
761 	if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
762 	    error (0, errno, "cannot remove %s directory", CVSADM);
763     }
764 #ifdef SERVER_SUPPORT
765     else if (!server_active && !pipeout)
766 #else
767     else if (!pipeout)
768 #endif /* SERVER_SUPPORT */
769     {
770         /* If there is no CVS/Root file, add one */
771         if (!isfile (CVSADM_ROOT))
772 	    Create_Root ((char *) NULL, CVSroot_original);
773     }
774 
775     return (err);
776 }
777 
778 /*
779  * update_dirent_proc () is called back by the recursion processor before a
780  * sub-directory is processed for update.  In this case, update_dirent proc
781  * will probably create the directory unless -d isn't specified and this is a
782  * new directory.  A return code of 0 indicates the directory should be
783  * processed by the recursion code.  A return of non-zero indicates the
784  * recursion code should skip this directory.
785  */
786 static Dtype
787 update_dirent_proc (callerdat, dir, repository, update_dir, entries)
788     void *callerdat;
789     char *dir;
790     char *repository;
791     char *update_dir;
792     List *entries;
793 {
794     if (ignore_directory (update_dir))
795     {
796 	/* print the warm fuzzy message */
797 	if (!quiet)
798 	  error (0, 0, "Ignoring %s", update_dir);
799         return R_SKIP_ALL;
800     }
801 
802     if (!isdir (dir))
803     {
804 	/* if we aren't building dirs, blow it off */
805 	if (!update_build_dirs)
806 	    return (R_SKIP_ALL);
807 
808 	if (noexec)
809 	{
810 	    /* ignore the missing dir if -n is specified */
811 	    error (0, 0, "New directory `%s' -- ignored", dir);
812 	    return (R_SKIP_ALL);
813 	}
814 	else
815 	{
816 	    /* otherwise, create the dir and appropriate adm files */
817 	    make_directory (dir);
818 	    Create_Admin (dir, update_dir, repository, tag, date,
819 			  /* This is a guess.  We will rewrite it later
820 			     via WriteTag.  */
821 			  0);
822 	    rewrite_tag = 1;
823 	    nonbranch = 0;
824 	    Subdir_Register (entries, (char *) NULL, dir);
825 	}
826     }
827     /* Do we need to check noexec here? */
828     else if (!pipeout)
829     {
830 	char *cvsadmdir;
831 
832 	/* The directory exists.  Check to see if it has a CVS
833 	   subdirectory.  */
834 
835 	cvsadmdir = xmalloc (strlen (dir) + 80);
836 	strcpy (cvsadmdir, dir);
837 	strcat (cvsadmdir, "/");
838 	strcat (cvsadmdir, CVSADM);
839 
840 	if (!isdir (cvsadmdir))
841 	{
842 	    /* We cannot successfully recurse into a directory without a CVS
843 	       subdirectory.  Generally we will have already printed
844 	       "? foo".  */
845 	    free (cvsadmdir);
846 	    return R_SKIP_ALL;
847 	}
848 	free (cvsadmdir);
849     }
850 
851     /*
852      * If we are building dirs and not going to stdout, we make sure there is
853      * no static entries file and write the tag file as appropriate
854      */
855     if (!pipeout)
856     {
857 	if (update_build_dirs)
858 	{
859 	    char *tmp;
860 
861 	    tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10);
862 	    (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
863 	    if (unlink_file (tmp) < 0 && ! existence_error (errno))
864 		error (1, errno, "cannot remove file %s", tmp);
865 #ifdef SERVER_SUPPORT
866 	    if (server_active)
867 		server_clear_entstat (update_dir, repository);
868 #endif
869 	    free (tmp);
870 	}
871 
872 	/* keep the CVS/Tag file current with the specified arguments */
873 	if (aflag || tag || date)
874 	{
875 	    WriteTag (dir, tag, date, 0, update_dir, repository);
876 	    rewrite_tag = 1;
877 	    nonbranch = 0;
878 	}
879 
880 	/* initialize the ignore list for this directory */
881 	ignlist = getlist ();
882     }
883 
884     /* print the warm fuzzy message */
885     if (!quiet)
886 	error (0, 0, "Updating %s", update_dir);
887 
888     return (R_PROCESS);
889 }
890 
891 /*
892  * update_dirleave_proc () is called back by the recursion code upon leaving
893  * a directory.  It will prune empty directories if needed and will execute
894  * any appropriate update programs.
895  */
896 /* ARGSUSED */
897 static int
898 update_dirleave_proc (callerdat, dir, err, update_dir, entries)
899     void *callerdat;
900     char *dir;
901     int err;
902     char *update_dir;
903     List *entries;
904 {
905     FILE *fp;
906 
907     /* run the update_prog if there is one */
908     /* FIXME: should be checking for errors from CVS_FOPEN and printing
909        them if not existence_error.  */
910     if (err == 0 && !pipeout && !noexec &&
911 	(fp = CVS_FOPEN (CVSADM_UPROG, "r")) != NULL)
912     {
913 	char *cp;
914 	char *repository;
915 	char *line = NULL;
916 	size_t line_allocated = 0;
917 
918 	repository = Name_Repository ((char *) NULL, update_dir);
919 	if (getline (&line, &line_allocated, fp) >= 0)
920 	{
921 	    if ((cp = strrchr (line, '\n')) != NULL)
922 		*cp = '\0';
923 	    run_setup ("%s %s", line, repository);
924 	    cvs_output (program_name, 0);
925 	    cvs_output (" ", 1);
926 	    cvs_output (command_name, 0);
927 	    cvs_output (": Executing '", 0);
928 	    run_print (stdout);
929 	    cvs_output ("'\n", 0);
930 	    (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
931 	}
932 	else if (ferror (fp))
933 	    error (0, errno, "cannot read %s", CVSADM_UPROG);
934 	else
935 	    error (0, 0, "unexpected end of file on %s", CVSADM_UPROG);
936 
937 	if (fclose (fp) < 0)
938 	    error (0, errno, "cannot close %s", CVSADM_UPROG);
939 	if (line != NULL)
940 	    free (line);
941 	free (repository);
942     }
943 
944     if (strchr (dir, '/') == NULL)
945     {
946 	/* FIXME: chdir ("..") loses with symlinks.  */
947 	/* Prune empty dirs on the way out - if necessary */
948 	(void) CVS_CHDIR ("..");
949 	if (update_prune_dirs && isemptydir (dir, 0))
950 	{
951 	    /* I'm not sure the existence_error is actually possible (except
952 	       in cases where we really should print a message), but since
953 	       this code used to ignore all errors, I'll play it safe.	*/
954 	    if (unlink_file_dir (dir) < 0 && !existence_error (errno))
955 		error (0, errno, "cannot remove %s directory", dir);
956 	    Subdir_Deregister (entries, (char *) NULL, dir);
957 	}
958     }
959 
960     return (err);
961 }
962 
963 static int isremoved PROTO ((Node *, void *));
964 
965 /* Returns 1 if the file indicated by node has been removed.  */
966 static int
967 isremoved (node, closure)
968     Node *node;
969     void *closure;
970 {
971     Entnode *entdata = (Entnode*) node->data;
972 
973     /* If the first character of the version is a '-', the file has been
974        removed. */
975     return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
976 }
977 
978 /* Returns 1 if the argument directory is completely empty, other than the
979    existence of the CVS directory entry.  Zero otherwise.  If MIGHT_NOT_EXIST
980    and the directory doesn't exist, then just return 0.  */
981 int
982 isemptydir (dir, might_not_exist)
983     char *dir;
984     int might_not_exist;
985 {
986     DIR *dirp;
987     struct dirent *dp;
988 
989     if ((dirp = CVS_OPENDIR (dir)) == NULL)
990     {
991 	if (might_not_exist && existence_error (errno))
992 	    return 0;
993 	error (0, errno, "cannot open directory %s for empty check", dir);
994 	return (0);
995     }
996     errno = 0;
997     while ((dp = readdir (dirp)) != NULL)
998     {
999 	if (strcmp (dp->d_name, ".") != 0
1000 	    && strcmp (dp->d_name, "..") != 0)
1001 	{
1002 	    if (strcmp (dp->d_name, CVSADM) != 0)
1003 	    {
1004 		/* An entry other than the CVS directory.  The directory
1005 		   is certainly not empty. */
1006 		(void) closedir (dirp);
1007 		return (0);
1008 	    }
1009 	    else
1010 	    {
1011 		/* The CVS directory entry.  We don't have to worry about
1012 		   this unless the Entries file indicates that files have
1013 		   been removed, but not committed, in this directory.
1014 		   (Removing the directory would prevent people from
1015 		   comitting the fact that they removed the files!) */
1016 		List *l;
1017 		int files_removed;
1018 		struct saved_cwd cwd;
1019 
1020 		if (save_cwd (&cwd))
1021 		    error_exit ();
1022 
1023 		if (CVS_CHDIR (dir) < 0)
1024 		    error (1, errno, "cannot change directory to %s", dir);
1025 		l = Entries_Open (0);
1026 		files_removed = walklist (l, isremoved, 0);
1027 		Entries_Close (l);
1028 
1029 		if (restore_cwd (&cwd, NULL))
1030 		    error_exit ();
1031 		free_cwd (&cwd);
1032 
1033 		if (files_removed != 0)
1034 		{
1035 		    /* There are files that have been removed, but not
1036 		       committed!  Do not consider the directory empty. */
1037 		    (void) closedir (dirp);
1038 		    return (0);
1039 		}
1040 	    }
1041 	}
1042 	errno = 0;
1043     }
1044     if (errno != 0)
1045     {
1046 	error (0, errno, "cannot read directory %s", dir);
1047 	(void) closedir (dirp);
1048 	return (0);
1049     }
1050     (void) closedir (dirp);
1051     return (1);
1052 }
1053 
1054 /*
1055  * scratch the Entries file entry associated with a file
1056  */
1057 static int
1058 scratch_file (finfo)
1059     struct file_info *finfo;
1060 {
1061     history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1062     Scratch_Entry (finfo->entries, finfo->file);
1063     if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1064 	error (0, errno, "unable to remove %s", finfo->fullname);
1065     return (0);
1066 }
1067 
1068 /*
1069  * Check out a file.
1070  */
1071 static int
1072 checkout_file (finfo, vers_ts, adding)
1073     struct file_info *finfo;
1074     Vers_TS *vers_ts;
1075     int adding;
1076 {
1077     char *backup;
1078     int set_time, retval = 0;
1079     int retcode = 0;
1080     int status;
1081     int file_is_dead;
1082 
1083     /* don't screw with backup files if we're going to stdout */
1084     if (!pipeout)
1085     {
1086 	backup = xmalloc (strlen (finfo->file)
1087 			  + sizeof (CVSADM)
1088 			  + sizeof (CVSPREFIX)
1089 			  + 10);
1090 	(void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1091 	if (isfile (finfo->file))
1092 	    rename_file (finfo->file, backup);
1093 	else
1094 	    /* If -f/-t wrappers are being used to wrap up a directory,
1095 	       then backup might be a directory instead of just a file.  */
1096 	    (void) unlink_file_dir (backup);
1097     }
1098 
1099     file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1100 
1101     if (!file_is_dead)
1102     {
1103 	/*
1104 	 * if we are checking out to stdout, print a nice message to
1105 	 * stderr, and add the -p flag to the command */
1106 	if (pipeout)
1107 	{
1108 	    if (!quiet)
1109 	    {
1110 		cvs_outerr ("\
1111 ===================================================================\n\
1112 Checking out ", 0);
1113 		cvs_outerr (finfo->fullname, 0);
1114 		cvs_outerr ("\n\
1115 RCS:  ", 0);
1116 		cvs_outerr (vers_ts->srcfile->path, 0);
1117 		cvs_outerr ("\n\
1118 VERS: ", 0);
1119 		cvs_outerr (vers_ts->vn_rcs, 0);
1120 		cvs_outerr ("\n***************\n", 0);
1121 	    }
1122 	}
1123 
1124 	status = RCS_checkout (vers_ts->srcfile,
1125 			       pipeout ? NULL : finfo->file,
1126 			       vers_ts->vn_rcs, vers_ts->vn_tag,
1127 			       vers_ts->options, RUN_TTY,
1128 			       (RCSCHECKOUTPROC) NULL, (void *) NULL);
1129     }
1130     if (file_is_dead || status == 0)
1131     {
1132 	if (!pipeout)
1133 	{
1134 	    Vers_TS *xvers_ts;
1135 
1136 	    if (cvswrite == TRUE
1137 		&& !file_is_dead
1138 		&& !fileattr_get (finfo->file, "_watched"))
1139 		xchmod (finfo->file, 1);
1140 
1141 	    {
1142 		/* A newly checked out file is never under the spell
1143 		   of "cvs edit".  If we think we were editing it
1144 		   from a previous life, clean up.  Would be better to
1145 		   check for same the working directory instead of
1146 		   same user, but that is hairy.  */
1147 
1148 		struct addremove_args args;
1149 
1150 		editor_set (finfo->file, getcaller (), NULL);
1151 
1152 		memset (&args, 0, sizeof args);
1153 		args.remove_temp = 1;
1154 		watch_modify_watchers (finfo->file, &args);
1155 	    }
1156 
1157 	    /* set the time from the RCS file iff it was unknown before */
1158 	    if (vers_ts->vn_user == NULL ||
1159 		strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1160 	    {
1161 		set_time = 1;
1162 	    }
1163 	    else
1164 		set_time = 0;
1165 
1166 	    wrap_fromcvs_process_file (finfo->file);
1167 
1168 	    xvers_ts = Version_TS (finfo, options, tag, date,
1169 				   force_tag_match, set_time);
1170 	    if (strcmp (xvers_ts->options, "-V4") == 0)
1171 		xvers_ts->options[0] = '\0';
1172 
1173 	    (void) time (&last_register_time);
1174 
1175 	    if (file_is_dead)
1176 	    {
1177 		if (xvers_ts->vn_user != NULL)
1178 		{
1179 		    error (0, 0,
1180 			   "warning: %s is not (any longer) pertinent",
1181 			   finfo->fullname);
1182 		}
1183 		Scratch_Entry (finfo->entries, finfo->file);
1184 #ifdef SERVER_SUPPORT
1185 		if (server_active && xvers_ts->ts_user == NULL)
1186 		    server_scratch_entry_only ();
1187 #endif
1188 		/* FIXME: Rather than always unlink'ing, and ignoring the
1189 		   existence_error, we should do the unlink only if
1190 		   vers_ts->ts_user is non-NULL.  Then there would be no
1191 		   need to ignore an existence_error (for example, if the
1192 		   user removes the file while we are running).  */
1193 		if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1194 		{
1195 		    error (0, errno, "cannot remove %s", finfo->fullname);
1196 		}
1197 	    }
1198 	    else
1199 		Register (finfo->entries, finfo->file,
1200 			  adding ? "0" : xvers_ts->vn_rcs,
1201 			  xvers_ts->ts_user, xvers_ts->options,
1202 			  xvers_ts->tag, xvers_ts->date,
1203 			  (char *)0); /* Clear conflict flag on fresh checkout */
1204 
1205 	    /* fix up the vers structure, in case it is used by join */
1206 	    if (join_rev1)
1207 	    {
1208 		if (vers_ts->vn_user != NULL)
1209 		    free (vers_ts->vn_user);
1210 		if (vers_ts->vn_rcs != NULL)
1211 		    free (vers_ts->vn_rcs);
1212 		vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1213 		vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1214 	    }
1215 
1216 	    /* If this is really Update and not Checkout, recode history */
1217 	    if (strcmp (command_name, "update") == 0)
1218 		history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1219 			       finfo->repository);
1220 
1221 	    freevers_ts (&xvers_ts);
1222 
1223 	    if (!really_quiet && !file_is_dead)
1224 	    {
1225 		write_letter (finfo->file, 'U', finfo->update_dir);
1226 	    }
1227 	}
1228     }
1229     else
1230     {
1231 	int old_errno = errno;		/* save errno value over the rename */
1232 
1233 	if (!pipeout && isfile (backup))
1234 	    rename_file (backup, finfo->file);
1235 
1236 	error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1237 	       "could not check out %s", finfo->fullname);
1238 
1239 	retval = retcode;
1240     }
1241 
1242     if (!pipeout)
1243     {
1244 	/* If -f/-t wrappers are being used to wrap up a directory,
1245 	   then backup might be a directory instead of just a file.  */
1246 	(void) unlink_file_dir (backup);
1247 	free (backup);
1248     }
1249 
1250     return (retval);
1251 }
1252 
1253 #ifdef SERVER_SUPPORT
1254 
1255 /* This structure is used to pass information between patch_file and
1256    patch_file_write.  */
1257 
1258 struct patch_file_data
1259 {
1260     /* File name, for error messages.  */
1261     const char *filename;
1262     /* File to which to write.  */
1263     FILE *fp;
1264     /* Whether to compute the MD5 checksum.  */
1265     int compute_checksum;
1266     /* Data structure for computing the MD5 checksum.  */
1267     struct MD5Context context;
1268     /* Set if the file has a final newline.  */
1269     int final_nl;
1270 };
1271 
1272 /* Patch a file.  Runs diff.  This is only done when running as the
1273  * server.  The hope is that the diff will be smaller than the file
1274  * itself.
1275  */
1276 static int
1277 patch_file (finfo, vers_ts, docheckout, file_info, checksum)
1278     struct file_info *finfo;
1279     Vers_TS *vers_ts;
1280     int *docheckout;
1281     struct stat *file_info;
1282     unsigned char *checksum;
1283 {
1284     char *backup;
1285     char *file1;
1286     char *file2;
1287     int retval = 0;
1288     int retcode = 0;
1289     int fail;
1290     long file_size;
1291     FILE *e;
1292     struct patch_file_data data;
1293 
1294     *docheckout = 0;
1295 
1296     if (noexec || pipeout || joining ())
1297     {
1298 	*docheckout = 1;
1299 	return 0;
1300     }
1301 
1302     /* If this file has been marked as being binary, then never send a
1303        patch.  */
1304     if (strcmp (vers_ts->options, "-kb") == 0)
1305     {
1306 	*docheckout = 1;
1307 	return 0;
1308     }
1309 
1310     backup = xmalloc (strlen (finfo->file)
1311 		      + sizeof (CVSADM)
1312 		      + sizeof (CVSPREFIX)
1313 		      + 10);
1314     (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1315     if (isfile (finfo->file))
1316         rename_file (finfo->file, backup);
1317     else
1318         (void) unlink_file (backup);
1319 
1320     file1 = xmalloc (strlen (finfo->file)
1321 		     + sizeof (CVSADM)
1322 		     + sizeof (CVSPREFIX)
1323 		     + 10);
1324     (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1325     file2 = xmalloc (strlen (finfo->file)
1326 		     + sizeof (CVSADM)
1327 		     + sizeof (CVSPREFIX)
1328 		     + 10);
1329     (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1330 
1331     fail = 0;
1332 
1333     /* We need to check out both revisions first, to see if either one
1334        has a trailing newline.  Because of this, we don't use rcsdiff,
1335        but just use diff.  */
1336 
1337     e = CVS_FOPEN (file1, "w");
1338     if (e == NULL)
1339 	error (1, errno, "cannot open %s", file1);
1340 
1341     data.filename = file1;
1342     data.fp = e;
1343     data.final_nl = 0;
1344     data.compute_checksum = 0;
1345 
1346     retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1347 			    vers_ts->vn_user, (char *) NULL,
1348 			    vers_ts->options, RUN_TTY,
1349 			    patch_file_write, (void *) &data);
1350 
1351     if (fclose (e) < 0)
1352 	error (1, errno, "cannot close %s", file1);
1353 
1354     if (retcode != 0 || ! data.final_nl)
1355 	fail = 1;
1356 
1357     if (! fail)
1358     {
1359 	e = CVS_FOPEN (file2, "w");
1360 	if (e == NULL)
1361 	    error (1, errno, "cannot open %s", file2);
1362 
1363 	data.filename = file2;
1364 	data.fp = e;
1365 	data.final_nl = 0;
1366 	data.compute_checksum = 1;
1367 	MD5Init (&data.context);
1368 
1369 	retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1370 				vers_ts->vn_rcs, (char *) NULL,
1371 				vers_ts->options, RUN_TTY,
1372 				patch_file_write, (void *) &data);
1373 
1374 	if (fclose (e) < 0)
1375 	    error (1, errno, "cannot close %s", file2);
1376 
1377 	if (retcode != 0 || ! data.final_nl)
1378 	    fail = 1;
1379 	else
1380 	    MD5Final (checksum, &data.context);
1381     }
1382 
1383     retcode = 0;
1384     if (! fail)
1385     {
1386 	const char *diff_options;
1387 
1388 	/* FIXME: It might be better to come up with a diff library
1389            which can be shared with the diffutils.  */
1390 	/* If the client does not support the Rcs-diff command, we
1391            send a context diff, and the client must invoke patch.
1392            That approach was problematical for various reasons.  The
1393            new approach only requires running diff in the server; the
1394            client can handle everything without invoking an external
1395            program.  */
1396 	if (! rcs_diff_patches)
1397 	{
1398 	    /* We use -c, not -u, because we have no way of knowing
1399 	       which DIFF is in use.  */
1400 	    diff_options = "-c";
1401 	}
1402 	else
1403 	{
1404 	    /* FIXME: We should use -a if diff supports it.  We should
1405                probably just copy over most or all of the diff
1406                handling in the RCS configure script.  */
1407 	    /* IMHO, we shouldn't copy over anything which even
1408 	       vaguely resembles the RCS configure script.  That kind of
1409 	       thing tends to be ugly, slow, and fragile.  It also is a
1410 	       a support headache for CVS to behave differently in subtle
1411 	       ways based on whether it was installed correctly.  Instead we
1412 	       should come up with a diff library.  -kingdon, Apr 1997.  */
1413 	    diff_options = "-n";
1414 	}
1415 	run_setup ("%s %s %s %s", DIFF, diff_options, file1, file2);
1416 
1417 	/* A retcode of 0 means no differences.  1 means some differences.  */
1418 	if ((retcode = run_exec (RUN_TTY, finfo->file, RUN_TTY, RUN_NORMAL)) != 0
1419 	    && retcode != 1)
1420 	{
1421 	    fail = 1;
1422 	}
1423 	else
1424 	{
1425 #define BINARY "Binary"
1426 	    char buf[sizeof BINARY];
1427 	    unsigned int c;
1428 
1429 	    /* Stat the original RCS file, and then adjust it the way
1430 	       that RCS_checkout would.  FIXME: This is an abstraction
1431 	       violation.  */
1432 	    if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
1433 		error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1434 	    if (chmod (finfo->file,
1435 		       file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1436 		< 0)
1437 		error (0, errno, "cannot change mode of file %s", finfo->file);
1438 	    if (cvswrite == TRUE
1439 		&& !fileattr_get (finfo->file, "_watched"))
1440 		xchmod (finfo->file, 1);
1441 
1442 	    /* Check the diff output to make sure patch will be handle it.  */
1443 	    e = CVS_FOPEN (finfo->file, "r");
1444 	    if (e == NULL)
1445 		error (1, errno, "could not open diff output file %s",
1446 		       finfo->fullname);
1447 	    c = fread (buf, 1, sizeof BINARY - 1, e);
1448 	    buf[c] = '\0';
1449 	    if (strcmp (buf, BINARY) == 0)
1450 	    {
1451 		/* These are binary files.  We could use diff -a, but
1452 		   patch can't handle that.  */
1453 		fail = 1;
1454 	    }
1455 	    else {
1456 		/*
1457 		 * Don't send a diff if just sending the entire file
1458 		 * would be smaller
1459 		 */
1460 		fseek(e, 0L, SEEK_END);
1461 		if (file_size < ftell(e))
1462 		    fail = 1;
1463 	    }
1464 
1465 	    fclose (e);
1466 	}
1467     }
1468 
1469     if (! fail)
1470     {
1471         Vers_TS *xvers_ts;
1472 
1473         /* This stuff is just copied blindly from checkout_file.  I
1474 	   don't really know what it does.  */
1475         xvers_ts = Version_TS (finfo, options, tag, date,
1476 			       force_tag_match, 0);
1477 	if (strcmp (xvers_ts->options, "-V4") == 0)
1478 	    xvers_ts->options[0] = '\0';
1479 
1480 	Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1481 		  xvers_ts->ts_user, xvers_ts->options,
1482 		  xvers_ts->tag, xvers_ts->date, NULL);
1483 
1484 	if (CVS_STAT (finfo->file, file_info) < 0)
1485 	    error (1, errno, "could not stat %s", finfo->file);
1486 
1487 	/* If this is really Update and not Checkout, recode history */
1488 	if (strcmp (command_name, "update") == 0)
1489 	    history_write ('P', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1490 			   finfo->repository);
1491 
1492 	freevers_ts (&xvers_ts);
1493 
1494 	if (!really_quiet)
1495 	{
1496 	    write_letter (finfo->file, 'P', finfo->update_dir);
1497 	}
1498     }
1499     else
1500     {
1501 	int old_errno = errno;		/* save errno value over the rename */
1502 
1503 	if (isfile (backup))
1504 	    rename_file (backup, finfo->file);
1505 
1506 	if (retcode != 0 && retcode != 1)
1507 	    error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1508 		   "could not diff %s", finfo->fullname);
1509 
1510 	*docheckout = 1;
1511 	retval = retcode;
1512     }
1513 
1514     (void) unlink_file (backup);
1515     (void) unlink_file (file1);
1516     (void) unlink_file (file2);
1517 
1518     free (backup);
1519     free (file1);
1520     free (file2);
1521     return (retval);
1522 }
1523 
1524 /* Write data to a file.  Record whether the last byte written was a
1525    newline.  Optionally compute a checksum.  This is called by
1526    patch_file via RCS_checkout.  */
1527 
1528 static void
1529 patch_file_write (callerdat, buffer, len)
1530      void *callerdat;
1531      const char *buffer;
1532      size_t len;
1533 {
1534     struct patch_file_data *data = (struct patch_file_data *) callerdat;
1535 
1536     if (fwrite (buffer, 1, len, data->fp) != len)
1537 	error (1, errno, "cannot write %s", data->filename);
1538 
1539     data->final_nl = (buffer[len - 1] == '\n');
1540 
1541     if (data->compute_checksum)
1542 	MD5Update (&data->context, buffer, len);
1543 }
1544 
1545 #endif /* SERVER_SUPPORT */
1546 
1547 /*
1548  * Several of the types we process only print a bit of information consisting
1549  * of a single letter and the name.
1550  */
1551 static int
1552 write_letter (file, letter, update_dir)
1553     char *file;
1554     int letter;
1555     char *update_dir;
1556 {
1557     if (!really_quiet)
1558     {
1559 	char buf[2];
1560 	buf[0] = letter;
1561 	buf[1] = ' ';
1562 	cvs_output (buf, 2);
1563 	if (update_dir[0])
1564 	{
1565 	    cvs_output (update_dir, 0);
1566 	    cvs_output ("/", 1);
1567 	}
1568 	cvs_output (file, 0);
1569 	cvs_output ("\n", 1);
1570     }
1571     return (0);
1572 }
1573 
1574 /*
1575  * Do all the magic associated with a file which needs to be merged
1576  */
1577 static int
1578 merge_file (finfo, vers)
1579     struct file_info *finfo;
1580     Vers_TS *vers;
1581 {
1582     char *backup;
1583     int status;
1584     int retcode = 0;
1585     int retval;
1586 
1587     /*
1588      * The users currently modified file is moved to a backup file name
1589      * ".#filename.version", so that it will stay around for a few days
1590      * before being automatically removed by some cron daemon.  The "version"
1591      * is the version of the file that the user was most up-to-date with
1592      * before the merge.
1593      */
1594     backup = xmalloc (strlen (finfo->file)
1595 		      + strlen (vers->vn_user)
1596 		      + sizeof (BAKPREFIX)
1597 		      + 10);
1598     (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1599 
1600     (void) unlink_file (backup);
1601     copy_file (finfo->file, backup);
1602     xchmod (finfo->file, 1);
1603 
1604     if (strcmp (vers->options, "-kb") == 0)
1605     {
1606 	/* For binary files, a merge is always a conflict.  We give the
1607 	   user the two files, and let them resolve it.  It is possible
1608 	   that we should require a "touch foo" or similar step before
1609 	   we allow a checkin.  */
1610 	status = checkout_file (finfo, vers, 0);
1611 #ifdef SERVER_SUPPORT
1612 	/* Send the new contents of the file before the message.  If we
1613 	   wanted to be totally correct, we would have the client write
1614 	   the message only after the file has safely been written.  */
1615 	if (server_active)
1616 	{
1617 	    server_copy_file (finfo->file, finfo->update_dir,
1618 			      finfo->repository, backup);
1619 	    server_updated (finfo, vers, SERVER_MERGED,
1620 			    (struct stat *) NULL, (unsigned char *) NULL);
1621 	}
1622 #endif
1623 	error (0, 0, "binary file needs merge");
1624 	error (0, 0, "revision %s from repository is now in %s",
1625 	       vers->vn_rcs, finfo->fullname);
1626 	error (0, 0, "file from working directory is now in %s", backup);
1627 	write_letter (finfo->file, 'C', finfo->update_dir);
1628 
1629 	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
1630 		       finfo->repository);
1631 	retval = 0;
1632 	goto out;
1633     }
1634 
1635     status = RCS_merge(vers->srcfile->path,
1636 		       vers->options, vers->vn_user, vers->vn_rcs);
1637     if (status != 0 && status != 1)
1638     {
1639 	error (0, status == -1 ? errno : 0,
1640 	       "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
1641 	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
1642 	       finfo->fullname, backup);
1643 	rename_file (backup, finfo->file);
1644 	retval = 1;
1645 	goto out;
1646     }
1647 
1648     if (strcmp (vers->options, "-V4") == 0)
1649 	vers->options[0] = '\0';
1650     (void) time (&last_register_time);
1651     {
1652 	char *cp = 0;
1653 
1654 	if (status)
1655 	    cp = time_stamp (finfo->file);
1656 	Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, vers->options,
1657 		  vers->tag, vers->date, cp);
1658 	if (cp)
1659 	    free (cp);
1660     }
1661 
1662     /* fix up the vers structure, in case it is used by join */
1663     if (join_rev1)
1664     {
1665 	if (vers->vn_user != NULL)
1666 	    free (vers->vn_user);
1667 	vers->vn_user = xstrdup (vers->vn_rcs);
1668     }
1669 
1670 #ifdef SERVER_SUPPORT
1671     /* Send the new contents of the file before the message.  If we
1672        wanted to be totally correct, we would have the client write
1673        the message only after the file has safely been written.  */
1674     if (server_active)
1675     {
1676         server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
1677 			  backup);
1678 	server_updated (finfo, vers, SERVER_MERGED,
1679 			(struct stat *) NULL, (unsigned char *) NULL);
1680     }
1681 #endif
1682 
1683     if (!noexec && !xcmp (backup, finfo->file))
1684     {
1685 	printf ("%s already contains the differences between %s and %s\n",
1686 		finfo->fullname, vers->vn_user, vers->vn_rcs);
1687 	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1688 		       finfo->repository);
1689 	retval = 0;
1690 	goto out;
1691     }
1692 
1693     if (status == 1)
1694     {
1695 	if (!noexec)
1696 	    error (0, 0, "conflicts found in %s", finfo->fullname);
1697 
1698 	write_letter (finfo->file, 'C', finfo->update_dir);
1699 
1700 	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, finfo->repository);
1701 
1702     }
1703     else if (retcode == -1)
1704     {
1705 	error (1, errno, "fork failed while examining update of %s",
1706 	       finfo->fullname);
1707     }
1708     else
1709     {
1710 	write_letter (finfo->file, 'M', finfo->update_dir);
1711 	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1712 		       finfo->repository);
1713     }
1714     retval = 0;
1715  out:
1716     free (backup);
1717     return retval;
1718 }
1719 
1720 /*
1721  * Do all the magic associated with a file which needs to be joined
1722  * (-j option)
1723  */
1724 static void
1725 join_file (finfo, vers)
1726     struct file_info *finfo;
1727     Vers_TS *vers;
1728 {
1729     char *backup;
1730     char *options;
1731     int status;
1732 
1733     char *rev1;
1734     char *rev2;
1735     char *jrev1;
1736     char *jrev2;
1737     char *jdate1;
1738     char *jdate2;
1739 
1740     jrev1 = join_rev1;
1741     jrev2 = join_rev2;
1742     jdate1 = date_rev1;
1743     jdate2 = date_rev2;
1744 
1745     if (wrap_merge_is_copy (finfo->file))
1746     {
1747 	error (0, 0,
1748 	       "Cannot merge %s because it is a merge-by-copy file.",
1749 	       finfo->fullname);
1750 	return;
1751     }
1752 
1753     /* Determine if we need to do anything at all.  */
1754     if (vers->srcfile == NULL ||
1755 	vers->srcfile->path == NULL)
1756     {
1757 	return;
1758     }
1759 
1760     /* If only one join revision is specified, it becomes the second
1761        revision.  */
1762     if (jrev2 == NULL)
1763     {
1764 	jrev2 = jrev1;
1765 	jrev1 = NULL;
1766 	jdate2 = jdate1;
1767 	jdate1 = NULL;
1768     }
1769 
1770     /* Convert the second revision, walking branches and dates.  */
1771     rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL);
1772 
1773     /* If this is a merge of two revisions, get the first revision.
1774        If only one join tag was specified, then the first revision is
1775        the greatest common ancestor of the second revision and the
1776        working file.  */
1777     if (jrev1 != NULL)
1778 	rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL);
1779     else
1780     {
1781 	/* Note that we use vn_rcs here, since vn_user may contain a
1782            special string such as "-nn".  */
1783 	if (vers->vn_rcs == NULL)
1784 	    rev1 = NULL;
1785 	else if (rev2 == NULL)
1786 	{
1787 	    /* This means that the file never existed on the branch.
1788                It does not mean that the file was removed on the
1789                branch: that case is represented by a dead rev2.  If
1790                the file never existed on the branch, then we have
1791                nothing to merge, so we just return.  */
1792 	    return;
1793 	}
1794 	else
1795 	    rev1 = gca (vers->vn_rcs, rev2);
1796     }
1797 
1798     /* Handle a nonexistent or dead merge target.  */
1799     if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
1800     {
1801 	char *mrev;
1802 
1803 	if (rev2 != NULL)
1804 	    free (rev2);
1805 
1806 	/* If the first revision doesn't exist either, then there is
1807            no change between the two revisions, so we don't do
1808            anything.  */
1809 	if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
1810 	{
1811 	    if (rev1 != NULL)
1812 		free (rev1);
1813 	    return;
1814 	}
1815 
1816 	/* If we are merging two revisions, then the file was removed
1817 	   between the first revision and the second one.  In this
1818 	   case we want to mark the file for removal.
1819 
1820 	   If we are merging one revision, then the file has been
1821 	   removed between the greatest common ancestor and the merge
1822 	   revision.  From the perspective of the branch on to which
1823 	   we ar emerging, which may be the trunk, either 1) the file
1824 	   does not currently exist on the target, or 2) the file has
1825 	   not been modified on the target branch since the greatest
1826 	   common ancestor, or 3) the file has been modified on the
1827 	   target branch since the greatest common ancestor.  In case
1828 	   1 there is nothing to do.  In case 2 we mark the file for
1829 	   removal.  In case 3 we have a conflict.
1830 
1831 	   Note that the handling is slightly different depending upon
1832 	   whether one or two join targets were specified.  If two
1833 	   join targets were specified, we don't check whether the
1834 	   file was modified since a given point.  My reasoning is
1835 	   that if you ask for an explicit merge between two tags,
1836 	   then you want to merge in whatever was changed between
1837 	   those two tags.  If a file was removed between the two
1838 	   tags, then you want it to be removed.  However, if you ask
1839 	   for a merge of a branch, then you want to merge in all
1840 	   changes which were made on the branch.  If a file was
1841 	   removed on the branch, that is a change to the file.  If
1842 	   the file was also changed on the main line, then that is
1843 	   also a change.  These two changes--the file removal and the
1844 	   modification--must be merged.  This is a conflict.  */
1845 
1846 	/* If the user file is dead, or does not exist, or has been
1847            marked for removal, then there is nothing to do.  */
1848 	if (vers->vn_user == NULL
1849 	    || vers->vn_user[0] == '-'
1850 	    || RCS_isdead (vers->srcfile, vers->vn_user))
1851 	{
1852 	    if (rev1 != NULL)
1853 		free (rev1);
1854 	    return;
1855 	}
1856 
1857 	/* If the user file has been marked for addition, or has been
1858 	   locally modified, then we have a conflict which we can not
1859 	   resolve.  No_Difference will already have been called in
1860 	   this case, so comparing the timestamps is sufficient to
1861 	   determine whether the file is locally modified.  */
1862 	if (strcmp (vers->vn_user, "0") == 0
1863 	    || (vers->ts_user != NULL
1864 		&& strcmp (vers->ts_user, vers->ts_rcs) != 0))
1865 	{
1866 	    if (jdate2 != NULL)
1867 		error (0, 0,
1868 		       "file %s is locally modified, but has been removed in revision %s as of %s",
1869 		       finfo->fullname, jrev2, jdate2);
1870 	    else
1871 		error (0, 0,
1872 		       "file %s is locally modified, but has been removed in revision %s",
1873 		       finfo->fullname, jrev2);
1874 
1875 	    /* FIXME: Should we arrange to return a non-zero exit
1876                status?  */
1877 
1878 	    if (rev1 != NULL)
1879 		free (rev1);
1880 
1881 	    return;
1882 	}
1883 
1884 	/* If only one join tag was specified, and the user file has
1885            been changed since the greatest common ancestor (rev1),
1886            then there is a conflict we can not resolve.  See above for
1887            the rationale.  */
1888 	if (join_rev2 == NULL
1889 	    && strcmp (rev1, vers->vn_user) != 0)
1890 	{
1891 	    if (jdate2 != NULL)
1892 		error (0, 0,
1893 		       "file %s has been modified, but has been removed in revision %s as of %s",
1894 		       finfo->fullname, jrev2, jdate2);
1895 	    else
1896 		error (0, 0,
1897 		       "file %s has been modified, but has been removed in revision %s",
1898 		       finfo->fullname, jrev2);
1899 
1900 	    /* FIXME: Should we arrange to return a non-zero exit
1901                status?  */
1902 
1903 	    if (rev1 != NULL)
1904 		free (rev1);
1905 
1906 	    return;
1907 	}
1908 
1909 	if (rev1 != NULL)
1910 	    free (rev1);
1911 
1912 	/* The user file exists and has not been modified.  Mark it
1913            for removal.  FIXME: If we are doing a checkout, this has
1914            the effect of first checking out the file, and then
1915            removing it.  It would be better to just register the
1916            removal.  */
1917 #ifdef SERVER_SUPPORT
1918 	if (server_active)
1919 	{
1920 	    server_scratch (finfo->file);
1921 	    server_updated (finfo, vers, SERVER_UPDATED, (struct stat *) NULL,
1922 			    (unsigned char *) NULL);
1923 	}
1924 #endif
1925 	mrev = xmalloc (strlen (vers->vn_user) + 2);
1926 	sprintf (mrev, "-%s", vers->vn_user);
1927 	Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
1928 		  vers->options, vers->tag, vers->date, vers->ts_conflict);
1929 	free (mrev);
1930 	/* We need to check existence_error here because if we are
1931            running as the server, and the file is up to date in the
1932            working directory, the client will not have sent us a copy.  */
1933 	if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1934 	    error (0, errno, "cannot remove file %s", finfo->fullname);
1935 #ifdef SERVER_SUPPORT
1936 	if (server_active)
1937 	    server_checked_in (finfo->file, finfo->update_dir,
1938 			       finfo->repository);
1939 #endif
1940 	if (! really_quiet)
1941 	    error (0, 0, "scheduling %s for removal", finfo->fullname);
1942 
1943 	return;
1944     }
1945 
1946     /* If the target of the merge is the same as the working file
1947        revision, then there is nothing to do.  */
1948     if (vers->vn_user != NULL && strcmp (rev2, vers->vn_user) == 0)
1949     {
1950 	if (rev1 != NULL)
1951 	    free (rev1);
1952 	free (rev2);
1953 	return;
1954     }
1955 
1956     /* If rev1 is dead or does not exist, then the file was added
1957        between rev1 and rev2.  */
1958     if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
1959     {
1960 	if (rev1 != NULL)
1961 	    free (rev1);
1962 	free (rev2);
1963 
1964 	/* If the file does not exist in the working directory, then
1965            we can just check out the new revision and mark it for
1966            addition.  */
1967 	if (vers->vn_user == NULL)
1968 	{
1969 	    Vers_TS *xvers;
1970 
1971 	    xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
1972 
1973 	    /* FIXME: If checkout_file fails, we should arrange to
1974                return a non-zero exit status.  */
1975 	    status = checkout_file (finfo, xvers, 1);
1976 
1977 #ifdef SERVER_SUPPORT
1978 	    if (server_active && status == 0)
1979 		server_updated (finfo, xvers,
1980 				SERVER_UPDATED, (struct stat *) NULL,
1981 				(unsigned char *) NULL);
1982 #endif
1983 
1984 	    freevers_ts (&xvers);
1985 
1986 	    return;
1987 	}
1988 
1989 	/* The file currently exists in the working directory, so we
1990            have a conflict which we can not resolve.  Note that this
1991            is true even if the file is marked for addition or removal.  */
1992 
1993 	if (jdate2 != NULL)
1994 	    error (0, 0,
1995 		   "file %s exists, but has been added in revision %s as of %s",
1996 		   finfo->fullname, jrev2, jdate2);
1997 	else
1998 	    error (0, 0,
1999 		   "file %s exists, but has been added in revision %s",
2000 		   finfo->fullname, jrev2);
2001 
2002 	return;
2003     }
2004 
2005     /* If the two merge revisions are the same, then there is nothing
2006        to do.  */
2007     if (strcmp (rev1, rev2) == 0)
2008     {
2009 	free (rev1);
2010 	free (rev2);
2011 	return;
2012     }
2013 
2014     /* If there is no working file, then we can't do the merge.  */
2015     if (vers->vn_user == NULL)
2016     {
2017 	free (rev1);
2018 	free (rev2);
2019 
2020 	if (jdate2 != NULL)
2021 	    error (0, 0,
2022 		   "file %s is present in revision %s as of %s",
2023 		   finfo->fullname, jrev2, jdate2);
2024 	else
2025 	    error (0, 0,
2026 		   "file %s is present in revision %s",
2027 		   finfo->fullname, jrev2);
2028 
2029 	/* FIXME: Should we arrange to return a non-zero exit status?  */
2030 
2031 	return;
2032     }
2033 
2034 #ifdef SERVER_SUPPORT
2035     if (server_active && !isreadable (finfo->file))
2036     {
2037 	int retcode;
2038 	/* The file is up to date.  Need to check out the current contents.  */
2039 	retcode = RCS_checkout (vers->srcfile, finfo->file,
2040 				vers->vn_user, (char *) NULL,
2041 				(char *) NULL, RUN_TTY,
2042 				(RCSCHECKOUTPROC) NULL, (void *) NULL);
2043 	if (retcode != 0)
2044 	    error (1, retcode == -1 ? errno : 0,
2045 		   "failed to check out %s file", finfo->fullname);
2046     }
2047 #endif
2048 
2049     /*
2050      * The users currently modified file is moved to a backup file name
2051      * ".#filename.version", so that it will stay around for a few days
2052      * before being automatically removed by some cron daemon.  The "version"
2053      * is the version of the file that the user was most up-to-date with
2054      * before the merge.
2055      */
2056     backup = xmalloc (strlen (finfo->file)
2057 		      + strlen (vers->vn_user)
2058 		      + sizeof (BAKPREFIX)
2059 		      + 10);
2060     (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2061 
2062     (void) unlink_file (backup);
2063     copy_file (finfo->file, backup);
2064     xchmod (finfo->file, 1);
2065 
2066     options = vers->options;
2067 #ifdef HAVE_RCS5
2068 #if 0
2069     if (*options == '\0')
2070 	options = "-kk";		/* to ignore keyword expansions */
2071 #endif
2072 #endif
2073 
2074     status = RCS_merge (vers->srcfile->path, options, rev1, rev2);
2075     if (status != 0 && status != 1)
2076     {
2077 	error (0, status == -1 ? errno : 0,
2078 	       "could not merge revision %s of %s", rev2, finfo->fullname);
2079 	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2080 	       finfo->fullname, backup);
2081 	rename_file (backup, finfo->file);
2082     }
2083     free (rev1);
2084     free (rev2);
2085 
2086 #ifdef SERVER_SUPPORT
2087     /*
2088      * If we're in server mode, then we need to re-register the file
2089      * even if there were no conflicts (status == 0).
2090      * This tells server_updated() to send the modified file back to
2091      * the client.
2092      */
2093     if (status == 1 || (status == 0 && server_active))
2094 #else
2095     if (status == 1)
2096 #endif
2097     {
2098 	char *cp = 0;
2099 
2100 	if (status)
2101 	    cp = time_stamp (finfo->file);
2102 	Register (finfo->entries, finfo->file,
2103 		  vers->vn_rcs, vers->ts_rcs, vers->options,
2104 		  vers->tag, vers->date, cp);
2105 	if (cp)
2106 	    free(cp);
2107     }
2108 
2109 #ifdef SERVER_SUPPORT
2110     if (server_active)
2111     {
2112 	server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2113 			  backup);
2114 	server_updated (finfo, vers, SERVER_MERGED,
2115 			(struct stat *) NULL, (unsigned char *) NULL);
2116     }
2117 #endif
2118     free (backup);
2119 }
2120 
2121 int
2122 joining ()
2123 {
2124     return (join_rev1 != NULL);
2125 }
2126