xref: /illumos-gate/usr/src/cmd/fs.d/ufs/clri/clri.c (revision fd6d41c5025e9fb45a115fc82d86e9983d1e9fd6)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * Portions of this source code were derived from Berkeley 4.3 BSD
32  * under license from the Regents of the University of California.
33  */
34 
35 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 /*
38  * clri filsys inumber ...
39  */
40 
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <string.h>
47 
48 #include <sys/param.h>
49 #include <sys/types.h>
50 #include <sys/mntent.h>
51 
52 #include <sys/vnode.h>
53 #include <sys/fs/ufs_inode.h>
54 #include <sys/fs/ufs_fs.h>
55 
56 #include "roll_log.h"
57 
58 #define	ISIZE	(sizeof (struct dinode))
59 #define	NI	(MAXBSIZE/ISIZE)
60 
61 static struct dinode buf[NI];
62 
63 static union {
64 	char		dummy[SBSIZE];
65 	struct fs	sblk;
66 } sb_un;
67 #define	sblock sb_un.sblk
68 
69 static int status;
70 
71 static int read_sb(int fd, const char *dev);
72 static int isnumber(const char *s);
73 
74 int
75 main(int argc, char *argv[])
76 {
77 	int		i, f;
78 	unsigned int	n;
79 	int		j;
80 	offset_t	off;
81 	int32_t		gen;
82 	time_t		t;
83 	int		sbrr;
84 
85 	if (argc < 3) {
86 		(void) printf("ufs usage: clri filsys inumber ...\n");
87 		return (35);
88 	}
89 	f = open64(argv[1], 2);
90 	if (f < 0) {
91 		(void) printf("cannot open %s\n", argv[1]);
92 		return (35);
93 	}
94 
95 	if ((sbrr = read_sb(f, argv[1])) != 0) {
96 		return (sbrr);
97 	}
98 
99 	if ((sblock.fs_magic != FS_MAGIC) &&
100 	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
101 		(void) printf("bad super block magic number\n");
102 		return (35);
103 	}
104 
105 	if (sblock.fs_magic == FS_MAGIC &&
106 	    (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
107 	    sblock.fs_version != UFS_VERSION_MIN)) {
108 		(void) printf(
109 		    "unrecognized version of UFS on-disk format: %d\n",
110 		    sblock.fs_version);
111 		return (35);
112 	}
113 
114 	if (sblock.fs_magic == MTB_UFS_MAGIC &&
115 	    (sblock.fs_version > MTB_UFS_VERSION_1 ||
116 	    sblock.fs_version < MTB_UFS_VERSION_MIN)) {
117 		(void) printf(
118 		    "unrecognized version of UFS on-disk format: %d\n",
119 		    sblock.fs_version);
120 		return (35);
121 	}
122 
123 	/* If fs is logged, roll the log. */
124 	if (sblock.fs_logbno) {
125 		switch (rl_roll_log(argv[1])) {
126 		case RL_SUCCESS:
127 			/*
128 			 * Reread the superblock.  Rolling the log may have
129 			 * changed it.
130 			 */
131 			if ((sbrr = read_sb(f, argv[1])) != 0) {
132 				return (sbrr);
133 			}
134 			break;
135 		case RL_SYSERR:
136 			(void) printf("Warning: Cannot roll log for %s.  %s.  "
137 				"Inodes will be cleared anyway.\n",
138 				argv[1], strerror(errno));
139 			break;
140 		default:
141 			(void) printf("Cannot roll log for %s.  "
142 				"Inodes will be cleared anyway.\n",
143 				argv[1]);
144 			break;
145 		}
146 	}
147 
148 	for (i = 2; i < argc; i++) {
149 		if (!isnumber(argv[i])) {
150 			(void) printf("%s: is not a number\n", argv[i]);
151 			status = 1;
152 			continue;
153 		}
154 		n = atoi(argv[i]);
155 		if (n == 0) {
156 			(void) printf("%s: is zero\n", argv[i]);
157 			status = 1;
158 			continue;
159 		}
160 		off = fsbtodb(&sblock, itod(&sblock, n));
161 		off *= DEV_BSIZE;
162 		(void) llseek(f, off, 0);
163 		if (read(f, (char *)buf, sblock.fs_bsize) != sblock.fs_bsize) {
164 			(void) printf("%s: read error\n", argv[i]);
165 			status = 1;
166 		}
167 	}
168 	if (status)
169 		return (status+31);
170 
171 	/*
172 	 * Update the time in superblock, so fsck will check this filesystem.
173 	 */
174 	(void) llseek(f, (offset_t)(SBLOCK * DEV_BSIZE), 0);
175 	(void) time(&t);
176 	sblock.fs_time = (time32_t)t;
177 	if (write(f, &sblock, SBSIZE) != SBSIZE) {
178 		(void) printf("cannot update %s\n", argv[1]);
179 		return (35);
180 	}
181 
182 	for (i = 2; i < argc; i++) {
183 		n = atoi(argv[i]);
184 		(void) printf("clearing %u\n", n);
185 		off = fsbtodb(&sblock, itod(&sblock, n));
186 		off *= DEV_BSIZE;
187 		(void) llseek(f, off, 0);
188 		(void) read(f, (char *)buf, sblock.fs_bsize);
189 		j = itoo(&sblock, n);
190 		gen = buf[j].di_gen;
191 		memset(&buf[j], 0, ISIZE);
192 		buf[j].di_gen = gen + 1;
193 		(void) llseek(f, off, 0);
194 		(void) write(f, (char *)buf, sblock.fs_bsize);
195 	}
196 	if (status)
197 		return (status+31);
198 	(void) close(f);
199 	return (0);
200 }
201 
202 static int
203 isnumber(const char *s)
204 {
205 	int c;
206 
207 	while ((c = *s++) != '\0')
208 		if (c < '0' || c > '9')
209 			return (0);
210 	return (1);
211 }
212 
213 static int
214 read_sb(int fd, const char *dev)
215 {
216 	(void) llseek(fd, (offset_t)(SBLOCK * DEV_BSIZE), 0);
217 	if (read(fd, &sblock, SBSIZE) != SBSIZE) {
218 		(void) printf("cannot read %s\n", dev);
219 		return (35);
220 	} else {
221 		return (0);
222 	}
223 }
224