xref: /openbsd/gnu/usr.bin/cvs/src/update.c (revision f2dfb0a4)
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 source distribution.
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 #include "buffer.h"
46 #include "hardlink.h"
47 
48 static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts,
49 				 int adding, int merging, int update_server));
50 #ifdef SERVER_SUPPORT
51 static void checkout_to_buffer PROTO ((void *, const char *, size_t));
52 #endif
53 #ifdef SERVER_SUPPORT
54 static int patch_file PROTO ((struct file_info *finfo,
55 			      Vers_TS *vers_ts,
56 			      int *docheckout, struct stat *file_info,
57 			      unsigned char *checksum));
58 static void patch_file_write PROTO ((void *, const char *, size_t));
59 #endif
60 static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
61 static int scratch_file PROTO((struct file_info *finfo));
62 static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir,
63 					char *repository, char *update_dir,
64 					List *entries));
65 static int update_dirleave_proc PROTO ((void *callerdat, char *dir,
66 					int err, char *update_dir,
67 					List *entries));
68 static int update_fileproc PROTO ((void *callerdat, struct file_info *));
69 static int update_filesdone_proc PROTO ((void *callerdat, int err,
70 					 char *repository, char *update_dir,
71 					 List *entries));
72 #ifdef PRESERVE_PERMISSIONS_SUPPORT
73 static int get_linkinfo_proc PROTO ((void *callerdat, struct file_info *));
74 #endif
75 static void write_letter PROTO ((struct file_info *finfo, int letter));
76 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts));
77 
78 static char *options = NULL;
79 static char *tag = NULL;
80 static char *date = NULL;
81 /* This is a bit of a kludge.  We call WriteTag at the beginning
82    before we know whether nonbranch is set or not.  And then at the
83    end, once we have the right value for nonbranch, we call WriteTag
84    again.  I don't know whether the first call is necessary or not.
85    rewrite_tag is nonzero if we are going to have to make that second
86    call.  */
87 static int rewrite_tag;
88 static int nonbranch;
89 
90 /* If we set the tag or date for a subdirectory, we use this to undo
91    the setting.  See update_dirent_proc.  */
92 static char *tag_update_dir;
93 
94 static char *join_rev1, *date_rev1;
95 static char *join_rev2, *date_rev2;
96 static int aflag = 0;
97 static int force_tag_match = 1;
98 static int update_build_dirs = 0;
99 static int update_prune_dirs = 0;
100 static int pipeout = 0;
101 #ifdef SERVER_SUPPORT
102 static int patches = 0;
103 static int rcs_diff_patches = 0;
104 #endif
105 static List *ignlist = (List *) NULL;
106 static time_t last_register_time;
107 static const char *const update_usage[] =
108 {
109     "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n",
110     "    [-I ign] [-W spec] [files...]\n",
111     "\t-A\tReset any sticky tags/date/kopts.\n",
112     "\t-P\tPrune empty directories.\n",
113     "\t-d\tBuild directories, like checkout does.\n",
114     "\t-f\tForce a head revision match if tag/date not found.\n",
115     "\t-l\tLocal directory only, no recursion.\n",
116     "\t-R\tProcess directories recursively.\n",
117     "\t-p\tSend updates to standard output (avoids stickiness).\n",
118     "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
119     "\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
120     "\t-D date\tSet date to update from (is sticky).\n",
121     "\t-j rev\tMerge in changes made between current revision and rev.\n",
122     "\t-I ign\tMore files to ignore (! to reset).\n",
123     "\t-W spec\tWrappers specification line.\n",
124     "(Specify the --help global option for a list of other help options)\n",
125     NULL
126 };
127 
128 /*
129  * update is the argv,argc based front end for arg parsing
130  */
131 int
132 update (argc, argv)
133     int argc;
134     char **argv;
135 {
136     int c, err;
137     int local = 0;			/* recursive by default */
138     int which;				/* where to look for files and dirs */
139 
140     if (argc == -1)
141 	usage (update_usage);
142 
143     ign_setup ();
144     wrap_setup ();
145 
146     /* parse the args */
147     optind = 0;
148     while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1)
149     {
150 	switch (c)
151 	{
152 	    case 'A':
153 		aflag = 1;
154 		break;
155 	    case 'I':
156 		ign_add (optarg, 0);
157 		break;
158 	    case 'W':
159 		wrap_add (optarg, 0);
160 		break;
161 	    case 'k':
162 		if (options)
163 		    free (options);
164 		options = RCS_check_kflag (optarg);
165 		break;
166 	    case 'l':
167 		local = 1;
168 		break;
169 	    case 'R':
170 		local = 0;
171 		break;
172 	    case 'Q':
173 	    case 'q':
174 #ifdef SERVER_SUPPORT
175 		/* The CVS 1.5 client sends these options (in addition to
176 		   Global_option requests), so we must ignore them.  */
177 		if (!server_active)
178 #endif
179 		    error (1, 0,
180 			   "-q or -Q must be specified before \"%s\"",
181 			   command_name);
182 		break;
183 	    case 'd':
184 		update_build_dirs = 1;
185 		break;
186 	    case 'f':
187 		force_tag_match = 0;
188 		break;
189 	    case 'r':
190 		tag = optarg;
191 		break;
192 	    case 'D':
193 		date = Make_Date (optarg);
194 		break;
195 	    case 'P':
196 		update_prune_dirs = 1;
197 		break;
198 	    case 'p':
199 		pipeout = 1;
200 		noexec = 1;		/* so no locks will be created */
201 		break;
202 	    case 'j':
203 		if (join_rev2)
204 		    error (1, 0, "only two -j options can be specified");
205 		if (join_rev1)
206 		    join_rev2 = optarg;
207 		else
208 		    join_rev1 = optarg;
209 		break;
210 	    case 'u':
211 #ifdef SERVER_SUPPORT
212 		if (server_active)
213 		{
214 		    patches = 1;
215 		    rcs_diff_patches = server_use_rcs_diff ();
216 		}
217 		else
218 #endif
219 		    usage (update_usage);
220 		break;
221 	    case '?':
222 	    default:
223 		usage (update_usage);
224 		break;
225 	}
226     }
227     argc -= optind;
228     argv += optind;
229 
230 #ifdef CLIENT_SUPPORT
231     if (client_active)
232     {
233 	int pass;
234 
235 	/* The first pass does the regular update.  If we receive at least
236 	   one patch which failed, we do a second pass and just fetch
237 	   those files whose patches failed.  */
238 	pass = 1;
239 	do
240 	{
241 	    int status;
242 
243 	    start_server ();
244 
245 	    if (local)
246 		send_arg("-l");
247 	    if (update_build_dirs)
248 		send_arg("-d");
249 	    if (pipeout)
250 		send_arg("-p");
251 	    if (!force_tag_match)
252 		send_arg("-f");
253 	    if (aflag)
254 		send_arg("-A");
255 	    if (update_prune_dirs)
256 		send_arg("-P");
257 	    client_prune_dirs = update_prune_dirs;
258 	    option_with_arg ("-r", tag);
259 	    if (options && options[0] != '\0')
260 		send_arg (options);
261 	    if (date)
262 		client_senddate (date);
263 	    if (join_rev1)
264 		option_with_arg ("-j", join_rev1);
265 	    if (join_rev2)
266 		option_with_arg ("-j", join_rev2);
267 	    wrap_send ();
268 
269 	    /* If the server supports the command "update-patches", that means
270 	       that it knows how to handle the -u argument to update, which
271 	       means to send patches instead of complete files.
272 
273 	       We don't send -u if failed_patches != NULL, so that the
274 	       server doesn't try to send patches which will just fail
275 	       again.  At least currently, the client also clobbers the
276 	       file and tells the server it is lost, which also will get
277 	       a full file instead of a patch, but it seems clean to omit
278 	       -u.  */
279 	    if (failed_patches == NULL)
280 	    {
281 		if (supported_request ("update-patches"))
282 		    send_arg ("-u");
283 	    }
284 
285 	    if (failed_patches == NULL)
286 	    {
287 		send_file_names (argc, argv, SEND_EXPAND_WILD);
288 		/* If noexec, probably could be setting SEND_NO_CONTENTS.
289 		   Same caveats as for "cvs status" apply.  */
290 		send_files (argc, argv, local, aflag,
291 			    update_build_dirs ? SEND_BUILD_DIRS : 0);
292 	    }
293 	    else
294 	    {
295 		int i;
296 
297 		(void) printf ("%s client: refetching unpatchable files\n",
298 			       program_name);
299 
300 		if (toplevel_wd != NULL
301 		    && CVS_CHDIR (toplevel_wd) < 0)
302 		{
303 		    error (1, errno, "could not chdir to %s", toplevel_wd);
304 		}
305 
306 		for (i = 0; i < failed_patches_count; i++)
307 		    (void) unlink_file (failed_patches[i]);
308 		send_file_names (failed_patches_count, failed_patches, 0);
309 		send_files (failed_patches_count, failed_patches, local,
310 			    aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
311 	    }
312 
313 	    failed_patches = NULL;
314 	    failed_patches_count = 0;
315 
316 	    send_to_server ("update\012", 0);
317 
318 	    status = get_responses_and_close ();
319 
320 	    /* If there are any conflicts, the server will return a
321                non-zero exit status.  If any patches failed, we still
322                want to run the update again.  We use a pass count to
323                avoid an endless loop.  */
324 
325 	    /* Notes: (1) assuming that status != 0 implies a
326 	       potential conflict is the best we can cleanly do given
327 	       the current protocol.  I suppose that trying to
328 	       re-fetch in cases where there was a more serious error
329 	       is probably more or less harmless, but it isn't really
330 	       ideal.  (2) it would be nice to have a testsuite case for the
331 	       conflict-and-patch-failed case.  */
332 
333 	    if (status != 0
334 		&& (failed_patches == NULL || pass > 1))
335 	    {
336 		return status;
337 	    }
338 
339 	    ++pass;
340 	} while (failed_patches != NULL);
341 
342 	return 0;
343     }
344 #endif
345 
346     if (tag != NULL)
347 	tag_check_valid (tag, argc, argv, local, aflag, "");
348     if (join_rev1 != NULL)
349         tag_check_valid_join (join_rev1, argc, argv, local, aflag, "");
350     if (join_rev2 != NULL)
351         tag_check_valid_join (join_rev2, argc, argv, local, aflag, "");
352 
353     /*
354      * If we are updating the entire directory (for real) and building dirs
355      * as we go, we make sure there is no static entries file and write the
356      * tag file as appropriate
357      */
358     if (argc <= 0 && !pipeout)
359     {
360 	if (update_build_dirs)
361 	{
362 	    if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
363 		error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
364 #ifdef SERVER_SUPPORT
365 	    if (server_active)
366 		server_clear_entstat (".", Name_Repository (NULL, NULL));
367 #endif
368 	}
369 
370 	/* keep the CVS/Tag file current with the specified arguments */
371 	if (aflag || tag || date)
372 	{
373 	    WriteTag ((char *) NULL, tag, date, 0,
374 		      ".", Name_Repository (NULL, NULL));
375 	    rewrite_tag = 1;
376 	    nonbranch = 0;
377 	}
378     }
379 
380     /* look for files/dirs locally and in the repository */
381     which = W_LOCAL | W_REPOS;
382 
383     /* look in the attic too if a tag or date is specified */
384     if (tag != NULL || date != NULL || joining())
385 	which |= W_ATTIC;
386 
387     /* call the command line interface */
388     err = do_update (argc, argv, options, tag, date, force_tag_match,
389 		     local, update_build_dirs, aflag, update_prune_dirs,
390 		     pipeout, which, join_rev1, join_rev2, (char *) NULL);
391 
392     /* free the space Make_Date allocated if necessary */
393     if (date != NULL)
394 	free (date);
395 
396     return (err);
397 }
398 
399 /*
400  * Command line interface to update (used by checkout)
401  */
402 int
403 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
404 	   xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir)
405     int argc;
406     char **argv;
407     char *xoptions;
408     char *xtag;
409     char *xdate;
410     int xforce;
411     int local;
412     int xbuild;
413     int xaflag;
414     int xprune;
415     int xpipeout;
416     int which;
417     char *xjoin_rev1;
418     char *xjoin_rev2;
419     char *preload_update_dir;
420 {
421     int err = 0;
422     char *cp;
423 
424     /* fill in the statics */
425     options = xoptions;
426     tag = xtag;
427     date = xdate;
428     force_tag_match = xforce;
429     update_build_dirs = xbuild;
430     aflag = xaflag;
431     update_prune_dirs = xprune;
432     pipeout = xpipeout;
433 
434     /* setup the join support */
435     join_rev1 = xjoin_rev1;
436     join_rev2 = xjoin_rev2;
437     if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL)
438     {
439 	*cp++ = '\0';
440 	date_rev1 = Make_Date (cp);
441     }
442     else
443 	date_rev1 = (char *) NULL;
444     if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL)
445     {
446 	*cp++ = '\0';
447 	date_rev2 = Make_Date (cp);
448     }
449     else
450 	date_rev2 = (char *) NULL;
451 
452 #ifdef PRESERVE_PERMISSIONS_SUPPORT
453     if (preserve_perms)
454     {
455 	/* We need to do an extra recursion, bleah.  It's to make sure
456 	   that we know as much as possible about file linkage. */
457 	hardlist = getlist();
458 	working_dir = xgetwd();		/* save top-level working dir */
459 
460 	/* FIXME-twp: the arguments to start_recursion make me dizzy.  This
461 	   function call was copied from the update_fileproc call that
462 	   follows it; someone should make sure that I did it right. */
463 	err = start_recursion (get_linkinfo_proc, (FILESDONEPROC) NULL,
464 			       (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
465 			       argc, argv, local, which, aflag, 1,
466 			       preload_update_dir, 1);
467 	if (err)
468 	    return (err);
469 
470 	/* FIXME-twp: at this point we should walk the hardlist
471 	   and update the `links' field of each hardlink_info struct
472 	   to list the files that are linked on dist.  That would make
473 	   it easier & more efficient to compare the disk linkage with
474 	   the repository linkage (a simple strcmp). */
475     }
476 #endif
477 
478     /* call the recursion processor */
479     err = start_recursion (update_fileproc, update_filesdone_proc,
480 			   update_dirent_proc, update_dirleave_proc, NULL,
481 			   argc, argv, local, which, aflag, 1,
482 			   preload_update_dir, 1);
483 
484     /* see if we need to sleep before returning */
485     if (last_register_time)
486     {
487 	time_t now;
488 
489 	(void) time (&now);
490 	if (now == last_register_time)
491 	    sleep (1);			/* to avoid time-stamp races */
492     }
493 
494     return (err);
495 }
496 
497 #ifdef PRESERVE_PERMISSIONS_SUPPORT
498 /*
499  * The get_linkinfo_proc callback adds each file to the hardlist
500  * (see hardlink.c).
501  */
502 
503 static int
504 get_linkinfo_proc (callerdat, finfo)
505     void *callerdat;
506     struct file_info *finfo;
507 {
508     char *fullpath;
509     Node *linkp;
510     struct hardlink_info *hlinfo;
511 
512     /* Get the full pathname of the current file. */
513     fullpath = xmalloc (strlen(working_dir) +
514 			strlen(finfo->fullname) + 2);
515     sprintf (fullpath, "%s/%s", working_dir, finfo->fullname);
516 
517     /* To permit recursing into subdirectories, files
518        are keyed on the full pathname and not on the basename. */
519     linkp = lookup_file_by_inode (fullpath);
520     if (linkp == NULL)
521     {
522 	/* The file isn't on disk; we are probably restoring
523 	   a file that was removed. */
524 	return 0;
525     }
526 
527     /* Create a new, empty hardlink_info node. */
528     hlinfo = (struct hardlink_info *)
529 	xmalloc (sizeof (struct hardlink_info));
530 
531     hlinfo->status = (Ctype) 0;	/* is this dumb? */
532     hlinfo->checked_out = 0;
533     hlinfo->links = NULL;
534 
535     linkp->data = (char *) hlinfo;
536 
537     return 0;
538 }
539 #endif
540 
541 /*
542  * This is the callback proc for update.  It is called for each file in each
543  * directory by the recursion code.  The current directory is the local
544  * instantiation.  file is the file name we are to operate on. update_dir is
545  * set to the path relative to where we started (for pretty printing).
546  * repository is the repository. entries and srcfiles are the pre-parsed
547  * entries and source control files.
548  *
549  * This routine decides what needs to be done for each file and does the
550  * appropriate magic for checkout
551  */
552 static int
553 update_fileproc (callerdat, finfo)
554     void *callerdat;
555     struct file_info *finfo;
556 {
557     int retval;
558     Ctype status;
559     Vers_TS *vers;
560     int resurrecting;
561 
562     resurrecting = 0;
563 
564     status = Classify_File (finfo, tag, date, options, force_tag_match,
565 			    aflag, &vers, pipeout);
566 
567     /* Keep track of whether TAG is a branch tag.
568        Note that if it is a branch tag in some files and a nonbranch tag
569        in others, treat it as a nonbranch tag.  It is possible that case
570        should elicit a warning or an error.  */
571     if (rewrite_tag
572 	&& tag != NULL
573 	&& finfo->rcs != NULL)
574     {
575 	char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
576 	if (rev != NULL
577 	    && !RCS_nodeisbranch (finfo->rcs, tag))
578 	    nonbranch = 1;
579 	if (rev != NULL)
580 	    free (rev);
581     }
582 
583     if (pipeout)
584     {
585 	/*
586 	 * We just return success without doing anything if any of the really
587 	 * funky cases occur
588 	 *
589 	 * If there is still a valid RCS file, do a regular checkout type
590 	 * operation
591 	 */
592 	switch (status)
593 	{
594 	    case T_UNKNOWN:		/* unknown file was explicitly asked
595 					 * about */
596 	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
597 	    case T_ADDED:		/* added but not committed */
598 		retval = 0;
599 		break;
600 	    case T_CONFLICT:		/* old punt-type errors */
601 		retval = 1;
602 		break;
603 	    case T_UPTODATE:		/* file was already up-to-date */
604 	    case T_NEEDS_MERGE:		/* needs merging */
605 	    case T_MODIFIED:		/* locally modified */
606 	    case T_REMOVED:		/* removed but not committed */
607 	    case T_CHECKOUT:		/* needs checkout */
608 #ifdef SERVER_SUPPORT
609 	    case T_PATCH:		/* needs patch */
610 #endif
611 		retval = checkout_file (finfo, vers, 0, 0, 0);
612 		break;
613 
614 	    default:			/* can't ever happen :-) */
615 		error (0, 0,
616 		       "unknown file status %d for file %s", status, finfo->file);
617 		retval = 0;
618 		break;
619 	}
620     }
621     else
622     {
623 	switch (status)
624 	{
625 	    case T_UNKNOWN:		/* unknown file was explicitly asked
626 					 * about */
627 	    case T_UPTODATE:		/* file was already up-to-date */
628 		retval = 0;
629 		break;
630 	    case T_CONFLICT:		/* old punt-type errors */
631 		retval = 1;
632 		write_letter (finfo, 'C');
633 		break;
634 	    case T_NEEDS_MERGE:		/* needs merging */
635 		if (noexec)
636 		{
637 		    retval = 1;
638 		    write_letter (finfo, 'C');
639 		}
640 		else
641 		{
642 		    retval = merge_file (finfo, vers);
643 		}
644 		break;
645 	    case T_MODIFIED:		/* locally modified */
646 		retval = 0;
647 		if (vers->ts_conflict)
648 		{
649 		    char *filestamp;
650 		    int retcode;
651 
652 		    /*
653 		     * If the timestamp has changed and no conflict indicators
654 		     * are found, it isn't a 'C' any more.
655 		     */
656 #ifdef SERVER_SUPPORT
657 		    if (server_active)
658 			retcode = vers->ts_conflict[0] != '=';
659 		    else {
660 			filestamp = time_stamp (finfo->file);
661 			retcode = strcmp (vers->ts_conflict, filestamp);
662 			free (filestamp);
663 		    }
664 #else
665 		    filestamp = time_stamp (finfo->file);
666 		    retcode = strcmp (vers->ts_conflict, filestamp);
667 		    free (filestamp);
668 #endif
669 
670 		    if (retcode)
671 		    {
672 			/* The timestamps differ.  But if there are conflict
673 			   markers print 'C' anyway.  */
674 			retcode = !file_has_markers (finfo);
675 		    }
676 
677 		    if (!retcode)
678 		    {
679 			write_letter (finfo, 'C');
680 			retval = 1;
681 		    }
682 		    else
683 		    {
684 			/* Reregister to clear conflict flag. */
685 			Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs,
686 				  vers->options, vers->tag,
687 				  vers->date, (char *)0);
688 		    }
689 		}
690 		if (!retval)
691 		{
692 		    write_letter (finfo, 'M');
693 		    retval = 0;
694 		}
695 		break;
696 #ifdef SERVER_SUPPORT
697 	    case T_PATCH:		/* needs patch */
698 		if (patches)
699 		{
700 		    int docheckout;
701 		    struct stat file_info;
702 		    unsigned char checksum[16];
703 
704 		    retval = patch_file (finfo,
705 					 vers, &docheckout,
706 					 &file_info, checksum);
707 		    if (! docheckout)
708 		    {
709 		        if (server_active && retval == 0)
710 			    server_updated (finfo, vers,
711 					    (rcs_diff_patches
712 					     ? SERVER_RCS_DIFF
713 					     : SERVER_PATCHED),
714 					    file_info.st_mode, checksum,
715 					    (struct buffer *) NULL);
716 			break;
717 		    }
718 		}
719 		/* If we're not running as a server, just check the
720 		   file out.  It's simpler and faster than producing
721 		   and applying patches.  */
722 		/* Fall through.  */
723 #endif
724 	    case T_CHECKOUT:		/* needs checkout */
725 		retval = checkout_file (finfo, vers, 0, 0, 1);
726 		break;
727 	    case T_ADDED:		/* added but not committed */
728 		write_letter (finfo, 'A');
729 		retval = 0;
730 		break;
731 	    case T_REMOVED:		/* removed but not committed */
732 		write_letter (finfo, 'R');
733 		retval = 0;
734 		break;
735 	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
736 		retval = scratch_file (finfo);
737 #ifdef SERVER_SUPPORT
738 		if (server_active && retval == 0)
739 		{
740 		    if (vers->ts_user == NULL)
741 			server_scratch_entry_only ();
742 		    server_updated (finfo, vers,
743 				    SERVER_UPDATED, (mode_t) -1,
744 				    (unsigned char *) NULL,
745 				    (struct buffer *) NULL);
746 		}
747 #endif
748 		break;
749 	    default:			/* can't ever happen :-) */
750 		error (0, 0,
751 		       "unknown file status %d for file %s", status, finfo->file);
752 		retval = 0;
753 		break;
754 	}
755     }
756 
757     /* only try to join if things have gone well thus far */
758     if (retval == 0 && join_rev1)
759 	join_file (finfo, vers);
760 
761     /* if this directory has an ignore list, add this file to it */
762     if (ignlist)
763     {
764 	Node *p;
765 
766 	p = getnode ();
767 	p->type = FILES;
768 	p->key = xstrdup (finfo->file);
769 	if (addnode (ignlist, p) != 0)
770 	    freenode (p);
771     }
772 
773     freevers_ts (&vers);
774     return (retval);
775 }
776 
777 static void update_ignproc PROTO ((char *, char *));
778 
779 static void
780 update_ignproc (file, dir)
781     char *file;
782     char *dir;
783 {
784     struct file_info finfo;
785 
786     memset (&finfo, 0, sizeof (finfo));
787     finfo.file = file;
788     finfo.update_dir = dir;
789     if (dir[0] == '\0')
790 	finfo.fullname = xstrdup (file);
791     else
792     {
793 	finfo.fullname = xmalloc (strlen (file) + strlen (dir) + 10);
794 	strcpy (finfo.fullname, dir);
795 	strcat (finfo.fullname, "/");
796 	strcat (finfo.fullname, file);
797     }
798 
799     write_letter (&finfo, '?');
800     free (finfo.fullname);
801 }
802 
803 /* ARGSUSED */
804 static int
805 update_filesdone_proc (callerdat, err, repository, update_dir, entries)
806     void *callerdat;
807     int err;
808     char *repository;
809     char *update_dir;
810     List *entries;
811 {
812     if (rewrite_tag)
813     {
814 	WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
815 	rewrite_tag = 0;
816     }
817 
818     /* if this directory has an ignore list, process it then free it */
819     if (ignlist)
820     {
821 	ignore_files (ignlist, entries, update_dir, update_ignproc);
822 	dellist (&ignlist);
823     }
824 
825     /* Clean up CVS admin dirs if we are export */
826     if (strcmp (command_name, "export") == 0)
827     {
828 	/* I'm not sure the existence_error is actually possible (except
829 	   in cases where we really should print a message), but since
830 	   this code used to ignore all errors, I'll play it safe.  */
831 	if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
832 	    error (0, errno, "cannot remove %s directory", CVSADM);
833     }
834 #ifdef SERVER_SUPPORT
835     else if (!server_active && !pipeout)
836 #else
837     else if (!pipeout)
838 #endif /* SERVER_SUPPORT */
839     {
840         /* If there is no CVS/Root file, add one */
841         if (!isfile (CVSADM_ROOT))
842 	    Create_Root ((char *) NULL, CVSroot_original);
843     }
844 
845     return (err);
846 }
847 
848 /*
849  * update_dirent_proc () is called back by the recursion processor before a
850  * sub-directory is processed for update.  In this case, update_dirent proc
851  * will probably create the directory unless -d isn't specified and this is a
852  * new directory.  A return code of 0 indicates the directory should be
853  * processed by the recursion code.  A return of non-zero indicates the
854  * recursion code should skip this directory.
855  */
856 static Dtype
857 update_dirent_proc (callerdat, dir, repository, update_dir, entries)
858     void *callerdat;
859     char *dir;
860     char *repository;
861     char *update_dir;
862     List *entries;
863 {
864     if (ignore_directory (update_dir))
865     {
866 	/* print the warm fuzzy message */
867 	if (!quiet)
868 	  error (0, 0, "Ignoring %s", update_dir);
869         return R_SKIP_ALL;
870     }
871 
872     if (!isdir (dir))
873     {
874 	/* if we aren't building dirs, blow it off */
875 	if (!update_build_dirs)
876 	    return (R_SKIP_ALL);
877 
878 	if (noexec)
879 	{
880 	    /* ignore the missing dir if -n is specified */
881 	    error (0, 0, "New directory `%s' -- ignored", update_dir);
882 	    return (R_SKIP_ALL);
883 	}
884 	else
885 	{
886 	    /* otherwise, create the dir and appropriate adm files */
887 
888 	    /* If no tag or date were specified on the command line,
889                and we're not using -A, we want the subdirectory to use
890                the tag and date, if any, of the current directory.
891                That way, update -d will work correctly when working on
892                a branch.
893 
894 	       We use TAG_UPDATE_DIR to undo the tag setting in
895 	       update_dirleave_proc.  If we did not do this, we would
896 	       not correctly handle a working directory with multiple
897 	       tags (and maybe we should prohibit such working
898 	       directories, but they work now and we shouldn't make
899 	       them stop working without more thought).  */
900 	    if ((tag == NULL && date == NULL) && ! aflag)
901 	    {
902 		ParseTag (&tag, &date, &nonbranch);
903 		if (tag != NULL || date != NULL)
904 		    tag_update_dir = xstrdup (update_dir);
905 	    }
906 
907 	    make_directory (dir);
908 	    Create_Admin (dir, update_dir, repository, tag, date,
909 			  /* This is a guess.  We will rewrite it later
910 			     via WriteTag.  */
911 			  0,
912 			  0);
913 	    rewrite_tag = 1;
914 	    nonbranch = 0;
915 	    Subdir_Register (entries, (char *) NULL, dir);
916 	}
917     }
918     /* Do we need to check noexec here? */
919     else if (!pipeout)
920     {
921 	char *cvsadmdir;
922 
923 	/* The directory exists.  Check to see if it has a CVS
924 	   subdirectory.  */
925 
926 	cvsadmdir = xmalloc (strlen (dir) + 80);
927 	strcpy (cvsadmdir, dir);
928 	strcat (cvsadmdir, "/");
929 	strcat (cvsadmdir, CVSADM);
930 
931 	if (!isdir (cvsadmdir))
932 	{
933 	    /* We cannot successfully recurse into a directory without a CVS
934 	       subdirectory.  Generally we will have already printed
935 	       "? foo".  */
936 	    free (cvsadmdir);
937 	    return R_SKIP_ALL;
938 	}
939 	free (cvsadmdir);
940     }
941 
942     /*
943      * If we are building dirs and not going to stdout, we make sure there is
944      * no static entries file and write the tag file as appropriate
945      */
946     if (!pipeout)
947     {
948 	if (update_build_dirs)
949 	{
950 	    char *tmp;
951 
952 	    tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10);
953 	    (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
954 	    if (unlink_file (tmp) < 0 && ! existence_error (errno))
955 		error (1, errno, "cannot remove file %s", tmp);
956 #ifdef SERVER_SUPPORT
957 	    if (server_active)
958 		server_clear_entstat (update_dir, repository);
959 #endif
960 	    free (tmp);
961 	}
962 
963 	/* keep the CVS/Tag file current with the specified arguments */
964 	if (aflag || tag || date)
965 	{
966 	    WriteTag (dir, tag, date, 0, update_dir, repository);
967 	    rewrite_tag = 1;
968 	    nonbranch = 0;
969 	}
970 
971 	/* initialize the ignore list for this directory */
972 	ignlist = getlist ();
973     }
974 
975     /* print the warm fuzzy message */
976     if (!quiet)
977 	error (0, 0, "Updating %s", update_dir);
978 
979     return (R_PROCESS);
980 }
981 
982 /*
983  * update_dirleave_proc () is called back by the recursion code upon leaving
984  * a directory.  It will prune empty directories if needed and will execute
985  * any appropriate update programs.
986  */
987 /* ARGSUSED */
988 static int
989 update_dirleave_proc (callerdat, dir, err, update_dir, entries)
990     void *callerdat;
991     char *dir;
992     int err;
993     char *update_dir;
994     List *entries;
995 {
996     FILE *fp;
997 
998     /* If we set the tag or date for a new subdirectory in
999        update_dirent_proc, and we're now done with that subdirectory,
1000        undo the tag/date setting.  Note that we know that the tag and
1001        date were both originally NULL in this case.  */
1002     if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0)
1003     {
1004 	if (tag != NULL)
1005 	{
1006 	    free (tag);
1007 	    tag = NULL;
1008 	}
1009 	if (date != NULL)
1010 	{
1011 	    free (date);
1012 	    date = NULL;
1013 	}
1014 	nonbranch = 0;
1015 	free (tag_update_dir);
1016 	tag_update_dir = NULL;
1017     }
1018 
1019     /* run the update_prog if there is one */
1020     /* FIXME: should be checking for errors from CVS_FOPEN and printing
1021        them if not existence_error.  */
1022     if (err == 0 && !pipeout && !noexec &&
1023 	(fp = CVS_FOPEN (CVSADM_UPROG, "r")) != NULL)
1024     {
1025 	char *cp;
1026 	char *repository;
1027 	char *line = NULL;
1028 	size_t line_allocated = 0;
1029 
1030 	repository = Name_Repository ((char *) NULL, update_dir);
1031 	if (getline (&line, &line_allocated, fp) >= 0)
1032 	{
1033 	    if ((cp = strrchr (line, '\n')) != NULL)
1034 		*cp = '\0';
1035 	    run_setup (line);
1036 	    run_arg (repository);
1037 	    cvs_output (program_name, 0);
1038 	    cvs_output (" ", 1);
1039 	    cvs_output (command_name, 0);
1040 	    cvs_output (": Executing '", 0);
1041 	    run_print (stdout);
1042 	    cvs_output ("'\n", 0);
1043 	    (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
1044 	}
1045 	else if (ferror (fp))
1046 	    error (0, errno, "cannot read %s", CVSADM_UPROG);
1047 	else
1048 	    error (0, 0, "unexpected end of file on %s", CVSADM_UPROG);
1049 
1050 	if (fclose (fp) < 0)
1051 	    error (0, errno, "cannot close %s", CVSADM_UPROG);
1052 	if (line != NULL)
1053 	    free (line);
1054 	free (repository);
1055     }
1056 
1057     if (strchr (dir, '/') == NULL)
1058     {
1059 	/* FIXME: chdir ("..") loses with symlinks.  */
1060 	/* Prune empty dirs on the way out - if necessary */
1061 	(void) CVS_CHDIR ("..");
1062 	if (update_prune_dirs && isemptydir (dir, 0))
1063 	{
1064 	    /* I'm not sure the existence_error is actually possible (except
1065 	       in cases where we really should print a message), but since
1066 	       this code used to ignore all errors, I'll play it safe.	*/
1067 	    if (unlink_file_dir (dir) < 0 && !existence_error (errno))
1068 		error (0, errno, "cannot remove %s directory", dir);
1069 	    Subdir_Deregister (entries, (char *) NULL, dir);
1070 	}
1071     }
1072 
1073     return (err);
1074 }
1075 
1076 static int isremoved PROTO ((Node *, void *));
1077 
1078 /* Returns 1 if the file indicated by node has been removed.  */
1079 static int
1080 isremoved (node, closure)
1081     Node *node;
1082     void *closure;
1083 {
1084     Entnode *entdata = (Entnode*) node->data;
1085 
1086     /* If the first character of the version is a '-', the file has been
1087        removed. */
1088     return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
1089 }
1090 
1091 /* Returns 1 if the argument directory is completely empty, other than the
1092    existence of the CVS directory entry.  Zero otherwise.  If MIGHT_NOT_EXIST
1093    and the directory doesn't exist, then just return 0.  */
1094 int
1095 isemptydir (dir, might_not_exist)
1096     char *dir;
1097     int might_not_exist;
1098 {
1099     DIR *dirp;
1100     struct dirent *dp;
1101 
1102     if ((dirp = CVS_OPENDIR (dir)) == NULL)
1103     {
1104 	if (might_not_exist && existence_error (errno))
1105 	    return 0;
1106 	error (0, errno, "cannot open directory %s for empty check", dir);
1107 	return (0);
1108     }
1109     errno = 0;
1110     while ((dp = readdir (dirp)) != NULL)
1111     {
1112 	if (strcmp (dp->d_name, ".") != 0
1113 	    && strcmp (dp->d_name, "..") != 0)
1114 	{
1115 	    if (strcmp (dp->d_name, CVSADM) != 0)
1116 	    {
1117 		/* An entry other than the CVS directory.  The directory
1118 		   is certainly not empty. */
1119 		(void) closedir (dirp);
1120 		return (0);
1121 	    }
1122 	    else
1123 	    {
1124 		/* The CVS directory entry.  We don't have to worry about
1125 		   this unless the Entries file indicates that files have
1126 		   been removed, but not committed, in this directory.
1127 		   (Removing the directory would prevent people from
1128 		   comitting the fact that they removed the files!) */
1129 		List *l;
1130 		int files_removed;
1131 		struct saved_cwd cwd;
1132 
1133 		if (save_cwd (&cwd))
1134 		    error_exit ();
1135 
1136 		if (CVS_CHDIR (dir) < 0)
1137 		    error (1, errno, "cannot change directory to %s", dir);
1138 		l = Entries_Open (0, NULL);
1139 		files_removed = walklist (l, isremoved, 0);
1140 		Entries_Close (l);
1141 
1142 		if (restore_cwd (&cwd, NULL))
1143 		    error_exit ();
1144 		free_cwd (&cwd);
1145 
1146 		if (files_removed != 0)
1147 		{
1148 		    /* There are files that have been removed, but not
1149 		       committed!  Do not consider the directory empty. */
1150 		    (void) closedir (dirp);
1151 		    return (0);
1152 		}
1153 	    }
1154 	}
1155 	errno = 0;
1156     }
1157     if (errno != 0)
1158     {
1159 	error (0, errno, "cannot read directory %s", dir);
1160 	(void) closedir (dirp);
1161 	return (0);
1162     }
1163     (void) closedir (dirp);
1164     return (1);
1165 }
1166 
1167 /*
1168  * scratch the Entries file entry associated with a file
1169  */
1170 static int
1171 scratch_file (finfo)
1172     struct file_info *finfo;
1173 {
1174     history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1175     Scratch_Entry (finfo->entries, finfo->file);
1176     if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1177 	error (0, errno, "unable to remove %s", finfo->fullname);
1178     return (0);
1179 }
1180 
1181 /*
1182  * Check out a file.
1183  */
1184 static int
1185 checkout_file (finfo, vers_ts, adding, merging, update_server)
1186     struct file_info *finfo;
1187     Vers_TS *vers_ts;
1188     int adding;
1189     int merging;
1190     int update_server;
1191 {
1192     char *backup;
1193     int set_time, retval = 0;
1194     int status;
1195     int file_is_dead;
1196     struct buffer *revbuf;
1197 
1198     backup = NULL;
1199     revbuf = NULL;
1200 
1201     /* Don't screw with backup files if we're going to stdout, or if
1202        we are the server.  */
1203     if (!pipeout
1204 #ifdef SERVER_SUPPORT
1205 	&& ! server_active
1206 #endif
1207 	)
1208     {
1209 	backup = xmalloc (strlen (finfo->file)
1210 			  + sizeof (CVSADM)
1211 			  + sizeof (CVSPREFIX)
1212 			  + 10);
1213 	(void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1214 	if (isfile (finfo->file))
1215 	    rename_file (finfo->file, backup);
1216 	else
1217 	{
1218 	    /* If -f/-t wrappers are being used to wrap up a directory,
1219 	       then backup might be a directory instead of just a file.  */
1220 	    if (unlink_file_dir (backup) < 0)
1221 	    {
1222 		/* Not sure if the existence_error check is needed here.  */
1223 		if (!existence_error (errno))
1224 		    /* FIXME: should include update_dir in message.  */
1225 		    error (0, errno, "error removing %s", backup);
1226 	    }
1227 	    free (backup);
1228 	    backup = NULL;
1229 	}
1230     }
1231 
1232     file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1233 
1234     if (!file_is_dead)
1235     {
1236 	/*
1237 	 * if we are checking out to stdout, print a nice message to
1238 	 * stderr, and add the -p flag to the command */
1239 	if (pipeout)
1240 	{
1241 	    if (!quiet)
1242 	    {
1243 		cvs_outerr ("\
1244 ===================================================================\n\
1245 Checking out ", 0);
1246 		cvs_outerr (finfo->fullname, 0);
1247 		cvs_outerr ("\n\
1248 RCS:  ", 0);
1249 		cvs_outerr (vers_ts->srcfile->path, 0);
1250 		cvs_outerr ("\n\
1251 VERS: ", 0);
1252 		cvs_outerr (vers_ts->vn_rcs, 0);
1253 		cvs_outerr ("\n***************\n", 0);
1254 	    }
1255 	}
1256 
1257 #ifdef SERVER_SUPPORT
1258 	if (update_server
1259 	    && server_active
1260 	    && ! pipeout
1261 	    && ! file_gzip_level
1262 	    && ! joining ()
1263 	    && ! wrap_name_has (finfo->file, WRAP_FROMCVS))
1264 	{
1265 	    revbuf = buf_nonio_initialize ((BUFMEMERRPROC) NULL);
1266 	    status = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1267 				   vers_ts->vn_rcs, vers_ts->vn_tag,
1268 				   vers_ts->options, RUN_TTY,
1269 				   checkout_to_buffer, revbuf);
1270 	}
1271 	else
1272 #endif
1273 	    status = RCS_checkout (vers_ts->srcfile,
1274 				   pipeout ? NULL : finfo->file,
1275 				   vers_ts->vn_rcs, vers_ts->vn_tag,
1276 				   vers_ts->options, RUN_TTY,
1277 				   (RCSCHECKOUTPROC) NULL, (void *) NULL);
1278     }
1279     if (file_is_dead || status == 0)
1280     {
1281 	mode_t mode;
1282 
1283 	mode = (mode_t) -1;
1284 
1285 	if (!pipeout)
1286 	{
1287 	    Vers_TS *xvers_ts;
1288 
1289 	    if (revbuf != NULL)
1290 	    {
1291 		struct stat sb;
1292 
1293 		/* FIXME: We should have RCS_checkout return the mode.  */
1294 		if (stat (vers_ts->srcfile->path, &sb) < 0)
1295 		    error (1, errno, "cannot stat %s",
1296 			   vers_ts->srcfile->path);
1297 		mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH);
1298 	    }
1299 
1300 	    if (cvswrite
1301 		&& !file_is_dead
1302 		&& !fileattr_get (finfo->file, "_watched"))
1303 	    {
1304 		if (revbuf == NULL)
1305 		    xchmod (finfo->file, 1);
1306 		else
1307 		{
1308 		    /* We know that we are the server here, so
1309                        although xchmod checks umask, we don't bother.  */
1310 		    mode |= (((mode & S_IRUSR) ? S_IWUSR : 0)
1311 			     | ((mode & S_IRGRP) ? S_IWGRP : 0)
1312 			     | ((mode & S_IROTH) ? S_IWOTH : 0));
1313 		}
1314 	    }
1315 
1316 	    {
1317 		/* A newly checked out file is never under the spell
1318 		   of "cvs edit".  If we think we were editing it
1319 		   from a previous life, clean up.  Would be better to
1320 		   check for same the working directory instead of
1321 		   same user, but that is hairy.  */
1322 
1323 		struct addremove_args args;
1324 
1325 		editor_set (finfo->file, getcaller (), NULL);
1326 
1327 		memset (&args, 0, sizeof args);
1328 		args.remove_temp = 1;
1329 		watch_modify_watchers (finfo->file, &args);
1330 	    }
1331 
1332 	    /* set the time from the RCS file iff it was unknown before */
1333 	    set_time =
1334 		(!noexec
1335 		 && (vers_ts->vn_user == NULL ||
1336 		     strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1337 		 && !file_is_dead);
1338 
1339 	    wrap_fromcvs_process_file (finfo->file);
1340 
1341 	    xvers_ts = Version_TS (finfo, options, tag, date,
1342 				   force_tag_match, set_time);
1343 	    if (strcmp (xvers_ts->options, "-V4") == 0)
1344 		xvers_ts->options[0] = '\0';
1345 
1346 	    if (revbuf != NULL)
1347 	    {
1348 		/* If we stored the file data into a buffer, then we
1349                    didn't create a file at all, so xvers_ts->ts_user
1350                    is wrong.  The correct value is to have it be the
1351                    same as xvers_ts->ts_rcs, meaning that the working
1352                    file is unchanged from the RCS file.
1353 
1354 		   FIXME: We should tell Version_TS not to waste time
1355 		   statting the nonexistent file.
1356 
1357 		   FIXME: Actually, I don't think the ts_user value
1358 		   matters at all here.  The only use I know of is
1359 		   that it is printed in a trace message by
1360 		   Server_Register.  */
1361 
1362 		if (xvers_ts->ts_user != NULL)
1363 		    free (xvers_ts->ts_user);
1364 		xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs);
1365 	    }
1366 
1367 	    (void) time (&last_register_time);
1368 
1369 	    if (file_is_dead)
1370 	    {
1371 		if (xvers_ts->vn_user != NULL)
1372 		{
1373 		    error (0, 0,
1374 			   "warning: %s is not (any longer) pertinent",
1375  			   finfo->fullname);
1376 		}
1377 		Scratch_Entry (finfo->entries, finfo->file);
1378 #ifdef SERVER_SUPPORT
1379 		if (server_active && xvers_ts->ts_user == NULL)
1380 		    server_scratch_entry_only ();
1381 #endif
1382 		/* FIXME: Rather than always unlink'ing, and ignoring the
1383 		   existence_error, we should do the unlink only if
1384 		   vers_ts->ts_user is non-NULL.  Then there would be no
1385 		   need to ignore an existence_error (for example, if the
1386 		   user removes the file while we are running).  */
1387 		if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1388 		{
1389 		    error (0, errno, "cannot remove %s", finfo->fullname);
1390 		}
1391 	    }
1392 	    else
1393 		Register (finfo->entries, finfo->file,
1394 			  adding ? "0" : xvers_ts->vn_rcs,
1395 			  xvers_ts->ts_user, xvers_ts->options,
1396 			  xvers_ts->tag, xvers_ts->date,
1397 			  (char *)0); /* Clear conflict flag on fresh checkout */
1398 
1399 	    /* fix up the vers structure, in case it is used by join */
1400 	    if (join_rev1)
1401 	    {
1402 		if (vers_ts->vn_user != NULL)
1403 		    free (vers_ts->vn_user);
1404 		if (vers_ts->vn_rcs != NULL)
1405 		    free (vers_ts->vn_rcs);
1406 		vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1407 		vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1408 	    }
1409 
1410 	    /* If this is really Update and not Checkout, recode history */
1411 	    if (strcmp (command_name, "update") == 0)
1412 		history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1413 			       finfo->repository);
1414 
1415 	    freevers_ts (&xvers_ts);
1416 
1417 	    if (!really_quiet && !file_is_dead)
1418 	    {
1419 		write_letter (finfo, 'U');
1420 	    }
1421 	}
1422 
1423 #ifdef SERVER_SUPPORT
1424 	if (update_server && server_active)
1425 	    server_updated (finfo, vers_ts,
1426 			    merging ? SERVER_MERGED : SERVER_UPDATED,
1427 			    mode, (unsigned char *) NULL, revbuf);
1428 #endif
1429     }
1430     else
1431     {
1432 	if (backup != NULL)
1433 	{
1434 	    rename_file (backup, finfo->file);
1435 	    free (backup);
1436 	    backup = NULL;
1437 	}
1438 
1439 	error (0, 0, "could not check out %s", finfo->fullname);
1440 
1441 	retval = status;
1442     }
1443 
1444     if (backup != NULL)
1445     {
1446 	/* If -f/-t wrappers are being used to wrap up a directory,
1447 	   then backup might be a directory instead of just a file.  */
1448 	if (unlink_file_dir (backup) < 0)
1449 	{
1450 	    /* Not sure if the existence_error check is needed here.  */
1451 	    if (!existence_error (errno))
1452 		/* FIXME: should include update_dir in message.  */
1453 		error (0, errno, "error removing %s", backup);
1454 	}
1455 	free (backup);
1456     }
1457 
1458     return (retval);
1459 }
1460 
1461 #ifdef SERVER_SUPPORT
1462 
1463 /* This function is used to write data from a file being checked out
1464    into a buffer.  */
1465 
1466 static void
1467 checkout_to_buffer (callerdat, data, len)
1468      void *callerdat;
1469      const char *data;
1470      size_t len;
1471 {
1472     struct buffer *buf = (struct buffer *) callerdat;
1473 
1474     buf_output (buf, data, len);
1475 }
1476 
1477 #endif /* SERVER_SUPPORT */
1478 
1479 #ifdef SERVER_SUPPORT
1480 
1481 /* This structure is used to pass information between patch_file and
1482    patch_file_write.  */
1483 
1484 struct patch_file_data
1485 {
1486     /* File name, for error messages.  */
1487     const char *filename;
1488     /* File to which to write.  */
1489     FILE *fp;
1490     /* Whether to compute the MD5 checksum.  */
1491     int compute_checksum;
1492     /* Data structure for computing the MD5 checksum.  */
1493     struct MD5Context context;
1494     /* Set if the file has a final newline.  */
1495     int final_nl;
1496 };
1497 
1498 /* Patch a file.  Runs diff.  This is only done when running as the
1499  * server.  The hope is that the diff will be smaller than the file
1500  * itself.
1501  */
1502 static int
1503 patch_file (finfo, vers_ts, docheckout, file_info, checksum)
1504     struct file_info *finfo;
1505     Vers_TS *vers_ts;
1506     int *docheckout;
1507     struct stat *file_info;
1508     unsigned char *checksum;
1509 {
1510     char *backup;
1511     char *file1;
1512     char *file2;
1513     int retval = 0;
1514     int retcode = 0;
1515     int fail;
1516     long file_size;
1517     FILE *e;
1518     struct patch_file_data data;
1519 
1520     *docheckout = 0;
1521 
1522     if (noexec || pipeout || joining ())
1523     {
1524 	*docheckout = 1;
1525 	return 0;
1526     }
1527 
1528     /* If this file has been marked as being binary, then never send a
1529        patch.  */
1530     if (strcmp (vers_ts->options, "-kb") == 0)
1531     {
1532 	*docheckout = 1;
1533 	return 0;
1534     }
1535 
1536     /* First check that the first revision exists.  If it has been nuked
1537        by cvs admin -o, then just fall back to checking out entire
1538        revisions.  In some sense maybe we don't have to do this; after
1539        all cvs.texinfo says "Make sure that no-one has checked out a
1540        copy of the revision you outdate" but then again, that advice
1541        doesn't really make complete sense, because "cvs admin" operates
1542        on a working directory and so _someone_ will almost always have
1543        _some_ revision checked out.  */
1544     {
1545 	char *rev;
1546 
1547 	rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL);
1548 	if (rev == NULL)
1549 	{
1550 	    *docheckout = 1;
1551 	    return 0;
1552 	}
1553 	else
1554 	    free (rev);
1555     }
1556 
1557     /* If the revision is dead, let checkout_file handle it rather
1558        than duplicating the processing here.  */
1559     if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs))
1560     {
1561 	*docheckout = 1;
1562 	return 0;
1563     }
1564 
1565     backup = xmalloc (strlen (finfo->file)
1566 		      + sizeof (CVSADM)
1567 		      + sizeof (CVSPREFIX)
1568 		      + 10);
1569     (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1570     if (isfile (finfo->file))
1571         rename_file (finfo->file, backup);
1572     else
1573         (void) unlink_file (backup);
1574 
1575     file1 = xmalloc (strlen (finfo->file)
1576 		     + sizeof (CVSADM)
1577 		     + sizeof (CVSPREFIX)
1578 		     + 10);
1579     (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1580     file2 = xmalloc (strlen (finfo->file)
1581 		     + sizeof (CVSADM)
1582 		     + sizeof (CVSPREFIX)
1583 		     + 10);
1584     (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1585 
1586     fail = 0;
1587 
1588     /* We need to check out both revisions first, to see if either one
1589        has a trailing newline.  Because of this, we don't use rcsdiff,
1590        but just use diff.  */
1591 
1592     e = CVS_FOPEN (file1, "w");
1593     if (e == NULL)
1594 	error (1, errno, "cannot open %s", file1);
1595 
1596     data.filename = file1;
1597     data.fp = e;
1598     data.final_nl = 0;
1599     data.compute_checksum = 0;
1600 
1601     retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1602 			    vers_ts->vn_user, (char *) NULL,
1603 			    vers_ts->options, RUN_TTY,
1604 			    patch_file_write, (void *) &data);
1605 
1606     if (fclose (e) < 0)
1607 	error (1, errno, "cannot close %s", file1);
1608 
1609     if (retcode != 0 || ! data.final_nl)
1610 	fail = 1;
1611 
1612     if (! fail)
1613     {
1614 	e = CVS_FOPEN (file2, "w");
1615 	if (e == NULL)
1616 	    error (1, errno, "cannot open %s", file2);
1617 
1618 	data.filename = file2;
1619 	data.fp = e;
1620 	data.final_nl = 0;
1621 	data.compute_checksum = 1;
1622 	MD5Init (&data.context);
1623 
1624 	retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1625 				vers_ts->vn_rcs, (char *) NULL,
1626 				vers_ts->options, RUN_TTY,
1627 				patch_file_write, (void *) &data);
1628 
1629 	if (fclose (e) < 0)
1630 	    error (1, errno, "cannot close %s", file2);
1631 
1632 	if (retcode != 0 || ! data.final_nl)
1633 	    fail = 1;
1634 	else
1635 	    MD5Final (checksum, &data.context);
1636     }
1637 
1638     retcode = 0;
1639     if (! fail)
1640     {
1641 	char *diff_options;
1642 
1643 	/* FIXME: It might be better to come up with a diff library
1644            which can be shared with the diffutils.  */
1645 	/* If the client does not support the Rcs-diff command, we
1646            send a context diff, and the client must invoke patch.
1647            That approach was problematical for various reasons.  The
1648            new approach only requires running diff in the server; the
1649            client can handle everything without invoking an external
1650            program.  */
1651 	if (! rcs_diff_patches)
1652 	{
1653 	    /* We use -c, not -u, because we have no way of knowing
1654 	       which DIFF is in use.  */
1655 	    diff_options = "-c";
1656 	}
1657 	else
1658 	{
1659 	    /* Now that diff is librarified, we could be passing -a if
1660 	       we wanted to.  However, it is unclear to me whether we
1661 	       would want to.  Does diff -a, in any significant
1662 	       percentage of cases, produce patches which are smaller
1663 	       than the files it is patching?  I guess maybe text
1664 	       files with character sets which diff regards as
1665 	       'binary'.  Conversely, do they tend to be much larger
1666 	       in the bad cases?  This needs some more
1667 	       thought/investigation, I suspect.  */
1668 
1669 	    diff_options = "-n";
1670 	}
1671 	retcode = diff_exec (file1, file2, diff_options, finfo->file);
1672 
1673 	/* A retcode of 0 means no differences.  1 means some differences.  */
1674 	if (retcode != 0
1675 	    && retcode != 1)
1676 	{
1677 	    fail = 1;
1678 	}
1679 	else
1680 	{
1681 #define BINARY "Binary"
1682 	    char buf[sizeof BINARY];
1683 	    unsigned int c;
1684 
1685 	    /* Stat the original RCS file, and then adjust it the way
1686 	       that RCS_checkout would.  FIXME: This is an abstraction
1687 	       violation.  */
1688 	    if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
1689 		error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1690 	    if (chmod (finfo->file,
1691 		       file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1692 		< 0)
1693 		error (0, errno, "cannot change mode of file %s", finfo->file);
1694 	    if (cvswrite
1695 		&& !fileattr_get (finfo->file, "_watched"))
1696 		xchmod (finfo->file, 1);
1697 
1698 	    /* Check the diff output to make sure patch will be handle it.  */
1699 	    e = CVS_FOPEN (finfo->file, "r");
1700 	    if (e == NULL)
1701 		error (1, errno, "could not open diff output file %s",
1702 		       finfo->fullname);
1703 	    c = fread (buf, 1, sizeof BINARY - 1, e);
1704 	    buf[c] = '\0';
1705 	    if (strcmp (buf, BINARY) == 0)
1706 	    {
1707 		/* These are binary files.  We could use diff -a, but
1708 		   patch can't handle that.  */
1709 		fail = 1;
1710 	    }
1711 	    else {
1712 		/*
1713 		 * Don't send a diff if just sending the entire file
1714 		 * would be smaller
1715 		 */
1716 		fseek(e, 0L, SEEK_END);
1717 		if (file_size < ftell(e))
1718 		    fail = 1;
1719 	    }
1720 
1721 	    fclose (e);
1722 	}
1723     }
1724 
1725     if (! fail)
1726     {
1727         Vers_TS *xvers_ts;
1728 
1729         /* This stuff is just copied blindly from checkout_file.  I
1730 	   don't really know what it does.  */
1731         xvers_ts = Version_TS (finfo, options, tag, date,
1732 			       force_tag_match, 0);
1733 	if (strcmp (xvers_ts->options, "-V4") == 0)
1734 	    xvers_ts->options[0] = '\0';
1735 
1736 	Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1737 		  xvers_ts->ts_user, xvers_ts->options,
1738 		  xvers_ts->tag, xvers_ts->date, NULL);
1739 
1740 	if (CVS_STAT (finfo->file, file_info) < 0)
1741 	    error (1, errno, "could not stat %s", finfo->file);
1742 
1743 	/* If this is really Update and not Checkout, recode history */
1744 	if (strcmp (command_name, "update") == 0)
1745 	    history_write ('P', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1746 			   finfo->repository);
1747 
1748 	freevers_ts (&xvers_ts);
1749 
1750 	if (!really_quiet)
1751 	{
1752 	    write_letter (finfo, 'P');
1753 	}
1754     }
1755     else
1756     {
1757 	int old_errno = errno;		/* save errno value over the rename */
1758 
1759 	if (isfile (backup))
1760 	    rename_file (backup, finfo->file);
1761 
1762 	if (retcode != 0 && retcode != 1)
1763 	    error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1764 		   "could not diff %s", finfo->fullname);
1765 
1766 	*docheckout = 1;
1767 	retval = retcode;
1768     }
1769 
1770     (void) unlink_file (backup);
1771     (void) unlink_file (file1);
1772     (void) unlink_file (file2);
1773 
1774     free (backup);
1775     free (file1);
1776     free (file2);
1777     return (retval);
1778 }
1779 
1780 /* Write data to a file.  Record whether the last byte written was a
1781    newline.  Optionally compute a checksum.  This is called by
1782    patch_file via RCS_checkout.  */
1783 
1784 static void
1785 patch_file_write (callerdat, buffer, len)
1786      void *callerdat;
1787      const char *buffer;
1788      size_t len;
1789 {
1790     struct patch_file_data *data = (struct patch_file_data *) callerdat;
1791 
1792     if (fwrite (buffer, 1, len, data->fp) != len)
1793 	error (1, errno, "cannot write %s", data->filename);
1794 
1795     data->final_nl = (buffer[len - 1] == '\n');
1796 
1797     if (data->compute_checksum)
1798 	MD5Update (&data->context, (unsigned char *) buffer, len);
1799 }
1800 
1801 #endif /* SERVER_SUPPORT */
1802 
1803 /*
1804  * Several of the types we process only print a bit of information consisting
1805  * of a single letter and the name.
1806  */
1807 static void
1808 write_letter (finfo, letter)
1809     struct file_info *finfo;
1810     int letter;
1811 {
1812     if (!really_quiet)
1813     {
1814 	char *tag = NULL;
1815 	/* Big enough for "+updated" or any of its ilk.  */
1816 	char buf[80];
1817 
1818 	switch (letter)
1819 	{
1820 	    case 'U':
1821 		tag = "updated";
1822 		break;
1823 	    default:
1824 		/* We don't yet support tagged output except for "U".  */
1825 		break;
1826 	}
1827 
1828 	if (tag != NULL)
1829 	{
1830 	    sprintf (buf, "+%s", tag);
1831 	    cvs_output_tagged (buf, NULL);
1832 	}
1833 	buf[0] = letter;
1834 	buf[1] = ' ';
1835 	buf[2] = '\0';
1836 	cvs_output_tagged ("text", buf);
1837 	cvs_output_tagged ("fname", finfo->fullname);
1838 	cvs_output_tagged ("newline", NULL);
1839 	if (tag != NULL)
1840 	{
1841 	    sprintf (buf, "-%s", tag);
1842 	    cvs_output_tagged (buf, NULL);
1843 	}
1844     }
1845     return;
1846 }
1847 
1848 /*
1849  * Do all the magic associated with a file which needs to be merged
1850  */
1851 static int
1852 merge_file (finfo, vers)
1853     struct file_info *finfo;
1854     Vers_TS *vers;
1855 {
1856     char *backup;
1857     int status;
1858     int retcode = 0;
1859     int retval;
1860 
1861     /*
1862      * The users currently modified file is moved to a backup file name
1863      * ".#filename.version", so that it will stay around for a few days
1864      * before being automatically removed by some cron daemon.  The "version"
1865      * is the version of the file that the user was most up-to-date with
1866      * before the merge.
1867      */
1868     backup = xmalloc (strlen (finfo->file)
1869 		      + strlen (vers->vn_user)
1870 		      + sizeof (BAKPREFIX)
1871 		      + 10);
1872     (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1873 
1874     (void) unlink_file (backup);
1875     copy_file (finfo->file, backup);
1876     xchmod (finfo->file, 1);
1877 
1878     if (strcmp (vers->options, "-kb") == 0
1879 	|| wrap_merge_is_copy (finfo->file)
1880 	|| special_file_mismatch (finfo, NULL, vers->vn_rcs))
1881     {
1882 	/* For binary files, a merge is always a conflict.  Same for
1883 	   files whose permissions or linkage do not match.  We give the
1884 	   user the two files, and let them resolve it.  It is possible
1885 	   that we should require a "touch foo" or similar step before
1886 	   we allow a checkin.  */
1887 
1888 	/* TODO: it may not always be necessary to regard a permission
1889 	   mismatch as a conflict.  The working file and the RCS file
1890 	   have a common ancestor `A'; if the working file's permissions
1891 	   match A's, then it's probably safe to overwrite them with the
1892 	   RCS permissions.  Only if the working file, the RCS file, and
1893 	   A all disagree should this be considered a conflict.  But more
1894 	   thought needs to go into this, and in the meantime it is safe
1895 	   to treat any such mismatch as an automatic conflict. -twp */
1896 
1897 #ifdef SERVER_SUPPORT
1898 	if (server_active)
1899 	    server_copy_file (finfo->file, finfo->update_dir,
1900 			      finfo->repository, backup);
1901 #endif
1902 
1903 	status = checkout_file (finfo, vers, 0, 1, 1);
1904 
1905 	/* Is there a better term than "nonmergeable file"?  What we
1906 	   really mean is, not something that CVS cannot or does not
1907 	   want to merge (there might be an external manual or
1908 	   automatic merge process).  */
1909 	error (0, 0, "nonmergeable file needs merge");
1910 	error (0, 0, "revision %s from repository is now in %s",
1911 	       vers->vn_rcs, finfo->fullname);
1912 	error (0, 0, "file from working directory is now in %s", backup);
1913 	write_letter (finfo, 'C');
1914 
1915 	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
1916 		       finfo->repository);
1917 	retval = 0;
1918 	goto out;
1919     }
1920 
1921     status = RCS_merge(finfo->rcs, vers->srcfile->path, finfo->file,
1922 		       vers->options, vers->vn_user, vers->vn_rcs);
1923     if (status != 0 && status != 1)
1924     {
1925 	error (0, status == -1 ? errno : 0,
1926 	       "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
1927 	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
1928 	       finfo->fullname, backup);
1929 	rename_file (backup, finfo->file);
1930 	retval = 1;
1931 	goto out;
1932     }
1933 
1934     if (strcmp (vers->options, "-V4") == 0)
1935 	vers->options[0] = '\0';
1936     (void) time (&last_register_time);
1937     {
1938 	char *cp = 0;
1939 
1940 	if (status)
1941 	    cp = time_stamp (finfo->file);
1942 	Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, vers->options,
1943 		  vers->tag, vers->date, cp);
1944 	if (cp)
1945 	    free (cp);
1946     }
1947 
1948     /* fix up the vers structure, in case it is used by join */
1949     if (join_rev1)
1950     {
1951 	if (vers->vn_user != NULL)
1952 	    free (vers->vn_user);
1953 	vers->vn_user = xstrdup (vers->vn_rcs);
1954     }
1955 
1956 #ifdef SERVER_SUPPORT
1957     /* Send the new contents of the file before the message.  If we
1958        wanted to be totally correct, we would have the client write
1959        the message only after the file has safely been written.  */
1960     if (server_active)
1961     {
1962         server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
1963 			  backup);
1964 	server_updated (finfo, vers, SERVER_MERGED,
1965 			(mode_t) -1, (unsigned char *) NULL,
1966 			(struct buffer *) NULL);
1967     }
1968 #endif
1969 
1970     if (!noexec && !xcmp (backup, finfo->file))
1971     {
1972 	printf ("%s already contains the differences between %s and %s\n",
1973 		finfo->fullname, vers->vn_user, vers->vn_rcs);
1974 	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1975 		       finfo->repository);
1976 	retval = 0;
1977 	goto out;
1978     }
1979 
1980     if (status == 1)
1981     {
1982 	if (!noexec)
1983 	    error (0, 0, "conflicts found in %s", finfo->fullname);
1984 
1985 	write_letter (finfo, 'C');
1986 
1987 	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, finfo->repository);
1988 
1989     }
1990     else if (retcode == -1)
1991     {
1992 	error (1, errno, "fork failed while examining update of %s",
1993 	       finfo->fullname);
1994     }
1995     else
1996     {
1997 	write_letter (finfo, 'M');
1998 	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1999 		       finfo->repository);
2000     }
2001     retval = 0;
2002  out:
2003     free (backup);
2004     return retval;
2005 }
2006 
2007 /*
2008  * Do all the magic associated with a file which needs to be joined
2009  * (-j option)
2010  */
2011 static void
2012 join_file (finfo, vers)
2013     struct file_info *finfo;
2014     Vers_TS *vers;
2015 {
2016     char *backup;
2017     char *options;
2018     int status;
2019 
2020     char *rev1;
2021     char *rev2;
2022     char *jrev1;
2023     char *jrev2;
2024     char *jdate1;
2025     char *jdate2;
2026 
2027     jrev1 = join_rev1;
2028     jrev2 = join_rev2;
2029     jdate1 = date_rev1;
2030     jdate2 = date_rev2;
2031 
2032     /* Determine if we need to do anything at all.  */
2033     if (vers->srcfile == NULL ||
2034 	vers->srcfile->path == NULL)
2035     {
2036 	return;
2037     }
2038 
2039     /* If only one join revision is specified, it becomes the second
2040        revision.  */
2041     if (jrev2 == NULL)
2042     {
2043 	jrev2 = jrev1;
2044 	jrev1 = NULL;
2045 	jdate2 = jdate1;
2046 	jdate1 = NULL;
2047     }
2048 
2049     /* Convert the second revision, walking branches and dates.  */
2050     rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL);
2051 
2052     /* If this is a merge of two revisions, get the first revision.
2053        If only one join tag was specified, then the first revision is
2054        the greatest common ancestor of the second revision and the
2055        working file.  */
2056     if (jrev1 != NULL)
2057 	rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL);
2058     else
2059     {
2060 	/* Note that we use vn_rcs here, since vn_user may contain a
2061            special string such as "-nn".  */
2062 	if (vers->vn_rcs == NULL)
2063 	    rev1 = NULL;
2064 	else if (rev2 == NULL)
2065 	{
2066 	    /* This means that the file never existed on the branch.
2067                It does not mean that the file was removed on the
2068                branch: that case is represented by a dead rev2.  If
2069                the file never existed on the branch, then we have
2070                nothing to merge, so we just return.  */
2071 	    return;
2072 	}
2073 	else
2074 	    rev1 = gca (vers->vn_rcs, rev2);
2075     }
2076 
2077     /* Handle a nonexistent or dead merge target.  */
2078     if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
2079     {
2080 	char *mrev;
2081 
2082 	if (rev2 != NULL)
2083 	    free (rev2);
2084 
2085 	/* If the first revision doesn't exist either, then there is
2086            no change between the two revisions, so we don't do
2087            anything.  */
2088 	if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2089 	{
2090 	    if (rev1 != NULL)
2091 		free (rev1);
2092 	    return;
2093 	}
2094 
2095 	/* If we are merging two revisions, then the file was removed
2096 	   between the first revision and the second one.  In this
2097 	   case we want to mark the file for removal.
2098 
2099 	   If we are merging one revision, then the file has been
2100 	   removed between the greatest common ancestor and the merge
2101 	   revision.  From the perspective of the branch on to which
2102 	   we ar emerging, which may be the trunk, either 1) the file
2103 	   does not currently exist on the target, or 2) the file has
2104 	   not been modified on the target branch since the greatest
2105 	   common ancestor, or 3) the file has been modified on the
2106 	   target branch since the greatest common ancestor.  In case
2107 	   1 there is nothing to do.  In case 2 we mark the file for
2108 	   removal.  In case 3 we have a conflict.
2109 
2110 	   Note that the handling is slightly different depending upon
2111 	   whether one or two join targets were specified.  If two
2112 	   join targets were specified, we don't check whether the
2113 	   file was modified since a given point.  My reasoning is
2114 	   that if you ask for an explicit merge between two tags,
2115 	   then you want to merge in whatever was changed between
2116 	   those two tags.  If a file was removed between the two
2117 	   tags, then you want it to be removed.  However, if you ask
2118 	   for a merge of a branch, then you want to merge in all
2119 	   changes which were made on the branch.  If a file was
2120 	   removed on the branch, that is a change to the file.  If
2121 	   the file was also changed on the main line, then that is
2122 	   also a change.  These two changes--the file removal and the
2123 	   modification--must be merged.  This is a conflict.  */
2124 
2125 	/* If the user file is dead, or does not exist, or has been
2126            marked for removal, then there is nothing to do.  */
2127 	if (vers->vn_user == NULL
2128 	    || vers->vn_user[0] == '-'
2129 	    || RCS_isdead (vers->srcfile, vers->vn_user))
2130 	{
2131 	    if (rev1 != NULL)
2132 		free (rev1);
2133 	    return;
2134 	}
2135 
2136 	/* If the user file has been marked for addition, or has been
2137 	   locally modified, then we have a conflict which we can not
2138 	   resolve.  No_Difference will already have been called in
2139 	   this case, so comparing the timestamps is sufficient to
2140 	   determine whether the file is locally modified.  */
2141 	if (strcmp (vers->vn_user, "0") == 0
2142 	    || (vers->ts_user != NULL
2143 		&& strcmp (vers->ts_user, vers->ts_rcs) != 0))
2144 	{
2145 	    if (jdate2 != NULL)
2146 		error (0, 0,
2147 		       "file %s is locally modified, but has been removed in revision %s as of %s",
2148 		       finfo->fullname, jrev2, jdate2);
2149 	    else
2150 		error (0, 0,
2151 		       "file %s is locally modified, but has been removed in revision %s",
2152 		       finfo->fullname, jrev2);
2153 
2154 	    /* FIXME: Should we arrange to return a non-zero exit
2155                status?  */
2156 
2157 	    if (rev1 != NULL)
2158 		free (rev1);
2159 
2160 	    return;
2161 	}
2162 
2163 	/* If only one join tag was specified, and the user file has
2164            been changed since the greatest common ancestor (rev1),
2165            then there is a conflict we can not resolve.  See above for
2166            the rationale.  */
2167 	if (join_rev2 == NULL
2168 	    && strcmp (rev1, vers->vn_user) != 0)
2169 	{
2170 	    if (jdate2 != NULL)
2171 		error (0, 0,
2172 		       "file %s has been modified, but has been removed in revision %s as of %s",
2173 		       finfo->fullname, jrev2, jdate2);
2174 	    else
2175 		error (0, 0,
2176 		       "file %s has been modified, but has been removed in revision %s",
2177 		       finfo->fullname, jrev2);
2178 
2179 	    /* FIXME: Should we arrange to return a non-zero exit
2180                status?  */
2181 
2182 	    if (rev1 != NULL)
2183 		free (rev1);
2184 
2185 	    return;
2186 	}
2187 
2188 	if (rev1 != NULL)
2189 	    free (rev1);
2190 
2191 	/* The user file exists and has not been modified.  Mark it
2192            for removal.  FIXME: If we are doing a checkout, this has
2193            the effect of first checking out the file, and then
2194            removing it.  It would be better to just register the
2195            removal.  */
2196 #ifdef SERVER_SUPPORT
2197 	if (server_active)
2198 	{
2199 	    server_scratch (finfo->file);
2200 	    server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1,
2201 			    (unsigned char *) NULL, (struct buffer *) NULL);
2202 	}
2203 #endif
2204 	mrev = xmalloc (strlen (vers->vn_user) + 2);
2205 	sprintf (mrev, "-%s", vers->vn_user);
2206 	Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
2207 		  vers->options, vers->tag, vers->date, vers->ts_conflict);
2208 	free (mrev);
2209 	/* We need to check existence_error here because if we are
2210            running as the server, and the file is up to date in the
2211            working directory, the client will not have sent us a copy.  */
2212 	if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
2213 	    error (0, errno, "cannot remove file %s", finfo->fullname);
2214 #ifdef SERVER_SUPPORT
2215 	if (server_active)
2216 	    server_checked_in (finfo->file, finfo->update_dir,
2217 			       finfo->repository);
2218 #endif
2219 	if (! really_quiet)
2220 	    error (0, 0, "scheduling %s for removal", finfo->fullname);
2221 
2222 	return;
2223     }
2224 
2225     /* If the target of the merge is the same as the working file
2226        revision, then there is nothing to do.  */
2227     if (vers->vn_user != NULL && strcmp (rev2, vers->vn_user) == 0)
2228     {
2229 	if (rev1 != NULL)
2230 	    free (rev1);
2231 	free (rev2);
2232 	return;
2233     }
2234 
2235     /* If rev1 is dead or does not exist, then the file was added
2236        between rev1 and rev2.  */
2237     if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2238     {
2239 	if (rev1 != NULL)
2240 	    free (rev1);
2241 	free (rev2);
2242 
2243 	/* If the file does not exist in the working directory, then
2244            we can just check out the new revision and mark it for
2245            addition.  */
2246 	if (vers->vn_user == NULL)
2247 	{
2248 	    Vers_TS *xvers;
2249 
2250 	    xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
2251 
2252 	    /* FIXME: If checkout_file fails, we should arrange to
2253                return a non-zero exit status.  */
2254 	    status = checkout_file (finfo, xvers, 1, 0, 1);
2255 
2256 	    freevers_ts (&xvers);
2257 
2258 	    return;
2259 	}
2260 
2261 	/* The file currently exists in the working directory, so we
2262            have a conflict which we can not resolve.  Note that this
2263            is true even if the file is marked for addition or removal.  */
2264 
2265 	if (jdate2 != NULL)
2266 	    error (0, 0,
2267 		   "file %s exists, but has been added in revision %s as of %s",
2268 		   finfo->fullname, jrev2, jdate2);
2269 	else
2270 	    error (0, 0,
2271 		   "file %s exists, but has been added in revision %s",
2272 		   finfo->fullname, jrev2);
2273 
2274 	return;
2275     }
2276 
2277     /* If the two merge revisions are the same, then there is nothing
2278        to do.  */
2279     if (strcmp (rev1, rev2) == 0)
2280     {
2281 	free (rev1);
2282 	free (rev2);
2283 	return;
2284     }
2285 
2286     /* If there is no working file, then we can't do the merge.  */
2287     if (vers->vn_user == NULL)
2288     {
2289 	free (rev1);
2290 	free (rev2);
2291 
2292 	if (jdate2 != NULL)
2293 	    error (0, 0,
2294 		   "file %s is present in revision %s as of %s",
2295 		   finfo->fullname, jrev2, jdate2);
2296 	else
2297 	    error (0, 0,
2298 		   "file %s is present in revision %s",
2299 		   finfo->fullname, jrev2);
2300 
2301 	/* FIXME: Should we arrange to return a non-zero exit status?  */
2302 
2303 	return;
2304     }
2305 
2306 #ifdef SERVER_SUPPORT
2307     if (server_active && !isreadable (finfo->file))
2308     {
2309 	int retcode;
2310 	/* The file is up to date.  Need to check out the current contents.  */
2311 	retcode = RCS_checkout (vers->srcfile, finfo->file,
2312 				vers->vn_user, (char *) NULL,
2313 				(char *) NULL, RUN_TTY,
2314 				(RCSCHECKOUTPROC) NULL, (void *) NULL);
2315 	if (retcode != 0)
2316 	    error (1, 0,
2317 		   "failed to check out %s file", finfo->fullname);
2318     }
2319 #endif
2320 
2321     /*
2322      * The users currently modified file is moved to a backup file name
2323      * ".#filename.version", so that it will stay around for a few days
2324      * before being automatically removed by some cron daemon.  The "version"
2325      * is the version of the file that the user was most up-to-date with
2326      * before the merge.
2327      */
2328     backup = xmalloc (strlen (finfo->file)
2329 		      + strlen (vers->vn_user)
2330 		      + sizeof (BAKPREFIX)
2331 		      + 10);
2332     (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2333 
2334     (void) unlink_file (backup);
2335     copy_file (finfo->file, backup);
2336     xchmod (finfo->file, 1);
2337 
2338     options = vers->options;
2339 #if 0
2340     if (*options == '\0')
2341 	options = "-kk";		/* to ignore keyword expansions */
2342 #endif
2343 
2344     /* If the source of the merge is the same as the working file
2345        revision, then we can just RCS_checkout the target (no merging
2346        as such).  In the text file case, this is probably quite
2347        similar to the RCS_merge, but in the binary file case,
2348        RCS_merge gives all kinds of trouble.  */
2349     if (vers->vn_user != NULL
2350 	&& strcmp (rev1, vers->vn_user) == 0
2351 	/* See comments above about how No_Difference has already been
2352 	   called.  */
2353 	&& vers->ts_user != NULL
2354 	&& strcmp (vers->ts_user, vers->ts_rcs) == 0
2355 
2356 	/* This is because of the worry below about $Name.  If that
2357 	   isn't a problem, I suspect this code probably works for
2358 	   text files too.  */
2359 	&& (strcmp (options, "-kb") == 0
2360 	    || wrap_merge_is_copy (finfo->file)))
2361     {
2362 	/* FIXME: what about nametag?  What does RCS_merge do with
2363 	   $Name?  */
2364 	if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
2365 			  RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
2366 	    status = 2;
2367 	else
2368 	    status = 0;
2369 
2370 	/* OK, this is really stupid.  RCS_checkout carefully removes
2371 	   write permissions, and we carefully put them back.  But
2372 	   until someone gets around to fixing it, that seems like the
2373 	   easiest way to get what would seem to be the right mode.
2374 	   I don't check CVSWRITE or _watched; I haven't thought about
2375 	   that in great detail, but it seems like a watched file should
2376 	   be checked out (writable) after a merge.  */
2377 	xchmod (finfo->file, 1);
2378 
2379 	/* Traditionally, the text file case prints a whole bunch of
2380 	   scary looking and verbose output which fails to tell the user
2381 	   what is really going on (it gives them rev1 and rev2 but doesn't
2382 	   indicate in any way that rev1 == vn_user).  I think just a
2383 	   simple "U foo" is good here; it seems analogous to the case in
2384 	   which the file was added on the branch in terms of what to
2385 	   print.  */
2386 	write_letter (finfo, 'U');
2387     }
2388     else if (strcmp (options, "-kb") == 0
2389 	     || wrap_merge_is_copy (finfo->file)
2390 	     || special_file_mismatch (finfo, rev1, rev2))
2391     {
2392 	/* We are dealing with binary files, or files with a
2393 	   permission/linkage mismatch, and real merging would
2394 	   need to take place.  This is a conflict.  We give the user
2395 	   the two files, and let them resolve it.  It is possible
2396 	   that we should require a "touch foo" or similar step before
2397 	   we allow a checkin.  */
2398 	if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
2399 			  RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
2400 	    status = 2;
2401 	else
2402 	    status = 0;
2403 
2404 	/* OK, this is really stupid.  RCS_checkout carefully removes
2405 	   write permissions, and we carefully put them back.  But
2406 	   until someone gets around to fixing it, that seems like the
2407 	   easiest way to get what would seem to be the right mode.
2408 	   I don't check CVSWRITE or _watched; I haven't thought about
2409 	   that in great detail, but it seems like a watched file should
2410 	   be checked out (writable) after a merge.  */
2411 	xchmod (finfo->file, 1);
2412 
2413 	/* Hmm.  We don't give them REV1 anywhere.  I guess most people
2414 	   probably don't have a 3-way merge tool for the file type in
2415 	   question, and might just get confused if we tried to either
2416 	   provide them with a copy of the file from REV1, or even just
2417 	   told them what REV1 is so they can get it themself, but it
2418 	   might be worth thinking about.  */
2419 	/* See comment in merge_file about the "nonmergeable file"
2420 	   terminology.  */
2421 	error (0, 0, "nonmergeable file needs merge");
2422 	error (0, 0, "revision %s from repository is now in %s",
2423 	       rev2, finfo->fullname);
2424 	error (0, 0, "file from working directory is now in %s", backup);
2425 	write_letter (finfo, 'C');
2426     }
2427     else
2428 	status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
2429 			    options, rev1, rev2);
2430 
2431     if (status != 0 && status != 1)
2432     {
2433 	error (0, status == -1 ? errno : 0,
2434 	       "could not merge revision %s of %s", rev2, finfo->fullname);
2435 	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2436 	       finfo->fullname, backup);
2437 	rename_file (backup, finfo->file);
2438     }
2439     free (rev1);
2440     free (rev2);
2441 
2442 #ifdef SERVER_SUPPORT
2443     /*
2444      * If we're in server mode, then we need to re-register the file
2445      * even if there were no conflicts (status == 0).
2446      * This tells server_updated() to send the modified file back to
2447      * the client.
2448      */
2449     if (status == 1 || (status == 0 && server_active))
2450 #else
2451     if (status == 1)
2452 #endif
2453     {
2454 	char *cp = 0;
2455 
2456 	if (status)
2457 	    cp = time_stamp (finfo->file);
2458 	Register (finfo->entries, finfo->file,
2459 		  vers->vn_rcs, vers->ts_rcs, vers->options,
2460 		  vers->tag, vers->date, cp);
2461 	if (cp)
2462 	    free(cp);
2463     }
2464 
2465 #ifdef SERVER_SUPPORT
2466     if (server_active)
2467     {
2468 	server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2469 			  backup);
2470 	server_updated (finfo, vers, SERVER_MERGED,
2471 			(mode_t) -1, (unsigned char *) NULL,
2472 			(struct buffer *) NULL);
2473     }
2474 #endif
2475     free (backup);
2476 }
2477 
2478 /*
2479  * Report whether revisions REV1 and REV2 of FINFO agree on:
2480  *   . file ownership
2481  *   . permissions
2482  *   . major and minor device numbers
2483  *   . symbolic links
2484  *   . hard links
2485  *
2486  * If either REV1 or REV2 is NULL, the working copy is used instead.
2487  *
2488  * Return 1 if the files differ on these data.
2489  */
2490 
2491 int
2492 special_file_mismatch (finfo, rev1, rev2)
2493     struct file_info *finfo;
2494     char *rev1;
2495     char *rev2;
2496 {
2497 #ifdef PRESERVE_PERMISSIONS_SUPPORT
2498     struct stat sb;
2499     RCSVers *vp;
2500     Node *n;
2501     uid_t rev1_uid, rev2_uid;
2502     gid_t rev1_gid, rev2_gid;
2503     mode_t rev1_mode, rev2_mode;
2504     unsigned long dev_long;
2505     dev_t rev1_dev, rev2_dev;
2506     char *rev1_symlink = NULL;
2507     char *rev2_symlink = NULL;
2508     char *rev1_hardlinks = NULL;
2509     char *rev2_hardlinks = NULL;
2510     int check_uids, check_gids, check_modes;
2511     int result;
2512 
2513     /* If we don't care about special file info, then
2514        don't report a mismatch in any case. */
2515     if (!preserve_perms)
2516 	return 0;
2517 
2518     /* When special_file_mismatch is called from No_Difference, the
2519        RCS file has been only partially parsed.  We must read the
2520        delta tree in order to compare special file info recorded in
2521        the delta nodes.  (I think this is safe. -twp) */
2522     if (finfo->rcs->flags & PARTIAL)
2523 	RCS_reparsercsfile (finfo->rcs, NULL, NULL);
2524 
2525     check_uids = check_gids = check_modes = 1;
2526 
2527     /* Obtain file information for REV1.  If this is null, then stat
2528        finfo->file and use that info. */
2529     /* If a revision does not know anything about its status,
2530        then presumably it doesn't matter, and indicates no conflict. */
2531 
2532     if (rev1 == NULL)
2533     {
2534 	if (islink (finfo->file))
2535 	    rev1_symlink = xreadlink (finfo->file);
2536 	else
2537 	{
2538 	    if (CVS_LSTAT (finfo->file, &sb) < 0)
2539 		error (1, errno, "could not get file information for %s",
2540 		       finfo->file);
2541 	    rev1_uid = sb.st_uid;
2542 	    rev1_gid = sb.st_gid;
2543 	    rev1_mode = sb.st_mode;
2544 	    if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
2545 		rev1_dev = sb.st_rdev;
2546 	}
2547 	rev1_hardlinks = list_files_linked_to (finfo->file);
2548     }
2549     else
2550     {
2551 	n = findnode (finfo->rcs->versions, rev1);
2552 	vp = (RCSVers *) n->data;
2553 
2554 	n = findnode (vp->other_delta, "symlink");
2555 	if (n != NULL)
2556 	    rev1_symlink = xstrdup (n->data);
2557 	else
2558 	{
2559 	    n = findnode (vp->other_delta, "owner");
2560 	    if (n == NULL)
2561 		check_uids = 0;	/* don't care */
2562 	    else
2563 		rev1_uid = strtoul (n->data, NULL, 10);
2564 
2565 	    n = findnode (vp->other_delta, "group");
2566 	    if (n == NULL)
2567 		check_gids = 0;	/* don't care */
2568 	    else
2569 		rev1_gid = strtoul (n->data, NULL, 10);
2570 
2571 	    n = findnode (vp->other_delta, "permissions");
2572 	    if (n == NULL)
2573 		check_modes = 0;	/* don't care */
2574 	    else
2575 		rev1_mode = strtoul (n->data, NULL, 8);
2576 
2577 	    n = findnode (vp->other_delta, "special");
2578 	    if (n == NULL)
2579 		rev1_mode |= S_IFREG;
2580 	    else
2581 	    {
2582 		/* If the size of `ftype' changes, fix the sscanf call also */
2583 		char ftype[16+1];
2584 		if (sscanf (n->data, "%16s %lu", ftype,
2585 			    &dev_long) < 2)
2586 		    error (1, 0, "%s:%s has bad `special' newphrase %s",
2587 			   finfo->file, rev1, n->data);
2588 		rev1_dev = dev_long;
2589 		if (strcmp (ftype, "character") == 0)
2590 		    rev1_mode |= S_IFCHR;
2591 		else if (strcmp (ftype, "block") == 0)
2592 		    rev1_mode |= S_IFBLK;
2593 		else
2594 		    error (0, 0, "%s:%s unknown file type `%s'",
2595 			   finfo->file, rev1, ftype);
2596 	    }
2597 
2598 	    n = findnode (vp->other_delta, "hardlinks");
2599 	    if (n == NULL)
2600 		rev1_hardlinks = xstrdup ("");
2601 	    else
2602 		rev1_hardlinks = xstrdup (n->data);
2603 	}
2604     }
2605 
2606     /* Obtain file information for REV2. */
2607     if (rev2 == NULL)
2608     {
2609 	if (islink (finfo->file))
2610 	    rev2_symlink = xreadlink (finfo->file);
2611 	else
2612 	{
2613 	    if (CVS_LSTAT (finfo->file, &sb) < 0)
2614 		error (1, errno, "could not get file information for %s",
2615 		       finfo->file);
2616 	    rev2_uid = sb.st_uid;
2617 	    rev2_gid = sb.st_gid;
2618 	    rev2_mode = sb.st_mode;
2619 	    if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
2620 		rev2_dev = sb.st_rdev;
2621 	}
2622 	rev2_hardlinks = list_files_linked_to (finfo->file);
2623     }
2624     else
2625     {
2626 	n = findnode (finfo->rcs->versions, rev2);
2627 	vp = (RCSVers *) n->data;
2628 
2629 	n = findnode (vp->other_delta, "symlink");
2630 	if (n != NULL)
2631 	    rev2_symlink = xstrdup (n->data);
2632 	else
2633 	{
2634 	    n = findnode (vp->other_delta, "owner");
2635 	    if (n == NULL)
2636 		check_uids = 0;	/* don't care */
2637 	    else
2638 		rev2_uid = strtoul (n->data, NULL, 10);
2639 
2640 	    n = findnode (vp->other_delta, "group");
2641 	    if (n == NULL)
2642 		check_gids = 0;	/* don't care */
2643 	    else
2644 		rev2_gid = strtoul (n->data, NULL, 10);
2645 
2646 	    n = findnode (vp->other_delta, "permissions");
2647 	    if (n == NULL)
2648 		check_modes = 0;	/* don't care */
2649 	    else
2650 		rev2_mode = strtoul (n->data, NULL, 8);
2651 
2652 	    n = findnode (vp->other_delta, "special");
2653 	    if (n == NULL)
2654 		rev2_mode |= S_IFREG;
2655 	    else
2656 	    {
2657 		/* If the size of `ftype' changes, fix the sscanf call also */
2658 		char ftype[16+1];
2659 		if (sscanf (n->data, "%16s %lu", ftype,
2660 			    &dev_long) < 2)
2661 		    error (1, 0, "%s:%s has bad `special' newphrase %s",
2662 			   finfo->file, rev2, n->data);
2663 		rev2_dev = dev_long;
2664 		if (strcmp (ftype, "character") == 0)
2665 		    rev2_mode |= S_IFCHR;
2666 		else if (strcmp (ftype, "block") == 0)
2667 		    rev2_mode |= S_IFBLK;
2668 		else
2669 		    error (0, 0, "%s:%s unknown file type `%s'",
2670 			   finfo->file, rev2, ftype);
2671 	    }
2672 
2673 	    n = findnode (vp->other_delta, "hardlinks");
2674 	    if (n == NULL)
2675 		rev2_hardlinks = xstrdup ("");
2676 	    else
2677 		rev2_hardlinks = xstrdup (n->data);
2678 	}
2679     }
2680 
2681     /* Check the user/group ownerships and file permissions, printing
2682        an error for each mismatch found.  Return 0 if all characteristics
2683        matched, and 1 otherwise. */
2684 
2685     result = 0;
2686 
2687     /* Compare symlinks first, since symlinks are simpler (don't have
2688        any other characteristics). */
2689     if (rev1_symlink != NULL && rev2_symlink == NULL)
2690     {
2691 	error (0, 0, "%s is a symbolic link",
2692 	       (rev1 == NULL ? "working file" : rev1));
2693 	result = 1;
2694     }
2695     else if (rev1_symlink == NULL && rev2_symlink != NULL)
2696     {
2697 	error (0, 0, "%s is a symbolic link",
2698 	       (rev2 == NULL ? "working file" : rev2));
2699 	result = 1;
2700     }
2701     else if (rev1_symlink != NULL)
2702 	result = (strcmp (rev1_symlink, rev2_symlink) == 0);
2703     else
2704     {
2705 	/* Compare user ownership. */
2706 	if (check_uids && rev1_uid != rev2_uid)
2707 	{
2708 	    error (0, 0, "%s: owner mismatch between %s and %s",
2709 		   finfo->file,
2710 		   (rev1 == NULL ? "working file" : rev1),
2711 		   (rev2 == NULL ? "working file" : rev2));
2712 	    result = 1;
2713 	}
2714 
2715 	/* Compare group ownership. */
2716 	if (check_gids && rev1_gid != rev2_gid)
2717 	{
2718 	    error (0, 0, "%s: group mismatch between %s and %s",
2719 		   finfo->file,
2720 		   (rev1 == NULL ? "working file" : rev1),
2721 		   (rev2 == NULL ? "working file" : rev2));
2722 	    result = 1;
2723 	}
2724 
2725 	/* Compare permissions. */
2726 	if (check_modes &&
2727 	    (rev1_mode & 07777) != (rev2_mode & 07777))
2728 	{
2729 	    error (0, 0, "%s: permission mismatch between %s and %s",
2730 		   finfo->file,
2731 		   (rev1 == NULL ? "working file" : rev1),
2732 		   (rev2 == NULL ? "working file" : rev2));
2733 	    result = 1;
2734 	}
2735 
2736 	/* Compare device file characteristics. */
2737 	if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT))
2738 	{
2739 	    error (0, 0, "%s: %s and %s are different file types",
2740 		   finfo->file,
2741 		   (rev1 == NULL ? "working file" : rev1),
2742 		   (rev2 == NULL ? "working file" : rev2));
2743 	    result = 1;
2744 	}
2745 	else if (S_ISBLK (rev1_mode))
2746 	{
2747 	    if (rev1_dev != rev2_dev)
2748 	    {
2749 		error (0, 0, "%s: device numbers of %s and %s do not match",
2750 		       finfo->file,
2751 		       (rev1 == NULL ? "working file" : rev1),
2752 		       (rev2 == NULL ? "working file" : rev2));
2753 		result = 1;
2754 	    }
2755 	}
2756 
2757 	/* Compare hard links. */
2758 	if (strcmp (rev1_hardlinks, rev2_hardlinks) != 0)
2759 	{
2760 	    error (0, 0, "%s: hard linkage of %s and %s do not match",
2761 		   finfo->file,
2762 		   (rev1 == NULL ? "working file" : rev1),
2763 		   (rev2 == NULL ? "working file" : rev2));
2764 	    result = 1;
2765 	}
2766     }
2767 
2768     if (rev1_symlink != NULL)
2769 	free (rev1_symlink);
2770     if (rev2_symlink != NULL)
2771 	free (rev2_symlink);
2772     if (rev1_hardlinks != NULL)
2773 	free (rev1_hardlinks);
2774     if (rev2_hardlinks != NULL)
2775 	free (rev2_hardlinks);
2776 
2777     return result;
2778 #else
2779     return 0;
2780 #endif
2781 }
2782 
2783 int
2784 joining ()
2785 {
2786     return (join_rev1 != NULL);
2787 }
2788