xref: /original-bsd/sbin/badsect/badsect.c (revision 365c7749)
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.7 (Berkeley) 07/30/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/time.h>
42 #include <sys/vnode.h>
43 #include <ufs/fs.h>
44 #include <ufs/inode.h>
45 #include <stdio.h>
46 #include <paths.h>
47 
48 union {
49 	struct	fs fs;
50 	char	fsx[SBSIZE];
51 } ufs;
52 #define sblock	ufs.fs
53 union {
54 	struct	cg cg;
55 	char	cgx[MAXBSIZE];
56 } ucg;
57 #define	acg	ucg.cg
58 struct	fs *fs;
59 int	fso, fsi;
60 int	errs;
61 long	dev_bsize = 1;
62 
63 char buf[MAXBSIZE];
64 
65 
66 main(argc, argv)
67 	int argc;
68 	char *argv[];
69 {
70 	daddr_t number;
71 	struct stat stbuf, devstat;
72 	register struct direct *dp;
73 	DIR *dirp;
74 	int fd;
75 	char name[BUFSIZ];
76 
77 	if (argc < 3) {
78 		fprintf(stderr, "usage: badsect bbdir blkno [ blkno ]\n");
79 		exit(1);
80 	}
81 	if (chdir(argv[1]) < 0 || stat(".", &stbuf) < 0) {
82 		perror(argv[1]);
83 		exit(2);
84 	}
85 	strcpy(name, _PATH_DEV);
86 	if ((dirp = opendir(name)) == NULL) {
87 		perror(name);
88 		exit(3);
89 	}
90 	while ((dp = readdir(dirp)) != NULL) {
91 		strcpy(&name[5], dp->d_name);
92 		if (stat(name, &devstat) < 0) {
93 			perror(name);
94 			exit(4);
95 		}
96 		if (stbuf.st_dev == devstat.st_rdev &&
97 		    (devstat.st_mode & IFMT) == IFBLK)
98 			break;
99 	}
100 	closedir(dirp);
101 	if (dp == NULL) {
102 		printf("Cannot find dev 0%o corresponding to %s\n",
103 			stbuf.st_rdev, argv[1]);
104 		exit(5);
105 	}
106 	if ((fsi = open(name, 0)) < 0) {
107 		perror(name);
108 		exit(6);
109 	}
110 	fs = &sblock;
111 	rdfs(SBOFF, SBSIZE, (char *)fs);
112 	dev_bsize = fs->fs_fsize / fsbtodb(fs, 1);
113 	for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
114 		number = atoi(*argv);
115 		if (chkuse(number, 1))
116 			continue;
117 		if (mknod(*argv, IFMT|0600, dbtofsb(fs, number)) < 0) {
118 			perror(*argv);
119 			errs++;
120 		}
121 	}
122 	printf("Don't forget to run ``fsck %s''\n", name);
123 	exit(errs);
124 }
125 
126 chkuse(blkno, cnt)
127 	daddr_t blkno;
128 	int cnt;
129 {
130 	int cg;
131 	daddr_t fsbn, bn;
132 
133 	fsbn = dbtofsb(fs, blkno);
134 	if ((unsigned)(fsbn+cnt) > fs->fs_size) {
135 		printf("block %d out of range of file system\n", blkno);
136 		return (1);
137 	}
138 	cg = dtog(fs, fsbn);
139 	if (fsbn < cgdmin(fs, cg)) {
140 		if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) {
141 			printf("block %d in non-data area: cannot attach\n",
142 				blkno);
143 			return (1);
144 		}
145 	} else {
146 		if ((fsbn+cnt) > cgbase(fs, cg+1)) {
147 			printf("block %d in non-data area: cannot attach\n",
148 				blkno);
149 			return (1);
150 		}
151 	}
152 	rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize,
153 	    (char *)&acg);
154 	if (!cg_chkmagic(&acg)) {
155 		fprintf(stderr, "cg %d: bad magic number\n", cg);
156 		errs++;
157 		return (1);
158 	}
159 	bn = dtogd(fs, fsbn);
160 	if (isclr(cg_blksfree(&acg), bn))
161 		printf("Warning: sector %d is in use\n", blkno);
162 	return (0);
163 }
164 
165 /*
166  * read a block from the file system
167  */
168 rdfs(bno, size, bf)
169 	int bno, size;
170 	char *bf;
171 {
172 	int n;
173 
174 	if (lseek(fsi, bno * dev_bsize, 0) < 0) {
175 		printf("seek error: %ld\n", bno);
176 		perror("rdfs");
177 		exit(1);
178 	}
179 	n = read(fsi, bf, size);
180 	if(n != size) {
181 		printf("read error: %ld\n", bno);
182 		perror("rdfs");
183 		exit(1);
184 	}
185 }
186