badsect.c revision 37233
1/*
2 * Copyright (c) 1981, 1983, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char copyright[] =
36"@(#) Copyright (c) 1981, 1983, 1993\n\
37	The Regents of the University of California.  All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41#if 0
42static const char sccsid[] = "@(#)badsect.c	8.1 (Berkeley) 6/5/93";
43#endif
44static const char rcsid[] =
45	"$Id: badsect.c,v 1.5 1998/06/04 06:38:03 charnier Exp $";
46#endif /* not lint */
47
48/*
49 * badsect
50 *
51 * Badsect takes a list of file-system relative sector numbers
52 * and makes files containing the blocks of which these sectors are a part.
53 * It can be used to contain sectors which have problems if these sectors
54 * are not part of the bad file for the pack (see bad144).  For instance,
55 * this program can be used if the driver for the file system in question
56 * does not support bad block forwarding.
57 */
58#include <sys/param.h>
59#include <sys/stat.h>
60
61#include <ufs/ffs/fs.h>
62#include <ufs/ufs/dinode.h>
63
64#include <err.h>
65#include <dirent.h>
66#include <fcntl.h>
67#include <paths.h>
68#include <stdio.h>
69#include <stdlib.h>
70#include <unistd.h>
71
72union {
73	struct	fs fs;
74	char	fsx[SBSIZE];
75} ufs;
76#define sblock	ufs.fs
77union {
78	struct	cg cg;
79	char	cgx[MAXBSIZE];
80} ucg;
81#define	acg	ucg.cg
82struct	fs *fs;
83int	fso, fsi;
84int	errs;
85long	dev_bsize = 1;
86
87char buf[MAXBSIZE];
88
89void	rdfs __P((daddr_t, int, char *));
90int	chkuse __P((daddr_t, int));
91
92static void
93usage(void)
94{
95	fprintf(stderr, "usage: badsect bbdir blkno ...\n");
96	exit(1);
97}
98
99int
100main(argc, argv)
101	int argc;
102	char *argv[];
103{
104	daddr_t diskbn;
105	daddr_t number;
106	struct stat stbuf, devstat;
107	register struct dirent *dp;
108	DIR *dirp;
109	char name[2 * MAXPATHLEN];
110	char *name_dir_end;
111
112	if (argc < 3)
113		usage();
114	if (chdir(argv[1]) < 0 || stat(".", &stbuf) < 0)
115		err(2, "%s", argv[1]);
116	strcpy(name, _PATH_DEV);
117	if ((dirp = opendir(name)) == NULL)
118		err(3, "%s", name);
119	name_dir_end = name + strlen(name);
120	while ((dp = readdir(dirp)) != NULL) {
121		strcpy(name_dir_end, dp->d_name);
122		if (lstat(name, &devstat) < 0)
123			err(4, "%s", name);
124		if (stbuf.st_dev == devstat.st_rdev &&
125		    (devstat.st_mode & IFMT) == IFBLK)
126			break;
127	}
128	closedir(dirp);
129	if (dp == NULL) {
130		printf("Cannot find dev 0%lo corresponding to %s\n",
131		    (u_long)stbuf.st_rdev, argv[1]);
132		exit(5);
133	}
134	/*
135	 * Opening of a mounted on device is not allowed.
136	 * Attempt to open the raw device instead.
137	 */
138	memcpy(name_dir_end + 1, name_dir_end, strlen(name_dir_end) + 1);
139	*name_dir_end = 'r';
140	if ((fsi = open(name, O_RDONLY)) < 0)
141		err(6, "%s", name);
142	fs = &sblock;
143	rdfs(SBOFF, SBSIZE, (char *)fs);
144	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
145	for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
146		number = atol(*argv);
147		if (chkuse(number, 1))
148			continue;
149		/*
150		 * Print a warning if converting the block number to a dev_t
151		 * will truncate it.  badsect was not very useful in versions
152		 * of BSD before 4.4 because dev_t was 16 bits and another
153		 * bit was lost by bogus sign extensions.
154		 */
155		diskbn = dbtofsb(fs, number);
156		if ((dev_t)diskbn != diskbn) {
157			printf("sector %ld cannot be represented as a dev_t\n",
158			    (long)number);
159			errs++;
160		}
161		else if (mknod(*argv, IFMT|0600, (dev_t)diskbn) < 0) {
162			warn("%s", *argv);
163			errs++;
164		}
165	}
166	printf("Don't forget to run ``fsck %s''\n", name);
167	exit(errs);
168}
169
170int
171chkuse(blkno, cnt)
172	daddr_t blkno;
173	int cnt;
174{
175	int cg;
176	daddr_t fsbn, bn;
177
178	fsbn = dbtofsb(fs, blkno);
179	if ((unsigned)(fsbn+cnt) > fs->fs_size) {
180		printf("block %ld out of range of file system\n", (long)blkno);
181		return (1);
182	}
183	cg = dtog(fs, fsbn);
184	if (fsbn < cgdmin(fs, cg)) {
185		if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) {
186			printf("block %ld in non-data area: cannot attach\n",
187			    (long)blkno);
188			return (1);
189		}
190	} else {
191		if ((fsbn+cnt) > cgbase(fs, cg+1)) {
192			printf("block %ld in non-data area: cannot attach\n",
193			    (long)blkno);
194			return (1);
195		}
196	}
197	rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize,
198	    (char *)&acg);
199	if (!cg_chkmagic(&acg)) {
200		fprintf(stderr, "cg %d: bad magic number\n", cg);
201		errs++;
202		return (1);
203	}
204	bn = dtogd(fs, fsbn);
205	if (isclr(cg_blksfree(&acg), bn))
206		printf("Warning: sector %ld is in use\n", (long)blkno);
207	return (0);
208}
209
210/*
211 * read a block from the file system
212 */
213void
214rdfs(bno, size, bf)
215	daddr_t bno;
216	int size;
217	char *bf;
218{
219	int n;
220
221	if (lseek(fsi, (off_t)bno * dev_bsize, SEEK_SET) < 0) {
222		printf("seek error: %ld\n", (long)bno);
223		err(1, "rdfs");
224	}
225	n = read(fsi, bf, size);
226	if (n != size) {
227		printf("read error: %ld\n", (long)bno);
228		err(1, "rdfs");
229	}
230}
231