v18i076: MIT Athena delete/undelete programs, Part04/06
Rich Salz
rsalz at uunet.uu.net
Wed Mar 29 14:32:41 AEST 1989
Submitted-by: Jonathan I. Kamens <jik at PIT-MANAGER.MIT.EDU>
Posting-number: Volume 18, Issue 76
Archive-name: undel/part04
#! /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 4 (of 6)."
# Contents: expunge.c pattern.c
# Wrapped by jik at pit-manager on Mon Mar 27 12:16:51 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'expunge.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'expunge.c'\"
else
echo shar: Extracting \"'expunge.c'\" \(10893 characters\)
sed "s/^X//" >'expunge.c' <<'END_OF_FILE'
X/*
X * $Source: /mit/jik/src/delete/RCS/expunge.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_expunge_c[] = "$Header: expunge.c,v 1.7 89/03/27 12:06:47 jik Exp $";
X#endif
X
X/*
X * Things that need to be fixed later:
X *
X * 1. The program should somehow store the sizes of deleted files and
X * report the total amount of space regained after an expunge or purge.
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/dir.h>
X#include <sys/param.h>
X#include <strings.h>
X#include <sys/stat.h>
X#include "col.h"
X#include "directories.h"
X#include "util.h"
X#include "pattern.h"
X#include "expunge.h"
X#include "mit-copyright.h"
X
Xextern char *malloc(), *realloc();
Xextern int current_time;
X
Xchar *whoami, *error_buf;
X
Xint timev, /* minimum mod time before undeletion */
X interactive, /* query before each expunge */
X recursive, /* expunge undeleted directories recursively */
X noop, /* print what would be done instead of doing it */
X verbose, /* print a line as each file is deleted */
X force, /* do not ask for any confirmation */
X listfiles, /* list files at toplevel */
X yield; /* print yield of expunge at end */
X
Xint blocks_removed = 0;
X
X
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X extern char *optarg;
X extern int optind;
X int arg;
X int status = 0;
X
X whoami = lastpart(argv[0]);
X error_buf = malloc(strlen(whoami) + MAXPATHLEN + 3);
X if (! error_buf) {
X perror(whoami);
X exit(1);
X }
X if (*whoami == 'p') { /* we're doing a purge */
X exit (purge());
X }
X timev = 0;
X yield = interactive = recursive = noop = verbose = listfiles = force = 0;
X while ((arg = getopt(argc, argv, "t:irfnvly")) != -1) {
X switch (arg) {
X case 't':
X timev = atoi(optarg);
X break;
X case 'i':
X interactive++;
X break;
X case 'r':
X recursive++;
X break;
X case 'f':
X force++;
X break;
X case 'n':
X noop++;
X break;
X case 'v':
X verbose++;
X break;
X case 'l':
X listfiles++;
X break;
X case 'y':
X yield++;
X break;
X default:
X usage();
X exit(1);
X }
X }
X if (optind == argc) {
X char *dir;
X dir = ".";
X status = status | expunge(&dir, 1); /* current working directory */
X }
X else
X status = status | expunge(&argv[optind], argc - optind);
X exit(status & ERROR_MASK);
X}
X
X
X
X
X
Xpurge()
X{
X char *home[1];
X
X home[0] = malloc(MAXPATHLEN);
X if (! home[0]) {
X perror(sprintf(error_buf, "%s: purge", whoami));
X exit(1);
X }
X timev = interactive = noop = verbose = force = 0;
X yield = listfiles = recursive = 1;
X get_home(home[0]);
X if (! *home[0]) {
X fprintf(stderr, "%s: purge: can't get home directory\n", whoami);
X exit(1);
X }
X
X printf("Please be patient.... this may take a while.\n\n");
X
X return(expunge(home, 1));
X}
X
X
X
X
Xusage()
X{
X printf("Usage: %s [ options ] [ filename [ ... ]]\n", whoami);
X printf("Options are:\n");
X printf(" -r recursive\n");
X printf(" -i interactive\n");
X printf(" -f force\n");
X printf(" -t n n-day-or-older expunge\n");
X printf(" -n noop\n");
X printf(" -v verbose\n");
X printf(" -l list files before expunging\n");
X printf(" -y print yield of expunge\n");
X printf(" -- end options and start filenames\n");
X}
X
X
X
X
X
Xexpunge(files, num)
Xchar **files;
Xint num;
X{
X char *file_re;
X char **found_files;
X int num_found;
X char *start_dir;
X int status = 0;
X int total = 0;
X filerec *current;
X
X if (initialize_tree())
X exit(1);
X
X for ( ; num ; num--) {
X if (*files[num - 1] == '/') {
X start_dir = "/";
X file_re = parse_pattern(files[num - 1] + 1);
X }
X else {
X start_dir = "";
X file_re = parse_pattern(files[num - 1]);
X }
X if (! file_re)
X return(ERROR_MASK);
X
X found_files = get_the_files(start_dir, file_re, &num_found);
X if (num_found)
X num_found = process_files(found_files, num_found);
X total += num_found;
X if (! num_found) if (! force) {
X /*
X * There are three different situations here. Eiter we
X * are dealing with an existing directory with no
X * deleted files in it, or we are deleting with a
X * non-existing deleted file with wildcards, or we are
X * dealing with a non-existing deleted file without
X * wildcards. In the former case we print nothing, and
X * in the latter cases we print either "no match" or
X * "not found" respectively
X */
X if (no_wildcards(file_re)) {
X if (! directory_exists(files[num - 1])) {
X fprintf(stderr, "%s: %s: not found\n",
X whoami, files[num - 1]);
X }
X }
X else {
X fprintf(stderr, "%s: %s: no match\n", whoami,
X files[num - 1]);
X }
X }
X free(file_re);
X }
X if (total && listfiles) {
X list_files();
X if (! force) if (! top_level())
X return(NO_DELETE_MASK);
X }
X current = get_root_tree();
X if (current)
X status = status | expunge_specified(current);
X current = get_cwd_tree();
X if (current)
X status = status | expunge_specified(current);
X
X if (yield) {
X if (noop)
X printf("Total that would be expunged: %dk\n",
X blk_to_k(blocks_removed));
X else
X printf("Total expunged: %dk\n", blk_to_k(blocks_removed));
X }
X return(status);
X}
X
X
X
Xexpunge_specified(leaf)
Xfilerec *leaf;
X{
X int status = 0;
X
X if ((leaf->specified) && ((leaf->specs.st_mode & S_IFMT) == S_IFDIR))
X status = do_directory_expunge(leaf);
X /* the "do_directory_expunge" really only asks the user if he */
X /* wants to expunge the directory, it doesn't do any deleting. */
X if (! status) {
X if (leaf->dirs)
X status |= expunge_specified(leaf->dirs);
X if (leaf->files)
X status |= expunge_specified(leaf->files);
X }
X if (leaf->specified)
X status |= really_do_expunge(leaf);
X if (leaf->next)
X status |= expunge_specified(leaf->next);
X free_leaf(leaf);
X return(status);
X}
X
X
Xprocess_files(files, num)
Xchar **files;
Xint num;
X{
X int i;
X filerec *leaf;
X
X for (i = 0; i < num; i++) {
X if (! (leaf = add_path_to_tree(files[i]))) {
X fprintf(stderr, "%s: error adding path to filename tree\n",
X whoami);
X exit(1);
X }
X
X free(files[i]);
X if (! timed_out(leaf, current_time, timev)) {
X free_leaf(leaf);
X num--;
X }
X }
X free(files);
X return(num);
X}
X
X
X
X
X
X
X
X
X
Xdo_directory_expunge(file_ent)
Xfilerec *file_ent;
X{
X char buf[MAXPATHLEN];
X
X get_leaf_path(file_ent, buf);
X convert_to_user_name(buf, buf);
X
X if (interactive) {
X printf("%s: Expunge directory %s? ", whoami, buf);
X if (! yes())
X return(NO_DELETE_MASK);
X }
X return(0);
X}
X
X
X
X
X
X
X
X
Xreally_do_expunge(file_ent)
Xfilerec *file_ent;
X{
X char real[MAXPATHLEN], user[MAXPATHLEN];
X int status;
X
X get_leaf_path(file_ent, real);
X convert_to_user_name(real, user);
X
X if (interactive) {
X printf ("%s: Expunge %s (%dk)? ", whoami, user,
X blk_to_k(file_ent->specs.st_blocks));
X if (! yes())
X return(NO_DELETE_MASK);
X }
X
X if (noop) {
X blocks_removed += file_ent->specs.st_blocks;
X printf("%s: %s (%dk) would be expunged (%dk total)\n", whoami, user,
X blk_to_k(file_ent->specs.st_blocks),
X blk_to_k(blocks_removed));
X return(0);
X }
X
X if ((file_ent->specs.st_mode & S_IFMT) == S_IFDIR)
X status = rmdir(real);
X else
X status = unlink(real);
X if (! status) {
X blocks_removed += file_ent->specs.st_blocks;
X if (verbose)
X printf("%s: %s (%dk) expunged (%dk total)\n", whoami, user,
X blk_to_k(file_ent->specs.st_blocks),
X blk_to_k(blocks_removed));
X return(0);
X }
X else {
X if (! force)
X fprintf(stderr, "%s: %s not expunged\n", whoami, user);
X return(ERROR_MASK);
X }
X}
X
X
X
X
X
X
X
X
X
Xtop_level()
X{
X if (interactive) {
Xprintf("The above files, which have been marked for deletion, are about to be\n");
Xprintf("expunged forever! You will be asked for confirmation before each file is\n");
Xprintf("deleted. Do you wish to continue [return = no]? ");
X }
X else {
Xprintf("The above files, which have been marked for deletion, are about to be\n");
Xprintf("expunged forever! Make sure you don't need any of them before continuing.\n");
Xprintf("Do you wish to continue [return = no]? ");
X }
X return (yes());
X}
X
X
X
X
X
Xlist_files()
X{
X filerec *current;
X char **strings;
X int num;
X
X strings = (char **) malloc(sizeof(char *));
X num = 0;
X if (! strings) {
X if (! force)
X perror(sprintf(error_buf, "%s: list_files", whoami));
X exit(1);
X }
X printf("The following deleted files are going to be expunged: \n\n");
X
X current = get_root_tree();
X strings = accumulate_names(current, strings, &num);
X current = get_cwd_tree();
X strings = accumulate_names(current, strings, &num);
X column_array(strings, num, DEF_SCR_WIDTH, 0, 0, 2, 1, 0, 1, stdout);
X printf("\n");
X return(0);
X}
X
X
X
X
X
Xchar **get_the_files(base, reg_exp, num_found)
Xchar *base, *reg_exp;
Xint *num_found;
X{
X char **matches;
X int num_matches;
X char **found;
X int num;
X int i;
X
X found = (char **) malloc(0);
X num = 0;
X
X matches = find_matches(base, reg_exp, &num_matches);
X if (recursive) {
X char **recurs_found;
X int recurs_num;
X
X for (i = 0; i < num_matches; free(matches[i]), i++) {
X if (is_deleted(lastpart(matches[i]))) {
X found = add_str(found, num, matches[i]);
X num++;
X }
X recurs_found = find_deleted_recurses(matches[i], &recurs_num);
X add_arrays(&found, &num, &recurs_found, &recurs_num);
X }
X }
X else {
X struct stat stat_buf;
X char **contents_found;
X int num_contents;
X
X for (i = 0; i < num_matches; free(matches[i]), i++) {
X if (is_deleted(lastpart(matches[i]))) {
X found = add_str(found, num, matches[i]);
X num++;
X }
X if (lstat(matches[i], &stat_buf))
X continue;
X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
X contents_found = find_deleted_contents_recurs(matches[i],
X &num_contents);
X add_arrays(&found, &num, &contents_found,
X &num_contents);
X }
X }
X }
X free(matches);
X *num_found = num;
X return(found);
X}
END_OF_FILE
if test 10893 -ne `wc -c <'expunge.c'`; then
echo shar: \"'expunge.c'\" unpacked with wrong size!
fi
# end of 'expunge.c'
fi
if test -f 'pattern.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'pattern.c'\"
else
echo shar: Extracting \"'pattern.c'\" \(12106 characters\)
sed "s/^X//" >'pattern.c' <<'END_OF_FILE'
X/*
X * $Source: /mit/jik/src/delete/RCS/pattern.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_pattern_c[] = "$Header: pattern.c,v 1.8 89/03/27 12:07:48 jik Exp $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <sys/param.h>
X#include <strings.h>
X#include <sys/stat.h>
X#include "directories.h"
X#include "pattern.h"
X#include "util.h"
X#include "undelete.h"
X#include "mit-copyright.h"
X
Xstatic char *add_char();
X
Xextern char *malloc(), *realloc();
X
Xextern char *whoami, *error_buf;
X
X/*
X * parse_pattern returns an area of memory allocated by malloc when it
X * is successful. Therefore, other procedures calling parse_pattern
X * should use free() to free the region of memory when they are done
X * with it.
X */
Xchar *parse_pattern(file_pattern)
Xchar *file_pattern;
X{
X char *re_pattern, *cur_ptr, *re_ptr;
X int guess_length;
X
X guess_length = strlen(file_pattern) + 5;
X re_ptr = re_pattern = malloc(guess_length);
X if (! re_ptr) {
X perror(sprintf(error_buf, "%s: parse_pattern", whoami));
X exit(1);
X }
X
X for (cur_ptr = file_pattern, re_ptr = re_pattern; *cur_ptr != NULL;
X cur_ptr++) {
X if (*cur_ptr == '\\') {
X if (! cur_ptr[1]) {
X fprintf(stderr,
X "%s: parse_pattern: incomplete expression\n",
X whoami);
X return((char *) NULL);
X }
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
X return ((char *) NULL);
X cur_ptr++;
X if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
X return ((char *) NULL);
X continue;
X }
X else if (*cur_ptr == '*') {
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
X return ((char *) NULL);
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '*'))
X return ((char *) NULL);
X continue;
X }
X else if (*cur_ptr == '?') {
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
X return ((char *) NULL);
X continue;
X }
X else if (*cur_ptr == '.') {
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '\\'))
X return ((char *) NULL);
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '.'))
X return ((char *) NULL);
X }
X else {
X if (! add_char(&re_pattern, &re_ptr, &guess_length, *cur_ptr))
X return ((char *) NULL);
X }
X }
X if (! add_char(&re_pattern, &re_ptr, &guess_length, '\0'))
X return ((char *) NULL);
X return (re_pattern);
X}
X
X
X
X
X
X
X/*
X * add_char() takes two char **, a length which is the current amount
X * of space implemented for the string pointed to by the first *(char **),
X * and a character to add to the string. It reallocs extra space if
X * necessary, adds the character, and messes with the pointers if necessary.
X */
Xstatic char *add_char(start, finish, length, chr)
Xchar **start, **finish;
Xint *length;
Xchar chr;
X{
X if (*finish - *start == *length) {
X *start = realloc(*start, *length + 5);
X if (! *start) {
X perror(sprintf(error_buf, "%s: add_char", whoami));
X exit(1);
X }
X *finish = *start + *length - 1;
X *length += 5;
X }
X **finish = chr;
X (*finish)++;
X return(*start);
X}
X
X
X
X
X
X
X/*
X * add_arrays() takes pointers to two arrays of char **'s and their
X * lengths, merges the two into the first by realloc'ing the first and
X * then free's the second's memory usage.
X */
Xadd_arrays(array1, num1, array2, num2)
Xchar ***array1, ***array2;
Xint *num1, *num2;
X{
X int counter;
X
X *array1 = (char **) realloc(*array1, sizeof(char *) * (*num1 + *num2));
X if (! *array1) {
X perror(sprintf(error_buf, "%s: add_arrays", whoami));
X exit(1);
X }
X for (counter = *num1; counter < *num1 + *num2; counter++)
X *(*array1 + counter) = *(*array2 + counter - *num1);
X free (*array2);
X *num1 += *num2;
X return(0);
X}
X
X
X
X
X
X
X
Xchar **add_str(strs, num, str)
Xchar **strs;
Xint num;
Xchar *str;
X{
X strs = (char **) realloc(strs, sizeof(char *) * (num + 1));
X if (! strs) {
X perror(sprintf(error_buf, "%s: add_str", whoami));
X exit(1);
X }
X strs[num] = malloc(strlen(str) + 1);
X if (! strs[num]) {
X perror(sprintf(error_buf, "%s: add_str", whoami));
X exit(1);
X }
X strcpy(strs[num], str);
X return(strs);
X}
X
X
X
X
X
X
X
Xchar **find_deleted_matches(base, expression, num_found)
Xchar *base, *expression;
Xint *num_found;
X{
X struct direct *dp;
X DIR *dirp;
X char **found;
X int num;
X char **next;
X int num_next;
X char first[MAXNAMLEN], rest[MAXPATHLEN];
X char new[MAXPATHLEN];
X
X#ifdef DEBUG
X printf("Looking for %s in %s\n", expression, base);
X#endif
X found = (char **) malloc(0);
X *num_found = num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X readdir(dirp); readdir(dirp); /* get rid of . and .. */
X
X strcpy(first, reg_firstpart(expression, rest));
X re_comp(first);
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X if (re_exec(dp->d_name) && *rest) {
X strcpy(new, append(base, dp->d_name));
X next = find_deleted_matches(new, rest, &num_next);
X add_arrays(&found, &num, &next, &num_next);
X }
X else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
X if (*rest) {
X strcpy(new, append(base, dp->d_name));
X next = find_deleted_matches(new, rest, &num_next);
X add_arrays(&found, &num, &next, &num_next);
X }
X else {
X found = add_str(found, num, append(base, dp->d_name));
X num++;
X }
X }
X }
X closedir(dirp);
X *num_found = num;
X return(found);
X}
X
X
X
X
X
Xchar **find_matches(base, expression, num_found)
Xchar *base, *expression;
Xint *num_found;
X{
X struct direct *dp;
X DIR *dirp;
X char **found;
X int num;
X char **next;
X int num_next;
X char first[MAXNAMLEN], rest[MAXPATHLEN];
X char new[MAXPATHLEN];
X
X#ifdef DEBUG
X printf("Looking for %s in %s\n", expression, base);
X#endif
X found = (char **) malloc(0);
X *num_found = num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X strcpy(first, reg_firstpart(expression, rest));
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X re_comp(first);
X if (re_exec(dp->d_name)) {
X if (*rest) {
X strcpy(new, append(base, dp->d_name));
X next = find_matches(new, rest, &num_next);
X add_arrays(&found, &num, &next, &num_next);
X }
X else {
X found = add_str(found, num, append(base, dp->d_name));
X num++;
X }
X }
X else if (is_deleted(dp->d_name)) if (re_exec(&dp->d_name[2])) {
X if (*rest) {
X strcpy(new, append(base, dp->d_name));
X next = find_matches(new, rest, &num_next);
X add_arrays(&found, &num, &next, &num_next);
X }
X else {
X found = add_str(found, num, append(base, dp->d_name));
X num++;
X }
X }
X }
X closedir(dirp);
X *num_found = num;
X return(found);
X}
X
X
X
X
X
X
X
Xchar **find_recurses(base, num_found)
Xchar *base;
Xint *num_found;
X{
X DIR *dirp;
X struct direct *dp;
X char newname[MAXPATHLEN];
X char **found, **new_found;
X int found_num, new_found_num;
X struct stat stat_buf;
X
X#ifdef DEBUG
X printf("Looking for subs of %s\n", base);
X#endif
X found = (char **) malloc(0);
X *num_found = found_num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X readdir(dirp); readdir(dirp); /* get rid of . and .. */
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X strcpy(newname, append(base, dp->d_name));
X found = add_str(found, found_num, newname);
X found_num++;
X if (lstat(newname, &stat_buf))
X continue;
X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
X new_found = find_recurses(newname, &new_found_num);
X add_arrays(&found, &found_num, &new_found, &new_found_num);
X }
X }
X closedir(dirp);
X *num_found = found_num;
X return(found);
X}
X
X
X
X
X
X
Xchar **find_deleted_recurses(base, num_found)
Xchar *base;
Xint *num_found;
X{
X DIR *dirp;
X struct direct *dp;
X char newname[MAXPATHLEN];
X char **found, **new_found;
X int found_num, new_found_num;
X struct stat stat_buf;
X
X found = (char **) malloc(0);
X *num_found = found_num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X readdir(dirp); readdir(dirp); /* get rid of . and .. */
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X strcpy(newname, append(base, dp->d_name));
X
X if (is_deleted(dp->d_name)) {
X found = add_str(found, found_num, newname);
X found_num++;
X }
X if (lstat(newname, &stat_buf)) {
X continue;
X }
X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
X new_found = find_deleted_recurses(newname, &new_found_num);
X add_arrays(&found, &found_num, &new_found, &new_found_num);
X }
X }
X closedir(dirp);
X *num_found = found_num;
X return(found);
X}
X
X
X
X
X
X
Xchar **find_contents(base, num_found)
Xchar *base;
Xint *num_found;
X{
X DIR *dirp;
X struct direct *dp;
X char **found;
X int num;
X
X#ifdef DEBUG
X printf("Looking for contents of %s\n", base);
X#endif
X found = (char **) malloc(0);
X *num_found = num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X readdir(dirp); readdir(dirp); /* get rid of . and .. */
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X found = add_str(found, num, append(base, dp->d_name));
X num += 1;
X }
X closedir(dirp);
X *num_found = num;
X return(found);
X}
X
X
X
Xchar **find_deleted_contents(base, num_found)
Xchar *base;
Xint *num_found;
X{
X DIR *dirp;
X struct direct *dp;
X char **found;
X int num;
X
X#ifdef DEBUG
X printf("Looking for deleted contents of %s\n", base);
X#endif
X found = (char **) malloc(0);
X *num_found = num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X readdir(dirp); readdir(dirp); /* get rid of . and .. */
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X if (is_deleted(dp->d_name)) {
X found = add_str(found, num, append(base, dp->d_name));
X num += 1;
X }
X }
X closedir(dirp);
X *num_found = num;
X return(found);
X}
X
X
X
X
Xchar **find_deleted_contents_recurs(base, num_found)
Xchar *base;
Xint *num_found;
X{
X DIR *dirp;
X struct direct *dp;
X char **found;
X int num;
X struct stat stat_buf;
X char newname[MAXPATHLEN];
X char **new_found;
X int new_found_num;
X
X#ifdef DEBUG
X printf("Looking for recursive deleted contents of %s\n", base);
X#endif
X found = (char **) malloc(0);
X *num_found = num = 0;
X
X dirp = opendir(base);
X if (! dirp)
X return(found);
X
X readdir(dirp); readdir(dirp); /* get rid of . and .. */
X
X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X if (is_deleted(dp->d_name)) {
X strcpy(newname, append(base, dp->d_name));
X found = add_str(found, num, newname);
X num += 1;
X if (lstat(newname, &stat_buf))
X continue;
X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
X new_found = find_recurses(newname, &new_found_num);
X add_arrays(&found, &num, &new_found, &new_found_num);
X }
X }
X }
X closedir(dirp);
X *num_found = num;
X return(found);
X}
X
X
X
X/*
X * returns true if the filename has no regular expression wildcards in
X * it. That means no non-quoted dots or asterisks. Assumes a
X * null-terminated string, and a valid regular expression.
X */
Xint no_wildcards(name)
Xchar *name;
X{
X do {
X switch (*name) {
X case '\\':
X name++;
X break;
X case '.':
X return(0);
X case '*':
X return(0);
X }
X } while (*++name);
X return(1);
X}
END_OF_FILE
if test 12106 -ne `wc -c <'pattern.c'`; then
echo shar: \"'pattern.c'\" unpacked with wrong size!
fi
# end of 'pattern.c'
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
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