1 /*
2 * Copyright (c) 1981, 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1981, 1983, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)badsect.c 8.2 (Berkeley) 05/04/95";
16 #endif /* not lint */
17
18 /*
19 * badsect
20 *
21 * Badsect takes a list of file-system relative sector numbers
22 * and makes files containing the blocks of which these sectors are a part.
23 * It can be used to contain sectors which have problems if these sectors
24 * are not part of the bad file for the pack (see bad144). For instance,
25 * this program can be used if the driver for the file system in question
26 * does not support bad block forwarding.
27 */
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <sys/stat.h>
31
32 #include <ufs/ufs/dinode.h>
33 #include <ufs/ffs/fs.h>
34
35 #include <fcntl.h>
36 #include <paths.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40
41 union {
42 struct fs fs;
43 char fsx[SBSIZE];
44 } ufs;
45 #define sblock ufs.fs
46 union {
47 struct cg cg;
48 char cgx[MAXBSIZE];
49 } ucg;
50 #define acg ucg.cg
51 struct fs *fs;
52 int fso, fsi;
53 int errs;
54 long dev_bsize = 1;
55
56 char buf[MAXBSIZE];
57
58 void rdfs __P((daddr_t, int, char *));
59 int chkuse __P((daddr_t, int));
60
61 int
main(argc,argv)62 main(argc, argv)
63 int argc;
64 char *argv[];
65 {
66 daddr_t number;
67 struct stat stbuf, devstat;
68 register struct direct *dp;
69 DIR *dirp;
70 char name[BUFSIZ];
71
72 if (argc < 3) {
73 fprintf(stderr, "usage: badsect bbdir blkno [ blkno ]\n");
74 exit(1);
75 }
76 if (chdir(argv[1]) < 0 || stat(".", &stbuf) < 0) {
77 perror(argv[1]);
78 exit(2);
79 }
80 strcpy(name, _PATH_DEV);
81 if ((dirp = opendir(name)) == NULL) {
82 perror(name);
83 exit(3);
84 }
85 while ((dp = readdir(dirp)) != NULL) {
86 strcpy(&name[5], dp->d_name);
87 if (stat(name, &devstat) < 0) {
88 perror(name);
89 exit(4);
90 }
91 if (stbuf.st_dev == devstat.st_rdev &&
92 (devstat.st_mode & IFMT) == IFBLK)
93 break;
94 }
95 closedir(dirp);
96 if (dp == NULL) {
97 printf("Cannot find dev 0%o corresponding to %s\n",
98 stbuf.st_rdev, argv[1]);
99 exit(5);
100 }
101 if ((fsi = open(name, 0)) < 0) {
102 perror(name);
103 exit(6);
104 }
105 fs = &sblock;
106 rdfs(SBOFF, SBSIZE, (char *)fs);
107 dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
108 for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
109 number = atoi(*argv);
110 if (chkuse(number, 1))
111 continue;
112 if (mknod(*argv, IFMT|0600, dbtofsb(fs, number)) < 0) {
113 perror(*argv);
114 errs++;
115 }
116 }
117 printf("Don't forget to run ``fsck %s''\n", name);
118 exit(errs);
119 }
120
121 int
chkuse(blkno,cnt)122 chkuse(blkno, cnt)
123 daddr_t blkno;
124 int cnt;
125 {
126 int cg;
127 daddr_t fsbn, bn;
128
129 fsbn = dbtofsb(fs, blkno);
130 if ((unsigned)(fsbn+cnt) > fs->fs_size) {
131 printf("block %d out of range of file system\n", blkno);
132 return (1);
133 }
134 cg = dtog(fs, fsbn);
135 if (fsbn < cgdmin(fs, cg)) {
136 if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) {
137 printf("block %d in non-data area: cannot attach\n",
138 blkno);
139 return (1);
140 }
141 } else {
142 if ((fsbn+cnt) > cgbase(fs, cg+1)) {
143 printf("block %d in non-data area: cannot attach\n",
144 blkno);
145 return (1);
146 }
147 }
148 rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize,
149 (char *)&acg);
150 if (!cg_chkmagic(&acg)) {
151 fprintf(stderr, "cg %d: bad magic number\n", cg);
152 errs++;
153 return (1);
154 }
155 bn = dtogd(fs, fsbn);
156 if (isclr(cg_blksfree(&acg), bn))
157 printf("Warning: sector %d is in use\n", blkno);
158 return (0);
159 }
160
161 /*
162 * read a block from the file system
163 */
164 void
rdfs(bno,size,bf)165 rdfs(bno, size, bf)
166 daddr_t bno;
167 int size;
168 char *bf;
169 {
170 int n;
171
172 if (lseek(fsi, (off_t)bno * dev_bsize, SEEK_SET) < 0) {
173 printf("seek error: %ld\n", bno);
174 perror("rdfs");
175 exit(1);
176 }
177 n = read(fsi, bf, size);
178 if (n != size) {
179 printf("read error: %ld\n", bno);
180 perror("rdfs");
181 exit(1);
182 }
183 }
184