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