home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3184 < prev    next >
Encoding:
Internet Message Format  |  1991-04-12  |  46.0 KB

  1. From: bob@reed.UUCP (Bob Ankeney)
  2. Newsgroups: alt.sources
  3. Subject: fssal - BSD filesystem salvage program, Part 01/01
  4. Message-ID: <16309@reed.UUCP>
  5. Date: 9 Apr 91 20:44:15 GMT
  6.  
  7.  
  8. #!/bin/sh
  9. # shar:    Shell Archiver  (v1.22)
  10. #
  11. #    Run the following text with /bin/sh to create:
  12. #      README
  13. #      FILES
  14. #      NOTES
  15. #      Makefile
  16. #      defs.h
  17. #      fs.h
  18. #      idir.c
  19. #      iname.c
  20. #      io.c
  21. #      ls.c
  22. #      main.c
  23. #      namei.c
  24. #      restore.c
  25. #      stat.c
  26. #
  27. sed 's/^X//' << 'SHAR_EOF' > README &&
  28. X     Fssal is a utility to salvage files from damaged BSD filesystems.
  29. XSuch damage might include a lost super-block, trashed cylinder group,
  30. Xdrive with bad blocks, or perhaps a filesystem with files that may get
  31. Xconsumed by a fsck.  It requires the presence of a relatively intact
  32. Xfilesystem (an intact original or alternate super-block, some semblence
  33. Xof an inode-structure, and some intact cylinder-groups).  Thus such
  34. Xthings as deleted files cannot be restored.
  35. X
  36. X     The impetus for writing this program was to recover files from a
  37. Xfilesystem with the original super-block and first (of six) cylinder
  38. Xgroups walked on.  What happened was a mkfs of a small system was
  39. Xaccidentally done, which wiped the initial data.  Data from all other
  40. Xcylinder groups was still intact and recoverable.  An alternate (spare)
  41. Xsuper-block is found within each cylinder group.
  42. X
  43. X     All restored files are placed relative to the working directory,
  44. Xand all permissions, creation/modification times, and ownerships are
  45. Xrestored.  Both real and symbolic links are handled, as well as
  46. Xcharacter and block special devices and sockets.
  47. X
  48. X     At no time is the specified file-system written on, thus data is
  49. Xsafe.  The specified file-system need not be mounted (and probably
  50. Xshouldn't be lest others modify it as a restore is in progress).
  51. X
  52. X     The general usage is:
  53. X
  54. X        fssal [-f device] [-s super-block] [-r root-inode] [-a] [-R] [-v]
  55. X
  56. X     where:
  57. X    -f device: is the file-system to use (do not use the raw device!!)
  58. X    -s super-block: is an alternate super-block
  59. X    -r root-inode: is an alternate directory inode to start at
  60. X
  61. X    -a: stats all inodes in file-system and restores those that are
  62. X        directories.  The -R flag can be used to recursively walk each
  63. X        sub-directory.  Each directory found that has not yet been
  64. X        restored will be created with the directory name '#inum', where
  65. X        inum is the inode number of that directory.
  66. X
  67. X    -R: recursively walk each sub-directory found.
  68. X
  69. X    -v: verbose mode.  Spews out lots of information as to what's been
  70. X        restored.
  71. X
  72. X     A link to fssal called fsls exists which does a directory listing on
  73. Xthe specified file system.  The general usage is:
  74. X
  75. X        fsls [-f device] [-s super-block] [-r root-inode] [-a] [-R] [-l]
  76. X
  77. X     where:
  78. X    -f device: is the file-system to use (do not use the raw device!!)
  79. X    -s super-block: is an alternate super-block
  80. X    -r root-inode: is an alternate directory inode to start at
  81. X
  82. X    -a: stats all inodes in file-system and lists those that are
  83. X        directories.  The -R flag can be used to recursively walk each
  84. X        sub-directory.
  85. X
  86. X    -R: recursively walk each sub-directory found.
  87. X
  88. X    -l: do a long directory list (like 'ls -liga')
  89. X
  90. X
  91. X     Hopefully someone will take this under their wing and make improvements
  92. Xto it.  Some suggestions are:
  93. X     a) Make it interactive (ala restore -i).
  94. X     b) Port it to other platforms; it has been used successfully on:
  95. X        DEC VAX with Mt. Xinu
  96. X        DEC VAX with Ultrix V2.3
  97. X        Sun-4 with SunOs V4.1
  98. X        Tektronix Utek V2.2
  99. X     c) A manual page.
  100. X
  101. X
  102. X     Feel free to mail me any suggestions, bug fixes and enhancements.  I'll
  103. Xtry to integrate them (it's been a while since I wrote this) and make occasional
  104. Xreleases.  If it looks solid enough, I'll post to comp.sources.unix.
  105. X
  106. X     Bob Ankeney
  107. X     ...!tektronix!bob@reed.bitnet
  108. X
  109. SHAR_EOF
  110. chmod 0644 README || echo "restore of README fails"
  111. sed 's/^X//' << 'SHAR_EOF' > FILES &&
  112. XREADME
  113. XFILES
  114. XNOTES
  115. XMakefile
  116. Xdefs.h
  117. Xfs.h
  118. Xidir.c
  119. Xiname.c
  120. Xio.c
  121. Xls.c
  122. Xmain.c
  123. Xnamei.c
  124. Xrestore.c
  125. Xstat.c
  126. SHAR_EOF
  127. chmod 0644 FILES || echo "restore of FILES fails"
  128. sed 's/^X//' << 'SHAR_EOF' > NOTES &&
  129. XThings to check for:
  130. X
  131. X     Error handling (failed reads especially).
  132. X
  133. X     Freeing of malloced space.
  134. X
  135. XTo do:
  136. X
  137. X     Read inode into buffer and get inode structures from it (fixes reads on
  138. X     raw device).
  139. X
  140. X     Cache ureads?  (uread reads entire block and bcopies desired info).
  141. X     Keep track of last block read to avoid duplicate reads.
  142. X
  143. SHAR_EOF
  144. chmod 0644 NOTES || echo "restore of NOTES fails"
  145. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  146. X#CFLAGS = -g -DDEBUG
  147. XCFLAGS = -g -DBSD4_3
  148. X
  149. XSRCS = io.c namei.c iname.c ls.c restore.c main.c stat.c idir.c
  150. XOBJS = io.o namei.o iname.o ls.o restore.o main.o stat.o idir.o
  151. X
  152. Xall:    fssal fsls
  153. X
  154. Xfssal:    $(OBJS)
  155. X    rm -f fsls
  156. X    cc $(CFLAGS) $(OBJS) -o fssal
  157. X
  158. Xfsls:    fssal
  159. X    ln fssal fsls
  160. X
  161. Xio.o: defs.h fs.h
  162. X
  163. Xnamei.o: defs.h fs.h
  164. X
  165. Xiname.o: defs.h fs.h
  166. X
  167. Xls.o: defs.h fs.h
  168. X
  169. Xrestore.o: defs.h fs.h
  170. X
  171. Xmain.o: defs.h fs.h
  172. X
  173. Xstat.o: defs.h fs.h
  174. X
  175. Xidir.o: defs.h fs.h
  176. X
  177. Xclean:
  178. X    rm -f $(OBJS)
  179. X
  180. Xlint:
  181. X    lint $(SRCS)
  182. X
  183. SHAR_EOF
  184. chmod 0644 Makefile || echo "restore of Makefile fails"
  185. sed 's/^X//' << 'SHAR_EOF' > defs.h &&
  186. X
  187. X#define FS_TO_READ    "/dev/dh60h"
  188. X
  189. X    /* Maximum size for path name */
  190. X#define MAX_PATH_LEN    128
  191. X
  192. X    /* Number of inode numbers per sturct idir segment */
  193. X#define MAX_ICNT    32
  194. X
  195. X#ifndef TRUE
  196. X#define    TRUE    (1)
  197. X#define FALSE    (0)
  198. X#endif
  199. X
  200. SHAR_EOF
  201. chmod 0644 defs.h || echo "restore of defs.h fails"
  202. sed 's/^X//' << 'SHAR_EOF' > fs.h &&
  203. X
  204. X#include <stdio.h>
  205. X#include <sys/types.h>
  206. X#include <sys/file.h>
  207. X#include <sys/param.h>
  208. X#ifdef BSD4_2
  209. X#include <sys/fs.h>
  210. X#include <sys/inode.h>
  211. X#endif
  212. X#ifdef BSD4_3
  213. X#include <sys/time.h>
  214. X#include <sys/vnode.h>
  215. X#include <ufs/fs.h>
  216. X#include <ufs/inode.h>
  217. X#endif
  218. X#include <sys/dir.h>
  219. X#include <sys/errno.h>
  220. X
  221. X#include "defs.h"
  222. X
  223. X/*
  224. X *    itobo -    Convert inode number to file system byte offset (for lseek).
  225. X *
  226. X *        Converts inode to file system block (itod), then to device
  227. X *        block (fsbtodb), multiplies by size of device block (DEV_BSIZE
  228. X *        = 512), and adds offset into block of inode (itoo).
  229. X */
  230. X#define itobo(x) (fsbtodb(&sb, itod(&sb, x)) * DEV_BSIZE +    \
  231. X          itoo(&sb,x) * sizeof(struct icommon))
  232. X
  233. X/*
  234. X *    btobo - Convert file system block number to byte offset (for lseek).
  235. X */
  236. X#define btobo(x) (fsbtodb(&sb, x) * DEV_BSIZE)
  237. X
  238. X#define ISIZE    sizeof(struct icommon)
  239. X
  240. X
  241. X/*
  242. X *    struct file_ptr is the structure returned from a uopen() call.
  243. X */
  244. Xstruct file_ptr {
  245. X    struct icommon    *ip;        /* Pointer to inode for file */
  246. X    long        file_ptr;    /* # bytes into file */
  247. X    long        file_size;    /* # bytes in file */
  248. X};
  249. X
  250. X/*
  251. X *    struct iname_list is a linked list of paths returned by iname() call.
  252. X */
  253. Xstruct iname_list {
  254. X    char    name[MAX_PATH_LEN];
  255. X    struct    iname_list *next_iname;
  256. X};
  257. X
  258. X/*
  259. X *    struct idir is a linked list of arrays of directory inode numbers.
  260. X *    inums[] is the array containing icnt inode numbers.  next_idir
  261. X *    points to the next list of numbers
  262. X */
  263. Xstruct idir {
  264. X    ino_t    inums[MAX_ICNT];
  265. X    int    icnt;
  266. X    struct    idir *next_idir;
  267. X};
  268. X
  269. SHAR_EOF
  270. chmod 0644 fs.h || echo "restore of fs.h fails"
  271. sed 's/^X//' << 'SHAR_EOF' > idir.c &&
  272. X
  273. X/*
  274. X *     fssal - BSD file system salvage program
  275. X *
  276. X *     Copyright 1989, Robert Ankeney
  277. X *                     Generic Computer Products
  278. X *                     5315 S.W. 53rd Court
  279. X *                     Portland, Oregon  97221
  280. X *                     (503) 244-3699
  281. X *     All Rights Reserved
  282. X *
  283. X *     Distribution of any portion of this software as part of any product
  284. X *     for sale is prohibited.
  285. X *
  286. X *     Version 1.00 (Preliminary)
  287. X */
  288. X
  289. X#include "fs.h"
  290. X#include <sys/stat.h>
  291. X
  292. X    /* File descriptor filesystem is open on */
  293. Xextern int        fs_fd;
  294. X
  295. X    /* struct holding super block */
  296. Xextern struct fs    sb;
  297. X
  298. X    /* size of file system block (= 4096) */
  299. X#define BLKSIZE sb.fs_bsize
  300. X
  301. X/*
  302. X *    get_dir_inodes - stats inodes from from_inode to to_inode and, if
  303. X *             a directory, adds to return_list.
  304. X */
  305. Xget_dir_inodes(return_list, from_inode, to_inode)
  306. Xstruct    idir **return_list;
  307. Xino_t    from_inode, to_inode;
  308. X{
  309. X    struct stat    statb;
  310. X    struct idir    *idir_list, *cur_ilist;
  311. X
  312. X    ino_t    i;
  313. X
  314. X    new_idir(&idir_list);
  315. X    cur_ilist = idir_list;
  316. X
  317. X    for (i = from_inode; i < to_inode; i++) {
  318. X        if (fs_stat (i, &statb)) {
  319. X            printf ("error reading inode %d\n");
  320. X            break;
  321. X        }
  322. X        if ((statb.st_mode & S_IFMT) == S_IFDIR) {
  323. X                /* Add inode number to list */
  324. X            add_dir_inode(&cur_ilist, i);
  325. X            printf ("found directory at %d\n", i);
  326. X        }
  327. X    }
  328. X    *return_list = idir_list;
  329. X}
  330. X
  331. X/*
  332. X *    new_idir - makes new idir segment and returns pointer new_ptr
  333. X */
  334. Xnew_idir(new_ptr)
  335. Xstruct    idir **new_ptr;
  336. X{
  337. X    char *malloc();
  338. X
  339. X    *new_ptr = (struct idir *) malloc(sizeof(struct idir));
  340. X    (*new_ptr)->icnt = 0;
  341. X    (*new_ptr)->next_idir = NULL;
  342. X}
  343. X
  344. X/*
  345. X *    add_dir_inode - adds inode number to struct idir, mallocing a new
  346. X *            one if needed.
  347. X */
  348. Xadd_dir_inode(idir_ptr, inum)
  349. Xstruct    idir **idir_ptr;
  350. Xino_t    inum;
  351. X{
  352. X    if ((*idir_ptr)->icnt == MAX_ICNT) {
  353. X            /* Current list full, add new segment */
  354. X        new_idir(&((*idir_ptr)->next_idir));
  355. X        *idir_ptr = (*idir_ptr)->next_idir;
  356. X    }
  357. X    (*idir_ptr)->inums[(*idir_ptr)->icnt++] = inum;
  358. X}
  359. X
  360. X/*
  361. X *    in_idir - returns TRUE if inum is found in idir_ptr
  362. X */
  363. Xin_idir(idir_ptr, inum)
  364. Xstruct    idir *idir_ptr;
  365. Xino_t    inum;
  366. X{
  367. X    struct    idir *itmp_ptr;
  368. X
  369. X    ino_t    itmp;
  370. X
  371. X    itmp_ptr = idir_ptr;
  372. X    while (itmp_ptr) {
  373. X        for (itmp = 0; itmp < itmp_ptr->icnt; itmp++)
  374. X            if (itmp_ptr->inums[itmp] == inum)
  375. X                return TRUE;
  376. X        itmp_ptr = itmp_ptr->next_idir;
  377. X    }
  378. X    return FALSE;
  379. X}
  380. X
  381. SHAR_EOF
  382. chmod 0644 idir.c || echo "restore of idir.c fails"
  383. sed 's/^X//' << 'SHAR_EOF' > iname.c &&
  384. X
  385. X/*
  386. X *     fssal - BSD file system salvage program
  387. X *
  388. X *     Copyright 1989, Robert Ankeney
  389. X *                     Generic Computer Products
  390. X *                     5315 S.W. 53rd Court
  391. X *                     Portland, Oregon  97221
  392. X *                     (503) 244-3699
  393. X *     All Rights Reserved
  394. X *
  395. X *     Distribution of any portion of this software as part of any product
  396. X *     for sale is prohibited.
  397. X *
  398. X *     Version 1.00 (Preliminary)
  399. X */
  400. X
  401. X#include "fs.h"
  402. X#include <sys/time.h>
  403. X
  404. X    /* struct holding super block */
  405. Xextern struct fs    sb;
  406. X
  407. X    /* File system block size */
  408. X#define BLKSIZE sb.fs_bsize
  409. X
  410. X/*
  411. X *    iname - generate list of file names based on given inode number.
  412. X *        Given inode inum and maximum count icnt, returns linked list
  413. X *        inames of path names and actual number found found_cnt.
  414. X *        ipath is path name to inode istart, which is prepended to each
  415. X *        iname.
  416. X *
  417. X *        Used for determining links to regular files.
  418. X */
  419. Xiname(ipath, istart, inum, icnt, inames, found_cnt)
  420. Xchar    ipath[MAX_PATH_LEN];
  421. Xino_t    istart, inum;
  422. Xint    icnt, *found_cnt;
  423. Xstruct    iname_list **inames;
  424. X{
  425. X    *inames = NULL;
  426. X    *found_cnt = 0;
  427. X    if (ilist(ipath, istart, inum, icnt, inames, found_cnt))
  428. X        fprintf(stderr, "Inode %d is not a directory\n", inum);
  429. X}
  430. X
  431. Xilist(ipath, istart, inum, icnt, inames, found_cnt)
  432. Xchar    ipath[MAX_PATH_LEN];
  433. Xino_t    istart, inum;
  434. Xint    icnt, *found_cnt;
  435. Xstruct    iname_list **inames;
  436. X{
  437. X    struct icommon    fs_inode;        /* Inode for directory */
  438. X    struct direct    *fs_dir;        /* Directory structure */
  439. X    struct file_ptr    dir_ptr;        /* Directory pointer */
  440. X
  441. X    char        dir_buf[MAXBSIZE];    /* Directory buffer */
  442. X    int        buf_cnt;        /* # chars in buffer */
  443. X    int        next_ent;        /* Buf offset of next dir */
  444. X
  445. X    char        cur_name[MAX_PATH_LEN];    /* Current directory pathname */
  446. X
  447. X    struct icommon    file_inode;        /* Inode for ls file */
  448. X
  449. X    static struct iname_list *cur_iname, *tmp_iname;
  450. X
  451. X    char        *strcpy(), *sprintf(), *strcat();
  452. X    char        *malloc();
  453. X
  454. X    extern int    errno;
  455. X
  456. X
  457. X        /* Fetch inode */
  458. X    get_inode(istart, &fs_inode);
  459. X
  460. X        /* Make sure it's a directory! */
  461. X    if ((fs_inode.ic_mode & IFMT) != IFDIR) {
  462. X        errno = ENOTDIR;
  463. X        return -1;
  464. X    }
  465. X        /* Open directory */
  466. X    uopen(&fs_inode, &dir_ptr);
  467. X
  468. X        /* Read each directory block */
  469. X    do {
  470. X            /* Read next block of directory */
  471. X        if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
  472. X            perror("Cannot read directory");
  473. X            exit(1);
  474. X        }
  475. X
  476. X        if (buf_cnt == 0)
  477. X        break;
  478. X
  479. X            /* For each file in directory, check inode # */
  480. X        next_ent = 0;
  481. X        do {
  482. X            /* Point to next directory entry */
  483. X        fs_dir = (struct direct *) &dir_buf[next_ent];
  484. X
  485. X            /* Directory entry here? */
  486. X        if (fs_dir->d_ino != 0) {
  487. X                /* Get inode */
  488. X            get_inode(fs_dir->d_ino, &file_inode);
  489. X
  490. X                /* Desired inode #? */
  491. X            if (fs_dir->d_ino == inum) {
  492. X                    /* Yep - Malloc new iname_list */
  493. X                tmp_iname = cur_iname;
  494. X                cur_iname = (struct iname_list *)
  495. X                    malloc(sizeof(struct iname_list));
  496. X                cur_iname->next_iname = NULL;
  497. X                if (tmp_iname)
  498. X                    tmp_iname->next_iname = cur_iname;
  499. X                if (*inames == NULL)
  500. X                    *inames = cur_iname;
  501. X
  502. X                    /* Copy starting path */
  503. X                (void) strcpy(cur_iname->name, ipath);
  504. X                (void) strcat(cur_iname->name, "/");
  505. X                    /* Append actual file name */
  506. X                (void) strcat(cur_iname->name, fs_dir->d_name);
  507. X                ++*found_cnt;
  508. X            }
  509. X        }
  510. X        next_ent += fs_dir->d_reclen;
  511. X        } while (next_ent < buf_cnt);
  512. X
  513. X    } while (buf_cnt > 0);
  514. X
  515. X        /* Open directory again */
  516. X    uopen(&fs_inode, &dir_ptr);
  517. X
  518. X        /* Read each directory block */
  519. X    do {
  520. X            /* Read next block of directory */
  521. X        if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
  522. X            perror("Cannot read directory");
  523. X            exit(1);
  524. X        }
  525. X
  526. X        if (buf_cnt == 0)
  527. X        break;
  528. X
  529. X            /* For each subdirectory in directory, check it */
  530. X        next_ent = 0;
  531. X        do {
  532. X            /* Point to next directory entry */
  533. X        fs_dir = (struct direct *) &dir_buf[next_ent];
  534. X
  535. X            /* Directory entry here? */
  536. X        if (fs_dir->d_ino != 0) {
  537. X                /* Get inode */
  538. X            get_inode(fs_dir->d_ino, &file_inode);
  539. X
  540. X                /* Make sure is dir and not . or .. */
  541. X            if ((file_inode.ic_mode & IFMT) == IFDIR)
  542. X                if (strcmp(fs_dir->d_name, ".") &&
  543. X                strcmp(fs_dir->d_name, "..")) {
  544. X                    if (*ipath)
  545. X                    (void) sprintf(cur_name, "%s/%s",
  546. X                        ipath, fs_dir->d_name);
  547. X                    else
  548. X                    (void) strcpy(cur_name, fs_dir->d_name);
  549. X
  550. X                    /* Check this directory! */
  551. X                if (ilist(cur_name, fs_dir->d_ino, inum,
  552. X                    icnt - *found_cnt, inames, found_cnt)) {
  553. X                    fprintf(stderr,
  554. X                    "Inode %d is not a directory\n", inum);
  555. X                    return -1;
  556. X                }
  557. X                }
  558. X        }
  559. X        next_ent += fs_dir->d_reclen;
  560. X        } while (next_ent < buf_cnt);
  561. X
  562. X    } while (buf_cnt > 0);
  563. X    return 0;
  564. X}
  565. SHAR_EOF
  566. chmod 0644 iname.c || echo "restore of iname.c fails"
  567. sed 's/^X//' << 'SHAR_EOF' > io.c &&
  568. X
  569. X/*
  570. X *     fssal - BSD file system salvage program
  571. X *
  572. X *     Copyright 1989, Robert Ankeney
  573. X *                     Generic Computer Products
  574. X *                     5315 S.W. 53rd Court
  575. X *                     Portland, Oregon  97221
  576. X *                     (503) 244-3699
  577. X *     All Rights Reserved
  578. X *
  579. X *     Distribution of any portion of this software as part of any product
  580. X *     for sale is prohibited.
  581. X *
  582. X *     Version 1.00 (Preliminary)
  583. X */
  584. X
  585. X#include "fs.h"
  586. X
  587. X
  588. X    /* File descriptor filesystem is open on */
  589. Xextern int    fs_fd;
  590. X
  591. X    /* struct holding super block */
  592. Xextern struct fs    sb;
  593. X
  594. X    /* size of file system block */
  595. X#define BLKSIZE sb.fs_bsize
  596. X
  597. X/*
  598. X *    getsb - read super block into struct sb
  599. X */
  600. Xgetsb(fs_to_read, sb_block)
  601. Xchar    *fs_to_read;
  602. Xint    sb_block;
  603. X{
  604. X    long    lseek();
  605. X
  606. X        /* Open file system */
  607. X    if ((fs_fd = open(fs_to_read, O_RDONLY)) == -1) {
  608. X        perror("Cannot open filesystem");
  609. X        exit(1);
  610. X    }
  611. X
  612. X        /* Seek to super block */
  613. X/*
  614. X    (void) lseek(fs_fd, (long) BBSIZE, L_SET);
  615. X*/
  616. X    (void) lseek(fs_fd, (long) 512 * sb_block, L_SET);
  617. X
  618. X        /* Read super block */
  619. X    if (read(fs_fd, (char *) &sb, sizeof(sb)) == -1) {
  620. X        perror("Cannot read filesystem");
  621. X        exit(1);
  622. X    }
  623. X
  624. X        /* Check magic number */
  625. X    if (sb.fs_magic != FS_MAGIC) {
  626. X        fprintf(stderr, "Bad magic number for super block\n");
  627. X        exit(1);
  628. X    }
  629. X
  630. X}
  631. X
  632. X/*
  633. X *    uopen - open file on unmounted file system.
  634. X *
  635. X *        Input is a pointer to the icommon for the file to open,
  636. X *        and a pointer (struct file_ptr) to the info to be
  637. X *        returned.  (Includes pointer to inode, index into file,
  638. X *        and size of file).
  639. X */
  640. Xuopen(ip, fp)
  641. Xstruct icommon    *ip;
  642. Xstruct file_ptr    *fp;
  643. X{
  644. X    fp->ip = ip;
  645. X    fp->file_ptr = 0;
  646. X    fp->file_size = fp->ip->ic_size.val[0];
  647. X}
  648. X
  649. X/*
  650. X *    uread - read data from uopened file.
  651. X *
  652. X *        Input is pointer to struct file_ptr returned from uopen,
  653. X *        pointer to buffer to place data in, and count of number
  654. X *        of bytes to read.
  655. X *
  656. X *        Note - Doesn't handle double-indirect blocks!
  657. X *            (Gawd, I'm lazy!)
  658. X *
  659. X *        Returns:
  660. X *            -1 if no data was read,
  661. X *            count if all data was transferred,
  662. X *            else actual number of bytes transferred.
  663. X */
  664. Xuread(fp, bp, count)
  665. Xstruct file_ptr    *fp;
  666. Xchar        *bp;
  667. Xlong        count;
  668. X{
  669. X    /* # indirect pointers in an indirect block */
  670. X#define    NUM_IND_PTRS    (BLKSIZE / sizeof(long))
  671. X    /* # bytes pointed to by an indirect block */
  672. X#define    IND_CNT        (NUM_IND_PTRS * BLKSIZE)
  673. X
  674. X    long    direct_blk;        /* Index into direct block numbers */
  675. X    long    ind_ptr;        /* Which byte in indirect block */
  676. X    int    ind_blk;        /* Which indirect pointer of NIADDR */
  677. X    int    ind_off;        /* Which indirect pointer in block */
  678. Xstatic    char    ind_buf[MAXBSIZE];    /* Indirect block */
  679. Xstatic    int    last_ind_blk;        /* Last indirect block read */
  680. X
  681. X    int    num_to_read;        /* # bytes of block to read */
  682. X    int    offset;            /* Offset into block to start read */
  683. X    int    nr;            /* # bytes actually read */
  684. X    long    file_cnt;        /* # bytes left in file */
  685. X    long    num_read;        /* # bytes read so far */
  686. X    long    block_to_read;        /* Block # for read */
  687. X
  688. X    char    *bufptr;        /* Next byte in buffer to read into */
  689. X
  690. X    long    lseek();
  691. X
  692. X    bufptr = bp;
  693. X    num_read = 0;
  694. X
  695. X        /* # bytes left in file */
  696. X    file_cnt = fp->file_size - fp->file_ptr;
  697. X
  698. X        /* Limit count to size of file */
  699. X    if (count > file_cnt)
  700. X        count = file_cnt;
  701. X
  702. X    while (count != 0) {
  703. X
  704. X            /* Get direct block # */
  705. X        direct_blk = fp->file_ptr / BLKSIZE;
  706. X
  707. X            /* Into indirect blocks? */
  708. X        if (direct_blk >= NDADDR) {
  709. X            ind_ptr = fp->file_ptr - NDADDR * BLKSIZE;
  710. X
  711. X                /* Into double-indirect blocks? */
  712. X            if ((ind_blk = ind_ptr / IND_CNT) >= NIADDR) {
  713. X                fprintf(stderr, "File too large\n");
  714. X                exit(1);
  715. X            }
  716. X
  717. X            ind_off = ind_ptr / BLKSIZE;
  718. X
  719. X            if (last_ind_blk != fp->ip->ic_ib[ind_blk]) {
  720. X                    /* Read indirect block */
  721. X#ifdef DEBUG
  722. X                printf("Reading indirect block %d\n",
  723. X                            last_ind_blk);
  724. X#endif
  725. X                last_ind_blk = fp->ip->ic_ib[ind_blk];
  726. X                (void) lseek(fs_fd, btobo(last_ind_blk), L_SET);
  727. X                if (read(fs_fd, ind_buf, (int) BLKSIZE) == -1) {
  728. X                    perror("Cannot read indirect block");
  729. X                    exit(1);
  730. X                }
  731. X            }
  732. X
  733. X            block_to_read = * ((long *) &ind_buf[ind_off *
  734. X                                sizeof(long)]);
  735. X        } else
  736. X            block_to_read = fp->ip->ic_db[direct_blk];
  737. X
  738. X            /* Offset into block to start read */
  739. X        offset = fp->file_ptr % BLKSIZE;
  740. X
  741. X            /* # bytes in block to read */
  742. X        num_to_read = ((BLKSIZE - offset) < count) ?
  743. X                (BLKSIZE - offset) : count;
  744. X
  745. X            /* Check for pointer to empty block */
  746. X        if (block_to_read == 0) {
  747. X            for (nr = 0; nr < num_to_read; nr++)
  748. X                bufptr[nr] = '\0';
  749. X        } else {
  750. X
  751. X#ifdef DEBUG
  752. X            printf("Reading block %d\n", block_to_read);
  753. X#endif
  754. X                /* Seek to block */
  755. X            (void) lseek(fs_fd, btobo(block_to_read), L_SET);
  756. X
  757. X                /* Read them */
  758. X            if ((nr = read(fs_fd, bufptr, num_to_read)) == -1)
  759. X                    /* Return error if nothing read,
  760. X                     * else # bytes actually read    */
  761. X                return (num_read == 0) ? -1 : num_read;
  762. X        }
  763. X
  764. X        count -= nr;
  765. X        file_cnt -= nr;
  766. X        fp->file_ptr += nr;
  767. X        num_read += nr;
  768. X        bufptr += nr;        /* Point to next part of buffer */
  769. X
  770. X            /* Read short */
  771. X        if (nr < num_to_read)
  772. X            return num_read;
  773. X    }
  774. X    return num_read;
  775. X}
  776. X
  777. SHAR_EOF
  778. chmod 0644 io.c || echo "restore of io.c fails"
  779. sed 's/^X//' << 'SHAR_EOF' > ls.c &&
  780. X
  781. X/*
  782. X *     fssal - BSD file system salvage program
  783. X *
  784. X *     Copyright 1989, Robert Ankeney
  785. X *                     Generic Computer Products
  786. X *                     5315 S.W. 53rd Court
  787. X *                     Portland, Oregon  97221
  788. X *                     (503) 244-3699
  789. X *     All Rights Reserved
  790. X *
  791. X *     Distribution of any portion of this software as part of any product
  792. X *     for sale is prohibited.
  793. X *
  794. X *     Version 1.00 (Preliminary)
  795. X */
  796. X
  797. X#include "fs.h"
  798. X#include <sys/time.h>
  799. X
  800. X    /* struct holding super block */
  801. Xextern struct fs    sb;
  802. X
  803. X    /* File system block size */
  804. X#define BLKSIZE sb.fs_bsize
  805. X
  806. X/*
  807. X *    ls -    Do a directory listing of given inode.  Do a 'ls -l'
  808. X *        if Lflag is set;  do a 'ls -R' if Rflag is set.
  809. X *        dir_name is name of passed directory.  idir_list is
  810. X *        updated with inode number of each listed directory.
  811. X */
  812. Xls(ls_inode, dir_name, idir_list, Lflag, Rflag)
  813. Xino_t    ls_inode;
  814. Xchar    *dir_name;
  815. Xstruct    idir **idir_list;
  816. Xchar    Lflag, Rflag;
  817. X{
  818. X    struct icommon    fs_inode;    /* Inode for directory */
  819. X    struct direct    *fs_dir;    /* Directory structure */
  820. X    struct file_ptr    dir_ptr;    /* Directory pointer */
  821. X
  822. X    struct icommon    sym_inode;    /* Inode for symbolic link */
  823. X    struct file_ptr    sym_ptr;    /* Symbolic link pointer */
  824. X    long        sym_size;    /* Length of symbolic name */
  825. X    char        sym_buf[MAX_PATH_LEN];    /* Buffer for symbolic name */
  826. X
  827. X    char        dir_buf[MAXBSIZE];    /* Directory buffer */
  828. X    int        buf_cnt;    /* # chars in buffer */
  829. X    int        next_ent;    /* Offset into buf of next direct */
  830. X
  831. X    int        mode;        /* File mode */
  832. X    char        modes[11];    /* File mode string */
  833. X    struct icommon    file_inode;    /* Inode for ls file */
  834. X    int        i;
  835. X    char        *create_time;    /* Creation date string */
  836. X    char        cur_name[1024];    /* Current directory pathname */
  837. X
  838. X    char        *ctime();
  839. X    char        *strcpy();
  840. X    char        *sprintf();
  841. X
  842. X    extern int    errno;
  843. X
  844. X        /* Fetch inode */
  845. X    get_inode(ls_inode, &fs_inode);
  846. X
  847. X        /* Make sure it's a directory! */
  848. X    if ((fs_inode.ic_mode & IFMT) != IFDIR) {
  849. X        errno = ENOTDIR;
  850. X        return -1;
  851. X    }
  852. X
  853. X        /* Add directory inode number to list */
  854. X    add_dir_inode(idir_list, ls_inode);
  855. X
  856. X        /* Open directory */
  857. X    uopen(&fs_inode, &dir_ptr);
  858. X
  859. X    if (Rflag && *dir_name)
  860. X        printf("%s:\n", dir_name);
  861. X
  862. X        /* Read each directory block */
  863. X    do {
  864. X            /* Read next block of directory */
  865. X        if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
  866. X            perror("Cannot read directory");
  867. X            exit(1);
  868. X        }
  869. X
  870. X        if (buf_cnt == 0)
  871. X        break;
  872. X
  873. X            /* For each file in directory, list it */
  874. X        next_ent = 0;
  875. X        do {
  876. X            /* Point to next directory entry */
  877. X        fs_dir = (struct direct *) &dir_buf[next_ent];
  878. X
  879. X            /* Directory entry here? */
  880. X        if (fs_dir->d_ino != 0) {
  881. X            if (Lflag) {
  882. X                /* Get inode */
  883. X            get_inode(fs_dir->d_ino, &file_inode);
  884. X
  885. X            printf("%5d ", fs_dir->d_ino);        /* Inode # */
  886. X            (void) strcpy(modes, "-rwxrwxrwx");
  887. X            mode = file_inode.ic_mode;
  888. X            for (i = 8; i >= 0; i--)
  889. X                if ((mode & (1 << i)) == 0)
  890. X                    modes[9 - i] = '-';    /* rwx bits */
  891. X            if ((mode & IFMT) == IFDIR)
  892. X                      modes[0] = 'd';    /* directory */
  893. X            if ((mode & IFMT) == IFLNK)
  894. X                      modes[0] = 'l';    /* sym link */
  895. X
  896. X            if (mode & ISUID) modes[3] = 's';    /* setuid */
  897. X            if (mode & ISGID) modes[6] = 's';    /* setgid */
  898. X            if (mode & ISVTX) modes[9] = 't';    /* sticky */
  899. X            printf("%s %3d %3d/%-3d %8ld",
  900. X                modes,                /* modes */
  901. X                file_inode.ic_nlink,        /* link cnt */
  902. X                file_inode.ic_uid,        /* uid */
  903. X                file_inode.ic_gid,        /* gid */
  904. X                file_inode.ic_size.val[0]);    /* size */
  905. X            create_time = ctime((long *) &file_inode.ic_ctime);
  906. X            printf(" %-12.12s %-4.4s ", create_time + 4,
  907. X                            create_time + 20);
  908. X                printf("%s", fs_dir->d_name);        /* file name */
  909. X
  910. X                /* Symbolic link? */
  911. X            if ((mode & IFMT) == IFLNK) {
  912. X                    /* Yup - print name of link */
  913. X                get_inode(fs_dir->d_ino, &sym_inode);
  914. X                sym_size = sym_inode.ic_size.val[0];
  915. X                if (sym_size >= sizeof(sym_buf))
  916. X                    printf(" -> ?name too big");
  917. X                else {
  918. X                    uopen(&sym_inode, &sym_ptr);
  919. X                    if (uread(&sym_ptr, sym_buf, sym_size)
  920. X                            != sym_size) {
  921. X                        perror("Cannot read symlink");
  922. X                        exit(1);
  923. X                    }
  924. X                    sym_buf[sym_size] = '\0';
  925. X                    printf(" -> %s", sym_buf);
  926. X                }
  927. X            }
  928. X            printf("\n");
  929. X
  930. X            } else
  931. X                printf("%s\n", fs_dir->d_name);        /* file name */
  932. X        }
  933. X        next_ent += fs_dir->d_reclen;
  934. X        } while (next_ent < buf_cnt);
  935. X
  936. X    } while (buf_cnt > 0);
  937. X
  938. X    printf("\n");
  939. X
  940. X    /* Recursive (ls -R)? */
  941. X    if (Rflag) {
  942. X        /* Open directory again */
  943. X    uopen(&fs_inode, &dir_ptr);
  944. X
  945. X        /* Read each directory block */
  946. X    do {
  947. X            /* Read next block of directory */
  948. X        if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
  949. X            perror("Cannot read directory");
  950. X            exit(1);
  951. X        }
  952. X
  953. X        if (buf_cnt == 0)
  954. X        break;
  955. X
  956. X            /* For each directory in directory, list it */
  957. X        next_ent = 0;
  958. X        do {
  959. X            /* Point to next directory entry */
  960. X        fs_dir = (struct direct *) &dir_buf[next_ent];
  961. X
  962. X            /* Directory entry here? */
  963. X        if (fs_dir->d_ino != 0) {
  964. X                /* Get inode */
  965. X            get_inode(fs_dir->d_ino, &file_inode);
  966. X
  967. X                /* Make sure is dir and not . or .. */
  968. X            if ((file_inode.ic_mode & IFMT) == IFDIR)
  969. X                if (strcmp(fs_dir->d_name, ".") &&
  970. X                strcmp(fs_dir->d_name, ".."))
  971. X
  972. X                /* Make sure not already listed */
  973. X                if (in_idir(*idir_list, fs_dir->d_ino))
  974. X                fprintf(stderr, "Already ls'd inum %d, directory: %s !\n", fs_dir->d_ino, cur_name);
  975. X                else {
  976. X                    if (*dir_name)
  977. X                    (void) sprintf(cur_name, "%s/%s",
  978. X                        dir_name, fs_dir->d_name);
  979. X                    else
  980. X                    (void) strcpy(cur_name, fs_dir->d_name);
  981. X
  982. X                    /* List this directory! */
  983. X                    if (ls(fs_dir->d_ino, cur_name, idir_list,
  984. X                    Lflag, Rflag))
  985. X                        return -1;
  986. X                }
  987. X        }
  988. X        next_ent += fs_dir->d_reclen;
  989. X        } while (next_ent < buf_cnt);
  990. X
  991. X    } while (buf_cnt > 0);
  992. X    }
  993. X    return 0;
  994. X}
  995. X
  996. X
  997. Xls_all(Rflag, verbose)
  998. Xchar    Rflag, verbose;
  999. X{
  1000. X    struct    idir *idir_list, *ls_list, *idir_ptr, *ls_ptr;
  1001. X
  1002. X    ino_t    inum;
  1003. X    int    icnt = 0;
  1004. X    char    iname[MAX_PATH_LEN];
  1005. X
  1006. X        /* Get list of directory inodes for filesystem */
  1007. X    get_dir_inodes(&idir_list, (ino_t) 2, (ino_t) sb.fs_ncg * sb.fs_ipg);
  1008. X
  1009. X        /* Make list of ls'd directory inodes */
  1010. X    new_idir(&ls_list);
  1011. X    idir_ptr = idir_list;
  1012. X    while (idir_ptr) {
  1013. X        inum = idir_ptr->inums[icnt];
  1014. X            /* Inode been ls'd? */
  1015. X        if (!in_idir(ls_list, inum)) {
  1016. X
  1017. X                /* Point to end of ls'd inode list */
  1018. X            ls_ptr = ls_list;
  1019. X            while(ls_ptr->next_idir)
  1020. X                ls_ptr = ls_ptr->next_idir;
  1021. X            
  1022. X                /* Append to end of ls'd inode list */
  1023. X            if (ls(inum, iname, &ls_ptr, Rflag, verbose))
  1024. X                return -1;
  1025. X        }
  1026. X        if (++icnt == idir_ptr->icnt) {
  1027. X            icnt = 0;
  1028. X            idir_ptr = idir_ptr->next_idir;
  1029. X        }
  1030. X    }
  1031. X    return 0;
  1032. X}
  1033. SHAR_EOF
  1034. chmod 0644 ls.c || echo "restore of ls.c fails"
  1035. sed 's/^X//' << 'SHAR_EOF' > main.c &&
  1036. X
  1037. X/*
  1038. X *     fssal - BSD file system salvage program
  1039. X *
  1040. X *     Copyright 1989, Robert Ankeney
  1041. X *                     Generic Computer Products
  1042. X *                     5315 S.W. 53rd Court
  1043. X *                     Portland, Oregon  97221
  1044. X *                     (503) 244-3699
  1045. X *     All Rights Reserved
  1046. X *
  1047. X *     Distribution of any portion of this software as part of any product
  1048. X *     for sale is prohibited.
  1049. X *
  1050. X *     Version 1.00 (Preliminary)
  1051. X */
  1052. X
  1053. X#include "fs.h"
  1054. X#include <sys/stat.h>
  1055. X
  1056. X    /* File descriptor filesystem is open on */
  1057. Xint        fs_fd;
  1058. X
  1059. X    /* struct holding super block */
  1060. Xstruct fs    sb;
  1061. X
  1062. X    /* Current root inode */
  1063. Xino_t    root_inode = ROOTINO;
  1064. X
  1065. Xchar    *fs_to_read = FS_TO_READ;
  1066. Xint    sb_block = BBSIZE / 512;
  1067. X
  1068. Xusage(fs_name)
  1069. Xchar    *fs_name;
  1070. X{
  1071. X    fprintf (stderr,
  1072. X"usage: %s [-f device] [-s super-block] [-r root-inode] [-a] [-l] [-R] [-v]\n",
  1073. X    fs_name);
  1074. X    exit(1);
  1075. X}
  1076. X
  1077. Xmain(argc, argv)
  1078. Xint    argc;
  1079. Xchar    *argv[];
  1080. X{
  1081. X    char    do_all, verbose, recurse, long_ls = FALSE;
  1082. X    char    *fs_name = argv[0];
  1083. X    struct    stat statb;
  1084. X    struct    idir *idir_list;
  1085. X
  1086. X    for (fs_name = argv[0] + strlen(argv[0]);
  1087. X        (fs_name != argv[0]) && (*(fs_name - 1) != '/'); fs_name--) ;
  1088. X
  1089. X    while (*++argv) {
  1090. X        if (**argv == '-') {
  1091. X            switch (*++*argv) {
  1092. X            case 'f':
  1093. X                fs_to_read = *++argv;
  1094. X                break;
  1095. X            case 's':
  1096. X                sb_block = atoi (*++argv);
  1097. X                break;
  1098. X            case 'r':
  1099. X                root_inode = atoi (*++argv);
  1100. X                break;
  1101. X            case 'a':
  1102. X                do_all = TRUE;
  1103. X                break;
  1104. X            case 'v':
  1105. X                verbose = TRUE;
  1106. X                break;
  1107. X            case 'R':
  1108. X                recurse = TRUE;
  1109. X                break;
  1110. X            case 'l':
  1111. X                long_ls = TRUE;
  1112. X                break;
  1113. X
  1114. X            default:
  1115. X                usage(fs_name);
  1116. X            }
  1117. X        }
  1118. X    }
  1119. X
  1120. X        /* Stat file and see if it's a block special device */
  1121. X    if (stat(fs_to_read, &statb)) {
  1122. X        perror("Cannot stat file");
  1123. X        exit(1);
  1124. X    } else
  1125. X        if ((statb.st_mode & S_IFMT) != S_IFBLK) {
  1126. X            fprintf(stderr, "%s not a block special device\n",
  1127. X                fs_to_read);
  1128. X        exit(1);
  1129. X    }
  1130. X
  1131. X        /* Read in superblock */
  1132. X    getsb(fs_to_read, sb_block);
  1133. X    
  1134. X    new_idir(&idir_list);
  1135. X
  1136. X    if (!strcmp(fs_name, "fssal"))
  1137. X        if (do_all)
  1138. X            exit( restore_all(recurse, verbose) );
  1139. X        else
  1140. X            exit( restore(".", root_inode, ".",
  1141. X                    &idir_list, recurse, verbose) );
  1142. X
  1143. X    if (!strcmp(fs_name, "fsls"))
  1144. X        if (do_all)
  1145. X            exit( ls_all(long_ls, recurse) );
  1146. X        else
  1147. X            exit( ls(root_inode, "", &idir_list, long_ls, recurse));
  1148. X
  1149. X    usage(fs_name);
  1150. X
  1151. X    (void) close(fs_fd);
  1152. X    exit(0);
  1153. X}
  1154. SHAR_EOF
  1155. chmod 0644 main.c || echo "restore of main.c fails"
  1156. sed 's/^X//' << 'SHAR_EOF' > namei.c &&
  1157. X
  1158. X/*
  1159. X *     fssal - BSD file system salvage program
  1160. X *
  1161. X *     Copyright 1989, Robert Ankeney
  1162. X *                     Generic Computer Products
  1163. X *                     5315 S.W. 53rd Court
  1164. X *                     Portland, Oregon  97221
  1165. X *                     (503) 244-3699
  1166. X *     All Rights Reserved
  1167. X *
  1168. X *     Distribution of any portion of this software as part of any product
  1169. X *     for sale is prohibited.
  1170. X *
  1171. X *     Version 1.00 (Preliminary)
  1172. X */
  1173. X
  1174. X#include "fs.h"
  1175. X
  1176. X
  1177. X    /* File descriptor filesystem is open on */
  1178. Xextern int    fs_fd;
  1179. X
  1180. X    /* struct holding super block */
  1181. Xextern struct fs    sb;
  1182. X
  1183. X    /* File system block size */
  1184. X#define BLKSIZE sb.fs_bsize
  1185. X
  1186. X/*
  1187. X *    get_inode - read inode inum into struct rd_inode
  1188. X */
  1189. Xget_inode(inum, rd_inode)
  1190. Xino_t        inum;
  1191. Xstruct icommon    *rd_inode;
  1192. X{
  1193. X    long    lseek();
  1194. X
  1195. X        /* Seek to desired inode */
  1196. X    (void) lseek(fs_fd, (long) itobo(inum), L_SET);
  1197. X
  1198. X        /* Read that inode */
  1199. X    if (read(fs_fd, (char *) rd_inode, ISIZE) == -1) {
  1200. X        perror("Cannot read file system");
  1201. X        exit(1);
  1202. X    }
  1203. X}
  1204. X
  1205. X/*
  1206. X *    namei -    Convert filename to inode number.
  1207. X *
  1208. X *        First get root inode for file system.
  1209. X *        From there, search each directory in path for next
  1210. X *        component of path name, till final filename found.
  1211. X *
  1212. X *        Returns:
  1213. X *            0 if file not found (ENOENT),
  1214. X *            0 if file in path was not a directory (ENOTDIR),
  1215. X *            else inode of file filename.
  1216. X */
  1217. Xnamei(filename)
  1218. Xchar    *filename;
  1219. X{
  1220. X    char    tmp_name[1024];        /* Copy of filename */
  1221. X    ino_t    cur_ino;        /* Current inode in path */
  1222. X    char     *curnam;        /* Points to next char in filename */
  1223. X    char    *next_name;        /* Next name to scan */
  1224. X    int    next_slash;
  1225. X
  1226. X    struct icommon    fs_inode;    /* Inode for file/directory */
  1227. X    struct direct    *fs_dir;    /* Directory structure */
  1228. X    struct file_ptr    dir_ptr;    /* Directory pointer */
  1229. X
  1230. X    char    dir_buf[MAXBSIZE];    /* Directory buffer */
  1231. X    int        buf_cnt;    /* # chars in buffer */
  1232. X
  1233. X    int        next_ent;    /* Offset into buf of next direct */
  1234. X
  1235. X    char        *strcpy();
  1236. X
  1237. X    extern int    errno;
  1238. X
  1239. X        /* Save copy of path name */
  1240. X    (void) strcpy(tmp_name, filename);
  1241. X    curnam = tmp_name;
  1242. X
  1243. X        /* Start at root inode */
  1244. X    cur_ino = ROOTINO;
  1245. X
  1246. X        /* Search till nothing left of path name */
  1247. X    while ((*curnam != '\0') && (cur_ino != 0)) {
  1248. X
  1249. X#ifdef DEBUG
  1250. X        printf("Reading inode %d\n", cur_ino);
  1251. X#endif
  1252. X            /* Get current inode */
  1253. X        get_inode(cur_ino, &fs_inode);
  1254. X
  1255. X            /* Make sure it's a directory! */
  1256. X        if ((fs_inode.ic_mode & IFMT) != IFDIR) {
  1257. X            errno = ENOTDIR;
  1258. X            return 0;
  1259. X        }
  1260. X
  1261. X            /* Skip /'s in next component of name */
  1262. X        while (*curnam == '/') curnam++;
  1263. X
  1264. X            /* Get next component of path in next_name */
  1265. X        for (next_slash = 0;
  1266. X            (curnam[next_slash] != '\0') && (curnam[next_slash] != '/');
  1267. X             next_slash ++) ;
  1268. X        
  1269. X        next_name = curnam;
  1270. X        curnam += next_slash;
  1271. X        if (*curnam == '/') curnam++;
  1272. X        next_name[next_slash] = '\0';
  1273. X
  1274. X#ifdef DEBUG
  1275. X        printf("Scanning directory for file '%s'.\n", next_name);
  1276. X#endif
  1277. X
  1278. X            /* Open directory */
  1279. X        uopen(&fs_inode, &dir_ptr);
  1280. X
  1281. X            /*
  1282. X             * Search each directory block for name.
  1283. X             * Return inode number in cur_ino when found.
  1284. X             */
  1285. X        cur_ino = 0;
  1286. X        do {
  1287. X
  1288. X                /* Read next block of directory */
  1289. X            if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE))
  1290. X                                == -1) {
  1291. X                perror("Cannot read directory");
  1292. X                exit(1);
  1293. X            }
  1294. X
  1295. X            if (buf_cnt == 0)
  1296. X                break;
  1297. X
  1298. X                /* Scan directory block for desired name */
  1299. X            next_ent = 0;
  1300. X            do {
  1301. X                    /* Point to next directory entry */
  1302. X                fs_dir = (struct direct *)
  1303. X                         &dir_buf[next_ent];
  1304. X
  1305. X                    /* Directory entry here? */
  1306. X                if (fs_dir->d_ino != 0) {
  1307. X#ifdef DEBUG
  1308. X                    printf("Inode: %6d file: %s\n",
  1309. X                        fs_dir->d_ino, fs_dir->d_name);
  1310. X#endif
  1311. X
  1312. X                        /* Names match? */
  1313. X                    if (!strcmp(next_name, fs_dir->d_name))
  1314. X                            /* Yes- save inode */
  1315. X                        cur_ino = fs_dir->d_ino;
  1316. X                }
  1317. X                next_ent += fs_dir->d_reclen;
  1318. X            } while ((cur_ino == 0) &&
  1319. X                 (next_ent < buf_cnt));
  1320. X
  1321. X        } while ((cur_ino == 0) && (buf_cnt > 0));
  1322. X    }
  1323. X
  1324. X    if (cur_ino == 0) {
  1325. X        errno = ENOENT;
  1326. X        return 0;        /* File not found - return 0 */
  1327. X    } else
  1328. X        return cur_ino;        /* Found - return inode number */
  1329. X}
  1330. X
  1331. SHAR_EOF
  1332. chmod 0644 namei.c || echo "restore of namei.c fails"
  1333. sed 's/^X//' << 'SHAR_EOF' > restore.c &&
  1334. X
  1335. X/*
  1336. X *     fssal - BSD file system salvage program
  1337. X *
  1338. X *     Copyright 1989, Robert Ankeney
  1339. X *                     Generic Computer Products
  1340. X *                     5315 S.W. 53rd Court
  1341. X *                     Portland, Oregon  97221
  1342. X *                     (503) 244-3699
  1343. X *     All Rights Reserved
  1344. X *
  1345. X *     Distribution of any portion of this software as part of any product
  1346. X *     for sale is prohibited.
  1347. X *
  1348. X *     Version 1.00 (Preliminary)
  1349. X */
  1350. X
  1351. X#include "fs.h"
  1352. X#include <sys/stat.h>
  1353. X#include <sys/time.h>
  1354. X
  1355. X    /* struct holding super block */
  1356. Xextern struct fs    sb;
  1357. X
  1358. X    /* Current root inode */
  1359. Xextern ino_t    root_inode;
  1360. X
  1361. X    /* File system block size */
  1362. X#define BLKSIZE sb.fs_bsize
  1363. X
  1364. Xchar *base_path;    /* Initial restore path */
  1365. Xino_t   base_inode;    /* Initial restore inode # */
  1366. X
  1367. X/*
  1368. X *    restore - Restore files from given directory.
  1369. X *          from_path is path name to from_inode, which is
  1370. X *          directory to be restored.  Files are restored to
  1371. X *          to_path.  If Rflag is set, restore is recursive
  1372. X *          ( cp -R ).  idir_list is updated with inode number of
  1373. X *          each directory restored.
  1374. X */
  1375. Xrestore(from_path, from_inode, to_path, idir_list, Rflag, verbose)
  1376. Xino_t    from_inode;
  1377. Xchar    *from_path, *to_path;
  1378. Xstruct    idir **idir_list;
  1379. Xchar    Rflag, verbose;
  1380. X{
  1381. X        /* Save initial restore path and inode # */
  1382. X    base_path = to_path;
  1383. X    base_inode = from_inode;
  1384. X    return
  1385. X        rrestore(from_path, from_inode, to_path, idir_list, Rflag, verbose);
  1386. X}
  1387. X
  1388. Xrrestore(from_path, from_inode, to_path, idir_list, Rflag, verbose)
  1389. Xino_t    from_inode;
  1390. Xchar    *from_path, *to_path;
  1391. Xstruct    idir **idir_list;
  1392. Xchar    Rflag, verbose;
  1393. X{
  1394. X    struct icommon    fs_inode;    /* Inode for directory */
  1395. X    struct direct    *fs_dir;    /* Directory structure */
  1396. X    struct file_ptr    dir_ptr;    /* Directory pointer */
  1397. X
  1398. X    struct icommon    sym_inode;    /* Inode for symbolic link */
  1399. X    struct file_ptr    sym_ptr;    /* Symbolic link pointer */
  1400. X    long        sym_size;    /* Length of symbolic name */
  1401. X    char        sym_buf[MAX_PATH_LEN];    /* Buffer for symbolic name */
  1402. X
  1403. X    char        dir_buf[MAXBSIZE];    /* Directory buffer */
  1404. X    int        buf_cnt;    /* # chars in buffer */
  1405. X    int        next_ent;    /* Offset into buf of next direct */
  1406. X
  1407. X    int        mode;        /* File mode */
  1408. X    struct icommon    file_inode;    /* Inode for ls file */
  1409. X    char        in_path[MAX_PATH_LEN];    /* Current input file name */
  1410. X    char        out_path[MAX_PATH_LEN];    /* Current output file name */
  1411. X
  1412. X    char        set_times;    /* TRUE to set creation time */
  1413. X    struct timeval    file_times[2];
  1414. X
  1415. X    struct iname_list *link_list;    /* List of files with common inode */
  1416. X    struct iname_list *temp_link;
  1417. X    int        links_found;
  1418. X    struct stat    file_stat;    /* File status (for inode # to link) */
  1419. X    int        out_file;    /* Output file descriptor */
  1420. X
  1421. X    char        copy_file;    /* TRUE to copy (not link) file */
  1422. X    struct file_ptr    in_ptr;        /* File pointer for input file */
  1423. X    int        nr;
  1424. X    char        buf[8192];
  1425. X
  1426. X    char        *ctime();
  1427. X    char        *strcpy(), *strcat();
  1428. X
  1429. X    extern int    errno;
  1430. X
  1431. X    (void) umask(0);        /* Create any mode file */
  1432. X
  1433. X        /* Fetch inode */
  1434. X    get_inode(from_inode, &fs_inode);
  1435. X
  1436. X        /* Make sure it's a directory! */
  1437. X    if ((fs_inode.ic_mode & IFMT) != IFDIR) {
  1438. X        errno = ENOTDIR;
  1439. X        return -1;
  1440. X    }
  1441. X
  1442. X        /* Add directory inode number to list */
  1443. X    add_dir_inode(idir_list, from_inode);
  1444. X
  1445. X        /* Open directory */
  1446. X    uopen(&fs_inode, &dir_ptr);
  1447. X
  1448. X        /* Read each directory block */
  1449. X    do {
  1450. X            /* Read next block of directory */
  1451. X        if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
  1452. X            perror("Cannot read directory");
  1453. X            exit(1);
  1454. X        }
  1455. X
  1456. X        if (buf_cnt == 0)
  1457. X        break;
  1458. X
  1459. X            /* For each file in directory, restore it */
  1460. X        next_ent = 0;
  1461. X        do {
  1462. X            /* Point to next directory entry */
  1463. X        fs_dir = (struct direct *) &dir_buf[next_ent];
  1464. X
  1465. X            /* Directory entry here? */
  1466. X        if ((fs_dir->d_ino != 0) && strcmp(fs_dir->d_name, ".")
  1467. X                     && strcmp(fs_dir->d_name, "..")) {
  1468. X                /* Get inode */
  1469. X            get_inode(fs_dir->d_ino, &file_inode);
  1470. X
  1471. X            (void) strcpy(in_path, from_path);
  1472. X            (void) strcat(in_path, "/");
  1473. X            (void) strcat(in_path, fs_dir->d_name);
  1474. X            (void) strcpy(out_path, to_path);
  1475. X            (void) strcat(out_path, "/");
  1476. X            (void) strcat(out_path, fs_dir->d_name);
  1477. X
  1478. X                /* Set up access and mod times */
  1479. X            set_times = TRUE;
  1480. X            file_times[0].tv_sec = file_inode.ic_atime;
  1481. X            file_times[0].tv_usec = file_times[1].tv_usec = 0;
  1482. X            file_times[1].tv_sec = file_inode.ic_mtime;
  1483. X
  1484. X            mode = file_inode.ic_mode;
  1485. X
  1486. X            switch (mode & IFMT) {
  1487. X
  1488. X            case 0020000:        /* character special */
  1489. X            case 0060000:        /* block special */
  1490. X            case 0140000:        /* socket - will it work? */
  1491. X                if (verbose)
  1492. X                    printf("Creating special file: %s\n",
  1493. X                        out_path);
  1494. X                if (mknod(out_path, mode,
  1495. X                    (int) file_inode.ic_db[0]))
  1496. X                {
  1497. X                    fprintf(stderr,
  1498. X                        "Cannot create special file: %s; ",
  1499. X                        out_path);
  1500. X                    perror("");
  1501. X                    set_times = FALSE;
  1502. X                }
  1503. X                break;
  1504. X
  1505. X            case 0040000:        /* directory */
  1506. X                if (verbose)
  1507. X                    printf("Creating directory: %s\n",
  1508. X                        out_path);
  1509. X                if (mkdir(out_path, mode)) {
  1510. X                    fprintf(stderr,
  1511. X                        "Cannot create directory: %s; ",
  1512. X                        out_path);
  1513. X                    perror("");
  1514. X                    set_times = FALSE;
  1515. X                }
  1516. X                break;
  1517. X
  1518. X            case 0100000:        /* regular file */
  1519. X                copy_file = (file_inode.ic_nlink == 1);
  1520. X                if (!copy_file) {
  1521. X                        /* Oh shit; it's a link */
  1522. X                        /* Get filenames with inode # */
  1523. X                    iname(base_path, base_inode,
  1524. X                        fs_dir->d_ino, file_inode.ic_nlink,
  1525. X                        &link_list, &links_found);
  1526. X
  1527. X                        /* Search for existing file */
  1528. X                        /* to link to */
  1529. X                    for (temp_link = link_list;
  1530. X                         temp_link;
  1531. X                         temp_link = temp_link->next_iname)
  1532. X                    {
  1533. X                        if (stat(temp_link->name,
  1534. X                            &file_stat)) {
  1535. X                            if (errno != ENOENT) {
  1536. X                            fprintf(stderr,
  1537. X                                "Cannot stat %s: ",
  1538. X                                temp_link->name);
  1539. X                            perror("");
  1540. X                            }
  1541. X                        } else
  1542. X                        if (mode != file_stat.st_mode) {
  1543. X                        fprintf(stderr,
  1544. X                            "Mode mismatch on %s\n",
  1545. X                            temp_link->name);
  1546. X                        } else
  1547. X                        break;
  1548. X                    }
  1549. X
  1550. X                    if (temp_link) {
  1551. X                        /* Found file to link to */
  1552. X                        if (verbose)
  1553. X                        printf("Linking %s to %s\n",
  1554. X                            temp_link->name, out_path);
  1555. X                        if (link(temp_link->name, out_path))
  1556. X                        {
  1557. X                        fprintf(stderr,
  1558. X                            "Cannot link %s to %s: ",
  1559. X                            temp_link->name, out_path);
  1560. X                        perror("");
  1561. X                        copy_file = TRUE;
  1562. X                        } else
  1563. X                        set_times = FALSE;
  1564. X                    } else
  1565. X                        copy_file = TRUE;
  1566. X                }
  1567. X
  1568. X                if (copy_file) {
  1569. X                        /* Copy file */
  1570. X                    if (verbose)
  1571. X                        printf("Copying %s to %s\n",
  1572. X                            in_path, out_path);
  1573. X                    uopen(&file_inode, &in_ptr);
  1574. X                    if ((out_file = open(out_path,
  1575. X                                O_CREAT | O_WRONLY,
  1576. X                                mode)) == -1) {
  1577. X                        fprintf(stderr,
  1578. X                            "Cannot create %s: ",
  1579. X                            out_path);
  1580. X                        perror("");
  1581. X                        break;
  1582. X                    }
  1583. X
  1584. X                        /* Copy file */
  1585. X                    do {
  1586. X                        if ((nr = uread(&in_ptr, buf,
  1587. X                                BLKSIZE)) == -1) {
  1588. X                            fprintf(stderr,
  1589. X                                "Cannot read %s: ",
  1590. X                                in_path);
  1591. X                            perror("");
  1592. X                        }
  1593. X
  1594. X                        if (nr > 0)
  1595. X                            if (write(out_file, buf, nr)
  1596. X                                == -1) {
  1597. X                            fprintf(stderr,
  1598. X                                "Cannot write %s: ",
  1599. X                                out_path);
  1600. X                            perror("");
  1601. X                        }
  1602. X                    } while (nr > 0);
  1603. X
  1604. X                    (void) close(out_file);
  1605. X                }
  1606. X                break;
  1607. X
  1608. X            case 0120000:            /* symbolic link */
  1609. X                    /* Can't utime symlink */
  1610. X                set_times = FALSE;
  1611. X                    /* Get name of link */
  1612. X                get_inode(fs_dir->d_ino, &sym_inode);
  1613. X                sym_size = sym_inode.ic_size.val[0];
  1614. X                if (sym_size >= sizeof(sym_buf)) {
  1615. X                    fprintf(stderr,
  1616. X                        "Symbolic link to %s too long\n",
  1617. X                        out_path);
  1618. X                    set_times = FALSE;
  1619. X                } else {
  1620. X                    uopen(&sym_inode, &sym_ptr);
  1621. X                    if (uread(&sym_ptr, sym_buf, sym_size)
  1622. X                            != sym_size) {
  1623. X                        perror("Cannot read symlink");
  1624. X                        set_times = FALSE;
  1625. X                    }
  1626. X                    sym_buf[sym_size] = '\0';
  1627. X
  1628. X                    if (verbose)
  1629. X                        printf("Creating symbolic link %s -> %s\n",
  1630. X                            sym_buf, out_path);
  1631. X                    if (symlink(sym_buf, out_path)) {
  1632. X                        fprintf(stderr,
  1633. X                            "Cannot create symbolic link %s -> %s: ",
  1634. X                            out_path, sym_buf);
  1635. X                        perror("");
  1636. X#ifdef UTEK
  1637. X                        if (errno != EDFSNOSUCHHOST)
  1638. X                            set_times = FALSE;
  1639. X#endif
  1640. X                    }
  1641. X                }
  1642. X                break;
  1643. X
  1644. X            default:
  1645. X                fprintf(stderr, "Unknown mode %o on file %s\n",
  1646. X                    mode, in_path);
  1647. X                set_times = FALSE;
  1648. X            }
  1649. X
  1650. X            if (set_times) {
  1651. X                    /* Set creation times on file */
  1652. X                if (utimes(out_path, file_times)) {
  1653. X                    fprintf(stderr,
  1654. X                        "Cannot set creation times on %s: ",
  1655. X                        out_path);
  1656. X                    perror("");
  1657. X                }
  1658. X                    /* Set owner and group */
  1659. X                if (chown(out_path, file_inode.ic_uid,
  1660. X                            file_inode.ic_gid)) {
  1661. X                    fprintf(stderr,
  1662. X                        "Cannot set owner on %s: ",
  1663. X                        out_path);
  1664. X                    perror("");
  1665. X                }
  1666. X            }
  1667. X
  1668. X        }
  1669. X        next_ent += fs_dir->d_reclen;
  1670. X        } while (next_ent < buf_cnt);
  1671. X
  1672. X    } while (buf_cnt > 0);
  1673. X
  1674. X    /* Recursive (cp -R)? */
  1675. X    if (Rflag) {
  1676. X        /* Open directory again */
  1677. X    uopen(&fs_inode, &dir_ptr);
  1678. X
  1679. X        /* Read each directory block */
  1680. X    do {
  1681. X            /* Read next block of directory */
  1682. X        if ((buf_cnt = uread(&dir_ptr, dir_buf, BLKSIZE)) == -1) {
  1683. X            perror("Cannot read directory");
  1684. X            exit(1);
  1685. X        }
  1686. X
  1687. X        if (buf_cnt == 0)
  1688. X        break;
  1689. X
  1690. X            /* For each sub-directory in directory, restore it */
  1691. X        next_ent = 0;
  1692. X        do {
  1693. X            /* Point to next directory entry */
  1694. X        fs_dir = (struct direct *) &dir_buf[next_ent];
  1695. X
  1696. X            /* Directory entry here? */
  1697. X        if (fs_dir->d_ino != 0) {
  1698. X                /* Get inode */
  1699. X            get_inode(fs_dir->d_ino, &file_inode);
  1700. X
  1701. X
  1702. X                /* Make sure is dir and not . or .. */
  1703. X            if ((file_inode.ic_mode & IFMT) == IFDIR)
  1704. X                    if (strcmp(fs_dir->d_name, ".") &&
  1705. X                    strcmp(fs_dir->d_name, "..")) {
  1706. X
  1707. X                /* Make sure not restored yet */
  1708. X                if (in_idir(*idir_list, fs_dir->d_ino)) {
  1709. X                fprintf(stderr,
  1710. X                  "Already restored inum %d, directory: %s !\n",
  1711. X                    fs_dir->d_ino, from_path);
  1712. X                } else {
  1713. X                (void) strcpy(in_path, from_path);
  1714. X                (void) strcat(in_path, "/");
  1715. X                (void) strcat(in_path, fs_dir->d_name);
  1716. X                (void) strcpy(out_path, to_path);
  1717. X                (void) strcat(out_path, "/");
  1718. X                (void) strcat(out_path, fs_dir->d_name);
  1719. X
  1720. X                file_times[0].tv_sec = file_inode.ic_atime;
  1721. X                file_times[0].tv_usec = file_times[1].tv_usec
  1722. X                                    = 0;
  1723. X                file_times[1].tv_sec = file_inode.ic_mtime;
  1724. X
  1725. X                    /* Restore this directory! */
  1726. X                if (rrestore(in_path, fs_dir->d_ino, out_path,
  1727. X                        idir_list, Rflag, verbose))
  1728. X                    return -1;
  1729. X
  1730. X                    /* Set creation times on directory */
  1731. X                if (utimes(out_path, file_times)) {
  1732. X                    fprintf(stderr,
  1733. X                        "Cannot set creation times on %s: ",
  1734. X                        out_path);
  1735. X                    perror("");
  1736. X                }
  1737. X                }
  1738. X            }
  1739. X        }
  1740. X        next_ent += fs_dir->d_reclen;
  1741. X        } while (next_ent < buf_cnt);
  1742. X
  1743. X    } while (buf_cnt > 0);
  1744. X    }
  1745. X    return 0;
  1746. X}
  1747. X
  1748. Xrestore_all(Rflag, verbose)
  1749. Xchar    Rflag, verbose;
  1750. X{
  1751. X    struct    idir *idir_list, *restore_list, *idir_ptr, *restore_ptr;
  1752. X
  1753. X    ino_t    inum;
  1754. X    int    icnt = 0;
  1755. X    char    iname[MAX_PATH_LEN];
  1756. X
  1757. X    char     *sprintf();
  1758. X
  1759. X        /* Get list of directory inodes for filesystem */
  1760. X    get_dir_inodes(&idir_list, (ino_t) 2, (ino_t) sb.fs_ncg * sb.fs_ipg);
  1761. X
  1762. X        /* Make list of restored directory inodes */
  1763. X    new_idir(&restore_list);
  1764. X    idir_ptr = idir_list;
  1765. X    while (idir_ptr) {
  1766. X        inum = idir_ptr->inums[icnt];
  1767. X            /* Inode been restored? */
  1768. X        if (!in_idir(restore_list, inum)) {
  1769. X
  1770. X                /* Nope - create directory and restore */
  1771. X            (void) sprintf(iname, "i%d", inum);
  1772. X
  1773. X            if (verbose)
  1774. X                printf("Creating new base directory: %s\n",
  1775. X                    iname);
  1776. X            if (mkdir(iname, 0775)) {
  1777. X                fprintf(stderr,
  1778. X                    "Cannot create directory: %s; ",
  1779. X                    iname);
  1780. X                perror("");
  1781. X            }
  1782. X
  1783. X                /* Point to end of restored inode list */
  1784. X            restore_ptr = restore_list;
  1785. X            while(restore_ptr->next_idir)
  1786. X                restore_ptr = restore_ptr->next_idir;
  1787. X            
  1788. X                /* Append to end of restored inode list */
  1789. X            if (restore(iname, inum, iname, &restore_ptr,
  1790. X                        Rflag, verbose))
  1791. X                return -1;
  1792. X        }
  1793. X        if (++icnt == idir_ptr->icnt) {
  1794. X            icnt = 0;
  1795. X            idir_ptr = idir_ptr->next_idir;
  1796. X        }
  1797. X    }
  1798. X    return 0;
  1799. X}
  1800. SHAR_EOF
  1801. chmod 0644 restore.c || echo "restore of restore.c fails"
  1802. sed 's/^X//' << 'SHAR_EOF' > stat.c &&
  1803. X
  1804. X/*
  1805. X *     fssal - BSD file system salvage program
  1806. X *
  1807. X *     Copyright 1989, Robert Ankeney
  1808. X *                     Generic Computer Products
  1809. X *                     5315 S.W. 53rd Court
  1810. X *                     Portland, Oregon  97221
  1811. X *                     (503) 244-3699
  1812. X *     All Rights Reserved
  1813. X *
  1814. X *     Distribution of any portion of this software as part of any product
  1815. X *     for sale is prohibited.
  1816. X *
  1817. X *     Version 1.00 (Preliminary)
  1818. X */
  1819. X
  1820. X/*
  1821. X * stat.c
  1822. X *
  1823. X * load an inode into memory
  1824. X */
  1825. X
  1826. X# include    "fs.h"
  1827. X# include    <sys/stat.h>
  1828. X
  1829. Xextern struct fs    sb;
  1830. Xextern int        fs_fd;
  1831. X
  1832. Xfs_stat (inum, statb)
  1833. Xino_t        inum;
  1834. Xstruct stat    *statb;
  1835. X{
  1836. X    long    off;
  1837. X    struct    dinode di;
  1838. X
  1839. X    long    lseek();
  1840. X
  1841. X    off = itobo (inum);
  1842. X    (void) lseek (fs_fd, off, L_SET);
  1843. X    if (read (fs_fd, (char *) &di, sizeof (di)) != sizeof (di))
  1844. X        return -1;
  1845. X    statb->st_dev = 0;
  1846. X    statb->st_ino = inum;
  1847. X    statb->st_mode = di.di_mode;
  1848. X    statb->st_nlink = di.di_nlink;
  1849. X    statb->st_uid = di.di_uid;
  1850. X    statb->st_gid = di.di_gid;
  1851. X    statb->st_atime = di.di_atime;
  1852. X    statb->st_mtime = di.di_mtime;
  1853. X    statb->st_ctime = di.di_ctime;
  1854. X    statb->st_blocks = di.di_blocks;
  1855. X    return 0;
  1856. X}
  1857. SHAR_EOF
  1858. chmod 0644 stat.c || echo "restore of stat.c fails"
  1859. exit 0
  1860.