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