xref: /dragonfly/contrib/cvs-1.12/src/checkout.c (revision 0db87cb7)
1 /*
2  * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
3  *
4  * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5  *                                  and others.
6  *
7  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8  * Portions Copyright (C) 1989-1992, Brian Berliner
9  *
10  * You may distribute under the terms of the GNU General Public License as
11  * specified in the README file that comes with the CVS source distribution.
12  *
13  * Create Version
14  *
15  * "checkout" creates a "version" of an RCS repository.  This version is owned
16  * totally by the user and is actually an independent copy, to be dealt with
17  * as seen fit.  Once "checkout" has been called in a given directory, it
18  * never needs to be called again.  The user can keep up-to-date by calling
19  * "update" when he feels like it; this will supply him with a merge of his
20  * own modifications and the changes made in the RCS original.  See "update"
21  * for details.
22  *
23  * "checkout" can be given a list of directories or files to be updated and in
24  * the case of a directory, will recursivley create any sub-directories that
25  * exist in the repository.
26  *
27  * When the user is satisfied with his own modifications, the present version
28  * can be committed by "commit"; this keeps the present version in tact,
29  * usually.
30  *
31  * The call is cvs checkout [options] <module-name>...
32  *
33  * "checkout" creates a directory ./CVS, in which it keeps its administration,
34  * in two files, Repository and Entries. The first contains the name of the
35  * repository.  The second contains one line for each registered file,
36  * consisting of the version number it derives from, its time stamp at
37  * derivation time and its name.  Both files are normal files and can be
38  * edited by the user, if necessary (when the repository is moved, e.g.)
39  */
40 
41 #include "cvs.h"
42 
43 static char *findslash (char *start, char *p);
44 static int checkout_proc (int argc, char **argv, char *where,
45 		          char *mwhere, char *mfile, int shorten,
46 		          int local_specified, char *omodule,
47 		          char *msg);
48 
49 static const char *const checkout_usage[] =
50 {
51     "Usage:\n  %s %s [-ANPRcflnps] [-r rev] [-D date] [-d dir]\n",
52     "    [-j rev1] [-j rev2] [-k kopt] modules...\n",
53     "\t-A\tReset any sticky tags/date/kopts.\n",
54     "\t-N\tDon't shorten module paths if -d specified.\n",
55     "\t-P\tPrune empty directories.\n",
56     "\t-R\tProcess directories recursively.\n",
57     "\t-c\t\"cat\" the module database.\n",
58     "\t-f\tForce a head revision match if tag/date not found.\n",
59     "\t-l\tLocal directory only, not recursive\n",
60     "\t-n\tDo not run module program (if any).\n",
61     "\t-p\tCheck out files to standard output (avoids stickiness).\n",
62     "\t-s\tLike -c, but include module status.\n",
63     "\t-r rev\tCheck out revision or tag. (implies -P) (is sticky)\n",
64     "\t-D date\tCheck out revisions as of date. (implies -P) (is sticky)\n",
65     "\t-d dir\tCheck out into dir instead of module name.\n",
66     "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
67     "\t-j rev\tMerge in changes made between current revision and rev.\n",
68     "(Specify the --help global option for a list of other help options)\n",
69     NULL
70 };
71 
72 static const char *const export_usage[] =
73 {
74     "Usage: %s %s [-NRfln] [-r tag] [-D date] [-d dir] [-k kopt] module...\n",
75     "\t-N\tDon't shorten module paths if -d specified.\n",
76     "\t-f\tForce a head revision match if tag/date not found.\n",
77     "\t-l\tLocal directory only, not recursive\n",
78     "\t-R\tProcess directories recursively (default).\n",
79     "\t-n\tDo not run module program (if any).\n",
80     "\t-r tag\tExport tagged revisions.\n",
81     "\t-D date\tExport revisions as of date.\n",
82     "\t-d dir\tExport into dir instead of module name.\n",
83     "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
84     "(Specify the --help global option for a list of other help options)\n",
85     NULL
86 };
87 
88 static int checkout_prune_dirs;
89 static int force_tag_match;
90 static int pipeout;
91 static int aflag;
92 static char *options;
93 static char *tag;
94 static bool tag_validated;
95 static char *date;
96 static char *join_rev1, *join_date1;
97 static char *join_rev2, *join_date2;
98 static bool join_tags_validated;
99 static char *preload_update_dir;
100 static char *history_name;
101 static enum mtype m_type;
102 
103 int
104 checkout (int argc, char **argv)
105 {
106     int i;
107     int c;
108     DBM *db;
109     int cat = 0, err = 0, status = 0;
110     int run_module_prog = 1;
111     int local = 0;
112     int shorten = -1;
113     char *where = NULL;
114     const char *valid_options;
115     const char *const *valid_usage;
116     char *join_orig1, *join_orig2;
117 
118     /* initialize static options */
119     force_tag_match = 1;
120     if (options)
121     {
122 	free (options);
123 	options = NULL;
124     }
125     tag = date = join_rev1 = join_date1 = join_rev2 = join_date2 =
126 	  join_orig1 = join_orig2 = preload_update_dir = NULL;
127     history_name = NULL;
128     tag_validated = join_tags_validated = false;
129 
130 
131     /*
132      * A smaller subset of options are allowed for the export command, which
133      * is essentially like checkout, except that it hard-codes certain
134      * options to be default (like -kv) and takes care to remove the CVS
135      * directory when it has done its duty
136      */
137     if (strcmp (cvs_cmd_name, "export") == 0)
138     {
139         m_type = EXPORT;
140 	valid_options = "+Nnk:d:flRQqr:D:";
141 	valid_usage = export_usage;
142     }
143     else
144     {
145         m_type = CHECKOUT;
146 	valid_options = "+ANnk:d:flRpQqcsr:D:j:P";
147 	valid_usage = checkout_usage;
148     }
149 
150     if (argc == -1)
151 	usage (valid_usage);
152 
153     ign_setup ();
154     wrap_setup ();
155 
156     optind = 0;
157     while ((c = getopt (argc, argv, valid_options)) != -1)
158     {
159 	switch (c)
160 	{
161 	    case 'A':
162 		aflag = 1;
163 		break;
164 	    case 'N':
165 		shorten = 0;
166 		break;
167 	    case 'k':
168 		if (options)
169 		    free (options);
170 		options = RCS_check_kflag (optarg);
171 		break;
172 	    case 'n':
173 		run_module_prog = 0;
174 		break;
175 	    case 'Q':
176 	    case 'q':
177 		/* The CVS 1.5 client sends these options (in addition to
178 		   Global_option requests), so we must ignore them.  */
179 		if (!server_active)
180 		    error (1, 0,
181 			   "-q or -Q must be specified before \"%s\"",
182 			   cvs_cmd_name);
183 		break;
184 	    case 'l':
185 		local = 1;
186 		break;
187 	    case 'R':
188 		local = 0;
189 		break;
190 	    case 'P':
191 		checkout_prune_dirs = 1;
192 		break;
193 	    case 'p':
194 		pipeout = 1;
195 		run_module_prog = 0;	/* don't run module prog when piping */
196 		noexec = 1;		/* so no locks will be created */
197 		break;
198 	    case 'c':
199 		cat = 1;
200 		break;
201 	    case 'd':
202 		where = optarg;
203 		if (shorten == -1)
204 		    shorten = 1;
205 		break;
206 	    case 's':
207 		cat = status = 1;
208 		break;
209 	    case 'f':
210 		force_tag_match = 0;
211 		break;
212 	    case 'r':
213 		parse_tagdate (&tag, &date, optarg);
214 		checkout_prune_dirs = 1;
215 		break;
216 	    case 'D':
217 		if (date) free (date);
218 		date = Make_Date (optarg);
219 		checkout_prune_dirs = 1;
220 		break;
221 	    case 'j':
222 		if (join_rev2 || join_date2)
223 		    error (1, 0, "only two -j options can be specified");
224 		if (join_rev1 || join_date1)
225 		{
226 		    if (join_orig2) free (join_orig2);
227 		    join_orig2 = xstrdup (optarg);
228 		    parse_tagdate (&join_rev2, &join_date2, optarg);
229 		}
230 		else
231 		{
232 		    if (join_orig1) free (join_orig1);
233 		    join_orig1 = xstrdup (optarg);
234 		    parse_tagdate (&join_rev1, &join_date1, optarg);
235 		}
236 		break;
237 	    case '?':
238 	    default:
239 		usage (valid_usage);
240 		break;
241 	}
242     }
243     argc -= optind;
244     argv += optind;
245 
246     if (shorten == -1)
247 	shorten = 0;
248 
249     if (cat && argc != 0)
250 	error (1, 0, "-c and -s must not get any arguments");
251 
252     if (!cat && argc == 0)
253 	error (1, 0, "must specify at least one module or directory");
254 
255     if (where && pipeout)
256 	error (1, 0, "-d and -p are mutually exclusive");
257 
258     if (m_type == EXPORT)
259     {
260 	if (!tag && !date)
261 	    error (1, 0, "must specify a tag or date");
262 
263 	if (tag && isdigit (tag[0]))
264 	    error (1, 0, "tag `%s' must be a symbolic tag", tag);
265     }
266 
267 #ifdef SERVER_SUPPORT
268     if (server_active && where != NULL)
269     {
270 	server_pathname_check (where);
271     }
272 #endif
273 
274     if (!cat && !pipeout && !safe_location (where))
275     {
276         error (1, 0, "Cannot check out files into the repository itself");
277     }
278 
279 #ifdef CLIENT_SUPPORT
280     if (current_parsed_root->isremote)
281     {
282 	int expand_modules;
283 
284 	start_server ();
285 
286 	ign_setup ();
287 
288 	expand_modules = (!cat && !pipeout
289 			  && supported_request ("expand-modules"));
290 
291 	if (expand_modules)
292 	{
293 	    /* This is done here because we need to read responses
294                from the server before we send the command checkout or
295                export files. */
296 
297 	    client_expand_modules (argc, argv, local);
298 	}
299 
300 	if (!run_module_prog)
301 	    send_arg ("-n");
302 	if (local)
303 	    send_arg ("-l");
304 	if (pipeout)
305 	    send_arg ("-p");
306 	if (!force_tag_match)
307 	    send_arg ("-f");
308 	if (aflag)
309 	    send_arg ("-A");
310 	if (!shorten)
311 	    send_arg ("-N");
312 	if (checkout_prune_dirs && m_type == CHECKOUT)
313 	    send_arg ("-P");
314 	client_prune_dirs = checkout_prune_dirs;
315 	if (cat && !status)
316 	    send_arg ("-c");
317 	if (where != NULL)
318 	    option_with_arg ("-d", where);
319 	if (status)
320 	    send_arg ("-s");
321 	if (options != NULL && options[0] != '\0')
322 	    send_arg (options);
323 	option_with_arg ("-r", tag);
324 	if (date)
325 	    client_senddate (date);
326 	if (join_orig1)
327 	    option_with_arg ("-j", join_orig1);
328 	if (join_orig2)
329 	    option_with_arg ("-j", join_orig2);
330 	send_arg ("--");
331 
332 	if (expand_modules)
333 	{
334 	    client_send_expansions (local, where, 1);
335 	}
336 	else
337 	{
338 	    int i;
339 	    for (i = 0; i < argc; ++i)
340 		send_arg (argv[i]);
341 	    client_nonexpanded_setup ();
342 	}
343 
344 	send_to_server (m_type == EXPORT ? "export\012" : "co\012", 0);
345 	return get_responses_and_close ();
346     }
347 #endif /* CLIENT_SUPPORT */
348 
349     if (cat)
350     {
351 	cat_module (status);
352 	if (options)
353 	{
354 	    free (options);
355 	    options = NULL;
356 	}
357 	return 0;
358     }
359     db = open_module ();
360 
361 
362     /* If we've specified something like "cvs co foo/bar baz/quux"
363        don't try to shorten names.  There are a few cases in which we
364        could shorten (e.g. "cvs co foo/bar foo/baz"), but we don't
365        handle those yet.  Better to have an extra directory created
366        than the thing checked out under the wrong directory name. */
367 
368     if (argc > 1)
369 	shorten = 0;
370 
371 
372     /* If we will be calling history_write, work out the name to pass
373        it.  */
374     if (!pipeout)
375     {
376 	if (!date)
377 	    history_name = tag;
378 	else if (!tag)
379 	    history_name = date;
380 	else
381 	    history_name = Xasprintf ("%s:%s", tag, date);
382     }
383 
384 
385     for (i = 0; i < argc; i++)
386 	err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
387 			  where, shorten, local, run_module_prog, !pipeout,
388 			  NULL);
389     close_module (db);
390     if (options)
391     {
392 	free (options);
393 	options = NULL;
394     }
395     if (history_name != tag && history_name != date && history_name != NULL)
396 	free (history_name);
397     return err;
398 }
399 
400 
401 
402 /* FIXME: This is and emptydir_name are in checkout.c for historical
403    reasons, probably want to move them.  */
404 
405 /* int
406  * safe_location ( char *where )
407  *
408  * Return true if where is a safe destination for a checkout.
409  *
410  * INPUTS
411  *  where	The requested destination directory.
412  *
413  * GLOBALS
414  *  current_parsed_root->directory
415  *  current_parsed_root->isremote
416  *  		Used to locate our CVSROOT.
417  *
418  * RETURNS
419  *  true	If we are running in client mode or if where is not located
420  *  		within the CVSROOT.
421  *  false	Otherwise.
422  *
423  * ERRORS
424  *  Exits with a fatal error message when various events occur, such as not
425  *  being able to resolve a path or failing ot chdir to a path.
426  */
427 int
428 safe_location (char *where)
429 {
430     char *current;
431     char *hardpath;
432     size_t hardpath_len;
433     int retval;
434 
435     TRACE (TRACE_FUNCTION, "safe_location( where=%s )",
436            where ? where : "(null)");
437 
438     /* Don't compare remote CVSROOTs to our destination directory. */
439     if (current_parsed_root->isremote) return 1;
440 
441     /* set current - even if where is set we'll need to cd back... */
442     current = xgetcwd ();
443     if (current == NULL)
444 	error (1, errno, "could not get working directory");
445 
446     hardpath = xcanonicalize_file_name (current_parsed_root->directory);
447 
448     /* if where is set, set current to as much of where as exists,
449      * or fail.
450      */
451     if (where != NULL)
452     {
453 	char *where_this_pass = xstrdup (where);
454 	while (1)
455 	{
456 	    if (CVS_CHDIR (where_this_pass) != -1)
457 	    {
458 		/* where */
459 		free (where_this_pass);
460 		where_this_pass = xgetcwd ();
461 		if (where_this_pass == NULL)
462 		    error (1, errno, "could not get working directory");
463 
464 		if (CVS_CHDIR (current) == -1)
465 		    error (1, errno,
466 			   "could not restore directory to `%s'", current);
467 
468 		free (current);
469 		current = where_this_pass;
470 		break;
471 	    }
472 	    else if (errno == ENOENT)
473 	    {
474 		/* where_this_pass - last_component (where_this_pass) */
475 		char *parent;
476 
477 		/* It's okay to cast out the const below since we know we
478 		 * allocated where_this_pass and have control of it.
479 		 */
480 		if ((parent = (char *)last_component (where_this_pass))
481 		        != where_this_pass)
482 		{
483 		    /* strip the last_component */
484 		    parent[-1] = '\0';
485 		    /* continue */
486 		}
487 		else
488 		{
489 		    /* ERRNO == ENOENT
490 		     *   && last_component (where_this_pass) == where_this_pass
491 		     * means we've tried all the parent diretories and not one
492 		     * exists, so there is no need to test any portion of where
493 		     * - it is all being created.
494 		     */
495 		    free (where_this_pass);
496 		    break;
497 		}
498 	    }
499 	    else
500 		/* we don't know how to handle other errors, so fail */
501 		error (1, errno, "\
502 could not change directory to requested checkout directory `%s'",
503 		       where_this_pass);
504 	} /* while (1) */
505     } /* where != NULL */
506 
507     hardpath_len = strlen (hardpath);
508     if (strlen (current) >= hardpath_len
509 	&& strncmp (current, hardpath, hardpath_len) == 0)
510     {
511 	if (/* Current is a subdirectory of hardpath.  */
512 	    current[hardpath_len] == '/'
513 
514 	    /* Current is hardpath itself.  */
515 	    || current[hardpath_len] == '\0')
516 	    retval = 0;
517 	else
518 	    /* It isn't a problem.  For example, current is
519 	       "/foo/cvsroot-bar" and hardpath is "/foo/cvsroot".  */
520 	    retval = 1;
521     }
522     else
523 	retval = 1;
524     free (current);
525     free (hardpath);
526     return retval;
527 }
528 
529 
530 
531 struct dir_to_build
532 {
533     /* What to put in CVS/Repository.  */
534     char *repository;
535     /* The path to the directory.  */
536     char *dirpath;
537 
538     struct dir_to_build *next;
539 };
540 
541 
542 
543 static int build_dirs_and_chdir (struct dir_to_build *list,
544 					int sticky);
545 
546 static void
547 build_one_dir (char *repository, char *dirpath, int sticky)
548 {
549     FILE *fp;
550 
551     if (isfile (CVSADM))
552     {
553 	if (m_type == EXPORT)
554 	    error (1, 0, "cannot export into a working directory");
555     }
556     else if (m_type == CHECKOUT)
557     {
558 	/* I suspect that this check could be omitted.  */
559 	if (!isdir (repository))
560 	    error (1, 0, "there is no repository %s", repository);
561 
562 	if (Create_Admin (".", dirpath, repository,
563 			  sticky ? tag : NULL,
564 			  sticky ? date : NULL,
565 
566 			  /* FIXME?  This is a guess.  If it is important
567 			     for nonbranch to be set correctly here I
568 			     think we need to write it one way now and
569 			     then rewrite it later via WriteTag, once
570 			     we've had a chance to call RCS_nodeisbranch
571 			     on each file.  */
572 			  0, 1, 1))
573 	    return;
574 
575 	if (!noexec)
576 	{
577 	    fp = xfopen (CVSADM_ENTSTAT, "w+");
578 	    if (fclose (fp) == EOF)
579 		error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
580 #ifdef SERVER_SUPPORT
581 	    if (server_active)
582 		server_set_entstat (dirpath, repository);
583 #endif
584 	}
585     }
586 }
587 
588 
589 
590 /*
591  * process_module calls us back here so we do the actual checkout stuff
592  */
593 /* ARGSUSED */
594 static int
595 checkout_proc (int argc, char **argv, char *where_orig, char *mwhere,
596 	       char *mfile, int shorten, int local_specified, char *omodule,
597 	       char *msg)
598 {
599     char *myargv[2];
600     int err = 0;
601     int which;
602     char *cp;
603     char *repository;
604     char *oldupdate = NULL;
605     char *where;
606 
607     TRACE (TRACE_FUNCTION, "checkout_proc (%s, %s, %s, %d, %d, %s, %s)\n",
608 	   where_orig ? where_orig : "(null)",
609 	   mwhere ? mwhere : "(null)",
610 	   mfile ? mfile : "(null)",
611 	   shorten, local_specified,
612 	   omodule ? omodule : "(null)",
613 	   msg ? msg : "(null)"
614 	  );
615 
616     /*
617      * OK, so we're doing the checkout! Our args are as follows:
618      *  argc,argv contain either dir or dir followed by a list of files
619      *  where contains where to put it (if supplied by checkout)
620      *  mwhere contains the module name or -d from module file
621      *  mfile says do only that part of the module
622      *  shorten = 1 says shorten as much as possible
623      *  omodule is the original arg to do_module()
624      */
625 
626     /* Set up the repository (maybe) for the bottom directory.
627        Allocate more space than we need so we don't need to keep
628        reallocating this string. */
629     repository = xmalloc (strlen (current_parsed_root->directory)
630 			  + strlen (argv[0])
631 			  + (mfile == NULL ? 0 : strlen (mfile))
632 			  + 10);
633     (void) sprintf (repository, "%s/%s",
634                     current_parsed_root->directory, argv[0]);
635     Sanitize_Repository_Name (repository);
636 
637 
638     /* save the original value of preload_update_dir */
639     if (preload_update_dir != NULL)
640 	oldupdate = xstrdup (preload_update_dir);
641 
642 
643     /* Allocate space and set up the where variable.  We allocate more
644        space than necessary here so that we don't have to keep
645        reallocaing it later on. */
646 
647     where = xmalloc (strlen (argv[0])
648 		     + (mfile == NULL ? 0 : strlen (mfile))
649 		     + (mwhere == NULL ? 0 : strlen (mwhere))
650 		     + (where_orig == NULL ? 0 : strlen (where_orig))
651 		     + 10);
652 
653     /* Yes, this could be written in a less verbose way, but in this
654        form it is quite easy to read.
655 
656        FIXME?  The following code that sets should probably be moved
657        to do_module in modules.c, since there is similar code in
658        patch.c and rtag.c. */
659 
660     if (shorten)
661     {
662 	if (where_orig != NULL)
663 	{
664 	    /* If the user has specified a directory with `-d' on the
665 	       command line, use it preferentially, even over the `-d'
666 	       flag in the modules file. */
667 
668 	    (void) strcpy (where, where_orig);
669 	}
670 	else if (mwhere != NULL)
671 	{
672 	    /* Second preference is the value of mwhere, which is from
673 	       the `-d' flag in the modules file. */
674 
675 	    (void) strcpy (where, mwhere);
676 	}
677 	else
678 	{
679 	    /* Third preference is the directory specified in argv[0]
680 	       which is this module'e directory in the repository. */
681 
682 	    (void) strcpy (where, argv[0]);
683 	}
684     }
685     else
686     {
687 	/* Use the same preferences here, bug don't shorten -- that
688            is, tack on where_orig if it exists. */
689 
690 	*where = '\0';
691 
692 	if (where_orig != NULL)
693 	{
694 	    (void) strcat (where, where_orig);
695 	    (void) strcat (where, "/");
696 	}
697 
698 	/* If the -d flag in the modules file specified an absolute
699            directory, let the user override it with the command-line
700            -d option. */
701 
702 	if (mwhere && !ISABSOLUTE (mwhere))
703 	    (void) strcat (where, mwhere);
704 	else
705 	    (void) strcat (where, argv[0]);
706     }
707     strip_trailing_slashes (where); /* necessary? */
708 
709 
710     /* At this point, the user may have asked for a single file or
711        directory from within a module.  In that case, we should modify
712        where, repository, and argv as appropriate. */
713 
714     if (mfile != NULL)
715     {
716 	/* The mfile variable can have one or more path elements.  If
717 	   it has multiple elements, we want to tack those onto both
718 	   repository and where.  The last element may refer to either
719 	   a file or directory.  Here's what to do:
720 
721 	   it refers to a directory
722 	     -> simply tack it on to where and repository
723 	   it refers to a file
724 	     -> munge argv to contain `basename mfile` */
725 
726 	char *cp;
727 	char *path;
728 
729 
730 	/* Paranoia check. */
731 
732 	if (mfile[strlen (mfile) - 1] == '/')
733 	{
734 	    error (0, 0, "checkout_proc: trailing slash on mfile (%s)!",
735 		   mfile);
736 	}
737 
738 
739 	/* Does mfile have multiple path elements? */
740 
741 	cp = strrchr (mfile, '/');
742 	if (cp != NULL)
743 	{
744 	    *cp = '\0';
745 	    (void) strcat (repository, "/");
746 	    (void) strcat (repository, mfile);
747 	    (void) strcat (where, "/");
748 	    (void) strcat (where, mfile);
749 	    mfile = cp + 1;
750 	}
751 
752 
753 	/* Now mfile is a single path element. */
754 
755 	path = Xasprintf ("%s/%s", repository, mfile);
756 	if (isdir (path))
757 	{
758 	    /* It's a directory, so tack it on to repository and
759                where, as we did above. */
760 
761 	    (void) strcat (repository, "/");
762 	    (void) strcat (repository, mfile);
763 	    (void) strcat (where, "/");
764 	    (void) strcat (where, mfile);
765 	}
766 	else
767 	{
768 	    /* It's a file, which means we have to screw around with
769                argv. */
770 	    myargv[0] = argv[0];
771 	    myargv[1] = mfile;
772 	    argc = 2;
773 	    argv = myargv;
774 	}
775 	free (path);
776     }
777 
778     if (preload_update_dir != NULL)
779     {
780 	preload_update_dir =
781 	    xrealloc (preload_update_dir,
782 		      strlen (preload_update_dir) + strlen (where) + 5);
783 	strcat (preload_update_dir, "/");
784 	strcat (preload_update_dir, where);
785     }
786     else
787 	preload_update_dir = xstrdup (where);
788 
789     /*
790      * At this point, where is the directory we want to build, repository is
791      * the repository for the lowest level of the path.
792      *
793      * We need to tell build_dirs not only the path we want it to
794      * build, but also the repositories we want it to populate the
795      * path with.  To accomplish this, we walk the path backwards, one
796      * pathname component at a time, constucting a linked list of
797      * struct dir_to_build.
798      */
799 
800     /*
801      * If we are sending everything to stdout, we can skip a whole bunch of
802      * work from here
803      */
804     if (!pipeout)
805     {
806 	struct dir_to_build *head;
807 	char *reposcopy;
808 
809 	if (strncmp (repository, current_parsed_root->directory,
810 		     strlen (current_parsed_root->directory)) != 0)
811 	    error (1, 0, "\
812 internal error: %s doesn't start with %s in checkout_proc",
813 		   repository, current_parsed_root->directory);
814 
815 	/* We always create at least one directory, which corresponds to
816 	   the entire strings for WHERE and REPOSITORY.  */
817 	head = xmalloc (sizeof (struct dir_to_build));
818 	/* Special marker to indicate that we don't want build_dirs_and_chdir
819 	   to create the CVSADM directory for us.  */
820 	head->repository = NULL;
821 	head->dirpath = xstrdup (where);
822 	head->next = NULL;
823 
824 	/* Make a copy of the repository name to play with. */
825 	reposcopy = xstrdup (repository);
826 
827 	/* FIXME: this should be written in terms of last_component
828 	   instead of hardcoding '/'.  This presumably affects OS/2,
829 	   NT, &c, if the user specifies '\'.  Likewise for the call
830 	   to findslash.  */
831 	cp = where + strlen (where);
832 	while (cp > where)
833 	{
834 	    struct dir_to_build *new;
835 
836 	    cp = findslash (where, cp - 1);
837 	    if (cp == NULL)
838 		break;		/* we're done */
839 
840 	    new = xmalloc (sizeof (struct dir_to_build));
841 	    new->dirpath = xmalloc (strlen (where));
842 
843 	    /* If the user specified an absolute path for where, the
844                last path element we create should be the top-level
845                directory. */
846 
847 	    if (cp > where)
848 	    {
849 		strncpy (new->dirpath, where, cp - where);
850 		new->dirpath[cp - where] = '\0';
851 	    }
852 	    else
853 	    {
854 		/* where should always be at least one character long. */
855 		assert (where[0] != '\0');
856 		strcpy (new->dirpath, "/");
857 	    }
858 	    new->next = head;
859 	    head = new;
860 
861 	    /* Now figure out what repository directory to generate.
862                The most complete case would be something like this:
863 
864 	       The modules file contains
865 	         foo -d bar/baz quux
866 
867 	       The command issued was:
868 	         cvs co -d what/ever -N foo
869 
870 	       The results in the CVS/Repository files should be:
871 	         .     -> (don't touch CVS/Repository)
872 			  (I think this case might be buggy currently)
873 		 what  -> (don't touch CVS/Repository)
874 		 ever  -> .          (same as "cd what/ever; cvs co -N foo")
875 		 bar   -> Emptydir   (generated dir -- not in repos)
876 		 baz   -> quux       (finally!) */
877 
878 	    if (strcmp (reposcopy, current_parsed_root->directory) == 0)
879 	    {
880 		/* We can't walk up past CVSROOT.  Instead, the
881                    repository should be Emptydir. */
882 		new->repository = emptydir_name ();
883 	    }
884 	    else
885 	    {
886 		/* It's a directory in the repository! */
887 
888 		char *rp;
889 
890 		/* We'll always be below CVSROOT, but check for
891 		   paranoia's sake. */
892 		rp = strrchr (reposcopy, '/');
893 		if (rp == NULL)
894 		    error (1, 0,
895 			   "internal error: %s doesn't contain a slash",
896 			   reposcopy);
897 
898 		*rp = '\0';
899 
900 		if (strcmp (reposcopy, current_parsed_root->directory) == 0)
901 		{
902 		    /* Special case -- the repository name needs
903 		       to be "/path/to/repos/." (the trailing dot
904 		       is important).  We might be able to get rid
905 		       of this after the we check out the other
906 		       code that handles repository names. */
907 		    new-> repository = Xasprintf ("%s/.", reposcopy);
908 		}
909 		else
910 		    new->repository = xstrdup (reposcopy);
911 	    }
912 	}
913 
914 	/* clean up */
915 	free (reposcopy);
916 
917 	/* The top-level CVSADM directory should always be
918 	   current_parsed_root->directory.  Create it, but only if WHERE is
919 	   relative.  If WHERE is absolute, our current directory
920 	   may not have a thing to do with where the sources are
921 	   being checked out.  If it does, build_dirs_and_chdir
922 	   will take care of creating adm files here. */
923 	/* FIXME: checking where_is_absolute is a horrid kludge;
924 	   I suspect we probably can just skip the call to
925 	   build_one_dir whenever the -d command option was specified
926 	   to checkout.  */
927 
928 	if (!ISABSOLUTE (where) && config->top_level_admin
929 	    && m_type == CHECKOUT)
930 	{
931 	    /* It may be argued that we shouldn't set any sticky
932 	       bits for the top-level repository.  FIXME?  */
933 	    build_one_dir (current_parsed_root->directory, ".", argc <= 1);
934 
935 #ifdef SERVER_SUPPORT
936 	    /* We _always_ want to have a top-level admin
937 	       directory.  If we're running in client/server mode,
938 	       send a "Clear-static-directory" command to make
939 	       sure it is created on the client side.  (See 5.10
940 	       in cvsclient.dvi to convince yourself that this is
941 	       OK.)  If this is a duplicate command being sent, it
942 	       will be ignored on the client side.  */
943 
944 	    if (server_active)
945 		server_clear_entstat (".", current_parsed_root->directory);
946 #endif
947 	}
948 
949 
950 	/* Build dirs on the path if necessary and leave us in the
951 	   bottom directory (where if where was specified) doesn't
952 	   contain a CVS subdir yet, but all the others contain
953 	   CVS and Entries.Static files */
954 
955 	if (build_dirs_and_chdir (head, argc <= 1) != 0)
956 	{
957 	    error (0, 0, "ignoring module %s", omodule);
958 	    err = 1;
959 	    goto out;
960 	}
961 
962 	/* set up the repository (or make sure the old one matches) */
963 	if (!isfile (CVSADM))
964 	{
965 	    FILE *fp;
966 
967 	    if (!noexec && argc > 1)
968 	    {
969 		/* I'm not sure whether this check is redundant.  */
970 		if (!isdir (repository))
971 		    error (1, 0, "there is no repository %s", repository);
972 
973 		Create_Admin (".", preload_update_dir, repository,
974 			      NULL, NULL, 0, 0, m_type == CHECKOUT);
975 		fp = xfopen (CVSADM_ENTSTAT, "w+");
976 		if (fclose (fp) == EOF)
977 		    error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
978 #ifdef SERVER_SUPPORT
979 		if (server_active)
980 		    server_set_entstat (where, repository);
981 #endif
982 	    }
983 	    else
984 	    {
985 		/* I'm not sure whether this check is redundant.  */
986 		if (!isdir (repository))
987 		    error (1, 0, "there is no repository %s", repository);
988 
989 		Create_Admin (".", preload_update_dir, repository, tag, date,
990 
991 			      /* FIXME?  This is a guess.  If it is important
992 				 for nonbranch to be set correctly here I
993 				 think we need to write it one way now and
994 				 then rewrite it later via WriteTag, once
995 				 we've had a chance to call RCS_nodeisbranch
996 				 on each file.  */
997 			      0, 0, m_type == CHECKOUT);
998 	    }
999 	}
1000 	else
1001 	{
1002 	    char *repos;
1003 
1004 	    if (m_type == EXPORT)
1005 		error (1, 0, "cannot export into working directory");
1006 
1007 	    /* get the contents of the previously existing repository */
1008 	    repos = Name_Repository (NULL, preload_update_dir);
1009 	    if (fncmp (repository, repos) != 0)
1010 	    {
1011 		char *prepos = xstrdup (primary_root_inverse_translate (repos));
1012 		char *prepository =
1013 		    xstrdup (primary_root_inverse_translate (repository));
1014 		error (0, 0, "existing repository %s does not match %s",
1015 		       prepos, prepository);
1016 		error (0, 0, "ignoring module %s", omodule);
1017 		free (repos);
1018 		free (prepos);
1019 		free (prepository);
1020 		err = 1;
1021 		goto out;
1022 	    }
1023 	    free (repos);
1024 	}
1025     }
1026 
1027     /*
1028      * If we are going to be updating to stdout, we need to cd to the
1029      * repository directory so the recursion processor can use the current
1030      * directory as the place to find repository information
1031      */
1032     if (pipeout)
1033     {
1034 	if (CVS_CHDIR (repository) < 0)
1035 	{
1036 	    error (0, errno, "cannot chdir to %s", repository);
1037 	    err = 1;
1038 	    goto out;
1039 	}
1040 	which = W_REPOS;
1041 	if (tag && !tag_validated)
1042 	{
1043 	    tag_check_valid (tag, argc - 1, argv + 1, 0, aflag,
1044 			     repository, false);
1045 	    tag_validated = true;
1046 	}
1047     }
1048     else
1049     {
1050 	which = W_LOCAL | W_REPOS;
1051 	if (tag && !tag_validated)
1052 	{
1053 	    tag_check_valid (tag, argc - 1, argv + 1, 0, aflag,
1054 			     repository, false);
1055 	    tag_validated = true;
1056 	}
1057     }
1058 
1059     if (tag || date || join_rev1 || join_date2)
1060 	which |= W_ATTIC;
1061 
1062     if (!join_tags_validated)
1063     {
1064         if (join_rev1)
1065 	    tag_check_valid (join_rev1, argc - 1, argv + 1, 0, aflag,
1066 			     repository, false);
1067 	if (join_rev2)
1068 	    tag_check_valid (join_rev2, argc - 1, argv + 1, 0, aflag,
1069 			     repository, false);
1070 	join_tags_validated = true;
1071     }
1072 
1073     /*
1074      * if we are going to be recursive (building dirs), go ahead and call the
1075      * update recursion processor.  We will be recursive unless either local
1076      * only was specified, or we were passed arguments
1077      */
1078     if (!(local_specified || argc > 1))
1079     {
1080 	if (!pipeout)
1081 	    history_write (m_type == CHECKOUT ? 'O' : 'E', preload_update_dir,
1082 			   history_name, where, repository);
1083 	err += do_update (0, NULL, options, tag, date,
1084 			  force_tag_match, false /* !local */ ,
1085 			  true /* update -d */ , aflag, checkout_prune_dirs,
1086 			  pipeout, which, join_rev1, join_date1,
1087 			  join_rev2, join_date2,
1088 			  preload_update_dir, m_type == CHECKOUT,
1089 			  repository);
1090 	goto out;
1091     }
1092 
1093     if (!pipeout)
1094     {
1095 	int i;
1096 	List *entries;
1097 
1098 	/* we are only doing files, so register them */
1099 	entries = Entries_Open (0, NULL);
1100 	for (i = 1; i < argc; i++)
1101 	{
1102 	    char *line;
1103 	    Vers_TS *vers;
1104 	    struct file_info finfo;
1105 
1106 	    memset (&finfo, 0, sizeof finfo);
1107 	    finfo.file = argv[i];
1108 	    /* Shouldn't be used, so set to arbitrary value.  */
1109 	    finfo.update_dir = NULL;
1110 	    finfo.fullname = argv[i];
1111 	    finfo.repository = repository;
1112 	    finfo.entries = entries;
1113 	    /* The rcs slot is needed to get the options from the RCS
1114                file */
1115 	    finfo.rcs = RCS_parse (finfo.file, repository);
1116 
1117 	    vers = Version_TS (&finfo, options, tag, date,
1118 			       force_tag_match, 0);
1119 	    if (vers->ts_user == NULL)
1120 	    {
1121 		line = Xasprintf ("Initial %s", finfo.file);
1122 		Register (entries, finfo.file,
1123 			  vers->vn_rcs ? vers->vn_rcs : "0",
1124 			  line, vers->options, vers->tag,
1125 			  vers->date, NULL);
1126 		free (line);
1127 	    }
1128 	    freevers_ts (&vers);
1129 	    freercsnode (&finfo.rcs);
1130 	}
1131 
1132 	Entries_Close (entries);
1133     }
1134 
1135     /* Don't log "export", just regular "checkouts" */
1136     if (m_type == CHECKOUT && !pipeout)
1137 	history_write ('O', preload_update_dir, history_name, where,
1138 		       repository);
1139 
1140     /* go ahead and call update now that everything is set */
1141     err += do_update (argc - 1, argv + 1, options, tag, date,
1142 		      force_tag_match, local_specified, true /* update -d */,
1143 		      aflag, checkout_prune_dirs, pipeout, which, join_rev1,
1144 		      join_date1, join_rev2, join_date2, preload_update_dir,
1145 		      m_type == CHECKOUT, repository);
1146 out:
1147     free (preload_update_dir);
1148     preload_update_dir = oldupdate;
1149     free (where);
1150     free (repository);
1151     return err;
1152 }
1153 
1154 
1155 
1156 static char *
1157 findslash (char *start, char *p)
1158 {
1159     for (;;)
1160     {
1161 	if (*p == '/') return p;
1162 	if (p == start) break;
1163 	--p;
1164     }
1165     return NULL;
1166 }
1167 
1168 
1169 
1170 /* Return a newly malloc'd string containing a pathname for CVSNULLREPOS,
1171    and make sure that it exists.  If there is an error creating the
1172    directory, give a fatal error.  Otherwise, the directory is guaranteed
1173    to exist when we return.  */
1174 char *
1175 emptydir_name (void)
1176 {
1177     char *repository;
1178 
1179     repository = Xasprintf ("%s/%s/%s", current_parsed_root->directory,
1180 			    CVSROOTADM, CVSNULLREPOS);
1181     if (!isfile (repository))
1182     {
1183 	mode_t omask;
1184 	omask = umask (cvsumask);
1185 	if (CVS_MKDIR (repository, 0777) < 0)
1186 	    error (1, errno, "cannot create %s", repository);
1187 	(void) umask (omask);
1188     }
1189     return repository;
1190 }
1191 
1192 
1193 
1194 /* Build all the dirs along the path to DIRS with CVS subdirs with appropriate
1195  * repositories.  If DIRS->repository is NULL or the directory already exists,
1196  * do not create a CVSADM directory for that subdirectory; just CVS_CHDIR into
1197  * it.  Frees all storage used by DIRS.
1198  *
1199  * ASSUMPTIONS
1200  *   1. Parent directories will be listed in DIRS before their children.
1201  *   2. At most a single directory will need to be changed at one time.  In
1202  *      other words, if we are in /a/b/c, and our final destination is
1203  *      /a/b/c/d/e/f, then we will build d, then d/e, then d/e/f.
1204  *
1205  * INPUTS
1206  *   dirs	Simple list composed of dir_to_build structures, listing
1207  *		information about directories to build.
1208  *   sticky	Passed to build_one_dir to tell it whether there are any sticky
1209  *		tags or dates to be concerned with.
1210  *
1211  * RETURNS
1212  *   1 on error, 0 otherwise.
1213  *
1214  * ERRORS
1215  *  The only nonfatal error this function may return is if the CHDIR fails.
1216  */
1217 static int
1218 build_dirs_and_chdir (struct dir_to_build *dirs, int sticky)
1219 {
1220     int retval = 0;
1221     struct dir_to_build *nextdir;
1222 
1223     while (dirs != NULL)
1224     {
1225 	const char *dir = last_component (dirs->dirpath);
1226 	int made_dir = 0;
1227 
1228 	made_dir = !mkdir_if_needed (dir);
1229 	if (made_dir) Subdir_Register (NULL, NULL, dir);
1230 
1231 	if (CVS_CHDIR (dir) < 0)
1232 	{
1233 	    error (0, errno, "cannot chdir to %s", dir);
1234 	    retval = 1;
1235 	    goto out;
1236 	}
1237 	if (dirs->repository != NULL)
1238 	{
1239 	    if (made_dir)
1240 		build_one_dir (dirs->repository, dirs->dirpath, sticky);
1241 	    free (dirs->repository);
1242 	}
1243 	nextdir = dirs->next;
1244 	free (dirs->dirpath);
1245 	free (dirs);
1246 	dirs = nextdir;
1247     }
1248 
1249  out:
1250     while (dirs != NULL)
1251     {
1252 	if (dirs->repository != NULL)
1253 	    free (dirs->repository);
1254 	nextdir = dirs->next;
1255 	free (dirs->dirpath);
1256 	free (dirs);
1257 	dirs = nextdir;
1258     }
1259     return retval;
1260 }
1261