create_adm.c revision 54427
1163953Srrs/*
2185694Srrs * Copyright (c) 1992, Brian Berliner and Jeff Polk
3235828Stuexen * Copyright (c) 1989-1992, Brian Berliner
4235828Stuexen *
5163953Srrs * You may distribute under the terms of the GNU General Public License as
6163953Srrs * specified in the README file that comes with the CVS source distribution.
7163953Srrs *
8163953Srrs * Create Administration.
9163953Srrs *
10228653Stuexen * Creates a CVS administration directory based on the argument repository; the
11163953Srrs * "Entries" file is prefilled from the "initrecord" argument.
12163953Srrs */
13163953Srrs
14228653Stuexen#include "cvs.h"
15163953Srrs
16163953Srrs/* update_dir includes dir as its last component.
17163953Srrs
18163953Srrs   Return value is 0 for success, or 1 if we printed a warning message.
19163953Srrs   Note that many errors are still fatal; particularly for unlikely errors
20163953Srrs   a fatal error is probably better than a warning which might be missed
21163953Srrs   or after which CVS might do something non-useful.  If WARN is zero, then
22163953Srrs   don't print warnings; all errors are fatal then.  */
23163953Srrs
24163953Srrsint
25163953SrrsCreate_Admin (dir, update_dir, repository, tag, date, nonbranch, warn)
26163953Srrs    char *dir;
27163953Srrs    char *update_dir;
28163953Srrs    char *repository;
29163953Srrs    char *tag;
30163953Srrs    char *date;
31163953Srrs    int nonbranch;
32163953Srrs    int warn;
33163953Srrs{
34163953Srrs    FILE *fout;
35235828Stuexen    char *cp;
36166086Srrs    char *reposcopy;
37163953Srrs    char *tmp;
38163953Srrs
39163953Srrs    if (trace)
40163953Srrs    {
41238475Stuexen	fprintf (stderr, "%s-> Create_Admin (%s, %s, %s, %s, %s, %d, %d)\n",
42283699Stuexen		 CLIENT_SERVER_STR,
43167695Srrs		 dir, update_dir, repository, tag ? tag : "",
44167598Srrs		 date ? date : "", nonbranch, warn);
45163953Srrs    }
46163953Srrs
47163953Srrs    if (noexec)
48163953Srrs	return 0;
49163953Srrs
50163953Srrs    tmp = xmalloc (strlen (dir) + 100);
51163953Srrs    if (dir != NULL)
52170091Srrs	(void) sprintf (tmp, "%s/%s", dir, CVSADM);
53185694Srrs    else
54164085Srrs	(void) strcpy (tmp, CVSADM);
55163953Srrs    if (isfile (tmp))
56163953Srrs	error (1, 0, "there is a version in %s already", update_dir);
57217611Stuexen
58217760Stuexen    if (CVS_MKDIR (tmp, 0777) < 0)
59170091Srrs    {
60163953Srrs	/* We want to print out the entire update_dir, since a lot of
61163953Srrs	   our code calls this function with dir == "." or dir ==
62163953Srrs	   NULL.  I hope that gives enough information in cases like
63163953Srrs	   absolute pathnames; printing out xgetwd or something would
64163953Srrs	   be way too verbose in the common cases.  */
65179783Srrs
66179783Srrs	if (warn)
67163953Srrs	{
68179783Srrs	    /* The reason that this is a warning, rather than silently
69163953Srrs	       just skipping creating the directory, is that we don't want
70163953Srrs	       CVS's behavior to vary subtly based on factors (like directory
71163953Srrs	       permissions) which are not made clear to the user.  With
72163953Srrs	       the warning at least we let them know what is going on.  */
73163953Srrs	    error (0, errno, "warning: cannot make directory %s in %s",
74179783Srrs		   CVSADM, update_dir);
75170056Srrs	    free (tmp);
76163953Srrs	    return 1;
77163953Srrs	}
78163953Srrs	else
79163953Srrs	    error (1, errno, "cannot make directory %s in %s",
80163953Srrs		   CVSADM, update_dir);
81179783Srrs    }
82179783Srrs
83179783Srrs    /* record the current cvs root for later use */
84179783Srrs
85179783Srrs    Create_Root (dir, CVSroot_original);
86179783Srrs    if (dir != NULL)
87179783Srrs	(void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
88179783Srrs    else
89179783Srrs	(void) strcpy (tmp, CVSADM_REP);
90163953Srrs    fout = CVS_FOPEN (tmp, "w+");
91163953Srrs    if (fout == NULL)
92179783Srrs    {
93179783Srrs	if (update_dir[0] == '\0')
94179783Srrs	    error (1, errno, "cannot open %s", tmp);
95179783Srrs	else
96179783Srrs	    error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP);
97163953Srrs    }
98166023Srrs    reposcopy = xstrdup (repository);
99163953Srrs    Sanitize_Repository_Name (reposcopy);
100179157Srrs
101228653Stuexen    /* The top level of the repository is a special case -- we need to
102163953Srrs       write it with an extra dot at the end.  This trailing `.' stuff
103163953Srrs       rubs me the wrong way -- on the other hand, I don't want to
104197257Stuexen       spend the time making sure all of the code can handle it if we
105163953Srrs       don't do it. */
106163953Srrs
107163953Srrs    if (strcmp (reposcopy, CVSroot_directory) == 0)
108163953Srrs    {
109197257Stuexen	reposcopy = xrealloc (reposcopy, strlen (reposcopy) + 3);
110197257Stuexen	strcat (reposcopy, "/.");
111197257Stuexen    }
112197257Stuexen
113163953Srrs    cp = reposcopy;
114197257Stuexen
115163953Srrs#ifdef RELATIVE_REPOS
116163953Srrs    /*
117163953Srrs     * If the Repository file is to hold a relative path, try to strip off
118163953Srrs     * the leading CVSroot argument.
119197257Stuexen     */
120163953Srrs    if (CVSroot_directory != NULL)
121163953Srrs    {
122163953Srrs	char *path = xmalloc (strlen (CVSroot_directory) + 10);
123163953Srrs
124163953Srrs	(void) sprintf (path, "%s/", CVSroot_directory);
125190689Srrs	if (strncmp (cp, path, strlen (path)) == 0)
126190689Srrs	    cp += strlen (path);
127190689Srrs	free (path);
128283729Stuexen    }
129163953Srrs#endif
130283729Stuexen
131283729Stuexen    if (fprintf (fout, "%s\n", cp) < 0)
132283729Stuexen    {
133283729Stuexen	if (update_dir[0] == '\0')
134283729Stuexen	    error (1, errno, "write to %s failed", tmp);
135283729Stuexen	else
136283729Stuexen	    error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP);
137283729Stuexen    }
138283729Stuexen    if (fclose (fout) == EOF)
139283729Stuexen    {
140163953Srrs	if (update_dir[0] == '\0')
141163953Srrs	    error (1, errno, "cannot close %s", tmp);
142163953Srrs	else
143163953Srrs	    error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP);
144163953Srrs    }
145221249Stuexen
146163953Srrs    /* now, do the Entries file */
147163953Srrs    if (dir != NULL)
148163953Srrs	(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
149163953Srrs    else
150163953Srrs	(void) strcpy (tmp, CVSADM_ENT);
151163953Srrs    fout = CVS_FOPEN (tmp, "w+");
152163953Srrs    if (fout == NULL)
153163953Srrs    {
154163953Srrs	if (update_dir[0] == '\0')
155163953Srrs	    error (1, errno, "cannot open %s", tmp);
156163953Srrs	else
157163953Srrs	    error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT);
158163953Srrs    }
159163953Srrs    if (fclose (fout) == EOF)
160169420Srrs    {
161163953Srrs	if (update_dir[0] == '\0')
162169420Srrs	    error (1, errno, "cannot close %s", tmp);
163163953Srrs	else
164163953Srrs	    error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT);
165163953Srrs    }
166163953Srrs
167163953Srrs    /* Create a new CVS/Tag file */
168163953Srrs    WriteTag (dir, tag, date, nonbranch, update_dir, repository);
169163953Srrs
170163953Srrs#ifdef SERVER_SUPPORT
171163953Srrs    if (server_active)
172163953Srrs    {
173163953Srrs	server_template (update_dir, repository);
174163953Srrs    }
175163953Srrs
176163953Srrs    if (trace)
177163953Srrs    {
178163953Srrs	fprintf (stderr, "%c<- Create_Admin\n",
179163953Srrs		 (server_active) ? 'S' : ' ');
180163953Srrs    }
181163953Srrs#endif
182241913Sglebius
183163953Srrs    free (reposcopy);
184171943Srrs    free (tmp);
185163953Srrs    return 0;
186163953Srrs}
187163953Srrs