fssal - BSD filesystem salvage program, Part 01/01
Bob Ankeney
bob at reed.UUCP
Wed Apr 10 06:44:15 AEST 1991
#!/bin/sh
# shar: Shell Archiver (v1.22)
#
# Run the following text with /bin/sh to create:
# README
# FILES
# NOTES
# Makefile
# defs.h
# fs.h
# idir.c
# iname.c
# io.c
# ls.c
# main.c
# namei.c
# restore.c
# stat.c
#
sed 's/^X//' << 'SHAR_EOF' > README &&
X Fssal is a utility to salvage files from damaged BSD filesystems.
XSuch damage might include a lost super-block, trashed cylinder group,
Xdrive with bad blocks, or perhaps a filesystem with files that may get
Xconsumed by a fsck. It requires the presence of a relatively intact
Xfilesystem (an intact original or alternate super-block, some semblence
Xof an inode-structure, and some intact cylinder-groups). Thus such
Xthings as deleted files cannot be restored.
X
X The impetus for writing this program was to recover files from a
Xfilesystem with the original super-block and first (of six) cylinder
Xgroups walked on. What happened was a mkfs of a small system was
Xaccidentally done, which wiped the initial data. Data from all other
Xcylinder groups was still intact and recoverable. An alternate (spare)
Xsuper-block is found within each cylinder group.
X
X All restored files are placed relative to the working directory,
Xand all permissions, creation/modification times, and ownerships are
Xrestored. Both real and symbolic links are handled, as well as
Xcharacter and block special devices and sockets.
X
X At no time is the specified file-system written on, thus data is
Xsafe. The specified file-system need not be mounted (and probably
Xshouldn't be lest others modify it as a restore is in progress).
X
X The general usage is:
X
X fssal [-f device] [-s super-block] [-r root-inode] [-a] [-R] [-v]
X
X where:
X -f device: is the file-system to use (do not use the raw device!!)
X -s super-block: is an alternate super-block
X -r root-inode: is an alternate directory inode to start at
X
X -a: stats all inodes in file-system and restores those that are
X directories. The -R flag can be used to recursively walk each
X sub-directory. Each directory found that has not yet been
X restored will be created with the directory name '#inum', where
X inum is the inode number of that directory.
X
X -R: recursively walk each sub-directory found.
X
X -v: verbose mode. Spews out lots of information as to what's been
X restored.
X
X A link to fssal called fsls exists which does a directory listing on
Xthe specified file system. The general usage is:
X
X fsls [-f device] [-s super-block] [-r root-inode] [-a] [-R] [-l]
X
X where:
X -f device: is the file-system to use (do not use the raw device!!)
X -s super-block: is an alternate super-block
X -r root-inode: is an alternate directory inode to start at
X
X -a: stats all inodes in file-system and lists those that are
X directories. The -R flag can be used to recursively walk each
X sub-directory.
X
X -R: recursively walk each sub-directory found.
X
X -l: do a long directory list (like 'ls -liga')
X
X
X Hopefully someone will take this under their wing and make improvements
Xto it. Some suggestions are:
X a) Make it interactive (ala restore -i).
X b) Port it to other platforms; it has been used successfully on:
X DEC VAX with Mt. Xinu
X DEC VAX with Ultrix V2.3
X Sun-4 with SunOs V4.1
X Tektronix Utek V2.2
X c) A manual page.
X
X
X Feel free to mail me any suggestions, bug fixes and enhancements. I'll
Xtry to integrate them (it's been a while since I wrote this) and make occasional
Xreleases. If it looks solid enough, I'll post to comp.sources.unix.
X
X Bob Ankeney
X ...!tektronix!bob at reed.bitnet
X
SHAR_EOF
chmod 0644 README || echo "restore of README fails"
sed 's/^X//' << 'SHAR_EOF' > FILES &&
XREADME
XFILES
XNOTES
XMakefile
Xdefs.h
Xfs.h
Xidir.c
Xiname.c
Xio.c
Xls.c
Xmain.c
Xnamei.c
Xrestore.c
Xstat.c
SHAR_EOF
chmod 0644 FILES || echo "restore of FILES fails"
sed 's/^X//' << 'SHAR_EOF' > NOTES &&
XThings to check for:
X
X Error handling (failed reads especially).
X
X Freeing of malloced space.
X
XTo do:
X
X Read inode into buffer and get inode structures from it (fixes reads on
X raw device).
X
X Cache ureads? (uread reads entire block and bcopies desired info).
X Keep track of last block read to avoid duplicate reads.
X
SHAR_EOF
chmod 0644 NOTES || echo "restore of NOTES fails"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#CFLAGS = -g -DDEBUG
XCFLAGS = -g -DBSD4_3
X
XSRCS = io.c namei.c iname.c ls.c restore.c main.c stat.c idir.c
XOBJS = io.o namei.o iname.o ls.o restore.o main.o stat.o idir.o
X
Xall: fssal fsls
X
Xfssal: $(OBJS)
X rm -f fsls
X cc $(CFLAGS) $(OBJS) -o fssal
X
Xfsls: fssal
X ln fssal fsls
X
Xio.o: defs.h fs.h
X
Xnamei.o: defs.h fs.h
X
Xiname.o: defs.h fs.h
X
Xls.o: defs.h fs.h
X
Xrestore.o: defs.h fs.h
X
Xmain.o: defs.h fs.h
X
Xstat.o: defs.h fs.h
X
Xidir.o: defs.h fs.h
X
Xclean:
X rm -f $(OBJS)
X
Xlint:
X lint $(SRCS)
X
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
sed 's/^X//' << 'SHAR_EOF' > defs.h &&
X
X#define FS_TO_READ "/dev/dh60h"
X
X /* Maximum size for path name */
X#define MAX_PATH_LEN 128
X
X /* Number of inode numbers per sturct idir segment */
X#define MAX_ICNT 32
X
X#ifndef TRUE
X#define TRUE (1)
X#define FALSE (0)
X#endif
X
SHAR_EOF
chmod 0644 defs.h || echo "restore of defs.h fails"
sed 's/^X//' << 'SHAR_EOF' > fs.h &&
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include <sys/param.h>
X#ifdef BSD4_2
X#include <sys/fs.h>
X#include <sys/inode.h>
X#endif
X#ifdef BSD4_3
X#include <sys/time.h>
X#include <sys/vnode.h>
X#include <ufs/fs.h>
X#include <ufs/inode.h>
X#endif
X#include <sys/dir.h>
X#include <sys/errno.h>
X
X#include "defs.h"
X
X/*
X * itobo - Convert inode number to file system byte offset (for lseek).
X *
X * Converts inode to file system block (itod), then to device
X * block (fsbtodb), multiplies by size of device block (DEV_BSIZE
X * = 512), and adds offset into block of inode (itoo).
X */
X#define itobo(x) (fsbtodb(&sb, itod(&sb, x)) * DEV_BSIZE + \
X itoo(&sb,x) * sizeof(struct icommon))
X
X/*
X * btobo - Convert file system block number to byte offset (for lseek).
X */
X#define btobo(x) (fsbtodb(&sb, x) * DEV_BSIZE)
X
X#define ISIZE sizeof(struct icommon)
X
X
X/*
X * struct file_ptr is the structure returned from a uopen() call.
X */
Xstruct file_ptr {
X struct icommon *ip; /* Pointer to inode for file */
X long file_ptr; /* # bytes into file */
X long file_size; /* # bytes in file */
X};
X
X/*
X * struct iname_list is a linked list of paths returned by iname() call.
X */
Xstruct iname_list {
X char name[MAX_PATH_LEN];
X struct iname_list *next_iname;
X};
X
X/*
X * struct idir is a linked list of arrays of directory inode numbers.
X * inums[] is the array containing icnt inode numbers. next_idir
X * points to the next list of numbers
X */
Xstruct idir {
X ino_t inums[MAX_ICNT];
X int icnt;
X struct idir *next_idir;
X};
X
SHAR_EOF
chmod 0644 fs.h || echo "restore of fs.h fails"
sed 's/^X//' << 'SHAR_EOF' > idir.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X#include <sys/stat.h>
X
X /* File descriptor filesystem is open on */
Xextern int fs_fd;
X
X /* struct holding super block */
Xextern struct fs sb;
X
X /* size of file system block (= 4096) */
X#define BLKSIZE sb.fs_bsize
X
X/*
X * get_dir_inodes - stats inodes from from_inode to to_inode and, if
X * a directory, adds to return_list.
X */
Xget_dir_inodes(return_list, from_inode, to_inode)
Xstruct idir **return_list;
Xino_t from_inode, to_inode;
X{
X struct stat statb;
X struct idir *idir_list, *cur_ilist;
X
X ino_t i;
X
X new_idir(&idir_list);
X cur_ilist = idir_list;
X
X for (i = from_inode; i < to_inode; i++) {
X if (fs_stat (i, &statb)) {
X printf ("error reading inode %d\n");
X break;
X }
X if ((statb.st_mode & S_IFMT) == S_IFDIR) {
X /* Add inode number to list */
X add_dir_inode(&cur_ilist, i);
X printf ("found directory at %d\n", i);
X }
X }
X *return_list = idir_list;
X}
X
X/*
X * new_idir - makes new idir segment and returns pointer new_ptr
X */
Xnew_idir(new_ptr)
Xstruct idir **new_ptr;
X{
X char *malloc();
X
X *new_ptr = (struct idir *) malloc(sizeof(struct idir));
X (*new_ptr)->icnt = 0;
X (*new_ptr)->next_idir = NULL;
X}
X
X/*
X * add_dir_inode - adds inode number to struct idir, mallocing a new
X * one if needed.
X */
Xadd_dir_inode(idir_ptr, inum)
Xstruct idir **idir_ptr;
Xino_t inum;
X{
X if ((*idir_ptr)->icnt == MAX_ICNT) {
X /* Current list full, add new segment */
X new_idir(&((*idir_ptr)->next_idir));
X *idir_ptr = (*idir_ptr)->next_idir;
X }
X (*idir_ptr)->inums[(*idir_ptr)->icnt++] = inum;
X}
X
X/*
X * in_idir - returns TRUE if inum is found in idir_ptr
X */
Xin_idir(idir_ptr, inum)
Xstruct idir *idir_ptr;
Xino_t inum;
X{
X struct idir *itmp_ptr;
X
X ino_t itmp;
X
X itmp_ptr = idir_ptr;
X while (itmp_ptr) {
X for (itmp = 0; itmp < itmp_ptr->icnt; itmp++)
X if (itmp_ptr->inums[itmp] == inum)
X return TRUE;
X itmp_ptr = itmp_ptr->next_idir;
X }
X return FALSE;
X}
X
SHAR_EOF
chmod 0644 idir.c || echo "restore of idir.c fails"
sed 's/^X//' << 'SHAR_EOF' > iname.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X#include <sys/time.h>
X
X /* struct holding super block */
Xextern struct fs sb;
X
X /* File system block size */
X#define BLKSIZE sb.fs_bsize
X
X/*
X * iname - generate list of file names based on given inode number.
X * Given inode inum and maximum count icnt, returns linked list
X * inames of path names and actual number found found_cnt.
X * ipath is path name to inode istart, which is prepended to each
X * iname.
X *
X * Used for determining links to regular files.
X */
Xiname(ipath, istart, inum, icnt, inames, found_cnt)
Xchar ipath[MAX_PATH_LEN];
Xino_t istart, inum;
Xint icnt, *found_cnt;
Xstruct iname_list **inames;
X{
X *inames = NULL;
X *found_cnt = 0;
X if (ilist(ipath, istart, inum, icnt, inames, found_cnt))
X fprintf(stderr, "Inode %d is not a directory\n", inum);
X}
X
Xilist(ipath, istart, inum, icnt, inames, found_cnt)
Xchar ipath[MAX_PATH_LEN];
Xino_t istart, inum;
Xint icnt, *found_cnt;
Xstruct iname_list **inames;
X{
X struct icommon fs_inode; /* Inode for directory */
X struct direct *fs_dir; /* Directory structure */
X struct file_ptr dir_ptr; /* Directory pointer */
X
X char dir_buf[MAXBSIZE]; /* Directory buffer */
X int buf_cnt; /* # chars in buffer */
X int next_ent; /* Buf offset of next dir */
X
X char cur_name[MAX_PATH_LEN]; /* Current directory pathname */
X
X struct icommon file_inode; /* Inode for ls file */
X
X static struct iname_list *cur_iname, *tmp_iname;
X
X char *strcpy(), *sprintf(), *strcat();
X char *malloc();
X
X extern int errno;
X
X
X /* Fetch inode */
X get_inode(istart, &fs_inode);
X
X /* Make sure it's a directory! */
X if ((fs_inode.ic_mode & IFMT) != IFDIR) {
X errno = ENOTDIR;
X return -1;
X }
X /* Open directory */
X uopen(&fs_inode, &dir_ptr);
X
X /* Read each directory block */
X do {
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* For each file in directory, check inode # */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *) &dir_buf[next_ent];
X
X /* Directory entry here? */
X if (fs_dir->d_ino != 0) {
X /* Get inode */
X get_inode(fs_dir->d_ino, &file_inode);
X
X /* Desired inode #? */
X if (fs_dir->d_ino == inum) {
X /* Yep - Malloc new iname_list */
X tmp_iname = cur_iname;
X cur_iname = (struct iname_list *)
X malloc(sizeof(struct iname_list));
X cur_iname->next_iname = NULL;
X if (tmp_iname)
X tmp_iname->next_iname = cur_iname;
X if (*inames == NULL)
X *inames = cur_iname;
X
X /* Copy starting path */
X (void) strcpy(cur_iname->name, ipath);
X (void) strcat(cur_iname->name, "/");
X /* Append actual file name */
X (void) strcat(cur_iname->name, fs_dir->d_name);
X ++*found_cnt;
X }
X }
X next_ent += fs_dir->d_reclen;
X } while (next_ent < buf_cnt);
X
X } while (buf_cnt > 0);
X
X /* Open directory again */
X uopen(&fs_inode, &dir_ptr);
X
X /* Read each directory block */
X do {
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* For each subdirectory in directory, check it */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *) &dir_buf[next_ent];
X
X /* Directory entry here? */
X if (fs_dir->d_ino != 0) {
X /* Get inode */
X get_inode(fs_dir->d_ino, &file_inode);
X
X /* Make sure is dir and not . or .. */
X if ((file_inode.ic_mode & IFMT) == IFDIR)
X if (strcmp(fs_dir->d_name, ".") &&
X strcmp(fs_dir->d_name, "..")) {
X if (*ipath)
X (void) sprintf(cur_name, "%s/%s",
X ipath, fs_dir->d_name);
X else
X (void) strcpy(cur_name, fs_dir->d_name);
X
X /* Check this directory! */
X if (ilist(cur_name, fs_dir->d_ino, inum,
X icnt - *found_cnt, inames, found_cnt)) {
X fprintf(stderr,
X "Inode %d is not a directory\n", inum);
X return -1;
X }
X }
X }
X next_ent += fs_dir->d_reclen;
X } while (next_ent < buf_cnt);
X
X } while (buf_cnt > 0);
X return 0;
X}
SHAR_EOF
chmod 0644 iname.c || echo "restore of iname.c fails"
sed 's/^X//' << 'SHAR_EOF' > io.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X
X
X /* File descriptor filesystem is open on */
Xextern int fs_fd;
X
X /* struct holding super block */
Xextern struct fs sb;
X
X /* size of file system block */
X#define BLKSIZE sb.fs_bsize
X
X/*
X * getsb - read super block into struct sb
X */
Xgetsb(fs_to_read, sb_block)
Xchar *fs_to_read;
Xint sb_block;
X{
X long lseek();
X
X /* Open file system */
X if ((fs_fd = open(fs_to_read, O_RDONLY)) == -1) {
X perror("Cannot open filesystem");
X exit(1);
X }
X
X /* Seek to super block */
X/*
X (void) lseek(fs_fd, (long) BBSIZE, L_SET);
X*/
X (void) lseek(fs_fd, (long) 512 * sb_block, L_SET);
X
X /* Read super block */
X if (read(fs_fd, (char *) &sb, sizeof(sb)) == -1) {
X perror("Cannot read filesystem");
X exit(1);
X }
X
X /* Check magic number */
X if (sb.fs_magic != FS_MAGIC) {
X fprintf(stderr, "Bad magic number for super block\n");
X exit(1);
X }
X
X}
X
X/*
X * uopen - open file on unmounted file system.
X *
X * Input is a pointer to the icommon for the file to open,
X * and a pointer (struct file_ptr) to the info to be
X * returned. (Includes pointer to inode, index into file,
X * and size of file).
X */
Xuopen(ip, fp)
Xstruct icommon *ip;
Xstruct file_ptr *fp;
X{
X fp->ip = ip;
X fp->file_ptr = 0;
X fp->file_size = fp->ip->ic_size.val[0];
X}
X
X/*
X * uread - read data from uopened file.
X *
X * Input is pointer to struct file_ptr returned from uopen,
X * pointer to buffer to place data in, and count of number
X * of bytes to read.
X *
X * Note - Doesn't handle double-indirect blocks!
X * (Gawd, I'm lazy!)
X *
X * Returns:
X * -1 if no data was read,
X * count if all data was transferred,
X * else actual number of bytes transferred.
X */
Xuread(fp, bp, count)
Xstruct file_ptr *fp;
Xchar *bp;
Xlong count;
X{
X /* # indirect pointers in an indirect block */
X#define NUM_IND_PTRS (BLKSIZE / sizeof(long))
X /* # bytes pointed to by an indirect block */
X#define IND_CNT (NUM_IND_PTRS * BLKSIZE)
X
X long direct_blk; /* Index into direct block numbers */
X long ind_ptr; /* Which byte in indirect block */
X int ind_blk; /* Which indirect pointer of NIADDR */
X int ind_off; /* Which indirect pointer in block */
Xstatic char ind_buf[MAXBSIZE]; /* Indirect block */
Xstatic int last_ind_blk; /* Last indirect block read */
X
X int num_to_read; /* # bytes of block to read */
X int offset; /* Offset into block to start read */
X int nr; /* # bytes actually read */
X long file_cnt; /* # bytes left in file */
X long num_read; /* # bytes read so far */
X long block_to_read; /* Block # for read */
X
X char *bufptr; /* Next byte in buffer to read into */
X
X long lseek();
X
X bufptr = bp;
X num_read = 0;
X
X /* # bytes left in file */
X file_cnt = fp->file_size - fp->file_ptr;
X
X /* Limit count to size of file */
X if (count > file_cnt)
X count = file_cnt;
X
X while (count != 0) {
X
X /* Get direct block # */
X direct_blk = fp->file_ptr / BLKSIZE;
X
X /* Into indirect blocks? */
X if (direct_blk >= NDADDR) {
X ind_ptr = fp->file_ptr - NDADDR * BLKSIZE;
X
X /* Into double-indirect blocks? */
X if ((ind_blk = ind_ptr / IND_CNT) >= NIADDR) {
X fprintf(stderr, "File too large\n");
X exit(1);
X }
X
X ind_off = ind_ptr / BLKSIZE;
X
X if (last_ind_blk != fp->ip->ic_ib[ind_blk]) {
X /* Read indirect block */
X#ifdef DEBUG
X printf("Reading indirect block %d\n",
X last_ind_blk);
X#endif
X last_ind_blk = fp->ip->ic_ib[ind_blk];
X (void) lseek(fs_fd, btobo(last_ind_blk), L_SET);
X if (read(fs_fd, ind_buf, (int) BLKSIZE) == -1) {
X perror("Cannot read indirect block");
X exit(1);
X }
X }
X
X block_to_read = * ((long *) &ind_buf[ind_off *
X sizeof(long)]);
X } else
X block_to_read = fp->ip->ic_db[direct_blk];
X
X /* Offset into block to start read */
X offset = fp->file_ptr % BLKSIZE;
X
X /* # bytes in block to read */
X num_to_read = ((BLKSIZE - offset) < count) ?
X (BLKSIZE - offset) : count;
X
X /* Check for pointer to empty block */
X if (block_to_read == 0) {
X for (nr = 0; nr < num_to_read; nr++)
X bufptr[nr] = '\0';
X } else {
X
X#ifdef DEBUG
X printf("Reading block %d\n", block_to_read);
X#endif
X /* Seek to block */
X (void) lseek(fs_fd, btobo(block_to_read), L_SET);
X
X /* Read them */
X if ((nr = read(fs_fd, bufptr, num_to_read)) == -1)
X /* Return error if nothing read,
X * else # bytes actually read */
X return (num_read == 0) ? -1 : num_read;
X }
X
X count -= nr;
X file_cnt -= nr;
X fp->file_ptr += nr;
X num_read += nr;
X bufptr += nr; /* Point to next part of buffer */
X
X /* Read short */
X if (nr < num_to_read)
X return num_read;
X }
X return num_read;
X}
X
SHAR_EOF
chmod 0644 io.c || echo "restore of io.c fails"
sed 's/^X//' << 'SHAR_EOF' > ls.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X#include <sys/time.h>
X
X /* struct holding super block */
Xextern struct fs sb;
X
X /* File system block size */
X#define BLKSIZE sb.fs_bsize
X
X/*
X * ls - Do a directory listing of given inode. Do a 'ls -l'
X * if Lflag is set; do a 'ls -R' if Rflag is set.
X * dir_name is name of passed directory. idir_list is
X * updated with inode number of each listed directory.
X */
Xls(ls_inode, dir_name, idir_list, Lflag, Rflag)
Xino_t ls_inode;
Xchar *dir_name;
Xstruct idir **idir_list;
Xchar Lflag, Rflag;
X{
X struct icommon fs_inode; /* Inode for directory */
X struct direct *fs_dir; /* Directory structure */
X struct file_ptr dir_ptr; /* Directory pointer */
X
X struct icommon sym_inode; /* Inode for symbolic link */
X struct file_ptr sym_ptr; /* Symbolic link pointer */
X long sym_size; /* Length of symbolic name */
X char sym_buf[MAX_PATH_LEN]; /* Buffer for symbolic name */
X
X char dir_buf[MAXBSIZE]; /* Directory buffer */
X int buf_cnt; /* # chars in buffer */
X int next_ent; /* Offset into buf of next direct */
X
X int mode; /* File mode */
X char modes[11]; /* File mode string */
X struct icommon file_inode; /* Inode for ls file */
X int i;
X char *create_time; /* Creation date string */
X char cur_name[1024]; /* Current directory pathname */
X
X char *ctime();
X char *strcpy();
X char *sprintf();
X
X extern int errno;
X
X /* Fetch inode */
X get_inode(ls_inode, &fs_inode);
X
X /* Make sure it's a directory! */
X if ((fs_inode.ic_mode & IFMT) != IFDIR) {
X errno = ENOTDIR;
X return -1;
X }
X
X /* Add directory inode number to list */
X add_dir_inode(idir_list, ls_inode);
X
X /* Open directory */
X uopen(&fs_inode, &dir_ptr);
X
X if (Rflag && *dir_name)
X printf("%s:\n", dir_name);
X
X /* Read each directory block */
X do {
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* For each file in directory, list it */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *) &dir_buf[next_ent];
X
X /* Directory entry here? */
X if (fs_dir->d_ino != 0) {
X if (Lflag) {
X /* Get inode */
X get_inode(fs_dir->d_ino, &file_inode);
X
X printf("%5d ", fs_dir->d_ino); /* Inode # */
X (void) strcpy(modes, "-rwxrwxrwx");
X mode = file_inode.ic_mode;
X for (i = 8; i >= 0; i--)
X if ((mode & (1 << i)) == 0)
X modes[9 - i] = '-'; /* rwx bits */
X if ((mode & IFMT) == IFDIR)
X modes[0] = 'd'; /* directory */
X if ((mode & IFMT) == IFLNK)
X modes[0] = 'l'; /* sym link */
X
X if (mode & ISUID) modes[3] = 's'; /* setuid */
X if (mode & ISGID) modes[6] = 's'; /* setgid */
X if (mode & ISVTX) modes[9] = 't'; /* sticky */
X printf("%s %3d %3d/%-3d %8ld",
X modes, /* modes */
X file_inode.ic_nlink, /* link cnt */
X file_inode.ic_uid, /* uid */
X file_inode.ic_gid, /* gid */
X file_inode.ic_size.val[0]); /* size */
X create_time = ctime((long *) &file_inode.ic_ctime);
X printf(" %-12.12s %-4.4s ", create_time + 4,
X create_time + 20);
X printf("%s", fs_dir->d_name); /* file name */
X
X /* Symbolic link? */
X if ((mode & IFMT) == IFLNK) {
X /* Yup - print name of link */
X get_inode(fs_dir->d_ino, &sym_inode);
X sym_size = sym_inode.ic_size.val[0];
X if (sym_size >= sizeof(sym_buf))
X printf(" -> ?name too big");
X else {
X uopen(&sym_inode, &sym_ptr);
X if (uread(&sym_ptr, sym_buf, sym_size)
X != sym_size) {
X perror("Cannot read symlink");
X exit(1);
X }
X sym_buf[sym_size] = '\0';
X printf(" -> %s", sym_buf);
X }
X }
X printf("\n");
X
X } else
X printf("%s\n", fs_dir->d_name); /* file name */
X }
X next_ent += fs_dir->d_reclen;
X } while (next_ent < buf_cnt);
X
X } while (buf_cnt > 0);
X
X printf("\n");
X
X /* Recursive (ls -R)? */
X if (Rflag) {
X /* Open directory again */
X uopen(&fs_inode, &dir_ptr);
X
X /* Read each directory block */
X do {
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* For each directory in directory, list it */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *) &dir_buf[next_ent];
X
X /* Directory entry here? */
X if (fs_dir->d_ino != 0) {
X /* Get inode */
X get_inode(fs_dir->d_ino, &file_inode);
X
X /* Make sure is dir and not . or .. */
X if ((file_inode.ic_mode & IFMT) == IFDIR)
X if (strcmp(fs_dir->d_name, ".") &&
X strcmp(fs_dir->d_name, ".."))
X
X /* Make sure not already listed */
X if (in_idir(*idir_list, fs_dir->d_ino))
X fprintf(stderr, "Already ls'd inum %d, directory: %s !\n", fs_dir->d_ino, cur_name);
X else {
X if (*dir_name)
X (void) sprintf(cur_name, "%s/%s",
X dir_name, fs_dir->d_name);
X else
X (void) strcpy(cur_name, fs_dir->d_name);
X
X /* List this directory! */
X if (ls(fs_dir->d_ino, cur_name, idir_list,
X Lflag, Rflag))
X return -1;
X }
X }
X next_ent += fs_dir->d_reclen;
X } while (next_ent < buf_cnt);
X
X } while (buf_cnt > 0);
X }
X return 0;
X}
X
X
Xls_all(Rflag, verbose)
Xchar Rflag, verbose;
X{
X struct idir *idir_list, *ls_list, *idir_ptr, *ls_ptr;
X
X ino_t inum;
X int icnt = 0;
X char iname[MAX_PATH_LEN];
X
X /* Get list of directory inodes for filesystem */
X get_dir_inodes(&idir_list, (ino_t) 2, (ino_t) sb.fs_ncg * sb.fs_ipg);
X
X /* Make list of ls'd directory inodes */
X new_idir(&ls_list);
X idir_ptr = idir_list;
X while (idir_ptr) {
X inum = idir_ptr->inums[icnt];
X /* Inode been ls'd? */
X if (!in_idir(ls_list, inum)) {
X
X /* Point to end of ls'd inode list */
X ls_ptr = ls_list;
X while(ls_ptr->next_idir)
X ls_ptr = ls_ptr->next_idir;
X
X /* Append to end of ls'd inode list */
X if (ls(inum, iname, &ls_ptr, Rflag, verbose))
X return -1;
X }
X if (++icnt == idir_ptr->icnt) {
X icnt = 0;
X idir_ptr = idir_ptr->next_idir;
X }
X }
X return 0;
X}
SHAR_EOF
chmod 0644 ls.c || echo "restore of ls.c fails"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X#include <sys/stat.h>
X
X /* File descriptor filesystem is open on */
Xint fs_fd;
X
X /* struct holding super block */
Xstruct fs sb;
X
X /* Current root inode */
Xino_t root_inode = ROOTINO;
X
Xchar *fs_to_read = FS_TO_READ;
Xint sb_block = BBSIZE / 512;
X
Xusage(fs_name)
Xchar *fs_name;
X{
X fprintf (stderr,
X"usage: %s [-f device] [-s super-block] [-r root-inode] [-a] [-l] [-R] [-v]\n",
X fs_name);
X exit(1);
X}
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X char do_all, verbose, recurse, long_ls = FALSE;
X char *fs_name = argv[0];
X struct stat statb;
X struct idir *idir_list;
X
X for (fs_name = argv[0] + strlen(argv[0]);
X (fs_name != argv[0]) && (*(fs_name - 1) != '/'); fs_name--) ;
X
X while (*++argv) {
X if (**argv == '-') {
X switch (*++*argv) {
X case 'f':
X fs_to_read = *++argv;
X break;
X case 's':
X sb_block = atoi (*++argv);
X break;
X case 'r':
X root_inode = atoi (*++argv);
X break;
X case 'a':
X do_all = TRUE;
X break;
X case 'v':
X verbose = TRUE;
X break;
X case 'R':
X recurse = TRUE;
X break;
X case 'l':
X long_ls = TRUE;
X break;
X
X default:
X usage(fs_name);
X }
X }
X }
X
X /* Stat file and see if it's a block special device */
X if (stat(fs_to_read, &statb)) {
X perror("Cannot stat file");
X exit(1);
X } else
X if ((statb.st_mode & S_IFMT) != S_IFBLK) {
X fprintf(stderr, "%s not a block special device\n",
X fs_to_read);
X exit(1);
X }
X
X /* Read in superblock */
X getsb(fs_to_read, sb_block);
X
X new_idir(&idir_list);
X
X if (!strcmp(fs_name, "fssal"))
X if (do_all)
X exit( restore_all(recurse, verbose) );
X else
X exit( restore(".", root_inode, ".",
X &idir_list, recurse, verbose) );
X
X if (!strcmp(fs_name, "fsls"))
X if (do_all)
X exit( ls_all(long_ls, recurse) );
X else
X exit( ls(root_inode, "", &idir_list, long_ls, recurse));
X
X usage(fs_name);
X
X (void) close(fs_fd);
X exit(0);
X}
SHAR_EOF
chmod 0644 main.c || echo "restore of main.c fails"
sed 's/^X//' << 'SHAR_EOF' > namei.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X
X
X /* File descriptor filesystem is open on */
Xextern int fs_fd;
X
X /* struct holding super block */
Xextern struct fs sb;
X
X /* File system block size */
X#define BLKSIZE sb.fs_bsize
X
X/*
X * get_inode - read inode inum into struct rd_inode
X */
Xget_inode(inum, rd_inode)
Xino_t inum;
Xstruct icommon *rd_inode;
X{
X long lseek();
X
X /* Seek to desired inode */
X (void) lseek(fs_fd, (long) itobo(inum), L_SET);
X
X /* Read that inode */
X if (read(fs_fd, (char *) rd_inode, ISIZE) == -1) {
X perror("Cannot read file system");
X exit(1);
X }
X}
X
X/*
X * namei - Convert filename to inode number.
X *
X * First get root inode for file system.
X * From there, search each directory in path for next
X * component of path name, till final filename found.
X *
X * Returns:
X * 0 if file not found (ENOENT),
X * 0 if file in path was not a directory (ENOTDIR),
X * else inode of file filename.
X */
Xnamei(filename)
Xchar *filename;
X{
X char tmp_name[1024]; /* Copy of filename */
X ino_t cur_ino; /* Current inode in path */
X char *curnam; /* Points to next char in filename */
X char *next_name; /* Next name to scan */
X int next_slash;
X
X struct icommon fs_inode; /* Inode for file/directory */
X struct direct *fs_dir; /* Directory structure */
X struct file_ptr dir_ptr; /* Directory pointer */
X
X char dir_buf[MAXBSIZE]; /* Directory buffer */
X int buf_cnt; /* # chars in buffer */
X
X int next_ent; /* Offset into buf of next direct */
X
X char *strcpy();
X
X extern int errno;
X
X /* Save copy of path name */
X (void) strcpy(tmp_name, filename);
X curnam = tmp_name;
X
X /* Start at root inode */
X cur_ino = ROOTINO;
X
X /* Search till nothing left of path name */
X while ((*curnam != '\0') && (cur_ino != 0)) {
X
X#ifdef DEBUG
X printf("Reading inode %d\n", cur_ino);
X#endif
X /* Get current inode */
X get_inode(cur_ino, &fs_inode);
X
X /* Make sure it's a directory! */
X if ((fs_inode.ic_mode & IFMT) != IFDIR) {
X errno = ENOTDIR;
X return 0;
X }
X
X /* Skip /'s in next component of name */
X while (*curnam == '/') curnam++;
X
X /* Get next component of path in next_name */
X for (next_slash = 0;
X (curnam[next_slash] != '\0') && (curnam[next_slash] != '/');
X next_slash ++) ;
X
X next_name = curnam;
X curnam += next_slash;
X if (*curnam == '/') curnam++;
X next_name[next_slash] = '\0';
X
X#ifdef DEBUG
X printf("Scanning directory for file '%s'.\n", next_name);
X#endif
X
X /* Open directory */
X uopen(&fs_inode, &dir_ptr);
X
X /*
X * Search each directory block for name.
X * Return inode number in cur_ino when found.
X */
X cur_ino = 0;
X do {
X
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE))
X == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* Scan directory block for desired name */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *)
X &dir_buf[next_ent];
X
X /* Directory entry here? */
X if (fs_dir->d_ino != 0) {
X#ifdef DEBUG
X printf("Inode: %6d file: %s\n",
X fs_dir->d_ino, fs_dir->d_name);
X#endif
X
X /* Names match? */
X if (!strcmp(next_name, fs_dir->d_name))
X /* Yes- save inode */
X cur_ino = fs_dir->d_ino;
X }
X next_ent += fs_dir->d_reclen;
X } while ((cur_ino == 0) &&
X (next_ent < buf_cnt));
X
X } while ((cur_ino == 0) && (buf_cnt > 0));
X }
X
X if (cur_ino == 0) {
X errno = ENOENT;
X return 0; /* File not found - return 0 */
X } else
X return cur_ino; /* Found - return inode number */
X}
X
SHAR_EOF
chmod 0644 namei.c || echo "restore of namei.c fails"
sed 's/^X//' << 'SHAR_EOF' > restore.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X#include "fs.h"
X#include <sys/stat.h>
X#include <sys/time.h>
X
X /* struct holding super block */
Xextern struct fs sb;
X
X /* Current root inode */
Xextern ino_t root_inode;
X
X /* File system block size */
X#define BLKSIZE sb.fs_bsize
X
Xchar *base_path; /* Initial restore path */
Xino_t base_inode; /* Initial restore inode # */
X
X/*
X * restore - Restore files from given directory.
X * from_path is path name to from_inode, which is
X * directory to be restored. Files are restored to
X * to_path. If Rflag is set, restore is recursive
X * ( cp -R ). idir_list is updated with inode number of
X * each directory restored.
X */
Xrestore(from_path, from_inode, to_path, idir_list, Rflag, verbose)
Xino_t from_inode;
Xchar *from_path, *to_path;
Xstruct idir **idir_list;
Xchar Rflag, verbose;
X{
X /* Save initial restore path and inode # */
X base_path = to_path;
X base_inode = from_inode;
X return
X rrestore(from_path, from_inode, to_path, idir_list, Rflag, verbose);
X}
X
Xrrestore(from_path, from_inode, to_path, idir_list, Rflag, verbose)
Xino_t from_inode;
Xchar *from_path, *to_path;
Xstruct idir **idir_list;
Xchar Rflag, verbose;
X{
X struct icommon fs_inode; /* Inode for directory */
X struct direct *fs_dir; /* Directory structure */
X struct file_ptr dir_ptr; /* Directory pointer */
X
X struct icommon sym_inode; /* Inode for symbolic link */
X struct file_ptr sym_ptr; /* Symbolic link pointer */
X long sym_size; /* Length of symbolic name */
X char sym_buf[MAX_PATH_LEN]; /* Buffer for symbolic name */
X
X char dir_buf[MAXBSIZE]; /* Directory buffer */
X int buf_cnt; /* # chars in buffer */
X int next_ent; /* Offset into buf of next direct */
X
X int mode; /* File mode */
X struct icommon file_inode; /* Inode for ls file */
X char in_path[MAX_PATH_LEN]; /* Current input file name */
X char out_path[MAX_PATH_LEN]; /* Current output file name */
X
X char set_times; /* TRUE to set creation time */
X struct timeval file_times[2];
X
X struct iname_list *link_list; /* List of files with common inode */
X struct iname_list *temp_link;
X int links_found;
X struct stat file_stat; /* File status (for inode # to link) */
X int out_file; /* Output file descriptor */
X
X char copy_file; /* TRUE to copy (not link) file */
X struct file_ptr in_ptr; /* File pointer for input file */
X int nr;
X char buf[8192];
X
X char *ctime();
X char *strcpy(), *strcat();
X
X extern int errno;
X
X (void) umask(0); /* Create any mode file */
X
X /* Fetch inode */
X get_inode(from_inode, &fs_inode);
X
X /* Make sure it's a directory! */
X if ((fs_inode.ic_mode & IFMT) != IFDIR) {
X errno = ENOTDIR;
X return -1;
X }
X
X /* Add directory inode number to list */
X add_dir_inode(idir_list, from_inode);
X
X /* Open directory */
X uopen(&fs_inode, &dir_ptr);
X
X /* Read each directory block */
X do {
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* For each file in directory, restore it */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *) &dir_buf[next_ent];
X
X /* Directory entry here? */
X if ((fs_dir->d_ino != 0) && strcmp(fs_dir->d_name, ".")
X && strcmp(fs_dir->d_name, "..")) {
X /* Get inode */
X get_inode(fs_dir->d_ino, &file_inode);
X
X (void) strcpy(in_path, from_path);
X (void) strcat(in_path, "/");
X (void) strcat(in_path, fs_dir->d_name);
X (void) strcpy(out_path, to_path);
X (void) strcat(out_path, "/");
X (void) strcat(out_path, fs_dir->d_name);
X
X /* Set up access and mod times */
X set_times = TRUE;
X file_times[0].tv_sec = file_inode.ic_atime;
X file_times[0].tv_usec = file_times[1].tv_usec = 0;
X file_times[1].tv_sec = file_inode.ic_mtime;
X
X mode = file_inode.ic_mode;
X
X switch (mode & IFMT) {
X
X case 0020000: /* character special */
X case 0060000: /* block special */
X case 0140000: /* socket - will it work? */
X if (verbose)
X printf("Creating special file: %s\n",
X out_path);
X if (mknod(out_path, mode,
X (int) file_inode.ic_db[0]))
X {
X fprintf(stderr,
X "Cannot create special file: %s; ",
X out_path);
X perror("");
X set_times = FALSE;
X }
X break;
X
X case 0040000: /* directory */
X if (verbose)
X printf("Creating directory: %s\n",
X out_path);
X if (mkdir(out_path, mode)) {
X fprintf(stderr,
X "Cannot create directory: %s; ",
X out_path);
X perror("");
X set_times = FALSE;
X }
X break;
X
X case 0100000: /* regular file */
X copy_file = (file_inode.ic_nlink == 1);
X if (!copy_file) {
X /* Oh shit; it's a link */
X /* Get filenames with inode # */
X iname(base_path, base_inode,
X fs_dir->d_ino, file_inode.ic_nlink,
X &link_list, &links_found);
X
X /* Search for existing file */
X /* to link to */
X for (temp_link = link_list;
X temp_link;
X temp_link = temp_link->next_iname)
X {
X if (stat(temp_link->name,
X &file_stat)) {
X if (errno != ENOENT) {
X fprintf(stderr,
X "Cannot stat %s: ",
X temp_link->name);
X perror("");
X }
X } else
X if (mode != file_stat.st_mode) {
X fprintf(stderr,
X "Mode mismatch on %s\n",
X temp_link->name);
X } else
X break;
X }
X
X if (temp_link) {
X /* Found file to link to */
X if (verbose)
X printf("Linking %s to %s\n",
X temp_link->name, out_path);
X if (link(temp_link->name, out_path))
X {
X fprintf(stderr,
X "Cannot link %s to %s: ",
X temp_link->name, out_path);
X perror("");
X copy_file = TRUE;
X } else
X set_times = FALSE;
X } else
X copy_file = TRUE;
X }
X
X if (copy_file) {
X /* Copy file */
X if (verbose)
X printf("Copying %s to %s\n",
X in_path, out_path);
X uopen(&file_inode, &in_ptr);
X if ((out_file = open(out_path,
X O_CREAT | O_WRONLY,
X mode)) == -1) {
X fprintf(stderr,
X "Cannot create %s: ",
X out_path);
X perror("");
X break;
X }
X
X /* Copy file */
X do {
X if ((nr = uread(&in_ptr, buf,
X BLKSIZE)) == -1) {
X fprintf(stderr,
X "Cannot read %s: ",
X in_path);
X perror("");
X }
X
X if (nr > 0)
X if (write(out_file, buf, nr)
X == -1) {
X fprintf(stderr,
X "Cannot write %s: ",
X out_path);
X perror("");
X }
X } while (nr > 0);
X
X (void) close(out_file);
X }
X break;
X
X case 0120000: /* symbolic link */
X /* Can't utime symlink */
X set_times = FALSE;
X /* Get name of link */
X get_inode(fs_dir->d_ino, &sym_inode);
X sym_size = sym_inode.ic_size.val[0];
X if (sym_size >= sizeof(sym_buf)) {
X fprintf(stderr,
X "Symbolic link to %s too long\n",
X out_path);
X set_times = FALSE;
X } else {
X uopen(&sym_inode, &sym_ptr);
X if (uread(&sym_ptr, sym_buf, sym_size)
X != sym_size) {
X perror("Cannot read symlink");
X set_times = FALSE;
X }
X sym_buf[sym_size] = '\0';
X
X if (verbose)
X printf("Creating symbolic link %s -> %s\n",
X sym_buf, out_path);
X if (symlink(sym_buf, out_path)) {
X fprintf(stderr,
X "Cannot create symbolic link %s -> %s: ",
X out_path, sym_buf);
X perror("");
X#ifdef UTEK
X if (errno != EDFSNOSUCHHOST)
X set_times = FALSE;
X#endif
X }
X }
X break;
X
X default:
X fprintf(stderr, "Unknown mode %o on file %s\n",
X mode, in_path);
X set_times = FALSE;
X }
X
X if (set_times) {
X /* Set creation times on file */
X if (utimes(out_path, file_times)) {
X fprintf(stderr,
X "Cannot set creation times on %s: ",
X out_path);
X perror("");
X }
X /* Set owner and group */
X if (chown(out_path, file_inode.ic_uid,
X file_inode.ic_gid)) {
X fprintf(stderr,
X "Cannot set owner on %s: ",
X out_path);
X perror("");
X }
X }
X
X }
X next_ent += fs_dir->d_reclen;
X } while (next_ent < buf_cnt);
X
X } while (buf_cnt > 0);
X
X /* Recursive (cp -R)? */
X if (Rflag) {
X /* Open directory again */
X uopen(&fs_inode, &dir_ptr);
X
X /* Read each directory block */
X do {
X /* Read next block of directory */
X if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
X perror("Cannot read directory");
X exit(1);
X }
X
X if (buf_cnt == 0)
X break;
X
X /* For each sub-directory in directory, restore it */
X next_ent = 0;
X do {
X /* Point to next directory entry */
X fs_dir = (struct direct *) &dir_buf[next_ent];
X
X /* Directory entry here? */
X if (fs_dir->d_ino != 0) {
X /* Get inode */
X get_inode(fs_dir->d_ino, &file_inode);
X
X
X /* Make sure is dir and not . or .. */
X if ((file_inode.ic_mode & IFMT) == IFDIR)
X if (strcmp(fs_dir->d_name, ".") &&
X strcmp(fs_dir->d_name, "..")) {
X
X /* Make sure not restored yet */
X if (in_idir(*idir_list, fs_dir->d_ino)) {
X fprintf(stderr,
X "Already restored inum %d, directory: %s !\n",
X fs_dir->d_ino, from_path);
X } else {
X (void) strcpy(in_path, from_path);
X (void) strcat(in_path, "/");
X (void) strcat(in_path, fs_dir->d_name);
X (void) strcpy(out_path, to_path);
X (void) strcat(out_path, "/");
X (void) strcat(out_path, fs_dir->d_name);
X
X file_times[0].tv_sec = file_inode.ic_atime;
X file_times[0].tv_usec = file_times[1].tv_usec
X = 0;
X file_times[1].tv_sec = file_inode.ic_mtime;
X
X /* Restore this directory! */
X if (rrestore(in_path, fs_dir->d_ino, out_path,
X idir_list, Rflag, verbose))
X return -1;
X
X /* Set creation times on directory */
X if (utimes(out_path, file_times)) {
X fprintf(stderr,
X "Cannot set creation times on %s: ",
X out_path);
X perror("");
X }
X }
X }
X }
X next_ent += fs_dir->d_reclen;
X } while (next_ent < buf_cnt);
X
X } while (buf_cnt > 0);
X }
X return 0;
X}
X
Xrestore_all(Rflag, verbose)
Xchar Rflag, verbose;
X{
X struct idir *idir_list, *restore_list, *idir_ptr, *restore_ptr;
X
X ino_t inum;
X int icnt = 0;
X char iname[MAX_PATH_LEN];
X
X char *sprintf();
X
X /* Get list of directory inodes for filesystem */
X get_dir_inodes(&idir_list, (ino_t) 2, (ino_t) sb.fs_ncg * sb.fs_ipg);
X
X /* Make list of restored directory inodes */
X new_idir(&restore_list);
X idir_ptr = idir_list;
X while (idir_ptr) {
X inum = idir_ptr->inums[icnt];
X /* Inode been restored? */
X if (!in_idir(restore_list, inum)) {
X
X /* Nope - create directory and restore */
X (void) sprintf(iname, "i%d", inum);
X
X if (verbose)
X printf("Creating new base directory: %s\n",
X iname);
X if (mkdir(iname, 0775)) {
X fprintf(stderr,
X "Cannot create directory: %s; ",
X iname);
X perror("");
X }
X
X /* Point to end of restored inode list */
X restore_ptr = restore_list;
X while(restore_ptr->next_idir)
X restore_ptr = restore_ptr->next_idir;
X
X /* Append to end of restored inode list */
X if (restore(iname, inum, iname, &restore_ptr,
X Rflag, verbose))
X return -1;
X }
X if (++icnt == idir_ptr->icnt) {
X icnt = 0;
X idir_ptr = idir_ptr->next_idir;
X }
X }
X return 0;
X}
SHAR_EOF
chmod 0644 restore.c || echo "restore of restore.c fails"
sed 's/^X//' << 'SHAR_EOF' > stat.c &&
X
X/*
X * fssal - BSD file system salvage program
X *
X * Copyright 1989, Robert Ankeney
X * Generic Computer Products
X * 5315 S.W. 53rd Court
X * Portland, Oregon 97221
X * (503) 244-3699
X * All Rights Reserved
X *
X * Distribution of any portion of this software as part of any product
X * for sale is prohibited.
X *
X * Version 1.00 (Preliminary)
X */
X
X/*
X * stat.c
X *
X * load an inode into memory
X */
X
X# include "fs.h"
X# include <sys/stat.h>
X
Xextern struct fs sb;
Xextern int fs_fd;
X
Xfs_stat (inum, statb)
Xino_t inum;
Xstruct stat *statb;
X{
X long off;
X struct dinode di;
X
X long lseek();
X
X off = itobo (inum);
X (void) lseek (fs_fd, off, L_SET);
X if (read (fs_fd, (char *) &di, sizeof (di)) != sizeof (di))
X return -1;
X statb->st_dev = 0;
X statb->st_ino = inum;
X statb->st_mode = di.di_mode;
X statb->st_nlink = di.di_nlink;
X statb->st_uid = di.di_uid;
X statb->st_gid = di.di_gid;
X statb->st_atime = di.di_atime;
X statb->st_mtime = di.di_mtime;
X statb->st_ctime = di.di_ctime;
X statb->st_blocks = di.di_blocks;
X return 0;
X}
SHAR_EOF
chmod 0644 stat.c || echo "restore of stat.c fails"
exit 0
More information about the Alt.sources
mailing list