source: trunk/athena/bin/delete/expunge.c @ 2179

Revision 2179, 11.9 KB checked in by jik, 35 years ago (diff)
lots of changes to fix lint errors and to deal with new error-handling
RevLine 
[1704]1/*
2 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/delete/expunge.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))
[2179]14     static char rcsid_expunge_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/delete/expunge.c,v 1.10 1989-10-23 13:37:44 jik Exp $";
[1704]15#endif
16
17#include <stdio.h>
18#include <sys/types.h>
19#include <sys/time.h>
20#include <sys/dir.h>
21#include <sys/param.h>
22#include <strings.h>
23#include <sys/stat.h>
[2179]24#include <com_err.h>
25#include <errno.h>
[1732]26#include "col.h"
[1704]27#include "directories.h"
28#include "util.h"
29#include "pattern.h"
30#include "expunge.h"
[2179]31#include "shell_regexp.h"
[1811]32#include "mit-copyright.h"
[2179]33#include "delete_errs.h"
34#include "errors.h"
[1704]35
36extern char *malloc(), *realloc();
[2179]37extern long current_time;
38extern int errno;
[1704]39
[2179]40char *whoami;
[1704]41
[1732]42int  timev,             /* minimum mod time before undeletion */
[1704]43     interactive,       /* query before each expunge */
44     recursive,         /* expunge undeleted directories recursively */
45     noop,              /* print what would be done instead of doing it */
46     verbose,           /* print a line as each file is deleted */
47     force,             /* do not ask for any confirmation */
[1732]48     listfiles,         /* list files at toplevel */
49     yield;             /* print yield of expunge at end */
[1704]50
[1732]51int blocks_removed = 0;
[1704]52
53
54
55
56main(argc, argv)
57int argc;
58char *argv[];
59{
60     extern char *optarg;
61     extern int optind;
62     int arg;
63
[2179]64     initialize_del_error_table();
65     
[1704]66     whoami = lastpart(argv[0]);
67     if (*whoami == 'p') { /* we're doing a purge */
[2179]68          if (purge())
69               error("purge");
70          exit(error_occurred ? 1 : 0);
[1704]71     }
[1732]72     timev = 0;
73     yield = interactive = recursive = noop = verbose = listfiles = force = 0;
[2179]74     while ((arg = getopt(argc, argv, "t:irfnvly")) != EOF) {
[1704]75          switch (arg) {
76          case 't':
[1732]77               timev = atoi(optarg);
[1704]78               break;
79          case 'i':
80               interactive++;
81               break;
82          case 'r':
83               recursive++;
84               break;
85          case 'f':
86               force++;
87               break;
88          case 'n':
89               noop++;
90               break;
91          case 'v':
92               verbose++;
93               break;
94          case 'l':
95               listfiles++;
96               break;
[1732]97          case 'y':
98               yield++;
99               break;
[1704]100          default:
101               usage();
102               exit(1);
103          }
104     }
105     if (optind == argc) {
106          char *dir;
[2179]107          dir = "."; /* current working directory */
108          if (expunge(&dir, 1))
109               error("expunging .");
[1704]110     }
[2179]111     else if (expunge(&argv[optind], argc - optind))
112          error("expunge");
113
114     exit((error_occurred && (! force)) ? 1 : 0);
[1704]115}
116
117
118
119
120
121purge()
122{
[2179]123     char *home;
124     int retval;
125     
126     home = malloc(MAXPATHLEN);
127     if (! home) {
128          set_error(errno);
129          error("purge");
130          return error_code;
[1704]131     }
[1732]132     timev = interactive = noop = verbose = force = 0;
133     yield = listfiles = recursive = 1;
[2179]134     if (retval = get_home(home)) {
135          error("purge");
136          return retval;
[1704]137     }
138
139     printf("Please be patient.... this may take a while.\n\n");
[2179]140
141     if (retval = expunge(&home, 1)) {
142          error("expunge");
143          return retval;
144     }
[1704]145}
146
147
148
149
150usage()
151{
152     printf("Usage: %s [ options ] [ filename [ ... ]]\n", whoami);
153     printf("Options are:\n");
154     printf("     -r     recursive\n");
155     printf("     -i     interactive\n");
156     printf("     -f     force\n");
157     printf("     -t n   n-day-or-older expunge\n");
158     printf("     -n     noop\n");
159     printf("     -v     verbose\n");
160     printf("     -l     list files before expunging\n");
[1732]161     printf("     -y     print yield of expunge\n");
[1707]162     printf("     --     end options and start filenames\n");
[1704]163}
164
165
166
167
168
[2179]169int expunge(files, num)
[1704]170char **files;
171int num;
172{
173     char *file_re;
174     char **found_files;
175     int num_found;
176     char *start_dir;
177     int status = 0;
178     int total = 0;
179     filerec *current;
[2179]180     int retval;
[1704]181     
182     if (initialize_tree())
183          exit(1);
184
185     for ( ; num ; num--) {
186          if (*files[num - 1] == '/') {
187               start_dir = "/";
[2179]188               file_re = files[num - 1] + 1;
[1704]189          }
190          else {
191               start_dir = "";
[2179]192               file_re = files[num - 1];
[1704]193          }
194         
[2179]195          retval = get_the_files(start_dir, file_re, &num_found, &found_files);
196          if (retval) {
197               error(files[num - 1]);
198               return retval;
199          }
200               
201          if (num_found) {
[1732]202               num_found = process_files(found_files, num_found);
[2179]203               if (num_found < 0) {
204                    error("process_files");
205                    return error_code;
206               }
207          }
208         
[1732]209          total += num_found;
210          if (! num_found) if (! force) {
[1753]211               /*
212                * There are three different situations here.  Eiter we
213                * are dealing with an existing directory with no
214                * deleted files in it, or we are deleting with a
215                * non-existing deleted file with wildcards, or we are
216                * dealing with a non-existing deleted file without
217                * wildcards.  In the former case we print nothing, and
218                * in the latter cases we print either "no match" or
219                * "not found" respectively
220                */
221               if (no_wildcards(file_re)) {
222                    if (! directory_exists(files[num - 1])) {
[2179]223                         set_error(ENOENT);
224                         error(files[num - 1]);
[1753]225                    }
226               }
227               else {
[2179]228                    set_error(ENOMATCH);
229                    error(files[num - 1]);
[1753]230               }
[1704]231          }
232     }
233     if (total && listfiles) {
[2179]234          if (retval = list_files()) {
235               error("list_files");
236               return retval;
237          }
238          if (! force) if (! top_level()) {
239               set_status(EXPUNGE_NOT_EXPUNGED);
240               return error_code;
241          }
[1704]242     }
[1732]243     current = get_root_tree();
[2179]244     if (current) {
245          if (retval = expunge_specified(current)) {
246               error("expunge_specified");
247               status = retval;
248          }
249     }
[1732]250     current = get_cwd_tree();
[2179]251     if (current) {
252          if (retval = expunge_specified(current)) {
253               error("expunge_specified");
254               status = retval;
255          }
256     }
[1732]257     if (yield) {
258          if (noop)
259               printf("Total that would be expunged: %dk\n",
260                      blk_to_k(blocks_removed));
261          else
262               printf("Total expunged: %dk\n", blk_to_k(blocks_removed));
263     }
[2179]264     return status;
[1704]265}
266
267
268
[1732]269expunge_specified(leaf)
270filerec *leaf;
271{
272     int status = 0;
[2179]273     int do_it = 1;
274     int retval;
275     
276     if ((leaf->specified) && ((leaf->specs.st_mode & S_IFMT) == S_IFDIR)) {
277          char buf[MAXPATHLEN];
[1704]278
[2179]279          if (retval = get_leaf_path(leaf, buf)) {
280               error("get_leaf_path");
281               return retval;
282          }
283          convert_to_user_name(buf, buf);
284
285          if (interactive) {
286               printf("%s: Expunge directory %s? ", whoami, buf);
287               status = (! (do_it = yes()));
288          }
[1850]289     }
[2179]290     if (do_it) {
291          if (leaf->dirs) {
292               if (retval = expunge_specified(leaf->dirs)) {
293                    error("expunge_specified");
294                    status = retval;
295               }
296          }
297          if (leaf->files) {
298               if (retval = expunge_specified(leaf->files)) {
299                    error("expunge_specified");
300                    status = retval;
301               }
302          }
[1732]303     }
[2179]304     if (leaf->specified && (! status)) {
305          if (retval = really_do_expunge(leaf)) {
306               error("really_do_expunge");
307               status = retval;
308          }
309     }
310     if (leaf->next) {
311          if (retval = expunge_specified(leaf->next)) {
312               error("expunge_specified");
313               status = retval;
314          }
315     }
316
[1732]317     free_leaf(leaf);
[2179]318     return status;
[1732]319}
[1704]320
[1732]321
[1704]322process_files(files, num)
323char **files;
324int num;
325{
[1831]326     int i, skipped = 0;
[1732]327     filerec *leaf;
328     
[1704]329     for (i = 0; i < num; i++) {
[2179]330          if (add_path_to_tree(files[i], &leaf)) {
331               error("add_path_to_tree");
332               return -1;
[1704]333          }
[1732]334          free(files[i]);
335          if (! timed_out(leaf, current_time, timev)) {
336               free_leaf(leaf);
[1831]337               skipped++;
[1704]338          }
339     }
[2179]340     free((char *) files);
[1831]341     return(num-skipped);
[1704]342}
343
344
345
346
347
348
349
350
351
352really_do_expunge(file_ent)
353filerec *file_ent;
354{
355     char real[MAXPATHLEN], user[MAXPATHLEN];
356     int status;
[2179]357     int retval;
[1704]358     
[2179]359     if (retval = get_leaf_path(file_ent, real)) {
360          error("get_leaf_path");
361          return retval;
362     }
[1704]363     convert_to_user_name(real, user);
364
365     if (interactive) {
[1732]366          printf ("%s: Expunge %s (%dk)? ", whoami, user,
367                  blk_to_k(file_ent->specs.st_blocks));
[2179]368          if (! yes()) {
369               set_status(EXPUNGE_NOT_EXPUNGED);
370               return error_code;
371          }
[1704]372     }
373
374     if (noop) {
[1732]375          blocks_removed += file_ent->specs.st_blocks;
376          printf("%s: %s (%dk) would be expunged (%dk total)\n", whoami, user,
377                 blk_to_k(file_ent->specs.st_blocks),
378                 blk_to_k(blocks_removed));
[2179]379          return 0;
[1704]380     }
381
[1732]382     if ((file_ent->specs.st_mode & S_IFMT) == S_IFDIR)
[1704]383          status = rmdir(real);
384     else
385          status = unlink(real);
386     if (! status) {
[1732]387          blocks_removed += file_ent->specs.st_blocks;
[1704]388          if (verbose)
[1732]389               printf("%s: %s (%dk) expunged (%dk total)\n", whoami, user,
390                      blk_to_k(file_ent->specs.st_blocks),
391                      blk_to_k(blocks_removed));
[2179]392          return 0;
[1704]393     }
394     else {
[2179]395          set_error(errno);
396          error(real);
397          return error_code;
[1704]398     }
399}
400
401
402
403
404
405
406
407
408
409top_level()
410{
411     if (interactive) {
412printf("The above files, which have been marked for deletion, are about to be\n");
413printf("expunged forever!  You will be asked for confirmation before each file is\n");
[1757]414printf("deleted.  Do you wish to continue [return = no]? ");
[1704]415     }
416     else {
417printf("The above files, which have been marked for deletion, are about to be\n");
418printf("expunged forever!  Make sure you don't need any of them before continuing.\n");
[1757]419printf("Do you wish to continue [return = no]? ");
[1704]420     }
421     return (yes());
422}
423
[1732]424
425
426
427
[1704]428list_files()
429{
430     filerec *current;
[1732]431     char **strings;
432     int num;
[2179]433     int retval;
[1704]434     
[1732]435     strings = (char **) malloc(sizeof(char *));
436     num = 0;
437     if (! strings) {
[2179]438          set_error(errno);
439          error("malloc");
440          return error_code;
[1732]441     }
[2179]442
[1704]443     printf("The following deleted files are going to be expunged: \n\n");
444
445     current = get_root_tree();
[2179]446     if (retval = accumulate_names(current, &strings, &num)) {
447          error("accumulate_names");
448          return retval;
449     }
[1704]450     current = get_cwd_tree();
[2179]451     if (retval = accumulate_names(current, &strings, &num)) {
452          error("accumulate_names");
453          return retval;
454     }
455     if (retval = column_array(strings, num, DEF_SCR_WIDTH, 0, 0, 2, 1, 0,
456                               1, stdout)) {
457          error("column_array");
458          return retval;
459     }
460     
[1704]461     printf("\n");
462     return(0);
463}
464     
465
466
467
468
[2179]469int get_the_files(base, reg_exp, num_found, found)
[1704]470char *base, *reg_exp;
471int *num_found;
[2179]472char ***found;
[1704]473{
474     char **matches;
475     int num_matches;
476     int num;
477     int i;
[2179]478     int retval;
[1704]479     
[2179]480     *found = (char **) malloc(0);
[1704]481     num = 0;
482     
[2179]483     if (retval = find_matches(base, reg_exp, &num_matches, &matches)) {
484          error("find_matches");
485          return retval;
486     }
487               
[1704]488     if (recursive) {
489          char **recurs_found;
490          int recurs_num;
491         
492          for (i = 0; i < num_matches; free(matches[i]), i++) {
493               if (is_deleted(lastpart(matches[i]))) {
[2179]494                    if (retval = add_str(found, num, matches[i])) {
495                         error("add_str");
496                         return retval;
497                    }
[1704]498                    num++;
499               }
[2179]500               if (retval = find_deleted_recurses(matches[i], &recurs_num,
501                                                  &recurs_found)) {
502                    error("find_deleted_recurses");
503                    return retval;
504               }
505               if (retval = add_arrays(found, &num, &recurs_found,
506                                       &recurs_num)) {
507                    error("add_arrays");
508                    return retval;
509               }
[1704]510          }
511     } 
512     else {
513          struct stat stat_buf;
514          char **contents_found;
515          int num_contents;
516         
517          for (i = 0; i < num_matches; free(matches[i]), i++) {
518               if (is_deleted(lastpart(matches[i]))) {
[2179]519                    if (retval = add_str(found, num, matches[i])) {
520                         error("add_str");
521                         return retval;
522                    }
[1704]523                    num++;
524               }
525               if (lstat(matches[i], &stat_buf))
526                    continue;
[1712]527               if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
[2179]528                    if (retval =
529                        find_deleted_contents_recurs(matches[i], &num_contents,
530                                                     &contents_found)) {
531                         error("find_deleted_contents_recurs");
532                         return retval;
533                    }
534                    if (retval = add_arrays(found, &num, &contents_found,
535                                            &num_contents)) {
536                         error("add_arrays");
537                         return retval;
538                    }
[1704]539               }
540          }
541     }
[2179]542     free((char *) matches);
[1704]543     *num_found = num;
[2179]544     return 0;
[1704]545}
Note: See TracBrowser for help on using the repository browser.