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
main(int argc,char * argv[])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
isnumber(const char * s)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
read_sb(int fd,const char * dev)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