| @@ -1,268 +1,268 @@ | | | @@ -1,268 +1,268 @@ |
1 | /* $NetBSD: badsect.c,v 1.31 2008/12/29 16:03:57 christos Exp $ */ | | 1 | /* $NetBSD: badsect.c,v 1.32 2009/03/16 12:53:30 lukem Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1981, 1983, 1993 | | 4 | * Copyright (c) 1981, 1983, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the name of the University nor the names of its contributors | | 15 | * 3. Neither the name of the University nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | __COPYRIGHT("@(#) Copyright (c) 1981, 1983, 1993\ | | 34 | __COPYRIGHT("@(#) Copyright (c) 1981, 1983, 1993\ |
35 | The Regents of the University of California. All rights reserved."); | | 35 | The Regents of the University of California. All rights reserved."); |
36 | #endif /* not lint */ | | 36 | #endif /* not lint */ |
37 | | | 37 | |
38 | #ifndef lint | | 38 | #ifndef lint |
39 | #if 0 | | 39 | #if 0 |
40 | static char sccsid[] = "@(#)badsect.c 8.2 (Berkeley) 5/4/95"; | | 40 | static char sccsid[] = "@(#)badsect.c 8.2 (Berkeley) 5/4/95"; |
41 | #else | | 41 | #else |
42 | __RCSID("$NetBSD: badsect.c,v 1.31 2008/12/29 16:03:57 christos Exp $"); | | 42 | __RCSID("$NetBSD: badsect.c,v 1.32 2009/03/16 12:53:30 lukem Exp $"); |
43 | #endif | | 43 | #endif |
44 | #endif /* not lint */ | | 44 | #endif /* not lint */ |
45 | | | 45 | |
46 | /* | | 46 | /* |
47 | * badsect | | 47 | * badsect |
48 | * | | 48 | * |
49 | * Badsect takes a list of file-system relative sector numbers | | 49 | * Badsect takes a list of file-system relative sector numbers |
50 | * and makes files containing the blocks of which these sectors are a part. | | 50 | * and makes files containing the blocks of which these sectors are a part. |
51 | * It can be used to contain sectors which have problems if these sectors | | 51 | * It can be used to contain sectors which have problems if these sectors |
52 | * are not part of the bad file for the pack (see bad144). For instance, | | 52 | * are not part of the bad file for the pack (see bad144). For instance, |
53 | * this program can be used if the driver for the file system in question | | 53 | * this program can be used if the driver for the file system in question |
54 | * does not support bad block forwarding. | | 54 | * does not support bad block forwarding. |
55 | */ | | 55 | */ |
56 | #include <sys/param.h> | | 56 | #include <sys/param.h> |
57 | #include <sys/dir.h> | | 57 | #include <sys/dir.h> |
58 | #include <sys/stat.h> | | 58 | #include <sys/stat.h> |
59 | | | 59 | |
60 | #include <ufs/ufs/dinode.h> | | 60 | #include <ufs/ufs/dinode.h> |
61 | #include <ufs/ufs/ufs_bswap.h> | | 61 | #include <ufs/ufs/ufs_bswap.h> |
62 | #include <ufs/ffs/fs.h> | | 62 | #include <ufs/ffs/fs.h> |
63 | #include <ufs/ffs/ffs_extern.h> | | 63 | #include <ufs/ffs/ffs_extern.h> |
64 | | | 64 | |
65 | #include <fcntl.h> | | 65 | #include <fcntl.h> |
66 | #include <paths.h> | | 66 | #include <paths.h> |
67 | #include <stdio.h> | | 67 | #include <stdio.h> |
68 | #include <stdlib.h> | | 68 | #include <stdlib.h> |
69 | #include <string.h> | | 69 | #include <string.h> |
70 | #include <unistd.h> | | 70 | #include <unistd.h> |
71 | #include <err.h> | | 71 | #include <err.h> |
72 | | | 72 | |
73 | static union { | | 73 | static union { |
74 | struct fs fs; | | 74 | struct fs fs; |
75 | char fsx[SBLOCKSIZE]; | | 75 | char fsx[SBLOCKSIZE]; |
76 | } ufs; | | 76 | } ufs; |
77 | #define sblock ufs.fs | | 77 | #define sblock ufs.fs |
78 | static union { | | 78 | static union { |
79 | struct cg cg; | | 79 | struct cg cg; |
80 | char cgx[MAXBSIZE]; | | 80 | char cgx[MAXBSIZE]; |
81 | } ucg; | | 81 | } ucg; |
82 | #define acg ucg.cg | | 82 | #define acg ucg.cg |
83 | static struct fs *fs; | | 83 | static struct fs *fs; |
84 | static int fsi; | | 84 | static int fsi; |
85 | static int errs; | | 85 | static int errs; |
86 | static off_t dev_bsize = 1; | | 86 | static off_t dev_bsize = 1; |
87 | static int needswap = 0; | | 87 | static int needswap = 0; |
88 | static int is_ufs2; | | 88 | static int is_ufs2; |
89 | | | 89 | |
90 | static void rdfs(off_t, size_t, void *); | | 90 | static void rdfs(off_t, size_t, void *); |
91 | static int chkuse(daddr_t, int); | | 91 | static int chkuse(daddr_t, int); |
92 | | | 92 | |
93 | int main(int, char *[]); | | 93 | int main(int, char *[]); |
94 | | | 94 | |
95 | static const off_t sblock_try[] = SBLOCKSEARCH; | | 95 | static const off_t sblock_try[] = SBLOCKSEARCH; |
96 | | | 96 | |
97 | int | | 97 | int |
98 | main(int argc, char *argv[]) | | 98 | main(int argc, char *argv[]) |
99 | { | | 99 | { |
100 | daddr_t number; | | 100 | daddr_t number; |
101 | struct stat stbuf, devstat; | | 101 | struct stat stbuf, devstat; |
102 | struct direct *dp; | | 102 | struct direct *dp; |
103 | int i, did = 0; | | 103 | int i, did = 0; |
104 | DIR *dirp; | | 104 | DIR *dirp; |
105 | char name[MAXPATHLEN]; | | 105 | char name[MAXPATHLEN]; |
106 | size_t dl = sizeof(_PATH_DEV); | | 106 | size_t dl = sizeof(_PATH_DEV); |
107 | | | 107 | |
108 | if (argc < 3) { | | 108 | if (argc < 3) { |
109 | (void)fprintf(stderr, "usage: %s bbdir blkno [ blkno ]\n", | | 109 | (void)fprintf(stderr, "usage: %s bbdir blkno [ blkno ]\n", |
110 | getprogname()); | | 110 | getprogname()); |
111 | exit(1); | | 111 | exit(1); |
112 | } | | 112 | } |
113 | if (chdir(argv[1]) == -1) | | 113 | if (chdir(argv[1]) == -1) |
114 | err(1, "Cannot change directory to `%s'", argv[1]); | | 114 | err(1, "Cannot change directory to `%s'", argv[1]); |
115 | | | 115 | |
116 | if (stat(".", &stbuf) == -1) | | 116 | if (stat(".", &stbuf) == -1) |
117 | err(1, "Cannot stat `%s'", argv[1]); | | 117 | err(1, "Cannot stat `%s'", argv[1]); |
118 | | | 118 | |
119 | (void)strlcpy(name, _PATH_DEV, sizeof(name)); | | 119 | (void)strlcpy(name, _PATH_DEV, sizeof(name)); |
120 | if ((dirp = opendir(name)) == NULL) | | 120 | if ((dirp = opendir(name)) == NULL) |
121 | err(1, "Cannot opendir `%s'", argv[1]); | | 121 | err(1, "Cannot opendir `%s'", argv[1]); |
122 | | | 122 | |
123 | while ((dp = readdir(dirp)) != NULL) { | | 123 | while ((dp = readdir(dirp)) != NULL) { |
124 | (void)strlcpy(name + dl - 1, dp->d_name, sizeof(name) - dl + 1); | | 124 | (void)strlcpy(name + dl - 1, dp->d_name, sizeof(name) - dl + 1); |
125 | if (stat(name, &devstat) == -1) | | 125 | if (stat(name, &devstat) == -1) |
126 | err(1, "Cannot stat `%s'", name); | | 126 | err(1, "Cannot stat `%s'", name); |
127 | if (stbuf.st_dev == devstat.st_rdev && | | 127 | if (stbuf.st_dev == devstat.st_rdev && |
128 | S_ISBLK(devstat.st_mode)) | | 128 | S_ISBLK(devstat.st_mode)) |
129 | break; | | 129 | break; |
130 | } | | 130 | } |
131 | | | 131 | |
132 | if (dp == NULL) | | 132 | if (dp == NULL) |
133 | errx(1, "Cannot find dev 0%llo corresponding to %s", | | 133 | errx(1, "Cannot find dev 0%llo corresponding to %s", |
134 | (long long)stbuf.st_rdev, argv[1]); | | 134 | (long long)stbuf.st_rdev, argv[1]); |
135 | | | 135 | |
136 | /* | | 136 | /* |
137 | * The filesystem is mounted; use the character device instead. | | 137 | * The filesystem is mounted; use the character device instead. |
138 | * XXX - Assume that prepending an `r' will give us the name of | | 138 | * XXX - Assume that prepending an `r' will give us the name of |
139 | * the character device. | | 139 | * the character device. |
140 | */ | | 140 | */ |
141 | name[dl - 1] = 'r'; | | 141 | name[dl - 1] = 'r'; |
142 | (void)strlcpy(name + dl, dp->d_name, sizeof(name) - dl); | | 142 | (void)strlcpy(name + dl, dp->d_name, sizeof(name) - dl); |
143 | (void)closedir(dirp); /* now *dp is invalid */ | | 143 | (void)closedir(dirp); /* now *dp is invalid */ |
144 | | | 144 | |
145 | if ((fsi = open(name, O_RDONLY)) == -1) | | 145 | if ((fsi = open(name, O_RDONLY)) == -1) |
146 | err(1, "Cannot open `%s'", argv[1]); | | 146 | err(1, "Cannot open `%s'", argv[1]); |
147 | | | 147 | |
148 | fs = &sblock; | | 148 | fs = &sblock; |
149 | | | 149 | |
150 | for (i = 0; ; i++) { | | 150 | for (i = 0; ; i++) { |
151 | if (sblock_try[i] == -1) | | 151 | if (sblock_try[i] == -1) |
152 | errx(1, "%s: bad superblock", name); | | 152 | errx(1, "%s: bad superblock", name); |
153 | rdfs(sblock_try[i], SBLOCKSIZE, fs); | | 153 | rdfs(sblock_try[i], SBLOCKSIZE, fs); |
154 | switch (fs->fs_magic) { | | 154 | switch (fs->fs_magic) { |
155 | case FS_UFS2_MAGIC: | | 155 | case FS_UFS2_MAGIC: |
156 | is_ufs2 = 1; | | 156 | is_ufs2 = 1; |
157 | /* FALLTHROUGH */ | | 157 | /* FALLTHROUGH */ |
158 | case FS_UFS1_MAGIC: | | 158 | case FS_UFS1_MAGIC: |
159 | break; | | 159 | break; |
160 | case FS_UFS2_MAGIC_SWAPPED: | | 160 | case FS_UFS2_MAGIC_SWAPPED: |
161 | is_ufs2 = 1; | | 161 | is_ufs2 = 1; |
162 | /* FALLTHROUGH */ | | 162 | /* FALLTHROUGH */ |
163 | case FS_UFS1_MAGIC_SWAPPED: | | 163 | case FS_UFS1_MAGIC_SWAPPED: |
164 | needswap = 1; | | 164 | needswap = 1; |
165 | ffs_sb_swap(fs, fs); | | 165 | ffs_sb_swap(fs, fs); |
166 | break; | | 166 | break; |
167 | default: | | 167 | default: |
168 | continue; | | 168 | continue; |
169 | } | | 169 | } |
170 | | | 170 | |
171 | /* Ensure we don't use 1st alternate if ffsv1 and bs=64k */ | | 171 | /* Ensure we don't use 1st alternate if ffsv1 and bs=64k */ |
172 | if (is_ufs2 || fs->fs_old_flags & FS_FLAGS_UPDATED) { | | 172 | if (is_ufs2 || fs->fs_old_flags & FS_FLAGS_UPDATED) { |
173 | if (fs->fs_sblockloc != sblock_try[i]) | | 173 | if (fs->fs_sblockloc != sblock_try[i]) |
174 | continue; | | 174 | continue; |
175 | } else { | | 175 | } else { |
176 | if (sblock_try[i] == SBLOCK_UFS2) | | 176 | if (sblock_try[i] == SBLOCK_UFS2) |
177 | continue; | | 177 | continue; |
178 | } | | 178 | } |
179 | break; | | 179 | break; |
180 | } | | 180 | } |
181 | | | 181 | |
182 | dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); | | 182 | dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); |
183 | for (argc -= 2, argv += 2; argc > 0; argc--, argv++) { | | 183 | for (argc -= 2, argv += 2; argc > 0; argc--, argv++) { |
184 | number = atoi(*argv); | | 184 | number = atoi(*argv); |
185 | if (chkuse(number, 1)) | | 185 | if (chkuse(number, 1)) |
186 | continue; | | 186 | continue; |
187 | if (mknod(*argv, S_IFMT|S_IRUSR|S_IWUSR, | | 187 | if (mknod(*argv, S_IFMT|S_IRUSR|S_IWUSR, |
188 | (dev_t)dbtofsb(fs, number)) == -1) { | | 188 | (dev_t)dbtofsb(fs, number)) == -1) { |
189 | warn("Cannot mknod `%s'", *argv); | | 189 | warn("Cannot mknod `%s'", *argv); |
190 | errs++; | | 190 | errs++; |
191 | continue; | | 191 | continue; |
192 | } | | 192 | } |
193 | did++; | | 193 | did++; |
194 | } | | 194 | } |
195 | | | 195 | |
196 | if (did) | | 196 | if (did) |
197 | warnx("Don't forget to run `fsck %s'", name); | | 197 | warnx("Don't forget to run `fsck %s'", name); |
198 | else | | 198 | else |
199 | warnx("File system `%s' was not modified", name); | | 199 | warnx("File system `%s' was not modified", name); |
200 | return errs; | | 200 | return errs; |
201 | } | | 201 | } |
202 | | | 202 | |
203 | static int | | 203 | static int |
204 | chkuse(off_t blkno, int cnt) | | 204 | chkuse(off_t blkno, int cnt) |
205 | { | | 205 | { |
206 | int cg; | | 206 | int cg; |
207 | off_t fsbn, bn, fsbe; | | 207 | off_t fsbn, bn, fsbe; |
208 | | | 208 | |
209 | fsbn = dbtofsb(fs, blkno); | | 209 | fsbn = dbtofsb(fs, blkno); |
210 | fsbe = fsbn + cnt; | | 210 | fsbe = fsbn + cnt; |
211 | if (fsbe > fs->fs_size) { | | 211 | if (fsbe > fs->fs_size) { |
212 | warnx("block %lld out of range of file system", | | 212 | warnx("block %lld out of range of file system", |
213 | (long long)blkno); | | 213 | (long long)blkno); |
214 | return 1; | | 214 | return 1; |
215 | } | | 215 | } |
216 | | | 216 | |
217 | cg = (int)dtog(fs, fsbn); | | 217 | cg = (int)dtog(fs, fsbn); |
218 | if (fsbn < cgdmin(fs, cg)) { | | 218 | if (fsbn < cgdmin(fs, cg)) { |
219 | if (cg == 0 || fsbe > cgsblock(fs, cg)) { | | 219 | if (cg == 0 || fsbe > cgsblock(fs, cg)) { |
220 | warnx("block %lld in superblock area: cannot attach", | | 220 | warnx("block %lld in superblock area: cannot attach", |
221 | (long long)blkno); | | 221 | (long long)blkno); |
222 | return 1; | | 222 | return 1; |
223 | } | | 223 | } |
224 | } else { | | 224 | } else { |
225 | if (fsbe > cgbase(fs, cg + 1)) { | | 225 | if (fsbe > cgbase(fs, cg + 1)) { |
226 | warnx("block %lld in beyond end of cylinder group: " | | 226 | warnx("block %lld in beyond end of cylinder group: " |
227 | "cannot attach", (long long)blkno); | | 227 | "cannot attach", (long long)blkno); |
228 | return 1; | | 228 | return 1; |
229 | } | | 229 | } |
230 | } | | 230 | } |
231 | | | 231 | |
232 | rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize, &acg); | | 232 | rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize, &acg); |
233 | | | 233 | |
234 | if (!cg_chkmagic(&acg, needswap)) { | | 234 | if (!cg_chkmagic(&acg, needswap)) { |
235 | warnx("cg %d: bad magic number", cg); | | 235 | warnx("cg %d: bad magic number", cg); |
236 | errs++; | | 236 | errs++; |
237 | return 1; | | 237 | return 1; |
238 | } | | 238 | } |
239 | | | 239 | |
240 | bn = dtogd(fs, fsbn); | | 240 | bn = dtogd(fs, fsbn); |
241 | if (isclr(cg_blksfree(&acg, needswap), bn)) | | 241 | if (isclr(cg_blksfree(&acg, needswap), bn)) |
242 | warnx("Warning: sector %lld is in use", (long long)blkno); | | 242 | warnx("Warning: sector %lld is in use", (long long)blkno); |
243 | | | 243 | |
244 | return 0; | | 244 | return 0; |
245 | } | | 245 | } |
246 | | | 246 | |
247 | /* | | 247 | /* |
248 | * read a block from the file system | | 248 | * read a block from the file system |
249 | */ | | 249 | */ |
250 | static void | | 250 | static void |
251 | rdfs(off_t bno, size_t size, void *bf) | | 251 | rdfs(off_t bno, size_t size, void *bf) |
252 | { | | 252 | { |
253 | int n; | | 253 | ssize_t n; |
254 | | | 254 | |
255 | if (lseek(fsi, bno * dev_bsize, SEEK_SET) == -1) | | 255 | if (lseek(fsi, bno * dev_bsize, SEEK_SET) == -1) |
256 | err(1, "seek error at block %lld", (long long)bno); | | 256 | err(1, "seek error at block %lld", (long long)bno); |
257 | | | 257 | |
258 | switch (n = read(fsi, bf, size)) { | | 258 | switch (n = read(fsi, bf, size)) { |
259 | case -1: | | 259 | case -1: |
260 | err(1, "read error at block %lld", (long long)bno); | | 260 | err(1, "read error at block %lld", (long long)bno); |
261 | break; | | 261 | break; |
262 | | | 262 | |
263 | default: | | 263 | default: |
264 | if (n == size) | | 264 | if ((size_t)n == size) |
265 | return; | | 265 | return; |
266 | errx(1, "incomplete read at block %lld", (long long)bno); | | 266 | errx(1, "incomplete read at block %lld", (long long)bno); |
267 | } | | 267 | } |
268 | } | | 268 | } |