home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / undel / part06 / directories.c
Encoding:
C/C++ Source or Header  |  1989-05-06  |  12.3 KB  |  605 lines

  1. /*
  2.  * $Source: /mit/jik/src/delete/RCS/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: directories.c,v 1.12 89/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.  
  26. extern char *malloc(), *realloc();
  27. extern char *whoami;
  28.  
  29. static filerec root_tree;
  30. static filerec cwd_tree;
  31. static char *error_buf;
  32.  
  33.  /* these are not static because external routines need to be able to */
  34.  /* access them. */
  35. long current_time;
  36.  
  37.  
  38. static 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.  
  50. static 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.  
  62. static 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.  
  74. static 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.  
  87. filerec *get_root_tree()
  88. {
  89.      return(&root_tree);
  90. }
  91.  
  92.  
  93.  
  94. filerec *get_cwd_tree()
  95. {
  96.      return(&cwd_tree);
  97. }
  98.  
  99.  
  100. initialize_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.  
  119. filerec *add_path_to_tree(path)
  120. char *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.  
  171. get_specs(path, specs, follow)
  172. char *path;
  173. struct stat *specs;
  174. int 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.  
  194. filerec *next_leaf(leaf)
  195. filerec *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.  
  213. filerec *next_specified_leaf(leaf)
  214. filerec *leaf;
  215. {
  216.      while (leaf = next_leaf(leaf))
  217.      if (leaf->specified)
  218.       return(leaf);
  219.      return((filerec *) NULL);
  220. }
  221.  
  222.  
  223. filerec *next_directory(leaf)
  224. filerec *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.  
  239. filerec *next_specified_directory(leaf)
  240. filerec *leaf;
  241. {
  242.      while (leaf = next_directory(leaf))
  243.       if (leaf->specified)
  244.            return(leaf);
  245.      return ((filerec *) NULL);
  246. }
  247.  
  248.  
  249.  
  250. filerec *next_in_directory(leaf)
  251. filerec *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.  
  269. filerec *next_specified_in_directory(leaf)
  270. filerec *leaf;
  271. {
  272.      while (leaf = next_in_directory(leaf))
  273.       if (leaf->specified)
  274.            return(leaf);
  275.      return ((filerec *) NULL);
  276. }
  277.  
  278.  
  279.  
  280. filerec *first_in_directory(leaf)
  281. filerec *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.  
  299. filerec *first_specified_in_directory(leaf)
  300. filerec *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.  
  314. print_paths_from(leaf)
  315. filerec *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.  
  330. print_specified_paths_from(leaf)
  331. filerec *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.  
  347. filerec *add_file_to_parent(parent, name, specified)
  348. filerec *parent;
  349. char *name;
  350. Boolean 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.  
  392. filerec *add_directory_to_parent(parent, name, specified)
  393. filerec *parent;
  394. char *name;
  395. Boolean 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.  
  437. free_leaf(leaf)
  438. filerec *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.  
  469. filerec *find_child(directory, name)
  470. filerec *directory;
  471. char *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.  
  500. change_path(old_path, new_path)
  501. char *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.  
  539. char *get_leaf_path(leaf, leaf_buf)
  540. filerec *leaf;
  541. char 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.  
  574. char **accumulate_names(leaf, strings, num)
  575. filerec *leaf;
  576. char **strings;
  577. int *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. }
  605.