source: trunk/athena/bin/delete/lsdel.c @ 11165

Revision 11165, 8.1 KB checked in by ghudson, 27 years ago (diff)
Assume any system's malloc(0) may return NULL.
Line 
1/*
2 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/delete/lsdel.c,v $
3 * $Author: ghudson $
4 *
5 * This program is a replacement for rm.  Instead of actually deleting
6 * files, it marks them for deletion by prefixing them with a ".#"
7 * prefix.
8 *
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file "mit-copying.h."
11 */
12
13#if (!defined(lint) && !defined(SABER))
14     static char rcsid_lsdel_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/delete/lsdel.c,v 1.22 1998-02-25 22:27:22 ghudson Exp $";
15#endif
16
17#include <stdio.h>
18#include <sys/types.h>
19#include <dirent.h>
20#include <sys/param.h>
21#include <string.h>
22#include <errno.h>
23#include <com_err.h>
24#include "col.h"
25#include "util.h"
26#include "directories.h"
27#include "pattern.h"
28#include "lsdel.h"
29#include "shell_regexp.h"
30#include "mit-copying.h"
31#include "delete_errs.h"
32#include "errors.h"
33
34extern time_t current_time;
35
36int space_total = 0;
37int dirsonly, recursive, yield, f_links, f_mounts, singlecolumn;
38time_t timev;
39
40main(argc, argv)
41int argc;
42char *argv[];
43{
44     extern char *optarg;
45     extern int optind;
46     int arg;
47     
48     whoami = lastpart(argv[0]);
49
50     dirsonly = recursive = timev = yield = f_links = f_mounts = 0;
51     singlecolumn = -1;
52     while ((arg = getopt(argc, argv, "1Cdrt:ysm")) != -1) {
53          switch (arg) {
54          case '1':
55               if ((singlecolumn != -1) && (! singlecolumn)) {
56                    fprintf(stderr,
57                            "%s: -1 and -C options are mutually exclusive\n",
58                            whoami);
59                    usage();
60                    exit(1);
61               }
62               singlecolumn = 1;
63               break;
64          case 'C':
65               if ((singlecolumn != -1) && singlecolumn) {
66                    fprintf(stderr,
67                            "%s: -1 and -C options are mutually exclusive\n",
68                            whoami);
69                    usage();
70                    exit(1);
71               }
72               singlecolumn = 0;
73               break;
74          case 'd':
75               dirsonly++;
76               break;
77          case 'r':
78               recursive++;
79               break;
80          case 't':
81               timev = atoi(optarg);
82               break;
83          case 'y':
84               yield++;
85               break;
86          case 's':
87               f_links++;
88               break;
89          case 'm':
90               f_mounts++;
91               break;
92          default:
93               usage();
94               exit(1);
95          }
96     }
97     if (singlecolumn == -1)
98          singlecolumn = ! isatty(1);
99
100     if (optind == argc) {
101          char *cwd;
102
103          cwd = ".";
104
105          if (ls(&cwd, 1))
106               error("ls of .");
107     }
108     else if (ls(&argv[optind], argc - optind))
109          error ("ls");
110
111     exit (error_occurred ? 1 : 0);
112}
113
114
115
116
117
118
119usage()
120{
121     fprintf(stderr, "Usage: %s [ options ] [ filename [ ...]]\n", whoami);
122     fprintf(stderr, "Options are:\n");
123     fprintf(stderr, "     -d     list directory names, not contents\n");
124     fprintf(stderr, "     -r     recursive\n");
125     fprintf(stderr, "     -t n   list n-day-or-older files only\n");
126     fprintf(stderr, "     -y     report total space taken up by files\n");
127     fprintf(stderr, "     -s     follow symbolic links to directories\n");
128     fprintf(stderr, "     -m     follow mount points\n");
129     fprintf(stderr, "     -1     force single-column output\n");
130     fprintf(stderr, "     -C     force multi-column output (default when output is to a terminal)\n");
131     fprintf(stderr, "-1 and -C are mutually exclusive\n");
132}
133
134
135
136
137ls(args, num)
138char **args;
139int num;
140{
141     char **found_files;
142     int num_found = 0, total = 0;
143     int status = 0;
144     int retval;
145
146     initialize_del_error_table();
147     
148     if (retval = initialize_tree()) {
149          error("initialize_tree");
150          return retval;
151     }
152     
153     for ( ; num; num--) {
154          if (retval = get_the_files(args[num - 1], &num_found,
155                                     &found_files)) {
156               error(args[num - 1]);
157               status = retval;
158               continue;
159          }
160
161          if (num_found) {
162               num_found = process_files(found_files, num_found);
163               if (num_found < 0) {
164                    error("process_files");
165                    status = error_code;
166                    continue;
167               }
168               total += num_found;
169          }
170          else {
171               /* What we do at this point depends on exactly what the
172                * filename is.  There are several possible conditions:
173                * 1. The filename has no wildcards in it, which means that
174                *    if we couldn't find it, that means it doesn't
175                *    exist.  Print a not found error.
176                * 2. Filename is an existing directory, with no deleted
177                *    files in it.  Print nothing.
178                * 3. Filename doesn't exist, and there are wildcards in
179                *    it.  Print "no match".
180                * None of these are considered error conditions, so we
181                * don't set the error flag.
182                */
183               if (no_wildcards(args[num - 1])) {
184                    if (! directory_exists(args[num - 1])) {
185                         set_error(ENOENT);
186                         error(args[num - 1]);
187                         status = error_code;
188                         continue;
189                    }
190               }
191               else {
192                    set_error(ENOMATCH);
193                    error(args[num - 1]);
194                    status = error_code;
195                    continue;
196               }
197          }
198     }
199     if (total) {
200          if (list_files()) {
201               error("list_files");
202               return error_code;
203          }
204     }
205     if (yield)
206          printf("\nTotal space taken up by file%s: %dk\n",
207                 (total == 1 ? "" : "s"), space_to_k(space_total));
208
209     return status;
210}
211
212
213
214
215int get_the_files(name, number_found, found)
216char *name;
217int *number_found;
218char ***found;
219{
220     int retval;
221     int options;
222     
223     options = FIND_DELETED | FIND_CONTENTS;
224     if (recursive)
225          options |= RECURS_FIND_DELETED;
226     if (! dirsonly)
227          options |= RECURS_DELETED;
228     if (f_mounts)
229          options |= FOLLW_MOUNTPOINTS;
230     if (f_links)
231          options |= FOLLW_LINKS;
232     
233     retval = find_matches(name, number_found, found, options);
234     if (retval) {
235          error("find_matches");
236          return retval;
237     }
238
239     return 0;
240}
241
242
243
244
245
246
247process_files(files, num)
248char **files;
249int num;
250{
251     int i, skipped = 0;
252     filerec *leaf;
253     
254     for (i = 0; i < num; i++) {
255          if (add_path_to_tree(files[i], &leaf)) {
256               error("add_path_to_tree");
257               return -1;
258          }
259          free(files[i]);
260          if (! timed_out(leaf, current_time, timev)) {
261               free_leaf(leaf);
262               skipped++;
263               continue;
264          }
265          space_total += specs_to_space(leaf->specs);
266     }
267     free((char *) files);
268     return(num-skipped);
269}
270
271
272
273
274static int alphacmp(str1, str2)
275char **str1, **str2;
276{
277     return(strcmp(*str1, *str2));
278}
279
280list_files()
281{
282     filerec *current;
283     char **strings;
284     int num;
285     int retval;
286     
287     strings = (char **) Malloc((unsigned) sizeof(char *));
288     num = 0;
289     if (! strings) {
290          set_error(errno);
291          error("Malloc");
292          return error_code;
293     }
294     current = get_root_tree();
295     if (retval = accumulate_names(current, &strings, &num)) {
296          error("accumulate_names");
297          return retval;
298     }
299     current = get_cwd_tree();
300     if (retval = accumulate_names(current, &strings, &num)) {
301          error("accumulate_names");
302          return retval;
303     }
304
305     if (retval = sort_files(strings, num)) {
306          error("sort_files");
307          return retval;
308     }
309     
310     if (retval = unique(&strings, &num)) {
311          error("unique");
312          return retval;
313     }
314
315     qsort((char *) strings, num, sizeof(char *), alphacmp);
316
317     if (retval = column_array(strings, num, DEF_SCR_WIDTH, 0, singlecolumn,
318                               2, 1, 0, 1, stdout)) {
319          error("column_array");
320          return retval;
321     }
322     
323     for ( ; num; num--)
324          free(strings[num - 1]);
325     free((char *) strings);
326     return 0;
327}
328
329
330int sort_files(data, num_data)
331char **data;
332int num_data;
333{
334     qsort((char *) data, num_data, sizeof(char *), strcmp);
335
336     return 0;
337}
338
339
340int unique(the_files, number)
341char ***the_files;
342int *number;
343{
344     int i, last;
345     int offset;
346     char **files;
347
348     files = *the_files;
349     for (last = 0, i = 1; i < *number; i++) {
350          if (! strcmp(files[last], files[i])) {
351               free (files[i]);
352               free (files[i]);
353               files[i] = (char *) NULL;
354          }
355          else
356               last = i;
357     }
358     
359     for (offset = 0, i = 0; i + offset < *number; i++) {
360          if (! files[i])
361               offset++;
362          if (i + offset < *number)
363               files[i] = files[i + offset];
364     }
365     *number -= offset;
366     files = (char **) realloc((char *) files,
367                               (unsigned) (sizeof(char *) * *number));
368     if ((! files) && *number)
369     {
370          set_error(errno);
371          error("realloc");
372          return errno;
373     }
374
375     *the_files = files;
376     return 0;
377}
Note: See TracBrowser for help on using the repository browser.