1*45db36d8Sandvar /* $NetBSD: clri.c,v 1.26 2023/02/26 22:55:02 andvar Exp $ */
20114e805Scgd
361f28255Scgd /*
4175ecf65Smycroft * Copyright (c) 1990, 1993
5175ecf65Smycroft * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * This code is derived from software contributed to Berkeley by
861f28255Scgd * Rich $alz of BBN Inc.
961f28255Scgd *
1061f28255Scgd * Redistribution and use in source and binary forms, with or without
1161f28255Scgd * modification, are permitted provided that the following conditions
1261f28255Scgd * are met:
1361f28255Scgd * 1. Redistributions of source code must retain the above copyright
1461f28255Scgd * notice, this list of conditions and the following disclaimer.
1561f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1661f28255Scgd * notice, this list of conditions and the following disclaimer in the
1761f28255Scgd * documentation and/or other materials provided with the distribution.
18bf07c871Sagc * 3. Neither the name of the University nor the names of its contributors
1961f28255Scgd * may be used to endorse or promote products derived from this software
2061f28255Scgd * without specific prior written permission.
2161f28255Scgd *
2261f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2361f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2461f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2561f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2661f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2761f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2861f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2961f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3061f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3161f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261f28255Scgd * SUCH DAMAGE.
3361f28255Scgd */
3461f28255Scgd
35e40e4b2aSlukem #include <sys/cdefs.h>
3661f28255Scgd #ifndef lint
376543a91fSlukem __COPYRIGHT("@(#) Copyright (c) 1990, 1993\
386543a91fSlukem The Regents of the University of California. All rights reserved.");
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd #ifndef lint
420114e805Scgd #if 0
43c697e3e2Slukem static char sccsid[] = "@(#)clri.c 8.3 (Berkeley) 4/28/95";
440114e805Scgd #else
45*45db36d8Sandvar __RCSID("$NetBSD: clri.c,v 1.26 2023/02/26 22:55:02 andvar Exp $");
460114e805Scgd #endif
4761f28255Scgd #endif /* not lint */
4861f28255Scgd
4961f28255Scgd #include <sys/param.h>
504417e586Scgd #include <sys/time.h>
51175ecf65Smycroft
52175ecf65Smycroft #include <ufs/ufs/dinode.h>
5308371645Sbouyer #include <ufs/ufs/ufs_bswap.h>
54175ecf65Smycroft #include <ufs/ffs/fs.h>
5508371645Sbouyer #include <ufs/ffs/ffs_extern.h>
56175ecf65Smycroft
57175ecf65Smycroft #include <err.h>
5861f28255Scgd #include <errno.h>
59175ecf65Smycroft #include <fcntl.h>
60175ecf65Smycroft #include <stdlib.h>
61175ecf65Smycroft #include <string.h>
62175ecf65Smycroft #include <stdio.h>
63175ecf65Smycroft #include <unistd.h>
6461f28255Scgd
6542614ed3Sfvdl /*
6642614ed3Sfvdl * Possible superblock locations ordered from most to least likely.
6742614ed3Sfvdl */
6842614ed3Sfvdl static off_t sblock_try[] = SBLOCKSEARCH;
6942614ed3Sfvdl off_t sblockloc;
7042614ed3Sfvdl
7142614ed3Sfvdl
72175ecf65Smycroft int
main(int argc,char * argv[])7310928b72Sxtraeme main(int argc, char *argv[])
7461f28255Scgd {
75e40e4b2aSlukem struct fs *sbp;
7642614ed3Sfvdl struct ufs1_dinode *ip1;
7742614ed3Sfvdl struct ufs2_dinode *ip2;
78e40e4b2aSlukem int fd;
79e05b6497Sdholland void *ibuf;
806e6fa279Smycroft int32_t generation;
81175ecf65Smycroft off_t offset;
826e6fa279Smycroft size_t bsize;
8361f28255Scgd int inonum;
8442614ed3Sfvdl char *fs, sblock[SBLOCKSIZE];
8542614ed3Sfvdl int needswap = 0, is_ufs2 = 0;
8608371645Sbouyer int i, imax;
8777d8bce2Smlelstv long dev_bsize;
8861f28255Scgd
8961f28255Scgd if (argc < 3) {
9061f28255Scgd (void)fprintf(stderr, "usage: clri filesystem inode ...\n");
9161f28255Scgd exit(1);
9261f28255Scgd }
9361f28255Scgd
9461f28255Scgd fs = *++argv;
9561f28255Scgd
9608371645Sbouyer
9761f28255Scgd /* get the superblock. */
9861f28255Scgd if ((fd = open(fs, O_RDWR, 0)) < 0)
99175ecf65Smycroft err(1, "%s", fs);
100d332d2a9Sdsl for (i = 0;; i++) {
101d332d2a9Sdsl sblockloc = sblock_try[i];
102d332d2a9Sdsl if (sblockloc == -1)
103d332d2a9Sdsl errx(1, "%s: can't find superblock", fs);
104d332d2a9Sdsl if (pread(fd, sblock, sizeof(sblock), sblockloc) != sizeof(sblock))
1058ffd59e2Smycroft errx(1, "%s: can't read superblock", fs);
10661f28255Scgd
10761f28255Scgd sbp = (struct fs *)sblock;
10842614ed3Sfvdl switch(sbp->fs_magic) {
10942614ed3Sfvdl case FS_UFS2_MAGIC:
11087ba0e2aSchs case FS_UFS2EA_MAGIC:
11142614ed3Sfvdl is_ufs2 = 1;
11242614ed3Sfvdl /*FALLTHROUGH*/
11342614ed3Sfvdl case FS_UFS1_MAGIC:
114d332d2a9Sdsl break;
11542614ed3Sfvdl case FS_UFS2_MAGIC_SWAPPED:
11687ba0e2aSchs case FS_UFS2EA_MAGIC_SWAPPED:
11742614ed3Sfvdl is_ufs2 = 1;
11842614ed3Sfvdl /*FALLTHROUGH*/
11942614ed3Sfvdl case FS_UFS1_MAGIC_SWAPPED:
12008371645Sbouyer needswap = 1;
121d332d2a9Sdsl break;
12242614ed3Sfvdl default:
12342614ed3Sfvdl continue;
124029a64ccSross }
12508371645Sbouyer
126d332d2a9Sdsl /* check we haven't found an alternate */
1272f7a90efSdsl if (is_ufs2 || sbp->fs_old_flags & FS_FLAGS_UPDATED) {
12807f76885Slukem if ((uint64_t)sblockloc != ufs_rw64(sbp->fs_sblockloc, needswap))
129d332d2a9Sdsl continue;
130d332d2a9Sdsl } else {
131d332d2a9Sdsl if (sblockloc == SBLOCK_UFS2)
132d332d2a9Sdsl continue;
133d332d2a9Sdsl }
134d332d2a9Sdsl
135d332d2a9Sdsl break;
136d332d2a9Sdsl }
137d332d2a9Sdsl
13808371645Sbouyer /* check that inode numbers are valid */
13908371645Sbouyer imax = ufs_rw32(sbp->fs_ncg, needswap) *
14008371645Sbouyer ufs_rw32(sbp->fs_ipg, needswap);
14108371645Sbouyer for (i = 1; i < (argc - 1); i++)
14208371645Sbouyer if (atoi(argv[i]) <= 0 || atoi(argv[i]) >= imax)
14308371645Sbouyer errx(1, "%s is not a valid inode number", argv[i]);
14408371645Sbouyer
145*45db36d8Sandvar /* delete clean flag in the superblock */
146d332d2a9Sdsl sbp->fs_clean = ufs_rw32(ufs_rw32(sbp->fs_clean, needswap) << 1,
14708371645Sbouyer needswap);
14842614ed3Sfvdl if (lseek(fd, sblockloc, SEEK_SET) < 0)
14908371645Sbouyer err(1, "%s", fs);
15008371645Sbouyer if (write(fd, sblock, sizeof(sblock)) != sizeof(sblock))
15108371645Sbouyer errx(1, "%s: can't rewrite superblock", fs);
15208371645Sbouyer (void)fsync(fd);
15308371645Sbouyer
15408371645Sbouyer if (needswap)
1551b81d635Slukem ffs_sb_swap(sbp, sbp);
156e05b6497Sdholland
15777d8bce2Smlelstv /* compute disk block size from superblock parameters */
15877d8bce2Smlelstv dev_bsize = sbp->fs_fsize / FFS_FSBTODB(sbp, 1);
15977d8bce2Smlelstv
16061f28255Scgd bsize = sbp->fs_bsize;
161e05b6497Sdholland ibuf = malloc(bsize);
162e05b6497Sdholland if (ibuf == NULL) {
163e05b6497Sdholland err(1, "malloc");
164e05b6497Sdholland }
16561f28255Scgd
16661f28255Scgd /* remaining arguments are inode numbers. */
16761f28255Scgd while (*++argv) {
16861f28255Scgd /* get the inode number. */
16908371645Sbouyer inonum = atoi(*argv);
17061f28255Scgd (void)printf("clearing %d\n", inonum);
17161f28255Scgd
17261f28255Scgd /* read in the appropriate block. */
173175ecf65Smycroft offset = ino_to_fsba(sbp, inonum); /* inode to fs blk */
1742737439dSdholland offset = FFS_FSBTODB(sbp, offset); /* fs blk disk blk */
17577d8bce2Smlelstv offset *= dev_bsize; /* disk blk to bytes */
17661f28255Scgd
17761f28255Scgd /* seek and read the block */
17861f28255Scgd if (lseek(fd, offset, SEEK_SET) < 0)
179175ecf65Smycroft err(1, "%s", fs);
18007f76885Slukem if ((size_t)read(fd, ibuf, bsize) != bsize)
181175ecf65Smycroft err(1, "%s", fs);
18261f28255Scgd
18361f28255Scgd /* get the inode within the block. */
18442614ed3Sfvdl if (is_ufs2) {
18542614ed3Sfvdl ip2 = &((struct ufs2_dinode *)ibuf)
18642614ed3Sfvdl [ino_to_fsbo(sbp, inonum)];
18761f28255Scgd /* clear the inode, and bump the generation count. */
18842614ed3Sfvdl generation = ip2->di_gen + 1;
18942614ed3Sfvdl memset(ip2, 0, sizeof(*ip2));
19042614ed3Sfvdl ip2->di_gen = generation;
19142614ed3Sfvdl } else {
19242614ed3Sfvdl ip1 = &((struct ufs1_dinode *)ibuf)
19342614ed3Sfvdl [ino_to_fsbo(sbp, inonum)];
19442614ed3Sfvdl /* clear the inode, and bump the generation count. */
19542614ed3Sfvdl generation = ip1->di_gen + 1;
19642614ed3Sfvdl memset(ip1, 0, sizeof(*ip1));
19742614ed3Sfvdl ip1->di_gen = generation;
19842614ed3Sfvdl }
19961f28255Scgd
20061f28255Scgd /* backup and write the block */
2016e6fa279Smycroft if (lseek(fd, offset, SEEK_SET) < 0)
202175ecf65Smycroft err(1, "%s", fs);
20307f76885Slukem if ((size_t)write(fd, ibuf, bsize) != bsize)
204175ecf65Smycroft err(1, "%s", fs);
20561f28255Scgd (void)fsync(fd);
20661f28255Scgd }
207e05b6497Sdholland free(ibuf);
20861f28255Scgd (void)close(fd);
20961f28255Scgd exit(0);
21061f28255Scgd }
211