fsdbutil.c revision 89827
134409Sjkh/* $NetBSD: fsdbutil.c,v 1.2 1995/10/08 23:18:12 thorpej Exp $ */ 250476Speter 334409Sjkh/* 4154638Snetchild * Copyright (c) 1995 John T. Kohl 572762Sru * All rights reserved. 679538Sru * 734409Sjkh * Redistribution and use in source and binary forms, with or without 8139403Sbrueffer * modification, are permitted provided that the following conditions 9139403Sbrueffer * are met: 1034409Sjkh * 1. Redistributions of source code must retain the above copyright 1168962Sru * notice, this list of conditions and the following disclaimer. 1240917Snsouch * 2. Redistributions in binary form must reproduce the above copyright 1368962Sru * notice, this list of conditions and the following disclaimer in the 1468962Sru * documentation and/or other materials provided with the distribution. 1568962Sru * 3. The name of the author may not be used to endorse or promote products 1634409Sjkh * derived from this software without specific prior written permission. 1734409Sjkh * 1834409Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 1934409Sjkh * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2034409Sjkh * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2151554Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2251554Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23117011Sru * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24117011Sru * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25139403Sbrueffer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26139403Sbrueffer * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27139403Sbrueffer * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2871895Sru * POSSIBILITY OF SUCH DAMAGE. 29139403Sbrueffer */ 30139403Sbrueffer 31139403Sbrueffer#ifndef lint 32139403Sbruefferstatic const char rcsid[] = 3351554Sroger "$FreeBSD: head/sbin/fsdb/fsdbutil.c 89827 2002-01-26 15:53:23Z joerg $"; 3493346Sschweikh#endif /* not lint */ 3534409Sjkh 3634409Sjkh#include <sys/param.h> 3760441Sphantom#include <ctype.h> 3834409Sjkh#include <err.h> 3934409Sjkh#include <grp.h> 4034409Sjkh#include <pwd.h> 4134409Sjkh#include <string.h> 4234409Sjkh#include <time.h> 4334409Sjkh 4460441Sphantom#include <ufs/ufs/dinode.h> 4534409Sjkh#include <ufs/ffs/fs.h> 46139403Sbrueffer 47139403Sbrueffer#include <sys/ioctl.h> 4840917Snsouch 4940917Snsouch#include "fsdb.h" 5040917Snsouch#include "fsck.h" 5140917Snsouch 5240917Snsouchstatic int charsperline __P((void)); 5340917Snsouchstatic int printindir __P((ufs_daddr_t blk, int level, char *bufp)); 54139403Sbruefferstatic void printblocks __P((ino_t inum, struct dinode *dp)); 55139403Sbrueffer 56139403Sbruefferchar ** 5740917Snsouchcrack(line, argc) 5834409Sjkh char *line; 5934409Sjkh int *argc; 6034409Sjkh{ 6134409Sjkh static char *argv[8]; 62117011Sru int i; 63117011Sru char *p, *val; 6434409Sjkh for (p = line, i = 0; p != NULL && i < 8; i++) { 6560441Sphantom while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0') 66140290Sru /**/; 67140290Sru if (val) 6860441Sphantom argv[i] = val; 6957731Ssheldonh else 7057731Ssheldonh break; 7151554Sroger } 7251554Sroger *argc = i; 7351554Sroger return argv; 7451554Sroger} 7551554Sroger 7668857Sruchar ** 77154529Snetchildrecrack(line, argc, argc_max) 7851554Sroger char *line; 79154529Snetchild int *argc; 8060441Sphantom int argc_max; 8160441Sphantom{ 8260441Sphantom static char *argv[8]; 8360441Sphantom int i; 8460441Sphantom char *p, *val; 8560441Sphantom for (p = line, i = 0; p != NULL && i < 8 && i < argc_max - 1; i++) { 8660441Sphantom while ((val = strsep(&p, " \t\n")) != NULL && *val == '\0') 8760441Sphantom /**/; 8860441Sphantom if (val) 8960441Sphantom argv[i] = val; 9060441Sphantom else 9160441Sphantom break; 9260441Sphantom } 9360441Sphantom argv[i] = argv[i - 1] + strlen(argv[i - 1]) + 1; 9460441Sphantom argv[i][strcspn(argv[i], "\n")] = '\0'; 9560441Sphantom *argc = i + 1; 9660441Sphantom return argv; 9760441Sphantom} 9860441Sphantom 9960441Sphantomint 10060441Sphantomargcount(cmdp, argc, argv) 10160441Sphantom struct cmdtable *cmdp; 10260441Sphantom int argc; 10360441Sphantom char *argv[]; 10460441Sphantom{ 10560441Sphantom if (cmdp->minargc == cmdp->maxargc) 106154529Snetchild warnx("command `%s' takes %u arguments, got %u", cmdp->cmd, 107154529Snetchild cmdp->minargc-1, argc); 108154529Snetchild else 109154529Snetchild warnx("command `%s' takes from %u to %u arguments", 110154529Snetchild cmdp->cmd, cmdp->minargc-1, cmdp->maxargc-1); 111154529Snetchild 112154529Snetchild warnx("usage: %s: %s", cmdp->cmd, cmdp->helptxt); 113154529Snetchild return 1; 114154529Snetchild} 115154529Snetchild 116154529Snetchildvoid 117154529Snetchildprintstat(cp, inum, dp) 118154529Snetchild const char *cp; 119154529Snetchild ino_t inum; 120154529Snetchild struct dinode *dp; 121154529Snetchild{ 122154529Snetchild struct group *grp; 123154529Snetchild struct passwd *pw; 124154529Snetchild char *p; 125154529Snetchild time_t t; 12660441Sphantom 12760441Sphantom printf("%s: ", cp); 12851554Sroger switch (dp->di_mode & IFMT) { 12951554Sroger case IFDIR: 13068857Sru puts("directory"); 131211397Sjoel break; 13251554Sroger case IFREG: 13360441Sphantom puts("regular file"); 13460441Sphantom break; 13560441Sphantom case IFBLK: 13660441Sphantom printf("block special (%d,%d)", 13760441Sphantom major(dp->di_rdev), minor(dp->di_rdev)); 13860441Sphantom break; 13960441Sphantom case IFCHR: 14060441Sphantom printf("character special (%d,%d)", 14160441Sphantom major(dp->di_rdev), minor(dp->di_rdev)); 14260441Sphantom break; 14360441Sphantom case IFLNK: 14460441Sphantom fputs("symlink",stdout); 14560441Sphantom if (dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && 14660441Sphantom dp->di_blocks == 0) 14760441Sphantom printf(" to `%.*s'\n", (int) dp->di_size, (char *)dp->di_shortlink); 14860441Sphantom else 14960441Sphantom putchar('\n'); 15060441Sphantom break; 15160441Sphantom case IFSOCK: 15260441Sphantom puts("socket"); 15360441Sphantom break; 15460441Sphantom case IFIFO: 15560441Sphantom puts("fifo"); 15660441Sphantom break; 15760441Sphantom } 15860441Sphantom printf("I=%lu MODE=%o SIZE=%qu", (u_long)inum, dp->di_mode, dp->di_size); 15960441Sphantom t = dp->di_mtime; 16060441Sphantom p = ctime(&t); 16160441Sphantom printf("\n\tMTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20], 162154529Snetchild dp->di_mtimensec); 163154529Snetchild t = dp->di_ctime; 164154529Snetchild p = ctime(&t); 165154529Snetchild printf("\n\tCTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20], 166154529Snetchild dp->di_ctimensec); 167154529Snetchild t = dp->di_atime; 16870466Sru p = ctime(&t); 169139403Sbrueffer printf("\n\tATIME=%15.15s %4.4s [%d nsec]\n", &p[4], &p[20], 170139403Sbrueffer dp->di_atimensec); 171139403Sbrueffer 172139403Sbrueffer if ((pw = getpwuid(dp->di_uid))) 173139403Sbrueffer printf("OWNER=%s ", pw->pw_name); 174139403Sbrueffer else 175139403Sbrueffer printf("OWNUID=%u ", dp->di_uid); 176139403Sbrueffer if ((grp = getgrgid(dp->di_gid))) 177139403Sbrueffer printf("GRP=%s ", grp->gr_name); 178139403Sbrueffer else 179139403Sbrueffer printf("GID=%u ", dp->di_gid); 180139403Sbrueffer 181139403Sbrueffer printf("LINKCNT=%hd FLAGS=%#x BLKCNT=%x GEN=%x\n", dp->di_nlink, dp->di_flags, 182139403Sbrueffer dp->di_blocks, dp->di_gen); 183139403Sbrueffer} 184139403Sbrueffer 185139403Sbrueffer 186139403Sbrueffer/* 187139403Sbrueffer * Determine the number of characters in a 188139403Sbrueffer * single line. 189139403Sbrueffer */ 190139403Sbrueffer 191139403Sbruefferstatic int 192139403Sbrueffercharsperline() 193139403Sbrueffer{ 194139403Sbrueffer int columns; 195139403Sbrueffer char *cp; 196139403Sbrueffer struct winsize ws; 197139403Sbrueffer 198139403Sbrueffer columns = 0; 199139403Sbrueffer if (ioctl(0, TIOCGWINSZ, &ws) != -1) 200139403Sbrueffer columns = ws.ws_col; 201139403Sbrueffer if (columns == 0 && (cp = getenv("COLUMNS"))) 202139403Sbrueffer columns = atoi(cp); 203139403Sbrueffer if (columns == 0) 204139574Sbrueffer columns = 80; /* last resort */ 205139574Sbrueffer return (columns); 206154529Snetchild} 207154529Snetchild 208139403Sbrueffer 209139403Sbrueffer/* 210139403Sbrueffer * Recursively print a list of indirect blocks. 211139403Sbrueffer */ 212139403Sbruefferstatic int 213139403Sbruefferprintindir(blk, level, bufp) 214154529Snetchild ufs_daddr_t blk; 215154529Snetchild int level; 216139403Sbrueffer char *bufp; 217139403Sbrueffer{ 218139403Sbrueffer struct bufarea buf, *bp; 219139403Sbrueffer char tempbuf[32]; /* enough to print an ufs_daddr_t */ 220139403Sbrueffer int i, j, cpl, charssofar; 221139403Sbrueffer ufs_daddr_t blkno; 22234409Sjkh 22334409Sjkh if (level == 0) { 22434409Sjkh /* for the final indirect level, don't use the cache */ 22534409Sjkh bp = &buf; 226121320Ssimon bp->b_un.b_buf = bufp; 22751554Sroger bp->b_prev = bp->b_next = bp; 22834409Sjkh initbarea(bp); 22934409Sjkh 23034409Sjkh getblk(bp, blk, sblock.fs_bsize); 23134409Sjkh } else 23251554Sroger bp = getdatablk(blk, sblock.fs_bsize); 23351554Sroger 23451554Sroger cpl = charsperline(); 23551554Sroger for (i = charssofar = 0; i < NINDIR(&sblock); i++) { 23651554Sroger blkno = bp->b_un.b_indir[i]; 23751554Sroger if (blkno == 0) { 23851554Sroger if (level == 0) 239131530Sru putchar('\n'); 24051554Sroger return 0; 24151554Sroger } 24251554Sroger j = sprintf(tempbuf, "%d", blkno); 24357731Ssheldonh if (level == 0) { 24457731Ssheldonh charssofar += j; 24551554Sroger if (charssofar >= cpl - 2) { 24651554Sroger putchar('\n'); 24751554Sroger charssofar = j; 24851554Sroger } 24934409Sjkh } 25034409Sjkh fputs(tempbuf, stdout); 25134409Sjkh if (level == 0) { 25234409Sjkh printf(", "); 25334409Sjkh charssofar += 2; 25434409Sjkh } else { 25534409Sjkh printf(" =>\n"); 25634409Sjkh if (printindir(blkno, level - 1, bufp) == 0) 257140561Sru return 0; 258140561Sru } 259140561Sru } 260140561Sru if (level == 0) 261140561Sru putchar('\n'); 262140561Sru return 1; 263140561Sru} 264140561Sru 265140561Sru 266140561Sru/* 267 * Print the block pointers for one inode. 268 */ 269static void 270printblocks(inum, dp) 271 ino_t inum; 272 struct dinode *dp; 273{ 274 char *bufp; 275 int i, j, nfrags; 276 long ndb, offset; 277 278 printf("Blocks for inode %d:\n", inum); 279 printf("Direct blocks:\n"); 280 ndb = howmany(dp->di_size, sblock.fs_bsize); 281 for (i = 0; i < NDADDR; i++) { 282 if (dp->di_db[i] == 0) { 283 putchar('\n'); 284 return; 285 } 286 if (i > 0) 287 printf(", "); 288 printf("%d", dp->di_db[i]); 289 if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0) { 290 nfrags = numfrags(&sblock, fragroundup(&sblock, offset)); 291 printf(" (%d frag%s)", nfrags, nfrags > 1? "s": ""); 292 } 293 } 294 putchar('\n'); 295 if (dp->di_ib[0] == 0) 296 return; 297 298 bufp = malloc((unsigned int)sblock.fs_bsize); 299 if (bufp == 0) 300 errx(EEXIT, "cannot allocate indirect block buffer"); 301 printf("Indirect blocks:\n"); 302 for (i = 0; i < NIADDR; i++) 303 if (printindir(dp->di_ib[i], i, bufp) == 0) 304 break; 305 free(bufp); 306} 307 308 309int 310checkactive() 311{ 312 if (!curinode) { 313 warnx("no current inode\n"); 314 return 0; 315 } 316 return 1; 317} 318 319int 320checkactivedir() 321{ 322 if (!curinode) { 323 warnx("no current inode\n"); 324 return 0; 325 } 326 if ((curinode->di_mode & IFMT) != IFDIR) { 327 warnx("inode %d not a directory", curinum); 328 return 0; 329 } 330 return 1; 331} 332 333int 334printactive(doblocks) 335 int doblocks; 336{ 337 if (!checkactive()) 338 return 1; 339 switch (curinode->di_mode & IFMT) { 340 case IFDIR: 341 case IFREG: 342 case IFBLK: 343 case IFCHR: 344 case IFLNK: 345 case IFSOCK: 346 case IFIFO: 347 if (doblocks) 348 printblocks(curinum, curinode); 349 else 350 printstat("current inode", curinum, curinode); 351 break; 352 case 0: 353 printf("current inode %d: unallocated inode\n", curinum); 354 break; 355 default: 356 printf("current inode %d: screwy itype 0%o (mode 0%o)?\n", 357 curinum, curinode->di_mode & IFMT, curinode->di_mode); 358 break; 359 } 360 return 0; 361} 362