home *** CD-ROM | disk | FTP | other *** search
- From: bob@reed.UUCP (Bob Ankeney)
- Newsgroups: alt.sources
- Subject: fssal - BSD filesystem salvage program, Part 01/01
- Message-ID: <16309@reed.UUCP>
- Date: 9 Apr 91 20:44:15 GMT
-
-
- #!/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@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
-