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.8 2006/04/03 01:58:49 dillon Exp $
36 #include <sys/disklabel.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
;
114 struct disklabel label
;
116 if ((devfd
= open(device
, printonly
? O_RDONLY
: O_RDWR
)) < 0) {
117 warn("can't open %s", device
);
121 /* Get block size (usually 512) from disklabel if possible */
123 if (ioctl(devfd
, DIOCGDINFO
, &label
) < 0)
124 warn("can't read disklabel, using sector size of %d",
127 bsize
= label
.d_secsize
;
130 /* Read in master superblock */
131 memset(&sbuf
, 0, sizeof(sbuf
));
132 sblock
= (struct fs
*)&sbuf
;
133 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
134 warn("can't seek to superblock (%qd) on %s", SBOFF
, device
);
137 if ((n
= read(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
138 warnx("can't read superblock on %s: %s", device
,
139 (n
< SBSIZE
) ? "short read" : strerror(errno
));
142 maxino
= sblock
->fs_ncg
* sblock
->fs_ipg
;
144 /* Simple sanity checks on the superblock */
145 if (sblock
->fs_magic
!= FS_MAGIC
) {
146 warnx("bad magic number in superblock");
149 if (sblock
->fs_sbsize
> SBSIZE
) {
150 warnx("superblock size is preposterous");
153 if (sblock
->fs_postblformat
== FS_42POSTBLFMT
) {
154 warnx("filesystem format is too old, sorry");
157 if (!force
&& !printonly
&& sblock
->fs_clean
!= 1) {
158 warnx("filesystem is not clean, fsck %s first", device
);
162 /* Make sure backup superblocks are sane. */
163 sblock
= (struct fs
*)&sbuftmp
;
164 for (cg
= 0; cg
< sblock
->fs_ncg
; cg
++) {
165 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
166 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
167 warn("can't seek to %qd", (off_t
)dblk
* bsize
);
169 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
170 warn("can't read backup superblock %d on %s: %s",
171 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
175 if (sblock
->fs_magic
!= FS_MAGIC
) {
176 warnx("bad magic number in backup superblock %d on %s",
180 if (sblock
->fs_sbsize
> SBSIZE
) {
181 warnx("size of backup superblock %d on %s is preposterous",
186 sblock
= (struct fs
*)&sbuf
;
188 /* XXX - should really cap buffer at 512kb or so */
189 ibufsize
= sizeof(struct ufs1_dinode
) * sblock
->fs_ipg
;
190 if (oldibufsize
< ibufsize
) {
191 if ((inodebuf
= realloc(inodebuf
, ibufsize
)) == NULL
)
192 errx(1, "can't allocate memory for inode buffer");
193 oldibufsize
= ibufsize
;
196 if (printonly
&& (sblock
->fs_id
[0] || sblock
->fs_id
[1])) {
197 if (sblock
->fs_inodefmt
>= FS_44INODEFMT
&& sblock
->fs_id
[0])
198 printf("%s was randomized on %s", device
,
199 ctime((const time_t *)&(sblock
->fs_id
[0])));
200 printf("fsid: %x %x\n", sblock
->fs_id
[0],
204 /* Randomize fs_id unless old 4.2BSD filesystem */
205 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
206 /* Randomize fs_id and write out new sblock and backups */
207 sblock
->fs_id
[0] = (u_int32_t
)time(NULL
);
208 sblock
->fs_id
[1] = random();
210 if (lseek(devfd
, SBOFF
, SEEK_SET
) == -1) {
211 warn("can't seek to superblock (%qd) on %s", SBOFF
,
215 if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
216 warn("can't read superblock on %s: %s", device
,
217 (n
< SBSIZE
) ? "short write" : strerror(errno
));
222 /* For each cylinder group, randomize inodes and update backup sblock */
223 for (cg
= 0, inumber
= 0; cg
< sblock
->fs_ncg
; cg
++) {
224 /* Update superblock if appropriate */
225 if ((sblock
->fs_inodefmt
>= FS_44INODEFMT
) && !printonly
) {
226 dblk
= fsbtodb(sblock
, cgsblock(sblock
, cg
));
227 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
228 warn("can't seek to %qd", (off_t
)dblk
* bsize
);
230 } else if ((n
= write(devfd
, (void *)sblock
, SBSIZE
)) != SBSIZE
) {
231 warn("can't read backup superblock %d on %s: %s",
232 cg
+ 1, device
, (n
< SBSIZE
) ? "short write"
238 /* Read in inodes, then print or randomize generation nums */
239 dblk
= fsbtodb(sblock
, ino_to_fsba(sblock
, inumber
));
240 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
241 warn("can't seek to %qd", (off_t
)dblk
* bsize
);
243 } else if ((n
= read(devfd
, inodebuf
, ibufsize
)) != ibufsize
) {
244 warnx("can't read inodes: %s",
245 (n
< ibufsize
) ? "short read" : strerror(errno
));
249 for (n
= 0; n
< sblock
->fs_ipg
; n
++, inumber
++) {
250 if (inumber
>= ROOTINO
) {
252 printf("ino %d gen %x\n", inumber
,
255 inodebuf
[n
].di_gen
= random();
259 /* Write out modified inodes */
261 if (lseek(devfd
, (off_t
)dblk
* bsize
, SEEK_SET
) < 0) {
262 warn("can't seek to %qd",
263 (off_t
)dblk
* bsize
);
265 } else if ((n
= write(devfd
, inodebuf
, ibufsize
)) !=
267 warnx("can't write inodes: %s",
268 (n
!= ibufsize
) ? "short write" :
283 "usage: fsirand [-b] [-f] [-p] special [special ...]\n");