xref: /openbsd/sbin/fsdb/fsdbutil.c (revision d415bd75)
1 /*	$OpenBSD: fsdbutil.c,v 1.20 2019/02/05 02:17:32 deraadt Exp $	*/
2 /*	$NetBSD: fsdbutil.c,v 1.5 1996/09/28 19:30:37 christos Exp $	*/
3 
4 /*-
5  * Copyright (c) 1996 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by John T. Kohl.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/mount.h>
36 #include <ctype.h>
37 #include <err.h>
38 #include <fcntl.h>
39 #include <grp.h>
40 #include <pwd.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include <ufs/ufs/dinode.h>
47 #include <ufs/ffs/fs.h>
48 
49 #include "fsdb.h"
50 #include "fsck.h"
51 
52 char **
53 crack(char *line, int *argc)
54 {
55 	static char *argv[8];
56 	int i;
57 	char *p, *val;
58 
59 	for (p = line, i = 0; p != NULL && i < 8; i++) {
60 		while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0')
61 			/**/;
62 		if (val)
63 			argv[i] = val;
64 		else
65 			break;
66 	}
67 	*argc = i;
68 	return argv;
69 }
70 
71 int
72 argcount(struct cmdtable *cmdp, int argc, char *argv[])
73 {
74 	if (cmdp->minargc == cmdp->maxargc)
75 		warnx("command `%s' takes %u arguments", cmdp->cmd, cmdp->minargc-1);
76 	else
77 		warnx("command `%s' takes from %u to %u arguments",
78 		    cmdp->cmd, cmdp->minargc-1, cmdp->maxargc-1);
79 	warnx("usage: %s: %s", cmdp->cmd, cmdp->helptxt);
80 	return 1;
81 }
82 
83 void
84 printstat(const char *cp, ino_t inum, union dinode *dp)
85 {
86 	const char *name;
87 	time_t t;
88 	char *p;
89 
90 	printf("%s: ", cp);
91 	switch (DIP(dp, di_mode) & IFMT) {
92 	case IFDIR:
93 		puts("directory");
94 		break;
95 	case IFREG:
96 		puts("regular file");
97 		break;
98 	case IFBLK:
99 		printf("block special (%u,%u)",
100 		    (int)major(DIP(dp, di_rdev)), (int)minor(DIP(dp, di_rdev)));
101 		break;
102 	case IFCHR:
103 		printf("character special (%u,%u)",
104 		    (int)major(DIP(dp, di_rdev)), (int)minor(DIP(dp, di_rdev)));
105 		break;
106 	case IFLNK:
107 		fputs("symlink",stdout);
108 		if (DIP(dp, di_size) > 0 &&
109 		    DIP(dp, di_size) < sblock.fs_maxsymlinklen &&
110 		    DIP(dp, di_blocks) == 0) {
111 			char *p = sblock.fs_magic == FS_UFS1_MAGIC ?
112 			    (char *)dp->dp1.di_shortlink :
113 			    (char *)dp->dp2.di_shortlink;
114 			printf(" to `%.*s'\n", (int)DIP(dp, di_size), p);
115 		} else
116 			putchar('\n');
117 		break;
118 	case IFSOCK:
119 		puts("socket");
120 		break;
121 	case IFIFO:
122 		puts("fifo");
123 		break;
124 	}
125 
126 	printf("I=%llu MODE=%o SIZE=%llu", (unsigned long long)inum,
127 	    DIP(dp, di_mode), DIP(dp, di_size));
128 	t = DIP(dp, di_mtime);
129 	p = ctime(&t);
130 	printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
131 	    DIP(dp, di_mtimensec));
132 	t = DIP(dp, di_ctime);
133 	p = ctime(&t);
134 	printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
135 	    DIP(dp, di_ctimensec));
136 	t = DIP(dp, di_atime);
137 	p = ctime(&t);
138 	printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20],
139 	    DIP(dp, di_atimensec));
140 
141 	if ((name = user_from_uid(DIP(dp, di_uid), 1)) != NULL)
142 		printf("OWNER=%s ", name);
143 	else
144 		printf("OWNUID=%u ", DIP(dp, di_uid));
145 	if ((name = group_from_gid(DIP(dp, di_gid), 1)) != NULL)
146 		printf("GRP=%s ", name);
147 	else
148 		printf("GID=%u ", DIP(dp, di_gid));
149 
150 	printf("LINKCNT=%d FLAGS=%#x BLKCNT=%x GEN=%x\n", DIP(dp, di_nlink),
151 	    DIP(dp, di_flags), (unsigned)DIP(dp, di_blocks), DIP(dp, di_gen));
152 }
153 
154 int
155 checkactive(void)
156 {
157 	if (!curinode) {
158 		warnx("no current inode");
159 		return 0;
160 	}
161 	return 1;
162 }
163 
164 int
165 checkactivedir(void)
166 {
167 	if (!curinode) {
168 		warnx("no current inode");
169 		return 0;
170 	}
171 	if ((DIP(curinode, di_mode) & IFMT) != IFDIR) {
172 		warnx("inode %llu not a directory",
173 		    (unsigned long long)curinum);
174 		return 0;
175 	}
176 	return 1;
177 }
178 
179 int
180 printactive(void)
181 {
182 	if (!checkactive())
183 		return 1;
184 	switch (DIP(curinode, di_mode) & IFMT) {
185 	case IFDIR:
186 	case IFREG:
187 	case IFBLK:
188 	case IFCHR:
189 	case IFLNK:
190 	case IFSOCK:
191 	case IFIFO:
192 		printstat("current inode", curinum, curinode);
193 		break;
194 	case 0:
195 		printf("current inode %llu: unallocated inode\n",
196 		    (unsigned long long)curinum);
197 		break;
198 	default:
199 		printf("current inode %llu: screwy itype 0%o (mode 0%o)?\n",
200 		    (unsigned long long)curinum, DIP(curinode, di_mode) & IFMT,
201 		    DIP(curinode, di_mode));
202 		break;
203 	}
204 	return 0;
205 }
206