1 /* $NetBSD: utilities.c,v 1.29 2010/01/07 01:39:56 christos Exp $ */
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
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
32 #include <sys/param.h>
34 #include <sys/mount.h>
36 #include <ufs/ufs/inode.h>
37 #include <ufs/ufs/dir.h>
40 #include <ufs/lfs/lfs.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
;
68 ftypeok(struct ufs1_dinode
* dp
)
70 switch (dp
->di_mode
& IFMT
) {
83 pwarn("bad file type 0%o\n", dp
->di_mode
);
89 reply(const char *question
)
95 err(1, "INTERNAL ERROR: GOT TO reply()");
96 persevere
= !strcmp(question
, "CONTINUE");
98 if (!persevere
&& nflag
) {
99 printf("%s? no\n\n", question
);
102 if (yflag
|| (persevere
&& nflag
)) {
103 printf("%s? yes\n\n", question
);
107 printf("%s? [yn] ", question
);
108 (void) fflush(stdout
);
110 while (c
!= '\n' && getc(stdin
) != '\n')
113 } while (c
!= 'y' && c
!= 'Y' && c
!= 'n' && c
!= 'N');
115 if (c
== 'y' || c
== 'Y')
121 write_superblocks(void)
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]);
132 ckfini(int markclean
)
134 if (locked_queue_bytes
> 0) {
135 if (preen
|| reply("WRITE CHANGES TO DISK") == 1) {
137 pwarn("WRITING CHANGES TO DISK\n");
138 lfs_segwrite(fs
, SEGM_CKP
);
144 if (!nflag
&& (fs
->lfs_pflags
& LFS_PF_CLEAN
) == 0) {
145 fs
->lfs_pflags
|= LFS_PF_CLEAN
;
149 if (fsmodified
&& (preen
|| reply("UPDATE SUPERBLOCKS"))) {
153 if (markclean
&& fsmodified
) {
155 * Mark the file system as clean, and sync the superblock.
158 pwarn("MARKING FILE SYSTEM CLEAN\n");
159 else if (!reply("MARK FILE SYSTEM CLEAN"))
162 fs
->lfs_pflags
|= LFS_PF_CLEAN
;
167 "\n***** FILE SYSTEM MARKED CLEAN *****\n");
173 (void) close(fsreadfd
);
176 * Free a previously allocated block
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
);
191 getpathname(char *namebuf
, size_t namebuflen
, ino_t curdir
, ino_t ino
)
195 struct inodesc idesc
;
198 if (curdir
== ino
&& ino
== ROOTINO
) {
199 (void) strlcpy(namebuf
, "/", namebuflen
);
203 (statemap
[curdir
] != DSTATE
&& statemap
[curdir
] != DFOUND
)) {
204 (void) strlcpy(namebuf
, "?", namebuflen
);
208 memset(&idesc
, 0, sizeof(struct inodesc
));
209 idesc
.id_type
= DATA
;
210 idesc
.id_fix
= IGNORE
;
211 cp
= &namebuf
[MAXPATHLEN
- 1];
214 idesc
.id_parent
= curdir
;
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)
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
)
230 if ((ckinode(ginode(idesc
.id_number
), &idesc
) & FOUND
) == 0)
232 len
= strlen(namebuf
);
234 memcpy(cp
, namebuf
, (size_t) len
);
236 if (cp
< &namebuf
[LFS_MAXNAMLEN
])
238 ino
= idesc
.id_number
;
243 memcpy(namebuf
, cp
, (size_t) (&namebuf
[MAXPATHLEN
] - cp
));
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.
260 static const char msg
[] =
261 "returning to single-user after filesystem check\n";
264 (void)write(STDOUT_FILENO
, msg
, sizeof(msg
) - 1);
266 (void) signal(SIGQUIT
, SIG_DFL
);
270 * Ignore a single quit signal; wait and flush just in case.
271 * Used by child processes in preen.
279 (void) signal(SIGQUIT
, SIG_IGN
);
280 (void) signal(SIGQUIT
, SIG_DFL
);
284 * determine whether an inode should be fixed.
287 dofix(struct inodesc
* idesc
, const char *msg
)
290 switch (idesc
->id_fix
) {
293 if (idesc
->id_type
== DATA
)
294 direrror(idesc
->id_number
, msg
);
298 printf(" (SALVAGED)\n");
302 if (reply("SALVAGE") == 0) {
303 idesc
->id_fix
= NOFIX
;
317 err(EEXIT
, "UNKNOWN INODESC FIX MODE %d\n", idesc
->id_fix
);