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