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 /*
36 * clri filsys inumber ...
37 */
38
39 #include <unistd.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <string.h>
45
46 #include <sys/param.h>
47 #include <sys/types.h>
48 #include <sys/mntent.h>
49
50 #include <sys/vnode.h>
51 #include <sys/fs/ufs_inode.h>
52 #include <sys/fs/ufs_fs.h>
53
54 #include "roll_log.h"
55
56 #define ISIZE (sizeof (struct dinode))
57 #define NI (MAXBSIZE/ISIZE)
58
59 static struct dinode buf[NI];
60
61 static union {
62 char dummy[SBSIZE];
63 struct fs sblk;
64 } sb_un;
65 #define sblock sb_un.sblk
66
67 static int status;
68
69 static int read_sb(int fd, const char *dev);
70 static int isnumber(const char *s);
71
72 int
main(int argc,char * argv[])73 main(int argc, char *argv[])
74 {
75 int i, f;
76 unsigned int n;
77 int j;
78 offset_t off;
79 int32_t gen;
80 time_t t;
81 int sbrr;
82
83 if (argc < 3) {
84 (void) printf("ufs usage: clri filsys inumber ...\n");
85 return (35);
86 }
87 f = open64(argv[1], 2);
88 if (f < 0) {
89 (void) printf("cannot open %s\n", argv[1]);
90 return (35);
91 }
92
93 if ((sbrr = read_sb(f, argv[1])) != 0) {
94 return (sbrr);
95 }
96
97 if ((sblock.fs_magic != FS_MAGIC) &&
98 (sblock.fs_magic != MTB_UFS_MAGIC)) {
99 (void) printf("bad super block magic number\n");
100 return (35);
101 }
102
103 if (sblock.fs_magic == FS_MAGIC &&
104 (sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
105 sblock.fs_version != UFS_VERSION_MIN)) {
106 (void) printf(
107 "unrecognized version of UFS on-disk format: %d\n",
108 sblock.fs_version);
109 return (35);
110 }
111
112 if (sblock.fs_magic == MTB_UFS_MAGIC &&
113 (sblock.fs_version > MTB_UFS_VERSION_1 ||
114 sblock.fs_version < MTB_UFS_VERSION_MIN)) {
115 (void) printf(
116 "unrecognized version of UFS on-disk format: %d\n",
117 sblock.fs_version);
118 return (35);
119 }
120
121 /* If fs is logged, roll the log. */
122 if (sblock.fs_logbno) {
123 switch (rl_roll_log(argv[1])) {
124 case RL_SUCCESS:
125 /*
126 * Reread the superblock. Rolling the log may have
127 * changed it.
128 */
129 if ((sbrr = read_sb(f, argv[1])) != 0) {
130 return (sbrr);
131 }
132 break;
133 case RL_SYSERR:
134 (void) printf("Warning: Cannot roll log for %s. %s. "
135 "Inodes will be cleared anyway.\n",
136 argv[1], strerror(errno));
137 break;
138 default:
139 (void) printf("Cannot roll log for %s. "
140 "Inodes will be cleared anyway.\n",
141 argv[1]);
142 break;
143 }
144 }
145
146 for (i = 2; i < argc; i++) {
147 if (!isnumber(argv[i])) {
148 (void) printf("%s: is not a number\n", argv[i]);
149 status = 1;
150 continue;
151 }
152 n = atoi(argv[i]);
153 if (n == 0) {
154 (void) printf("%s: is zero\n", argv[i]);
155 status = 1;
156 continue;
157 }
158 off = fsbtodb(&sblock, itod(&sblock, n));
159 off *= DEV_BSIZE;
160 (void) llseek(f, off, 0);
161 if (read(f, (char *)buf, sblock.fs_bsize) != sblock.fs_bsize) {
162 (void) printf("%s: read error\n", argv[i]);
163 status = 1;
164 }
165 }
166 if (status)
167 return (status+31);
168
169 /*
170 * Update the time in superblock, so fsck will check this filesystem.
171 */
172 (void) llseek(f, (offset_t)(SBLOCK * DEV_BSIZE), 0);
173 (void) time(&t);
174 sblock.fs_time = (time32_t)t;
175 if (write(f, &sblock, SBSIZE) != SBSIZE) {
176 (void) printf("cannot update %s\n", argv[1]);
177 return (35);
178 }
179
180 for (i = 2; i < argc; i++) {
181 n = atoi(argv[i]);
182 (void) printf("clearing %u\n", n);
183 off = fsbtodb(&sblock, itod(&sblock, n));
184 off *= DEV_BSIZE;
185 (void) llseek(f, off, 0);
186 (void) read(f, (char *)buf, sblock.fs_bsize);
187 j = itoo(&sblock, n);
188 gen = buf[j].di_gen;
189 memset(&buf[j], 0, ISIZE);
190 buf[j].di_gen = gen + 1;
191 (void) llseek(f, off, 0);
192 (void) write(f, (char *)buf, sblock.fs_bsize);
193 }
194 if (status)
195 return (status+31);
196 (void) close(f);
197 return (0);
198 }
199
200 static int
isnumber(const char * s)201 isnumber(const char *s)
202 {
203 int c;
204
205 while ((c = *s++) != '\0')
206 if (c < '0' || c > '9')
207 return (0);
208 return (1);
209 }
210
211 static int
read_sb(int fd,const char * dev)212 read_sb(int fd, const char *dev)
213 {
214 (void) llseek(fd, (offset_t)(SBLOCK * DEV_BSIZE), 0);
215 if (read(fd, &sblock, SBSIZE) != SBSIZE) {
216 (void) printf("cannot read %s\n", dev);
217 return (35);
218 } else {
219 return (0);
220 }
221 }
222