v18i078: MIT Athena delete/undelete programs, Part06/06
Rich Salz
rsalz at uunet.uu.net
Wed Mar 29 14:33:55 AEST 1989
Submitted-by: Jonathan I. Kamens <jik at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list