Home | History | Annotate | Line # | Download | only in badsect
badsect.c revision 1.17.8.1
      1  1.17.8.1        he /*	$NetBSD: badsect.c,v 1.17.8.1 2001/11/25 19:24:43 he 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.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16       1.1       cgd  *    must display the following acknowledgement:
     17       1.1       cgd  *	This product includes software developed by the University of
     18       1.1       cgd  *	California, Berkeley and its contributors.
     19       1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20       1.1       cgd  *    may be used to endorse or promote products derived from this software
     21       1.1       cgd  *    without specific prior written permission.
     22       1.1       cgd  *
     23       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33       1.1       cgd  * SUCH DAMAGE.
     34       1.1       cgd  */
     35       1.1       cgd 
     36      1.12  christos #include <sys/cdefs.h>
     37       1.1       cgd #ifndef lint
     38      1.12  christos __COPYRIGHT("@(#) Copyright (c) 1981, 1983, 1993\n\
     39      1.12  christos 	The Regents of the University of California.  All rights reserved.\n");
     40       1.1       cgd #endif /* not lint */
     41       1.1       cgd 
     42       1.1       cgd #ifndef lint
     43      1.10       cgd #if 0
     44      1.14     lukem static char sccsid[] = "@(#)badsect.c	8.2 (Berkeley) 5/4/95";
     45      1.10       cgd #else
     46  1.17.8.1        he __RCSID("$NetBSD: badsect.c,v 1.17.8.1 2001/11/25 19:24:43 he Exp $");
     47      1.10       cgd #endif
     48       1.1       cgd #endif /* not lint */
     49       1.1       cgd 
     50       1.1       cgd /*
     51       1.1       cgd  * badsect
     52       1.1       cgd  *
     53       1.1       cgd  * Badsect takes a list of file-system relative sector numbers
     54       1.1       cgd  * and makes files containing the blocks of which these sectors are a part.
     55       1.1       cgd  * It can be used to contain sectors which have problems if these sectors
     56       1.1       cgd  * are not part of the bad file for the pack (see bad144).  For instance,
     57       1.1       cgd  * this program can be used if the driver for the file system in question
     58       1.1       cgd  * does not support bad block forwarding.
     59       1.1       cgd  */
     60       1.1       cgd #include <sys/param.h>
     61       1.6        pk #include <sys/dir.h>
     62       1.1       cgd #include <sys/stat.h>
     63       1.6        pk 
     64      1.14     lukem #include <ufs/ufs/dinode.h>
     65      1.15    bouyer #include <ufs/ufs/ufs_bswap.h>
     66       1.6        pk #include <ufs/ffs/fs.h>
     67      1.15    bouyer #include <ufs/ffs/ffs_extern.h>
     68       1.6        pk 
     69       1.6        pk #include <fcntl.h>
     70       1.6        pk #include <paths.h>
     71       1.1       cgd #include <stdio.h>
     72       1.6        pk #include <stdlib.h>
     73       1.8       cgd #include <string.h>
     74       1.6        pk #include <unistd.h>
     75      1.12  christos #include <err.h>
     76       1.1       cgd 
     77       1.1       cgd union {
     78       1.1       cgd 	struct	fs fs;
     79       1.1       cgd 	char	fsx[SBSIZE];
     80       1.1       cgd } ufs;
     81       1.1       cgd #define sblock	ufs.fs
     82       1.1       cgd union {
     83       1.1       cgd 	struct	cg cg;
     84       1.1       cgd 	char	cgx[MAXBSIZE];
     85       1.1       cgd } ucg;
     86       1.1       cgd #define	acg	ucg.cg
     87       1.1       cgd struct	fs *fs;
     88       1.1       cgd int	fso, fsi;
     89       1.1       cgd int	errs;
     90       1.1       cgd long	dev_bsize = 1;
     91      1.15    bouyer int needswap = 0;
     92       1.1       cgd 
     93       1.1       cgd char buf[MAXBSIZE];
     94       1.1       cgd 
     95       1.6        pk void	rdfs __P((daddr_t, int, char *));
     96       1.6        pk int	chkuse __P((daddr_t, int));
     97      1.12  christos int	main __P((int, char *[]));
     98       1.1       cgd 
     99       1.6        pk int
    100       1.1       cgd main(argc, argv)
    101       1.1       cgd 	int argc;
    102       1.1       cgd 	char *argv[];
    103       1.1       cgd {
    104       1.1       cgd 	daddr_t number;
    105       1.1       cgd 	struct stat stbuf, devstat;
    106      1.13     lukem 	struct direct *dp;
    107       1.1       cgd 	DIR *dirp;
    108      1.12  christos 	char name[MAXPATHLEN];
    109      1.12  christos 	extern char *__progname;
    110       1.1       cgd 
    111       1.1       cgd 	if (argc < 3) {
    112      1.12  christos 		(void) fprintf(stderr, "Usage: %s bbdir blkno [ blkno ]\n",
    113      1.12  christos 		    __progname);
    114       1.1       cgd 		exit(1);
    115       1.1       cgd 	}
    116      1.12  christos 	if (chdir(argv[1]) == -1)
    117      1.12  christos 		err(1, "Cannot change directory to `%s'", argv[1]);
    118      1.12  christos 
    119      1.12  christos 	if (stat(".", &stbuf) == -1)
    120      1.12  christos 		err(1, "Cannot stat `%s'", argv[1]);
    121      1.12  christos 
    122      1.12  christos 	(void) strcpy(name, _PATH_DEV);
    123      1.12  christos 	if ((dirp = opendir(name)) == NULL)
    124      1.12  christos 		err(1, "Cannot opendir `%s'", argv[1]);
    125      1.11    scottr 
    126       1.1       cgd 	while ((dp = readdir(dirp)) != NULL) {
    127      1.12  christos 		(void) snprintf(name, sizeof(name), "%s%s", _PATH_DEV,
    128      1.12  christos 		    dp->d_name);
    129      1.12  christos 		if (stat(name, &devstat) == -1)
    130      1.12  christos 			err(1, "Cannot stat `%s'", name);
    131       1.1       cgd 		if (stbuf.st_dev == devstat.st_rdev &&
    132       1.9   mycroft 		    S_ISBLK(devstat.st_mode))
    133       1.1       cgd 			break;
    134       1.1       cgd 	}
    135      1.17  drochner 	if (dp == NULL) {
    136      1.17  drochner 		closedir(dirp);
    137      1.12  christos 		errx(1, "Cannot find dev 0%o corresponding to %s",
    138      1.12  christos 		    stbuf.st_rdev, argv[1]);
    139      1.17  drochner 	}
    140      1.11    scottr 
    141      1.11    scottr 	/*
    142      1.11    scottr 	 * The filesystem is mounted; use the character device instead.
    143      1.11    scottr 	 * XXX - Assume that prepending an `r' will give us the name of
    144      1.11    scottr 	 * the character device.
    145      1.11    scottr 	 */
    146      1.12  christos 	(void) snprintf(name, sizeof(name), "%sr%s", _PATH_DEV, dp->d_name);
    147      1.17  drochner 
    148      1.17  drochner 	closedir(dirp); /* now *dp is invalid */
    149      1.17  drochner 
    150      1.12  christos 	if ((fsi = open(name, O_RDONLY)) == -1)
    151      1.12  christos 		err(1, "Cannot open `%s'", argv[1]);
    152      1.11    scottr 
    153       1.1       cgd 	fs = &sblock;
    154       1.1       cgd 	rdfs(SBOFF, SBSIZE, (char *)fs);
    155      1.16      ross 	if (fs->fs_magic != FS_MAGIC) {
    156      1.15    bouyer 		if(fs->fs_magic == bswap32(FS_MAGIC))
    157      1.15    bouyer 			needswap = 1;
    158      1.15    bouyer 		else
    159      1.15    bouyer 			errx(1, "%s: bad superblock", name);
    160      1.16      ross 	}
    161      1.15    bouyer 	if (needswap)
    162  1.17.8.1        he 		ffs_sb_swap(fs, fs);
    163       1.1       cgd 	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
    164       1.1       cgd 	for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
    165       1.1       cgd 		number = atoi(*argv);
    166       1.1       cgd 		if (chkuse(number, 1))
    167       1.1       cgd 			continue;
    168       1.9   mycroft 		if (mknod(*argv, S_IFMT|S_IRUSR|S_IWUSR,
    169      1.12  christos 		    dbtofsb(fs, number)) == -1) {
    170      1.12  christos 			warn("Cannot mknod `%s'", *argv);
    171       1.1       cgd 			errs++;
    172       1.1       cgd 		}
    173       1.1       cgd 	}
    174      1.11    scottr 
    175      1.12  christos 	warnx("Don't forget to run ``fsck %s''", name);
    176      1.12  christos 	return errs;
    177       1.1       cgd }
    178       1.1       cgd 
    179       1.6        pk int
    180       1.1       cgd chkuse(blkno, cnt)
    181       1.1       cgd 	daddr_t blkno;
    182       1.1       cgd 	int cnt;
    183       1.1       cgd {
    184       1.1       cgd 	int cg;
    185       1.1       cgd 	daddr_t fsbn, bn;
    186       1.1       cgd 
    187       1.1       cgd 	fsbn = dbtofsb(fs, blkno);
    188       1.1       cgd 	if ((unsigned)(fsbn+cnt) > fs->fs_size) {
    189      1.12  christos 		warnx("block %d out of range of file system", blkno);
    190       1.1       cgd 		return (1);
    191       1.1       cgd 	}
    192      1.11    scottr 
    193       1.1       cgd 	cg = dtog(fs, fsbn);
    194       1.1       cgd 	if (fsbn < cgdmin(fs, cg)) {
    195       1.1       cgd 		if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) {
    196      1.12  christos 			warnx("block %d in non-data area: cannot attach",
    197      1.12  christos 			    blkno);
    198       1.1       cgd 			return (1);
    199       1.1       cgd 		}
    200       1.1       cgd 	} else {
    201       1.1       cgd 		if ((fsbn+cnt) > cgbase(fs, cg+1)) {
    202      1.13     lukem 			warnx("block %d in non-data area: cannot attach",
    203      1.12  christos 			    blkno);
    204       1.1       cgd 			return (1);
    205       1.1       cgd 		}
    206       1.1       cgd 	}
    207      1.11    scottr 
    208       1.1       cgd 	rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize,
    209       1.1       cgd 	    (char *)&acg);
    210      1.11    scottr 
    211      1.15    bouyer 	if (!cg_chkmagic(&acg, needswap)) {
    212      1.12  christos 		warnx("cg %d: bad magic number", cg);
    213       1.1       cgd 		errs++;
    214       1.1       cgd 		return (1);
    215       1.1       cgd 	}
    216      1.11    scottr 
    217       1.1       cgd 	bn = dtogd(fs, fsbn);
    218      1.15    bouyer 	if (isclr(cg_blksfree(&acg, needswap), bn))
    219      1.12  christos 		warnx("Warning: sector %d is in use", blkno);
    220      1.11    scottr 
    221       1.1       cgd 	return (0);
    222       1.1       cgd }
    223       1.1       cgd 
    224       1.1       cgd /*
    225       1.1       cgd  * read a block from the file system
    226       1.1       cgd  */
    227       1.6        pk void
    228       1.1       cgd rdfs(bno, size, bf)
    229       1.6        pk 	daddr_t bno;
    230       1.6        pk 	int size;
    231       1.1       cgd 	char *bf;
    232       1.1       cgd {
    233       1.1       cgd 	int n;
    234       1.1       cgd 
    235      1.12  christos 	if (lseek(fsi, (off_t)bno * dev_bsize, SEEK_SET) == -1)
    236      1.12  christos 		err(1, "seek error at block %d", bno);
    237      1.11    scottr 
    238      1.12  christos 	switch (n = read(fsi, bf, size)) {
    239      1.12  christos 	case -1:
    240      1.12  christos 		err(1, "read error at block %d", bno);
    241      1.12  christos 		break;
    242      1.12  christos 
    243      1.12  christos 	default:
    244      1.12  christos 		if (n == size)
    245      1.12  christos 			return;
    246      1.12  christos 		errx(1, "incomplete read at block %d", bno);
    247       1.1       cgd 	}
    248       1.1       cgd }
    249