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

Revision 24908, 8.0 KB checked in by ghudson, 14 years ago (diff)
In delete: * Patches from Jonathan Kamens: - The "-f" flag to delete should suppress nonexistent file errors but not other errors. - When the "-v" flag is specified to expunge, the correct totals should be reported. Previously, the totals were incorrect. - Code cleanup.
Line 
1/*
2 * $Id: lsdel.c,v 1.24 1999-01-22 23:09:01 ghudson Exp $
3 *
4 * This program is a replacement for rm.  Instead of actually deleting
5 * files, it marks them for deletion by prefixing them with a ".#"
6 * prefix.
7 *
8 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, see the file "mit-copying.h."
10 */
11
12#include <stdio.h>
13#include <sys/types.h>
14#include <dirent.h>
15#include <sys/param.h>
16#include <string.h>
17#include <errno.h>
18#include <com_err.h>
19#include <unistd.h>
20#include "col.h"
21#include "directories.h"
22#include "pattern.h"
23#include "lsdel.h"
24#include "shell_regexp.h"
25#include "mit-copying.h"
26#include "delete_errs.h"
27#include "errors.h"
28#include "util.h"
29
30static void usage(void);
31static int ls(char **args, int num), process_files(char **files, int num);
32static int list_files(void), unique(char ***the_files, int *number);
33
34extern time_t current_time;
35
36int space_total = 0;
37int dirsonly, recursive, yield, f_links, f_mounts, singlecolumn;
38time_t timev;
39
40int main(int argc, char *argv[])
41{
42     extern char *optarg;
43     extern int optind;
44     int arg;
45     
46     whoami = lastpart(argv[0]);
47
48     dirsonly = recursive = timev = yield = f_links = f_mounts = 0;
49     singlecolumn = -1;
50     while ((arg = getopt(argc, argv, "1Cdrt:ysm")) != -1) {
51          switch (arg) {
52          case '1':
53               if ((singlecolumn != -1) && (! singlecolumn)) {
54                    fprintf(stderr,
55                            "%s: -1 and -C options are mutually exclusive\n",
56                            whoami);
57                    usage();
58                    exit(1);
59               }
60               singlecolumn = 1;
61               break;
62          case 'C':
63               if ((singlecolumn != -1) && singlecolumn) {
64                    fprintf(stderr,
65                            "%s: -1 and -C options are mutually exclusive\n",
66                            whoami);
67                    usage();
68                    exit(1);
69               }
70               singlecolumn = 0;
71               break;
72          case 'd':
73               dirsonly++;
74               break;
75          case 'r':
76               recursive++;
77               break;
78          case 't':
79               timev = atoi(optarg);
80               break;
81          case 'y':
82               yield++;
83               break;
84          case 's':
85               f_links++;
86               break;
87          case 'm':
88               f_mounts++;
89               break;
90          default:
91               usage();
92               exit(1);
93          }
94     }
95     if (singlecolumn == -1)
96          singlecolumn = ! isatty(1);
97
98     if (optind == argc) {
99          char *cwd;
100
101          cwd = ".";
102
103          if (ls(&cwd, 1))
104               error("ls of .");
105     }
106     else if (ls(&argv[optind], argc - optind))
107          error ("ls");
108
109     exit (error_occurred ? 1 : 0);
110}
111
112
113
114
115
116
117static void usage()
118{
119     fprintf(stderr, "Usage: %s [ options ] [ filename [ ...]]\n", whoami);
120     fprintf(stderr, "Options are:\n");
121     fprintf(stderr, "     -d     list directory names, not contents\n");
122     fprintf(stderr, "     -r     recursive\n");
123     fprintf(stderr, "     -t n   list n-day-or-older files only\n");
124     fprintf(stderr, "     -y     report total space taken up by files\n");
125     fprintf(stderr, "     -s     follow symbolic links to directories\n");
126     fprintf(stderr, "     -m     follow mount points\n");
127     fprintf(stderr, "     -1     force single-column output\n");
128     fprintf(stderr, "     -C     force multi-column output (default when output is to a terminal)\n");
129     fprintf(stderr, "-1 and -C are mutually exclusive\n");
130}
131
132
133
134
135static int ls(char **args, int num)
136{
137     char **found_files;
138     int num_found = 0, total = 0;
139     int status = 0;
140     int retval;
141
142#if defined(__APPLE__) && defined(__MACH__)
143     add_error_table(&et_del_error_table);
144#else
145     initialize_del_error_table();
146#endif
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(DELETE_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       char *friendly = space_to_friendly(space_total);
207       printf("\nTotal space taken up by file%s: %s\n",
208              (total == 1 ? "" : "s"), friendly);
209       free(friendly);
210     }
211     return status;
212}
213
214
215
216
217int get_the_files(name, number_found, found)
218char *name;
219int *number_found;
220char ***found;
221{
222     int retval;
223     int options;
224     
225     options = FIND_DELETED | FIND_CONTENTS;
226     if (recursive)
227          options |= RECURS_FIND_DELETED;
228     if (! dirsonly)
229          options |= RECURS_DELETED;
230     if (f_mounts)
231          options |= FOLLW_MOUNTPOINTS;
232     if (f_links)
233          options |= FOLLW_LINKS;
234     
235     retval = find_matches(name, number_found, found, options);
236     if (retval) {
237          error("find_matches");
238          return retval;
239     }
240
241     return 0;
242}
243
244
245
246
247
248
249static int process_files(char **files, int 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(arg1, arg2)
275const void *arg1, *arg2;
276{
277     return(strcmp(*(char **) arg1, *(char **) arg2));
278}
279
280static int list_files(void)
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     qsort(strings, num, sizeof(char *), alphacmp);
306
307     if ((retval = unique(&strings, &num))) {
308          error("unique");
309          return retval;
310     }
311
312     if ((retval = column_array(strings, num, DEF_SCR_WIDTH, 0, singlecolumn,
313                                2, 1, 0, 1, stdout))) {
314          error("column_array");
315          return retval;
316     }
317     
318     for ( ; num; num--)
319          free(strings[num - 1]);
320     free((char *) strings);
321     return 0;
322}
323
324
325static int unique(char ***the_files, int *number)
326{
327     int i, last;
328     int offset;
329     char **files;
330
331     files = *the_files;
332     for (last = 0, i = 1; i < *number; i++) {
333          if (! strcmp(files[last], files[i])) {
334               free (files[i]);
335               files[i] = (char *) NULL;
336          }
337          else
338               last = i;
339     }
340     
341     for (offset = 0, i = 0; i + offset < *number; i++) {
342          if (! files[i])
343               offset++;
344          if (i + offset < *number)
345               files[i] = files[i + offset];
346     }
347     *number -= offset;
348     files = (char **) realloc((char *) files,
349                               (unsigned) (sizeof(char *) * *number));
350     if ((! files) && *number)
351     {
352          set_error(errno);
353          error("realloc");
354          return errno;
355     }
356
357     *the_files = files;
358     return 0;
359}
Note: See TracBrowser for help on using the repository browser.