[BACK]Return to util.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Diff for /src/usr.bin/cvs/util.c between version 1.78 and 1.79

version 1.78, 2006/04/14 02:45:35 version 1.79, 2006/05/27 03:30:31
Line 32 
Line 32 
 #include "log.h"  #include "log.h"
 #include "util.h"  #include "util.h"
   
 #if !defined(RCSPROG)  
 /* letter -> mode type map */  /* letter -> mode type map */
 static const int cvs_modetypes[26] = {  static const int cvs_modetypes[26] = {
         -1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1,          -1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1,
Line 67 
Line 66 
         "", "x", "w", "wx", "r", "rx", "rw", "rwx"          "", "x", "w", "wx", "r", "rx", "rw", "rwx"
 };  };
   
   
   
 /*  /*
  * cvs_readrepo()  
  *  
  * Read the path stored in the `Repository' CVS file for a given directory  
  * <dir>, and store that path into the buffer pointed to by <dst>, whose size  
  * is <len>.  
  */  
 int  
 cvs_readrepo(const char *dir, char *dst, size_t len)  
 {  
         size_t dlen, l;  
         FILE *fp;  
         char repo_path[MAXPATHLEN];  
   
         l = cvs_path_cat(dir, "CVS/Repository", repo_path, sizeof(repo_path));  
         if (l >= sizeof(repo_path))  
                 return (-1);  
   
         fp = fopen(repo_path, "r");  
         if (fp == NULL)  
                 return (-1);  
   
         if (fgets(dst, (int)len, fp) == NULL) {  
                 if (ferror(fp)) {  
                         cvs_log(LP_ERRNO, "failed to read from `%s'",  
                             repo_path);  
                 }  
                 (void)fclose(fp);  
                 return (-1);  
         }  
         dlen = strlen(dst);  
         if (dlen > 0 && dst[dlen - 1] == '\n')  
                 dst[--dlen] = '\0';  
   
         (void)fclose(fp);  
         return (0);  
 }  
   
   
 /*  
  * cvs_strtomode()   * cvs_strtomode()
  *   *
  * Read the contents of the string <str> and generate a permission mode from   * Read the contents of the string <str> and generate a permission mode from
Line 141 
Line 99 
                 memset(ms, 0, sizeof ms);                  memset(ms, 0, sizeof ms);
                 if (sscanf(sp, "%c=%3s", &type, ms) != 2 &&                  if (sscanf(sp, "%c=%3s", &type, ms) != 2 &&
                         sscanf(sp, "%c=", &type) != 1) {                          sscanf(sp, "%c=", &type) != 1) {
                         cvs_log(LP_WARN, "failed to scan mode string `%s'", sp);                          cvs_log(LP_ERR, "failed to scan mode string `%s'", sp);
                         continue;                          continue;
                 }                  }
   
                 if (type <= 'a' || type >= 'z' ||                  if (type <= 'a' || type >= 'z' ||
                     cvs_modetypes[type - 'a'] == -1) {                      cvs_modetypes[type - 'a'] == -1) {
                         cvs_log(LP_WARN,                          cvs_log(LP_ERR,
                             "invalid mode type `%c'"                              "invalid mode type `%c'"
                             " (`u', `g' or `o' expected), ignoring", type);                              " (`u', `g' or `o' expected), ignoring", type);
                         continue;                          continue;
Line 159 
Line 117 
                 for (sp = ms; *sp != '\0'; sp++) {                  for (sp = ms; *sp != '\0'; sp++) {
                         if (*sp <= 'a' || *sp >= 'z' ||                          if (*sp <= 'a' || *sp >= 'z' ||
                             cvs_modes[(int)type][*sp - 'a'] == 0) {                              cvs_modes[(int)type][*sp - 'a'] == 0) {
                                 cvs_log(LP_WARN,                                  cvs_log(LP_ERR,
                                     "invalid permission bit `%c'", *sp);                                      "invalid permission bit `%c'", *sp);
                         } else                          } else
                                 m |= cvs_modes[(int)type][*sp - 'a'];                                  m |= cvs_modes[(int)type][*sp - 'a'];
Line 169 
Line 127 
         *mode = m;          *mode = m;
 }  }
   
   
 /*  /*
  * cvs_modetostr()   * cvs_modetostr()
  *   *
Line 241 
Line 198 
 cvs_cksum(const char *file, char *dst, size_t len)  cvs_cksum(const char *file, char *dst, size_t len)
 {  {
         if (len < CVS_CKSUM_LEN) {          if (len < CVS_CKSUM_LEN) {
                 cvs_log(LP_WARN, "buffer too small for checksum");                  cvs_log(LP_ERR, "buffer too small for checksum");
                 return (-1);                  return (-1);
         }          }
         if (MD5File(file, dst) == NULL) {          if (MD5File(file, dst) == NULL) {
                 cvs_log(LP_ERRNO, "failed to generate checksum for %s", file);                  cvs_log(LP_ERR, "failed to generate checksum for %s", file);
                 return (-1);                  return (-1);
         }          }
   
Line 368 
Line 325 
         return (argc);          return (argc);
 }  }
   
   
 /*  /*
  * cvs_makeargv()   * cvs_makeargv()
  *   *
Line 395 
Line 351 
         return (copy);          return (copy);
 }  }
   
   
 /*  /*
  * cvs_freeargv()   * cvs_freeargv()
  *   *
Line 411 
Line 366 
                         xfree(argv[i]);                          xfree(argv[i]);
 }  }
   
   
 /*  /*
  * cvs_mkadmin()  
  *  
  * Create the CVS administrative files within the directory <cdir>.  If the  
  * files already exist, they are kept as is.  
  * Returns 0 on success, or -1 on failure.  
  */  
 int  
 cvs_mkadmin(const char *dpath, const char *rootpath, const char *repopath,  
     char *tag, char *date, int nb)  
 {  
         size_t l;  
         char path[MAXPATHLEN];  
         FILE *fp;  
         CVSENTRIES *ef;  
         struct stat st;  
   
         cvs_log(LP_TRACE, "cvs_mkadmin(%s, %s, %s, %s, %s, %d)",  
             dpath, rootpath, repopath, tag ? tag : "", date ? date : "", nb);  
   
         l = cvs_path_cat(dpath, CVS_PATH_CVSDIR, path, sizeof(path));  
         if (l >= sizeof(path))  
                 fatal("cvs_mkadmin: path truncation");  
   
         if (mkdir(path, 0755) == -1 && errno != EEXIST)  
                 fatal("cvs_mkadmin: mkdir: `%s': %s", path, strerror(errno));  
   
         /* just create an empty Entries file */  
         ef = cvs_ent_open(dpath, O_WRONLY);  
         if (ef != NULL)  
                 cvs_ent_close(ef);  
   
         l = cvs_path_cat(dpath, CVS_PATH_ROOTSPEC, path, sizeof(path));  
         if (l >= sizeof(path))  
                 fatal("cvs_mkadmin: path truncation");  
   
         if (stat(path, &st) == -1 && errno == ENOENT) {  
                 if ((fp = fopen(path, "w")) == NULL)  
                         fatal("cvs_mkadmin: fopen: `%s': %s",  
                             path, strerror(errno));  
   
                 if (rootpath != NULL)  
                         fprintf(fp, "%s\n", rootpath);  
                 (void)fclose(fp);  
         }  
   
         l = cvs_path_cat(dpath, CVS_PATH_REPOSITORY, path, sizeof(path));  
         if (l >= sizeof(path))  
                 fatal("cvs_mkadmin: path truncation");  
   
         if (stat(path, &st) == -1 && errno == ENOENT) {  
                 if ((fp = fopen(path, "w")) == NULL)  
                         fatal("cvs_mkadmin: fopen: `%s': %s",  
                             path, strerror(errno));  
   
                 if (repopath != NULL)  
                         fprintf(fp, "%s\n", repopath);  
                 (void)fclose(fp);  
         }  
   
         /* create CVS/Tag file (if needed) */  
         /* XXX correct? */  
         if (tag != NULL || date != NULL)  
                 (void)cvs_write_tagfile(tag, date, nb);  
   
         return (0);  
 }  
   
   
 /*  
  * cvs_exec()   * cvs_exec()
  */   */
 int  int
Line 491 
Line 376 
         pid_t pid;          pid_t pid;
   
         if ((pid = fork()) == -1) {          if ((pid = fork()) == -1) {
                 cvs_log(LP_ERRNO, "failed to fork");                  cvs_log(LP_ERR, "failed to fork");
                 return (-1);                  return (-1);
         } else if (pid == 0) {          } else if (pid == 0) {
                 execvp(argv[0], argv);                  execvp(argv[0], argv);
                 cvs_log(LP_ERRNO, "failed to exec %s", argv[0]);                  cvs_log(LP_ERR, "failed to exec %s", argv[0]);
                 exit(1);                  exit(1);
         }          }
   
         if (waitpid(pid, &ret, 0) == -1)          if (waitpid(pid, &ret, 0) == -1)
                 cvs_log(LP_ERRNO, "failed to waitpid");                  cvs_log(LP_ERR, "failed to waitpid");
   
         return (ret);          return (ret);
 }  }
Line 561 
Line 446 
                 return (0);                  return (0);
   
         if (unlink(path) == -1 && errno != ENOENT) {          if (unlink(path) == -1 && errno != ENOENT) {
                 cvs_log(LP_ERRNO, "cannot remove `%s'", path);                  cvs_log(LP_ERR, "cannot remove `%s'", path);
                 return (-1);                  return (-1);
         }          }
   
Line 589 
Line 474 
                 return (0);                  return (0);
   
         if ((dirp = opendir(path)) == NULL) {          if ((dirp = opendir(path)) == NULL) {
                 cvs_log(LP_ERRNO, "failed to open '%s'", path);                  cvs_log(LP_ERR, "failed to open '%s'", path);
                 return (-1);                  return (-1);
         }          }
   
Line 611 
Line 496 
   
   
         if (rmdir(path) == -1 && errno != ENOENT) {          if (rmdir(path) == -1 && errno != ENOENT) {
                 cvs_log(LP_ERRNO, "failed to remove '%s'", path);                  cvs_log(LP_ERR, "failed to remove '%s'", path);
                 goto done;                  goto done;
         }          }
   
Line 622 
Line 507 
 }  }
   
 /*  /*
  * Create a directory, and the parent directories if needed.  
  * based upon mkpath() from mkdir.c  
  */  
 int  
 cvs_create_dir(const char *path, int create_adm, char *root, char *repo)  
 {  
         int ret;  
         char *d, *s;  
         struct stat sb;  
         char rpath[MAXPATHLEN], entry[MAXPATHLEN];  
         CVSENTRIES *entf;  
         struct cvs_ent *ent;  
   
         if (create_adm == 1 && root == NULL)  
                 fatal("cvs_create_dir failed");  
   
         s = xstrdup(path);  
         rpath[0] = '\0';  
         if (repo != NULL) {  
                 if (strlcpy(rpath, repo, sizeof(rpath)) >= sizeof(rpath))  
                         fatal("cvs_create_dir: path truncation");  
   
                 if (strlcat(rpath, "/", sizeof(rpath)) >= sizeof(rpath))  
                         fatal("cvs_create_dir: path truncation");  
         }  
   
         ret = -1;  
         entf = NULL;  
         d = strtok(s, "/");  
         while (d != NULL) {  
                 if (stat(d, &sb)) {  
                         /* try to create the directory */  
                         if (errno != ENOENT ||  
                             (mkdir(d, 0755) && errno != EEXIST)) {  
                                 cvs_log(LP_ERRNO, "failed to create `%s'", d);  
                                 goto done;  
                         }  
                 } else if (!S_ISDIR(sb.st_mode)) {  
                         cvs_log(LP_ERR, "`%s' not a directory", d);  
                         goto done;  
                 }  
   
                 /*  
                  * Create administrative files if requested.  
                  */  
                 if (create_adm == 1) {  
                         if (strlcat(rpath, d, sizeof(rpath)) >= sizeof(rpath))  
                                 fatal("cvs_create_dir: path truncation");  
   
                         if (strlcat(rpath, "/", sizeof(rpath)) >= sizeof(rpath))  
                                 fatal("cvs_create_dir: path truncation");  
   
                         cvs_mkadmin(d, root, rpath, NULL, NULL, 0);  
                 }  
   
                 /*  
                  * Add it to the parent directory entry file.  
                  * (if any).  
                  */  
                 entf = cvs_ent_open(".", O_RDWR);  
                 if (entf != NULL && strcmp(d, ".")) {  
                         if (strlcpy(entry, "D/", sizeof(entry)) >=  
                             sizeof(entry) ||  
                             strlcat(entry, d, sizeof(entry)) >= sizeof(entry) ||  
                             strlcat(entry, "////", sizeof(entry)) >=  
                             sizeof(entry))  
                                 fatal("cvs_create_dir: overflow in entry buf");  
   
                         if ((ent = cvs_ent_parse(entry)) == NULL) {  
                                 cvs_log(LP_ERR, "failed to parse entry");  
                                 goto done;  
                         }  
   
                         cvs_ent_remove(entf, d, 0);  
   
                         if (cvs_ent_add(entf, ent) < 0) {  
                                 cvs_log(LP_ERR, "failed to add entry");  
                                 goto done;  
                         }  
                 }  
   
                 if (entf != NULL) {  
                         cvs_ent_close(entf);  
                         entf = NULL;  
                 }  
   
                 /* All went ok, switch to the newly created directory. */  
                 cvs_chdir(d, 0);  
   
                 d = strtok(NULL, "/");  
         }  
   
         ret = 0;  
 done:  
         if (entf != NULL)  
                 cvs_ent_close(entf);  
         xfree(s);  
         return (ret);  
 }  
   
 /*  
  * cvs_path_cat()   * cvs_path_cat()
  *   *
  * Concatenate the two paths <base> and <end> and store the generated path   * Concatenate the two paths <base> and <end> and store the generated path
Line 740 
Line 524 
         len = strlcpy(dst, base, dlen);          len = strlcpy(dst, base, dlen);
         if (len >= dlen - 1) {          if (len >= dlen - 1) {
                 errno = ENAMETOOLONG;                  errno = ENAMETOOLONG;
                 cvs_log(LP_ERRNO, "%s", dst);                  fatal("overflow in cvs_path_cat");
         } else {          } else {
                 dst[len] = '/';                  dst[len] = '/';
                 dst[len + 1] = '\0';                  dst[len + 1] = '\0';
                 len = strlcat(dst, end, dlen);                  len = strlcat(dst, end, dlen);
                 if (len >= dlen) {                  if (len >= dlen) {
                         errno = ENAMETOOLONG;                          errno = ENAMETOOLONG;
                         cvs_log(LP_ERRNO, "%s", dst);                          cvs_log(LP_ERR, "%s", dst);
                 }                  }
         }          }
   
Line 755 
Line 539 
 }  }
   
 /*  /*
  * cvs_rcs_getpath()   * a hack to mimic and thus match gnu cvs behaviour.
  *  
  * Get the RCS path of the file <file> and store it in <buf>, which is  
  * of size <len>. For portability, it is recommended that <buf> always be  
  * at least MAXPATHLEN bytes long.  
  * Returns a pointer to the start of the path on success, or NULL on failure.  
  */   */
 char *  time_t
 cvs_rcs_getpath(CVSFILE *file, char *buf, size_t len)  cvs_hack_time(time_t oldtime, int togmt)
 {  {
         char *repo;          int l;
         struct cvsroot *root;          struct tm *t;
           char tbuf[32];
   
         root = CVS_DIR_ROOT(file);          if (togmt == 1) {
         repo = CVS_DIR_REPO(file);                  t = gmtime(&oldtime);
                   if (t == NULL)
                           return (0);
   
         if (strlcpy(buf, root->cr_dir, len) >= len ||                  return (mktime(t));
             strlcat(buf, "/", len) >= len ||          }
             strlcat(buf, repo, len) >= len ||  
             strlcat(buf, "/", len) >= len ||  
             strlcat(buf, file->cf_name, len) >= len ||  
             strlcat(buf, RCS_FILE_EXT, len) >= len)  
                 fatal("cvs_rcs_getpath: path truncation");  
   
         return (buf);          t = localtime(&oldtime);
   
           l = snprintf(tbuf, sizeof(tbuf), "%d/%d/%d GMT %d:%d:%d",
               t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour,
               t->tm_min, t->tm_sec);
           if (l == -1 || l >= (int)sizeof(tbuf))
                   return (0);
   
           return (cvs_date_parse(tbuf));
 }  }
   
 /*  
  * cvs_write_tagfile()  
  *  
  * Write the CVS/Tag file for current directory.  
  */  
 void  void
 cvs_write_tagfile(char *tag, char *date, int nb)  cvs_get_repo(const char *dir, char *dst, size_t len)
 {  {
           int l;
         FILE *fp;          FILE *fp;
         char tagpath[MAXPATHLEN];          char *s, buf[MAXPATHLEN], fpath[MAXPATHLEN];
   
         if (cvs_noexec == 1)          if (strlcpy(buf, dir, sizeof(buf)) >= sizeof(buf))
                 return;                  fatal("cvs_get_repo: truncation");
   
         if (strlcpy(tagpath, CVS_PATH_TAG, sizeof(tagpath)) >= sizeof(tagpath))          l = snprintf(fpath, sizeof(fpath), "%s/%s", dir, CVS_PATH_REPOSITORY);
                 return;          if (l == -1 || l >= (int)sizeof(fpath))
                   fatal("cvs_get_repo: overflow");
   
         if (tag != NULL || date != NULL) {          if ((fp = fopen(fpath, "r")) != NULL) {
                 fp = fopen(tagpath, "w+");                  fgets(buf, sizeof(buf), fp);
                 if (fp == NULL) {  
                         if (errno != ENOENT)                  if ((s = strrchr(buf, '\n')) != NULL)
                                 cvs_log(LP_NOTICE,                          *s = '\0';
                                     "failed to open `%s' : %s", tagpath,  
                                     strerror(errno));  
                         return;  
                 }  
                 if (tag != NULL) {  
                         if (nb != 0)  
                                 fprintf(fp, "N%s\n", tag);  
                         else  
                                 fprintf(fp, "T%s\n", tag);  
                 } else {  
                         fprintf(fp, "D%s\n", date);  
                 }  
                 (void)fclose(fp);                  (void)fclose(fp);
         } else {  
                 cvs_unlink(tagpath);  
                 return;  
         }          }
   
           l = snprintf(dst, len, "%s/%s", current_cvsroot->cr_dir, buf);
           if (l == -1 || l >= (int)len)
                   fatal("cvs_get_repo: overflow");
 }  }
   
 /*  
  * cvs_parse_tagfile()  
  *  
  * Parse the CVS/Tag file for current directory.  
  *  
  * If it contains a branch tag, sets <tagp>.  
  * If it contains a date, sets <datep>.  
  * If it contains a non-branch tag, sets <nbp>.  
  *  
  * Returns nothing but an error message, and sets <tagp>, <datep> to NULL  
  * and <nbp> to 0.  
  */  
 void  void
 cvs_parse_tagfile(char **tagp, char **datep, int *nbp)  cvs_mkadmin(const char *path, const char *root, const char *repo)
 {  {
         FILE *fp;          FILE *fp;
         int linenum;  
         size_t len;          size_t len;
         char linebuf[128], tagpath[MAXPATHLEN];          struct stat st;
           char buf[MAXPATHLEN];
   
         if (tagp != NULL)          cvs_log(LP_TRACE, "cvs_mkadmin(%s, %s, %s)", path, root, repo);
                 *tagp = (char *)NULL;  
   
         if (datep != NULL)          len = cvs_path_cat(path, CVS_PATH_CVSDIR, buf, sizeof(buf));
                 *datep = (char *)NULL;          if (len >= sizeof(buf))
                   fatal("cvs_mkadmin: truncation");
   
         if (nbp != NULL)          if (stat(buf, &st) != -1)
                 *nbp = 0;  
   
         if (strlcpy(tagpath, CVS_PATH_TAG, sizeof(tagpath)) >= sizeof(tagpath))  
                 return;                  return;
   
         fp = fopen(tagpath, "r");          if (mkdir(buf, 0755) == -1 && errno != EEXIST)
         if (fp == NULL) {                  fatal("cvs_mkadmin: %s: %s", buf, strerror(errno));
                 if (errno != ENOENT)  
                         cvs_log(LP_NOTICE, "failed to open `%s' : %s", tagpath,  
                             strerror(errno));  
                 return;  
         }  
   
         linenum = 0;          len = cvs_path_cat(path, CVS_PATH_ROOTSPEC, buf, sizeof(buf));
           if (len >= sizeof(buf))
                   fatal("cvs_mkadmin: truncation");
   
         while (fgets(linebuf, (int)sizeof(linebuf), fp) != NULL) {          if ((fp = fopen(buf, "w")) == NULL)
                 linenum++;                  fatal("cvs_mkadmin: %s: %s", buf, strerror(errno));
                 if ((len = strlen(linebuf)) == 0)  
                         continue;  
                 if (linebuf[len -1] != '\n') {  
                         cvs_log(LP_WARN, "line too long in `%s:%d'", tagpath,  
                             linenum);  
                         break;  
                 }  
                 linebuf[--len] = '\0';  
   
                 switch (*linebuf) {          fprintf(fp, "%s\n", root);
                 case 'T':          (void)fclose(fp);
                         if (tagp != NULL)  
                                 *tagp = xstrdup(linebuf);  
                         break;  
                 case 'D':  
                         if (datep != NULL)  
                                 *datep = xstrdup(linebuf);  
                         break;  
                 case 'N':  
                         if (tagp != NULL)  
                                 *tagp = xstrdup(linebuf);  
                         if (nbp != NULL)  
                                 *nbp = 1;  
                         break;  
                 default:  
                         break;  
                 }  
         }  
         if (ferror(fp))  
                 cvs_log(LP_NOTICE, "failed to read line from `%s'", tagpath);  
   
           len = cvs_path_cat(path, CVS_PATH_REPOSITORY, buf, sizeof(buf));
           if (len >= sizeof(buf))
                   fatal("cvs_mkadmin: truncation");
   
           if ((fp = fopen(buf, "w")) == NULL)
                   fatal("cvs_mkadmin: %s: %s", buf, strerror(errno));
   
           fprintf(fp, "%s\n", repo);
         (void)fclose(fp);          (void)fclose(fp);
   
           len = cvs_path_cat(path, CVS_PATH_ENTRIES, buf, sizeof(buf));
           if (len >= sizeof(buf))
                   fatal("cvs_mkadmin: truncation");
   
           if ((fp = fopen(buf, "w")) == NULL)
                   fatal("cvs_mkadmin: %s: %s", buf, strerror(errno));
           (void)fclose(fp);
 }  }
   
 /*  void
  * a hack to mimic and thus match gnu cvs behaviour.  cvs_mkpath(const char *path)
  */  
 time_t  
 cvs_hack_time(time_t oldtime, int togmt)  
 {  {
         int l;          FILE *fp;
         struct tm *t;          size_t len;
         char tbuf[32];          struct stat st;
           char *sp, *dp, *dir, rpath[MAXPATHLEN], repo[MAXPATHLEN];
   
         if (togmt == 1) {          dir = xstrdup(path);
                 t = gmtime(&oldtime);  
                 if (t == NULL)  
                         return (0);  
   
                 return (mktime(t));          STRIP_SLASH(dir);
           cvs_log(LP_TRACE, "cvs_mkpath(%s)", dir);
   
           repo[0] = '\0';
           rpath[0] = '\0';
   
           if (cvs_cmdop == CVS_OP_UPDATE) {
                   if ((fp = fopen(CVS_PATH_REPOSITORY, "r")) != NULL) {
                           fgets(repo, sizeof(repo), fp);
                           if (repo[strlen(repo) - 1] == '\n')
                                   repo[strlen(repo) - 1] = '\0';
                           (void)fclose(fp);
                   }
         }          }
   
         t = localtime(&oldtime);          for (sp = dir; sp != NULL; sp = dp) {
                   dp = strchr(sp, '/');
                   if (dp != NULL)
                           *(dp++) = '\0';
   
         l = snprintf(tbuf, sizeof(tbuf), "%d/%d/%d GMT %d:%d:%d",                  if (repo[0] != '\0') {
             t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour,                          len = strlcat(repo, "/", sizeof(repo));
             t->tm_min, t->tm_sec);                          if (len >= (int)sizeof(repo))
         if (l == -1 || l >= (int)sizeof(tbuf))                                  fatal("cvs_mkpath: overflow");
                 return (0);                  }
   
         return (cvs_date_parse(tbuf));                  len = strlcat(repo, sp, sizeof(repo));
 }                  if (len >= (int)sizeof(repo))
                           fatal("cvs_mkpath: overflow");
   
 #endif  /* !RCSPROG */                  if (rpath[0] != '\0') {
                           len = strlcat(rpath, "/", sizeof(rpath));
                           if (len >= (int)sizeof(rpath))
                                   fatal("cvs_mkpath: overflow");
                   }
   
                   len = strlcat(rpath, sp, sizeof(rpath));
                   if (len >= (int)sizeof(rpath))
                           fatal("cvs_mkpath: overflow");
   
                   if (stat(repo, &st) != -1)
                           continue;
   
                   if (mkdir(rpath, 0755) == -1 && errno != EEXIST)
                           fatal("cvs_mkpath: %s: %s", rpath, strerror(errno));
   
                   cvs_mkadmin(rpath, current_cvsroot->cr_dir, repo);
           }
   
           xfree(dir);
   }
   
 /*  /*
  * Split the contents of a file into a list of lines.   * Split the contents of a file into a list of lines.

Legend:
Removed from v.1.78  
changed lines
  Added in v.1.79