No empty .Rs/.Re
[netbsd-mini2440.git] / sbin / fsck_lfs / utilities.c
blob38dcb4d388edce416ab007807e8d7fe78afd9a0a
1 /* $NetBSD: utilities.c,v 1.29 2010/01/07 01:39:56 christos Exp $ */
3 /*
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/mount.h>
36 #include <ufs/ufs/inode.h>
37 #include <ufs/ufs/dir.h>
38 #define buf ubuf
39 #define vnode uvnode
40 #include <ufs/lfs/lfs.h>
42 #include <err.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ctype.h>
47 #include <unistd.h>
48 #include <errno.h>
50 #include <signal.h>
52 #include "bufcache.h"
53 #include "vnode.h"
54 #include "lfs_user.h"
55 #include "segwrite.h"
57 #include "fsutil.h"
58 #include "fsck.h"
59 #include "extern.h"
60 #include "exitvalues.h"
62 long diskreads, totalreads; /* Disk cache statistics */
64 extern volatile sig_atomic_t returntosingle;
65 extern off_t locked_queue_bytes;
67 int
68 ftypeok(struct ufs1_dinode * dp)
70 switch (dp->di_mode & IFMT) {
72 case IFDIR:
73 case IFREG:
74 case IFBLK:
75 case IFCHR:
76 case IFLNK:
77 case IFSOCK:
78 case IFIFO:
79 return (1);
81 default:
82 if (debug)
83 pwarn("bad file type 0%o\n", dp->di_mode);
84 return (0);
88 int
89 reply(const char *question)
91 int persevere;
92 char c;
94 if (preen)
95 err(1, "INTERNAL ERROR: GOT TO reply()");
96 persevere = !strcmp(question, "CONTINUE");
97 pwarn("\n");
98 if (!persevere && nflag) {
99 printf("%s? no\n\n", question);
100 return (0);
102 if (yflag || (persevere && nflag)) {
103 printf("%s? yes\n\n", question);
104 return (1);
106 do {
107 printf("%s? [yn] ", question);
108 (void) fflush(stdout);
109 c = getc(stdin);
110 while (c != '\n' && getc(stdin) != '\n')
111 if (feof(stdin))
112 return (0);
113 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
114 printf("\n");
115 if (c == 'y' || c == 'Y')
116 return (1);
117 return (0);
120 static void
121 write_superblocks(void)
123 if (debug)
124 pwarn("writing superblocks with lfs_idaddr = 0x%x\n",
125 (int)fs->lfs_idaddr);
126 lfs_writesuper(fs, fs->lfs_sboffs[0]);
127 lfs_writesuper(fs, fs->lfs_sboffs[1]);
128 fsmodified = 1;
131 void
132 ckfini(int markclean)
134 if (locked_queue_bytes > 0) {
135 if (preen || reply("WRITE CHANGES TO DISK") == 1) {
136 if (preen == 0)
137 pwarn("WRITING CHANGES TO DISK\n");
138 lfs_segwrite(fs, SEGM_CKP);
139 fsdirty = 0;
140 fsmodified = 1;
144 if (!nflag && (fs->lfs_pflags & LFS_PF_CLEAN) == 0) {
145 fs->lfs_pflags |= LFS_PF_CLEAN;
146 fsmodified = 1;
149 if (fsmodified && (preen || reply("UPDATE SUPERBLOCKS"))) {
150 sbdirty();
151 write_superblocks();
153 if (markclean && fsmodified) {
155 * Mark the file system as clean, and sync the superblock.
157 if (preen)
158 pwarn("MARKING FILE SYSTEM CLEAN\n");
159 else if (!reply("MARK FILE SYSTEM CLEAN"))
160 markclean = 0;
161 if (markclean) {
162 fs->lfs_pflags |= LFS_PF_CLEAN;
163 sbdirty();
164 write_superblocks();
165 if (!preen)
166 printf(
167 "\n***** FILE SYSTEM MARKED CLEAN *****\n");
171 if (debug)
172 bufstats();
173 (void) close(fsreadfd);
176 * Free a previously allocated block
178 void
179 freeblk(daddr_t blkno, long frags)
181 struct inodesc idesc;
183 idesc.id_blkno = blkno;
184 idesc.id_numfrags = frags;
185 (void) pass4check(&idesc);
188 * Find a pathname
190 void
191 getpathname(char *namebuf, size_t namebuflen, ino_t curdir, ino_t ino)
193 int len;
194 char *cp;
195 struct inodesc idesc;
196 static int busy = 0;
198 if (curdir == ino && ino == ROOTINO) {
199 (void) strlcpy(namebuf, "/", namebuflen);
200 return;
202 if (busy ||
203 (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
204 (void) strlcpy(namebuf, "?", namebuflen);
205 return;
207 busy = 1;
208 memset(&idesc, 0, sizeof(struct inodesc));
209 idesc.id_type = DATA;
210 idesc.id_fix = IGNORE;
211 cp = &namebuf[MAXPATHLEN - 1];
212 *cp = '\0';
213 if (curdir != ino) {
214 idesc.id_parent = curdir;
215 goto namelookup;
217 while (ino != ROOTINO) {
218 idesc.id_number = ino;
219 idesc.id_func = findino;
220 idesc.id_name = "..";
221 if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
222 break;
223 namelookup:
224 idesc.id_number = idesc.id_parent;
225 idesc.id_parent = ino;
226 idesc.id_func = findname;
227 idesc.id_name = namebuf;
228 if (ginode(idesc.id_number) == NULL)
229 break;
230 if ((ckinode(ginode(idesc.id_number), &idesc) & FOUND) == 0)
231 break;
232 len = strlen(namebuf);
233 cp -= len;
234 memcpy(cp, namebuf, (size_t) len);
235 *--cp = '/';
236 if (cp < &namebuf[LFS_MAXNAMLEN])
237 break;
238 ino = idesc.id_number;
240 busy = 0;
241 if (ino != ROOTINO)
242 *--cp = '?';
243 memcpy(namebuf, cp, (size_t) (&namebuf[MAXPATHLEN] - cp));
246 void
247 catch(int n)
249 ckfini(0);
250 _exit(FSCK_EXIT_SIGNALLED);
253 * When preening, allow a single quit to signal
254 * a special exit after filesystem checks complete
255 * so that reboot sequence may be interrupted.
257 void
258 catchquit(int n)
260 static const char msg[] =
261 "returning to single-user after filesystem check\n";
262 int serrno = errno;
264 (void)write(STDOUT_FILENO, msg, sizeof(msg) - 1);
265 returntosingle = 1;
266 (void) signal(SIGQUIT, SIG_DFL);
267 serrno = errno;
270 * Ignore a single quit signal; wait and flush just in case.
271 * Used by child processes in preen.
273 void
274 voidquit(int n)
276 int serrno = errno;
278 sleep(1);
279 (void) signal(SIGQUIT, SIG_IGN);
280 (void) signal(SIGQUIT, SIG_DFL);
281 errno = serrno;
284 * determine whether an inode should be fixed.
287 dofix(struct inodesc * idesc, const char *msg)
290 switch (idesc->id_fix) {
292 case DONTKNOW:
293 if (idesc->id_type == DATA)
294 direrror(idesc->id_number, msg);
295 else
296 pwarn("%s", msg);
297 if (preen) {
298 printf(" (SALVAGED)\n");
299 idesc->id_fix = FIX;
300 return (ALTERED);
302 if (reply("SALVAGE") == 0) {
303 idesc->id_fix = NOFIX;
304 return (0);
306 idesc->id_fix = FIX;
307 return (ALTERED);
309 case FIX:
310 return (ALTERED);
312 case NOFIX:
313 case IGNORE:
314 return (0);
316 default:
317 err(EEXIT, "UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
319 /* NOTREACHED */