139bb6d1eSPeter Wemm /* $NetBSD: fsdb.c,v 1.2 1995/10/08 23:18:10 thorpej Exp $ */
239bb6d1eSPeter Wemm
31de7b4b8SPedro F. Giffuni /*-
41de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
51de7b4b8SPedro F. Giffuni *
639bb6d1eSPeter Wemm * Copyright (c) 1995 John T. Kohl
739bb6d1eSPeter Wemm * All rights reserved.
839bb6d1eSPeter Wemm *
939bb6d1eSPeter Wemm * Redistribution and use in source and binary forms, with or without
1039bb6d1eSPeter Wemm * modification, are permitted provided that the following conditions
1139bb6d1eSPeter Wemm * are met:
1239bb6d1eSPeter Wemm * 1. Redistributions of source code must retain the above copyright
1339bb6d1eSPeter Wemm * notice, this list of conditions and the following disclaimer.
1439bb6d1eSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright
1539bb6d1eSPeter Wemm * notice, this list of conditions and the following disclaimer in the
1639bb6d1eSPeter Wemm * documentation and/or other materials provided with the distribution.
1739bb6d1eSPeter Wemm * 3. The name of the author may not be used to endorse or promote products
1839bb6d1eSPeter Wemm * derived from this software without specific prior written permission.
1939bb6d1eSPeter Wemm *
2039bb6d1eSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
2139bb6d1eSPeter Wemm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2239bb6d1eSPeter Wemm * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2339bb6d1eSPeter Wemm * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2439bb6d1eSPeter Wemm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2539bb6d1eSPeter Wemm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2639bb6d1eSPeter Wemm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2739bb6d1eSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2839bb6d1eSPeter Wemm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2939bb6d1eSPeter Wemm * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3039bb6d1eSPeter Wemm * POSSIBILITY OF SUCH DAMAGE.
3139bb6d1eSPeter Wemm */
3239bb6d1eSPeter Wemm
3339bb6d1eSPeter Wemm #include <sys/param.h>
3439bb6d1eSPeter Wemm #include <ctype.h>
350227048aSPhilippe Charnier #include <err.h>
3639bb6d1eSPeter Wemm #include <grp.h>
3739bb6d1eSPeter Wemm #include <histedit.h>
3839bb6d1eSPeter Wemm #include <pwd.h>
39e25a029eSMatthew D Fleming #include <stdint.h>
4039bb6d1eSPeter Wemm #include <string.h>
417649cb00SKirk McKusick #include <time.h>
428b5e064dSJohan Karlsson #include <timeconv.h>
4339bb6d1eSPeter Wemm
4439bb6d1eSPeter Wemm #include <ufs/ufs/dinode.h>
4539bb6d1eSPeter Wemm #include <ufs/ufs/dir.h>
4639bb6d1eSPeter Wemm #include <ufs/ffs/fs.h>
4739bb6d1eSPeter Wemm
4839bb6d1eSPeter Wemm #include "fsdb.h"
4939bb6d1eSPeter Wemm #include "fsck.h"
5039bb6d1eSPeter Wemm
510638cc1aSWarner Losh static void usage(void) __dead2;
520638cc1aSWarner Losh int cmdloop(void);
5382d9b14eSMaxim Konovalov static int compare_blk32(uint32_t *wantedblk, uint32_t curblk);
5482d9b14eSMaxim Konovalov static int compare_blk64(uint64_t *wantedblk, uint64_t curblk);
5582d9b14eSMaxim Konovalov static int founddatablk(uint64_t blk);
5682d9b14eSMaxim Konovalov static int find_blks32(uint32_t *buf, int size, uint32_t *blknum);
5782d9b14eSMaxim Konovalov static int find_blks64(uint64_t *buf, int size, uint64_t *blknum);
5882d9b14eSMaxim Konovalov static int find_indirblks32(uint32_t blk, int ind_level, uint32_t *blknum);
5982d9b14eSMaxim Konovalov static int find_indirblks64(uint64_t blk, int ind_level, uint64_t *blknum);
6039bb6d1eSPeter Wemm
61d51bdf32SKirk McKusick /*
62d51bdf32SKirk McKusick * Track modifications to the filesystem. Two types of changes are tracked.
63d51bdf32SKirk McKusick * The first type of changes are those that are not critical to the integrity
64d51bdf32SKirk McKusick * of the filesystem such as owner, group, time stamps, access mode, and
65d51bdf32SKirk McKusick * generation number. The second type of changes are those that do affect
66d51bdf32SKirk McKusick * the integrity of the filesystem including zeroing inodes, changing block
67d51bdf32SKirk McKusick * pointers, directory entries, link counts, file lengths, file types and
68d51bdf32SKirk McKusick * file flags.
69d51bdf32SKirk McKusick *
70d51bdf32SKirk McKusick * When quitting having made no changes or only changes to data that is not
71d51bdf32SKirk McKusick * critical to filesystem integrity, the clean state of the filesystem is
72d51bdf32SKirk McKusick * left unchanged. But if filesystem critical data are changed then fsdb
73d51bdf32SKirk McKusick * will set the unclean flag which will require a full fsck to be run
74d51bdf32SKirk McKusick * before the filesystem can be mounted.
75d51bdf32SKirk McKusick */
76d51bdf32SKirk McKusick static int fsnoncritmodified; /* filesystem non-critical modifications */
77d51bdf32SKirk McKusick static int fscritmodified; /* filesystem integrity critical mods */
785cc52631SKirk McKusick struct inode curip;
795cc52631SKirk McKusick union dinode *curinode;
805cc52631SKirk McKusick ino_t curinum, ocurrent;
815cc52631SKirk McKusick
82617f1bc8SPhilippe Charnier static void
usage(void)830638cc1aSWarner Losh usage(void)
8439bb6d1eSPeter Wemm {
85617f1bc8SPhilippe Charnier fprintf(stderr, "usage: fsdb [-d] [-f] [-r] fsname\n");
86617f1bc8SPhilippe Charnier exit(1);
8739bb6d1eSPeter Wemm }
8839bb6d1eSPeter Wemm
8939bb6d1eSPeter Wemm /*
9039bb6d1eSPeter Wemm * We suck in lots of fsck code, and just pick & choose the stuff we want.
9139bb6d1eSPeter Wemm *
9239bb6d1eSPeter Wemm * fsreadfd is set up to read from the file system, fswritefd to write to
9339bb6d1eSPeter Wemm * the file system.
9439bb6d1eSPeter Wemm */
95ebe70c8fSWarner Losh int
main(int argc,char * argv[])960638cc1aSWarner Losh main(int argc, char *argv[])
9739bb6d1eSPeter Wemm {
9839bb6d1eSPeter Wemm int ch, rval;
9939bb6d1eSPeter Wemm char *fsys = NULL;
10039bb6d1eSPeter Wemm
101617f1bc8SPhilippe Charnier while (-1 != (ch = getopt(argc, argv, "fdr"))) {
10239bb6d1eSPeter Wemm switch (ch) {
10339bb6d1eSPeter Wemm case 'f':
104617f1bc8SPhilippe Charnier /* The -f option is left for historical
105617f1bc8SPhilippe Charnier * reasons and has no meaning.
106617f1bc8SPhilippe Charnier */
10739bb6d1eSPeter Wemm break;
10839bb6d1eSPeter Wemm case 'd':
10939bb6d1eSPeter Wemm debug++;
11039bb6d1eSPeter Wemm break;
11136b8baa3SJoerg Wunsch case 'r':
11236b8baa3SJoerg Wunsch nflag++; /* "no" in fsck, readonly for us */
11336b8baa3SJoerg Wunsch break;
11439bb6d1eSPeter Wemm default:
11539bb6d1eSPeter Wemm usage();
11639bb6d1eSPeter Wemm }
11739bb6d1eSPeter Wemm }
118fe3a5bd4SGuido van Rooij argc -= optind;
119fe3a5bd4SGuido van Rooij argv += optind;
120fe3a5bd4SGuido van Rooij if (argc != 1)
12139bb6d1eSPeter Wemm usage();
122fe3a5bd4SGuido van Rooij else
123fe3a5bd4SGuido van Rooij fsys = argv[0];
124fe3a5bd4SGuido van Rooij
125d164d805SIan Dowse sblock_init();
126e6886616SKirk McKusick if (openfilesys(fsys) == 0 || readsb() == 0 || setup(fsys) == 0)
12739bb6d1eSPeter Wemm errx(1, "cannot set up file system `%s'", fsys);
12868d7185bSKirk McKusick if (fswritefd < 0)
12968d7185bSKirk McKusick nflag++;
13036b8baa3SJoerg Wunsch printf("%s file system `%s'\nLast Mounted on %s\n",
13136b8baa3SJoerg Wunsch nflag? "Examining": "Editing", fsys, sblock.fs_fsmnt);
13239bb6d1eSPeter Wemm rval = cmdloop();
13336b8baa3SJoerg Wunsch if (!nflag) {
134d51bdf32SKirk McKusick if (fscritmodified != 0) {
13539bb6d1eSPeter Wemm sblock.fs_clean = 0; /* mark it dirty */
13639bb6d1eSPeter Wemm sbdirty();
137d51bdf32SKirk McKusick }
138d51bdf32SKirk McKusick ckfini(fscritmodified ? 0 : sblock.fs_clean);
139d51bdf32SKirk McKusick if (fscritmodified == 0)
140d51bdf32SKirk McKusick exit(0);
14139bb6d1eSPeter Wemm printf("*** FILE SYSTEM MARKED DIRTY\n");
14239bb6d1eSPeter Wemm printf("*** BE SURE TO RUN FSCK TO CLEAN UP ANY DAMAGE\n");
1435cc52631SKirk McKusick printf("*** IF IT IS MOUNTED, RE-MOUNT WITH -u -o reload\n");
14436b8baa3SJoerg Wunsch }
14539bb6d1eSPeter Wemm exit(rval);
14639bb6d1eSPeter Wemm }
14739bb6d1eSPeter Wemm
1480638cc1aSWarner Losh #define CMDFUNC(func) int func(int argc, char *argv[])
1490638cc1aSWarner Losh #define CMDFUNCSTART(func) int func(int argc, char *argv[])
15039bb6d1eSPeter Wemm
15139bb6d1eSPeter Wemm CMDFUNC(helpfn);
15239bb6d1eSPeter Wemm CMDFUNC(focus); /* focus on inode */
15339bb6d1eSPeter Wemm CMDFUNC(active); /* print active inode */
154280a49ecSJoerg Wunsch CMDFUNC(blocks); /* print blocks for active inode */
15539bb6d1eSPeter Wemm CMDFUNC(focusname); /* focus by name */
15639bb6d1eSPeter Wemm CMDFUNC(zapi); /* clear inode */
15739bb6d1eSPeter Wemm CMDFUNC(uplink); /* incr link */
15839bb6d1eSPeter Wemm CMDFUNC(downlink); /* decr link */
15939bb6d1eSPeter Wemm CMDFUNC(linkcount); /* set link count */
16039bb6d1eSPeter Wemm CMDFUNC(quit); /* quit */
161*d059e44bSKirk McKusick CMDFUNC(quitclean); /* quit with filesystem marked clean */
16282d9b14eSMaxim Konovalov CMDFUNC(findblk); /* find block */
16339bb6d1eSPeter Wemm CMDFUNC(ls); /* list directory */
16439bb6d1eSPeter Wemm CMDFUNC(rm); /* remove name */
16539bb6d1eSPeter Wemm CMDFUNC(ln); /* add name */
16639bb6d1eSPeter Wemm CMDFUNC(newtype); /* change type */
16739bb6d1eSPeter Wemm CMDFUNC(chmode); /* change mode */
168a9bb2677SGuido van Rooij CMDFUNC(chlen); /* change length */
16939bb6d1eSPeter Wemm CMDFUNC(chaflags); /* change flags */
17039bb6d1eSPeter Wemm CMDFUNC(chgen); /* change generation */
17139bb6d1eSPeter Wemm CMDFUNC(chowner); /* change owner */
17239bb6d1eSPeter Wemm CMDFUNC(chgroup); /* Change group */
17339bb6d1eSPeter Wemm CMDFUNC(back); /* pop back to last ino */
17496dd6360SCeri Davies CMDFUNC(chbtime); /* Change btime */
17539bb6d1eSPeter Wemm CMDFUNC(chmtime); /* Change mtime */
17639bb6d1eSPeter Wemm CMDFUNC(chctime); /* Change ctime */
17739bb6d1eSPeter Wemm CMDFUNC(chatime); /* Change atime */
17839bb6d1eSPeter Wemm CMDFUNC(chinum); /* Change inode # of dirent */
17939bb6d1eSPeter Wemm CMDFUNC(chname); /* Change dirname of dirent */
180ac4b20a0SKirk McKusick CMDFUNC(chsize); /* Change size */
1817636973cSKirk McKusick CMDFUNC(chdb); /* Change direct block pointer */
18239bb6d1eSPeter Wemm
18339bb6d1eSPeter Wemm struct cmdtable cmds[] = {
18436b8baa3SJoerg Wunsch { "help", "Print out help", 1, 1, FL_RO, helpfn },
18536b8baa3SJoerg Wunsch { "?", "Print out help", 1, 1, FL_RO, helpfn },
18636b8baa3SJoerg Wunsch { "inode", "Set active inode to INUM", 2, 2, FL_RO, focus },
187d51bdf32SKirk McKusick { "clri", "Clear inode INUM", 2, 2, FL_CWR, zapi },
1881bc50849SMaxim Konovalov { "lookup", "Set active inode by looking up NAME", 2, 2, FL_RO | FL_ST, focusname },
1891bc50849SMaxim Konovalov { "cd", "Set active inode by looking up NAME", 2, 2, FL_RO | FL_ST, focusname },
19036b8baa3SJoerg Wunsch { "back", "Go to previous active inode", 1, 1, FL_RO, back },
19136b8baa3SJoerg Wunsch { "active", "Print active inode", 1, 1, FL_RO, active },
19236b8baa3SJoerg Wunsch { "print", "Print active inode", 1, 1, FL_RO, active },
193280a49ecSJoerg Wunsch { "blocks", "Print block numbers of active inode", 1, 1, FL_RO, blocks },
194d51bdf32SKirk McKusick { "uplink", "Increment link count", 1, 1, FL_CWR, uplink },
195d51bdf32SKirk McKusick { "downlink", "Decrement link count", 1, 1, FL_CWR, downlink },
196d51bdf32SKirk McKusick { "linkcount", "Set link count to COUNT", 2, 2, FL_CWR, linkcount },
19782d9b14eSMaxim Konovalov { "findblk", "Find inode owning disk block(s)", 2, 33, FL_RO, findblk},
19836b8baa3SJoerg Wunsch { "ls", "List current inode as directory", 1, 1, FL_RO, ls },
199d51bdf32SKirk McKusick { "rm", "Remove NAME from current inode directory", 2, 2, FL_CWR | FL_ST, rm },
200d51bdf32SKirk McKusick { "del", "Remove NAME from current inode directory", 2, 2, FL_CWR | FL_ST, rm },
201d51bdf32SKirk McKusick { "ln", "Hardlink INO into current inode directory as NAME", 3, 3, FL_CWR | FL_ST, ln },
202d51bdf32SKirk McKusick { "chinum", "Change dir entry number INDEX to INUM", 3, 3, FL_CWR, chinum },
2031bc50849SMaxim Konovalov { "chname", "Change dir entry number INDEX to NAME", 3, 3, FL_WR | FL_ST, chname },
204d51bdf32SKirk McKusick { "chtype", "Change type of current inode to TYPE", 2, 2, FL_CWR, newtype },
20536b8baa3SJoerg Wunsch { "chmod", "Change mode of current inode to MODE", 2, 2, FL_WR, chmode },
20636b8baa3SJoerg Wunsch { "chown", "Change owner of current inode to OWNER", 2, 2, FL_WR, chowner },
20736b8baa3SJoerg Wunsch { "chgrp", "Change group of current inode to GROUP", 2, 2, FL_WR, chgroup },
208d51bdf32SKirk McKusick { "chflags", "Change flags of current inode to FLAGS", 2, 2, FL_CWR, chaflags },
20936b8baa3SJoerg Wunsch { "chgen", "Change generation number of current inode to GEN", 2, 2, FL_WR, chgen },
210d51bdf32SKirk McKusick { "chsize", "Change size of current inode to SIZE", 2, 2, FL_CWR, chsize },
21196dd6360SCeri Davies { "btime", "Change btime of current inode to BTIME", 2, 2, FL_WR, chbtime },
21236b8baa3SJoerg Wunsch { "mtime", "Change mtime of current inode to MTIME", 2, 2, FL_WR, chmtime },
21336b8baa3SJoerg Wunsch { "ctime", "Change ctime of current inode to CTIME", 2, 2, FL_WR, chctime },
21436b8baa3SJoerg Wunsch { "atime", "Change atime of current inode to ATIME", 2, 2, FL_WR, chatime },
215d51bdf32SKirk McKusick { "chdb", "Change db pointer N of current inode to BLKNO", 3, 3, FL_CWR, chdb },
216*d059e44bSKirk McKusick { "quitclean", "Exit with filesystem marked clean", 1, 1, FL_RO, quitclean },
21736b8baa3SJoerg Wunsch { "quit", "Exit", 1, 1, FL_RO, quit },
21836b8baa3SJoerg Wunsch { "q", "Exit", 1, 1, FL_RO, quit },
21936b8baa3SJoerg Wunsch { "exit", "Exit", 1, 1, FL_RO, quit },
220c9eaf226SLukas Ertl { NULL, 0, 0, 0, 0, NULL },
22139bb6d1eSPeter Wemm };
22239bb6d1eSPeter Wemm
22339bb6d1eSPeter Wemm int
helpfn(int argc,char * argv[])2240638cc1aSWarner Losh helpfn(int argc, char *argv[])
22539bb6d1eSPeter Wemm {
2263d438ad6SDavid E. O'Brien struct cmdtable *cmdtp;
22739bb6d1eSPeter Wemm
22839bb6d1eSPeter Wemm printf("Commands are:\n%-10s %5s %5s %s\n",
2291bc50849SMaxim Konovalov "command", "min args", "max args", "what");
23039bb6d1eSPeter Wemm
23139bb6d1eSPeter Wemm for (cmdtp = cmds; cmdtp->cmd; cmdtp++)
23239bb6d1eSPeter Wemm printf("%-10s %5u %5u %s\n",
2331bc50849SMaxim Konovalov cmdtp->cmd, cmdtp->minargc-1, cmdtp->maxargc-1, cmdtp->helptxt);
23439bb6d1eSPeter Wemm return 0;
23539bb6d1eSPeter Wemm }
23639bb6d1eSPeter Wemm
23739bb6d1eSPeter Wemm char *
prompt(EditLine * el)2380638cc1aSWarner Losh prompt(EditLine *el)
23939bb6d1eSPeter Wemm {
24039bb6d1eSPeter Wemm static char pstring[64];
241e25a029eSMatthew D Fleming snprintf(pstring, sizeof(pstring), "fsdb (inum: %ju)> ",
242e25a029eSMatthew D Fleming (uintmax_t)curinum);
24339bb6d1eSPeter Wemm return pstring;
24439bb6d1eSPeter Wemm }
24539bb6d1eSPeter Wemm
2465cc52631SKirk McKusick static void
setcurinode(ino_t inum)2475cc52631SKirk McKusick setcurinode(ino_t inum)
2485cc52631SKirk McKusick {
2495cc52631SKirk McKusick
2505cc52631SKirk McKusick if (curip.i_number != 0)
2515cc52631SKirk McKusick irelse(&curip);
2525cc52631SKirk McKusick ginode(inum, &curip);
2535cc52631SKirk McKusick curinode = curip.i_dp;
2545cc52631SKirk McKusick curinum = inum;
2555cc52631SKirk McKusick }
25639bb6d1eSPeter Wemm
25739bb6d1eSPeter Wemm int
cmdloop(void)2580638cc1aSWarner Losh cmdloop(void)
25939bb6d1eSPeter Wemm {
26039bb6d1eSPeter Wemm char *line;
26139bb6d1eSPeter Wemm const char *elline;
26239bb6d1eSPeter Wemm int cmd_argc, rval = 0, known;
26339bb6d1eSPeter Wemm #define scratch known
26439bb6d1eSPeter Wemm char **cmd_argv;
26539bb6d1eSPeter Wemm struct cmdtable *cmdp;
26639bb6d1eSPeter Wemm History *hist;
26739bb6d1eSPeter Wemm EditLine *elptr;
268757eeda0SDavid E. O'Brien HistEvent he;
26939bb6d1eSPeter Wemm
2705cc52631SKirk McKusick setcurinode(UFS_ROOTINO);
271280a49ecSJoerg Wunsch printactive(0);
27239bb6d1eSPeter Wemm
27339bb6d1eSPeter Wemm hist = history_init();
2742110d9c3SStefan Farfeleder history(hist, &he, H_SETSIZE, 100); /* 100 elt history buffer */
27539bb6d1eSPeter Wemm
276757eeda0SDavid E. O'Brien elptr = el_init("fsdb", stdin, stdout, stderr);
27739bb6d1eSPeter Wemm el_set(elptr, EL_EDITOR, "emacs");
27839bb6d1eSPeter Wemm el_set(elptr, EL_PROMPT, prompt);
27939bb6d1eSPeter Wemm el_set(elptr, EL_HIST, history, hist);
28039bb6d1eSPeter Wemm el_source(elptr, NULL);
28139bb6d1eSPeter Wemm
28239bb6d1eSPeter Wemm while ((elline = el_gets(elptr, &scratch)) != NULL && scratch != 0) {
28339bb6d1eSPeter Wemm if (debug)
2840227048aSPhilippe Charnier printf("command `%s'\n", elline);
28539bb6d1eSPeter Wemm
286757eeda0SDavid E. O'Brien history(hist, &he, H_ENTER, elline);
28739bb6d1eSPeter Wemm
28839bb6d1eSPeter Wemm line = strdup(elline);
28939bb6d1eSPeter Wemm cmd_argv = crack(line, &cmd_argc);
29039bb6d1eSPeter Wemm /*
29139bb6d1eSPeter Wemm * el_parse returns -1 to signal that it's not been handled
29239bb6d1eSPeter Wemm * internally.
29339bb6d1eSPeter Wemm */
294515faf2fSStefan Farfeleder if (el_parse(elptr, cmd_argc, (const char **)cmd_argv) != -1)
29539bb6d1eSPeter Wemm continue;
29639bb6d1eSPeter Wemm if (cmd_argc) {
29739bb6d1eSPeter Wemm known = 0;
29839bb6d1eSPeter Wemm for (cmdp = cmds; cmdp->cmd; cmdp++) {
29939bb6d1eSPeter Wemm if (!strcmp(cmdp->cmd, cmd_argv[0])) {
300d51bdf32SKirk McKusick if ((cmdp->flags & (FL_CWR | FL_WR)) != 0 && nflag)
30136b8baa3SJoerg Wunsch warnx("`%s' requires write access", cmd_argv[0]),
30236b8baa3SJoerg Wunsch rval = 1;
30336b8baa3SJoerg Wunsch else if (cmd_argc >= cmdp->minargc &&
30439bb6d1eSPeter Wemm cmd_argc <= cmdp->maxargc)
30539bb6d1eSPeter Wemm rval = (*cmdp->handler)(cmd_argc, cmd_argv);
3061bc50849SMaxim Konovalov else if (cmd_argc >= cmdp->minargc &&
3071bc50849SMaxim Konovalov (cmdp->flags & FL_ST) == FL_ST) {
3088660ce22SBrian Feldman strcpy(line, elline);
3098660ce22SBrian Feldman cmd_argv = recrack(line, &cmd_argc, cmdp->maxargc);
3108660ce22SBrian Feldman rval = (*cmdp->handler)(cmd_argc, cmd_argv);
3118660ce22SBrian Feldman } else
31239bb6d1eSPeter Wemm rval = argcount(cmdp, cmd_argc, cmd_argv);
31339bb6d1eSPeter Wemm known = 1;
314d51bdf32SKirk McKusick if (rval == 0) {
315d51bdf32SKirk McKusick if ((cmdp->flags & FL_WR) != 0)
316d51bdf32SKirk McKusick fsnoncritmodified = 1;
317d51bdf32SKirk McKusick if ((cmdp->flags & FL_CWR) != 0)
318d51bdf32SKirk McKusick fscritmodified = 1;
319d51bdf32SKirk McKusick }
32039bb6d1eSPeter Wemm break;
32139bb6d1eSPeter Wemm }
32239bb6d1eSPeter Wemm }
32339bb6d1eSPeter Wemm if (!known)
32439bb6d1eSPeter Wemm warnx("unknown command `%s'", cmd_argv[0]), rval = 1;
32539bb6d1eSPeter Wemm } else
32639bb6d1eSPeter Wemm rval = 0;
32739bb6d1eSPeter Wemm free(line);
3285cc52631SKirk McKusick if (rval < 0) {
329aaadf688SJoerg Wunsch /* user typed "quit" */
3305cc52631SKirk McKusick irelse(&curip);
331aaadf688SJoerg Wunsch return 0;
3325cc52631SKirk McKusick }
33339bb6d1eSPeter Wemm if (rval)
334d51bdf32SKirk McKusick warnx("command failed, return value was %d", rval);
33539bb6d1eSPeter Wemm }
33639bb6d1eSPeter Wemm el_end(elptr);
33739bb6d1eSPeter Wemm history_end(hist);
3385cc52631SKirk McKusick irelse(&curip);
33939bb6d1eSPeter Wemm return rval;
34039bb6d1eSPeter Wemm }
34139bb6d1eSPeter Wemm
34239bb6d1eSPeter Wemm #define GETINUM(ac,inum) inum = strtoul(argv[ac], &cp, 0); \
3431dc349abSEd Maste if (inum < UFS_ROOTINO || inum > maxino || cp == argv[ac] || *cp != '\0' ) { \
344e25a029eSMatthew D Fleming printf("inode %ju out of range; range is [%ju,%ju]\n", \
3451dc349abSEd Maste (uintmax_t)inum, (uintmax_t)UFS_ROOTINO, (uintmax_t)maxino);\
34639bb6d1eSPeter Wemm return 1; \
34739bb6d1eSPeter Wemm }
34839bb6d1eSPeter Wemm
34939bb6d1eSPeter Wemm /*
35039bb6d1eSPeter Wemm * Focus on given inode number
35139bb6d1eSPeter Wemm */
CMDFUNCSTART(focus)35239bb6d1eSPeter Wemm CMDFUNCSTART(focus)
35339bb6d1eSPeter Wemm {
35439bb6d1eSPeter Wemm ino_t inum;
35539bb6d1eSPeter Wemm char *cp;
35639bb6d1eSPeter Wemm
35739bb6d1eSPeter Wemm GETINUM(1,inum);
35839bb6d1eSPeter Wemm ocurrent = curinum;
3595cc52631SKirk McKusick setcurinode(inum);
360280a49ecSJoerg Wunsch printactive(0);
36139bb6d1eSPeter Wemm return 0;
36239bb6d1eSPeter Wemm }
36339bb6d1eSPeter Wemm
CMDFUNCSTART(back)36439bb6d1eSPeter Wemm CMDFUNCSTART(back)
36539bb6d1eSPeter Wemm {
3665cc52631SKirk McKusick setcurinode(ocurrent);
367280a49ecSJoerg Wunsch printactive(0);
36839bb6d1eSPeter Wemm return 0;
36939bb6d1eSPeter Wemm }
37039bb6d1eSPeter Wemm
CMDFUNCSTART(zapi)37139bb6d1eSPeter Wemm CMDFUNCSTART(zapi)
37239bb6d1eSPeter Wemm {
3735cc52631SKirk McKusick struct inode ip;
37439bb6d1eSPeter Wemm ino_t inum;
37539bb6d1eSPeter Wemm char *cp;
37639bb6d1eSPeter Wemm
37739bb6d1eSPeter Wemm GETINUM(1,inum);
3785cc52631SKirk McKusick ginode(inum, &ip);
3795cc52631SKirk McKusick clearinode(ip.i_dp);
3805cc52631SKirk McKusick inodirty(&ip);
3815cc52631SKirk McKusick irelse(&ip);
38239bb6d1eSPeter Wemm return 0;
38339bb6d1eSPeter Wemm }
38439bb6d1eSPeter Wemm
CMDFUNCSTART(active)38539bb6d1eSPeter Wemm CMDFUNCSTART(active)
38639bb6d1eSPeter Wemm {
387280a49ecSJoerg Wunsch printactive(0);
38839bb6d1eSPeter Wemm return 0;
38939bb6d1eSPeter Wemm }
39039bb6d1eSPeter Wemm
CMDFUNCSTART(blocks)391280a49ecSJoerg Wunsch CMDFUNCSTART(blocks)
392280a49ecSJoerg Wunsch {
393280a49ecSJoerg Wunsch printactive(1);
394280a49ecSJoerg Wunsch return 0;
395280a49ecSJoerg Wunsch }
39639bb6d1eSPeter Wemm
CMDFUNCSTART(quit)39739bb6d1eSPeter Wemm CMDFUNCSTART(quit)
39839bb6d1eSPeter Wemm {
39939bb6d1eSPeter Wemm return -1;
40039bb6d1eSPeter Wemm }
40139bb6d1eSPeter Wemm
CMDFUNCSTART(quitclean)402*d059e44bSKirk McKusick CMDFUNCSTART(quitclean)
403*d059e44bSKirk McKusick {
404*d059e44bSKirk McKusick if (fscritmodified) {
405*d059e44bSKirk McKusick printf("Warning: modified filesystem marked clean\n");
406*d059e44bSKirk McKusick fscritmodified = 0;
407*d059e44bSKirk McKusick sblock.fs_clean = 1;
408*d059e44bSKirk McKusick }
409*d059e44bSKirk McKusick return -1;
410*d059e44bSKirk McKusick }
411*d059e44bSKirk McKusick
CMDFUNCSTART(uplink)41239bb6d1eSPeter Wemm CMDFUNCSTART(uplink)
41339bb6d1eSPeter Wemm {
41439bb6d1eSPeter Wemm if (!checkactive())
41539bb6d1eSPeter Wemm return 1;
416c9eaf226SLukas Ertl DIP_SET(curinode, di_nlink, DIP(curinode, di_nlink) + 1);
417e25a029eSMatthew D Fleming printf("inode %ju link count now %d\n",
418e25a029eSMatthew D Fleming (uintmax_t)curinum, DIP(curinode, di_nlink));
4195cc52631SKirk McKusick inodirty(&curip);
42039bb6d1eSPeter Wemm return 0;
42139bb6d1eSPeter Wemm }
42239bb6d1eSPeter Wemm
CMDFUNCSTART(downlink)42339bb6d1eSPeter Wemm CMDFUNCSTART(downlink)
42439bb6d1eSPeter Wemm {
42539bb6d1eSPeter Wemm if (!checkactive())
42639bb6d1eSPeter Wemm return 1;
427c9eaf226SLukas Ertl DIP_SET(curinode, di_nlink, DIP(curinode, di_nlink) - 1);
428e25a029eSMatthew D Fleming printf("inode %ju link count now %d\n",
429e25a029eSMatthew D Fleming (uintmax_t)curinum, DIP(curinode, di_nlink));
4305cc52631SKirk McKusick inodirty(&curip);
43139bb6d1eSPeter Wemm return 0;
43239bb6d1eSPeter Wemm }
43339bb6d1eSPeter Wemm
43439bb6d1eSPeter Wemm const char *typename[] = {
43539bb6d1eSPeter Wemm "unknown",
43639bb6d1eSPeter Wemm "fifo",
43739bb6d1eSPeter Wemm "char special",
43839bb6d1eSPeter Wemm "unregistered #3",
43939bb6d1eSPeter Wemm "directory",
44039bb6d1eSPeter Wemm "unregistered #5",
44139bb6d1eSPeter Wemm "blk special",
44239bb6d1eSPeter Wemm "unregistered #7",
44339bb6d1eSPeter Wemm "regular",
44439bb6d1eSPeter Wemm "unregistered #9",
44539bb6d1eSPeter Wemm "symlink",
44639bb6d1eSPeter Wemm "unregistered #11",
44739bb6d1eSPeter Wemm "socket",
44839bb6d1eSPeter Wemm "unregistered #13",
44939bb6d1eSPeter Wemm "whiteout",
45039bb6d1eSPeter Wemm };
45139bb6d1eSPeter Wemm
452113db2ddSJeff Roberson int diroff;
45339bb6d1eSPeter Wemm int slot;
45439bb6d1eSPeter Wemm
45539bb6d1eSPeter Wemm int
scannames(struct inodesc * idesc)4560638cc1aSWarner Losh scannames(struct inodesc *idesc)
45739bb6d1eSPeter Wemm {
4583d438ad6SDavid E. O'Brien struct direct *dirp = idesc->id_dirp;
45939bb6d1eSPeter Wemm
460113db2ddSJeff Roberson printf("slot %d off %d ino %d reclen %d: %s, `%.*s'\n",
461113db2ddSJeff Roberson slot++, diroff, dirp->d_ino, dirp->d_reclen,
462113db2ddSJeff Roberson typename[dirp->d_type], dirp->d_namlen, dirp->d_name);
463113db2ddSJeff Roberson diroff += dirp->d_reclen;
46439bb6d1eSPeter Wemm return (KEEPON);
46539bb6d1eSPeter Wemm }
46639bb6d1eSPeter Wemm
CMDFUNCSTART(ls)46739bb6d1eSPeter Wemm CMDFUNCSTART(ls)
46839bb6d1eSPeter Wemm {
46939bb6d1eSPeter Wemm struct inodesc idesc;
47039bb6d1eSPeter Wemm checkactivedir(); /* let it go on anyway */
47139bb6d1eSPeter Wemm
47239bb6d1eSPeter Wemm slot = 0;
473113db2ddSJeff Roberson diroff = 0;
47439bb6d1eSPeter Wemm idesc.id_number = curinum;
47539bb6d1eSPeter Wemm idesc.id_func = scannames;
47639bb6d1eSPeter Wemm idesc.id_type = DATA;
47739bb6d1eSPeter Wemm idesc.id_fix = IGNORE;
47839bb6d1eSPeter Wemm ckinode(curinode, &idesc);
47939bb6d1eSPeter Wemm
48039bb6d1eSPeter Wemm return 0;
48139bb6d1eSPeter Wemm }
48239bb6d1eSPeter Wemm
48382d9b14eSMaxim Konovalov static int findblk_numtofind;
48482d9b14eSMaxim Konovalov static int wantedblksize;
48582d9b14eSMaxim Konovalov
CMDFUNCSTART(findblk)48682d9b14eSMaxim Konovalov CMDFUNCSTART(findblk)
48782d9b14eSMaxim Konovalov {
48882d9b14eSMaxim Konovalov ino_t inum, inosused;
48982d9b14eSMaxim Konovalov uint32_t *wantedblk32;
49082d9b14eSMaxim Konovalov uint64_t *wantedblk64;
49181fbded2SKirk McKusick struct bufarea *cgbp;
49281fbded2SKirk McKusick struct cg *cgp;
49382d9b14eSMaxim Konovalov int c, i, is_ufs2;
49482d9b14eSMaxim Konovalov
49582d9b14eSMaxim Konovalov wantedblksize = (argc - 1);
49682d9b14eSMaxim Konovalov is_ufs2 = sblock.fs_magic == FS_UFS2_MAGIC;
49782d9b14eSMaxim Konovalov ocurrent = curinum;
49882d9b14eSMaxim Konovalov
49982d9b14eSMaxim Konovalov if (is_ufs2) {
50082d9b14eSMaxim Konovalov wantedblk64 = calloc(wantedblksize, sizeof(uint64_t));
50182d9b14eSMaxim Konovalov if (wantedblk64 == NULL)
50282d9b14eSMaxim Konovalov err(1, "malloc");
50382d9b14eSMaxim Konovalov for (i = 1; i < argc; i++)
50482d9b14eSMaxim Konovalov wantedblk64[i - 1] = dbtofsb(&sblock, strtoull(argv[i], NULL, 0));
50582d9b14eSMaxim Konovalov } else {
50682d9b14eSMaxim Konovalov wantedblk32 = calloc(wantedblksize, sizeof(uint32_t));
50782d9b14eSMaxim Konovalov if (wantedblk32 == NULL)
50882d9b14eSMaxim Konovalov err(1, "malloc");
50982d9b14eSMaxim Konovalov for (i = 1; i < argc; i++)
51082d9b14eSMaxim Konovalov wantedblk32[i - 1] = dbtofsb(&sblock, strtoull(argv[i], NULL, 0));
51182d9b14eSMaxim Konovalov }
51282d9b14eSMaxim Konovalov findblk_numtofind = wantedblksize;
51382d9b14eSMaxim Konovalov /*
51482d9b14eSMaxim Konovalov * sblock.fs_ncg holds a number of cylinder groups.
51582d9b14eSMaxim Konovalov * Iterate over all cylinder groups.
51682d9b14eSMaxim Konovalov */
51782d9b14eSMaxim Konovalov for (c = 0; c < sblock.fs_ncg; c++) {
51882d9b14eSMaxim Konovalov /*
51982d9b14eSMaxim Konovalov * sblock.fs_ipg holds a number of inodes per cylinder group.
52082d9b14eSMaxim Konovalov * Calculate a highest inode number for a given cylinder group.
52182d9b14eSMaxim Konovalov */
52282d9b14eSMaxim Konovalov inum = c * sblock.fs_ipg;
52382d9b14eSMaxim Konovalov /* Read cylinder group. */
5242d3c3a50SDimitry Andric cgbp = cglookup(c);
52581fbded2SKirk McKusick cgp = cgbp->b_un.b_cg;
52682d9b14eSMaxim Konovalov /*
52782d9b14eSMaxim Konovalov * Get a highest used inode number for a given cylinder group.
52882d9b14eSMaxim Konovalov * For UFS1 all inodes initialized at the newfs stage.
52982d9b14eSMaxim Konovalov */
53082d9b14eSMaxim Konovalov if (is_ufs2)
53182d9b14eSMaxim Konovalov inosused = cgp->cg_initediblk;
53282d9b14eSMaxim Konovalov else
53382d9b14eSMaxim Konovalov inosused = sblock.fs_ipg;
53482d9b14eSMaxim Konovalov
53582d9b14eSMaxim Konovalov for (; inosused > 0; inum++, inosused--) {
5361dc349abSEd Maste /* Skip magic inodes: 0, UFS_WINO, UFS_ROOTINO. */
5371dc349abSEd Maste if (inum < UFS_ROOTINO)
53882d9b14eSMaxim Konovalov continue;
53982d9b14eSMaxim Konovalov /*
54082d9b14eSMaxim Konovalov * Check if the block we are looking for is just an inode block.
54182d9b14eSMaxim Konovalov *
54282d9b14eSMaxim Konovalov * ino_to_fsba() - get block containing inode from its number.
54382d9b14eSMaxim Konovalov * INOPB() - get a number of inodes in one disk block.
54482d9b14eSMaxim Konovalov */
54582d9b14eSMaxim Konovalov if (is_ufs2 ?
54682d9b14eSMaxim Konovalov compare_blk64(wantedblk64, ino_to_fsba(&sblock, inum)) :
54782d9b14eSMaxim Konovalov compare_blk32(wantedblk32, ino_to_fsba(&sblock, inum))) {
548e25a029eSMatthew D Fleming printf("block %llu: inode block (%ju-%ju)\n",
54982d9b14eSMaxim Konovalov (unsigned long long)fsbtodb(&sblock,
55082d9b14eSMaxim Konovalov ino_to_fsba(&sblock, inum)),
551e25a029eSMatthew D Fleming (uintmax_t)(inum / INOPB(&sblock)) * INOPB(&sblock),
552e25a029eSMatthew D Fleming (uintmax_t)(inum / INOPB(&sblock) + 1) * INOPB(&sblock));
55382d9b14eSMaxim Konovalov findblk_numtofind--;
55482d9b14eSMaxim Konovalov if (findblk_numtofind == 0)
55582d9b14eSMaxim Konovalov goto end;
55682d9b14eSMaxim Konovalov }
55782d9b14eSMaxim Konovalov /* Get on-disk inode aka dinode. */
5585cc52631SKirk McKusick setcurinode(inum);
559d8ba45e2SEd Maste /* Find IFLNK dinode with allocated data blocks. */
560d8ba45e2SEd Maste switch (DIP(curinode, di_mode) & IFMT) {
561d8ba45e2SEd Maste case IFDIR:
562d8ba45e2SEd Maste case IFREG:
56382d9b14eSMaxim Konovalov if (DIP(curinode, di_blocks) == 0)
56482d9b14eSMaxim Konovalov continue;
56582d9b14eSMaxim Konovalov break;
566d8ba45e2SEd Maste case IFLNK:
56782d9b14eSMaxim Konovalov {
56882d9b14eSMaxim Konovalov uint64_t size = DIP(curinode, di_size);
56982d9b14eSMaxim Konovalov if (size > 0 && size < sblock.fs_maxsymlinklen &&
57082d9b14eSMaxim Konovalov DIP(curinode, di_blocks) == 0)
57182d9b14eSMaxim Konovalov continue;
57282d9b14eSMaxim Konovalov else
57382d9b14eSMaxim Konovalov break;
57482d9b14eSMaxim Konovalov }
57582d9b14eSMaxim Konovalov default:
57682d9b14eSMaxim Konovalov continue;
57782d9b14eSMaxim Konovalov }
57882d9b14eSMaxim Konovalov /* Look through direct data blocks. */
57982d9b14eSMaxim Konovalov if (is_ufs2 ?
5801dc349abSEd Maste find_blks64(curinode->dp2.di_db, UFS_NDADDR, wantedblk64) :
5811dc349abSEd Maste find_blks32(curinode->dp1.di_db, UFS_NDADDR, wantedblk32))
58282d9b14eSMaxim Konovalov goto end;
5831dc349abSEd Maste for (i = 0; i < UFS_NIADDR; i++) {
58482d9b14eSMaxim Konovalov /*
58582d9b14eSMaxim Konovalov * Does the block we are looking for belongs to the
58682d9b14eSMaxim Konovalov * indirect blocks?
58782d9b14eSMaxim Konovalov */
58882d9b14eSMaxim Konovalov if (is_ufs2 ?
58982d9b14eSMaxim Konovalov compare_blk64(wantedblk64, curinode->dp2.di_ib[i]) :
59082d9b14eSMaxim Konovalov compare_blk32(wantedblk32, curinode->dp1.di_ib[i]))
59182d9b14eSMaxim Konovalov if (founddatablk(is_ufs2 ? curinode->dp2.di_ib[i] :
59282d9b14eSMaxim Konovalov curinode->dp1.di_ib[i]))
59382d9b14eSMaxim Konovalov goto end;
59482d9b14eSMaxim Konovalov /*
59582d9b14eSMaxim Konovalov * Search through indirect, double and triple indirect
59682d9b14eSMaxim Konovalov * data blocks.
59782d9b14eSMaxim Konovalov */
59882d9b14eSMaxim Konovalov if (is_ufs2 ? (curinode->dp2.di_ib[i] != 0) :
59982d9b14eSMaxim Konovalov (curinode->dp1.di_ib[i] != 0))
60082d9b14eSMaxim Konovalov if (is_ufs2 ?
60182d9b14eSMaxim Konovalov find_indirblks64(curinode->dp2.di_ib[i], i,
60282d9b14eSMaxim Konovalov wantedblk64) :
60382d9b14eSMaxim Konovalov find_indirblks32(curinode->dp1.di_ib[i], i,
60482d9b14eSMaxim Konovalov wantedblk32))
60582d9b14eSMaxim Konovalov goto end;
60682d9b14eSMaxim Konovalov }
60782d9b14eSMaxim Konovalov }
60882d9b14eSMaxim Konovalov }
60982d9b14eSMaxim Konovalov end:
6105cc52631SKirk McKusick setcurinode(ocurrent);
6115a8ad265SXin LI if (is_ufs2)
6120bebba31SWarner Losh free(wantedblk64);
6135a8ad265SXin LI else
6145a8ad265SXin LI free(wantedblk32);
61582d9b14eSMaxim Konovalov return 0;
61682d9b14eSMaxim Konovalov }
61782d9b14eSMaxim Konovalov
61882d9b14eSMaxim Konovalov static int
compare_blk32(uint32_t * wantedblk,uint32_t curblk)61982d9b14eSMaxim Konovalov compare_blk32(uint32_t *wantedblk, uint32_t curblk)
62082d9b14eSMaxim Konovalov {
62182d9b14eSMaxim Konovalov int i;
62282d9b14eSMaxim Konovalov
62382d9b14eSMaxim Konovalov for (i = 0; i < wantedblksize; i++) {
62482d9b14eSMaxim Konovalov if (wantedblk[i] != 0 && wantedblk[i] == curblk) {
62582d9b14eSMaxim Konovalov wantedblk[i] = 0;
62682d9b14eSMaxim Konovalov return 1;
62782d9b14eSMaxim Konovalov }
62882d9b14eSMaxim Konovalov }
62982d9b14eSMaxim Konovalov return 0;
63082d9b14eSMaxim Konovalov }
63182d9b14eSMaxim Konovalov
63282d9b14eSMaxim Konovalov static int
compare_blk64(uint64_t * wantedblk,uint64_t curblk)63382d9b14eSMaxim Konovalov compare_blk64(uint64_t *wantedblk, uint64_t curblk)
63482d9b14eSMaxim Konovalov {
63582d9b14eSMaxim Konovalov int i;
63682d9b14eSMaxim Konovalov
63782d9b14eSMaxim Konovalov for (i = 0; i < wantedblksize; i++) {
63882d9b14eSMaxim Konovalov if (wantedblk[i] != 0 && wantedblk[i] == curblk) {
63982d9b14eSMaxim Konovalov wantedblk[i] = 0;
64082d9b14eSMaxim Konovalov return 1;
64182d9b14eSMaxim Konovalov }
64282d9b14eSMaxim Konovalov }
64382d9b14eSMaxim Konovalov return 0;
64482d9b14eSMaxim Konovalov }
64582d9b14eSMaxim Konovalov
64682d9b14eSMaxim Konovalov static int
founddatablk(uint64_t blk)64782d9b14eSMaxim Konovalov founddatablk(uint64_t blk)
64882d9b14eSMaxim Konovalov {
64982d9b14eSMaxim Konovalov
650e25a029eSMatthew D Fleming printf("%llu: data block of inode %ju\n",
651e25a029eSMatthew D Fleming (unsigned long long)fsbtodb(&sblock, blk), (uintmax_t)curinum);
65282d9b14eSMaxim Konovalov findblk_numtofind--;
65382d9b14eSMaxim Konovalov if (findblk_numtofind == 0)
65482d9b14eSMaxim Konovalov return 1;
65582d9b14eSMaxim Konovalov return 0;
65682d9b14eSMaxim Konovalov }
65782d9b14eSMaxim Konovalov
65882d9b14eSMaxim Konovalov static int
find_blks32(uint32_t * buf,int size,uint32_t * wantedblk)65982d9b14eSMaxim Konovalov find_blks32(uint32_t *buf, int size, uint32_t *wantedblk)
66082d9b14eSMaxim Konovalov {
66182d9b14eSMaxim Konovalov int blk;
66282d9b14eSMaxim Konovalov for (blk = 0; blk < size; blk++) {
66382d9b14eSMaxim Konovalov if (buf[blk] == 0)
66482d9b14eSMaxim Konovalov continue;
66582d9b14eSMaxim Konovalov if (compare_blk32(wantedblk, buf[blk])) {
66682d9b14eSMaxim Konovalov if (founddatablk(buf[blk]))
66782d9b14eSMaxim Konovalov return 1;
66882d9b14eSMaxim Konovalov }
66982d9b14eSMaxim Konovalov }
67082d9b14eSMaxim Konovalov return 0;
67182d9b14eSMaxim Konovalov }
67282d9b14eSMaxim Konovalov
67382d9b14eSMaxim Konovalov static int
find_indirblks32(uint32_t blk,int ind_level,uint32_t * wantedblk)67482d9b14eSMaxim Konovalov find_indirblks32(uint32_t blk, int ind_level, uint32_t *wantedblk)
67582d9b14eSMaxim Konovalov {
67682d9b14eSMaxim Konovalov #define MAXNINDIR (MAXBSIZE / sizeof(uint32_t))
67782d9b14eSMaxim Konovalov uint32_t idblk[MAXNINDIR];
67882d9b14eSMaxim Konovalov int i;
67982d9b14eSMaxim Konovalov
680fffbc2a5SPawel Jakub Dawidek blread(fsreadfd, (char *)idblk, fsbtodb(&sblock, blk), (int)sblock.fs_bsize);
68182d9b14eSMaxim Konovalov if (ind_level <= 0) {
68282d9b14eSMaxim Konovalov if (find_blks32(idblk, sblock.fs_bsize / sizeof(uint32_t), wantedblk))
68382d9b14eSMaxim Konovalov return 1;
68482d9b14eSMaxim Konovalov } else {
68582d9b14eSMaxim Konovalov ind_level--;
68682d9b14eSMaxim Konovalov for (i = 0; i < sblock.fs_bsize / sizeof(uint32_t); i++) {
68782d9b14eSMaxim Konovalov if (compare_blk32(wantedblk, idblk[i])) {
68882d9b14eSMaxim Konovalov if (founddatablk(idblk[i]))
68982d9b14eSMaxim Konovalov return 1;
69082d9b14eSMaxim Konovalov }
69182d9b14eSMaxim Konovalov if (idblk[i] != 0)
69282d9b14eSMaxim Konovalov if (find_indirblks32(idblk[i], ind_level, wantedblk))
69382d9b14eSMaxim Konovalov return 1;
69482d9b14eSMaxim Konovalov }
69582d9b14eSMaxim Konovalov }
69682d9b14eSMaxim Konovalov #undef MAXNINDIR
69782d9b14eSMaxim Konovalov return 0;
69882d9b14eSMaxim Konovalov }
69982d9b14eSMaxim Konovalov
70082d9b14eSMaxim Konovalov static int
find_blks64(uint64_t * buf,int size,uint64_t * wantedblk)70182d9b14eSMaxim Konovalov find_blks64(uint64_t *buf, int size, uint64_t *wantedblk)
70282d9b14eSMaxim Konovalov {
70382d9b14eSMaxim Konovalov int blk;
70482d9b14eSMaxim Konovalov for (blk = 0; blk < size; blk++) {
70582d9b14eSMaxim Konovalov if (buf[blk] == 0)
70682d9b14eSMaxim Konovalov continue;
70782d9b14eSMaxim Konovalov if (compare_blk64(wantedblk, buf[blk])) {
70882d9b14eSMaxim Konovalov if (founddatablk(buf[blk]))
70982d9b14eSMaxim Konovalov return 1;
71082d9b14eSMaxim Konovalov }
71182d9b14eSMaxim Konovalov }
71282d9b14eSMaxim Konovalov return 0;
71382d9b14eSMaxim Konovalov }
71482d9b14eSMaxim Konovalov
71582d9b14eSMaxim Konovalov static int
find_indirblks64(uint64_t blk,int ind_level,uint64_t * wantedblk)71682d9b14eSMaxim Konovalov find_indirblks64(uint64_t blk, int ind_level, uint64_t *wantedblk)
71782d9b14eSMaxim Konovalov {
71882d9b14eSMaxim Konovalov #define MAXNINDIR (MAXBSIZE / sizeof(uint64_t))
71982d9b14eSMaxim Konovalov uint64_t idblk[MAXNINDIR];
72082d9b14eSMaxim Konovalov int i;
72182d9b14eSMaxim Konovalov
722fffbc2a5SPawel Jakub Dawidek blread(fsreadfd, (char *)idblk, fsbtodb(&sblock, blk), (int)sblock.fs_bsize);
72382d9b14eSMaxim Konovalov if (ind_level <= 0) {
72482d9b14eSMaxim Konovalov if (find_blks64(idblk, sblock.fs_bsize / sizeof(uint64_t), wantedblk))
72582d9b14eSMaxim Konovalov return 1;
72682d9b14eSMaxim Konovalov } else {
72782d9b14eSMaxim Konovalov ind_level--;
72882d9b14eSMaxim Konovalov for (i = 0; i < sblock.fs_bsize / sizeof(uint64_t); i++) {
72982d9b14eSMaxim Konovalov if (compare_blk64(wantedblk, idblk[i])) {
73082d9b14eSMaxim Konovalov if (founddatablk(idblk[i]))
73182d9b14eSMaxim Konovalov return 1;
73282d9b14eSMaxim Konovalov }
73382d9b14eSMaxim Konovalov if (idblk[i] != 0)
73482d9b14eSMaxim Konovalov if (find_indirblks64(idblk[i], ind_level, wantedblk))
73582d9b14eSMaxim Konovalov return 1;
73682d9b14eSMaxim Konovalov }
73782d9b14eSMaxim Konovalov }
73882d9b14eSMaxim Konovalov #undef MAXNINDIR
73982d9b14eSMaxim Konovalov return 0;
74082d9b14eSMaxim Konovalov }
74182d9b14eSMaxim Konovalov
7420638cc1aSWarner Losh int findino(struct inodesc *idesc); /* from fsck */
7430638cc1aSWarner Losh static int dolookup(char *name);
74439bb6d1eSPeter Wemm
74539bb6d1eSPeter Wemm static int
dolookup(char * name)7460638cc1aSWarner Losh dolookup(char *name)
74739bb6d1eSPeter Wemm {
74839bb6d1eSPeter Wemm struct inodesc idesc;
74939bb6d1eSPeter Wemm
75039bb6d1eSPeter Wemm if (!checkactivedir())
75139bb6d1eSPeter Wemm return 0;
75239bb6d1eSPeter Wemm idesc.id_number = curinum;
75339bb6d1eSPeter Wemm idesc.id_func = findino;
75439bb6d1eSPeter Wemm idesc.id_name = name;
75539bb6d1eSPeter Wemm idesc.id_type = DATA;
75639bb6d1eSPeter Wemm idesc.id_fix = IGNORE;
75739bb6d1eSPeter Wemm if (ckinode(curinode, &idesc) & FOUND) {
7585cc52631SKirk McKusick setcurinode(idesc.id_parent);
759280a49ecSJoerg Wunsch printactive(0);
76039bb6d1eSPeter Wemm return 1;
76139bb6d1eSPeter Wemm } else {
76239bb6d1eSPeter Wemm warnx("name `%s' not found in current inode directory", name);
76339bb6d1eSPeter Wemm return 0;
76439bb6d1eSPeter Wemm }
76539bb6d1eSPeter Wemm }
76639bb6d1eSPeter Wemm
CMDFUNCSTART(focusname)76739bb6d1eSPeter Wemm CMDFUNCSTART(focusname)
76839bb6d1eSPeter Wemm {
76939bb6d1eSPeter Wemm char *p, *val;
77039bb6d1eSPeter Wemm
77139bb6d1eSPeter Wemm if (!checkactive())
77239bb6d1eSPeter Wemm return 1;
77339bb6d1eSPeter Wemm
77439bb6d1eSPeter Wemm ocurrent = curinum;
77539bb6d1eSPeter Wemm
77639bb6d1eSPeter Wemm if (argv[1][0] == '/') {
7775cc52631SKirk McKusick setcurinode(UFS_ROOTINO);
77839bb6d1eSPeter Wemm } else {
77939bb6d1eSPeter Wemm if (!checkactivedir())
78039bb6d1eSPeter Wemm return 1;
78139bb6d1eSPeter Wemm }
78239bb6d1eSPeter Wemm for (p = argv[1]; p != NULL;) {
78339bb6d1eSPeter Wemm while ((val = strsep(&p, "/")) != NULL && *val == '\0');
78439bb6d1eSPeter Wemm if (val) {
78539bb6d1eSPeter Wemm printf("component `%s': ", val);
78639bb6d1eSPeter Wemm fflush(stdout);
78739bb6d1eSPeter Wemm if (!dolookup(val)) {
78839bb6d1eSPeter Wemm return(1);
78939bb6d1eSPeter Wemm }
79039bb6d1eSPeter Wemm }
79139bb6d1eSPeter Wemm }
79239bb6d1eSPeter Wemm return 0;
79339bb6d1eSPeter Wemm }
79439bb6d1eSPeter Wemm
CMDFUNCSTART(ln)79539bb6d1eSPeter Wemm CMDFUNCSTART(ln)
79639bb6d1eSPeter Wemm {
79739bb6d1eSPeter Wemm ino_t inum;
79839bb6d1eSPeter Wemm int rval;
79939bb6d1eSPeter Wemm char *cp;
80039bb6d1eSPeter Wemm
80139bb6d1eSPeter Wemm GETINUM(1,inum);
80239bb6d1eSPeter Wemm
80339bb6d1eSPeter Wemm if (!checkactivedir())
80439bb6d1eSPeter Wemm return 1;
80539bb6d1eSPeter Wemm rval = makeentry(curinum, inum, argv[2]);
80639bb6d1eSPeter Wemm if (rval)
807e25a029eSMatthew D Fleming printf("Ino %ju entered as `%s'\n", (uintmax_t)inum, argv[2]);
80839bb6d1eSPeter Wemm else
80939bb6d1eSPeter Wemm printf("could not enter name? weird.\n");
81039bb6d1eSPeter Wemm return rval;
81139bb6d1eSPeter Wemm }
81239bb6d1eSPeter Wemm
CMDFUNCSTART(rm)81339bb6d1eSPeter Wemm CMDFUNCSTART(rm)
81439bb6d1eSPeter Wemm {
81539bb6d1eSPeter Wemm int rval;
81639bb6d1eSPeter Wemm
81739bb6d1eSPeter Wemm if (!checkactivedir())
81839bb6d1eSPeter Wemm return 1;
819fe5e6e2cSKirk McKusick rval = changeino(curinum, argv[1], 0, 0);
82039bb6d1eSPeter Wemm if (rval & ALTERED) {
82139bb6d1eSPeter Wemm printf("Name `%s' removed\n", argv[1]);
82239bb6d1eSPeter Wemm return 0;
82339bb6d1eSPeter Wemm } else {
8248660ce22SBrian Feldman printf("could not remove name ('%s')? weird.\n", argv[1]);
82539bb6d1eSPeter Wemm return 1;
82639bb6d1eSPeter Wemm }
82739bb6d1eSPeter Wemm }
82839bb6d1eSPeter Wemm
82939bb6d1eSPeter Wemm long slotcount, desired;
83039bb6d1eSPeter Wemm
83139bb6d1eSPeter Wemm int
chinumfunc(struct inodesc * idesc)8320638cc1aSWarner Losh chinumfunc(struct inodesc *idesc)
83339bb6d1eSPeter Wemm {
8343d438ad6SDavid E. O'Brien struct direct *dirp = idesc->id_dirp;
83539bb6d1eSPeter Wemm
83639bb6d1eSPeter Wemm if (slotcount++ == desired) {
83739bb6d1eSPeter Wemm dirp->d_ino = idesc->id_parent;
83839bb6d1eSPeter Wemm return STOP|ALTERED|FOUND;
83939bb6d1eSPeter Wemm }
84039bb6d1eSPeter Wemm return KEEPON;
84139bb6d1eSPeter Wemm }
84239bb6d1eSPeter Wemm
CMDFUNCSTART(chinum)84339bb6d1eSPeter Wemm CMDFUNCSTART(chinum)
84439bb6d1eSPeter Wemm {
84539bb6d1eSPeter Wemm char *cp;
84639bb6d1eSPeter Wemm ino_t inum;
84739bb6d1eSPeter Wemm struct inodesc idesc;
84839bb6d1eSPeter Wemm
84939bb6d1eSPeter Wemm slotcount = 0;
85039bb6d1eSPeter Wemm if (!checkactivedir())
85139bb6d1eSPeter Wemm return 1;
85239bb6d1eSPeter Wemm GETINUM(2,inum);
85339bb6d1eSPeter Wemm
85439bb6d1eSPeter Wemm desired = strtol(argv[1], &cp, 0);
85539bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0' || desired < 0) {
85639bb6d1eSPeter Wemm printf("invalid slot number `%s'\n", argv[1]);
85739bb6d1eSPeter Wemm return 1;
85839bb6d1eSPeter Wemm }
85939bb6d1eSPeter Wemm
86039bb6d1eSPeter Wemm idesc.id_number = curinum;
86139bb6d1eSPeter Wemm idesc.id_func = chinumfunc;
86239bb6d1eSPeter Wemm idesc.id_fix = IGNORE;
86339bb6d1eSPeter Wemm idesc.id_type = DATA;
86439bb6d1eSPeter Wemm idesc.id_parent = inum; /* XXX convenient hiding place */
86539bb6d1eSPeter Wemm
86639bb6d1eSPeter Wemm if (ckinode(curinode, &idesc) & FOUND)
86739bb6d1eSPeter Wemm return 0;
86839bb6d1eSPeter Wemm else {
86939bb6d1eSPeter Wemm warnx("no %sth slot in current directory", argv[1]);
87039bb6d1eSPeter Wemm return 1;
87139bb6d1eSPeter Wemm }
87239bb6d1eSPeter Wemm }
87339bb6d1eSPeter Wemm
87439bb6d1eSPeter Wemm int
chnamefunc(struct inodesc * idesc)8750638cc1aSWarner Losh chnamefunc(struct inodesc *idesc)
87639bb6d1eSPeter Wemm {
8773d438ad6SDavid E. O'Brien struct direct *dirp = idesc->id_dirp;
87839bb6d1eSPeter Wemm struct direct testdir;
87939bb6d1eSPeter Wemm
88039bb6d1eSPeter Wemm if (slotcount++ == desired) {
88139bb6d1eSPeter Wemm /* will name fit? */
88239bb6d1eSPeter Wemm testdir.d_namlen = strlen(idesc->id_name);
88339bb6d1eSPeter Wemm if (DIRSIZ(NEWDIRFMT, &testdir) <= dirp->d_reclen) {
88439bb6d1eSPeter Wemm dirp->d_namlen = testdir.d_namlen;
88539bb6d1eSPeter Wemm strcpy(dirp->d_name, idesc->id_name);
88639bb6d1eSPeter Wemm return STOP|ALTERED|FOUND;
88739bb6d1eSPeter Wemm } else
88839bb6d1eSPeter Wemm return STOP|FOUND; /* won't fit, so give up */
88939bb6d1eSPeter Wemm }
89039bb6d1eSPeter Wemm return KEEPON;
89139bb6d1eSPeter Wemm }
89239bb6d1eSPeter Wemm
CMDFUNCSTART(chname)89339bb6d1eSPeter Wemm CMDFUNCSTART(chname)
89439bb6d1eSPeter Wemm {
89539bb6d1eSPeter Wemm int rval;
89639bb6d1eSPeter Wemm char *cp;
89739bb6d1eSPeter Wemm struct inodesc idesc;
89839bb6d1eSPeter Wemm
89939bb6d1eSPeter Wemm slotcount = 0;
90039bb6d1eSPeter Wemm if (!checkactivedir())
90139bb6d1eSPeter Wemm return 1;
90239bb6d1eSPeter Wemm
90339bb6d1eSPeter Wemm desired = strtoul(argv[1], &cp, 0);
90439bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0') {
90539bb6d1eSPeter Wemm printf("invalid slot number `%s'\n", argv[1]);
90639bb6d1eSPeter Wemm return 1;
90739bb6d1eSPeter Wemm }
90839bb6d1eSPeter Wemm
90939bb6d1eSPeter Wemm idesc.id_number = curinum;
91039bb6d1eSPeter Wemm idesc.id_func = chnamefunc;
91139bb6d1eSPeter Wemm idesc.id_fix = IGNORE;
91239bb6d1eSPeter Wemm idesc.id_type = DATA;
91339bb6d1eSPeter Wemm idesc.id_name = argv[2];
91439bb6d1eSPeter Wemm
91539bb6d1eSPeter Wemm rval = ckinode(curinode, &idesc);
91639bb6d1eSPeter Wemm if ((rval & (FOUND|ALTERED)) == (FOUND|ALTERED))
91739bb6d1eSPeter Wemm return 0;
91839bb6d1eSPeter Wemm else if (rval & FOUND) {
91939bb6d1eSPeter Wemm warnx("new name `%s' does not fit in slot %s\n", argv[2], argv[1]);
92039bb6d1eSPeter Wemm return 1;
92139bb6d1eSPeter Wemm } else {
92239bb6d1eSPeter Wemm warnx("no %sth slot in current directory", argv[1]);
92339bb6d1eSPeter Wemm return 1;
92439bb6d1eSPeter Wemm }
92539bb6d1eSPeter Wemm }
92639bb6d1eSPeter Wemm
92739bb6d1eSPeter Wemm struct typemap {
92839bb6d1eSPeter Wemm const char *typename;
92939bb6d1eSPeter Wemm int typebits;
93039bb6d1eSPeter Wemm } typenamemap[] = {
931d8ba45e2SEd Maste {"file", IFREG},
932d8ba45e2SEd Maste {"dir", IFDIR},
933d8ba45e2SEd Maste {"socket", IFSOCK},
934d8ba45e2SEd Maste {"fifo", IFIFO},
93539bb6d1eSPeter Wemm };
93639bb6d1eSPeter Wemm
CMDFUNCSTART(newtype)93739bb6d1eSPeter Wemm CMDFUNCSTART(newtype)
93839bb6d1eSPeter Wemm {
93939bb6d1eSPeter Wemm int type;
94039bb6d1eSPeter Wemm struct typemap *tp;
94139bb6d1eSPeter Wemm
94239bb6d1eSPeter Wemm if (!checkactive())
94339bb6d1eSPeter Wemm return 1;
944d8ba45e2SEd Maste type = DIP(curinode, di_mode) & IFMT;
94539bb6d1eSPeter Wemm for (tp = typenamemap;
94602c8c118SMarcelo Araujo tp < &typenamemap[nitems(typenamemap)];
94739bb6d1eSPeter Wemm tp++) {
94839bb6d1eSPeter Wemm if (!strcmp(argv[1], tp->typename)) {
94939bb6d1eSPeter Wemm printf("setting type to %s\n", tp->typename);
95039bb6d1eSPeter Wemm type = tp->typebits;
95139bb6d1eSPeter Wemm break;
95239bb6d1eSPeter Wemm }
95339bb6d1eSPeter Wemm }
95402c8c118SMarcelo Araujo if (tp == &typenamemap[nitems(typenamemap)]) {
95539bb6d1eSPeter Wemm warnx("type `%s' not known", argv[1]);
95639bb6d1eSPeter Wemm warnx("try one of `file', `dir', `socket', `fifo'");
95739bb6d1eSPeter Wemm return 1;
95839bb6d1eSPeter Wemm }
959d8ba45e2SEd Maste DIP_SET(curinode, di_mode, DIP(curinode, di_mode) & ~IFMT);
960c9eaf226SLukas Ertl DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | type);
9615cc52631SKirk McKusick inodirty(&curip);
962280a49ecSJoerg Wunsch printactive(0);
96339bb6d1eSPeter Wemm return 0;
96439bb6d1eSPeter Wemm }
96539bb6d1eSPeter Wemm
CMDFUNCSTART(chmode)96639bb6d1eSPeter Wemm CMDFUNCSTART(chmode)
96739bb6d1eSPeter Wemm {
96839bb6d1eSPeter Wemm long modebits;
96939bb6d1eSPeter Wemm char *cp;
97039bb6d1eSPeter Wemm
97139bb6d1eSPeter Wemm if (!checkactive())
97239bb6d1eSPeter Wemm return 1;
97339bb6d1eSPeter Wemm
97439bb6d1eSPeter Wemm modebits = strtol(argv[1], &cp, 8);
97575249b64SIan Dowse if (cp == argv[1] || *cp != '\0' || (modebits & ~07777)) {
97639bb6d1eSPeter Wemm warnx("bad modebits `%s'", argv[1]);
97739bb6d1eSPeter Wemm return 1;
97839bb6d1eSPeter Wemm }
97939bb6d1eSPeter Wemm
980c9eaf226SLukas Ertl DIP_SET(curinode, di_mode, DIP(curinode, di_mode) & ~07777);
981c9eaf226SLukas Ertl DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | modebits);
9825cc52631SKirk McKusick inodirty(&curip);
983280a49ecSJoerg Wunsch printactive(0);
984d51bdf32SKirk McKusick return 0;
98539bb6d1eSPeter Wemm }
98639bb6d1eSPeter Wemm
CMDFUNCSTART(chaflags)98739bb6d1eSPeter Wemm CMDFUNCSTART(chaflags)
98839bb6d1eSPeter Wemm {
98939bb6d1eSPeter Wemm u_long flags;
99039bb6d1eSPeter Wemm char *cp;
99139bb6d1eSPeter Wemm
99239bb6d1eSPeter Wemm if (!checkactive())
99339bb6d1eSPeter Wemm return 1;
99439bb6d1eSPeter Wemm
99539bb6d1eSPeter Wemm flags = strtoul(argv[1], &cp, 0);
99639bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0' ) {
99739bb6d1eSPeter Wemm warnx("bad flags `%s'", argv[1]);
99839bb6d1eSPeter Wemm return 1;
99939bb6d1eSPeter Wemm }
100039bb6d1eSPeter Wemm
100139bb6d1eSPeter Wemm if (flags > UINT_MAX) {
100239bb6d1eSPeter Wemm warnx("flags set beyond 32-bit range of field (%lx)\n", flags);
100339bb6d1eSPeter Wemm return(1);
100439bb6d1eSPeter Wemm }
1005c9eaf226SLukas Ertl DIP_SET(curinode, di_flags, flags);
10065cc52631SKirk McKusick inodirty(&curip);
1007280a49ecSJoerg Wunsch printactive(0);
1008d51bdf32SKirk McKusick return 0;
100939bb6d1eSPeter Wemm }
101039bb6d1eSPeter Wemm
CMDFUNCSTART(chgen)101139bb6d1eSPeter Wemm CMDFUNCSTART(chgen)
101239bb6d1eSPeter Wemm {
101339bb6d1eSPeter Wemm long gen;
101439bb6d1eSPeter Wemm char *cp;
101539bb6d1eSPeter Wemm
101639bb6d1eSPeter Wemm if (!checkactive())
101739bb6d1eSPeter Wemm return 1;
101839bb6d1eSPeter Wemm
101939bb6d1eSPeter Wemm gen = strtol(argv[1], &cp, 0);
102039bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0' ) {
102139bb6d1eSPeter Wemm warnx("bad gen `%s'", argv[1]);
102239bb6d1eSPeter Wemm return 1;
102339bb6d1eSPeter Wemm }
102439bb6d1eSPeter Wemm
1025d51bdf32SKirk McKusick if (gen > UINT_MAX) {
1026d51bdf32SKirk McKusick warnx("gen set beyond 32-bit range of field (0x%lx), max is 0x%x\n",
1027d51bdf32SKirk McKusick gen, UINT_MAX);
102839bb6d1eSPeter Wemm return(1);
102939bb6d1eSPeter Wemm }
1030c9eaf226SLukas Ertl DIP_SET(curinode, di_gen, gen);
10315cc52631SKirk McKusick inodirty(&curip);
1032280a49ecSJoerg Wunsch printactive(0);
1033d51bdf32SKirk McKusick return 0;
103439bb6d1eSPeter Wemm }
103539bb6d1eSPeter Wemm
CMDFUNCSTART(chsize)1036ac4b20a0SKirk McKusick CMDFUNCSTART(chsize)
1037ac4b20a0SKirk McKusick {
1038ac4b20a0SKirk McKusick off_t size;
1039ac4b20a0SKirk McKusick char *cp;
1040ac4b20a0SKirk McKusick
1041ac4b20a0SKirk McKusick if (!checkactive())
1042ac4b20a0SKirk McKusick return 1;
1043ac4b20a0SKirk McKusick
1044ac4b20a0SKirk McKusick size = strtoll(argv[1], &cp, 0);
1045ac4b20a0SKirk McKusick if (cp == argv[1] || *cp != '\0') {
1046ac4b20a0SKirk McKusick warnx("bad size `%s'", argv[1]);
1047ac4b20a0SKirk McKusick return 1;
1048ac4b20a0SKirk McKusick }
1049ac4b20a0SKirk McKusick
1050ac4b20a0SKirk McKusick if (size < 0) {
1051ac4b20a0SKirk McKusick warnx("size set to negative (%jd)\n", (intmax_t)size);
1052ac4b20a0SKirk McKusick return(1);
1053ac4b20a0SKirk McKusick }
1054ac4b20a0SKirk McKusick DIP_SET(curinode, di_size, size);
10555cc52631SKirk McKusick inodirty(&curip);
1056ac4b20a0SKirk McKusick printactive(0);
1057d51bdf32SKirk McKusick return 0;
1058ac4b20a0SKirk McKusick }
1059ac4b20a0SKirk McKusick
CMDFUNC(chdb)10607636973cSKirk McKusick CMDFUNC(chdb)
10617636973cSKirk McKusick {
10627636973cSKirk McKusick unsigned int idx;
10637636973cSKirk McKusick daddr_t bno;
10647636973cSKirk McKusick char *cp;
10657636973cSKirk McKusick
10667636973cSKirk McKusick if (!checkactive())
10677636973cSKirk McKusick return 1;
10687636973cSKirk McKusick
10697636973cSKirk McKusick idx = strtoull(argv[1], &cp, 0);
10707636973cSKirk McKusick if (cp == argv[1] || *cp != '\0') {
10717636973cSKirk McKusick warnx("bad pointer idx `%s'", argv[1]);
10727636973cSKirk McKusick return 1;
10737636973cSKirk McKusick }
10747636973cSKirk McKusick bno = strtoll(argv[2], &cp, 0);
10757636973cSKirk McKusick if (cp == argv[2] || *cp != '\0') {
10767636973cSKirk McKusick warnx("bad block number `%s'", argv[2]);
10777636973cSKirk McKusick return 1;
10787636973cSKirk McKusick }
10797636973cSKirk McKusick if (idx >= UFS_NDADDR) {
10807636973cSKirk McKusick warnx("pointer index %d is out of range", idx);
10817636973cSKirk McKusick return 1;
10827636973cSKirk McKusick }
10837636973cSKirk McKusick
10847636973cSKirk McKusick DIP_SET(curinode, di_db[idx], bno);
10857636973cSKirk McKusick inodirty(&curip);
10867636973cSKirk McKusick printactive(0);
10877636973cSKirk McKusick return 0;
10887636973cSKirk McKusick }
10897636973cSKirk McKusick
CMDFUNCSTART(linkcount)109039bb6d1eSPeter Wemm CMDFUNCSTART(linkcount)
109139bb6d1eSPeter Wemm {
109239bb6d1eSPeter Wemm int lcnt;
109339bb6d1eSPeter Wemm char *cp;
109439bb6d1eSPeter Wemm
109539bb6d1eSPeter Wemm if (!checkactive())
109639bb6d1eSPeter Wemm return 1;
109739bb6d1eSPeter Wemm
109839bb6d1eSPeter Wemm lcnt = strtol(argv[1], &cp, 0);
109939bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0' ) {
110039bb6d1eSPeter Wemm warnx("bad link count `%s'", argv[1]);
110139bb6d1eSPeter Wemm return 1;
110239bb6d1eSPeter Wemm }
110339bb6d1eSPeter Wemm if (lcnt > USHRT_MAX || lcnt < 0) {
110439bb6d1eSPeter Wemm warnx("max link count is %d\n", USHRT_MAX);
110539bb6d1eSPeter Wemm return 1;
110639bb6d1eSPeter Wemm }
110739bb6d1eSPeter Wemm
1108c9eaf226SLukas Ertl DIP_SET(curinode, di_nlink, lcnt);
11095cc52631SKirk McKusick inodirty(&curip);
1110280a49ecSJoerg Wunsch printactive(0);
1111d51bdf32SKirk McKusick return 0;
111239bb6d1eSPeter Wemm }
111339bb6d1eSPeter Wemm
CMDFUNCSTART(chowner)111439bb6d1eSPeter Wemm CMDFUNCSTART(chowner)
111539bb6d1eSPeter Wemm {
111639bb6d1eSPeter Wemm unsigned long uid;
111739bb6d1eSPeter Wemm char *cp;
111839bb6d1eSPeter Wemm struct passwd *pwd;
111939bb6d1eSPeter Wemm
112039bb6d1eSPeter Wemm if (!checkactive())
112139bb6d1eSPeter Wemm return 1;
112239bb6d1eSPeter Wemm
112339bb6d1eSPeter Wemm uid = strtoul(argv[1], &cp, 0);
112439bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0' ) {
112539bb6d1eSPeter Wemm /* try looking up name */
11260227048aSPhilippe Charnier if ((pwd = getpwnam(argv[1]))) {
112739bb6d1eSPeter Wemm uid = pwd->pw_uid;
112839bb6d1eSPeter Wemm } else {
112939bb6d1eSPeter Wemm warnx("bad uid `%s'", argv[1]);
113039bb6d1eSPeter Wemm return 1;
113139bb6d1eSPeter Wemm }
113239bb6d1eSPeter Wemm }
113339bb6d1eSPeter Wemm
1134c9eaf226SLukas Ertl DIP_SET(curinode, di_uid, uid);
11355cc52631SKirk McKusick inodirty(&curip);
1136280a49ecSJoerg Wunsch printactive(0);
1137d51bdf32SKirk McKusick return 0;
113839bb6d1eSPeter Wemm }
113939bb6d1eSPeter Wemm
CMDFUNCSTART(chgroup)114039bb6d1eSPeter Wemm CMDFUNCSTART(chgroup)
114139bb6d1eSPeter Wemm {
114239bb6d1eSPeter Wemm unsigned long gid;
114339bb6d1eSPeter Wemm char *cp;
114439bb6d1eSPeter Wemm struct group *grp;
114539bb6d1eSPeter Wemm
114639bb6d1eSPeter Wemm if (!checkactive())
114739bb6d1eSPeter Wemm return 1;
114839bb6d1eSPeter Wemm
114939bb6d1eSPeter Wemm gid = strtoul(argv[1], &cp, 0);
115039bb6d1eSPeter Wemm if (cp == argv[1] || *cp != '\0' ) {
11510227048aSPhilippe Charnier if ((grp = getgrnam(argv[1]))) {
115239bb6d1eSPeter Wemm gid = grp->gr_gid;
115339bb6d1eSPeter Wemm } else {
115439bb6d1eSPeter Wemm warnx("bad gid `%s'", argv[1]);
115539bb6d1eSPeter Wemm return 1;
115639bb6d1eSPeter Wemm }
115739bb6d1eSPeter Wemm }
115839bb6d1eSPeter Wemm
1159c9eaf226SLukas Ertl DIP_SET(curinode, di_gid, gid);
11605cc52631SKirk McKusick inodirty(&curip);
1161280a49ecSJoerg Wunsch printactive(0);
1162d51bdf32SKirk McKusick return 0;
116339bb6d1eSPeter Wemm }
116439bb6d1eSPeter Wemm
116539bb6d1eSPeter Wemm int
dotime(char * name,time_t * secp,int32_t * nsecp)11661c85e6a3SKirk McKusick dotime(char *name, time_t *secp, int32_t *nsecp)
116739bb6d1eSPeter Wemm {
116839bb6d1eSPeter Wemm char *p, *val;
116939bb6d1eSPeter Wemm struct tm t;
117039bb6d1eSPeter Wemm int32_t nsec;
117139bb6d1eSPeter Wemm p = strchr(name, '.');
117239bb6d1eSPeter Wemm if (p) {
117339bb6d1eSPeter Wemm *p = '\0';
117439bb6d1eSPeter Wemm nsec = strtoul(++p, &val, 0);
117539bb6d1eSPeter Wemm if (val == p || *val != '\0' || nsec >= 1000000000 || nsec < 0) {
117639bb6d1eSPeter Wemm warnx("invalid nanoseconds");
117739bb6d1eSPeter Wemm goto badformat;
117839bb6d1eSPeter Wemm }
117939bb6d1eSPeter Wemm } else
118039bb6d1eSPeter Wemm nsec = 0;
118139bb6d1eSPeter Wemm if (strlen(name) != 14) {
118239bb6d1eSPeter Wemm badformat:
118339bb6d1eSPeter Wemm warnx("date format: YYYYMMDDHHMMSS[.nsec]");
118439bb6d1eSPeter Wemm return 1;
118539bb6d1eSPeter Wemm }
11861c85e6a3SKirk McKusick *nsecp = nsec;
118739bb6d1eSPeter Wemm
118839bb6d1eSPeter Wemm for (p = name; *p; p++)
118939bb6d1eSPeter Wemm if (*p < '0' || *p > '9')
119039bb6d1eSPeter Wemm goto badformat;
119139bb6d1eSPeter Wemm
119239bb6d1eSPeter Wemm p = name;
119339bb6d1eSPeter Wemm #define VAL() ((*p++) - '0')
119439bb6d1eSPeter Wemm t.tm_year = VAL();
119539bb6d1eSPeter Wemm t.tm_year = VAL() + t.tm_year * 10;
119639bb6d1eSPeter Wemm t.tm_year = VAL() + t.tm_year * 10;
119739bb6d1eSPeter Wemm t.tm_year = VAL() + t.tm_year * 10 - 1900;
119839bb6d1eSPeter Wemm t.tm_mon = VAL();
119939bb6d1eSPeter Wemm t.tm_mon = VAL() + t.tm_mon * 10 - 1;
120039bb6d1eSPeter Wemm t.tm_mday = VAL();
120139bb6d1eSPeter Wemm t.tm_mday = VAL() + t.tm_mday * 10;
120239bb6d1eSPeter Wemm t.tm_hour = VAL();
120339bb6d1eSPeter Wemm t.tm_hour = VAL() + t.tm_hour * 10;
120439bb6d1eSPeter Wemm t.tm_min = VAL();
120539bb6d1eSPeter Wemm t.tm_min = VAL() + t.tm_min * 10;
120639bb6d1eSPeter Wemm t.tm_sec = VAL();
120739bb6d1eSPeter Wemm t.tm_sec = VAL() + t.tm_sec * 10;
120839bb6d1eSPeter Wemm t.tm_isdst = -1;
120939bb6d1eSPeter Wemm
12101c85e6a3SKirk McKusick *secp = mktime(&t);
12111c85e6a3SKirk McKusick if (*secp == -1) {
121239bb6d1eSPeter Wemm warnx("date/time out of range");
121339bb6d1eSPeter Wemm return 1;
121439bb6d1eSPeter Wemm }
121539bb6d1eSPeter Wemm return 0;
121639bb6d1eSPeter Wemm }
121739bb6d1eSPeter Wemm
CMDFUNCSTART(chbtime)121896dd6360SCeri Davies CMDFUNCSTART(chbtime)
121996dd6360SCeri Davies {
122096dd6360SCeri Davies time_t secs;
122196dd6360SCeri Davies int32_t nsecs;
122296dd6360SCeri Davies
122396dd6360SCeri Davies if (dotime(argv[1], &secs, &nsecs))
122496dd6360SCeri Davies return 1;
122596dd6360SCeri Davies if (sblock.fs_magic == FS_UFS1_MAGIC)
122696dd6360SCeri Davies return 1;
122796dd6360SCeri Davies curinode->dp2.di_birthtime = _time_to_time64(secs);
122896dd6360SCeri Davies curinode->dp2.di_birthnsec = nsecs;
12295cc52631SKirk McKusick inodirty(&curip);
123096dd6360SCeri Davies printactive(0);
123196dd6360SCeri Davies return 0;
123296dd6360SCeri Davies }
123396dd6360SCeri Davies
CMDFUNCSTART(chmtime)123439bb6d1eSPeter Wemm CMDFUNCSTART(chmtime)
123539bb6d1eSPeter Wemm {
12361c85e6a3SKirk McKusick time_t secs;
12371c85e6a3SKirk McKusick int32_t nsecs;
12381c85e6a3SKirk McKusick
12391c85e6a3SKirk McKusick if (dotime(argv[1], &secs, &nsecs))
124039bb6d1eSPeter Wemm return 1;
12411c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
12421c85e6a3SKirk McKusick curinode->dp1.di_mtime = _time_to_time32(secs);
12431c85e6a3SKirk McKusick else
12441c85e6a3SKirk McKusick curinode->dp2.di_mtime = _time_to_time64(secs);
1245c9eaf226SLukas Ertl DIP_SET(curinode, di_mtimensec, nsecs);
12465cc52631SKirk McKusick inodirty(&curip);
1247280a49ecSJoerg Wunsch printactive(0);
124839bb6d1eSPeter Wemm return 0;
124939bb6d1eSPeter Wemm }
125039bb6d1eSPeter Wemm
CMDFUNCSTART(chatime)125139bb6d1eSPeter Wemm CMDFUNCSTART(chatime)
125239bb6d1eSPeter Wemm {
12531c85e6a3SKirk McKusick time_t secs;
12541c85e6a3SKirk McKusick int32_t nsecs;
12551c85e6a3SKirk McKusick
12561c85e6a3SKirk McKusick if (dotime(argv[1], &secs, &nsecs))
125739bb6d1eSPeter Wemm return 1;
12581c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
12591c85e6a3SKirk McKusick curinode->dp1.di_atime = _time_to_time32(secs);
12601c85e6a3SKirk McKusick else
12611c85e6a3SKirk McKusick curinode->dp2.di_atime = _time_to_time64(secs);
1262c9eaf226SLukas Ertl DIP_SET(curinode, di_atimensec, nsecs);
12635cc52631SKirk McKusick inodirty(&curip);
1264280a49ecSJoerg Wunsch printactive(0);
126539bb6d1eSPeter Wemm return 0;
126639bb6d1eSPeter Wemm }
126739bb6d1eSPeter Wemm
CMDFUNCSTART(chctime)126839bb6d1eSPeter Wemm CMDFUNCSTART(chctime)
126939bb6d1eSPeter Wemm {
12701c85e6a3SKirk McKusick time_t secs;
12711c85e6a3SKirk McKusick int32_t nsecs;
12721c85e6a3SKirk McKusick
12731c85e6a3SKirk McKusick if (dotime(argv[1], &secs, &nsecs))
127439bb6d1eSPeter Wemm return 1;
12751c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
12761c85e6a3SKirk McKusick curinode->dp1.di_ctime = _time_to_time32(secs);
12771c85e6a3SKirk McKusick else
12781c85e6a3SKirk McKusick curinode->dp2.di_ctime = _time_to_time64(secs);
1279c9eaf226SLukas Ertl DIP_SET(curinode, di_ctimensec, nsecs);
12805cc52631SKirk McKusick inodirty(&curip);
1281280a49ecSJoerg Wunsch printactive(0);
128239bb6d1eSPeter Wemm return 0;
128339bb6d1eSPeter Wemm }
1284