create_adm.c revision 175262
167754Smsmith/* 267754Smsmith * Copyright (C) 1986-2005 The Free Software Foundation, Inc. 367754Smsmith * 467754Smsmith * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, 582367Smsmith * and others. 667754Smsmith * 767754Smsmith * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk 867754Smsmith * Portions Copyright (C) 1989-1992, Brian Berliner 967754Smsmith * 1067754Smsmith * You may distribute under the terms of the GNU General Public License as 1167754Smsmith * specified in the README file that comes with the CVS source distribution. 1267754Smsmith * 1371867Smsmith * Create Administration. 1470243Smsmith * 1567754Smsmith * Creates a CVS administration directory based on the argument repository; the 1667754Smsmith * "Entries" file is prefilled from the "initrecord" argument. 1767754Smsmith */ 1867754Smsmith 1967754Smsmith#include "cvs.h" 2067754Smsmith 2167754Smsmith/* update_dir includes dir as its last component. 2267754Smsmith 2367754Smsmith Return value is 0 for success, or 1 if we printed a warning message. 2467754Smsmith Note that many errors are still fatal; particularly for unlikely errors 2567754Smsmith a fatal error is probably better than a warning which might be missed 2667754Smsmith or after which CVS might do something non-useful. If WARN is zero, then 2767754Smsmith don't print warnings; all errors are fatal then. */ 2867754Smsmith 2967754Smsmithint 3067754SmsmithCreate_Admin (dir, update_dir, repository, tag, date, nonbranch, warn, 3167754Smsmith dotemplate) 3267754Smsmith const char *dir; 3367754Smsmith const char *update_dir; 3467754Smsmith const char *repository; 3567754Smsmith const char *tag; 3667754Smsmith const char *date; 3767754Smsmith int nonbranch; 3867754Smsmith int warn; 3967754Smsmith int dotemplate; 4067754Smsmith{ 4167754Smsmith FILE *fout; 4267754Smsmith char *cp; 4367754Smsmith char *reposcopy; 4467754Smsmith char *tmp; 4567754Smsmith 4667754Smsmith if (trace) 4767754Smsmith { 4867754Smsmith fprintf (stderr, "%s-> Create_Admin (%s, %s, %s, %s, %s, %d, %d, %d)\n", 4967754Smsmith CLIENT_SERVER_STR, 5067754Smsmith dir, update_dir, repository, tag ? tag : "", 5167754Smsmith date ? date : "", nonbranch, warn, dotemplate); 5267754Smsmith } 5367754Smsmith 5467754Smsmith if (noexec) 5567754Smsmith return 0; 5667754Smsmith 5767754Smsmith tmp = xmalloc (strlen (dir) + 100); 5867754Smsmith (void) sprintf (tmp, "%s/%s", dir, CVSADM); 5967754Smsmith if (isfile (tmp)) 6067754Smsmith error (1, 0, "there is a version in %s already", update_dir); 6167754Smsmith 6267754Smsmith if (CVS_MKDIR (tmp, 0777) < 0) 6367754Smsmith { 6467754Smsmith /* We want to print out the entire update_dir, since a lot of 6567754Smsmith our code calls this function with dir == "." or dir == 6667754Smsmith NULL. I hope that gives enough information in cases like 6767754Smsmith absolute pathnames; printing out xgetwd or something would 6867754Smsmith be way too verbose in the common cases. */ 6967754Smsmith 7067754Smsmith if (warn) 7167754Smsmith { 7267754Smsmith /* The reason that this is a warning, rather than silently 7367754Smsmith just skipping creating the directory, is that we don't want 7467754Smsmith CVS's behavior to vary subtly based on factors (like directory 7567754Smsmith permissions) which are not made clear to the user. With 7667754Smsmith the warning at least we let them know what is going on. */ 7767754Smsmith error (0, errno, "warning: cannot make directory %s in %s", 7867754Smsmith CVSADM, update_dir); 7967754Smsmith free (tmp); 8067754Smsmith return 1; 8167754Smsmith } 8267754Smsmith else 8367754Smsmith error (1, errno, "cannot make directory %s in %s", 8467754Smsmith CVSADM, update_dir); 8567754Smsmith } 8667754Smsmith 8767754Smsmith /* record the current cvs root for later use */ 8867754Smsmith 8967754Smsmith Create_Root (dir, current_parsed_root->original); 9067754Smsmith if (dir != NULL) 9167754Smsmith (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP); 9267754Smsmith else 9367754Smsmith (void) strcpy (tmp, CVSADM_REP); 9467754Smsmith fout = CVS_FOPEN (tmp, "w+"); 9567754Smsmith if (fout == NULL) 9667754Smsmith { 9767754Smsmith if (update_dir[0] == '\0') 9867754Smsmith error (1, errno, "cannot open %s", tmp); 9967754Smsmith else 10067754Smsmith error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP); 10167754Smsmith } 10267754Smsmith reposcopy = xstrdup (repository); 10367754Smsmith Sanitize_Repository_Name (reposcopy); 10467754Smsmith 10567754Smsmith /* The top level of the repository is a special case -- we need to 10667754Smsmith write it with an extra dot at the end. This trailing `.' stuff 10767754Smsmith rubs me the wrong way -- on the other hand, I don't want to 10867754Smsmith spend the time making sure all of the code can handle it if we 10967754Smsmith don't do it. */ 11067754Smsmith 11167754Smsmith if (strcmp (reposcopy, current_parsed_root->directory) == 0) 11267754Smsmith { 11367754Smsmith reposcopy = xrealloc (reposcopy, strlen (reposcopy) + 3); 11467754Smsmith strcat (reposcopy, "/."); 11567754Smsmith } 11667754Smsmith 11767754Smsmith cp = reposcopy; 11867754Smsmith 11967754Smsmith /* 12067754Smsmith * If the Repository file is to hold a relative path, try to strip off 12167754Smsmith * the leading CVSroot argument. 12267754Smsmith */ 12367754Smsmith { 12477424Smsmith char *path = xmalloc (strlen (current_parsed_root->directory) + 2); 12567754Smsmith 12667754Smsmith (void) sprintf (path, "%s/", current_parsed_root->directory); 12767754Smsmith if (strncmp (cp, path, strlen (path)) == 0) 12877424Smsmith cp += strlen (path); 12967754Smsmith free (path); 13077424Smsmith } 13167754Smsmith 13267754Smsmith if (fprintf (fout, "%s\n", cp) < 0) 13367754Smsmith { 13467754Smsmith if (update_dir[0] == '\0') 13567754Smsmith error (1, errno, "write to %s failed", tmp); 13667754Smsmith else 13767754Smsmith error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP); 13867754Smsmith } 13977424Smsmith if (fclose (fout) == EOF) 14067754Smsmith { 14177424Smsmith if (update_dir[0] == '\0') 14277424Smsmith error (1, errno, "cannot close %s", tmp); 14377424Smsmith else 14467754Smsmith error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP); 14567754Smsmith } 14667754Smsmith 14777424Smsmith /* now, do the Entries file */ 14877424Smsmith if (dir != NULL) 14977424Smsmith (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT); 15067754Smsmith else 15167754Smsmith (void) strcpy (tmp, CVSADM_ENT); 15277424Smsmith fout = CVS_FOPEN (tmp, "w+"); 15377424Smsmith if (fout == NULL) 15477424Smsmith { 15567754Smsmith if (update_dir[0] == '\0') 15667754Smsmith error (1, errno, "cannot open %s", tmp); 15767754Smsmith else 15867754Smsmith error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT); 15967754Smsmith } 16067754Smsmith if (fclose (fout) == EOF) 16167754Smsmith { 16282367Smsmith if (update_dir[0] == '\0') 16382367Smsmith error (1, errno, "cannot close %s", tmp); 16467754Smsmith else 16567754Smsmith error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT); 16667754Smsmith } 16767754Smsmith 16882367Smsmith /* Create a new CVS/Tag file */ 16967754Smsmith WriteTag (dir, tag, date, nonbranch, update_dir, repository); 17067754Smsmith 17167754Smsmith#ifdef SERVER_SUPPORT 17282367Smsmith if (server_active && dotemplate) 17367754Smsmith { 17467754Smsmith server_template (update_dir, repository); 17567754Smsmith } 17682367Smsmith 17767754Smsmith if (trace) 17867754Smsmith { 17967754Smsmith fprintf (stderr, "%c<- Create_Admin\n", 18082367Smsmith (server_active) ? 'S' : ' '); 18167754Smsmith } 18267754Smsmith#endif 18367754Smsmith 18482367Smsmith free (reposcopy); 18567754Smsmith free (tmp); 18667754Smsmith return 0; 18767754Smsmith} 18867754Smsmith