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

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