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