]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/global/lib/find.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / contrib / global / lib / find.c
1 /*
2  * Copyright (c) 1996, 1997, 1998 Shigio Yamaguchi. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by Shigio Yamaguchi.
15  * 4. Neither the name of the author nor the names of any co-contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *      find.c                                  1-May-98
32  *
33  */
34 /*
35  * USEFIND      use find(1) to traverse directory tree.
36  *              Otherwise, use dirent(3) library.
37  */
38 #define USEFIND
39
40 #include <sys/param.h>
41
42 #include <assert.h>
43 #include <ctype.h>
44 #ifndef USEFIND
45 #include <dirent.h>
46 #ifndef BSD4_4
47 #include <sys/stat.h>
48 #endif
49 #endif
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <strings.h>
53 #include <regex.h>
54
55 #include "conf.h"
56 #include "die.h"
57 #include "find.h"
58 #include "gparam.h"
59 #include "locatestring.h"
60 #include "makepath.h"
61 #include "strbuf.h"
62
63 /*
64  * usage of findxxx()
65  *
66  *      findopen(db);
67  *      while (path = findread(&length)) {
68  *              ...
69  *      }
70  *      findclose();
71  *
72  */
73 static regex_t  skip_area;
74 static regex_t  *skip = &skip_area;
75 static int      opened;
76
77 static void     trim __P((char *));
78
79 /*
80  * trim: remove blanks and '\'.
81  */
82 static void
83 trim(s)
84 char    *s;
85 {
86         char    *p;
87
88         for (p = s; *s; s++) {
89                 if (isspace(*s))
90                         continue;       
91                 if (*s == '\\' && *(s + 1))
92                         s++;
93                 *p++ = *s;
94         }
95         *p = 0;
96 }
97 #ifdef USEFIND
98 /*----------------------------------------------------------------------*/
99 /* find command version                                                 */
100 /*----------------------------------------------------------------------*/
101 static FILE     *ip;
102
103 void
104 findopen()
105 {
106         char    *findcom, *p, *q;
107         STRBUF  *sb;
108         char    *sufflist = NULL;
109         char    *skiplist = NULL;
110
111         assert(opened == 0);
112         opened = 1;
113
114         sb = stropen();
115         if (!getconfs("suffixes", sb))
116                 die("cannot get suffixes data.");
117         sufflist = strdup(strvalue(sb));
118         if (!sufflist)
119                 die("short of memory.");
120         trim(sufflist);
121         strstart(sb);
122         if (getconfs("skip", sb)) {
123                 skiplist = strdup(strvalue(sb));
124                 if (!skiplist)
125                         die("short of memory.");
126                 trim(skiplist);
127         }
128
129         strstart(sb);
130         strputs(sb, "find . \\( -type f -o -type l \\) \\(");
131         for (p = sufflist; p; ) {
132                 char    *suff = p;
133                 if ((p = locatestring(p, ",", MATCH_FIRST)) != NULL)
134                         *p++ = 0;
135                 strputs(sb, " -name '*.");
136                 strputs(sb, suff);
137                 strputs(sb, "'");
138                 if (p)
139                         strputs(sb, " -o");
140         }
141         strputs(sb, " \\) -print");
142         findcom = strvalue(sb);
143
144         if (skiplist) {
145                 char    *reg;
146                 STRBUF  *sbb = stropen();
147                 /*
148                  * construct regular expression.
149                  */
150                 strputc(sbb, '(');      /* ) */
151                 for (p = skiplist; p; ) {
152                         char    *skipf = p;
153                         if ((p = locatestring(p, ",", MATCH_FIRST)) != NULL)
154                                 *p++ = 0;
155                         strputc(sbb, '/');
156                         for (q = skipf; *q; q++) {
157                                 if (*q == '.')
158                                         strputc(sbb, '\\');
159                                 strputc(sbb, *q);
160                         }
161                         if (*(q - 1) != '/')
162                                 strputc(sbb, '$');
163                         if (p)
164                                 strputc(sbb, '|');
165                 }
166                 strputc(sbb, ')');
167                 reg = strvalue(sbb);
168                 /*
169                  * compile regular expression.
170                  */
171                 if (regcomp(skip, reg, REG_EXTENDED|REG_NEWLINE) != 0)
172                         die("cannot compile regular expression.");
173                 strclose(sbb);
174         } else {
175                 skip = (regex_t *)0;
176         }
177         if (!(ip = popen(findcom, "r")))
178                 die("cannot execute find.");
179         strclose(sb);
180         if (sufflist)
181                 free(sufflist);
182         if (skiplist)
183                 free(skiplist);
184 }
185 char    *
186 findread(length)
187 int     *length;
188 {
189         static char     path[MAXPATHLEN+1];
190         char    *p;
191
192         assert(opened == 1);
193         while (fgets(path, MAXPATHLEN, ip)) {
194                 if (!skip || regexec(skip, path, 0, 0, 0) != 0) {
195                         /*
196                          * chop(path)
197                          */
198                         p = path + strlen(path) - 1;
199                         if (*p != '\n')
200                                 die("output of find(1) is wrong (findread).");
201                         *p = 0;
202                         if (length)
203                                 *length = p - path;
204                         return path;
205                 }
206         }
207         return NULL;
208 }
209 void
210 findclose(void)
211 {
212         assert(opened == 1);
213         pclose(ip);
214         opened = 0;
215 }
216 #else /* USEFIND */
217 /*----------------------------------------------------------------------*/
218 /* dirent version findxxx()                                             */
219 /*----------------------------------------------------------------------*/
220 #define STACKSIZE 50
221 static  char    dir[MAXPATHLEN+1];              /* directory path */
222 static  struct {
223         STRBUF  *sb;
224         char    *dirp, *start, *end, *p;
225 } stack[STACKSIZE], *topp, *curp;               /* stack */
226
227 static regex_t  suff_area;
228 static regex_t  *suff = &suff_area;
229
230 static int
231 getdirs(dir, sb)
232 char    *dir;
233 STRBUF  *sb;
234 {
235         DIR     *dirp;
236         struct dirent *dp;
237 #ifndef BSD4_4
238         struct stat st;
239 #endif
240
241         if ((dirp = opendir(dir)) == NULL)
242                 return -1;
243         while ((dp = readdir(dirp)) != NULL) {
244 #ifdef BSD4_4
245                 if (dp->d_namlen == 1 && dp->d_name[0] == '.')
246                         continue;
247                 if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
248                         continue;
249                 if (dp->d_type == DT_DIR)
250                         strputc(sb, 'd');
251                 else if (dp->d_type == DT_REG)
252                         strputc(sb, 'f');
253                 else if (dp->d_type == DT_LNK)
254                         strputc(sb, 'l');
255                 else
256                         strputc(sb, ' ');
257                 strnputs(sb, dp->d_name, (int)dp->d_namlen);
258 #else
259                 if (stat(path, &st) < 0) {
260                         fprintf(stderr, "cannot stat '%s'. (Ignored)\n", path);
261                         continue;
262                 }
263                 if (S_ISDIR(st.st_mode))
264                         strputc(sb, 'd');
265                 else if (S_ISREG(st.st_mode))
266                         strputc(sb, 'f');
267                 else if (S_ISLNK(st.st_mode))
268                         strputc(sb, 'l');
269                 else
270                         strputc(sb, ' ');
271                 strputs(sb, dp->d_name);
272 #endif /* BSD4_4 */
273                 strputc(sb, '\0');
274         }
275         (void)closedir(dirp);
276         return 0;
277 }
278 void
279 findopen()
280 {
281         STRBUF  *sb = stropen();
282         char    *sufflist = NULL;
283         char    *skiplist = NULL;
284
285         assert(opened == 0);
286         opened = 1;
287
288         /*
289          * setup stack.
290          */
291         curp = &stack[0];
292         topp = curp + STACKSIZE; 
293         strcpy(dir, ".");
294
295         curp->dirp = dir + strlen(dir);
296         curp->sb = stropen();
297         if (getdirs(dir, curp->sb) < 0)
298                 die("cannot open '.' directory.");
299         curp->start = curp->p = strvalue(curp->sb);
300         curp->end   = curp->start + strbuflen(curp->sb);
301
302         /*
303          * preparing regular expression.
304          */
305         strstart(sb);
306         if (!getconfs("suffixes", sb))
307                 die("cannot get suffixes data.");
308         sufflist = strdup(strvalue(sb));
309         if (!sufflist)
310                 die("short of memory.");
311         trim(sufflist);
312         strstart(sb);
313         if (getconfs("skip", sb)) {
314                 skiplist = strdup(strvalue(sb));
315                 if (!skiplist)
316                         die("short of memory.");
317                 trim(skiplist);
318         }
319         {
320                 char    *p;
321
322                 strstart(sb);
323                 strputc(sb, '(');       /* ) */
324                 for (p = sufflist; p; ) {
325                         char    *suffp = p;
326                         if ((p = locatestring(p, ",", MATCH_FIRST)) != NULL)
327                                 *p++ = 0;
328                         strputs(sb, "\\.");
329                         strputs(sb, suffp);
330                         strputc(sb, '$');
331                         if (p)
332                                 strputc(sb, '|');
333                 }
334                 strputc(sb, ')');
335                 /*
336                  * compile regular expression.
337                  */
338                 if (regcomp(suff, strvalue(sb), REG_EXTENDED) != 0)
339                         die("cannot compile regular expression.");
340         }
341         if (skiplist) {
342                 char    *p, *q;
343                 /*
344                  * construct regular expression.
345                  */
346                 strstart(sb);
347                 strputc(sb, '(');       /* ) */
348                 for (p = skiplist; p; ) {
349                         char    *skipf = p;
350                         if ((p = locatestring(p, ",", MATCH_FIRST)) != NULL)
351                                 *p++ = 0;
352                         strputc(sb, '/');
353                         for (q = skipf; *q; q++) {
354                                 if (*q == '.')
355                                         strputc(sb, '\\');
356                                 strputc(sb, *q);
357                         }
358                         if (*(q - 1) != '/')
359                                 strputc(sb, '$');
360                         if (p)
361                                 strputc(sb, '|');
362                 }
363                 strputc(sb, ')');
364                 /*
365                  * compile regular expression.
366                  */
367                 if (regcomp(skip, strvalue(sb), REG_EXTENDED) != 0)
368                         die("cannot compile regular expression.");
369         } else {
370                 skip = (regex_t *)0;
371         }
372         strclose(sb);
373         if (sufflist)
374                 free(sufflist);
375         if (skiplist)
376                 free(skiplist);
377 }
378 char    *
379 findread(length)
380 int     *length;
381 {
382         static  char val[MAXPATHLEN+1];
383
384         for (;;) {
385                 while (curp->p < curp->end) {
386                         char    type = *(curp->p);
387                         char    *unit = curp->p + 1;
388
389                         curp->p += strlen(curp->p) + 1;
390                         if (type == 'f' || type == 'l') {
391                                 char    *path = makepath(dir, unit);
392                                 if (regexec(suff, path, 0, 0, 0) != 0)
393                                         continue;
394                                 if (skip && regexec(skip, path, 0, 0, 0) == 0)
395                                         continue;
396                                 strcpy(val, path);
397                                 return val;
398                         }
399                         if (type == 'd') {
400                                 STRBUF  *sb = stropen();
401                                 char    *dirp = curp->dirp;
402
403                                 strcat(dirp, "/");
404                                 strcat(dirp, unit);
405                                 if (getdirs(dir, sb) < 0) {
406                                         fprintf(stderr, "cannot open directory '%s'. (Ignored)\n", dir);
407                                         strclose(sb);
408                                         *(curp->dirp) = 0;
409                                         continue;
410                                 }
411                                 /*
412                                  * Push stack.
413                                  */
414                                 if (++curp >= topp)
415                                         die("directory stack over flow.");
416                                 curp->dirp = dirp + strlen(dirp);
417                                 curp->sb = sb;
418                                 curp->start = curp->p = strvalue(sb);
419                                 curp->end   = curp->start + strbuflen(sb);
420                         }
421                 }
422                 strclose(curp->sb);
423                 curp->sb = NULL;
424                 if (curp == &stack[0])
425                         break;
426                 /*
427                  * Pop stack.
428                  */
429                 curp--;
430                 *(curp->dirp) = 0;
431         }
432         return NULL;
433 }
434 void
435 findclose(void)
436 {
437         assert(opened == 1);
438         for (curp = &stack[0]; curp < topp; curp++)
439                 if (curp->sb != NULL)
440                         strclose(curp->sb);
441                 else
442                         break;
443         opened = 0;
444 }
445 #endif /* !USEFIND */