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