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