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