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

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