rsalz@uunet.uu.net (Rich Salz) (03/29/89)
Submitted-by: Jonathan I. Kamens <jik@PIT-MANAGER.MIT.EDU> Posting-number: Volume 18, Issue 78 Archive-name: undel/part06 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 6 (of 6)." # Contents: directories.c # Wrapped by jik@pit-manager on Mon Mar 27 12:16:56 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'directories.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'directories.c'\" else echo shar: Extracting \"'directories.c'\" \(12581 characters\) sed "s/^X//" >'directories.c' <<'END_OF_FILE' X/* X * $Source: /mit/jik/src/delete/RCS/directories.c,v $ X * $Author: jik $ X * X * This program is part of a package including delete, undelete, X * lsdel, expunge and purge. The software suite is meant as a X * replacement for rm which allows for file recovery. X * X * Copyright (c) 1989 by the Massachusetts Institute of Technology. X * For copying and distribution information, see the file "mit-copyright.h." X */ X X#if !defined(lint) && !defined(SABER) X static char rcsid_directories_c[] = "$Header: directories.c,v 1.12 89/03/27 12:06:16 jik Exp $"; X#endif X X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/param.h> X#include <sys/dir.h> X#include <strings.h> X#include "directories.h" X#include "util.h" X#include "mit-copyright.h" X Xextern char *malloc(), *realloc(); Xextern char *whoami; X Xstatic filerec root_tree; Xstatic filerec cwd_tree; Xstatic char *error_buf; X X /* these are not static because external routines need to be able to */ X /* access them. */ Xlong current_time; X X Xstatic filerec default_cwd = { X "", X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X False, X False, X {0} X}; X Xstatic filerec default_root = { X "/", X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X False, X False, X {0} X}; X Xstatic filerec default_directory = { X "", X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X False, X False, X {0} X}; X Xstatic filerec default_file = { X "", X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X (filerec *) NULL, X False, X False, X {0} X}; X X Xfilerec *get_root_tree() X{ X return(&root_tree); X} X X X Xfilerec *get_cwd_tree() X{ X return(&cwd_tree); X} X X Xinitialize_tree() X{ X int status; X X root_tree = default_root; X cwd_tree = default_cwd; X X current_time = time(0); X error_buf = (char *) malloc(MAXPATHLEN + strlen(whoami) + 5); X if (! error_buf) { X return(1); X } X status = get_specs("", &cwd_tree.specs, FOLLOW_LINKS); X if (! status) X status = get_specs("/", &root_tree.specs, FOLLOW_LINKS); X return(status); X} X X Xfilerec *add_path_to_tree(path) Xchar *path; X{ X filerec *parent, *leaf; X char next_name[MAXNAMLEN]; X char lpath[MAXPATHLEN], built_path[MAXPATHLEN], *ptr; X struct stat specs; X X if (get_specs(path, &specs, DONT_FOLLOW_LINKS)) X return((filerec *) NULL); X ptr = strcpy(lpath, path); /* we don't want to damage the user's string */ X if (*ptr == '/') { X parent = &root_tree; X ptr++; X strcpy(built_path, "/"); X } X else if (! strncmp(ptr, "./", 2)) { X parent = &cwd_tree; X ptr += 2; X *built_path = '\0'; X } X else { X parent = &cwd_tree; X *built_path = '\0'; X } X X strcpy(next_name, firstpart(ptr, ptr)); X while (*ptr) { X strcat(built_path, next_name); X parent = add_directory_to_parent(parent, next_name, False); X if (! parent) X return ((filerec *) NULL); X strcpy(next_name, firstpart(ptr, ptr)); X if (get_specs(built_path, &parent->specs, FOLLOW_LINKS)) X return((filerec *) NULL); X strcat(built_path, "/"); X } X if ((specs.st_mode & S_IFMT) == S_IFDIR) X leaf = add_directory_to_parent(parent, next_name, True); X else X leaf = add_file_to_parent(parent, next_name, True); X X if (! leaf) X return ((filerec *) NULL); X leaf->specs = specs; X X return(leaf); X} X X X X Xget_specs(path, specs, follow) Xchar *path; Xstruct stat *specs; Xint follow; X{ X int status; X X if (strlen(path)) if ((path[strlen(path) - 1] == '/') && X (strlen(path) != 1)) X path[strlen(path) - 1] = '\0'; X if (follow == FOLLOW_LINKS) X status = stat(path, specs); X else X status = lstat(path, specs); X X if (status) X return(1); X else X return(0); X} X X X Xfilerec *next_leaf(leaf) Xfilerec *leaf; X{ X filerec *new; X X if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) { X new = first_in_directory(leaf); X if (new) X return(new); X new = next_directory(leaf); X return(new); X } X else { X new = next_in_directory(leaf); X return(new); X } X} X X Xfilerec *next_specified_leaf(leaf) Xfilerec *leaf; X{ X while (leaf = next_leaf(leaf)) X if (leaf->specified) X return(leaf); X return((filerec *) NULL); X} X X Xfilerec *next_directory(leaf) Xfilerec *leaf; X{ X filerec *ret; X if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR) X leaf = leaf->parent; X if (leaf) X ret = leaf->next; X else X ret = (filerec *) NULL; X if (ret) if (ret->freed) X ret = next_directory(ret); X return(ret); X} X X Xfilerec *next_specified_directory(leaf) Xfilerec *leaf; X{ X while (leaf = next_directory(leaf)) X if (leaf->specified) X return(leaf); X return ((filerec *) NULL); X} X X X Xfilerec *next_in_directory(leaf) Xfilerec *leaf; X{ X filerec *ret; X X if (leaf->next) X ret = leaf->next; X else if (((leaf->specs.st_mode & S_IFMT) != S_IFDIR) && leaf->parent) X ret = leaf->parent->dirs; X else X ret = (filerec *) NULL; X if (ret) if (ret->freed) X ret = next_in_directory(ret); X return (ret); X} X X X X Xfilerec *next_specified_in_directory(leaf) Xfilerec *leaf; X{ X while (leaf = next_in_directory(leaf)) X if (leaf->specified) X return(leaf); X return ((filerec *) NULL); X} X X X Xfilerec *first_in_directory(leaf) Xfilerec *leaf; X{ X filerec *ret; X X if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR) X ret = (filerec *) NULL; X else if (leaf->files) X ret = leaf->files; X else if (leaf->dirs) X ret = leaf->dirs; X else X ret = (filerec *) NULL; X if (ret) if (ret->freed) X ret = next_in_directory(ret); X return(ret); X} X X Xfilerec *first_specified_in_directory(leaf) Xfilerec *leaf; X{ X leaf = first_in_directory(leaf); X if (! leaf) X return((filerec *) NULL); X X if (leaf->specified) X return(leaf); X else X leaf = next_specified_in_directory(leaf); X return (leaf); X} X X Xprint_paths_from(leaf) Xfilerec *leaf; X{ X char buf[MAXPATHLEN]; X X printf("%s\n", get_leaf_path(leaf, buf)); X if (leaf->dirs) X print_paths_from(leaf->dirs); X if (leaf->files) X print_paths_from(leaf->files); X if (leaf->next) X print_paths_from(leaf->next); X return(0); X} X X Xprint_specified_paths_from(leaf) Xfilerec *leaf; X{ X char buf[MAXPATHLEN]; X X if (leaf->specified) X printf("%s\n", get_leaf_path(leaf, buf)); X if (leaf->dirs) X print_specified_paths_from(leaf->dirs); X if (leaf->files) X print_specified_paths_from(leaf->files); X if (leaf->next) X print_specified_paths_from(leaf->next); X return(0); X} X X Xfilerec *add_file_to_parent(parent, name, specified) Xfilerec *parent; Xchar *name; XBoolean specified; X{ X filerec *files, *last = (filerec *) NULL; X X files = parent->files; X while (files) { X if (! strcmp(files->name, name)) X break; X last = files; X files = files->next; X } X if (files) { X files->specified = (files->specified || specified); X return(files); X } X if (last) { X last->next = (filerec *) malloc(sizeof(filerec)); X if (! last->next) X return((filerec *) NULL); X *last->next = default_file; X last->next->previous = last; X last->next->parent = parent; X last = last->next; X } X else { X parent->files = (filerec *) malloc(sizeof(filerec)); X if (! parent->files) X return((filerec *) NULL); X *parent->files = default_file; X parent->files->parent = parent; X parent->files->previous = (filerec *) NULL; X last = parent->files; X } X strcpy(last->name, name); X last->specified = specified; X return(last); X} X X X X X Xfilerec *add_directory_to_parent(parent, name, specified) Xfilerec *parent; Xchar *name; XBoolean specified; X{ X filerec *directories, *last = (filerec *) NULL; X X directories = parent->dirs; X while (directories) { X if (! strcmp(directories->name, name)) X break; X last = directories; X directories = directories->next; X } X if (directories) { X directories->specified = (directories->specified || specified); X return(directories); X } X if (last) { X last->next = (filerec *) malloc(sizeof(filerec)); X if (! last->next) X return((filerec *) NULL); X *last->next = default_directory; X last->next->previous = last; X last->next->parent = parent; X last = last->next; X } X else { X parent->dirs = (filerec *) malloc(sizeof(filerec)); X if (! parent->dirs) X return((filerec *) NULL); X *parent->dirs = default_directory; X parent->dirs->parent = parent; X parent->dirs->previous = (filerec *) NULL; X last = parent->dirs; X } X strcpy(last->name, name); X last->specified = specified; X return(last); X} X X X X X Xfree_leaf(leaf) Xfilerec *leaf; X{ X leaf->freed = True; X if (! (leaf->dirs || leaf->files)) { X if (leaf->previous) X leaf->previous->next = leaf->next; X if (leaf->next) X leaf->next->previous = leaf->previous; X if (leaf->parent) { X if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) { X if (leaf->parent->dirs == leaf) { X leaf->parent->dirs = leaf->next; X if (leaf->parent->freed) X free_leaf(leaf->parent); X } X } X else { X if (leaf->parent->files == leaf) { X leaf->parent->files = leaf->next; X if (leaf->parent->freed) X free_leaf(leaf->parent); X } X } X free(leaf); X } X } X return(0); X} X X X Xfilerec *find_child(directory, name) Xfilerec *directory; Xchar *name; X{ X filerec *ptr; X X if ((directory->specs.st_mode & S_IFMT) != S_IFDIR) X return ((filerec *) NULL); X ptr = directory->dirs; X while (ptr) X if (strcmp(ptr->name, name)) X ptr = ptr->next; X else X break; X if (ptr) X return (ptr); X ptr = directory->files; X while (ptr) X if (strcmp(ptr->name, name)) X ptr = ptr->next; X else X break; X if (ptr) X return (ptr); X return ((filerec *) NULL); X} X X X X X Xchange_path(old_path, new_path) Xchar *old_path, *new_path; X{ X char next_old[MAXNAMLEN], next_new[MAXNAMLEN]; X char rest_old[MAXPATHLEN], rest_new[MAXPATHLEN]; X X filerec *current; X X if (*old_path == '/') { X current = &root_tree; X old_path++; X new_path++; X } X else if (! strncmp(old_path, "./", 2)) { X current = &cwd_tree; X old_path += 2; X new_path += 2; X } X else X current = &cwd_tree; X X strcpy(next_old, firstpart(old_path, rest_old)); X strcpy(next_new, firstpart(new_path, rest_new)); X while (*next_old && *next_new) { X current = find_child(current, next_old); X if (current) X strcpy(current->name, next_new); X else X return(1); X strcpy(next_old, firstpart(rest_old, rest_old)); X strcpy(next_new, firstpart(rest_new, rest_new)); X } X if (! (*next_old || *next_new)) X return(0); X else X return(1); X} X X Xchar *get_leaf_path(leaf, leaf_buf) Xfilerec *leaf; Xchar leaf_buf[]; /* RETURN */ X{ X char *name_ptr; X X name_ptr = malloc(1); X if (! name_ptr) { X *leaf_buf = '\0'; X return(leaf_buf); X } X *name_ptr = '\0'; X do { X name_ptr = realloc(name_ptr, strlen(leaf->name) + X strlen(name_ptr) + 2); X if (! name_ptr) { X *leaf_buf = '\0'; X return(leaf_buf); X } X strcpy(leaf_buf, name_ptr); X *name_ptr = '\0'; X if (leaf->parent) if (leaf->parent->parent) X strcat(name_ptr, "/"); X strcat(name_ptr, leaf->name); X strcat(name_ptr, leaf_buf); X leaf = leaf->parent; X } while (leaf); X strcpy(leaf_buf, name_ptr); X return(leaf_buf); X} X X X X X Xchar **accumulate_names(leaf, strings, num) Xfilerec *leaf; Xchar **strings; Xint *num; X{ X char newname[MAXPATHLEN]; X X if (leaf->specified) { X *num += 1; X strings = (char **) realloc(strings, sizeof(char *) * (*num)); X if (! strings) { X perror(sprintf(error_buf, "%s: accumulate_names", whoami)); X exit(1); X } X convert_to_user_name(get_leaf_path(leaf, newname), newname); X strings[*num - 1] = malloc(strlen(newname) + 1); X if (! strings[*num - 1]) { X perror(sprintf(error_buf, "%s: accumulate_names", whoami)); X exit(1); X } X strcpy(strings[*num - 1], newname); X } X if (leaf->files) X strings = accumulate_names(leaf->files, strings, num); X if (leaf->dirs) X strings = accumulate_names(leaf->dirs, strings, num); X if (leaf->next) X strings = accumulate_names(leaf->next, strings, num); X X return(strings); X} END_OF_FILE if test 12581 -ne `wc -c <'directories.c'`; then echo shar: \"'directories.c'\" unpacked with wrong size! fi # end of 'directories.c' fi echo shar: End of archive 6 \(of 6\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.