xref: /original-bsd/sbin/badsect/badsect.c (revision 0f81f0ee)
1 /*
2  * Copyright (c) 1981, 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1981, 1983, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)badsect.c	8.2 (Berkeley) 05/04/95";
16 #endif /* not lint */
17 
18 /*
19  * badsect
20  *
21  * Badsect takes a list of file-system relative sector numbers
22  * and makes files containing the blocks of which these sectors are a part.
23  * It can be used to contain sectors which have problems if these sectors
24  * are not part of the bad file for the pack (see bad144).  For instance,
25  * this program can be used if the driver for the file system in question
26  * does not support bad block forwarding.
27  */
28 #include <sys/param.h>
29 #include <sys/dir.h>
30 #include <sys/stat.h>
31 
32 #include <ufs/ufs/dinode.h>
33 #include <ufs/ffs/fs.h>
34 
35 #include <fcntl.h>
36 #include <paths.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 
41 union {
42 	struct	fs fs;
43 	char	fsx[SBSIZE];
44 } ufs;
45 #define sblock	ufs.fs
46 union {
47 	struct	cg cg;
48 	char	cgx[MAXBSIZE];
49 } ucg;
50 #define	acg	ucg.cg
51 struct	fs *fs;
52 int	fso, fsi;
53 int	errs;
54 long	dev_bsize = 1;
55 
56 char buf[MAXBSIZE];
57 
58 void	rdfs __P((daddr_t, int, char *));
59 int	chkuse __P((daddr_t, int));
60 
61 int
62 main(argc, argv)
63 	int argc;
64 	char *argv[];
65 {
66 	daddr_t number;
67 	struct stat stbuf, devstat;
68 	register struct direct *dp;
69 	DIR *dirp;
70 	char name[BUFSIZ];
71 
72 	if (argc < 3) {
73 		fprintf(stderr, "usage: badsect bbdir blkno [ blkno ]\n");
74 		exit(1);
75 	}
76 	if (chdir(argv[1]) < 0 || stat(".", &stbuf) < 0) {
77 		perror(argv[1]);
78 		exit(2);
79 	}
80 	strcpy(name, _PATH_DEV);
81 	if ((dirp = opendir(name)) == NULL) {
82 		perror(name);
83 		exit(3);
84 	}
85 	while ((dp = readdir(dirp)) != NULL) {
86 		strcpy(&name[5], dp->d_name);
87 		if (stat(name, &devstat) < 0) {
88 			perror(name);
89 			exit(4);
90 		}
91 		if (stbuf.st_dev == devstat.st_rdev &&
92 		    (devstat.st_mode & IFMT) == IFBLK)
93 			break;
94 	}
95 	closedir(dirp);
96 	if (dp == NULL) {
97 		printf("Cannot find dev 0%o corresponding to %s\n",
98 			stbuf.st_rdev, argv[1]);
99 		exit(5);
100 	}
101 	if ((fsi = open(name, 0)) < 0) {
102 		perror(name);
103 		exit(6);
104 	}
105 	fs = &sblock;
106 	rdfs(SBOFF, SBSIZE, (char *)fs);
107 	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
108 	for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
109 		number = atoi(*argv);
110 		if (chkuse(number, 1))
111 			continue;
112 		if (mknod(*argv, IFMT|0600, dbtofsb(fs, number)) < 0) {
113 			perror(*argv);
114 			errs++;
115 		}
116 	}
117 	printf("Don't forget to run ``fsck %s''\n", name);
118 	exit(errs);
119 }
120 
121 int
122 chkuse(blkno, cnt)
123 	daddr_t blkno;
124 	int cnt;
125 {
126 	int cg;
127 	daddr_t fsbn, bn;
128 
129 	fsbn = dbtofsb(fs, blkno);
130 	if ((unsigned)(fsbn+cnt) > fs->fs_size) {
131 		printf("block %d out of range of file system\n", blkno);
132 		return (1);
133 	}
134 	cg = dtog(fs, fsbn);
135 	if (fsbn < cgdmin(fs, cg)) {
136 		if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) {
137 			printf("block %d in non-data area: cannot attach\n",
138 				blkno);
139 			return (1);
140 		}
141 	} else {
142 		if ((fsbn+cnt) > cgbase(fs, cg+1)) {
143 			printf("block %d in non-data area: cannot attach\n",
144 				blkno);
145 			return (1);
146 		}
147 	}
148 	rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize,
149 	    (char *)&acg);
150 	if (!cg_chkmagic(&acg)) {
151 		fprintf(stderr, "cg %d: bad magic number\n", cg);
152 		errs++;
153 		return (1);
154 	}
155 	bn = dtogd(fs, fsbn);
156 	if (isclr(cg_blksfree(&acg), bn))
157 		printf("Warning: sector %d is in use\n", blkno);
158 	return (0);
159 }
160 
161 /*
162  * read a block from the file system
163  */
164 void
165 rdfs(bno, size, bf)
166 	daddr_t bno;
167 	int size;
168 	char *bf;
169 {
170 	int n;
171 
172 	if (lseek(fsi, (off_t)bno * dev_bsize, SEEK_SET) < 0) {
173 		printf("seek error: %ld\n", bno);
174 		perror("rdfs");
175 		exit(1);
176 	}
177 	n = read(fsi, bf, size);
178 	if (n != size) {
179 		printf("read error: %ld\n", bno);
180 		perror("rdfs");
181 		exit(1);
182 	}
183 }
184