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