badsect.c revision 98542
1238104Sdes/* 2238104Sdes * Copyright (c) 1981, 1983, 1993 3238104Sdes * The Regents of the University of California. All rights reserved. 4238104Sdes * 5238104Sdes * Redistribution and use in source and binary forms, with or without 6238104Sdes * modification, are permitted provided that the following conditions 7238104Sdes * are met: 8238104Sdes * 1. Redistributions of source code must retain the above copyright 9238104Sdes * notice, this list of conditions and the following disclaimer. 10238104Sdes * 2. Redistributions in binary form must reproduce the above copyright 11238104Sdes * notice, this list of conditions and the following disclaimer in the 12238104Sdes * documentation and/or other materials provided with the distribution. 13238104Sdes * 3. All advertising materials mentioning features or use of this software 14238104Sdes * must display the following acknowledgement: 15238104Sdes * This product includes software developed by the University of 16238104Sdes * California, Berkeley and its contributors. 17238104Sdes * 4. Neither the name of the University nor the names of its contributors 18238104Sdes * may be used to endorse or promote products derived from this software 19238104Sdes * without specific prior written permission. 20238104Sdes * 21238104Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22238104Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23238104Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24238104Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25238104Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26238104Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27238104Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28238104Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29238104Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30238104Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31238104Sdes * SUCH DAMAGE. 32238104Sdes */ 33238104Sdes 34238104Sdes#ifndef lint 35238104Sdesstatic const char copyright[] = 36238104Sdes"@(#) Copyright (c) 1981, 1983, 1993\n\ 37238104Sdes The Regents of the University of California. All rights reserved.\n"; 38238104Sdes#endif /* not lint */ 39238104Sdes 40238104Sdes#ifndef lint 41238104Sdes#if 0 42238104Sdesstatic const char sccsid[] = "@(#)badsect.c 8.1 (Berkeley) 6/5/93"; 43238104Sdes#endif 44238104Sdesstatic const char rcsid[] = 45238104Sdes "$FreeBSD: head/sbin/badsect/badsect.c 98542 2002-06-21 06:18:05Z mckusick $"; 46238104Sdes#endif /* not lint */ 47238104Sdes 48238104Sdes/* 49238104Sdes * badsect 50238104Sdes * 51238104Sdes * Badsect takes a list of file-system relative sector numbers 52238104Sdes * and makes files containing the blocks of which these sectors are a part. 53238104Sdes * It can be used to contain sectors which have problems if these sectors 54238104Sdes * are not part of the bad file for the pack (see bad144). For instance, 55238104Sdes * this program can be used if the driver for the filesystem in question 56238104Sdes * does not support bad block forwarding. 57238104Sdes */ 58238104Sdes#include <sys/param.h> 59238104Sdes#include <sys/stat.h> 60238104Sdes#include <sys/disklabel.h> 61238104Sdes 62238104Sdes#include <ufs/ufs/dinode.h> 63238104Sdes#include <ufs/ffs/fs.h> 64238104Sdes 65238104Sdes#include <err.h> 66238104Sdes#include <dirent.h> 67238104Sdes#include <fcntl.h> 68238104Sdes#include <paths.h> 69238104Sdes#include <stdio.h> 70238104Sdes#include <stdlib.h> 71238104Sdes#include <string.h> 72238104Sdes#include <unistd.h> 73238104Sdes 74238104Sdesunion { 75238104Sdes struct fs fs; 76238104Sdes char fsx[SBLOCKSIZE]; 77238104Sdes} ufs; 78238104Sdes#define sblock ufs.fs 79238104Sdesunion { 80238104Sdes struct cg cg; 81238104Sdes char cgx[MAXBSIZE]; 82238104Sdes} ucg; 83238104Sdes#define acg ucg.cg 84238104Sdesstruct fs *fs; 85238104Sdesint fso, fsi; 86238104Sdesint errs; 87238104Sdeslong dev_bsize = 1; 88238104Sdes 89238104Sdeschar buf[MAXBSIZE]; 90238104Sdes 91238104Sdesvoid rdfs(daddr_t, int, char *); 92238104Sdesint chkuse(daddr_t, int); 93238104Sdes 94238104Sdes/* 95238104Sdes * Possible superblock locations ordered from most to least likely. 96238104Sdes */ 97238104Sdesstatic int sblock_try[] = SBLOCKSEARCH; 98238104Sdes 99238104Sdesstatic void 100238104Sdesusage(void) 101238104Sdes{ 102238104Sdes fprintf(stderr, "usage: badsect bbdir blkno ...\n"); 103238104Sdes exit(1); 104238104Sdes} 105238104Sdes 106238104Sdesint 107238104Sdesmain(int argc, char *argv[]) 108238104Sdes{ 109238104Sdes daddr_t diskbn; 110238104Sdes daddr_t number; 111238104Sdes struct stat stbuf, devstat; 112238104Sdes struct dirent *dp; 113238104Sdes DIR *dirp; 114238104Sdes char name[2 * MAXPATHLEN]; 115238104Sdes char *name_dir_end; 116238104Sdes int i; 117238104Sdes 118238104Sdes if (argc < 3) 119238104Sdes usage(); 120238104Sdes if (chdir(argv[1]) < 0 || stat(".", &stbuf) < 0) 121238104Sdes err(2, "%s", argv[1]); 122238104Sdes strcpy(name, _PATH_DEV); 123238104Sdes if ((dirp = opendir(name)) == NULL) 124238104Sdes err(3, "%s", name); 125238104Sdes name_dir_end = name + strlen(name); 126238104Sdes while ((dp = readdir(dirp)) != NULL) { 127238104Sdes strcpy(name_dir_end, dp->d_name); 128238104Sdes if (lstat(name, &devstat) < 0) 129238104Sdes err(4, "%s", name); 130238104Sdes if (stbuf.st_dev == devstat.st_rdev && 131238104Sdes (devstat.st_mode & IFMT) == IFCHR) 132238104Sdes break; 133238104Sdes } 134238104Sdes closedir(dirp); 135238104Sdes if (dp == NULL) { 136238104Sdes printf("Cannot find dev 0%lo corresponding to %s\n", 137238104Sdes (u_long)stbuf.st_rdev, argv[1]); 138238104Sdes exit(5); 139238104Sdes } 140238104Sdes if ((fsi = open(name, O_RDONLY)) < 0) 141238104Sdes err(6, "%s", name); 142238104Sdes fs = &sblock; 143238104Sdes for (i = 0; sblock_try[i] != -1; i++) { 144238104Sdes rdfs(sblock_try[i] / dev_bsize, SBLOCKSIZE, (char *)fs); 145238104Sdes if ((fs->fs_magic == FS_UFS1_MAGIC || 146238104Sdes (fs->fs_magic == FS_UFS2_MAGIC && 147238104Sdes fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) && 148238104Sdes fs->fs_bsize <= MAXBSIZE && 149238104Sdes fs->fs_bsize >= sizeof(struct fs)) 150238104Sdes break; 151238104Sdes } 152238104Sdes if (sblock_try[i] == -1) { 153238104Sdes printf("Cannot find filesystem\n"); 154238104Sdes exit(7); 155238104Sdes } 156238104Sdes dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 157238104Sdes for (argc -= 2, argv += 2; argc > 0; argc--, argv++) { 158238104Sdes number = atol(*argv); 159238104Sdes if (chkuse(number, 1)) 160238104Sdes continue; 161238104Sdes /* 162238104Sdes * Print a warning if converting the block number to a dev_t 163238104Sdes * will truncate it. badsect was not very useful in versions 164238104Sdes * of BSD before 4.4 because dev_t was 16 bits and another 165238104Sdes * bit was lost by bogus sign extensions. 166238104Sdes */ 167238104Sdes diskbn = dbtofsb(fs, number); 168238104Sdes if ((dev_t)diskbn != diskbn) { 169238104Sdes printf("sector %ld cannot be represented as a dev_t\n", 170238104Sdes (long)number); 171238104Sdes errs++; 172238104Sdes } 173238104Sdes else if (mknod(*argv, IFMT|0600, (dev_t)diskbn) < 0) { 174238104Sdes warn("%s", *argv); 175238104Sdes errs++; 176238104Sdes } 177238104Sdes } 178238104Sdes printf("Don't forget to run ``fsck %s''\n", name); 179238104Sdes exit(errs); 180238104Sdes} 181238104Sdes 182238104Sdesint 183238104Sdeschkuse(daddr_t blkno, int cnt) 184238104Sdes{ 185238104Sdes int cg; 186238104Sdes daddr_t fsbn, bn; 187238104Sdes 188238104Sdes fsbn = dbtofsb(fs, blkno); 189238104Sdes if ((unsigned)(fsbn+cnt) > fs->fs_size) { 190238104Sdes printf("block %ld out of range of filesystem\n", (long)blkno); 191238104Sdes return (1); 192238104Sdes } 193238104Sdes cg = dtog(fs, fsbn); 194238104Sdes if (fsbn < cgdmin(fs, cg)) { 195238104Sdes if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) { 196238104Sdes printf("block %ld in non-data area: cannot attach\n", 197238104Sdes (long)blkno); 198238104Sdes return (1); 199238104Sdes } 200238104Sdes } else { 201238104Sdes if ((fsbn+cnt) > cgbase(fs, cg+1)) { 202238104Sdes printf("block %ld in non-data area: cannot attach\n", 203238104Sdes (long)blkno); 204238104Sdes return (1); 205238104Sdes } 206238104Sdes } 207238104Sdes rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize, 208238104Sdes (char *)&acg); 209238104Sdes if (!cg_chkmagic(&acg)) { 210238104Sdes fprintf(stderr, "cg %d: bad magic number\n", cg); 211238104Sdes errs++; 212238104Sdes return (1); 213238104Sdes } 214238104Sdes bn = dtogd(fs, fsbn); 215238104Sdes if (isclr(cg_blksfree(&acg), bn)) 216238104Sdes printf("Warning: sector %ld is in use\n", (long)blkno); 217238104Sdes return (0); 218238104Sdes} 219238104Sdes 220238104Sdes/* 221238104Sdes * read a block from the filesystem 222238104Sdes */ 223238104Sdesvoid 224238104Sdesrdfs(daddr_t bno, int size, char *bf) 225238104Sdes{ 226238104Sdes int n; 227238104Sdes 228238104Sdes if (lseek(fsi, (off_t)bno * dev_bsize, SEEK_SET) < 0) { 229238104Sdes printf("seek error: %ld\n", (long)bno); 230238104Sdes err(1, "rdfs"); 231 } 232 n = read(fsi, bf, size); 233 if (n != size) { 234 printf("read error: %ld\n", (long)bno); 235 err(1, "rdfs"); 236 } 237} 238