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