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