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

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