GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/badsect/badsect.c Lines: 0 60 0.0 %
Date: 2017-11-07 Branches: 0 42 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: badsect.c,v 1.27 2015/11/12 22:33:07 deraadt Exp $	*/
2
/*	$NetBSD: badsect.c,v 1.10 1995/03/18 14:54:28 cgd Exp $	*/
3
4
/*
5
 * Copyright (c) 1981, 1983, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
/*
34
 * badsect
35
 *
36
 * Badsect takes a list of file-system relative sector numbers
37
 * and makes files containing the blocks of which these sectors are a part.
38
 * It can be used to contain sectors which have problems if these sectors
39
 * are not part of the bad file for the pack (see bad144).  For instance,
40
 * this program can be used if the driver for the file system in question
41
 * does not support bad block forwarding.
42
 */
43
#include <sys/param.h>	/* MAXBSIZE DEV_BSIZE isclr */
44
#include <sys/stat.h>
45
46
#include <ufs/ffs/fs.h>
47
#include <ufs/ufs/dinode.h>
48
49
#include <dirent.h>
50
#include <fcntl.h>
51
#include <paths.h>
52
#include <stdio.h>
53
#include <stdlib.h>
54
#include <string.h>
55
#include <unistd.h>
56
#include <limits.h>
57
#include <err.h>
58
59
static int chkuse(daddr_t, int);
60
static void rdfs(daddr_t, int, char *);
61
62
static union {
63
	struct	fs fs;
64
	char	fsx[SBSIZE];
65
} ufs;
66
#define sblock	ufs.fs
67
static union {
68
	struct	cg cg;
69
	char	cgx[MAXBSIZE];
70
} ucg;
71
#define	acg	ucg.cg
72
static struct	fs *fs;
73
static int	fsi;
74
static int	errs;
75
76
int
77
main(int argc, char *argv[])
78
{
79
	daddr_t number;
80
	struct stat stbuf, devstat;
81
	struct dirent *dp;
82
	DIR *dirp;
83
	char name[BUFSIZ];
84
	int len;
85
86
	if (argc < 3) {
87
		fprintf(stderr, "usage: badsect bbdir sector ...\n");
88
		exit(1);
89
	}
90
	if (chdir(argv[1]) < 0 || stat(".", &stbuf) < 0)
91
		err(2, "%s", argv[1]);
92
93
	strlcpy(name, _PATH_DEV, sizeof name);
94
	len = strlen(name);
95
	if ((dirp = opendir(name)) == NULL)
96
		err(3, "%s", name);
97
98
	while ((dp = readdir(dirp)) != NULL) {
99
		strlcpy(&name[len], dp->d_name, sizeof name - len);
100
		if (stat(name, &devstat) < 0)
101
			err(4, "%s", name);
102
103
		if (stbuf.st_dev == devstat.st_rdev &&
104
		    S_ISBLK(devstat.st_mode))
105
			break;
106
	}
107
108
	/*
109
	 * We've found the block device, but since the filesystem
110
	 * is mounted, we must write to the raw (character) device
111
	 * instead. This is not guaranteed to work if someone has a
112
	 * /dev that doesn't follow standard naming conventions, but
113
	 * it's all we've got.
114
	 */
115
	name[len] = 'r';
116
	strlcpy(&name[len+1], dp->d_name, sizeof name - (len+1));
117
	closedir(dirp);
118
	if (dp == NULL)
119
		err(5, "Cannot find dev 0%o corresponding to %s",
120
			stbuf.st_rdev, argv[1]);
121
122
	if ((fsi = open(name, O_RDONLY)) < 0)
123
		err(6, "%s", name);
124
125
	fs = &sblock;
126
	rdfs(SBOFF, SBSIZE, (char *)fs);
127
	for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
128
		number = strtonum(*argv, 0, QUAD_MAX, NULL);
129
		if (chkuse(number, 1))
130
			continue;
131
		if (mknod(*argv, S_IFMT|S_IRUSR|S_IWUSR,
132
		    dbtofsb(fs, number)) < 0) {
133
			warn("%s", *argv);
134
			errs++;
135
		}
136
	}
137
	printf("Don't forget to run ``fsck %s''\n", name);
138
	exit(errs);
139
}
140
141
static int
142
chkuse(daddr_t blkno, int cnt)
143
{
144
	int cg;
145
	daddr_t fsbn, bn;
146
147
	fsbn = dbtofsb(fs, blkno);
148
	if (fsbn+cnt > fs->fs_ffs1_size) {
149
		fprintf(stderr, "block %lld out of range of file system\n",
150
		    (long long)blkno);
151
		return (1);
152
	}
153
	cg = dtog(fs, fsbn);
154
	if (fsbn < cgdmin(fs, cg)) {
155
		if (cg == 0 || (fsbn+cnt) > cgsblock(fs, cg)) {
156
			fprintf(stderr, "block %lld in non-data area: cannot "
157
			    "attach\n", (long long)blkno);
158
			return (1);
159
		}
160
	} else {
161
		if ((fsbn+cnt) > cgbase(fs, cg+1)) {
162
			fprintf(stderr, "block %lld in non-data area: cannot "
163
			    "attach\n", (long long)blkno);
164
			return (1);
165
		}
166
	}
167
	rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)sblock.fs_cgsize,
168
	    (char *)&acg);
169
	if (!cg_chkmagic(&acg)) {
170
		fprintf(stderr, "cg %d: bad magic number\n", cg);
171
		errs++;
172
		return (1);
173
	}
174
	bn = dtogd(fs, fsbn);
175
	if (isclr(cg_blksfree(&acg), bn))
176
		fprintf(stderr, "Warning: sector %lld is in use\n",
177
		    (long long)blkno);
178
	return (0);
179
}
180
181
/*
182
 * read a block from the file system
183
 */
184
static void
185
rdfs(daddr_t bno, int size, char *bf)
186
{
187
	if (pread(fsi, bf, size, bno * DEV_BSIZE) != size) {
188
		fprintf(stderr, "read error: %lld\n", (long long)bno);
189
		err(1, "rdfs");
190
	}
191
}