xref: /netbsd-src/sbin/fsdb/fsdbutil.c (revision 87ba0e2a319653af510fae24a6d2975d3589735b)
1*87ba0e2aSchs /*	$NetBSD: fsdbutil.c,v 1.24 2022/11/17 06:40:38 chs Exp $	*/
2e727d216Sthorpej 
38bd51c47Sjtc /*-
48bd51c47Sjtc  * Copyright (c) 1996 The NetBSD Foundation, Inc.
53f7621c1Sthorpej  * All rights reserved.
63f7621c1Sthorpej  *
78bd51c47Sjtc  * This code is derived from software contributed to The NetBSD Foundation
88bd51c47Sjtc  * by John T. Kohl.
98bd51c47Sjtc  *
103f7621c1Sthorpej  * Redistribution and use in source and binary forms, with or without
113f7621c1Sthorpej  * modification, are permitted provided that the following conditions
123f7621c1Sthorpej  * are met:
133f7621c1Sthorpej  * 1. Redistributions of source code must retain the above copyright
143f7621c1Sthorpej  *    notice, this list of conditions and the following disclaimer.
153f7621c1Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
163f7621c1Sthorpej  *    notice, this list of conditions and the following disclaimer in the
173f7621c1Sthorpej  *    documentation and/or other materials provided with the distribution.
183f7621c1Sthorpej  *
198bd51c47Sjtc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
208bd51c47Sjtc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
218bd51c47Sjtc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22fb0208bcSjtc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23fb0208bcSjtc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
248bd51c47Sjtc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
258bd51c47Sjtc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268bd51c47Sjtc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
278bd51c47Sjtc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
288bd51c47Sjtc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293f7621c1Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
303f7621c1Sthorpej  */
313f7621c1Sthorpej 
3266a64254Slukem #include <sys/cdefs.h>
333f7621c1Sthorpej #ifndef lint
34*87ba0e2aSchs __RCSID("$NetBSD: fsdbutil.c,v 1.24 2022/11/17 06:40:38 chs Exp $");
353f7621c1Sthorpej #endif /* not lint */
363f7621c1Sthorpej 
373f7621c1Sthorpej #include <sys/types.h>
383f7621c1Sthorpej #include <sys/stat.h>
393f7621c1Sthorpej #include <sys/param.h>
403f7621c1Sthorpej #include <sys/time.h>
413f7621c1Sthorpej #include <sys/mount.h>
42e727d216Sthorpej #include <fcntl.h>
433f7621c1Sthorpej #include <grp.h>
443f7621c1Sthorpej #include <pwd.h>
45e727d216Sthorpej #include <stdio.h>
46e727d216Sthorpej #include <stdlib.h>
47e727d216Sthorpej #include <string.h>
4822821b35Skleink #include <time.h>
49e727d216Sthorpej #include <unistd.h>
5060e2d41cSchristos #include <err.h>
51e727d216Sthorpej 
52e727d216Sthorpej #include <ufs/ufs/dinode.h>
53e727d216Sthorpej #include <ufs/ffs/fs.h>
543f7621c1Sthorpej 
553f7621c1Sthorpej #include "fsdb.h"
563f7621c1Sthorpej #include "fsck.h"
573f7621c1Sthorpej 
583f7621c1Sthorpej char  **
crack(char * line,int * argc)59d4a0de51Sxtraeme crack(char *line, int *argc)
603f7621c1Sthorpej {
613f7621c1Sthorpej 	static char *argv[8];
623f7621c1Sthorpej 	int     i;
633f7621c1Sthorpej 	char   *p, *val;
643f7621c1Sthorpej 	for (p = line, i = 0; p != NULL && i < 8; i++) {
653f7621c1Sthorpej 		while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0')
663f7621c1Sthorpej 			 /**/ ;
673f7621c1Sthorpej 		if (val)
683f7621c1Sthorpej 			argv[i] = val;
693f7621c1Sthorpej 		else
703f7621c1Sthorpej 			break;
713f7621c1Sthorpej 	}
723f7621c1Sthorpej 	*argc = i;
733f7621c1Sthorpej 	return argv;
743f7621c1Sthorpej }
753f7621c1Sthorpej 
763f7621c1Sthorpej int
argcount(struct cmdtable * cmdp,int argc,char * argv[])77d4a0de51Sxtraeme argcount(struct cmdtable *cmdp, int argc, char *argv[])
783f7621c1Sthorpej {
793f7621c1Sthorpej 	if (cmdp->minargc == cmdp->maxargc)
8066a64254Slukem 		warnx("command `%s' takes %u arguments", cmdp->cmd,
8166a64254Slukem 		    cmdp->minargc - 1);
823f7621c1Sthorpej 	else
833f7621c1Sthorpej 		warnx("command `%s' takes from %u to %u arguments",
843f7621c1Sthorpej 		    cmdp->cmd, cmdp->minargc - 1, cmdp->maxargc - 1);
853f7621c1Sthorpej 
863f7621c1Sthorpej 	warnx("usage: %s: %s", cmdp->cmd, cmdp->helptxt);
873f7621c1Sthorpej 	return 1;
883f7621c1Sthorpej }
893f7621c1Sthorpej 
903f7621c1Sthorpej void
printstat(const char * cp,ino_t inum,union dinode * dp)91d4a0de51Sxtraeme printstat(const char *cp, ino_t inum, union dinode *dp)
923f7621c1Sthorpej {
933f7621c1Sthorpej 	struct group *grp;
943f7621c1Sthorpej 	struct passwd *pw;
9547efd9f3Sthorpej 	time_t  t;
963f7621c1Sthorpej 	char   *p;
9742614ed3Sfvdl 	uint64_t size, blocks;
98*87ba0e2aSchs 	uint32_t extsize;
9942614ed3Sfvdl 	uint16_t mode;
10042614ed3Sfvdl 	uint32_t rdev;
101efbd5db6Sdbj 	uint32_t uid, gid;
10242614ed3Sfvdl 
10342614ed3Sfvdl 	size = iswap64(DIP(dp, size));
104*87ba0e2aSchs 	extsize = is_ufs2 ? iswap32(dp->dp2.di_extsize) : 0;
10542614ed3Sfvdl 	blocks = is_ufs2 ? iswap64(DIP(dp, blocks)) : iswap32(DIP(dp, blocks));
10642614ed3Sfvdl 	mode = iswap16(DIP(dp, mode));
10742614ed3Sfvdl 	rdev = iswap32(DIP(dp, rdev));
1083f7621c1Sthorpej 
1093f7621c1Sthorpej 	printf("%s: ", cp);
11042614ed3Sfvdl 	switch (mode & IFMT) {
1113f7621c1Sthorpej 	case IFDIR:
1123f7621c1Sthorpej 		puts("directory");
1133f7621c1Sthorpej 		break;
1143f7621c1Sthorpej 	case IFREG:
1153f7621c1Sthorpej 		puts("regular file");
1163f7621c1Sthorpej 		break;
1173f7621c1Sthorpej 	case IFBLK:
118bb90b5f0Smlelstv 		printf("block special (%llu,%llu)",
119bb90b5f0Smlelstv 		    (unsigned long long)major(rdev),
120bb90b5f0Smlelstv 		    (unsigned long long)minor(rdev));
1213f7621c1Sthorpej 		break;
1223f7621c1Sthorpej 	case IFCHR:
123ac43585bSchristos 		printf("character special (%llu,%llu)",
124ac43585bSchristos 		    (unsigned long long)major(rdev),
125ac43585bSchristos 		    (unsigned long long)minor(rdev));
1263f7621c1Sthorpej 		break;
1273f7621c1Sthorpej 	case IFLNK:
1283f7621c1Sthorpej 		fputs("symlink", stdout);
129cefb0777Slukem 		if (size > 0 && size < (uint64_t)sblock->fs_maxsymlinklen &&
13042614ed3Sfvdl 		    DIP(dp, blocks) == 0) {
13142614ed3Sfvdl 			p = is_ufs2 ? (char *)dp->dp2.di_db :
13242614ed3Sfvdl 			    (char *)dp->dp1.di_db;
13342614ed3Sfvdl 			printf(" to `%.*s'\n", (int)size, p);
13442614ed3Sfvdl 		} else
1353f7621c1Sthorpej 			putchar('\n');
1363f7621c1Sthorpej 		break;
1373f7621c1Sthorpej 	case IFSOCK:
1383f7621c1Sthorpej 		puts("socket");
1393f7621c1Sthorpej 		break;
1403f7621c1Sthorpej 	case IFIFO:
1413f7621c1Sthorpej 		puts("fifo");
1423f7621c1Sthorpej 		break;
1433f7621c1Sthorpej 	}
144*87ba0e2aSchs 	printf("I=%llu MODE=%o SIZE=%llu EXTSIZE=%u", (unsigned long long)inum,
145*87ba0e2aSchs 	    mode, (unsigned long long)size, extsize);
14642614ed3Sfvdl 	t = is_ufs2 ? iswap64(dp->dp2.di_mtime) : iswap32(dp->dp1.di_mtime);
14747efd9f3Sthorpej 	p = ctime(&t);
1483f7621c1Sthorpej 	printf("\n\t    MTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
14942614ed3Sfvdl 	    iswap32(DIP(dp, mtimensec)));
15042614ed3Sfvdl 	t = is_ufs2 ? iswap64(dp->dp2.di_ctime) : iswap32(dp->dp1.di_ctime);
15147efd9f3Sthorpej 	p = ctime(&t);
1523f7621c1Sthorpej 	printf("\n\t    CTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
15342614ed3Sfvdl 	    iswap32(DIP(dp, ctimensec)));
15442614ed3Sfvdl 	t = is_ufs2 ? iswap64(dp->dp2.di_atime) : iswap32(dp->dp1.di_atime);
15547efd9f3Sthorpej 	p = ctime(&t);
15681d30165Schristos 	printf("\n\t    ATIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
15742614ed3Sfvdl 	    iswap32(DIP(dp,atimensec)));
15881d30165Schristos 	if (is_ufs2) {
15981d30165Schristos 		t = iswap64(dp->dp2.di_birthtime);
16081d30165Schristos 		p = ctime(&t);
16181d30165Schristos 		printf("\n\tBIRTHTIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20],
16281d30165Schristos 		    iswap32(dp->dp2.di_birthnsec));
16381d30165Schristos 	} else {
16481d30165Schristos 		printf("\n");
16581d30165Schristos 	}
1663f7621c1Sthorpej 
167efbd5db6Sdbj 	if (!is_ufs2 && sblock->fs_old_inodefmt < FS_44INODEFMT)
168efbd5db6Sdbj 		uid = iswap16(dp->dp1.di_ouid);
169efbd5db6Sdbj 	else
170efbd5db6Sdbj 		uid = iswap32(DIP(dp, uid));
171efbd5db6Sdbj 	if ((pw = getpwuid(uid)) != NULL)
1723f7621c1Sthorpej 		printf("OWNER=%s ", pw->pw_name);
1733f7621c1Sthorpej 	else
174efbd5db6Sdbj 		printf("OWNUID=%u ", uid);
175efbd5db6Sdbj 	if (!is_ufs2 && sblock->fs_old_inodefmt < FS_44INODEFMT)
176efbd5db6Sdbj 		gid = iswap16(dp->dp1.di_ogid);
177efbd5db6Sdbj 	else
178efbd5db6Sdbj 		gid = iswap32(DIP(dp, gid));
179efbd5db6Sdbj 	if ((grp = getgrgid(gid)) != NULL)
1803f7621c1Sthorpej 		printf("GRP=%s ", grp->gr_name);
1813f7621c1Sthorpej 	else
182efbd5db6Sdbj 		printf("GID=%u ", gid);
1833f7621c1Sthorpej 
18412e5d916Ssimonb 	printf("LINKCNT=%hd FLAGS=0x%x BLKCNT=0x%llx GEN=0x%x\n",
18542614ed3Sfvdl 		iswap16(DIP(dp, nlink)),
18642614ed3Sfvdl 	    iswap32(DIP(dp, flags)), (unsigned long long)blocks,
18742614ed3Sfvdl 		iswap32(DIP(dp, gen)));
1883f7621c1Sthorpej }
1893f7621c1Sthorpej 
1903f7621c1Sthorpej int
checkactive(void)191d4a0de51Sxtraeme checkactive(void)
1923f7621c1Sthorpej {
1933f7621c1Sthorpej 	if (!curinode) {
1946742cb18Sgrant 		warnx("no current inode");
1953f7621c1Sthorpej 		return 0;
1963f7621c1Sthorpej 	}
1973f7621c1Sthorpej 	return 1;
1983f7621c1Sthorpej }
1993f7621c1Sthorpej 
2003f7621c1Sthorpej int
checkactivedir(void)201d4a0de51Sxtraeme checkactivedir(void)
2023f7621c1Sthorpej {
2033f7621c1Sthorpej 	if (!curinode) {
2046742cb18Sgrant 		warnx("no current inode");
2053f7621c1Sthorpej 		return 0;
2063f7621c1Sthorpej 	}
20742614ed3Sfvdl 	if ((iswap16(DIP(curinode, mode)) & IFMT) != IFDIR) {
208c4ee9f6dSchristos 		warnx("inode %llu not a directory",
209c4ee9f6dSchristos 		    (unsigned long long)curinum);
2103f7621c1Sthorpej 		return 0;
2113f7621c1Sthorpej 	}
2123f7621c1Sthorpej 	return 1;
2133f7621c1Sthorpej }
2143f7621c1Sthorpej 
2153f7621c1Sthorpej int
printactive(void)216d4a0de51Sxtraeme printactive(void)
2173f7621c1Sthorpej {
21842614ed3Sfvdl 	uint16_t mode;
21942614ed3Sfvdl 
2203f7621c1Sthorpej 	if (!checkactive())
2213f7621c1Sthorpej 		return 1;
22242614ed3Sfvdl 	mode = iswap16(DIP(curinode, mode));
22342614ed3Sfvdl 	switch (mode & IFMT) {
2243f7621c1Sthorpej 	case IFDIR:
2253f7621c1Sthorpej 	case IFREG:
2263f7621c1Sthorpej 	case IFBLK:
2273f7621c1Sthorpej 	case IFCHR:
2283f7621c1Sthorpej 	case IFLNK:
2293f7621c1Sthorpej 	case IFSOCK:
2303f7621c1Sthorpej 	case IFIFO:
2313f7621c1Sthorpej 		printstat("current inode", curinum, curinode);
2323f7621c1Sthorpej 		break;
2333f7621c1Sthorpej 	case 0:
234c4ee9f6dSchristos 		printf("current inode %llu: unallocated inode\n",
235c4ee9f6dSchristos 		    (unsigned long long)curinum);
2363f7621c1Sthorpej 		break;
2373f7621c1Sthorpej 	default:
238c4ee9f6dSchristos 		printf("current inode %llu: screwy itype 0%o (mode 0%o)?\n",
239c4ee9f6dSchristos 		    (unsigned long long)curinum, mode & IFMT, mode);
2403f7621c1Sthorpej 		break;
2413f7621c1Sthorpej 	}
2423f7621c1Sthorpej 	return 0;
2433f7621c1Sthorpej }
244