source: trunk/athena/bin/delete/directories.c @ 2181

Revision 2181, 14.5 KB checked in by jik, 35 years ago (diff)
mostly changes for lint errors and new error-handling
Line 
1/*
2 * $Source: /afs/dev.mit.edu/source/repository/athena/bin/delete/directories.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_directories_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/delete/directories.c,v 1.13 1989-10-23 13:40:43 jik Exp $";
15#endif
16
17#include <stdio.h>
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <sys/param.h>
21#include <sys/dir.h>
22#include <strings.h>
23#include <errno.h>
24#include <com_err.h>
25#include "delete_errs.h"
26#include "directories.h"
27#include "util.h"
28#include "mit-copyright.h"
29#include "errors.h"
30
31extern char *malloc(), *realloc();
32extern long time();
33extern int errno;
34
35static filerec root_tree;
36static filerec cwd_tree;
37
38 /* these are not static because external routines need to be able to */
39 /* access them. */
40long current_time;
41
42
43static filerec default_cwd = {
44     "",
45     (filerec *) NULL,
46     (filerec *) NULL,
47     (filerec *) NULL,
48     (filerec *) NULL,
49     (filerec *) NULL,
50     False,
51     False,
52     {0}
53};
54
55static filerec default_root = {
56     "/",
57     (filerec *) NULL,
58     (filerec *) NULL,
59     (filerec *) NULL,
60     (filerec *) NULL,
61     (filerec *) NULL,
62     False,
63     False,
64     {0}
65};
66
67static filerec default_directory = {
68     "",
69     (filerec *) NULL,
70     (filerec *) NULL,
71     (filerec *) NULL,
72     (filerec *) NULL,
73     (filerec *) NULL,
74     False,
75     False,
76     {0}
77};
78
79static filerec default_file = {
80     "",
81     (filerec *) NULL,
82     (filerec *) NULL,
83     (filerec *) NULL,
84     (filerec *) NULL,
85     (filerec *) NULL,
86     False,
87     False,
88     {0}
89};
90
91
92filerec *get_root_tree()
93{
94     return(&root_tree);
95}
96
97
98
99filerec *get_cwd_tree()
100{
101     return(&cwd_tree);
102}
103
104
105int initialize_tree()
106{
107     int retval;
108     
109     root_tree = default_root;
110     cwd_tree = default_cwd;
111
112     current_time = time((time_t *)0);
113     if (retval = get_specs(".", &cwd_tree.specs, FOLLOW_LINKS)) {
114          error("get_specs on .");
115          return retval;
116     }
117     if (retval = get_specs("/", &root_tree.specs, FOLLOW_LINKS)) {
118          error("get_specs on /");
119          return retval;
120     }
121     return 0;
122}
123
124
125int add_path_to_tree(path, leaf)
126char *path;
127filerec **leaf;
128{
129     filerec *parent;
130     char next_name[MAXNAMLEN];
131     char lpath[MAXPATHLEN], built_path[MAXPATHLEN], *ptr;
132     struct stat specs;
133     int retval;
134     
135     if (retval = get_specs(path, &specs, DONT_FOLLOW_LINKS)) {
136          char error_buf[MAXPATHLEN+14];
137
138          (void) sprintf(error_buf, "get_specs on %s", path);
139          error(error_buf);
140          return retval;
141     }
142     
143     (void) strcpy(lpath, path); /* we don't want to damage the user's */
144                                 /* string */
145     ptr = lpath;
146     if (*ptr == '/') {
147          parent = &root_tree;
148          ptr++;
149          (void) strcpy(built_path, "/");
150     }
151     else if (! strncmp(ptr, "./", 2)) {
152          parent = &cwd_tree;
153          ptr += 2;
154          *built_path = '\0';
155     }
156     else {
157          parent = &cwd_tree;
158          *built_path = '\0';
159     }
160     
161     (void) strcpy(next_name, firstpart(ptr, ptr));
162     while (*ptr) {
163          (void) strcat(built_path, next_name);
164          if (retval = add_directory_to_parent(parent, next_name, False,
165                                               &parent)) {
166               error("add_directory_to_parent");
167               return retval;
168          }
169          (void) strcpy(next_name, firstpart(ptr, ptr));
170          if (retval = get_specs(built_path, &parent->specs, FOLLOW_LINKS)) {
171               char error_buf[MAXPATHLEN+14];
172
173               (void) sprintf(error_buf, "get_specs on %s", built_path);
174               error(error_buf);
175               return retval;
176          }
177          (void) strcat(built_path, "/");
178     }
179     if ((specs.st_mode & S_IFMT) == S_IFDIR) {
180          retval = add_directory_to_parent(parent, next_name, True, leaf);
181          if (retval) {
182               error("add_directory_to_parent");
183               return retval;
184          }
185     }
186     else {
187          retval = add_file_to_parent(parent, next_name, True, leaf);
188          if (retval) {
189               error("add_file_to_parent");
190               return retval;
191          }
192     }         
193
194     (*leaf)->specs = specs;
195
196     return 0;
197}
198
199
200
201
202int get_specs(path, specs, follow)
203char *path;
204struct stat *specs;
205int follow; /* follow symlinks or not? */
206{
207     int status;
208     
209     if (strlen(path)) if ((path[strlen(path) - 1] == '/') &&
210                           (strlen(path) != 1))
211          path[strlen(path) - 1] = '\0';
212     if (follow == FOLLOW_LINKS)
213          status = stat(path, specs);
214     else
215          status = lstat(path, specs);
216
217     if (status) {
218          set_error(errno);
219          error(path);
220          return error_code;
221     }
222
223     return 0;
224}
225
226
227
228filerec *next_leaf(leaf)
229filerec *leaf;
230{
231     filerec *new;
232
233     if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) {
234          new = first_in_directory(leaf);
235          if (new)
236               return(new);
237          new = next_directory(leaf);
238          return(new);
239     }
240     else {
241          new = next_in_directory(leaf);
242          return(new);
243     }
244}
245
246
247filerec *next_specified_leaf(leaf)
248filerec *leaf;
249{
250     while (leaf = next_leaf(leaf))
251     if (leaf->specified)
252          return(leaf);
253     return((filerec *) NULL);
254}
255
256
257filerec *next_directory(leaf)
258filerec *leaf;
259{
260     filerec *ret;
261     if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR)
262          leaf = leaf->parent;
263     if (leaf)
264          ret = leaf->next;
265     else
266          ret = (filerec *) NULL;
267     if (ret) if (ret->freed)
268          ret = next_directory(ret);
269     return(ret);
270}
271
272
273filerec *next_specified_directory(leaf)
274filerec *leaf;
275{
276     while (leaf = next_directory(leaf))
277          if (leaf->specified)
278               return(leaf);
279     return ((filerec *) NULL);
280}
281
282
283
284filerec *next_in_directory(leaf)
285filerec *leaf;
286{
287     filerec *ret;
288
289     if (leaf->next)
290          ret = leaf->next;
291     else if (((leaf->specs.st_mode & S_IFMT) != S_IFDIR) && leaf->parent)
292          ret = leaf->parent->dirs;
293     else
294          ret = (filerec *) NULL;
295     if (ret) if (ret->freed)
296          ret = next_in_directory(ret);
297     return (ret);
298}
299
300
301
302
303filerec *next_specified_in_directory(leaf)
304filerec *leaf;
305{
306     while (leaf = next_in_directory(leaf))
307          if (leaf->specified)
308               return(leaf);
309     return ((filerec *) NULL);
310}
311
312
313
314filerec *first_in_directory(leaf)
315filerec *leaf;
316{
317     filerec *ret;
318
319     if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR)
320          ret = (filerec *) NULL;
321     else if (leaf->files)
322          ret = leaf->files;
323     else if (leaf->dirs)
324          ret =  leaf->dirs;
325     else
326          ret = (filerec *) NULL;
327     if (ret) if (ret->freed)
328          ret = next_in_directory(ret);
329     return(ret);
330}
331
332
333filerec *first_specified_in_directory(leaf)
334filerec *leaf;
335{
336     leaf = first_in_directory(leaf);
337     if (! leaf)
338          return((filerec *) NULL);
339     
340     if (leaf->specified)
341          return(leaf);
342     else
343          leaf = next_specified_in_directory(leaf);
344     return (leaf);
345}
346
347
348print_paths_from(leaf)
349filerec *leaf;
350{
351     char buf[MAXPATHLEN];
352
353     printf("%s\n", get_leaf_path(leaf, buf));
354     if (leaf->dirs)
355          print_paths_from(leaf->dirs);
356     if (leaf->files)
357          print_paths_from(leaf->files);
358     if (leaf->next)
359          print_paths_from(leaf->next);
360     return(0);
361}
362
363
364print_specified_paths_from(leaf)
365filerec *leaf;
366{
367     char buf[MAXPATHLEN];
368
369     if (leaf->specified)
370          printf("%s\n", get_leaf_path(leaf, buf));
371     if (leaf->dirs)
372          print_specified_paths_from(leaf->dirs);
373     if (leaf->files)
374          print_specified_paths_from(leaf->files);
375     if (leaf->next)
376          print_specified_paths_from(leaf->next);
377     return(0);
378}
379     
380
381int add_file_to_parent(parent, name, specified, last)
382filerec *parent, **last;
383char *name;
384Boolean specified;
385{
386     filerec *files;
387
388     *last = files = (filerec *) NULL;
389     files = parent->files;
390     while (files) {
391          if (! strcmp(files->name, name))
392               break;
393          *last = files;
394          files = files->next;
395     }
396     if (files) {
397          files->specified = (files->specified || specified);
398          *last = files;
399          return 0;
400     }
401     if (*last) {
402          (*last)->next = (filerec *) malloc((unsigned) sizeof(filerec));
403          if (! (*last)->next) {
404               set_error(errno);
405               error("malloc");
406               return error_code;
407          }
408          *(*last)->next = default_file;
409          (*last)->next->previous = *last;
410          (*last)->next->parent = parent;
411          (*last) = (*last)->next;
412     }
413     else {
414          parent->files = (filerec *) malloc(sizeof(filerec));
415          if (! parent->files) {
416               set_error(errno);
417               error("malloc");
418               return error_code;
419          }
420          *parent->files = default_file;
421          parent->files->parent = parent;
422          parent->files->previous = (filerec *) NULL;
423          *last = parent->files;
424     }
425     (void) strcpy((*last)->name, name);
426     (*last)->specified = specified;
427     return 0;
428}
429
430
431
432
433
434int add_directory_to_parent(parent, name, specified, last)
435filerec *parent, **last;
436char *name;
437Boolean specified;
438{
439     filerec *directories;
440
441     *last = (filerec *) NULL;
442     directories = parent->dirs;
443     while (directories) {
444          if (! strcmp(directories->name, name))
445               break;
446          (*last) = directories;
447          directories = directories->next;
448     }
449     if (directories) {
450          directories->specified = (directories->specified || specified);
451          *last = directories;
452          return 0;
453     }
454     if (*last) {
455          (*last)->next = (filerec *) malloc(sizeof(filerec));
456          if (! (*last)->next) {
457               set_error(errno);
458               error("malloc");
459               return error_code;
460          }
461          *(*last)->next = default_directory;
462          (*last)->next->previous = *last;
463          (*last)->next->parent = parent;
464          (*last) = (*last)->next;
465     }
466     else {
467          parent->dirs = (filerec *) malloc(sizeof(filerec));
468          if (! parent->dirs) {
469               set_error(errno);
470               error("malloc");
471               return error_code;
472          }
473          *parent->dirs = default_directory;
474          parent->dirs->parent = parent;
475          parent->dirs->previous = (filerec *) NULL;
476          (*last) = parent->dirs;
477     }
478     (void) strcpy((*last)->name, name);
479     (*last)->specified = specified;
480     return 0;
481}
482
483
484
485
486
487int free_leaf(leaf)
488filerec *leaf;
489{
490     int retval;
491     
492     leaf->freed = True;
493     if (! (leaf->dirs || leaf->files)) {
494          if (leaf->previous)
495               leaf->previous->next = leaf->next;
496          if (leaf->next)
497               leaf->next->previous = leaf->previous;
498          if (leaf->parent) {
499               if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) {
500                    if (leaf->parent->dirs == leaf) {
501                         leaf->parent->dirs = leaf->next;
502                         if (leaf->parent->freed)
503                              if (retval = free_leaf(leaf->parent))
504                                   return retval;
505                    }
506               }
507               else {
508                    if (leaf->parent->files == leaf) {
509                         leaf->parent->files = leaf->next;
510                         if (leaf->parent->freed)
511                              if (retval = free_leaf(leaf->parent))
512                                   return retval;
513                    }
514               }
515               free((char *) leaf);
516          }
517     }
518     return 0;
519}     
520
521
522
523int find_child(directory, name, child)
524filerec *directory, **child;
525char *name;
526{
527     filerec *ptr;
528     
529     *child = (filerec *) NULL;
530     if ((directory->specs.st_mode & S_IFMT) != S_IFDIR)
531          return DIR_NOT_DIRECTORY;
532     ptr = directory->dirs;
533     while (ptr)
534          if (strcmp(ptr->name, name))
535               ptr = ptr->next;
536          else
537               break;
538     if (ptr) {
539          *child = ptr;
540          return DIR_MATCH;
541     }
542     ptr = directory->files;
543     while (ptr)
544          if (strcmp(ptr->name, name))
545               ptr = ptr->next;
546          else
547               break;
548     if (ptr) {
549          *child = ptr;
550          return DIR_MATCH;
551     }
552     set_status(DIR_NO_MATCH);
553     return DIR_NO_MATCH;
554}
555
556
557
558
559
560int change_path(old_path, new_path)
561char *old_path, *new_path;
562{
563     char next_old[MAXNAMLEN], next_new[MAXNAMLEN];
564     char rest_old[MAXPATHLEN], rest_new[MAXPATHLEN];
565     int retval;
566     filerec *current;
567     
568     if (*old_path == '/') {
569          current = &root_tree;
570          old_path++;
571          new_path++;
572     }
573     else if (! strncmp(old_path, "./", 2)) {
574          current = &cwd_tree;
575          old_path += 2;
576          new_path += 2;
577     }
578     else
579          current = &cwd_tree;
580     
581     (void) strcpy(next_old, firstpart(old_path, rest_old));
582     (void) strcpy(next_new, firstpart(new_path, rest_new));
583     while (*next_old && *next_new) {
584          retval = find_child(current, next_old, &current);
585          if (retval == DIR_MATCH) {
586               if (current) {
587                    (void) strcpy(current->name, next_new);
588                    current->specified = False;
589               }
590               else {
591                    set_error(INTERNAL_ERROR);
592                    error("change_path");
593                    return error_code;
594               }
595          }
596          else {
597               error("change_path");
598               return retval;
599          }
600         
601          (void) strcpy(next_old, firstpart(rest_old, rest_old));
602          (void) strcpy(next_new, firstpart(rest_new, rest_new));
603     }
604     return 0;
605}
606
607
608int get_leaf_path(leaf, leaf_buf)
609filerec *leaf;
610char leaf_buf[]; /* RETURN */
611{
612     char *name_ptr;
613
614     name_ptr = malloc(1);
615     if (! name_ptr) {
616          set_error(errno);
617          error("malloc");
618          *leaf_buf = '\0';
619          return error_code;
620     }
621     *name_ptr = '\0';
622     do {
623          name_ptr = realloc((char *) name_ptr, (unsigned)
624                             (strlen(leaf->name) + strlen(name_ptr) + 2));
625          if (! name_ptr) {
626               set_error(errno);
627               *leaf_buf = '\0';
628               error("realloc");
629               return error_code;
630          }
631          (void) strcpy(leaf_buf, name_ptr);
632          *name_ptr = '\0';
633          if (leaf->parent) if (leaf->parent->parent)
634               (void) strcat(name_ptr, "/");
635          (void) strcat(name_ptr, leaf->name);
636          (void) strcat(name_ptr, leaf_buf);
637          leaf = leaf->parent;
638     } while (leaf);
639     (void) strcpy(leaf_buf, name_ptr);
640     return 0;
641}
642
643
644
645
646
647int accumulate_names(leaf, in_strings, num)
648filerec *leaf;
649char ***in_strings;
650int *num;
651{
652     char newname[MAXPATHLEN];
653     char **strings;
654     int retval;
655     
656     strings = *in_strings;
657     if (leaf->specified) {
658          *num += 1;
659          strings = (char **) realloc((char *) strings, (unsigned)
660                                      (sizeof(char *) * (*num)));
661          if (! strings) {
662               set_error(errno);
663               error("realloc");
664               return error_code;
665          }
666          if (retval = get_leaf_path(leaf, newname)) {
667               error("get_leaf_path");
668               return retval;
669          }
670          convert_to_user_name(newname, newname);
671          strings[*num - 1] = malloc((unsigned) (strlen(newname) + 1));
672          if (! strings[*num - 1]) {
673               set_error(errno);
674               error("malloc");
675               return error_code;
676          }
677          (void) strcpy(strings[*num - 1], newname);
678     }
679     if (leaf->files) if (retval = accumulate_names(leaf->files, &strings,
680                                                    num)) {
681          error("accumulate_names");
682          return retval;
683     }
684     if (leaf->dirs) if (retval = accumulate_names(leaf->dirs, &strings,
685                                                   num)) {
686          error("accumulate_names");
687          return retval;
688     }
689     if (leaf->next) if (retval = accumulate_names(leaf->next, &strings,
690                                                   num)) {
691          error("accumulate_names");
692          return retval;
693     }
694
695     *in_strings = strings;
696     return 0;
697}
Note: See TracBrowser for help on using the repository browser.