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 $
33 * $DragonFly: src/sbin/fsirand/fsirand.c,v 1.10 2007/05/20 23:21:36 dillon Exp $
36 #include <sys/diskslice.h>
37 #include <sys/param.h>
39 #include <sys/resource.h>
41 #include <vfs/ufs/dinode.h>
42 #include <vfs/ufs/fs.h>
52 static void usage(void);
55 int printonly
= 0, force
= 0, ignorelabel
= 0;
58 main(int argc
, char **argv
)
63 while ((n
= getopt(argc
, argv
, "bfp")) != -1) {
78 if (argc
- optind
< 1)
83 /* Increase our data size to the max */
84 if (getrlimit(RLIMIT_DATA
, &rl
) == 0) {
85 rl
.rlim_cur
= rl
.rlim_max
;
86 if (setrlimit(RLIMIT_DATA
, &rl
) < 0)
87 warn("can't get resource limit to max data size");
89 warn("can't get resource limit for data size");
91 for (n
= optind
; n
< argc
; n
++) {
92 if (argc
- optind
!= 1)
94 ex
+= fsirand(argv
[n
]);
103 fsirand(char *device
)
105 static struct ufs1_dinode
*inodebuf
;
106 static ssize_t oldibufsize
= 0;
109 ino_t inumber
, maxino
;
111 char sbuf
[SBSIZE
], sbuftmp
[SBSIZE
];
113 u_int32_t bsize
= DEV_BSIZE
;
115 if ((devfd
= open(device
, printonly
? O_RDONLY
: O_RDWR
)) < 0) {
116 warn("can't open %s", device
);
120 /* Get block size (usually 512) from partinfo if possible */
122 struct partinfo pinfo
;
124 if (ioctl(devfd
, DIOCGPART
, &pinfo
) < 0) {
126 "can't read partition info, assuming sector "
127 "size of %d\n", bsize
);
129 bsize
= pinfo
.media_blksize
;
133 /* Read in master superblock */
134 memset(&sbuf
, 0, sizeof(sbuf
));
135 sblock
= (struct fs
*)&sbuf
;
136 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
137 warn("can't seek to superblock (%qd) on %s", 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
));
145 maxino
= sblock
->fs_ncg
* sblock
->fs_ipg
;
147 /* Simple sanity checks on the superblock */
148 if (sblock
->fs_magic
!= FS_MAGIC
) {
149 warnx("bad magic number in superblock");
152 if (sblock
->fs_sbsize
> SBSIZE
) {
153 warnx("superblock size is preposterous");
156 if (sblock
->fs_postblformat
== FS_42POSTBLFMT
) {
157 warnx("filesystem format is too old, sorry");
160 if (!force
&& !printonly
&& sblock
->fs_clean
!= 1) {
161 warnx("filesystem is not clean, fsck %s first", device
);
165 /* Make sure backup superblocks are sane. */
166 sblock
= (struct fs
*)&sbuftmp
;
167 for (cg
= 0; cg
< sblock
->fs_ncg
; cg
++) {
168 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
169 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
170 warn("can't seek to %qd", (off_t
)dblk
* bsize
);
172 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
173 warn("can't read backup superblock %d on %s: %s",
174 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
178 if (sblock
->fs_magic
!= FS_MAGIC
) {
179 warnx("bad magic number in backup superblock %d on %s",
183 if (sblock
->fs_sbsize
> SBSIZE
) {
184 warnx("size of backup superblock %d on %s is preposterous",
189 sblock
= (struct fs
*)&sbuf
;
191 /* XXX - should really cap buffer at 512kb or so */
192 ibufsize
= sizeof(struct ufs1_dinode
) * sblock
->fs_ipg
;
193 if (oldibufsize
< ibufsize
) {
194 if ((inodebuf
= realloc(inodebuf
, ibufsize
)) == NULL
)
195 errx(1, "can't allocate memory for inode buffer");
196 oldibufsize
= ibufsize
;
199 if (printonly
&& (sblock
->fs_id
[0] || sblock
->fs_id
[1])) {
200 if (sblock
->fs_inodefmt
>= FS_44INODEFMT
&& sblock
->fs_id
[0])
201 printf("%s was randomized on %s", device
,
202 ctime((const time_t *)&(sblock
->fs_id
[0])));
203 printf("fsid: %x %x\n", sblock
->fs_id
[0],
207 /* Randomize fs_id unless old 4.2BSD filesystem */
208 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
209 /* Randomize fs_id and write out new sblock and backups */
210 sblock
->fs_id
[0] = (u_int32_t
)time(NULL
);
211 sblock
->fs_id
[1] = random();
213 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
214 warn("can't seek to superblock (%qd) on %s", SBOFF
,
218 if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
219 warn("can't read superblock on %s: %s", device
,
220 (n
< SBSIZE
) ? "short write" : strerror(errno
));
225 /* For each cylinder group, randomize inodes and update backup sblock */
226 for (cg
= 0, inumber
= 0; cg
< sblock
->fs_ncg
; cg
++) {
227 /* Update superblock if appropriate */
228 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
229 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
230 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
231 warn("can't seek to %qd", (off_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 %qd", (off_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
>= ROOTINO
) {
255 printf("ino %lld gen %x\n", inumber
,
258 inodebuf
[n
].di_gen
= random();
262 /* Write out modified inodes */
264 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
265 warn("can't seek to %qd",
266 (off_t
)dblk
* bsize
);
268 } else if ((n
= write(devfd
, inodebuf
, ibufsize
)) !=
270 warnx("can't write inodes: %s",
271 (n
!= ibufsize
) ? "short write" :
286 "usage: fsirand [-b] [-f] [-p] special [special ...]\n");