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
43static char *findslash (char *start, char *p);
44static 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
49static 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
72static 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
88static int checkout_prune_dirs;
89static int force_tag_match;
90static int pipeout;
91static int aflag;
92static char *options;
93static char *tag;
94static bool tag_validated;
95static char *date;
96static char *join_rev1, *join_date1;
97static char *join_rev2, *join_date2;
98static bool join_tags_validated;
99static char *preload_update_dir;
100static char *history_name;
101static enum mtype m_type;
102
103int
104checkout (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    getoptreset ();
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 = nolock = 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 */
427int
428safe_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, "\
502could 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
531struct 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
543static int build_dirs_and_chdir (struct dir_to_build *list,
544					int sticky);
545
546static void
547build_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 */
594static int
595checkout_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, "\
812internal 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);
1146out:
1147    free (preload_update_dir);
1148    preload_update_dir = oldupdate;
1149    free (where);
1150    free (repository);
1151    return err;
1152}
1153
1154
1155
1156static char *
1157findslash (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.  */
1174char *
1175emptydir_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 */
1217static int
1218build_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