checkout.c revision 25839
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 1.4 kit.
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 "cvs.h"
37
38static char *findslash PROTO((char *start, char *p));
39static int checkout_proc PROTO((int *pargc, char **argv, char *where,
40		          char *mwhere, char *mfile, int shorten,
41		          int local_specified, char *omodule,
42		          char *msg));
43static int safe_location PROTO((void));
44
45static const char *const checkout_usage[] =
46{
47    "Usage:\n  %s %s [-ANPRcflnps] [-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.\n",
63    "\t-j rev\tMerge in changes made between current revision and rev.\n",
64    NULL
65};
66
67static const char *const export_usage[] =
68{
69    "Usage: %s %s [-NRfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n",
70    "\t-N\tDon't shorten module paths if -d specified.\n",
71    "\t-f\tForce a head revision match if tag/date not found.\n",
72    "\t-l\tLocal directory only, not recursive\n",
73    "\t-R\tProcess directories recursively (default).\n",
74    "\t-n\tDo not run module program (if any).\n",
75    "\t-r rev\tExport revision or tag.\n",
76    "\t-D date\tExport revisions as of date.\n",
77    "\t-d dir\tExport into dir instead of module name.\n",
78    "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
79    NULL
80};
81
82static int checkout_prune_dirs;
83static int force_tag_match = 1;
84static int pipeout;
85static int aflag;
86static char *options = NULL;
87static char *tag = NULL;
88static int tag_validated = 0;
89static char *date = NULL;
90static char *join_rev1 = NULL;
91static char *join_rev2 = NULL;
92static int join_tags_validated = 0;
93static char *preload_update_dir = NULL;
94static char *history_name = NULL;
95
96int
97checkout (argc, argv)
98    int argc;
99    char **argv;
100{
101    int i;
102    int c;
103    DBM *db;
104    int cat = 0, err = 0, status = 0;
105    int run_module_prog = 1;
106    int local = 0;
107    int shorten = -1;
108    char *where = NULL;
109    char *valid_options;
110    const char *const *valid_usage;
111    enum mtype m_type;
112
113    /*
114     * A smaller subset of options are allowed for the export command, which
115     * is essentially like checkout, except that it hard-codes certain
116     * options to be default (like -kv) and takes care to remove the CVS
117     * directory when it has done its duty
118     */
119    if (strcmp (command_name, "export") == 0)
120    {
121        m_type = EXPORT;
122	valid_options = "+Nnk:d:flRQqr:D:";
123	valid_usage = export_usage;
124    }
125    else
126    {
127        m_type = CHECKOUT;
128	valid_options = "+ANnk:d:flRpQqcsr:D:j:P";
129	valid_usage = checkout_usage;
130    }
131
132    if (argc == -1)
133	usage (valid_usage);
134
135    ign_setup ();
136    wrap_setup ();
137
138    optind = 1;
139    while ((c = getopt (argc, argv, valid_options)) != -1)
140    {
141	switch (c)
142	{
143	    case 'A':
144		aflag = 1;
145		break;
146	    case 'N':
147		shorten = 0;
148		break;
149	    case 'k':
150		if (options)
151		    free (options);
152		options = RCS_check_kflag (optarg);
153		break;
154	    case 'n':
155		run_module_prog = 0;
156		break;
157	    case 'Q':
158	    case 'q':
159#ifdef SERVER_SUPPORT
160		/* The CVS 1.5 client sends these options (in addition to
161		   Global_option requests), so we must ignore them.  */
162		if (!server_active)
163#endif
164		    error (1, 0,
165			   "-q or -Q must be specified before \"%s\"",
166			   command_name);
167		break;
168	    case 'l':
169		local = 1;
170		break;
171	    case 'R':
172		local = 0;
173		break;
174	    case 'P':
175		checkout_prune_dirs = 1;
176		break;
177	    case 'p':
178		pipeout = 1;
179		run_module_prog = 0;	/* don't run module prog when piping */
180		noexec = 1;		/* so no locks will be created */
181		break;
182	    case 'c':
183		cat = 1;
184		break;
185	    case 'd':
186		where = optarg;
187		if (shorten == -1)
188		    shorten = 1;
189		break;
190	    case 's':
191		status = 1;
192		break;
193	    case 'f':
194		force_tag_match = 0;
195		break;
196	    case 'r':
197		tag = optarg;
198		checkout_prune_dirs = 1;
199		break;
200	    case 'D':
201		date = Make_Date (optarg);
202		checkout_prune_dirs = 1;
203		break;
204	    case 'j':
205		if (join_rev2)
206		    error (1, 0, "only two -j options can be specified");
207		if (join_rev1)
208		    join_rev2 = optarg;
209		else
210		    join_rev1 = optarg;
211		break;
212	    case '?':
213	    default:
214		usage (valid_usage);
215		break;
216	}
217    }
218    argc -= optind;
219    argv += optind;
220
221    if (shorten == -1)
222	shorten = 0;
223
224    if ((!(cat + status) && argc == 0) || ((cat + status) && argc != 0))
225	usage (valid_usage);
226
227    if (where && pipeout)
228	error (1, 0, "-d and -p are mutually exclusive");
229
230    if (strcmp (command_name, "export") == 0)
231    {
232	if (!tag && !date)
233	{
234	    error (0, 0, "must specify a tag or date");
235	    usage (valid_usage);
236	}
237	if (tag && isdigit (tag[0]))
238	    error (1, 0, "tag `%s' must be a symbolic tag", tag);
239/*
240 * mhy 950615: -kv doesn't work for binaries with RCS keywords.
241 * Instead use the default provided in the RCS file (-ko for binaries).
242 */
243#if 0
244	if (!options)
245	  options = RCS_check_kflag ("v");/* -kv is default */
246#endif
247    }
248
249    if (!safe_location()) {
250        error(1, 0, "Cannot check out files into the repository itself");
251    }
252
253#ifdef CLIENT_SUPPORT
254    if (client_active)
255    {
256	int expand_modules;
257
258	start_server ();
259
260	ign_setup ();
261
262	/* We have to expand names here because the "expand-modules"
263           directive to the server has the side-effect of having the
264           server send the check-in and update programs for the
265           various modules/dirs requested.  If we turn this off and
266           simply request the names of the modules and directories (as
267           below in !expand_modules), those files (CVS/Checking.prog
268           or CVS/Update.prog) don't get created.  Grrr.  */
269
270	expand_modules = (!cat && !status && !pipeout
271			  && supported_request ("expand-modules"));
272
273	if (expand_modules)
274	{
275	    /* This is done here because we need to read responses
276               from the server before we send the command checkout or
277               export files. */
278
279	    client_expand_modules (argc, argv, local);
280	}
281
282	if (!run_module_prog) send_arg ("-n");
283	if (local) send_arg ("-l");
284	if (pipeout) send_arg ("-p");
285	if (!force_tag_match) send_arg ("-f");
286	if (aflag)
287	    send_arg("-A");
288	if (!shorten)
289	    send_arg("-N");
290	if (checkout_prune_dirs && strcmp (command_name, "export") != 0)
291	    send_arg("-P");
292	client_prune_dirs = checkout_prune_dirs;
293	if (cat)
294	    send_arg("-c");
295	if (where != NULL)
296	{
297	    option_with_arg ("-d", where);
298	}
299	if (status)
300	    send_arg("-s");
301	/* Why not send -k for export?  This would appear to make
302	   remote export differ from local export.  FIXME.  */
303	if (strcmp (command_name, "export") != 0
304	    && options != NULL
305	    && options[0] != '\0')
306	    send_arg (options);
307	option_with_arg ("-r", tag);
308	if (date)
309	    client_senddate (date);
310	if (join_rev1 != NULL)
311	    option_with_arg ("-j", join_rev1);
312	if (join_rev2 != NULL)
313	    option_with_arg ("-j", join_rev2);
314
315	if (expand_modules)
316	{
317	    client_send_expansions (local, where, 1);
318	}
319	else
320	{
321	    int i;
322	    for (i = 0; i < argc; ++i)
323		send_arg (argv[i]);
324	    client_nonexpanded_setup ();
325	}
326
327	send_to_server (strcmp (command_name, "export") == 0 ?
328                        "export\012" : "co\012",
329                        0);
330
331	return get_responses_and_close ();
332    }
333#endif /* CLIENT_SUPPORT */
334
335    if (cat || status)
336    {
337	cat_module (status);
338	return (0);
339    }
340    db = open_module ();
341
342    /*
343     * if we have more than one argument and where was specified, we make the
344     * where, cd into it, and try to shorten names as much as possible.
345     * Otherwise, we pass the where as a single argument to do_module.
346     */
347    if (argc > 1 && where != NULL)
348    {
349	(void) CVS_MKDIR (where, 0777);
350	if ( CVS_CHDIR (where) < 0)
351	    error (1, errno, "cannot chdir to %s", where);
352	preload_update_dir = xstrdup (where);
353	where = (char *) NULL;
354	if (!isfile (CVSADM))
355	{
356	    char *repository;
357
358	    repository = xmalloc (strlen (CVSroot_directory) + 80);
359	    (void) sprintf (repository, "%s/%s/%s", CVSroot_directory,
360			    CVSROOTADM, CVSNULLREPOS);
361	    if (!isfile (repository))
362	    {
363		mode_t omask;
364		omask = umask (cvsumask);
365		(void) CVS_MKDIR (repository, 0777);
366		(void) umask (omask);
367	    }
368
369	    /* I'm not sure whether this check is redundant.  */
370	    if (!isdir (repository))
371		error (1, 0, "there is no repository %s", repository);
372
373	    Create_Admin (".", preload_update_dir, repository,
374			  (char *) NULL, (char *) NULL, 0);
375	    if (!noexec)
376	    {
377		FILE *fp;
378
379		fp = open_file (CVSADM_ENTSTAT, "w+");
380		if (fclose(fp) == EOF)
381		    error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
382#ifdef SERVER_SUPPORT
383		if (server_active)
384		    server_set_entstat (preload_update_dir, repository);
385#endif
386	    }
387	    free (repository);
388	}
389    }
390
391    /* If we will be calling history_write, work out the name to pass
392       it.  */
393    if (strcmp (command_name, "export") != 0 && !pipeout)
394    {
395	if (tag && date)
396	{
397	    history_name = xmalloc (strlen (tag) + strlen (date) + 2);
398	    sprintf (history_name, "%s:%s", tag, date);
399	}
400	else if (tag)
401	    history_name = tag;
402	else
403	    history_name = date;
404    }
405
406    /*
407     * if where was specified (-d) and we have not taken care of it already
408     * with the multiple arg stuff, and it was not a simple directory name
409     * but rather a path, we strip off everything but the last component and
410     * attempt to cd to the indicated place.  where then becomes simply the
411     * last component
412     */
413    if (where != NULL && strchr (where, '/') != NULL)
414    {
415	char *slash;
416
417	slash = strrchr (where, '/');
418	*slash = '\0';
419
420	if ( CVS_CHDIR (where) < 0)
421	    error (1, errno, "cannot chdir to %s", where);
422
423	preload_update_dir = xstrdup (where);
424
425	where = slash + 1;
426	if (*where == '\0')
427	    where = NULL;
428    }
429
430    for (i = 0; i < argc; i++)
431	err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
432			  where, shorten, local, run_module_prog,
433			  (char *) NULL);
434    close_module (db);
435    return (err);
436}
437
438static int
439safe_location ()
440{
441    char *current;
442    char hardpath[PATH_MAX+5];
443    size_t hardpath_len;
444    int  x;
445    int retval;
446
447#ifdef HAVE_READLINK
448    /* FIXME-arbitrary limit: should be retrying this like xgetwd.
449       But how does readlink let us know that the buffer was too small?
450       (by returning sizeof hardpath - 1?).  */
451    x = readlink(CVSroot_directory, hardpath, sizeof hardpath - 1);
452#else
453    x = -1;
454#endif
455    if (x == -1)
456    {
457        strcpy(hardpath, CVSroot_directory);
458    }
459    else
460    {
461        hardpath[x] = '\0';
462    }
463    current = xgetwd ();
464    hardpath_len = strlen (hardpath);
465    if (strlen (current) >= hardpath_len
466	&& strncmp (current, hardpath, hardpath_len) == 0)
467    {
468	if (/* Current is a subdirectory of hardpath.  */
469	    current[hardpath_len] == '/'
470
471	    /* Current is hardpath itself.  */
472	    || current[hardpath_len] == '\0')
473	    retval = 0;
474	else
475	    /* It isn't a problem.  For example, current is
476	       "/foo/cvsroot-bar" and hardpath is "/foo/cvsroot".  */
477	    retval = 1;
478    }
479    else
480	retval = 1;
481    free (current);
482    return retval;
483}
484
485struct dir_to_build
486{
487    /* What to put in CVS/Repository.  */
488    char *repository;
489    /* The path to the directory.  */
490    char *dirpath;
491
492    struct dir_to_build *next;
493};
494
495static int build_dirs_and_chdir PROTO ((struct dir_to_build *list,
496					int sticky));
497
498static void build_one_dir PROTO ((char *, char *, int));
499
500static void
501build_one_dir (repository, dirpath, sticky)
502    char *repository;
503    char *dirpath;
504    int sticky;
505{
506    FILE *fp;
507
508    if (!isfile (CVSADM) && strcmp (command_name, "export") != 0)
509    {
510	/* I suspect that this check could be omitted.  */
511	if (!isdir (repository))
512	    error (1, 0, "there is no repository %s", repository);
513
514	Create_Admin (".", dirpath, repository,
515		      sticky ? (char *) NULL : tag,
516		      sticky ? (char *) NULL : date,
517
518		      /* FIXME?  This is a guess.  If it is important
519			 for nonbranch to be set correctly here I
520			 think we need to write it one way now and
521			 then rewrite it later via WriteTag, once
522			 we've had a chance to call RCS_nodeisbranch
523			 on each file.  */
524		      0);
525
526	if (!noexec)
527	{
528	    fp = open_file (CVSADM_ENTSTAT, "w+");
529	    if (fclose (fp) == EOF)
530		error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
531#ifdef SERVER_SUPPORT
532	    if (server_active)
533		server_set_entstat (dirpath, repository);
534#endif
535	}
536    }
537}
538
539/*
540 * process_module calls us back here so we do the actual checkout stuff
541 */
542/* ARGSUSED */
543static int
544checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
545	       local_specified, omodule, msg)
546    int *pargc;
547    char **argv;
548    char *where;
549    char *mwhere;
550    char *mfile;
551    int shorten;
552    int local_specified;
553    char *omodule;
554    char *msg;
555{
556    int err = 0;
557    int which;
558    char *cp;
559    char *cp2;
560    char *repository;
561    char *xwhere = NULL;
562    char *oldupdate = NULL;
563    char *prepath;
564
565    /*
566     * OK, so we're doing the checkout! Our args are as follows:
567     *  argc,argv contain either dir or dir followed by a list of files
568     *  where contains where to put it (if supplied by checkout)
569     *  mwhere contains the module name or -d from module file
570     *  mfile says do only that part of the module
571     *  shorten = TRUE says shorten as much as possible
572     *  omodule is the original arg to do_module()
573     */
574
575    /* set up the repository (maybe) for the bottom directory */
576    repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0]) + 5);
577    (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
578
579    /* save the original value of preload_update_dir */
580    if (preload_update_dir != NULL)
581	oldupdate = xstrdup (preload_update_dir);
582
583    /* fix up argv[] for the case of partial modules */
584    if (mfile != NULL)
585    {
586	char *file;
587
588	/* if mfile is really a path, straighten it out first */
589	if ((cp = strrchr (mfile, '/')) != NULL)
590	{
591	    *cp = 0;
592	    repository = xrealloc (repository,
593				   strlen (repository) + strlen (mfile) + 10);
594	    (void) strcat (repository, "/");
595	    (void) strcat (repository, mfile);
596
597	    /*
598	     * Now we need to fill in the where correctly. if !shorten, tack
599	     * the rest of the path onto where if where is filled in
600	     * otherwise tack the rest of the path onto mwhere and make that
601	     * the where
602	     *
603	     * If shorten is enabled, we might use mwhere to set where if
604	     * nobody set it yet, so we'll need to setup mwhere as the last
605	     * component of the path we are tacking onto repository
606	     */
607	    if (!shorten)
608	    {
609		if (where != NULL)
610		{
611		    xwhere = xmalloc (strlen (where) + strlen (mfile) + 5);
612		    (void) sprintf (xwhere, "%s/%s", where, mfile);
613		}
614		else
615		{
616		    xwhere = xmalloc (strlen (mwhere) + strlen (mfile) + 5);
617		    (void) sprintf (xwhere, "%s/%s", mwhere, mfile);
618		}
619		where = xwhere;
620	    }
621	    else
622	    {
623		char *slash;
624
625		if ((slash = strrchr (mfile, '/')) != NULL)
626		    mwhere = slash + 1;
627		else
628		    mwhere = mfile;
629	    }
630	    mfile = cp + 1;
631	}
632
633	file = xmalloc (strlen (repository) + strlen (mfile) + 5);
634	(void) sprintf (file, "%s/%s", repository, mfile);
635	if (isdir (file))
636	{
637
638	    /*
639	     * The portion of a module was a directory, so kludge up where to
640	     * be the subdir, and fix up repository
641	     */
642	    free (repository);
643	    repository = xstrdup (file);
644
645	    /*
646	     * At this point, if shorten is not enabled, we make where either
647	     * where with mfile concatenated, or if where hadn't been set we
648	     * set it to mwhere with mfile concatenated.
649	     *
650	     * If shorten is enabled and where hasn't been set yet, then where
651	     * becomes mfile
652	     */
653	    if (!shorten)
654	    {
655		if (where != NULL)
656		{
657		    xwhere = xmalloc (strlen (where) + strlen (mfile) + 5);
658		    (void) sprintf (xwhere, "%s/%s", where, mfile);
659		}
660		else
661		{
662		    xwhere = xmalloc (strlen (mwhere) + strlen (mfile) + 5);
663		    (void) sprintf (xwhere, "%s/%s", mwhere, mfile);
664		}
665		where = xwhere;
666	    }
667	    else if (where == NULL)
668		where = mfile;
669	}
670	else
671	{
672	    int i;
673
674	    /*
675	     * The portion of a module was a file, so kludge up argv to be
676	     * correct
677	     */
678	    for (i = 1; i < *pargc; i++)/* free the old ones */
679		free (argv[i]);
680	    /* FIXME: Normally one has to realloc argv to make sure
681               argv[1] exists.  But this argv does not points to the
682               beginning of an allocated block.  For now we allocate
683               at least 4 entries for argv (in line2argv).  */
684	    argv[1] = xstrdup (mfile);	/* set up the new one */
685	    *pargc = 2;
686
687	    /* where gets mwhere if where isn't set */
688	    if (where == NULL)
689		where = mwhere;
690	}
691	free (file);
692    }
693
694    /*
695     * if shorten is enabled and where isn't specified yet, we pluck the last
696     * directory component of argv[0] and make it the where
697     */
698    if (shorten && where == NULL)
699    {
700	if ((cp = strrchr (argv[0], '/')) != NULL)
701	{
702	    xwhere = xstrdup (cp + 1);
703	    where = xwhere;
704	}
705    }
706
707    /* if where is still NULL, use mwhere if set or the argv[0] dir */
708    if (where == NULL)
709    {
710	if (mwhere)
711	    where = mwhere;
712	else
713	{
714	    xwhere = xstrdup (argv[0]);
715	    where = xwhere;
716	}
717    }
718
719    if (preload_update_dir != NULL)
720    {
721	preload_update_dir =
722	    xrealloc (preload_update_dir,
723		      strlen (preload_update_dir) + strlen (where) + 5);
724	strcat (preload_update_dir, "/");
725	strcat (preload_update_dir, where);
726    }
727    else
728	preload_update_dir = xstrdup (where);
729
730    /*
731     * At this point, where is the directory we want to build, repository is
732     * the repository for the lowest level of the path.
733     */
734
735    /*
736     * If we are sending everything to stdout, we can skip a whole bunch of
737     * work from here
738     */
739    if (!pipeout)
740    {
741	size_t root_len;
742	struct dir_to_build *head;
743
744	/* We need to tell build_dirs not only the path we want it to
745	   build, but also the repositories we want it to populate the
746	   path with. To accomplish this, we walk the path backwards,
747	   one pathname component at a time, constucting a linked
748	   list of struct dir_to_build.  */
749	prepath = xstrdup (repository);
750
751	/* We don't want to start stripping elements off prepath after we
752	   get to CVSROOT.  */
753	root_len = strlen (CVSroot_directory);
754	if (strncmp (repository, CVSroot_directory, root_len) != 0)
755	    error (1, 0, "\
756internal error: %s doesn't start with %s in checkout_proc",
757		   repository, CVSroot_directory);
758
759	/* We always create at least one directory, which corresponds to
760	   the entire strings for WHERE and REPOSITORY.  */
761	head = (struct dir_to_build *) xmalloc (sizeof (struct dir_to_build));
762	/* Special marker to indicate that we don't want build_dirs_and_chdir
763	   to create the CVSADM directory for us.  */
764	head->repository = NULL;
765	head->dirpath = xstrdup (where);
766	head->next = NULL;
767
768	cp = strrchr (where, '/');
769	cp2 = strrchr (prepath, '/');
770
771	while (cp != NULL)
772	{
773	    struct dir_to_build *new;
774	    new = (struct dir_to_build *)
775		xmalloc (sizeof (struct dir_to_build));
776	    new->dirpath = xmalloc (strlen (where));
777	    strncpy (new->dirpath, where, cp - where);
778	    new->dirpath[cp - where] = '\0';
779	    if (cp2 == NULL || cp2 < prepath + root_len)
780	    {
781		/* Don't walk up past CVSROOT; instead put in CVSNULLREPOS.  */
782		new->repository =
783		    xmalloc (strlen (CVSroot_directory) + 80);
784		(void) sprintf (new->repository, "%s/%s/%s",
785				CVSroot_directory,
786				CVSROOTADM, CVSNULLREPOS);
787		if (!isfile (new->repository))
788		{
789		    mode_t omask;
790		    omask = umask (cvsumask);
791		    if (CVS_MKDIR (new->repository, 0777) < 0)
792			error (0, errno, "cannot create %s",
793			       new->repository);
794		    (void) umask (omask);
795		}
796	    }
797	    else
798	    {
799		new->repository = xmalloc (strlen (prepath));
800		strncpy (new->repository, prepath, cp2 - prepath);
801		new->repository[cp2 - prepath] = '\0';
802	    }
803	    new->next = head;
804	    head = new;
805
806	    cp = findslash (where, cp - 1);
807	    cp2 = findslash (prepath, cp2 - 1);
808	}
809
810	/* First build the top-level CVSADM directory.  The value we
811	   pass in here for repository is probably wrong; see modules3-7f
812	   in the testsuite.  */
813	build_one_dir (head->repository != NULL ? head->repository : prepath,
814		       ".", *pargc <= 1);
815
816	/*
817	 * build dirs on the path if necessary and leave us in the bottom
818	 * directory (where if where was specified) doesn't contain a CVS
819	 * subdir yet, but all the others contain CVS and Entries.Static
820	 * files
821	 */
822	if (build_dirs_and_chdir (head, *pargc <= 1) != 0)
823	{
824	    error (0, 0, "ignoring module %s", omodule);
825	    free (prepath);
826	    err = 1;
827	    goto out;
828	}
829
830	/* clean up */
831	free (prepath);
832
833	/* set up the repository (or make sure the old one matches) */
834	if (!isfile (CVSADM))
835	{
836	    FILE *fp;
837
838	    if (!noexec && *pargc > 1)
839	    {
840		/* I'm not sure whether this check is redundant.  */
841		if (!isdir (repository))
842		    error (1, 0, "there is no repository %s", repository);
843
844		Create_Admin (".", preload_update_dir, repository,
845			      (char *) NULL, (char *) NULL, 0);
846		fp = open_file (CVSADM_ENTSTAT, "w+");
847		if (fclose(fp) == EOF)
848		    error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
849#ifdef SERVER_SUPPORT
850		if (server_active)
851		    server_set_entstat (where, repository);
852#endif
853	    }
854	    else
855	    {
856		/* I'm not sure whether this check is redundant.  */
857		if (!isdir (repository))
858		    error (1, 0, "there is no repository %s", repository);
859
860		Create_Admin (".", preload_update_dir, repository, tag, date,
861
862			      /* FIXME?  This is a guess.  If it is important
863				 for nonbranch to be set correctly here I
864				 think we need to write it one way now and
865				 then rewrite it later via WriteTag, once
866				 we've had a chance to call RCS_nodeisbranch
867				 on each file.  */
868			      0);
869	    }
870	}
871	else
872	{
873	    char *repos;
874
875	    /* get the contents of the previously existing repository */
876	    repos = Name_Repository ((char *) NULL, preload_update_dir);
877	    if (fncmp (repository, repos) != 0)
878	    {
879		error (0, 0, "existing repository %s does not match %s",
880		       repos, repository);
881		error (0, 0, "ignoring module %s", omodule);
882		free (repos);
883		err = 1;
884		goto out;
885	    }
886	    free (repos);
887	}
888    }
889
890    /*
891     * If we are going to be updating to stdout, we need to cd to the
892     * repository directory so the recursion processor can use the current
893     * directory as the place to find repository information
894     */
895    if (pipeout)
896    {
897	if ( CVS_CHDIR (repository) < 0)
898	{
899	    error (0, errno, "cannot chdir to %s", repository);
900	    err = 1;
901	    goto out;
902	}
903	which = W_REPOS;
904	if (tag != NULL && !tag_validated)
905	{
906	    tag_check_valid (tag, *pargc - 1, argv + 1, 0, aflag, NULL);
907	    tag_validated = 1;
908	}
909    }
910    else
911    {
912	which = W_LOCAL | W_REPOS;
913	if (tag != NULL && !tag_validated)
914	{
915	    tag_check_valid (tag, *pargc - 1, argv + 1, 0, aflag,
916			     repository);
917	    tag_validated = 1;
918	}
919    }
920
921    if (tag != NULL || date != NULL || join_rev1 != NULL)
922	which |= W_ATTIC;
923
924    if (! join_tags_validated)
925    {
926        if (join_rev1 != NULL)
927	    tag_check_valid_join (join_rev1, *pargc - 1, argv + 1, 0, aflag,
928				  repository);
929	if (join_rev2 != NULL)
930	    tag_check_valid_join (join_rev2, *pargc - 1, argv + 1, 0, aflag,
931				  repository);
932	join_tags_validated = 1;
933    }
934
935    /*
936     * if we are going to be recursive (building dirs), go ahead and call the
937     * update recursion processor.  We will be recursive unless either local
938     * only was specified, or we were passed arguments
939     */
940    if (!(local_specified || *pargc > 1))
941    {
942	if (strcmp (command_name, "export") != 0 && !pipeout)
943	    history_write ('O', preload_update_dir, history_name, where,
944			   repository);
945	else if (strcmp (command_name, "export") == 0 && !pipeout)
946	    history_write ('E', preload_update_dir, tag ? tag : date, where,
947			   repository);
948	err += do_update (0, (char **) NULL, options, tag, date,
949			  force_tag_match, 0 /* !local */ ,
950			  1 /* update -d */ , aflag, checkout_prune_dirs,
951			  pipeout, which, join_rev1, join_rev2,
952			  preload_update_dir);
953	goto out;
954    }
955
956    if (!pipeout)
957    {
958	int i;
959	List *entries;
960
961	/* we are only doing files, so register them */
962	entries = Entries_Open (0);
963	for (i = 1; i < *pargc; i++)
964	{
965	    char *line;
966	    Vers_TS *vers;
967	    struct file_info finfo;
968
969	    memset (&finfo, 0, sizeof finfo);
970	    finfo.file = argv[i];
971	    /* Shouldn't be used, so set to arbitrary value.  */
972	    finfo.update_dir = NULL;
973	    finfo.fullname = argv[i];
974	    finfo.repository = repository;
975	    finfo.entries = entries;
976	    /* The rcs slot is needed to get the options from the RCS
977               file */
978	    finfo.rcs = RCS_parse (finfo.file, repository);
979
980	    vers = Version_TS (&finfo, options, tag, date,
981			       force_tag_match, 0);
982	    if (vers->ts_user == NULL)
983	    {
984		line = xmalloc (strlen (finfo.file) + 15);
985		(void) sprintf (line, "Initial %s", finfo.file);
986		Register (entries, finfo.file,
987			  vers->vn_rcs ? vers->vn_rcs : "0",
988			  line, vers->options, vers->tag,
989			  vers->date, (char *) 0);
990		free (line);
991	    }
992	    freevers_ts (&vers);
993	    freercsnode (&finfo.rcs);
994	}
995
996	Entries_Close (entries);
997    }
998
999    /* Don't log "export", just regular "checkouts" */
1000    if (strcmp (command_name, "export") != 0 && !pipeout)
1001	history_write ('O', preload_update_dir, history_name, where,
1002		       repository);
1003
1004    /* go ahead and call update now that everything is set */
1005    err += do_update (*pargc - 1, argv + 1, options, tag, date,
1006		      force_tag_match, local_specified, 1 /* update -d */,
1007		      aflag, checkout_prune_dirs, pipeout, which, join_rev1,
1008		      join_rev2, preload_update_dir);
1009out:
1010    free (preload_update_dir);
1011    preload_update_dir = oldupdate;
1012    if (xwhere != NULL)
1013	free (xwhere);
1014    free (repository);
1015    return (err);
1016}
1017
1018static char *
1019findslash (start, p)
1020    char *start;
1021    char *p;
1022{
1023    while (p >= start && *p != '/')
1024	p--;
1025    /* FIXME: indexing off the start of the array like this is *NOT*
1026       OK according to ANSI, and will break some of the time on certain
1027       segmented architectures.  */
1028    if (p < start)
1029	return (NULL);
1030    else
1031	return (p);
1032}
1033
1034/* Build all the dirs along the path to DIRS with CVS subdirs with appropriate
1035   repositories.  If ->repository is NULL, do not create a CVSADM directory
1036   for that subdirectory; just CVS_CHDIR into it.  */
1037static int
1038build_dirs_and_chdir (dirs, sticky)
1039    struct dir_to_build *dirs;
1040    int sticky;
1041{
1042    int retval = 0;
1043    struct dir_to_build *nextdir;
1044
1045    while (dirs != NULL)
1046    {
1047	char *dir = last_component (dirs->dirpath);
1048
1049	mkdir_if_needed (dir);
1050	Subdir_Register (NULL, NULL, dir);
1051	if (CVS_CHDIR (dir) < 0)
1052	{
1053	    error (0, errno, "cannot chdir to %s", dir);
1054	    retval = 1;
1055	    goto out;
1056	}
1057	if (dirs->repository != NULL)
1058	{
1059	    build_one_dir (dirs->repository, dirs->dirpath, sticky);
1060	    free (dirs->repository);
1061	}
1062	nextdir = dirs->next;
1063	free (dirs->dirpath);
1064	free (dirs);
1065	dirs = nextdir;
1066    }
1067
1068 out:
1069    return retval;
1070}
1071