1 /* $NetBSD: fsirand.c,v 1.27 2007/02/08 21:36:58 drochner Exp $ */
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: fsirand.c,v 1.27 2007/02/08 21:36:58 drochner Exp $");
37 #include <sys/param.h>
39 #include <sys/vnode.h>
40 #include <sys/disklabel.h>
41 #include <sys/ioctl.h>
54 #include <ufs/ufs/ufs_bswap.h>
56 #include <ufs/ufs/dinode.h>
57 #include <ufs/ffs/fs.h>
58 #include <ufs/ffs/ffs_extern.h>
60 static void usage(void);
61 static void getsblock(int, const char *, struct fs
*);
62 static void fixinodes(int, struct fs
*, struct disklabel
*, int, long);
63 static void statussig(int);
65 int needswap
, ino
, imax
, is_ufs2
;
72 (void) fprintf(stderr
,
73 "usage: %s [-F] [-p] [-x <constant>] <special>\n",
79 static const off_t sblock_try
[] = SBLOCKSEARCH
;
83 * Return the superblock
86 getsblock(int fd
, const char *name
, struct fs
*fs
)
91 if (sblock_try
[i
] == -1)
92 errx(1, "%s: can't find superblock", name
);
93 if (pread(fd
, fs
, SBLOCKSIZE
, sblock_try
[i
]) != SBLOCKSIZE
)
96 switch(fs
->fs_magic
) {
102 case FS_UFS2_MAGIC_SWAPPED
:
105 case FS_UFS1_MAGIC_SWAPPED
:
113 if (!is_ufs2
&& sblock_try
[i
] == SBLOCK_UFS2
)
119 errx(1, "%s: bad ncg in superblock", name
);
121 if (fs
->fs_sbsize
> SBLOCKSIZE
)
122 errx(1, "%s: superblock too large", name
);
128 * Randomize the inode generation numbers
131 fixinodes(int fd
, struct fs
*fs
, struct disklabel
*lab
, int pflag
, long xorval
)
133 int inopb
= INOPB(fs
);
136 struct ufs1_dinode
*dp1
= NULL
;
137 struct ufs2_dinode
*dp2
= NULL
;
140 size
= is_ufs2
? inopb
* sizeof (struct ufs2_dinode
) :
141 inopb
* sizeof (struct ufs1_dinode
);
143 if ((buf
= malloc(size
)) == NULL
)
144 err(1, "Out of memory");
147 dp2
= (struct ufs2_dinode
*)buf
;
149 dp1
= (struct ufs1_dinode
*)buf
;
151 for (ino
= 0, imax
= fs
->fs_ipg
* fs
->fs_ncg
; ino
< imax
;) {
153 sp
= (off_t
) fsbtodb(fs
, ino_to_fsba(fs
, ino
)) *
154 (off_t
) lab
->d_secsize
;
156 if (lseek(fd
, sp
, SEEK_SET
) == (off_t
) -1)
157 err(1, "Seeking to inode %d failed", ino
);
159 if (read(fd
, buf
, size
) != size
)
160 err(1, "Reading inodes %d+%d failed", ino
, inopb
);
162 for (i
= 0; i
< inopb
; i
++) {
165 printf("inode %10d gen 0x%08x\n",
167 ufs_rw32(dp2
[i
].di_gen
, needswap
));
170 ufs_rw32((arc4random() & INT32_MAX
)^ xorval
,
174 printf("inode %10d gen 0x%08x\n",
176 ufs_rw32(dp1
[i
].di_gen
, needswap
));
179 ufs_rw32((arc4random() & INT32_MAX
) ^ xorval
,
183 errx(1, "Exceeded number of inodes");
189 if (lseek(fd
, sp
, SEEK_SET
) == (off_t
) -1)
190 err(1, "Seeking to inode %d failed", ino
);
192 if (write(fd
, buf
, size
) != size
)
193 err(1, "Writing inodes %d+%d failed", ino
, inopb
);
200 * display current status
207 time_t tnow
, elapsed
;
210 elapsed
= tnow
- tstart
;
211 len
= snprintf(msgbuf
, sizeof(msgbuf
),
212 "fsirand: completed inode %d of %d (%3.2f%%)",
213 ino
, imax
, (ino
* 100.0) / imax
);
215 deltat
= tstart
- tnow
+ (1.0 * (tnow
- tstart
)) / ino
* imax
;
216 len
+= snprintf(msgbuf
+ len
, sizeof(msgbuf
) - len
,
217 ", finished in %d:%02d\n", deltat
/ 60, deltat
% 60);
219 len
+= snprintf(msgbuf
+ len
, sizeof(msgbuf
) - len
, "\n");
221 write(STDERR_FILENO
, msgbuf
, len
);
225 main(int argc
, char *argv
[])
228 char buf
[SBLOCKSIZE
], device
[MAXPATHLEN
];
229 struct fs
*fs
= (struct fs
*) buf
;
230 struct disklabel lab
;
233 int fd
, c
, Fflag
, pflag
, openflags
;
238 while ((c
= getopt(argc
, argv
, "Fpx:")) != -1)
248 xorval
= strtol(optarg
, &ep
, 0);
249 if ((xorval
== LONG_MIN
|| xorval
== LONG_MAX
) &&
251 err(1, "Out of range constant");
253 errx(1, "Bad constant");
266 openflags
= pflag
? O_RDONLY
: O_RDWR
;
268 fd
= open(special
, openflags
);
270 fd
= opendisk(special
, openflags
, device
, sizeof(device
), 0);
274 err(1, "Cannot open `%s'", special
);
277 memset(&lab
, 0, sizeof(lab
));
278 lab
.d_secsize
= DEV_BSIZE
; /* XXX */
280 if (ioctl(fd
, DIOCGDINFO
, &lab
) == -1)
281 err(1, "%s: cannot get disklabel information", special
);
285 (void)signal(SIGINFO
, statussig
);
286 getsblock(fd
, special
, fs
);
287 fixinodes(fd
, fs
, &lab
, pflag
, xorval
);