18f89943eSGuido van Rooij /* $OpenBSD: fsirand.c,v 1.9 1997/02/28 00:46:33 millert Exp $ */
28f89943eSGuido van Rooij
31de7b4b8SPedro F. Giffuni /*-
4*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni *
68f89943eSGuido van Rooij * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
78f89943eSGuido van Rooij * All rights reserved.
88f89943eSGuido van Rooij *
98f89943eSGuido van Rooij * Redistribution and use in source and binary forms, with or without
108f89943eSGuido van Rooij * modification, are permitted provided that the following conditions
118f89943eSGuido van Rooij * are met:
128f89943eSGuido van Rooij * 1. Redistributions of source code must retain the above copyright
138f89943eSGuido van Rooij * notice, this list of conditions and the following disclaimer.
148f89943eSGuido van Rooij * 2. Redistributions in binary form must reproduce the above copyright
158f89943eSGuido van Rooij * notice, this list of conditions and the following disclaimer in the
168f89943eSGuido van Rooij * documentation and/or other materials provided with the distribution.
178f89943eSGuido van Rooij * 3. All advertising materials mentioning features or use of this software
188f89943eSGuido van Rooij * must display the following acknowledgement:
198f89943eSGuido van Rooij * This product includes software developed by Todd C. Miller.
208f89943eSGuido van Rooij * 4. The name of the author may not be used to endorse or promote products
218f89943eSGuido van Rooij * derived from this software without specific prior written permission.
228f89943eSGuido van Rooij *
238f89943eSGuido van Rooij * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
248f89943eSGuido van Rooij * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
258f89943eSGuido van Rooij * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
268f89943eSGuido van Rooij * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
278f89943eSGuido van Rooij * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
288f89943eSGuido van Rooij * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
298f89943eSGuido van Rooij * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
308f89943eSGuido van Rooij * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
318f89943eSGuido van Rooij * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
328f89943eSGuido van Rooij * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338f89943eSGuido van Rooij */
348f89943eSGuido van Rooij
358f89943eSGuido van Rooij #include <sys/param.h>
368f89943eSGuido van Rooij #include <sys/resource.h>
378f89943eSGuido van Rooij
388f89943eSGuido van Rooij #include <ufs/ufs/dinode.h>
391c85e6a3SKirk McKusick #include <ufs/ffs/fs.h>
408f89943eSGuido van Rooij
418f89943eSGuido van Rooij #include <err.h>
428f89943eSGuido van Rooij #include <errno.h>
438f89943eSGuido van Rooij #include <fcntl.h>
44dffce215SKirk McKusick #include <libufs.h>
458f89943eSGuido van Rooij #include <stdio.h>
46bbdc11d2SUlrich Spörlein #include <stdint.h>
478f89943eSGuido van Rooij #include <stdlib.h>
488f89943eSGuido van Rooij #include <string.h>
497649cb00SKirk McKusick #include <time.h>
508f89943eSGuido van Rooij #include <unistd.h>
518f89943eSGuido van Rooij
520638cc1aSWarner Losh static void usage(void) __dead2;
530638cc1aSWarner Losh int fsirand(char *);
548f89943eSGuido van Rooij
551efe3c6bSEd Schouten static int printonly = 0, force = 0, ignorelabel = 0;
568f89943eSGuido van Rooij
578f89943eSGuido van Rooij int
main(int argc,char * argv[])580638cc1aSWarner Losh main(int argc, char *argv[])
598f89943eSGuido van Rooij {
608f89943eSGuido van Rooij int n, ex = 0;
618f89943eSGuido van Rooij struct rlimit rl;
628f89943eSGuido van Rooij
638f89943eSGuido van Rooij while ((n = getopt(argc, argv, "bfp")) != -1) {
648f89943eSGuido van Rooij switch (n) {
658f89943eSGuido van Rooij case 'b':
668f89943eSGuido van Rooij ignorelabel++;
678f89943eSGuido van Rooij break;
688f89943eSGuido van Rooij case 'p':
698f89943eSGuido van Rooij printonly++;
708f89943eSGuido van Rooij break;
718f89943eSGuido van Rooij case 'f':
728f89943eSGuido van Rooij force++;
738f89943eSGuido van Rooij break;
748f89943eSGuido van Rooij default:
75c27b7badSPhilippe Charnier usage();
768f89943eSGuido van Rooij }
778f89943eSGuido van Rooij }
788f89943eSGuido van Rooij if (argc - optind < 1)
79c27b7badSPhilippe Charnier usage();
808f89943eSGuido van Rooij
818f89943eSGuido van Rooij /* Increase our data size to the max */
828f89943eSGuido van Rooij if (getrlimit(RLIMIT_DATA, &rl) == 0) {
838f89943eSGuido van Rooij rl.rlim_cur = rl.rlim_max;
848f89943eSGuido van Rooij if (setrlimit(RLIMIT_DATA, &rl) < 0)
85c27b7badSPhilippe Charnier warn("can't get resource limit to max data size");
868f89943eSGuido van Rooij } else
87c27b7badSPhilippe Charnier warn("can't get resource limit for data size");
888f89943eSGuido van Rooij
898f89943eSGuido van Rooij for (n = optind; n < argc; n++) {
908f89943eSGuido van Rooij if (argc - optind != 1)
918f89943eSGuido van Rooij (void)puts(argv[n]);
928f89943eSGuido van Rooij ex += fsirand(argv[n]);
938f89943eSGuido van Rooij if (n < argc - 1)
948f89943eSGuido van Rooij putchar('\n');
958f89943eSGuido van Rooij }
968f89943eSGuido van Rooij
978f89943eSGuido van Rooij exit(ex);
988f89943eSGuido van Rooij }
998f89943eSGuido van Rooij
1008f89943eSGuido van Rooij int
fsirand(char * device)1010638cc1aSWarner Losh fsirand(char *device)
1028f89943eSGuido van Rooij {
1031c85e6a3SKirk McKusick struct ufs1_dinode *dp1;
1041c85e6a3SKirk McKusick struct ufs2_dinode *dp2;
1051c85e6a3SKirk McKusick caddr_t inodebuf;
106bbdc11d2SUlrich Spörlein ssize_t ibufsize;
1078f89943eSGuido van Rooij struct fs *sblock;
108507d0cc9SEitan Adler ino_t inumber;
109dffce215SKirk McKusick ufs2_daddr_t dblk;
110b21582eeSKirk McKusick int devfd, n, cg;
1118f89943eSGuido van Rooij u_int32_t bsize = DEV_BSIZE;
1128f89943eSGuido van Rooij
1138f89943eSGuido van Rooij if ((devfd = open(device, printonly ? O_RDONLY : O_RDWR)) < 0) {
114c27b7badSPhilippe Charnier warn("can't open %s", device);
1158f89943eSGuido van Rooij return (1);
1168f89943eSGuido van Rooij }
1178f89943eSGuido van Rooij
118bbdc11d2SUlrich Spörlein dp1 = NULL;
119bbdc11d2SUlrich Spörlein dp2 = NULL;
120bbdc11d2SUlrich Spörlein
1218f89943eSGuido van Rooij /* Read in master superblock */
122b21582eeSKirk McKusick if ((errno = sbget(devfd, &sblock, UFS_STDSB, UFS_NOCSUM)) != 0) {
123b21582eeSKirk McKusick switch (errno) {
124dffce215SKirk McKusick case ENOENT:
125b21582eeSKirk McKusick warnx("Cannot find file system superblock");
126dffce215SKirk McKusick return (1);
127dffce215SKirk McKusick default:
128dffce215SKirk McKusick warn("Unable to read file system superblock");
1298f89943eSGuido van Rooij return (1);
1308f89943eSGuido van Rooij }
1318f89943eSGuido van Rooij }
1326eb925f8SKirk McKusick /*
1336eb925f8SKirk McKusick * Check for unclean filesystem.
1346eb925f8SKirk McKusick */
1356eb925f8SKirk McKusick if (sblock->fs_clean == 0 ||
1366eb925f8SKirk McKusick (sblock->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) != 0)
1376eb925f8SKirk McKusick errx(1, "%s is not clean - run fsck.\n", device);
1388f89943eSGuido van Rooij
1391c85e6a3SKirk McKusick if (sblock->fs_magic == FS_UFS1_MAGIC &&
1401c85e6a3SKirk McKusick sblock->fs_old_inodefmt < FS_44INODEFMT) {
141c27b7badSPhilippe Charnier warnx("file system format is too old, sorry");
1428f89943eSGuido van Rooij return (1);
1438f89943eSGuido van Rooij }
1448f89943eSGuido van Rooij if (!force && !printonly && sblock->fs_clean != 1) {
145c27b7badSPhilippe Charnier warnx("file system is not clean, fsck %s first", device);
1468f89943eSGuido van Rooij return (1);
1478f89943eSGuido van Rooij }
1488f89943eSGuido van Rooij
1498f89943eSGuido van Rooij /* XXX - should really cap buffer at 512kb or so */
1501c85e6a3SKirk McKusick if (sblock->fs_magic == FS_UFS1_MAGIC)
1511c85e6a3SKirk McKusick ibufsize = sizeof(struct ufs1_dinode) * sblock->fs_ipg;
1521c85e6a3SKirk McKusick else
1531c85e6a3SKirk McKusick ibufsize = sizeof(struct ufs2_dinode) * sblock->fs_ipg;
1541c85e6a3SKirk McKusick if ((inodebuf = malloc(ibufsize)) == NULL)
155c27b7badSPhilippe Charnier errx(1, "can't allocate memory for inode buffer");
1568f89943eSGuido van Rooij
1578f89943eSGuido van Rooij if (printonly && (sblock->fs_id[0] || sblock->fs_id[1])) {
1581c85e6a3SKirk McKusick if (sblock->fs_id[0])
1598f89943eSGuido van Rooij (void)printf("%s was randomized on %s", device,
160bbdc11d2SUlrich Spörlein ctime((void *)&(sblock->fs_id[0])));
1618f89943eSGuido van Rooij (void)printf("fsid: %x %x\n", sblock->fs_id[0],
1628f89943eSGuido van Rooij sblock->fs_id[1]);
1638f89943eSGuido van Rooij }
1648f89943eSGuido van Rooij
1658f89943eSGuido van Rooij /* Randomize fs_id unless old 4.2BSD file system */
1661c85e6a3SKirk McKusick if (!printonly) {
1678f89943eSGuido van Rooij /* Randomize fs_id and write out new sblock and backups */
1688f89943eSGuido van Rooij sblock->fs_id[0] = (u_int32_t)time(NULL);
169d82e4d75SConrad Meyer sblock->fs_id[1] = arc4random();
170dffce215SKirk McKusick if (sbput(devfd, sblock, sblock->fs_ncg) != 0) {
171dffce215SKirk McKusick warn("could not write updated superblock");
1728f89943eSGuido van Rooij return (1);
1738f89943eSGuido van Rooij }
1748f89943eSGuido van Rooij }
1758f89943eSGuido van Rooij
1768f89943eSGuido van Rooij /* For each cylinder group, randomize inodes and update backup sblock */
1779fc5d538SKirk McKusick for (cg = 0, inumber = UFS_ROOTINO; cg < (int)sblock->fs_ncg; cg++) {
1788f89943eSGuido van Rooij /* Read in inodes, then print or randomize generation nums */
1798f89943eSGuido van Rooij dblk = fsbtodb(sblock, ino_to_fsba(sblock, inumber));
1808f89943eSGuido van Rooij if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
181bbdc11d2SUlrich Spörlein warn("can't seek to %jd", (intmax_t)dblk * bsize);
1828f89943eSGuido van Rooij return (1);
1838f89943eSGuido van Rooij } else if ((n = read(devfd, inodebuf, ibufsize)) != ibufsize) {
184c27b7badSPhilippe Charnier warnx("can't read inodes: %s",
1858f89943eSGuido van Rooij (n < ibufsize) ? "short read" : strerror(errno));
1868f89943eSGuido van Rooij return (1);
1878f89943eSGuido van Rooij }
1888f89943eSGuido van Rooij
1899fc5d538SKirk McKusick dp1 = (struct ufs1_dinode *)(void *)inodebuf;
1909fc5d538SKirk McKusick dp2 = (struct ufs2_dinode *)(void *)inodebuf;
1919fc5d538SKirk McKusick for (n = cg > 0 ? 0 : UFS_ROOTINO;
1929fc5d538SKirk McKusick n < (int)sblock->fs_ipg;
1939fc5d538SKirk McKusick n++, inumber++) {
1949fc5d538SKirk McKusick if (printonly) {
195e25a029eSMatthew D Fleming (void)printf("ino %ju gen %08x\n",
196e25a029eSMatthew D Fleming (uintmax_t)inumber,
1971c85e6a3SKirk McKusick sblock->fs_magic == FS_UFS1_MAGIC ?
198bbdc11d2SUlrich Spörlein dp1->di_gen : dp2->di_gen);
1999fc5d538SKirk McKusick } else if (sblock->fs_magic == FS_UFS1_MAGIC) {
2009fc5d538SKirk McKusick dp1->di_gen = arc4random();
2019fc5d538SKirk McKusick dp1++;
2029fc5d538SKirk McKusick } else {
2039fc5d538SKirk McKusick dp2->di_gen = arc4random();
2048f829a5cSKirk McKusick ffs_update_dinode_ckhash(sblock, dp2);
2059fc5d538SKirk McKusick dp2++;
2068f89943eSGuido van Rooij }
2078f89943eSGuido van Rooij }
2088f89943eSGuido van Rooij
2098f89943eSGuido van Rooij /* Write out modified inodes */
2108f89943eSGuido van Rooij if (!printonly) {
2118f89943eSGuido van Rooij if (lseek(devfd, (off_t)dblk * bsize, SEEK_SET) < 0) {
212bbdc11d2SUlrich Spörlein warn("can't seek to %jd",
213bbdc11d2SUlrich Spörlein (intmax_t)dblk * bsize);
2148f89943eSGuido van Rooij return (1);
2158f89943eSGuido van Rooij } else if ((n = write(devfd, inodebuf, ibufsize)) !=
2168f89943eSGuido van Rooij ibufsize) {
217c27b7badSPhilippe Charnier warnx("can't write inodes: %s",
2188f89943eSGuido van Rooij (n != ibufsize) ? "short write" :
2198f89943eSGuido van Rooij strerror(errno));
2208f89943eSGuido van Rooij return (1);
2218f89943eSGuido van Rooij }
2228f89943eSGuido van Rooij }
2238f89943eSGuido van Rooij }
2248f89943eSGuido van Rooij (void)close(devfd);
2258f89943eSGuido van Rooij
2268f89943eSGuido van Rooij return(0);
2278f89943eSGuido van Rooij }
2288f89943eSGuido van Rooij
229c9ea311aSPhilippe Charnier static void
usage(void)2300638cc1aSWarner Losh usage(void)
2318f89943eSGuido van Rooij {
232e2bb969aSGuido van Rooij (void)fprintf(stderr,
233c9ea311aSPhilippe Charnier "usage: fsirand [-b] [-f] [-p] special [special ...]\n");
234c27b7badSPhilippe Charnier exit(1);
2358f89943eSGuido van Rooij }
236