2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
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 source distribution.
10 * Finds all the pertinent file names, both from the administration and from the
15 * Finds all pertinent sub-directories of the checked out instantiation and the
16 * repository (and optionally the attic)
21 static int find_dirs PROTO((char *dir, List * list, int checkadm,
23 static int find_rcs PROTO((char *dir, List * list));
24 static int add_subdir_proc PROTO((Node *, void *));
25 static int register_subdir_proc PROTO((Node *, void *));
27 static List *filelist;
30 * add the key from entry on entries list to the files list
32 static int add_entries_proc PROTO((Node *, void *));
34 add_entries_proc (node, closure)
41 entnode = (Entnode *) node->data;
42 if (entnode->type != ENT_FILE)
47 fnode->key = xstrdup (node->key);
48 if (addnode (filelist, fnode) != 0)
54 Find_Names (repository, which, aflag, optentries)
63 /* make a list for the files */
64 files = filelist = getlist ();
66 /* look at entries (if necessary) */
69 /* parse the entries file (if it exists) */
70 entries = Entries_Open (aflag, NULL);
73 /* walk the entries file adding elements to the files list */
74 (void) walklist (entries, add_entries_proc, NULL);
76 /* if our caller wanted the entries list, return it; else free it */
77 if (optentries != NULL)
78 *optentries = entries;
80 Entries_Close (entries);
84 if ((which & W_REPOS) && repository && !isreadable (CVSADM_ENTSTAT))
86 /* search the repository */
87 if (find_rcs (repository, files) != 0)
88 error (1, errno, "cannot open directory %s", repository);
90 /* search the attic too */
94 dir = xmalloc (strlen (repository) + sizeof (CVSATTIC) + 10);
95 (void) sprintf (dir, "%s/%s", repository, CVSATTIC);
96 (void) find_rcs (dir, files);
101 /* sort the list into alphabetical order and return it */
102 sortlist (files, fsortcmp);
107 * Add an entry from the subdirs list to the directories list. This
108 * is called via walklist.
112 add_subdir_proc (p, closure)
116 List *dirlist = (List *) closure;
120 entnode = (Entnode *) p->data;
121 if (entnode->type != ENT_SUBDIR)
126 dnode->key = xstrdup (entnode->user);
127 if (addnode (dirlist, dnode) != 0)
133 * Register a subdirectory. This is called via walklist.
138 register_subdir_proc (p, closure)
142 List *entries = (List *) closure;
144 Subdir_Register (entries, (char *) NULL, p->key);
149 * create a list of directories to traverse from the current directory
152 Find_Directories (repository, which, entries)
159 /* make a list for the directories */
160 dirlist = getlist ();
162 /* find the local ones */
166 struct stickydirtag *sdtp;
168 /* Look through the Entries file. */
171 tmpentries = entries;
172 else if (isfile (CVSADM_ENT))
173 tmpentries = Entries_Open (0, NULL);
177 if (tmpentries != NULL)
178 sdtp = (struct stickydirtag *) tmpentries->list->data;
180 /* If we do have an entries list, then if sdtp is NULL, or if
181 sdtp->subdirs is nonzero, all subdirectory information is
182 recorded in the entries list. */
183 if (tmpentries != NULL && (sdtp == NULL || sdtp->subdirs))
184 walklist (tmpentries, add_subdir_proc, (void *) dirlist);
187 /* This is an old working directory, in which subdirectory
188 information is not recorded in the Entries file. Find
189 the subdirectories the hard way, and, if possible, add
190 it to the Entries file for next time. */
192 /* FIXME-maybe: find_dirs is bogus for this usage because
193 it skips CVSATTIC and CVSLCK directories--those names
194 should be special only in the repository. However, in
195 the interests of not perturbing this code, we probably
196 should leave well enough alone unless we want to write
197 a sanity.sh test case (which would operate by manually
198 hacking on the CVS/Entries file). */
200 if (find_dirs (".", dirlist, 1, tmpentries) != 0)
201 error (1, errno, "cannot open current directory");
202 if (tmpentries != NULL)
204 if (! list_isempty (dirlist))
205 walklist (dirlist, register_subdir_proc,
206 (void *) tmpentries);
208 Subdirs_Known (tmpentries);
212 if (entries == NULL && tmpentries != NULL)
213 Entries_Close (tmpentries);
216 /* look for sub-dirs in the repository */
217 if ((which & W_REPOS) && repository)
219 /* search the repository */
220 if (find_dirs (repository, dirlist, 0, entries) != 0)
221 error (1, errno, "cannot open directory %s", repository);
223 /* We don't need to look in the attic because directories
224 never go in the attic. In the future, there hopefully will
225 be a better mechanism for detecting whether a directory in
226 the repository is alive or dead; it may or may not involve
227 moving directories to the attic. */
230 /* sort the list into alphabetical order and return it */
231 sortlist (dirlist, fsortcmp);
236 * Finds all the ,v files in the argument directory, and adds them to the
237 * files list. Returns 0 for success and non-zero if the argument directory
249 /* set up to read the dir */
250 if ((dirp = CVS_OPENDIR (dir)) == NULL)
253 /* read the dir, grabbing the ,v files */
254 while ((dp = readdir (dirp)) != NULL)
256 if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
260 comma = strrchr (dp->d_name, ','); /* strip the ,v */
264 p->key = xstrdup (dp->d_name);
265 if (addnode (list, p) != 0)
269 (void) closedir (dirp);
274 * Finds all the subdirectories of the argument dir and adds them to
275 * the specified list. Sub-directories without a CVS administration
276 * directory are optionally ignored. If ENTRIES is not NULL, all
277 * files on the list are ignored. Returns 0 for success or 1 on
281 find_dirs (dir, list, checkadm, entries)
292 int skip_emptydir = 0;
294 /* First figure out whether we need to skip directories named
295 Emptydir. Except in the CVSNULLREPOS case, Emptydir is just
296 a normal directory name. */
298 && strncmp (dir, CVSroot_directory, strlen (CVSroot_directory)) == 0
299 && ISDIRSEP (dir[strlen (CVSroot_directory)])
300 && strcmp (dir + strlen (CVSroot_directory) + 1, CVSROOTADM) == 0)
303 /* set up to read the dir */
304 if ((dirp = CVS_OPENDIR (dir)) == NULL)
307 /* read the dir, grabbing sub-dirs */
308 while ((dp = readdir (dirp)) != NULL)
310 if (strcmp (dp->d_name, ".") == 0 ||
311 strcmp (dp->d_name, "..") == 0 ||
312 strcmp (dp->d_name, CVSATTIC) == 0 ||
313 strcmp (dp->d_name, CVSLCK) == 0 ||
314 strcmp (dp->d_name, CVSREP) == 0)
317 /* findnode() is going to be significantly faster than stat()
318 because it involves no system calls. That is why we bother
319 with the entries argument, and why we check this first. */
320 if (entries != NULL && findnode (entries, dp->d_name) != NULL)
324 && strcmp (dp->d_name, CVSNULLREPOS) == 0)
328 if (dp->d_type != DT_DIR)
330 if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
333 /* don't bother stating ,v files */
334 if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
339 strlen (dir) + strlen (dp->d_name) + 10);
340 sprintf (tmp, "%s/%s", dir, dp->d_name);
348 /* check for administration directories (if needed) */
351 /* blow off symbolic links to dirs in local dir */
353 if (dp->d_type != DT_DIR)
355 /* we're either unknown or a symlink at this point */
356 if (dp->d_type == DT_LNK)
359 /* Note that we only get here if we already set tmp
367 /* check for new style */
370 (strlen (dir) + strlen (dp->d_name)
371 + sizeof (CVSADM) + 10));
372 (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
377 /* put it in the list */
380 p->key = xstrdup (dp->d_name);
381 if (addnode (list, p) != 0)
384 (void) closedir (dirp);