[comp.sources.unix] v18i078: MIT Athena delete/undelete programs, Part06/06

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.