xref: /illumos-gate/usr/src/cmd/fs.d/ufs/clri/clri.c (revision 0fb96ba1f1ce26ff8b286f8f928769a6afcb00a6)
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
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
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
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