find_names.c revision 17721
1/* 2 * Copyright (c) 1992, Brian Berliner and Jeff Polk 3 * Copyright (c) 1989-1992, Brian Berliner 4 * 5 * You may distribute under the terms of the GNU General Public License as 6 * specified in the README file that comes with the CVS 1.4 kit. 7 * 8 * Find Names 9 * 10 * Finds all the pertinent file names, both from the administration and from the 11 * repository 12 * 13 * Find Dirs 14 * 15 * Finds all pertinent sub-directories of the checked out instantiation and the 16 * repository (and optionally the attic) 17 */ 18 19#include "cvs.h" 20 21static int find_dirs PROTO((char *dir, List * list, int checkadm)); 22static int find_rcs PROTO((char *dir, List * list)); 23 24static List *filelist; 25 26/* 27 * add the key from entry on entries list to the files list 28 */ 29static int add_entries_proc PROTO((Node *, void *)); 30static int 31add_entries_proc (node, closure) 32 Node *node; 33 void *closure; 34{ 35 Node *fnode; 36 37 fnode = getnode (); 38 fnode->type = FILES; 39 fnode->key = xstrdup (node->key); 40 if (addnode (filelist, fnode) != 0) 41 freenode (fnode); 42 return (0); 43} 44 45/* 46 * compare two files list node (for sort) 47 */ 48static int fsortcmp PROTO ((const Node *, const Node *)); 49static int 50fsortcmp (p, q) 51 const Node *p; 52 const Node *q; 53{ 54 return (strcmp (p->key, q->key)); 55} 56 57List * 58Find_Names (repository, which, aflag, optentries) 59 char *repository; 60 int which; 61 int aflag; 62 List **optentries; 63{ 64 List *entries; 65 List *files; 66 char dir[PATH_MAX]; 67 68 /* make a list for the files */ 69 files = filelist = getlist (); 70 71 /* look at entries (if necessary) */ 72 if (which & W_LOCAL) 73 { 74 /* parse the entries file (if it exists) */ 75 entries = Entries_Open (aflag); 76 if (entries != NULL) 77 { 78 /* walk the entries file adding elements to the files list */ 79 (void) walklist (entries, add_entries_proc, NULL); 80 81 /* if our caller wanted the entries list, return it; else free it */ 82 if (optentries != NULL) 83 *optentries = entries; 84 else 85 Entries_Close (entries); 86 } 87 } 88 89 if ((which & W_REPOS) && repository && !isreadable (CVSADM_ENTSTAT)) 90 { 91 /* search the repository */ 92 if (find_rcs (repository, files) != 0) 93 error (1, errno, "cannot open directory %s", repository); 94 95 /* search the attic too */ 96 if (which & W_ATTIC) 97 { 98 (void) sprintf (dir, "%s/%s", repository, CVSATTIC); 99 (void) find_rcs (dir, files); 100 } 101 } 102 103 /* sort the list into alphabetical order and return it */ 104 sortlist (files, fsortcmp); 105 return (files); 106} 107 108/* 109 * create a list of directories to traverse from the current directory 110 */ 111List * 112Find_Directories (repository, which) 113 char *repository; 114 int which; 115{ 116 List *dirlist; 117 118 /* make a list for the directories */ 119 dirlist = getlist (); 120 121 /* find the local ones */ 122 if (which & W_LOCAL) 123 { 124 /* look only for CVS controlled sub-directories */ 125 if (find_dirs (".", dirlist, 1) != 0) 126 error (1, errno, "cannot open current directory"); 127 } 128 129 /* look for sub-dirs in the repository */ 130 if ((which & W_REPOS) && repository) 131 { 132 /* search the repository */ 133 if (find_dirs (repository, dirlist, 0) != 0) 134 error (1, errno, "cannot open directory %s", repository); 135 136#ifdef ATTIC_DIR_SUPPORT /* XXX - FIXME */ 137 /* search the attic too */ 138 if (which & W_ATTIC) 139 { 140 char dir[PATH_MAX]; 141 142 (void) sprintf (dir, "%s/%s", repository, CVSATTIC); 143 (void) find_dirs (dir, dirlist, 0); 144 } 145#endif 146 } 147 148 /* sort the list into alphabetical order and return it */ 149 sortlist (dirlist, fsortcmp); 150 return (dirlist); 151} 152 153/* 154 * Finds all the ,v files in the argument directory, and adds them to the 155 * files list. Returns 0 for success and non-zero if the argument directory 156 * cannot be opened. 157 */ 158static int 159find_rcs (dir, list) 160 char *dir; 161 List *list; 162{ 163 Node *p; 164 struct dirent *dp; 165 DIR *dirp; 166 167 /* set up to read the dir */ 168 if ((dirp = opendir (dir)) == NULL) 169 return (1); 170 171 /* read the dir, grabbing the ,v files */ 172 while ((dp = readdir (dirp)) != NULL) 173 { 174 if (fnmatch (RCSPAT, dp->d_name, 0) == 0) 175 { 176 char *comma; 177 178 comma = strrchr (dp->d_name, ','); /* strip the ,v */ 179 *comma = '\0'; 180 p = getnode (); 181 p->type = FILES; 182 p->key = xstrdup (dp->d_name); 183 if (addnode (list, p) != 0) 184 freenode (p); 185 } 186 } 187 (void) closedir (dirp); 188 return (0); 189} 190 191/* 192 * Finds all the subdirectories of the argument dir and adds them to the 193 * specified list. Sub-directories without a CVS administration directory 194 * are optionally ignored Returns 0 for success or 1 on error. 195 */ 196static int 197find_dirs (dir, list, checkadm) 198 char *dir; 199 List *list; 200 int checkadm; 201{ 202 Node *p; 203 char tmp[PATH_MAX]; 204 struct dirent *dp; 205 DIR *dirp; 206 207 /* set up to read the dir */ 208 if ((dirp = opendir (dir)) == NULL) 209 return (1); 210 211 /* read the dir, grabbing sub-dirs */ 212 while ((dp = readdir (dirp)) != NULL) 213 { 214 if (strcmp (dp->d_name, ".") == 0 || 215 strcmp (dp->d_name, "..") == 0 || 216 strcmp (dp->d_name, CVSATTIC) == 0 || 217 strcmp (dp->d_name, CVSLCK) == 0 || 218 strcmp (dp->d_name, CVSREP) == 0) 219 continue; 220 221#ifdef DT_DIR 222 if (dp->d_type != DT_DIR) 223 { 224 if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK) 225 continue; 226#endif 227 /* don't bother stating ,v files */ 228 if (fnmatch (RCSPAT, dp->d_name, 0) == 0) 229 continue; 230 231 sprintf (tmp, "%s/%s", dir, dp->d_name); 232 if (!isdir (tmp)) 233 continue; 234 235#ifdef DT_DIR 236 } 237#endif 238 239 /* check for administration directories (if needed) */ 240 if (checkadm) 241 { 242 /* blow off symbolic links to dirs in local dir */ 243#ifdef DT_DIR 244 if (dp->d_type != DT_DIR) 245 { 246 /* we're either unknown or a symlink at this point */ 247 if (dp->d_type == DT_LNK) 248 continue; 249#endif 250 if (islink (tmp)) 251 continue; 252#ifdef DT_DIR 253 } 254#endif 255 256 /* check for new style */ 257 (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM); 258 if (!isdir (tmp)) 259 continue; 260 } 261 262 /* put it in the list */ 263 p = getnode (); 264 p->type = DIRS; 265 p->key = xstrdup (dp->d_name); 266 if (addnode (list, p) != 0) 267 freenode (p); 268 } 269 (void) closedir (dirp); 270 return (0); 271} 272