Home | History | Annotate | Line # | Download | only in fsck_lfs
utilities.c revision 1.41.16.1
      1  1.41.16.1    martin /* $NetBSD: utilities.c,v 1.41.16.1 2020/04/08 14:07:18 martin Exp $	 */
      2        1.1  perseant 
      3        1.1  perseant /*
      4        1.1  perseant  * Copyright (c) 1980, 1986, 1993
      5        1.1  perseant  *	The Regents of the University of California.  All rights reserved.
      6        1.1  perseant  *
      7        1.1  perseant  * Redistribution and use in source and binary forms, with or without
      8        1.1  perseant  * modification, are permitted provided that the following conditions
      9        1.1  perseant  * are met:
     10        1.1  perseant  * 1. Redistributions of source code must retain the above copyright
     11        1.1  perseant  *    notice, this list of conditions and the following disclaimer.
     12        1.1  perseant  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1  perseant  *    notice, this list of conditions and the following disclaimer in the
     14        1.1  perseant  *    documentation and/or other materials provided with the distribution.
     15       1.15       agc  * 3. Neither the name of the University nor the names of its contributors
     16        1.1  perseant  *    may be used to endorse or promote products derived from this software
     17        1.1  perseant  *    without specific prior written permission.
     18        1.1  perseant  *
     19        1.1  perseant  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20        1.1  perseant  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21        1.1  perseant  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22        1.1  perseant  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23        1.1  perseant  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24        1.1  perseant  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25        1.1  perseant  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26        1.1  perseant  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27        1.1  perseant  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28        1.1  perseant  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29        1.1  perseant  * SUCH DAMAGE.
     30        1.1  perseant  */
     31        1.1  perseant 
     32        1.1  perseant #include <sys/param.h>
     33        1.1  perseant #include <sys/time.h>
     34       1.12  perseant #include <sys/mount.h>
     35       1.11  perseant 
     36       1.12  perseant #define buf ubuf
     37       1.12  perseant #define vnode uvnode
     38        1.1  perseant #include <ufs/lfs/lfs.h>
     39       1.40  dholland #include <ufs/lfs/lfs_accessors.h>
     40       1.11  perseant 
     41       1.11  perseant #include <err.h>
     42        1.1  perseant #include <stdio.h>
     43        1.1  perseant #include <stdlib.h>
     44        1.1  perseant #include <string.h>
     45        1.1  perseant #include <ctype.h>
     46        1.1  perseant #include <unistd.h>
     47       1.30  christos #include <errno.h>
     48        1.1  perseant 
     49        1.1  perseant #include <signal.h>
     50        1.1  perseant 
     51       1.11  perseant #include "bufcache.h"
     52       1.22  christos #include "lfs_user.h"
     53       1.11  perseant #include "segwrite.h"
     54       1.11  perseant 
     55        1.1  perseant #include "fsutil.h"
     56        1.1  perseant #include "fsck.h"
     57        1.1  perseant #include "extern.h"
     58       1.27  christos #include "exitvalues.h"
     59        1.1  perseant 
     60       1.11  perseant long diskreads, totalreads;	/* Disk cache statistics */
     61        1.1  perseant 
     62        1.1  perseant int
     63       1.41  dholland ftypeok(union lfs_dinode * dp)
     64        1.1  perseant {
     65       1.41  dholland 	switch (lfs_dino_getmode(fs, dp) & LFS_IFMT) {
     66        1.1  perseant 
     67       1.34  dholland 	case LFS_IFDIR:
     68       1.34  dholland 	case LFS_IFREG:
     69       1.34  dholland 	case LFS_IFBLK:
     70       1.34  dholland 	case LFS_IFCHR:
     71       1.34  dholland 	case LFS_IFLNK:
     72       1.34  dholland 	case LFS_IFSOCK:
     73       1.34  dholland 	case LFS_IFIFO:
     74        1.1  perseant 		return (1);
     75        1.1  perseant 
     76        1.1  perseant 	default:
     77        1.1  perseant 		if (debug)
     78       1.41  dholland 			pwarn("bad file type 0%o\n", lfs_dino_getmode(fs, dp));
     79        1.1  perseant 		return (0);
     80        1.1  perseant 	}
     81        1.1  perseant }
     82        1.1  perseant 
     83        1.1  perseant int
     84       1.19  christos reply(const char *question)
     85        1.1  perseant {
     86       1.11  perseant 	int persevere;
     87       1.11  perseant 	char c;
     88        1.1  perseant 
     89        1.1  perseant 	if (preen)
     90       1.36  christos 		err(EXIT_FAILURE, "INTERNAL ERROR: GOT TO reply()");
     91        1.1  perseant 	persevere = !strcmp(question, "CONTINUE");
     92       1.16       dsl 	pwarn("\n");
     93       1.11  perseant 	if (!persevere && nflag) {
     94        1.1  perseant 		printf("%s? no\n\n", question);
     95        1.1  perseant 		return (0);
     96        1.1  perseant 	}
     97        1.1  perseant 	if (yflag || (persevere && nflag)) {
     98        1.1  perseant 		printf("%s? yes\n\n", question);
     99        1.1  perseant 		return (1);
    100        1.1  perseant 	}
    101        1.4  perseant 	do {
    102        1.1  perseant 		printf("%s? [yn] ", question);
    103       1.11  perseant 		(void) fflush(stdout);
    104        1.1  perseant 		c = getc(stdin);
    105        1.1  perseant 		while (c != '\n' && getc(stdin) != '\n')
    106        1.1  perseant 			if (feof(stdin))
    107        1.1  perseant 				return (0);
    108        1.1  perseant 	} while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
    109        1.1  perseant 	printf("\n");
    110        1.1  perseant 	if (c == 'y' || c == 'Y')
    111        1.1  perseant 		return (1);
    112        1.1  perseant 	return (0);
    113        1.1  perseant }
    114        1.1  perseant 
    115        1.1  perseant static void
    116       1.11  perseant write_superblocks(void)
    117        1.1  perseant {
    118       1.25  perseant 	if (debug)
    119       1.38  dholland 		pwarn("writing superblocks with lfs_idaddr = 0x%jx\n",
    120       1.38  dholland 			(uintmax_t)lfs_sb_getidaddr(fs));
    121       1.39  dholland 	lfs_writesuper(fs, lfs_sb_getsboff(fs, 0));
    122       1.39  dholland 	lfs_writesuper(fs, lfs_sb_getsboff(fs, 1));
    123       1.11  perseant 	fsmodified = 1;
    124        1.1  perseant }
    125        1.1  perseant 
    126        1.1  perseant void
    127        1.4  perseant ckfini(int markclean)
    128        1.1  perseant {
    129       1.12  perseant 	if (locked_queue_bytes > 0) {
    130       1.11  perseant 		if (preen || reply("WRITE CHANGES TO DISK") == 1) {
    131       1.12  perseant 			if (preen == 0)
    132       1.12  perseant 				pwarn("WRITING CHANGES TO DISK\n");
    133       1.11  perseant 			lfs_segwrite(fs, SEGM_CKP);
    134       1.11  perseant 			fsdirty = 0;
    135       1.11  perseant 			fsmodified = 1;
    136       1.11  perseant 		}
    137       1.11  perseant 	}
    138        1.1  perseant 
    139       1.39  dholland 	if (!nflag && (lfs_sb_getpflags(fs) & LFS_PF_CLEAN) == 0) {
    140       1.39  dholland 		lfs_sb_setpflags(fs, lfs_sb_getpflags(fs) | LFS_PF_CLEAN);
    141       1.12  perseant 		fsmodified = 1;
    142       1.18  perseant 	}
    143       1.12  perseant 
    144       1.25  perseant 	if (fsmodified && (preen || reply("UPDATE SUPERBLOCKS"))) {
    145        1.1  perseant 		sbdirty();
    146       1.11  perseant 		write_superblocks();
    147        1.1  perseant 	}
    148       1.12  perseant 	if (markclean && fsmodified) {
    149        1.1  perseant 		/*
    150        1.1  perseant 		 * Mark the file system as clean, and sync the superblock.
    151        1.1  perseant 		 */
    152        1.1  perseant 		if (preen)
    153        1.1  perseant 			pwarn("MARKING FILE SYSTEM CLEAN\n");
    154        1.1  perseant 		else if (!reply("MARK FILE SYSTEM CLEAN"))
    155        1.1  perseant 			markclean = 0;
    156        1.1  perseant 		if (markclean) {
    157       1.39  dholland 			lfs_sb_setpflags(fs, lfs_sb_getpflags(fs) | LFS_PF_CLEAN);
    158        1.1  perseant 			sbdirty();
    159       1.11  perseant 			write_superblocks();
    160       1.11  perseant 			if (!preen)
    161       1.11  perseant 				printf(
    162       1.11  perseant 					"\n***** FILE SYSTEM MARKED CLEAN *****\n");
    163        1.1  perseant 		}
    164        1.1  perseant 	}
    165       1.12  perseant 
    166        1.1  perseant 	if (debug)
    167       1.11  perseant 		bufstats();
    168       1.11  perseant 	(void) close(fsreadfd);
    169        1.1  perseant }
    170        1.1  perseant /*
    171        1.1  perseant  * Free a previously allocated block
    172        1.1  perseant  */
    173        1.1  perseant void
    174        1.4  perseant freeblk(daddr_t blkno, long frags)
    175        1.1  perseant {
    176       1.11  perseant 	struct inodesc idesc;
    177        1.1  perseant 
    178        1.1  perseant 	idesc.id_blkno = blkno;
    179        1.1  perseant 	idesc.id_numfrags = frags;
    180       1.11  perseant 	(void) pass4check(&idesc);
    181        1.1  perseant }
    182        1.1  perseant /*
    183        1.1  perseant  * Find a pathname
    184        1.1  perseant  */
    185        1.1  perseant void
    186       1.14    itojun getpathname(char *namebuf, size_t namebuflen, ino_t curdir, ino_t ino)
    187        1.4  perseant {
    188       1.11  perseant 	int len;
    189       1.17     perry 	char *cp;
    190       1.11  perseant 	struct inodesc idesc;
    191       1.11  perseant 	static int busy = 0;
    192        1.1  perseant 
    193       1.33  dholland 	if (curdir == ino && ino == ULFS_ROOTINO) {
    194       1.14    itojun 		(void) strlcpy(namebuf, "/", namebuflen);
    195        1.1  perseant 		return;
    196        1.1  perseant 	}
    197        1.1  perseant 	if (busy ||
    198        1.1  perseant 	    (statemap[curdir] != DSTATE && statemap[curdir] != DFOUND)) {
    199       1.14    itojun 		(void) strlcpy(namebuf, "?", namebuflen);
    200        1.1  perseant 		return;
    201        1.1  perseant 	}
    202        1.1  perseant 	busy = 1;
    203        1.1  perseant 	memset(&idesc, 0, sizeof(struct inodesc));
    204        1.1  perseant 	idesc.id_type = DATA;
    205        1.1  perseant 	idesc.id_fix = IGNORE;
    206        1.1  perseant 	cp = &namebuf[MAXPATHLEN - 1];
    207        1.1  perseant 	*cp = '\0';
    208        1.1  perseant 	if (curdir != ino) {
    209        1.1  perseant 		idesc.id_parent = curdir;
    210        1.1  perseant 		goto namelookup;
    211        1.1  perseant 	}
    212       1.33  dholland 	while (ino != ULFS_ROOTINO) {
    213        1.1  perseant 		idesc.id_number = ino;
    214        1.1  perseant 		idesc.id_func = findino;
    215        1.1  perseant 		idesc.id_name = "..";
    216        1.1  perseant 		if ((ckinode(ginode(ino), &idesc) & FOUND) == 0)
    217        1.1  perseant 			break;
    218        1.4  perseant namelookup:
    219        1.1  perseant 		idesc.id_number = idesc.id_parent;
    220        1.1  perseant 		idesc.id_parent = ino;
    221        1.1  perseant 		idesc.id_func = findname;
    222        1.1  perseant 		idesc.id_name = namebuf;
    223       1.24  perseant 		if (ginode(idesc.id_number) == NULL)
    224       1.24  perseant 			break;
    225        1.4  perseant 		if ((ckinode(ginode(idesc.id_number), &idesc) & FOUND) == 0)
    226        1.1  perseant 			break;
    227        1.1  perseant 		len = strlen(namebuf);
    228        1.1  perseant 		cp -= len;
    229       1.11  perseant 		memcpy(cp, namebuf, (size_t) len);
    230        1.1  perseant 		*--cp = '/';
    231       1.21  christos 		if (cp < &namebuf[LFS_MAXNAMLEN])
    232        1.1  perseant 			break;
    233        1.1  perseant 		ino = idesc.id_number;
    234        1.1  perseant 	}
    235        1.1  perseant 	busy = 0;
    236       1.33  dholland 	if (ino != ULFS_ROOTINO)
    237        1.1  perseant 		*--cp = '?';
    238       1.11  perseant 	memcpy(namebuf, cp, (size_t) (&namebuf[MAXPATHLEN] - cp));
    239        1.1  perseant }
    240        1.1  perseant 
    241        1.1  perseant /*
    242        1.1  perseant  * determine whether an inode should be fixed.
    243        1.1  perseant  */
    244        1.1  perseant int
    245       1.19  christos dofix(struct inodesc * idesc, const char *msg)
    246        1.1  perseant {
    247        1.1  perseant 
    248        1.1  perseant 	switch (idesc->id_fix) {
    249        1.1  perseant 
    250       1.11  perseant 	case DONTKNOW:
    251        1.1  perseant 		if (idesc->id_type == DATA)
    252        1.1  perseant 			direrror(idesc->id_number, msg);
    253        1.1  perseant 		else
    254        1.6        is 			pwarn("%s", msg);
    255        1.1  perseant 		if (preen) {
    256        1.1  perseant 			printf(" (SALVAGED)\n");
    257        1.1  perseant 			idesc->id_fix = FIX;
    258        1.1  perseant 			return (ALTERED);
    259        1.1  perseant 		}
    260        1.1  perseant 		if (reply("SALVAGE") == 0) {
    261        1.1  perseant 			idesc->id_fix = NOFIX;
    262        1.1  perseant 			return (0);
    263        1.1  perseant 		}
    264        1.1  perseant 		idesc->id_fix = FIX;
    265        1.1  perseant 		return (ALTERED);
    266        1.1  perseant 
    267        1.1  perseant 	case FIX:
    268        1.1  perseant 		return (ALTERED);
    269        1.1  perseant 
    270        1.1  perseant 	case NOFIX:
    271        1.1  perseant 	case IGNORE:
    272        1.1  perseant 		return (0);
    273        1.1  perseant 
    274        1.1  perseant 	default:
    275       1.37  christos 		err(EEXIT, "UNKNOWN INODESC FIX MODE %d", idesc->id_fix);
    276        1.1  perseant 	}
    277        1.1  perseant 	/* NOTREACHED */
    278        1.1  perseant }
    279