xref: /freebsd/sbin/fsirand/fsirand.c (revision eba230afba4932f02a1ca44efc797cf7499a5cb0)
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