/* * Copyright (c) 1992, Brian Berliner and Jeff Polk * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as * specified in the README file that comes with the CVS 1.4 kit. * * Find Names * * Finds all the pertinent file names, both from the administration and from the * repository * * Find Dirs * * Finds all pertinent sub-directories of the checked out instantiation and the * repository (and optionally the attic) */ #include "cvs.h" static int find_dirs PROTO((char *dir, List * list, int checkadm)); static int find_rcs PROTO((char *dir, List * list)); static List *filelist; /* * add the key from entry on entries list to the files list */ static int add_entries_proc PROTO((Node *, void *)); static int add_entries_proc (node, closure) Node *node; void *closure; { Node *fnode; fnode = getnode (); fnode->type = FILES; fnode->key = xstrdup (node->key); if (addnode (filelist, fnode) != 0) freenode (fnode); return (0); } /* * compare two files list node (for sort) */ static int fsortcmp PROTO ((const Node *, const Node *)); static int fsortcmp (p, q) const Node *p; const Node *q; { return (strcmp (p->key, q->key)); } List * Find_Names (repository, which, aflag, optentries) char *repository; int which; int aflag; List **optentries; { List *entries; List *files; char dir[PATH_MAX]; /* make a list for the files */ files = filelist = getlist (); /* look at entries (if necessary) */ if (which & W_LOCAL) { /* parse the entries file (if it exists) */ entries = Entries_Open (aflag); if (entries != NULL) { /* walk the entries file adding elements to the files list */ (void) walklist (entries, add_entries_proc, NULL); /* if our caller wanted the entries list, return it; else free it */ if (optentries != NULL) *optentries = entries; else Entries_Close (entries); } } if ((which & W_REPOS) && repository && !isreadable (CVSADM_ENTSTAT)) { /* search the repository */ if (find_rcs (repository, files) != 0) error (1, errno, "cannot open directory %s", repository); /* search the attic too */ if (which & W_ATTIC) { (void) sprintf (dir, "%s/%s", repository, CVSATTIC); (void) find_rcs (dir, files); } } /* sort the list into alphabetical order and return it */ sortlist (files, fsortcmp); return (files); } /* * create a list of directories to traverse from the current directory */ List * Find_Directories (repository, which) char *repository; int which; { List *dirlist; /* make a list for the directories */ dirlist = getlist (); /* find the local ones */ if (which & W_LOCAL) { /* look only for CVS controlled sub-directories */ if (find_dirs (".", dirlist, 1) != 0) error (1, errno, "cannot open current directory"); } /* look for sub-dirs in the repository */ if ((which & W_REPOS) && repository) { /* search the repository */ if (find_dirs (repository, dirlist, 0) != 0) error (1, errno, "cannot open directory %s", repository); #ifdef ATTIC_DIR_SUPPORT /* XXX - FIXME */ /* search the attic too */ if (which & W_ATTIC) { char dir[PATH_MAX]; (void) sprintf (dir, "%s/%s", repository, CVSATTIC); (void) find_dirs (dir, dirlist, 0); } #endif } /* sort the list into alphabetical order and return it */ sortlist (dirlist, fsortcmp); return (dirlist); } /* * Finds all the ,v files in the argument directory, and adds them to the * files list. Returns 0 for success and non-zero if the argument directory * cannot be opened. */ static int find_rcs (dir, list) char *dir; List *list; { Node *p; struct dirent *dp; DIR *dirp; /* set up to read the dir */ if ((dirp = opendir (dir)) == NULL) return (1); /* read the dir, grabbing the ,v files */ while ((dp = readdir (dirp)) != NULL) { if (fnmatch (RCSPAT, dp->d_name, 0) == 0) { char *comma; comma = strrchr (dp->d_name, ','); /* strip the ,v */ *comma = '\0'; p = getnode (); p->type = FILES; p->key = xstrdup (dp->d_name); if (addnode (list, p) != 0) freenode (p); } } (void) closedir (dirp); return (0); } /* * Finds all the subdirectories of the argument dir and adds them to the * specified list. Sub-directories without a CVS administration directory * are optionally ignored Returns 0 for success or 1 on error. */ static int find_dirs (dir, list, checkadm) char *dir; List *list; int checkadm; { Node *p; char tmp[PATH_MAX]; struct dirent *dp; DIR *dirp; /* set up to read the dir */ if ((dirp = opendir (dir)) == NULL) return (1); /* read the dir, grabbing sub-dirs */ while ((dp = readdir (dirp)) != NULL) { if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0 || strcmp (dp->d_name, CVSATTIC) == 0 || strcmp (dp->d_name, CVSLCK) == 0 || strcmp (dp->d_name, CVSREP) == 0) continue; #ifdef DT_DIR if (dp->d_type != DT_DIR) { if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK) continue; #endif /* don't bother stating ,v files */ if (fnmatch (RCSPAT, dp->d_name, 0) == 0) continue; sprintf (tmp, "%s/%s", dir, dp->d_name); if (!isdir (tmp)) continue; #ifdef DT_DIR } #endif /* check for administration directories (if needed) */ if (checkadm) { /* blow off symbolic links to dirs in local dir */ #ifdef DT_DIR if (dp->d_type != DT_DIR) { /* we're either unknown or a symlink at this point */ if (dp->d_type == DT_LNK) continue; #endif if (islink (tmp)) continue; #ifdef DT_DIR } #endif /* check for new style */ (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM); if (!isdir (tmp)) continue; } /* put it in the list */ p = getnode (); p->type = DIRS; p->key = xstrdup (dp->d_name); if (addnode (list, p) != 0) freenode (p); } (void) closedir (dirp); return (0); }