1 /* $OpenBSD: fsirand.c,v 1.9 1997/02/28 00:46:33 millert Exp $ */
4 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Todd C. Miller.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: src/sbin/fsirand/fsirand.c,v 1.7.2.1 2000/07/01 06:23:36 ps Exp $
35 #include <sys/diskslice.h>
36 #include <sys/param.h>
38 #include <sys/resource.h>
40 #include <vfs/ufs/dinode.h>
41 #include <vfs/ufs/fs.h>
51 static void usage(void);
54 int printonly
= 0, force
= 0, ignorelabel
= 0;
57 main(int argc
, char **argv
)
62 while ((n
= getopt(argc
, argv
, "bfp")) != -1) {
77 if (argc
- optind
< 1)
82 /* Increase our data size to the max */
83 if (getrlimit(RLIMIT_DATA
, &rl
) == 0) {
84 rl
.rlim_cur
= rl
.rlim_max
;
85 if (setrlimit(RLIMIT_DATA
, &rl
) < 0)
86 warn("can't get resource limit to max data size");
88 warn("can't get resource limit for data size");
90 for (n
= optind
; n
< argc
; n
++) {
91 if (argc
- optind
!= 1)
93 ex
+= fsirand(argv
[n
]);
102 fsirand(char *device
)
104 static struct ufs1_dinode
*inodebuf
;
105 static ssize_t oldibufsize
= 0;
110 char sbuf
[SBSIZE
], sbuftmp
[SBSIZE
];
112 u_int32_t bsize
= DEV_BSIZE
;
114 if ((devfd
= open(device
, printonly
? O_RDONLY
: O_RDWR
)) < 0) {
115 warn("can't open %s", device
);
119 /* Get block size (usually 512) from partinfo if possible */
121 struct partinfo pinfo
;
123 if (ioctl(devfd
, DIOCGPART
, &pinfo
) < 0) {
125 "can't read partition info, assuming sector "
126 "size of %d\n", bsize
);
128 bsize
= pinfo
.media_blksize
;
132 /* Read in master superblock */
133 memset(&sbuf
, 0, sizeof(sbuf
));
134 sblock
= (struct fs
*)&sbuf
;
135 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
136 warn("can't seek to superblock (%jd) on %s",
137 (intmax_t)SBOFF
, device
);
140 if ((n
= read(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
141 warnx("can't read superblock on %s: %s", device
,
142 (n
< SBSIZE
) ? "short read" : strerror(errno
));
146 /* Simple sanity checks on the superblock */
147 if (sblock
->fs_magic
!= FS_MAGIC
) {
148 warnx("bad magic number in superblock");
151 if (sblock
->fs_sbsize
> SBSIZE
) {
152 warnx("superblock size is preposterous");
155 if (sblock
->fs_postblformat
== FS_42POSTBLFMT
) {
156 warnx("filesystem format is too old, sorry");
159 if (!force
&& !printonly
&& sblock
->fs_clean
!= 1) {
160 warnx("filesystem is not clean, fsck %s first", device
);
164 /* Make sure backup superblocks are sane. */
165 sblock
= (struct fs
*)&sbuftmp
;
166 for (cg
= 0; cg
< sblock
->fs_ncg
; cg
++) {
167 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
168 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
169 warn("can't seek to %jd", (intmax_t)dblk
* bsize
);
171 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
172 warn("can't read backup superblock %d on %s: %s",
173 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
177 if (sblock
->fs_magic
!= FS_MAGIC
) {
178 warnx("bad magic number in backup superblock %d on %s",
182 if (sblock
->fs_sbsize
> SBSIZE
) {
183 warnx("size of backup superblock %d on %s is preposterous",
188 sblock
= (struct fs
*)&sbuf
;
190 /* XXX - should really cap buffer at 512kb or so */
191 ibufsize
= sizeof(struct ufs1_dinode
) * sblock
->fs_ipg
;
192 if (oldibufsize
< ibufsize
) {
193 if ((inodebuf
= realloc(inodebuf
, ibufsize
)) == NULL
)
194 errx(1, "can't allocate memory for inode buffer");
195 oldibufsize
= ibufsize
;
198 if (printonly
&& (sblock
->fs_id
[0] || sblock
->fs_id
[1])) {
199 if (sblock
->fs_inodefmt
>= FS_44INODEFMT
&& sblock
->fs_id
[0])
200 printf("%s was randomized on %s", device
,
201 ctime((const time_t *)&(sblock
->fs_id
[0])));
202 printf("fsid: %x %x\n", sblock
->fs_id
[0],
206 /* Randomize fs_id unless old 4.2BSD filesystem */
207 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
208 /* Randomize fs_id and write out new sblock and backups */
209 sblock
->fs_id
[0] = (u_int32_t
)time(NULL
);
210 sblock
->fs_id
[1] = random();
212 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
213 warn("can't seek to superblock (%jd) on %s",
214 (intmax_t)SBOFF
, device
);
217 if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
218 warn("can't read superblock on %s: %s", device
,
219 (n
< SBSIZE
) ? "short write" : strerror(errno
));
224 /* For each cylinder group, randomize inodes and update backup sblock */
225 for (cg
= 0, inumber
= 0; cg
< sblock
->fs_ncg
; cg
++) {
226 /* Update superblock if appropriate */
227 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
228 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
229 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
230 warn("can't seek to %jd",
231 (intmax_t)dblk
* bsize
);
233 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
234 warn("can't read backup superblock %d on %s: %s",
235 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
241 /* Read in inodes, then print or randomize generation nums */
242 dblk
= fsbtodb(sblock
, ino_to_fsba(sblock
, inumber
));
243 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
244 warn("can't seek to %jd", (intmax_t)dblk
* bsize
);
246 } else if ((n
= read(devfd
, inodebuf
, ibufsize
)) != ibufsize
) {
247 warnx("can't read inodes: %s",
248 (n
< ibufsize
) ? "short read" : strerror(errno
));
252 for (n
= 0; n
< sblock
->fs_ipg
; n
++, inumber
++) {
253 if (inumber
>= UFS_ROOTINO
) {
255 printf("ino %jd gen %x\n",
259 inodebuf
[n
].di_gen
= random();
264 /* Write out modified inodes */
266 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
267 warn("can't seek to %jd",
268 (intmax_t)dblk
* bsize
);
270 } else if ((n
= write(devfd
, inodebuf
, ibufsize
)) !=
272 warnx("can't write inodes: %s",
273 (n
!= ibufsize
) ? "short write" :
288 "usage: fsirand [-b] [-f] [-p] special [special ...]\n");