1
/* $NetBSD: fsdbutil.c,v 1.2 1995/10/08 23:18:12 thorpej Exp $ */
4
* Copyright (c) 1995 John T. Kohl
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. The name of the author may not be used to endorse or promote products
16
* derived from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
* POSSIBILITY OF SUCH DAMAGE.
32
static const char rcsid[] =
36
#include <sys/param.h>
45
#include <ufs/ufs/dinode.h>
46
#include <ufs/ffs/fs.h>
48
#include <sys/ioctl.h>
54
_time64_to_time(int64_t t64)
60
_time32_to_time(int32_t t32)
65
static int charsperline(void);
66
static int printindir(ufs2_daddr_t blk, int level, char *bufp);
67
static void printblocks(ino_t inum, union dinode *dp);
70
crack(char *line, int *argc)
75
for (p = line, i = 0; p != NULL && i < 8; i++) {
76
while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0')
88
recrack(char *line, int *argc, int argc_max)
93
for (p = line, i = 0; p != NULL && i < 8 && i < argc_max - 1; i++) {
94
while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0')
101
argv[i] = argv[i - 1] + strlen(argv[i - 1]) + 1;
102
argv[i][strcspn(argv[i], "\n")] = '\0';
108
argcount(struct cmdtable *cmdp, int argc, char *argv[])
110
if (cmdp->minargc == cmdp->maxargc)
111
warnx("command `%s' takes %u arguments, got %u", cmdp->cmd,
112
cmdp->minargc-1, argc-1);
114
warnx("command `%s' takes from %u to %u arguments",
115
cmdp->cmd, cmdp->minargc-1, cmdp->maxargc-1);
117
warnx("usage: %s: %s", cmdp->cmd, cmdp->helptxt);
122
printstat(const char *cp, ino_t inum, union dinode *dp)
132
switch (DIP(dp, di_mode) & IFMT) {
137
puts("regular file");
140
printf("block special (%d,%d)",
141
major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
144
printf("character special (%d,%d)",
145
major(DIP(dp, di_rdev)), minor(DIP(dp, di_rdev)));
148
fputs("symlink",stdout);
149
if (DIP(dp, di_size) > 0 &&
150
DIP(dp, di_size) < sblock.fs_maxsymlinklen &&
151
DIP(dp, di_blocks) == 0) {
152
if (sblock.fs_magic == FS_UFS1_MAGIC)
153
p = (caddr_t)dp->dp1.di_db;
155
p = (caddr_t)dp->dp2.di_db;
156
printf(" to `%.*s'\n", (int) DIP(dp, di_size), p);
168
printf("I=%lu MODE=%o SIZE=%ju", (u_long)inum, DIP(dp, di_mode),
169
(uintmax_t)DIP(dp, di_size));
170
if (sblock.fs_magic != FS_UFS1_MAGIC) {
171
t = _time64_to_time(dp->dp2.di_birthtime);
173
printf("\n\tBTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
174
dp->dp2.di_birthnsec);
176
if (sblock.fs_magic == FS_UFS1_MAGIC)
177
t = _time32_to_time(dp->dp1.di_mtime);
179
t = _time64_to_time(dp->dp2.di_mtime);
181
printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
182
DIP(dp, di_mtimensec));
183
if (sblock.fs_magic == FS_UFS1_MAGIC)
184
t = _time32_to_time(dp->dp1.di_ctime);
186
t = _time64_to_time(dp->dp2.di_ctime);
188
printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20],
189
DIP(dp, di_ctimensec));
190
if (sblock.fs_magic == FS_UFS1_MAGIC)
191
t = _time32_to_time(dp->dp1.di_atime);
193
t = _time64_to_time(dp->dp2.di_atime);
195
printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20],
196
DIP(dp, di_atimensec));
198
if ((pw = getpwuid(DIP(dp, di_uid))))
199
printf("OWNER=%s ", pw->pw_name);
201
printf("OWNUID=%u ", DIP(dp, di_uid));
202
if ((grp = getgrgid(DIP(dp, di_gid))))
203
printf("GRP=%s ", grp->gr_name);
205
printf("GID=%u ", DIP(dp, di_gid));
207
blocks = DIP(dp, di_blocks);
208
gen = DIP(dp, di_gen);
209
printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%jx GEN=%jx\n", DIP(dp, di_nlink),
210
DIP(dp, di_flags), (intmax_t)blocks, (intmax_t)gen);
215
* Determine the number of characters in a
227
if (ioctl(0, TIOCGWINSZ, &ws) != -1)
229
if (columns == 0 && (cp = getenv("COLUMNS")))
232
columns = 80; /* last resort */
238
* Recursively print a list of indirect blocks.
241
printindir(ufs2_daddr_t blk, int level, char *bufp)
243
struct bufarea buf, *bp;
244
char tempbuf[32]; /* enough to print an ufs2_daddr_t */
245
int i, j, cpl, charssofar;
249
/* for the final indirect level, don't use the cache */
251
bp->b_un.b_buf = bufp;
252
bp->b_prev = bp->b_next = bp;
255
getblk(bp, blk, sblock.fs_bsize);
257
bp = getdatablk(blk, sblock.fs_bsize);
259
cpl = charsperline();
260
for (i = charssofar = 0; i < NINDIR(&sblock); i++) {
261
if (sblock.fs_magic == FS_UFS1_MAGIC)
262
blkno = bp->b_un.b_indir1[i];
264
blkno = bp->b_un.b_indir2[i];
270
j = sprintf(tempbuf, "%jd", (intmax_t)blkno);
273
if (charssofar >= cpl - 2) {
278
fputs(tempbuf, stdout);
284
if (printindir(blkno, level - 1, bufp) == 0)
295
* Print the block pointers for one inode.
298
printblocks(ino_t inum, union dinode *dp)
305
printf("Blocks for inode %d:\n", inum);
306
printf("Direct blocks:\n");
307
ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
308
for (i = 0; i < NDADDR; i++) {
309
if (DIP(dp, di_db[i]) == 0) {
315
blkno = DIP(dp, di_db[i]);
316
printf("%jd", (intmax_t)blkno);
317
if (--ndb == 0 && (offset = blkoff(&sblock, DIP(dp, di_size))) != 0) {
318
nfrags = numfrags(&sblock, fragroundup(&sblock, offset));
319
printf(" (%d frag%s)", nfrags, nfrags > 1? "s": "");
323
if (DIP(dp, di_ib[0]) == 0)
326
bufp = malloc((unsigned int)sblock.fs_bsize);
328
errx(EEXIT, "cannot allocate indirect block buffer");
329
printf("Indirect blocks:\n");
330
for (i = 0; i < NIADDR; i++)
331
if (printindir(DIP(dp, di_ib[i]), i, bufp) == 0)
341
warnx("no current inode\n");
351
warnx("no current inode\n");
354
if ((DIP(curinode, di_mode) & IFMT) != IFDIR) {
355
warnx("inode %d not a directory", curinum);
362
printactive(int doblocks)
366
switch (DIP(curinode, di_mode) & IFMT) {
375
printblocks(curinum, curinode);
377
printstat("current inode", curinum, curinode);
380
printf("current inode %d: unallocated inode\n", curinum);
383
printf("current inode %d: screwy itype 0%o (mode 0%o)?\n",
384
curinum, DIP(curinode, di_mode) & IFMT, DIP(curinode, di_mode));