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 (%jd) on %s",
138 (intmax_t)SBOFF
, device
);
141 if ((n
= read(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
142 warnx("can't read superblock on %s: %s", device
,
143 (n
< SBSIZE
) ? "short read" : strerror(errno
));
146 maxino
= sblock
->fs_ncg
* sblock
->fs_ipg
;
148 /* Simple sanity checks on the superblock */
149 if (sblock
->fs_magic
!= FS_MAGIC
) {
150 warnx("bad magic number in superblock");
153 if (sblock
->fs_sbsize
> SBSIZE
) {
154 warnx("superblock size is preposterous");
157 if (sblock
->fs_postblformat
== FS_42POSTBLFMT
) {
158 warnx("filesystem format is too old, sorry");
161 if (!force
&& !printonly
&& sblock
->fs_clean
!= 1) {
162 warnx("filesystem is not clean, fsck %s first", device
);
166 /* Make sure backup superblocks are sane. */
167 sblock
= (struct fs
*)&sbuftmp
;
168 for (cg
= 0; cg
< sblock
->fs_ncg
; cg
++) {
169 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
170 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
171 warn("can't seek to %jd", (intmax_t)dblk
* bsize
);
173 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
174 warn("can't read backup superblock %d on %s: %s",
175 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
179 if (sblock
->fs_magic
!= FS_MAGIC
) {
180 warnx("bad magic number in backup superblock %d on %s",
184 if (sblock
->fs_sbsize
> SBSIZE
) {
185 warnx("size of backup superblock %d on %s is preposterous",
190 sblock
= (struct fs
*)&sbuf
;
192 /* XXX - should really cap buffer at 512kb or so */
193 ibufsize
= sizeof(struct ufs1_dinode
) * sblock
->fs_ipg
;
194 if (oldibufsize
< ibufsize
) {
195 if ((inodebuf
= realloc(inodebuf
, ibufsize
)) == NULL
)
196 errx(1, "can't allocate memory for inode buffer");
197 oldibufsize
= ibufsize
;
200 if (printonly
&& (sblock
->fs_id
[0] || sblock
->fs_id
[1])) {
201 if (sblock
->fs_inodefmt
>= FS_44INODEFMT
&& sblock
->fs_id
[0])
202 printf("%s was randomized on %s", device
,
203 ctime((const time_t *)&(sblock
->fs_id
[0])));
204 printf("fsid: %x %x\n", sblock
->fs_id
[0],
208 /* Randomize fs_id unless old 4.2BSD filesystem */
209 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
210 /* Randomize fs_id and write out new sblock and backups */
211 sblock
->fs_id
[0] = (u_int32_t
)time(NULL
);
212 sblock
->fs_id
[1] = random();
214 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
215 warn("can't seek to superblock (%jd) on %s",
216 (intmax_t)SBOFF
, device
);
219 if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
220 warn("can't read superblock on %s: %s", device
,
221 (n
< SBSIZE
) ? "short write" : strerror(errno
));
226 /* For each cylinder group, randomize inodes and update backup sblock */
227 for (cg
= 0, inumber
= 0; cg
< sblock
->fs_ncg
; cg
++) {
228 /* Update superblock if appropriate */
229 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
230 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
231 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
232 warn("can't seek to %jd",
233 (intmax_t)dblk
* bsize
);
235 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
236 warn("can't read backup superblock %d on %s: %s",
237 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
243 /* Read in inodes, then print or randomize generation nums */
244 dblk
= fsbtodb(sblock
, ino_to_fsba(sblock
, inumber
));
245 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
246 warn("can't seek to %jd", (intmax_t)dblk
* bsize
);
248 } else if ((n
= read(devfd
, inodebuf
, ibufsize
)) != ibufsize
) {
249 warnx("can't read inodes: %s",
250 (n
< ibufsize
) ? "short read" : strerror(errno
));
254 for (n
= 0; n
< sblock
->fs_ipg
; n
++, inumber
++) {
255 if (inumber
>= ROOTINO
) {
257 printf("ino %jd gen %x\n",
261 inodebuf
[n
].di_gen
= random();
266 /* Write out modified inodes */
268 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
269 warn("can't seek to %jd",
270 (intmax_t)dblk
* bsize
);
272 } else if ((n
= write(devfd
, inodebuf
, ibufsize
)) !=
274 warnx("can't write inodes: %s",
275 (n
!= ibufsize
) ? "short write" :
290 "usage: fsirand [-b] [-f] [-p] special [special ...]\n");