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