source: trunk/athena/bin/delete/pattern.c @ 2081

Revision 2081, 11.8 KB checked in by jik, 35 years ago (diff)
Fixed so that you can use ./ and ../ in filenames.
Line 
1/*
2 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/delete/pattern.c,v $
3 * $Author: jik $
4 *
5 * This program is part of a package including delete, undelete,
6 * lsdel, expunge and purge.  The software suite is meant as a
7 * replacement for rm which allows for file recovery.
8 *
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file "mit-copyright.h."
11 */
12
13#if (!defined(lint) && !defined(SABER))
14     static char rcsid_pattern_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/delete/pattern.c,v 1.10 1989-09-03 17:49:10 jik Exp $";
15#endif
16
17#include <stdio.h>
18#include <sys/types.h>
19#include <sys/dir.h>
20#include <sys/param.h>
21#include <strings.h>
22#include <sys/stat.h>
23#include "directories.h"
24#include "pattern.h"
25#include "util.h"
26#include "undelete.h"
27#include "mit-copyright.h"
28
29static char *add_char();
30
31extern char *malloc(), *realloc();
32
33extern char *whoami, *error_buf;
34
35/*
36 * parse_pattern returns an area of memory allocated by malloc when it
37 * is successful.  Therefore, other procedures calling parse_pattern
38 * should use free() to free the region of memory when they are done
39 * with it.
40 */
41char *parse_pattern(file_pattern)
42char *file_pattern;
43{
44     char *re_pattern, *cur_ptr, *re_ptr;
45     int guess_length;
46     
47     guess_length = strlen(file_pattern) + 5;
48     re_ptr = re_pattern = malloc(guess_length);
49     if (! re_ptr) {
50          perror(sprintf(error_buf, "%s: parse_pattern", whoami));
51          exit(1);
52     }
53     
54     for (cur_ptr = file_pattern, re_ptr = re_pattern; *cur_ptr != NULL;
55          cur_ptr++) {
56          if (*cur_ptr == '\\') {
57               if (! cur_ptr[1]) {
58                    fprintf(stderr,
59                            "%s: parse_pattern: incomplete expression\n",
60                            whoami);
61                    return((char *) NULL);
62               }
63               if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
64                    return ((char *) NULL);
65               cur_ptr++;
66               if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
67                    return ((char *) NULL);
68               continue;
69          }
70          else if (*cur_ptr == '*') {
71               if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
72                    return ((char *) NULL);
73               if (! add_char(&re_pattern, &re_ptr, &guess_length, '*'))
74                    return ((char *) NULL);
75               continue;
76          }
77          else if (*cur_ptr == '?') {
78               if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
79                    return ((char *) NULL);
80               continue;
81          }
82          else if (*cur_ptr == '.') {
83               if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
84                    return ((char *) NULL);
85               if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
86                    return ((char *) NULL);
87          }
88          else {
89               if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
90                    return ((char *) NULL);
91          }
92     }
93     if (! add_char(&re_pattern, &re_ptr, &guess_length, '\0'))
94          return ((char *) NULL);
95     return (re_pattern);
96}
97
98
99
100
101
102
103/*
104 * add_char() takes two char **, a length which is the current amount
105 * of space implemented for the string pointed to by the first *(char **),
106 * and a character to add to the string.  It reallocs extra space if
107 * necessary, adds the character, and messes with the pointers if necessary.
108 */
109static char *add_char(start, finish, length, chr)
110char **start, **finish;
111int *length;
112char chr;
113{
114     if (*finish - *start == *length) {
115          *start = realloc(*start, *length + 5);
116          if (! *start) {
117               perror(sprintf(error_buf, "%s: add_char", whoami));
118               exit(1);
119          }
120          *finish = *start + *length - 1;
121          *length += 5;
122     }
123     **finish = chr;
124     (*finish)++;
125     return(*start);
126}
127
128         
129
130
131
132
133/*
134 * add_arrays() takes pointers to two arrays of char **'s and their
135 * lengths, merges the two into the first by realloc'ing the first and
136 * then free's the second's memory usage.
137 */ 
138add_arrays(array1, num1, array2, num2)
139char ***array1, ***array2;
140int *num1, *num2;
141{
142     int counter;
143     
144     *array1 = (char **) realloc(*array1, sizeof(char *) * (*num1 + *num2));
145     if (! *array1) {
146          perror(sprintf(error_buf, "%s: add_arrays", whoami));
147          exit(1);
148     }
149     for (counter = *num1; counter < *num1 + *num2; counter++)
150          *(*array1 + counter) = *(*array2 + counter - *num1);
151     free (*array2);
152     *num1 += *num2;
153     return(0);
154}
155
156
157
158
159
160
161
162char **add_str(strs, num, str)
163char **strs;
164int num;
165char *str;
166{
167     strs = (char **) realloc(strs, sizeof(char *) * (num + 1));
168     if (! strs) {
169          perror(sprintf(error_buf, "%s: add_str", whoami));
170          exit(1);
171     }
172     strs[num] = malloc(strlen(str) + 1);
173     if (! strs[num]) {
174          perror(sprintf(error_buf, "%s: add_str", whoami));
175          exit(1);
176     }
177     strcpy(strs[num], str);
178     return(strs);
179}
180
181
182
183
184
185
186
187char **find_deleted_matches(base, expression, num_found)
188char *base, *expression;
189int *num_found;
190{
191     struct direct *dp;
192     DIR *dirp;
193     char **found;
194     int num;
195     char **next;
196     int num_next;
197     char first[MAXNAMLEN], rest[MAXPATHLEN];
198     char new[MAXPATHLEN];
199
200#ifdef DEBUG
201     printf("Looking for %s in %s\n", expression, base);
202#endif
203     found = (char **) malloc(0);
204     *num_found = num = 0;
205
206     dirp = opendir(base);
207     if (! dirp)
208          return(found);
209
210     strcpy(first, reg_firstpart(expression, rest));
211     re_comp(first);
212
213     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
214          if (re_exec(dp->d_name) && *rest) {
215               strcpy(new, append(base, dp->d_name));
216               next = find_deleted_matches(new, rest, &num_next);
217               add_arrays(&found, &num, &next, &num_next);
218          }
219          else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
220               if (*rest) {
221                    strcpy(new, append(base, dp->d_name));
222                    next = find_deleted_matches(new, rest, &num_next);
223                    add_arrays(&found, &num, &next, &num_next);
224               }
225               else {
226                    found = add_str(found, num, append(base, dp->d_name));
227                    num++;
228               }
229          }
230     }
231     closedir(dirp);
232     *num_found = num;
233     return(found);
234}
235
236
237
238
239
240char **find_matches(base, expression, num_found)
241char *base, *expression;
242int *num_found;
243{
244     struct direct *dp;
245     DIR *dirp;
246     char **found;
247     int num;
248     char **next;
249     int num_next;
250     char first[MAXNAMLEN], rest[MAXPATHLEN];
251     char new[MAXPATHLEN];
252     
253#ifdef DEBUG
254     printf("Looking for %s in %s\n", expression, base);
255#endif
256     found = (char **) malloc(0);
257     *num_found = num = 0;
258
259     dirp = opendir(base);
260     if (! dirp)
261          return(found);
262
263     strcpy(first, reg_firstpart(expression, rest));
264
265     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
266          re_comp(first);
267          if (re_exec(dp->d_name)) {
268               if (*rest) {
269                    strcpy(new, append(base, dp->d_name));
270                    next = find_matches(new, rest, &num_next);
271                    add_arrays(&found, &num, &next, &num_next);
272               }
273               else {
274                    found = add_str(found, num, append(base, dp->d_name));
275                    num++;
276               }
277          }
278          else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
279               if (*rest) {
280                    strcpy(new, append(base, dp->d_name));
281                    next = find_matches(new, rest, &num_next);
282                    add_arrays(&found, &num, &next, &num_next);
283               }
284               else {
285                    found = add_str(found, num, append(base, dp->d_name));
286                    num++;
287               }
288          }
289     }
290     closedir(dirp);
291     *num_found = num;
292     return(found);
293}
294
295
296
297
298
299
300
301char **find_recurses(base, num_found)
302char *base;
303int *num_found;
304{
305     DIR *dirp;
306     struct direct *dp;
307     char newname[MAXPATHLEN];
308     char **found, **new_found;
309     int found_num, new_found_num;
310     struct stat stat_buf;
311     
312#ifdef DEBUG
313     printf("Looking for subs of %s\n", base);
314#endif
315     found = (char **) malloc(0);
316     *num_found = found_num = 0;
317     
318     dirp = opendir(base);
319     if (! dirp)
320          return(found);
321
322     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
323          if (is_dotfile(dp->d_name))
324               continue;
325          strcpy(newname, append(base, dp->d_name));
326          found = add_str(found, found_num, newname);
327          found_num++;
328          if (lstat(newname, &stat_buf))
329               continue;
330          if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
331               new_found = find_recurses(newname, &new_found_num);
332               add_arrays(&found, &found_num, &new_found, &new_found_num);
333          }
334     }
335     closedir(dirp);
336     *num_found = found_num;
337     return(found);
338}
339
340
341
342
343
344
345char **find_deleted_recurses(base, num_found)
346char *base;
347int *num_found;
348{
349     DIR *dirp;
350     struct direct *dp;
351     char newname[MAXPATHLEN];
352     char **found, **new_found;
353     int found_num, new_found_num;
354     struct stat stat_buf;
355     
356     found = (char **) malloc(0);
357     *num_found = found_num = 0;
358     
359     dirp = opendir(base);
360     if (! dirp)
361          return(found);
362
363     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
364          if (is_dotfile(dp->d_name))
365               continue;
366
367          strcpy(newname, append(base, dp->d_name));
368         
369          if (is_deleted(dp->d_name)) {
370               found = add_str(found, found_num, newname);
371               found_num++;
372          }
373          if (lstat(newname, &stat_buf)) {
374               continue;
375          }
376          if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
377               new_found = find_deleted_recurses(newname, &new_found_num);
378               add_arrays(&found, &found_num, &new_found, &new_found_num);
379          }
380     }
381     closedir(dirp);
382     *num_found = found_num;
383     return(found);
384}
385
386
387
388
389
390
391char **find_contents(base, num_found)
392char *base;
393int *num_found;
394{
395     DIR *dirp;
396     struct direct *dp;
397     char **found;
398     int num;
399
400#ifdef DEBUG
401     printf("Looking for contents of %s\n", base);
402#endif
403     found = (char **) malloc(0);
404     *num_found = num = 0;
405   
406     dirp = opendir(base);
407     if (! dirp)
408          return(found);
409
410     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
411          if (is_dotfile(dp->d_name))
412               continue;
413          found = add_str(found, num, append(base, dp->d_name));
414          num += 1;
415     }
416     closedir(dirp);
417     *num_found = num;
418     return(found);
419}
420
421
422     
423char **find_deleted_contents(base, num_found)
424char *base;
425int *num_found;
426{
427     DIR *dirp;
428     struct direct *dp;
429     char **found;
430     int num;
431
432#ifdef DEBUG
433     printf("Looking for deleted contents of %s\n", base);
434#endif
435     found = (char **) malloc(0);
436     *num_found = num = 0;
437   
438     dirp = opendir(base);
439     if (! dirp)
440          return(found);
441
442     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
443          if (is_dotfile(dp->d_name))
444               continue;
445          if (is_deleted(dp->d_name)) {
446               found = add_str(found, num, append(base, dp->d_name));
447               num += 1;
448          }
449     }
450     closedir(dirp);
451     *num_found = num;
452     return(found);
453}
454
455
456
457
458char **find_deleted_contents_recurs(base, num_found)
459char *base;
460int *num_found;
461{
462     DIR *dirp;
463     struct direct *dp;
464     char **found;
465     int num;
466     struct stat stat_buf;
467     char newname[MAXPATHLEN];
468     char **new_found;
469     int new_found_num;
470     
471#ifdef DEBUG
472     printf("Looking for recursive deleted contents of %s\n", base);
473#endif
474     found = (char **) malloc(0);
475     *num_found = num = 0;
476   
477     dirp = opendir(base);
478     if (! dirp)
479          return(found);
480
481     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
482          if (is_dotfile(dp->d_name))
483               continue;
484          if (is_deleted(dp->d_name)) {
485               strcpy(newname, append(base, dp->d_name));
486               found = add_str(found, num, newname);
487               num += 1;
488               if (lstat(newname, &stat_buf))
489                    continue;
490               if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
491                    new_found = find_recurses(newname, &new_found_num);
492                    add_arrays(&found, &num, &new_found, &new_found_num);
493               }
494          }
495     }
496     closedir(dirp);
497     *num_found = num;
498     return(found);
499}
500     
501
502
503/*
504 * returns true if the filename has no regular expression wildcards in
505 * it.  That means no non-quoted dots or asterisks.  Assumes a
506 * null-terminated string, and a valid regular expression.
507 */
508int no_wildcards(name)
509char *name;
510{
511     do {
512          switch (*name) {
513          case '\\':
514               name++;
515               break;
516          case '.':
517               return(0);
518          case '*':
519               return(0);
520          }
521     } while (*++name);
522     return(1);
523}
Note: See TracBrowser for help on using the repository browser.