xref: /dragonfly/contrib/cvs-1.12/src/create_adm.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino  * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino  *
4*86d7f5d3SJohn Marino  * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5*86d7f5d3SJohn Marino  *                                  and others.
6*86d7f5d3SJohn Marino  *
7*86d7f5d3SJohn Marino  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8*86d7f5d3SJohn Marino  * Portions Copyright (C) 1989-1992, Brian Berliner
9*86d7f5d3SJohn Marino  *
10*86d7f5d3SJohn Marino  * You may distribute under the terms of the GNU General Public License as
11*86d7f5d3SJohn Marino  * specified in the README file that comes with the CVS source distribution.
12*86d7f5d3SJohn Marino  *
13*86d7f5d3SJohn Marino  * Create Administration.
14*86d7f5d3SJohn Marino  *
15*86d7f5d3SJohn Marino  * Creates a CVS administration directory based on the argument repository; the
16*86d7f5d3SJohn Marino  * "Entries" file is prefilled from the "initrecord" argument.
17*86d7f5d3SJohn Marino  */
18*86d7f5d3SJohn Marino 
19*86d7f5d3SJohn Marino #include "cvs.h"
20*86d7f5d3SJohn Marino 
21*86d7f5d3SJohn Marino 
22*86d7f5d3SJohn Marino 
23*86d7f5d3SJohn Marino /* update_dir includes dir as its last component.
24*86d7f5d3SJohn Marino 
25*86d7f5d3SJohn Marino    Return value is 0 for success, or 1 if we printed a warning message.
26*86d7f5d3SJohn Marino    Note that many errors are still fatal; particularly for unlikely errors
27*86d7f5d3SJohn Marino    a fatal error is probably better than a warning which might be missed
28*86d7f5d3SJohn Marino    or after which CVS might do something non-useful.  If WARN is zero, then
29*86d7f5d3SJohn Marino    don't print warnings; all errors are fatal then.  */
30*86d7f5d3SJohn Marino 
31*86d7f5d3SJohn Marino int
Create_Admin(const char * dir,const char * update_dir,const char * repository,const char * tag,const char * date,int nonbranch,int warn,int dotemplate)32*86d7f5d3SJohn Marino Create_Admin (const char *dir, const char *update_dir, const char *repository,
33*86d7f5d3SJohn Marino               const char *tag, const char *date, int nonbranch, int warn,
34*86d7f5d3SJohn Marino               int dotemplate)
35*86d7f5d3SJohn Marino {
36*86d7f5d3SJohn Marino     FILE *fout;
37*86d7f5d3SJohn Marino     char *cp;
38*86d7f5d3SJohn Marino     char *reposcopy;
39*86d7f5d3SJohn Marino     char *tmp;
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino     TRACE (TRACE_FUNCTION, "Create_Admin (%s, %s, %s, %s, %s, %d, %d, %d)",
42*86d7f5d3SJohn Marino 	   dir, update_dir, repository, tag ? tag : "",
43*86d7f5d3SJohn Marino 	   date ? date : "", nonbranch, warn, dotemplate);
44*86d7f5d3SJohn Marino 
45*86d7f5d3SJohn Marino     if (noexec)
46*86d7f5d3SJohn Marino 	return 0;
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino     tmp = Xasprintf ("%s/%s", dir, CVSADM);
49*86d7f5d3SJohn Marino     if (isfile (tmp))
50*86d7f5d3SJohn Marino 	error (1, 0, "there is a version in %s already", update_dir);
51*86d7f5d3SJohn Marino 
52*86d7f5d3SJohn Marino     if (CVS_MKDIR (tmp, 0777) < 0)
53*86d7f5d3SJohn Marino     {
54*86d7f5d3SJohn Marino 	free (tmp);
55*86d7f5d3SJohn Marino 	tmp = NULL;
56*86d7f5d3SJohn Marino 
57*86d7f5d3SJohn Marino 	/* We want to print out the entire update_dir, since a lot of
58*86d7f5d3SJohn Marino 	   our code calls this function with dir == "." or dir ==
59*86d7f5d3SJohn Marino 	   NULL.  I hope that gives enough information in cases like
60*86d7f5d3SJohn Marino 	   absolute pathnames; printing out xgetcwd() or something would
61*86d7f5d3SJohn Marino 	   be way too verbose in the common cases.  */
62*86d7f5d3SJohn Marino 
63*86d7f5d3SJohn Marino 	if (warn)
64*86d7f5d3SJohn Marino 	{
65*86d7f5d3SJohn Marino 	    /* The reason that this is a warning, rather than silently
66*86d7f5d3SJohn Marino 	       just skipping creating the directory, is that we don't want
67*86d7f5d3SJohn Marino 	       CVS's behavior to vary subtly based on factors (like directory
68*86d7f5d3SJohn Marino 	       permissions) which are not made clear to the user.  With
69*86d7f5d3SJohn Marino 	       the warning at least we let them know what is going on.  */
70*86d7f5d3SJohn Marino 	    error (0, errno, "warning: cannot make directory %s in %s",
71*86d7f5d3SJohn Marino 		   CVSADM, update_dir);
72*86d7f5d3SJohn Marino 	    return 1;
73*86d7f5d3SJohn Marino 	}
74*86d7f5d3SJohn Marino 	else
75*86d7f5d3SJohn Marino 	    error (1, errno, "cannot make directory %s in %s",
76*86d7f5d3SJohn Marino 		   CVSADM, update_dir);
77*86d7f5d3SJohn Marino     }
78*86d7f5d3SJohn Marino     else
79*86d7f5d3SJohn Marino     {
80*86d7f5d3SJohn Marino 	free (tmp);
81*86d7f5d3SJohn Marino 	tmp = NULL;
82*86d7f5d3SJohn Marino     }
83*86d7f5d3SJohn Marino 
84*86d7f5d3SJohn Marino     /* record the current cvs root for later use */
85*86d7f5d3SJohn Marino 
86*86d7f5d3SJohn Marino     Create_Root (dir, original_parsed_root->original);
87*86d7f5d3SJohn Marino     if (dir != NULL)
88*86d7f5d3SJohn Marino 	tmp = Xasprintf ("%s/%s", dir, CVSADM_REP);
89*86d7f5d3SJohn Marino     else
90*86d7f5d3SJohn Marino 	tmp = xstrdup (CVSADM_REP);
91*86d7f5d3SJohn Marino     fout = CVS_FOPEN (tmp, "w+");
92*86d7f5d3SJohn Marino     if (fout == NULL)
93*86d7f5d3SJohn Marino     {
94*86d7f5d3SJohn Marino 	if (update_dir[0] == '\0')
95*86d7f5d3SJohn Marino 	    error (1, errno, "cannot open %s", tmp);
96*86d7f5d3SJohn Marino 	else
97*86d7f5d3SJohn Marino 	    error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP);
98*86d7f5d3SJohn Marino     }
99*86d7f5d3SJohn Marino     reposcopy = xstrdup (repository);
100*86d7f5d3SJohn Marino     Sanitize_Repository_Name (reposcopy);
101*86d7f5d3SJohn Marino 
102*86d7f5d3SJohn Marino     /* The top level of the repository is a special case -- we need to
103*86d7f5d3SJohn Marino        write it with an extra dot at the end.  This trailing `.' stuff
104*86d7f5d3SJohn Marino        rubs me the wrong way -- on the other hand, I don't want to
105*86d7f5d3SJohn Marino        spend the time making sure all of the code can handle it if we
106*86d7f5d3SJohn Marino        don't do it. */
107*86d7f5d3SJohn Marino 
108*86d7f5d3SJohn Marino     if (strcmp (reposcopy, current_parsed_root->directory) == 0)
109*86d7f5d3SJohn Marino     {
110*86d7f5d3SJohn Marino 	reposcopy = xrealloc (reposcopy, strlen (reposcopy) + 3);
111*86d7f5d3SJohn Marino 	strcat (reposcopy, "/.");
112*86d7f5d3SJohn Marino     }
113*86d7f5d3SJohn Marino 
114*86d7f5d3SJohn Marino     cp = reposcopy;
115*86d7f5d3SJohn Marino 
116*86d7f5d3SJohn Marino     /*
117*86d7f5d3SJohn Marino      * If the Repository file is to hold a relative path, try to strip off
118*86d7f5d3SJohn Marino      * the leading CVSroot argument.
119*86d7f5d3SJohn Marino      */
120*86d7f5d3SJohn Marino     {
121*86d7f5d3SJohn Marino 	char *path = Xasprintf ("%s/", current_parsed_root->directory);
122*86d7f5d3SJohn Marino 	if (strncmp (cp, path, strlen (path)) == 0)
123*86d7f5d3SJohn Marino 	    cp += strlen (path);
124*86d7f5d3SJohn Marino 	free (path);
125*86d7f5d3SJohn Marino     }
126*86d7f5d3SJohn Marino 
127*86d7f5d3SJohn Marino     if (fprintf (fout, "%s\n", cp) < 0)
128*86d7f5d3SJohn Marino     {
129*86d7f5d3SJohn Marino 	if (update_dir[0] == '\0')
130*86d7f5d3SJohn Marino 	    error (1, errno, "write to %s failed", tmp);
131*86d7f5d3SJohn Marino 	else
132*86d7f5d3SJohn Marino 	    error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP);
133*86d7f5d3SJohn Marino     }
134*86d7f5d3SJohn Marino     if (fclose (fout) == EOF)
135*86d7f5d3SJohn Marino     {
136*86d7f5d3SJohn Marino 	if (update_dir[0] == '\0')
137*86d7f5d3SJohn Marino 	    error (1, errno, "cannot close %s", tmp);
138*86d7f5d3SJohn Marino 	else
139*86d7f5d3SJohn Marino 	    error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP);
140*86d7f5d3SJohn Marino     }
141*86d7f5d3SJohn Marino 
142*86d7f5d3SJohn Marino     /* now, do the Entries file */
143*86d7f5d3SJohn Marino     if (dir != NULL)
144*86d7f5d3SJohn Marino 	(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
145*86d7f5d3SJohn Marino     else
146*86d7f5d3SJohn Marino 	(void) strcpy (tmp, CVSADM_ENT);
147*86d7f5d3SJohn Marino     fout = CVS_FOPEN (tmp, "w+");
148*86d7f5d3SJohn Marino     if (fout == NULL)
149*86d7f5d3SJohn Marino     {
150*86d7f5d3SJohn Marino 	if (update_dir[0] == '\0')
151*86d7f5d3SJohn Marino 	    error (1, errno, "cannot open %s", tmp);
152*86d7f5d3SJohn Marino 	else
153*86d7f5d3SJohn Marino 	    error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT);
154*86d7f5d3SJohn Marino     }
155*86d7f5d3SJohn Marino     if (fclose (fout) == EOF)
156*86d7f5d3SJohn Marino     {
157*86d7f5d3SJohn Marino 	if (update_dir[0] == '\0')
158*86d7f5d3SJohn Marino 	    error (1, errno, "cannot close %s", tmp);
159*86d7f5d3SJohn Marino 	else
160*86d7f5d3SJohn Marino 	    error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT);
161*86d7f5d3SJohn Marino     }
162*86d7f5d3SJohn Marino 
163*86d7f5d3SJohn Marino     /* Create a new CVS/Tag file */
164*86d7f5d3SJohn Marino     WriteTag (dir, tag, date, nonbranch, update_dir, repository);
165*86d7f5d3SJohn Marino 
166*86d7f5d3SJohn Marino     TRACE (TRACE_FUNCTION, "Create_Admin");
167*86d7f5d3SJohn Marino 
168*86d7f5d3SJohn Marino     free (reposcopy);
169*86d7f5d3SJohn Marino     free (tmp);
170*86d7f5d3SJohn Marino     return 0;
171*86d7f5d3SJohn Marino }
172