1 /* 2 * This program, created 2002-10-03 by Garrett A. Wollman 3 * <wollman@FreeBSD.org>, is in the public domain. Use at your own risk. 4 */ 5 6 #ifdef __FreeBSD__ 7 #include <sys/param.h> 8 9 #include <ufs/ufs/dinode.h> 10 #include <ufs/ffs/fs.h> 11 #else 12 #include "mini_ufs.h" 13 #endif 14 15 #include <err.h> 16 #include <fcntl.h> 17 #include <inttypes.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 static union { 24 char buf[SBLOCKSIZE]; 25 struct fs sblock; 26 } u; 27 28 int 29 main(int argc, char **argv) 30 { 31 off_t end, last1, last2; 32 size_t len; 33 ssize_t justread; 34 int fd; 35 char *ch; 36 char c; 37 intmax_t offset; 38 39 offset = 0; 40 while ((c = getopt(argc, argv, "o:")) != -1) { 41 switch (c) { 42 case 'o': 43 if (optarg[0] == '\0') 44 errx(1, "usage"); 45 offset = strtoimax(optarg, &ch, 10); 46 if (*ch != '\0' || offset < 0) 47 errx(1, "usage"); 48 offset -= offset % DEV_BSIZE; 49 break; 50 51 default: 52 errx(1, "usage"); 53 } 54 } 55 argc -= optind; 56 argv += optind; 57 58 if (argc != 1) 59 errx(1, "usage"); 60 61 fd = open(argv[0], O_RDONLY, 0); 62 if (fd < 0) 63 err(1, "%s", argv[0]); 64 65 if (offset != 0) { 66 end = lseek(fd, offset, SEEK_SET); 67 if (end == -1) 68 err(1, "%s", argv[0]); 69 } else { 70 end = 0; 71 } 72 len = 0; 73 last1 = last2 = -1; 74 75 while (1) { 76 justread = read(fd, &u.buf[len], DEV_BSIZE); 77 if (justread != DEV_BSIZE) { 78 if (justread == 0) { 79 printf("reached end-of-file at %jd\n", 80 (intmax_t)end); 81 exit (0); 82 } 83 if (justread < 0) 84 err(1, "read"); 85 errx(1, "short read %jd (wanted %d) at %jd", 86 (intmax_t)justread, DEV_BSIZE, (intmax_t)end); 87 } 88 len += DEV_BSIZE; 89 end += DEV_BSIZE; 90 if (len >= sizeof(struct fs)) { 91 offset = end - len; 92 93 if (u.sblock.fs_magic == FS_UFS1_MAGIC) { 94 intmax_t fsbegin = offset - SBLOCK_UFS1; 95 printf("Found UFS1 superblock at offset %jd, " 96 "block %jd\n", offset, 97 offset / DEV_BSIZE); 98 printf("Filesystem might begin at offset %jd, " 99 "block %jd\n", fsbegin, 100 fsbegin / DEV_BSIZE); 101 if (last1 >= 0) { 102 printf("%jd blocks from last guess\n", 103 fsbegin / DEV_BSIZE - last1); 104 } 105 last1 = fsbegin / DEV_BSIZE; 106 len -= DEV_BSIZE; 107 memmove(u.buf, &u.buf[DEV_BSIZE], len); 108 } else if (u.sblock.fs_magic == FS_UFS2_MAGIC) { 109 intmax_t fsbegin = offset - SBLOCK_UFS2; 110 printf("Found UFS2 superblock at offset %jd, " 111 "block %jd\n", offset, 112 offset / DEV_BSIZE); 113 printf("Filesystem might begin at offset %jd, " 114 "block %jd\n", fsbegin, 115 fsbegin / DEV_BSIZE); 116 if (last2 >= 0) { 117 printf("%jd blocks from last guess\n", 118 fsbegin / DEV_BSIZE - last2); 119 } 120 last2 = fsbegin / DEV_BSIZE; 121 len -= DEV_BSIZE; 122 memmove(u.buf, &u.buf[DEV_BSIZE], len); 123 } 124 } 125 if (len >= SBLOCKSIZE) { 126 memmove(u.buf, &u.buf[DEV_BSIZE], 127 SBLOCKSIZE - DEV_BSIZE); 128 len -= DEV_BSIZE; 129 } 130 } 131 } 132