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