1*da5362d5Sguenther /* $OpenBSD: fsdb.c,v 1.36 2024/01/09 03:16:00 guenther Exp $ */
200829d25Smillert /* $NetBSD: fsdb.c,v 1.7 1997/01/11 06:50:53 lukem Exp $ */
3df930be7Sderaadt
4be0fe854Sniklas /*-
5be0fe854Sniklas * Copyright (c) 1996 The NetBSD Foundation, Inc.
6df930be7Sderaadt * All rights reserved.
7df930be7Sderaadt *
8be0fe854Sniklas * This code is derived from software contributed to The NetBSD Foundation
9be0fe854Sniklas * by John T. Kohl.
10be0fe854Sniklas *
11df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt * modification, are permitted provided that the following conditions
13df930be7Sderaadt * are met:
14df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt * documentation and/or other materials provided with the distribution.
19df930be7Sderaadt *
20be0fe854Sniklas * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21be0fe854Sniklas * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22be0fe854Sniklas * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23be0fe854Sniklas * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
24be0fe854Sniklas * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25be0fe854Sniklas * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26be0fe854Sniklas * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27be0fe854Sniklas * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28be0fe854Sniklas * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29be0fe854Sniklas * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30df930be7Sderaadt * POSSIBILITY OF SUCH DAMAGE.
31df930be7Sderaadt */
32df930be7Sderaadt
33df930be7Sderaadt #include <sys/stat.h>
34df930be7Sderaadt #include <sys/time.h>
35df930be7Sderaadt #include <sys/mount.h>
36df930be7Sderaadt #include <ctype.h>
3700829d25Smillert #include <err.h>
38df930be7Sderaadt #include <fcntl.h>
39df930be7Sderaadt #include <grp.h>
40df930be7Sderaadt #include <histedit.h>
41df930be7Sderaadt #include <limits.h>
42df930be7Sderaadt #include <pwd.h>
43df930be7Sderaadt #include <stdio.h>
44df930be7Sderaadt #include <stdlib.h>
45df930be7Sderaadt #include <string.h>
46df930be7Sderaadt #include <unistd.h>
47df930be7Sderaadt
48df930be7Sderaadt #include <ufs/ufs/dinode.h>
49df930be7Sderaadt #include <ufs/ufs/dir.h>
50df930be7Sderaadt #include <ufs/ffs/fs.h>
51df930be7Sderaadt
52df930be7Sderaadt #include "fsdb.h"
53df930be7Sderaadt #include "fsck.h"
5400829d25Smillert #include "extern.h"
55df930be7Sderaadt
56df930be7Sderaadt extern char *__progname; /* from crt0.o */
57df930be7Sderaadt
58c72b5b24Smillert int main(int, char *[]);
59c72b5b24Smillert static void usage(void);
60c72b5b24Smillert static int cmdloop(void);
61c72b5b24Smillert static int helpfn(int, char *[]);
62c72b5b24Smillert static char *prompt(EditLine *);
63c72b5b24Smillert static int scannames(struct inodesc *);
64c72b5b24Smillert static int dolookup(char *);
65c72b5b24Smillert static int chinumfunc(struct inodesc *);
66c72b5b24Smillert static int chnamefunc(struct inodesc *);
67904f6f58Sotto static int dotime(char *, time_t *, int32_t *);
68df930be7Sderaadt
6900829d25Smillert int returntosingle = 0;
70c913562aSmillert union dinode *curinode;
7100829d25Smillert ino_t curinum;
7200829d25Smillert
730986c204Sderaadt struct inostatlist *inostathead;
740986c204Sderaadt
750986c204Sderaadt struct bufarea bufhead; /* head of list of other blks in filesys */
760986c204Sderaadt struct bufarea sblk; /* file system superblock */
770986c204Sderaadt struct bufarea asblk; /* alternate file system superblock */
780986c204Sderaadt struct bufarea *pdirbp; /* current directory contents */
790986c204Sderaadt struct bufarea *pbp; /* current inode block */
800986c204Sderaadt
810986c204Sderaadt struct dups *duplist; /* head of dup list */
820986c204Sderaadt struct dups *muldup; /* end of unique duplicate dup block numbers */
830986c204Sderaadt
840986c204Sderaadt struct zlncnt *zlnhead; /* head of zero link count list */
850986c204Sderaadt
860986c204Sderaadt struct inoinfo **inphead, **inpsort;
870986c204Sderaadt
880986c204Sderaadt extern long numdirs, listmax, inplast;
890986c204Sderaadt
900986c204Sderaadt long secsize; /* actual disk sector size */
910986c204Sderaadt char nflag; /* assume a no response */
920986c204Sderaadt char yflag; /* assume a yes response */
930986c204Sderaadt daddr_t bflag; /* location of alternate super block */
940986c204Sderaadt int debug; /* output debugging info */
950986c204Sderaadt int cvtlevel; /* convert to newer file system format */
960986c204Sderaadt char usedsoftdep; /* just fix soft dependency inconsistencies */
970986c204Sderaadt int preen; /* just fix normal inconsistencies */
980986c204Sderaadt char resolved; /* cleared if unresolved changes => not clean */
990986c204Sderaadt char havesb; /* superblock has been read */
1000986c204Sderaadt char skipclean; /* skip clean file systems if preening */
1010986c204Sderaadt int fsmodified; /* 1 => write done to file system */
1020986c204Sderaadt int fsreadfd; /* file descriptor for reading file system */
1030986c204Sderaadt int fswritefd; /* file descriptor for writing file system */
1040986c204Sderaadt int rerun; /* rerun fsck. Only used in non-preen mode */
1050986c204Sderaadt
1060986c204Sderaadt daddr_t maxfsblock; /* number of blocks in the file system */
1070986c204Sderaadt char *blockmap; /* ptr to primary blk allocation map */
1080986c204Sderaadt ino_t maxino; /* number of inodes in file system */
1090986c204Sderaadt ino_t lastino; /* last inode in use */
1100986c204Sderaadt
1110986c204Sderaadt ino_t lfdir; /* lost & found directory inode number */
1120986c204Sderaadt
1130986c204Sderaadt daddr_t n_blks; /* number of blocks in use */
1140986c204Sderaadt int64_t n_files; /* number of files in use */
1150986c204Sderaadt
1160986c204Sderaadt struct ufs1_dinode ufs1_zino;
1170986c204Sderaadt struct ufs2_dinode ufs2_zino;
1180986c204Sderaadt
1190986c204Sderaadt
12000829d25Smillert static void
usage(void)1218809fabbSderaadt usage(void)
122df930be7Sderaadt {
1233fd4512fSjmc fprintf(stderr, "usage: %s [-d] -f fsname\n", __progname);
124209724cbSalex exit(1);
125df930be7Sderaadt }
126df930be7Sderaadt
127df930be7Sderaadt /*
128df930be7Sderaadt * We suck in lots of fsck code, and just pick & choose the stuff we want.
129df930be7Sderaadt *
130df930be7Sderaadt * fsreadfd is set up to read from the file system, fswritefd to write to
131df930be7Sderaadt * the file system.
132df930be7Sderaadt */
133f3bae140Sderaadt int
main(int argc,char * argv[])1348809fabbSderaadt main(int argc, char *argv[])
135df930be7Sderaadt {
136df930be7Sderaadt int ch, rval;
137df930be7Sderaadt char *fsys = NULL;
138df930be7Sderaadt
139df930be7Sderaadt while (-1 != (ch = getopt(argc, argv, "f:d"))) {
140df930be7Sderaadt switch (ch) {
141df930be7Sderaadt case 'f':
142df930be7Sderaadt fsys = optarg;
143df930be7Sderaadt break;
144df930be7Sderaadt case 'd':
145df930be7Sderaadt debug++;
146df930be7Sderaadt break;
147df930be7Sderaadt default:
148df930be7Sderaadt usage();
149df930be7Sderaadt }
150df930be7Sderaadt }
151df930be7Sderaadt if (fsys == NULL)
152df930be7Sderaadt usage();
153f0bf880cStb if (!setup(fsys, 1))
154df930be7Sderaadt errx(1, "cannot set up file system `%s'", fsys);
155df930be7Sderaadt printf("Editing file system `%s'\nLast Mounted on %s\n", fsys,
156df930be7Sderaadt sblock.fs_fsmnt);
157df930be7Sderaadt rval = cmdloop();
158df930be7Sderaadt sblock.fs_clean = 0; /* mark it dirty */
159df930be7Sderaadt sbdirty();
160df930be7Sderaadt ckfini(0);
161df930be7Sderaadt printf("*** FILE SYSTEM MARKED DIRTY\n");
162df930be7Sderaadt printf("*** BE SURE TO RUN FSCK TO CLEAN UP ANY DAMAGE\n");
163df930be7Sderaadt printf("*** IF IT WAS MOUNTED, RE-MOUNT WITH -u -o reload\n");
164df930be7Sderaadt exit(rval);
165df930be7Sderaadt }
166df930be7Sderaadt
167c72b5b24Smillert #define CMDFUNC(func) static int func(int argc, char *argv[])
1688809fabbSderaadt #define CMDFUNCSTART(func) static int func(int argc, char *argv[])
169df930be7Sderaadt
170df930be7Sderaadt CMDFUNC(helpfn);
171df930be7Sderaadt CMDFUNC(focus); /* focus on inode */
172df930be7Sderaadt CMDFUNC(active); /* print active inode */
173df930be7Sderaadt CMDFUNC(focusname); /* focus by name */
174df930be7Sderaadt CMDFUNC(zapi); /* clear inode */
175df930be7Sderaadt CMDFUNC(uplink); /* incr link */
176df930be7Sderaadt CMDFUNC(downlink); /* decr link */
177df930be7Sderaadt CMDFUNC(linkcount); /* set link count */
178df930be7Sderaadt CMDFUNC(quit); /* quit */
179df930be7Sderaadt CMDFUNC(ls); /* list directory */
180df930be7Sderaadt CMDFUNC(rm); /* remove name */
181df930be7Sderaadt CMDFUNC(ln); /* add name */
182df930be7Sderaadt CMDFUNC(newtype); /* change type */
183df930be7Sderaadt CMDFUNC(chmode); /* change mode */
18400829d25Smillert CMDFUNC(chlen); /* change length */
185df930be7Sderaadt CMDFUNC(chaflags); /* change flags */
186df930be7Sderaadt CMDFUNC(chgen); /* change generation */
187df930be7Sderaadt CMDFUNC(chowner); /* change owner */
188df930be7Sderaadt CMDFUNC(chgroup); /* Change group */
189df930be7Sderaadt CMDFUNC(back); /* pop back to last ino */
190df930be7Sderaadt CMDFUNC(chmtime); /* Change mtime */
191df930be7Sderaadt CMDFUNC(chctime); /* Change ctime */
192df930be7Sderaadt CMDFUNC(chatime); /* Change atime */
193df930be7Sderaadt CMDFUNC(chinum); /* Change inode # of dirent */
194df930be7Sderaadt CMDFUNC(chname); /* Change dirname of dirent */
195df930be7Sderaadt
19600829d25Smillert static struct cmdtable cmds[] = {
197df930be7Sderaadt { "help", "Print out help", 1, 1, helpfn },
198df930be7Sderaadt { "?", "Print out help", 1, 1, helpfn },
199df930be7Sderaadt { "inode", "Set active inode to INUM", 2, 2, focus },
200df930be7Sderaadt { "clri", "Clear inode INUM", 2, 2, zapi },
201df930be7Sderaadt { "lookup", "Set active inode by looking up NAME", 2, 2, focusname },
202df930be7Sderaadt { "cd", "Set active inode by looking up NAME", 2, 2, focusname },
203df930be7Sderaadt { "back", "Go to previous active inode", 1, 1, back },
204df930be7Sderaadt { "active", "Print active inode", 1, 1, active },
205df930be7Sderaadt { "print", "Print active inode", 1, 1, active },
206df930be7Sderaadt { "uplink", "Increment link count", 1, 1, uplink },
207df930be7Sderaadt { "downlink", "Decrement link count", 1, 1, downlink },
208df930be7Sderaadt { "linkcount", "Set link count to COUNT", 2, 2, linkcount },
209df930be7Sderaadt { "ls", "List current inode as directory", 1, 1, ls },
210df930be7Sderaadt { "rm", "Remove NAME from current inode directory", 2, 2, rm },
211df930be7Sderaadt { "del", "Remove NAME from current inode directory", 2, 2, rm },
212df930be7Sderaadt { "ln", "Hardlink INO into current inode directory as NAME", 3, 3, ln },
213df930be7Sderaadt { "chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum },
214df930be7Sderaadt { "chname", "Change dir entry number INDEX to NAME", 3, 3, chname },
215df930be7Sderaadt { "chtype", "Change type of current inode to TYPE", 2, 2, newtype },
216df930be7Sderaadt { "chmod", "Change mode of current inode to MODE", 2, 2, chmode },
217df930be7Sderaadt { "chown", "Change owner of current inode to OWNER", 2, 2, chowner },
21800829d25Smillert { "chlen", "Change length of current inode to LENGTH", 2, 2, chlen },
219df930be7Sderaadt { "chgrp", "Change group of current inode to GROUP", 2, 2, chgroup },
220df930be7Sderaadt { "chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags },
221df930be7Sderaadt { "chgen", "Change generation number of current inode to GEN", 2, 2, chgen },
222df930be7Sderaadt { "mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime },
223df930be7Sderaadt { "ctime", "Change ctime of current inode to CTIME", 2, 2, chctime },
224df930be7Sderaadt { "atime", "Change atime of current inode to ATIME", 2, 2, chatime },
225df930be7Sderaadt { "quit", "Exit", 1, 1, quit },
226df930be7Sderaadt { "q", "Exit", 1, 1, quit },
227df930be7Sderaadt { "exit", "Exit", 1, 1, quit },
228df930be7Sderaadt { NULL, 0, 0, 0 },
229df930be7Sderaadt };
230df930be7Sderaadt
23100829d25Smillert static int
helpfn(int argc,char * argv[])2328809fabbSderaadt helpfn(int argc, char *argv[])
233df930be7Sderaadt {
234e073c79dSmpech struct cmdtable *cmdtp;
235df930be7Sderaadt
236df930be7Sderaadt printf("Commands are:\n%-10s %5s %5s %s\n",
237df930be7Sderaadt "command", "min argc", "max argc", "what");
238df930be7Sderaadt
239df930be7Sderaadt for (cmdtp = cmds; cmdtp->cmd; cmdtp++)
240df930be7Sderaadt printf("%-10s %5u %5u %s\n",
241df930be7Sderaadt cmdtp->cmd, cmdtp->minargc, cmdtp->maxargc, cmdtp->helptxt);
242df930be7Sderaadt return 0;
243df930be7Sderaadt }
244df930be7Sderaadt
24500829d25Smillert static char *
prompt(EditLine * el)2468809fabbSderaadt prompt(EditLine *el)
247df930be7Sderaadt {
248df930be7Sderaadt static char pstring[64];
2498809fabbSderaadt
2503b92bd08Sderaadt snprintf(pstring, sizeof(pstring), "fsdb (inum: %llu)> ",
2513b92bd08Sderaadt (unsigned long long)curinum);
252df930be7Sderaadt return pstring;
253df930be7Sderaadt }
254df930be7Sderaadt
255df930be7Sderaadt
25600829d25Smillert static int
cmdloop(void)2578809fabbSderaadt cmdloop(void)
258df930be7Sderaadt {
25900829d25Smillert char *line = NULL;
260df930be7Sderaadt const char *elline;
261df930be7Sderaadt int cmd_argc, rval = 0, known;
262df930be7Sderaadt #define scratch known
263df930be7Sderaadt char **cmd_argv;
264df930be7Sderaadt struct cmdtable *cmdp;
265df930be7Sderaadt History *hist;
266df930be7Sderaadt EditLine *elptr;
2678b59c5f0Sotto HistEvent hev;
268df930be7Sderaadt
269df930be7Sderaadt curinode = ginode(ROOTINO);
270df930be7Sderaadt curinum = ROOTINO;
271df930be7Sderaadt printactive();
272df930be7Sderaadt
273df930be7Sderaadt hist = history_init();
2748b59c5f0Sotto history(hist, &hev, H_SETSIZE, 100); /* 100 elt history buffer */
275df930be7Sderaadt
2768b59c5f0Sotto elptr = el_init(__progname, stdin, stdout, stderr);
277df930be7Sderaadt el_set(elptr, EL_EDITOR, "emacs");
278df930be7Sderaadt el_set(elptr, EL_PROMPT, prompt);
279df930be7Sderaadt el_set(elptr, EL_HIST, history, hist);
280df930be7Sderaadt el_source(elptr, NULL);
281df930be7Sderaadt
282df930be7Sderaadt while ((elline = el_gets(elptr, &scratch)) != NULL && scratch != 0) {
283df930be7Sderaadt if (debug)
284aed4bff2Sjsg printf("command `%s'\n", elline);
285df930be7Sderaadt
2868b59c5f0Sotto history(hist, &hev, H_ENTER, elline);
287df930be7Sderaadt
288df930be7Sderaadt line = strdup(elline);
289ca198d9fSderaadt if (line == NULL)
290ca198d9fSderaadt errx(1, "out of memory");
291df930be7Sderaadt cmd_argv = crack(line, &cmd_argc);
29200829d25Smillert if (cmd_argc) {
293df930be7Sderaadt /*
294df930be7Sderaadt * el_parse returns -1 to signal that it's not been handled
295df930be7Sderaadt * internally.
296df930be7Sderaadt */
2978b59c5f0Sotto if (el_parse(elptr, cmd_argc, (const char **)cmd_argv) != -1)
298df930be7Sderaadt continue;
299df930be7Sderaadt known = 0;
300df930be7Sderaadt for (cmdp = cmds; cmdp->cmd; cmdp++) {
301df930be7Sderaadt if (!strcmp(cmdp->cmd, cmd_argv[0])) {
302df930be7Sderaadt if (cmd_argc >= cmdp->minargc &&
303df930be7Sderaadt cmd_argc <= cmdp->maxargc)
3048809fabbSderaadt rval = (*cmdp->handler)(cmd_argc,
3058809fabbSderaadt cmd_argv);
306df930be7Sderaadt else
3078809fabbSderaadt rval = argcount(cmdp,
3088809fabbSderaadt cmd_argc, cmd_argv);
309df930be7Sderaadt known = 1;
310df930be7Sderaadt break;
311df930be7Sderaadt }
312df930be7Sderaadt }
3138809fabbSderaadt if (!known) {
3148809fabbSderaadt warnx("unknown command `%s'", cmd_argv[0]);
3158809fabbSderaadt rval = 1;
3168809fabbSderaadt }
317df930be7Sderaadt } else
318df930be7Sderaadt rval = 0;
319df930be7Sderaadt free(line);
320df930be7Sderaadt if (rval < 0)
321df930be7Sderaadt return rval;
322df930be7Sderaadt if (rval)
323df930be7Sderaadt warnx("rval was %d", rval);
324df930be7Sderaadt }
325df930be7Sderaadt el_end(elptr);
326df930be7Sderaadt history_end(hist);
327df930be7Sderaadt return rval;
328df930be7Sderaadt }
329df930be7Sderaadt
33000829d25Smillert static ino_t ocurrent;
331df930be7Sderaadt
332520eb379Sotto #define GETINUM(ac,inum) inum = strtoull(argv[ac], &cp, 0); \
333df930be7Sderaadt if (inum < ROOTINO || inum > maxino || cp == argv[ac] || *cp != '\0' ) { \
334520eb379Sotto printf("inode %llu out of range; range is [%llu,%llu]\n", \
335520eb379Sotto (unsigned long long)inum, (unsigned long long)ROOTINO, \
336520eb379Sotto (unsigned long long)maxino); \
337df930be7Sderaadt return 1; \
338df930be7Sderaadt }
339df930be7Sderaadt
340df930be7Sderaadt /*
341df930be7Sderaadt * Focus on given inode number
342df930be7Sderaadt */
CMDFUNCSTART(focus)343df930be7Sderaadt CMDFUNCSTART(focus)
344df930be7Sderaadt {
345df930be7Sderaadt ino_t inum;
346df930be7Sderaadt char *cp;
347df930be7Sderaadt
348df930be7Sderaadt GETINUM(1,inum);
349df930be7Sderaadt curinode = ginode(inum);
350df930be7Sderaadt ocurrent = curinum;
351df930be7Sderaadt curinum = inum;
352df930be7Sderaadt printactive();
353df930be7Sderaadt return 0;
354df930be7Sderaadt }
355df930be7Sderaadt
CMDFUNCSTART(back)356df930be7Sderaadt CMDFUNCSTART(back)
357df930be7Sderaadt {
358df930be7Sderaadt curinum = ocurrent;
359df930be7Sderaadt curinode = ginode(curinum);
360df930be7Sderaadt printactive();
361df930be7Sderaadt return 0;
362df930be7Sderaadt }
363df930be7Sderaadt
CMDFUNCSTART(zapi)364df930be7Sderaadt CMDFUNCSTART(zapi)
365df930be7Sderaadt {
366df930be7Sderaadt ino_t inum;
367c913562aSmillert union dinode *dp;
368df930be7Sderaadt char *cp;
369df930be7Sderaadt
370df930be7Sderaadt GETINUM(1,inum);
371df930be7Sderaadt dp = ginode(inum);
372df930be7Sderaadt clearinode(dp);
373df930be7Sderaadt inodirty();
374df930be7Sderaadt if (curinode) /* re-set after potential change */
375df930be7Sderaadt curinode = ginode(curinum);
376df930be7Sderaadt return 0;
377df930be7Sderaadt }
378df930be7Sderaadt
CMDFUNCSTART(active)379df930be7Sderaadt CMDFUNCSTART(active)
380df930be7Sderaadt {
381df930be7Sderaadt printactive();
382df930be7Sderaadt return 0;
383df930be7Sderaadt }
384df930be7Sderaadt
385df930be7Sderaadt
CMDFUNCSTART(quit)386df930be7Sderaadt CMDFUNCSTART(quit)
387df930be7Sderaadt {
388df930be7Sderaadt return -1;
389df930be7Sderaadt }
390df930be7Sderaadt
CMDFUNCSTART(uplink)391df930be7Sderaadt CMDFUNCSTART(uplink)
392df930be7Sderaadt {
393df930be7Sderaadt if (!checkactive())
394df930be7Sderaadt return 1;
395c913562aSmillert DIP_SET(curinode, di_nlink, DIP(curinode, di_nlink) + 1);
3963b92bd08Sderaadt printf("inode %llu link count now %d\n",
3973b92bd08Sderaadt (unsigned long long)curinum, DIP(curinode, di_nlink));
398df930be7Sderaadt inodirty();
399df930be7Sderaadt return 0;
400df930be7Sderaadt }
401df930be7Sderaadt
CMDFUNCSTART(downlink)402df930be7Sderaadt CMDFUNCSTART(downlink)
403df930be7Sderaadt {
404df930be7Sderaadt if (!checkactive())
405df930be7Sderaadt return 1;
406c913562aSmillert DIP_SET(curinode, di_nlink, DIP(curinode, di_nlink) - 1);
4073b92bd08Sderaadt printf("inode %llu link count now %d\n",
4083b92bd08Sderaadt (unsigned long long)curinum, DIP(curinode, di_nlink));
409df930be7Sderaadt inodirty();
410df930be7Sderaadt return 0;
411df930be7Sderaadt }
412df930be7Sderaadt
41300829d25Smillert static const char *typename[] = {
414df930be7Sderaadt "unknown",
415df930be7Sderaadt "fifo",
416df930be7Sderaadt "char special",
417df930be7Sderaadt "unregistered #3",
418df930be7Sderaadt "directory",
419df930be7Sderaadt "unregistered #5",
420df930be7Sderaadt "blk special",
421df930be7Sderaadt "unregistered #7",
422df930be7Sderaadt "regular",
423df930be7Sderaadt "unregistered #9",
424df930be7Sderaadt "symlink",
425df930be7Sderaadt "unregistered #11",
426df930be7Sderaadt "socket",
427df930be7Sderaadt "unregistered #13",
428df930be7Sderaadt "whiteout",
429df930be7Sderaadt };
430df930be7Sderaadt
43100829d25Smillert static int slot;
432df930be7Sderaadt
43300829d25Smillert static int
scannames(struct inodesc * idesc)4348809fabbSderaadt scannames(struct inodesc *idesc)
435df930be7Sderaadt {
436e073c79dSmpech struct direct *dirp = idesc->id_dirp;
437df930be7Sderaadt
4383b92bd08Sderaadt printf("slot %d ino %llu reclen %d: %s, `%.*s'\n",
4393b92bd08Sderaadt slot++, (unsigned long long)dirp->d_ino, dirp->d_reclen,
4403b92bd08Sderaadt typename[dirp->d_type], dirp->d_namlen, dirp->d_name);
441df930be7Sderaadt return (KEEPON);
442df930be7Sderaadt }
443df930be7Sderaadt
CMDFUNCSTART(ls)444df930be7Sderaadt CMDFUNCSTART(ls)
445df930be7Sderaadt {
446df930be7Sderaadt struct inodesc idesc;
447df930be7Sderaadt checkactivedir(); /* let it go on anyway */
448df930be7Sderaadt
449df930be7Sderaadt slot = 0;
450df930be7Sderaadt idesc.id_number = curinum;
451df930be7Sderaadt idesc.id_func = scannames;
452df930be7Sderaadt idesc.id_type = DATA;
453df930be7Sderaadt idesc.id_fix = IGNORE;
454df930be7Sderaadt ckinode(curinode, &idesc);
455df930be7Sderaadt curinode = ginode(curinum);
456df930be7Sderaadt
457df930be7Sderaadt return 0;
458df930be7Sderaadt }
459df930be7Sderaadt
460df930be7Sderaadt static int
dolookup(char * name)4618809fabbSderaadt dolookup(char *name)
462df930be7Sderaadt {
463df930be7Sderaadt struct inodesc idesc;
464df930be7Sderaadt
465df930be7Sderaadt if (!checkactivedir())
466df930be7Sderaadt return 0;
467df930be7Sderaadt idesc.id_number = curinum;
468df930be7Sderaadt idesc.id_func = findino;
469df930be7Sderaadt idesc.id_name = name;
470df930be7Sderaadt idesc.id_type = DATA;
471df930be7Sderaadt idesc.id_fix = IGNORE;
472df930be7Sderaadt if (ckinode(curinode, &idesc) & FOUND) {
473df930be7Sderaadt curinum = idesc.id_parent;
474df930be7Sderaadt curinode = ginode(curinum);
475df930be7Sderaadt printactive();
476df930be7Sderaadt return 1;
477df930be7Sderaadt } else {
478df930be7Sderaadt warnx("name `%s' not found in current inode directory", name);
479df930be7Sderaadt return 0;
480df930be7Sderaadt }
481df930be7Sderaadt }
482df930be7Sderaadt
CMDFUNCSTART(focusname)483df930be7Sderaadt CMDFUNCSTART(focusname)
484df930be7Sderaadt {
485df930be7Sderaadt char *p, *val;
486df930be7Sderaadt
487df930be7Sderaadt if (!checkactive())
488df930be7Sderaadt return 1;
489df930be7Sderaadt
490df930be7Sderaadt ocurrent = curinum;
491df930be7Sderaadt
492df930be7Sderaadt if (argv[1][0] == '/') {
493df930be7Sderaadt curinum = ROOTINO;
494df930be7Sderaadt curinode = ginode(ROOTINO);
495df930be7Sderaadt } else {
496df930be7Sderaadt if (!checkactivedir())
497df930be7Sderaadt return 1;
498df930be7Sderaadt }
499df930be7Sderaadt for (p = argv[1]; p != NULL;) {
5001a14b407Saaron while ((val = strsep(&p, "/")) != NULL && *val == '\0')
501252fb110Stedu continue;
502df930be7Sderaadt if (val) {
503df930be7Sderaadt printf("component `%s': ", val);
504df930be7Sderaadt fflush(stdout);
505df930be7Sderaadt if (!dolookup(val)) {
506df930be7Sderaadt curinode = ginode(curinum);
507df930be7Sderaadt return(1);
508df930be7Sderaadt }
509df930be7Sderaadt }
510df930be7Sderaadt }
511df930be7Sderaadt return 0;
512df930be7Sderaadt }
513df930be7Sderaadt
CMDFUNCSTART(ln)514df930be7Sderaadt CMDFUNCSTART(ln)
515df930be7Sderaadt {
516df930be7Sderaadt ino_t inum;
517df930be7Sderaadt int rval;
518df930be7Sderaadt char *cp;
519df930be7Sderaadt
520df930be7Sderaadt GETINUM(1,inum);
521df930be7Sderaadt
522df930be7Sderaadt if (!checkactivedir())
523df930be7Sderaadt return 1;
524df930be7Sderaadt rval = makeentry(curinum, inum, argv[2]);
525df930be7Sderaadt if (rval)
5263b92bd08Sderaadt printf("Ino %llu entered as `%s'\n",
5273b92bd08Sderaadt (unsigned long long)inum, argv[2]);
528df930be7Sderaadt else
529df930be7Sderaadt printf("could not enter name? weird.\n");
530df930be7Sderaadt curinode = ginode(curinum);
531df930be7Sderaadt return rval;
532df930be7Sderaadt }
533df930be7Sderaadt
CMDFUNCSTART(rm)534df930be7Sderaadt CMDFUNCSTART(rm)
535df930be7Sderaadt {
536df930be7Sderaadt int rval;
537df930be7Sderaadt
538df930be7Sderaadt if (!checkactivedir())
539df930be7Sderaadt return 1;
540df930be7Sderaadt rval = changeino(curinum, argv[1], 0);
541df930be7Sderaadt if (rval & ALTERED) {
542df930be7Sderaadt printf("Name `%s' removed\n", argv[1]);
543df930be7Sderaadt return 0;
544df930be7Sderaadt } else {
545df930be7Sderaadt printf("could not remove name? weird.\n");
546df930be7Sderaadt return 1;
547df930be7Sderaadt }
548df930be7Sderaadt }
549df930be7Sderaadt
55000829d25Smillert static long slotcount, desired;
551df930be7Sderaadt
55200829d25Smillert static int
chinumfunc(struct inodesc * idesc)5538809fabbSderaadt chinumfunc(struct inodesc *idesc)
554df930be7Sderaadt {
555e073c79dSmpech struct direct *dirp = idesc->id_dirp;
556df930be7Sderaadt
557df930be7Sderaadt if (slotcount++ == desired) {
558df930be7Sderaadt dirp->d_ino = idesc->id_parent;
559df930be7Sderaadt return STOP|ALTERED|FOUND;
560df930be7Sderaadt }
561df930be7Sderaadt return KEEPON;
562df930be7Sderaadt }
563df930be7Sderaadt
CMDFUNCSTART(chinum)564df930be7Sderaadt CMDFUNCSTART(chinum)
565df930be7Sderaadt {
566df930be7Sderaadt char *cp;
567df930be7Sderaadt ino_t inum;
568df930be7Sderaadt struct inodesc idesc;
569df930be7Sderaadt
570df930be7Sderaadt slotcount = 0;
571df930be7Sderaadt if (!checkactivedir())
572df930be7Sderaadt return 1;
573df930be7Sderaadt GETINUM(2,inum);
574df930be7Sderaadt
575df930be7Sderaadt desired = strtol(argv[1], &cp, 0);
576df930be7Sderaadt if (cp == argv[1] || *cp != '\0' || desired < 0) {
577df930be7Sderaadt printf("invalid slot number `%s'\n", argv[1]);
578df930be7Sderaadt return 1;
579df930be7Sderaadt }
580df930be7Sderaadt
581df930be7Sderaadt idesc.id_number = curinum;
582df930be7Sderaadt idesc.id_func = chinumfunc;
583df930be7Sderaadt idesc.id_fix = IGNORE;
584df930be7Sderaadt idesc.id_type = DATA;
585df930be7Sderaadt idesc.id_parent = inum; /* XXX convenient hiding place */
586df930be7Sderaadt
587df930be7Sderaadt if (ckinode(curinode, &idesc) & FOUND)
588df930be7Sderaadt return 0;
589df930be7Sderaadt else {
590df930be7Sderaadt warnx("no %sth slot in current directory", argv[1]);
591df930be7Sderaadt return 1;
592df930be7Sderaadt }
593df930be7Sderaadt }
594df930be7Sderaadt
59500829d25Smillert static int
chnamefunc(struct inodesc * idesc)5968809fabbSderaadt chnamefunc(struct inodesc *idesc)
597df930be7Sderaadt {
598e073c79dSmpech struct direct *dirp = idesc->id_dirp;
599df930be7Sderaadt struct direct testdir;
600df930be7Sderaadt
601df930be7Sderaadt if (slotcount++ == desired) {
602df930be7Sderaadt /* will name fit? */
603df930be7Sderaadt testdir.d_namlen = strlen(idesc->id_name);
604*da5362d5Sguenther if (DIRSIZ(&testdir) <= dirp->d_reclen) {
605df930be7Sderaadt dirp->d_namlen = testdir.d_namlen;
6069bf6056aSderaadt strlcpy(dirp->d_name, idesc->id_name, sizeof dirp->d_name);
607df930be7Sderaadt return STOP|ALTERED|FOUND;
608df930be7Sderaadt } else
609df930be7Sderaadt return STOP|FOUND; /* won't fit, so give up */
610df930be7Sderaadt }
611df930be7Sderaadt return KEEPON;
612df930be7Sderaadt }
613df930be7Sderaadt
CMDFUNCSTART(chname)614df930be7Sderaadt CMDFUNCSTART(chname)
615df930be7Sderaadt {
616df930be7Sderaadt int rval;
617df930be7Sderaadt char *cp;
618df930be7Sderaadt struct inodesc idesc;
619df930be7Sderaadt
620df930be7Sderaadt slotcount = 0;
621df930be7Sderaadt if (!checkactivedir())
622df930be7Sderaadt return 1;
623df930be7Sderaadt
624df930be7Sderaadt desired = strtoul(argv[1], &cp, 0);
625df930be7Sderaadt if (cp == argv[1] || *cp != '\0') {
626df930be7Sderaadt printf("invalid slot number `%s'\n", argv[1]);
627df930be7Sderaadt return 1;
628df930be7Sderaadt }
629df930be7Sderaadt
630df930be7Sderaadt idesc.id_number = curinum;
631df930be7Sderaadt idesc.id_func = chnamefunc;
632df930be7Sderaadt idesc.id_fix = IGNORE;
633df930be7Sderaadt idesc.id_type = DATA;
634df930be7Sderaadt idesc.id_name = argv[2];
635df930be7Sderaadt
636df930be7Sderaadt rval = ckinode(curinode, &idesc);
637df930be7Sderaadt if ((rval & (FOUND|ALTERED)) == (FOUND|ALTERED))
638df930be7Sderaadt return 0;
639df930be7Sderaadt else if (rval & FOUND) {
64046347781Smpech warnx("new name `%s' does not fit in slot %s", argv[2], argv[1]);
641df930be7Sderaadt return 1;
642df930be7Sderaadt } else {
643df930be7Sderaadt warnx("no %sth slot in current directory", argv[1]);
644df930be7Sderaadt return 1;
645df930be7Sderaadt }
646df930be7Sderaadt }
647df930be7Sderaadt
64800829d25Smillert static struct typemap {
649df930be7Sderaadt const char *typename;
650df930be7Sderaadt int typebits;
651df930be7Sderaadt } typenamemap[] = {
652df930be7Sderaadt {"file", IFREG},
653df930be7Sderaadt {"dir", IFDIR},
654df930be7Sderaadt {"socket", IFSOCK},
655df930be7Sderaadt {"fifo", IFIFO},
656df930be7Sderaadt };
657df930be7Sderaadt
CMDFUNCSTART(newtype)658df930be7Sderaadt CMDFUNCSTART(newtype)
659df930be7Sderaadt {
660df930be7Sderaadt int type;
661df930be7Sderaadt struct typemap *tp;
662df930be7Sderaadt
663df930be7Sderaadt if (!checkactive())
664df930be7Sderaadt return 1;
665c913562aSmillert type = DIP(curinode, di_mode) & IFMT;
666df930be7Sderaadt for (tp = typenamemap;
6673249b019Sotto tp < &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)];
668df930be7Sderaadt tp++) {
669df930be7Sderaadt if (!strcmp(argv[1], tp->typename)) {
670df930be7Sderaadt printf("setting type to %s\n", tp->typename);
671df930be7Sderaadt type = tp->typebits;
672df930be7Sderaadt break;
673df930be7Sderaadt }
674df930be7Sderaadt }
6753249b019Sotto if (tp == &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)]) {
676df930be7Sderaadt warnx("type `%s' not known", argv[1]);
677df930be7Sderaadt warnx("try one of `file', `dir', `socket', `fifo'");
678df930be7Sderaadt return 1;
679df930be7Sderaadt }
680c913562aSmillert DIP_SET(curinode, di_mode, DIP(curinode, di_mode) & ~IFMT);
681c913562aSmillert DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | type);
682df930be7Sderaadt inodirty();
683df930be7Sderaadt printactive();
684df930be7Sderaadt return 0;
685df930be7Sderaadt }
686df930be7Sderaadt
CMDFUNCSTART(chmode)687df930be7Sderaadt CMDFUNCSTART(chmode)
688df930be7Sderaadt {
689df930be7Sderaadt int rval = 1;
690df930be7Sderaadt long modebits;
691df930be7Sderaadt char *cp;
692df930be7Sderaadt
693df930be7Sderaadt if (!checkactive())
694df930be7Sderaadt return 1;
695df930be7Sderaadt
696df930be7Sderaadt modebits = strtol(argv[1], &cp, 8);
697df930be7Sderaadt if (cp == argv[1] || *cp != '\0' ) {
698df930be7Sderaadt warnx("bad modebits `%s'", argv[1]);
699df930be7Sderaadt return 1;
700df930be7Sderaadt }
701df930be7Sderaadt
702c913562aSmillert DIP_SET(curinode, di_mode, DIP(curinode, di_mode) & ~07777);
703c913562aSmillert DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | modebits);
704df930be7Sderaadt inodirty();
705df930be7Sderaadt printactive();
706df930be7Sderaadt return rval;
707df930be7Sderaadt }
708df930be7Sderaadt
CMDFUNCSTART(chlen)70900829d25Smillert CMDFUNCSTART(chlen)
71000829d25Smillert {
71100829d25Smillert int rval = 1;
71200829d25Smillert long len;
71300829d25Smillert char *cp;
71400829d25Smillert
71500829d25Smillert if (!checkactive())
71600829d25Smillert return 1;
71700829d25Smillert
71800829d25Smillert len = strtol(argv[1], &cp, 0);
71900829d25Smillert if (cp == argv[1] || *cp != '\0' || len < 0) {
72000829d25Smillert warnx("bad length '%s'", argv[1]);
72100829d25Smillert return 1;
72200829d25Smillert }
72300829d25Smillert
724c913562aSmillert DIP_SET(curinode, di_size, len);
72500829d25Smillert inodirty();
72600829d25Smillert printactive();
72700829d25Smillert return rval;
72800829d25Smillert }
72900829d25Smillert
CMDFUNCSTART(chaflags)730df930be7Sderaadt CMDFUNCSTART(chaflags)
731df930be7Sderaadt {
732df930be7Sderaadt int rval = 1;
733df930be7Sderaadt u_long flags;
734df930be7Sderaadt char *cp;
735df930be7Sderaadt
736df930be7Sderaadt if (!checkactive())
737df930be7Sderaadt return 1;
738df930be7Sderaadt
739df930be7Sderaadt flags = strtoul(argv[1], &cp, 0);
740df930be7Sderaadt if (cp == argv[1] || *cp != '\0' ) {
741df930be7Sderaadt warnx("bad flags `%s'", argv[1]);
742df930be7Sderaadt return 1;
743df930be7Sderaadt }
744df930be7Sderaadt
745df930be7Sderaadt if (flags > UINT_MAX) {
74646347781Smpech warnx("flags set beyond 32-bit range of field (%lx)", flags);
747df930be7Sderaadt return(1);
748df930be7Sderaadt }
749c913562aSmillert DIP_SET(curinode, di_flags, flags);
750df930be7Sderaadt inodirty();
751df930be7Sderaadt printactive();
752df930be7Sderaadt return rval;
753df930be7Sderaadt }
754df930be7Sderaadt
CMDFUNCSTART(chgen)755df930be7Sderaadt CMDFUNCSTART(chgen)
756df930be7Sderaadt {
757df930be7Sderaadt int rval = 1;
758d06c4e1fSotto long long gen;
759df930be7Sderaadt char *cp;
760df930be7Sderaadt
761df930be7Sderaadt if (!checkactive())
762df930be7Sderaadt return 1;
763df930be7Sderaadt
764d06c4e1fSotto gen = strtoll(argv[1], &cp, 0);
765df930be7Sderaadt if (cp == argv[1] || *cp != '\0' ) {
766df930be7Sderaadt warnx("bad gen `%s'", argv[1]);
767df930be7Sderaadt return 1;
768df930be7Sderaadt }
769df930be7Sderaadt
770d06c4e1fSotto if (gen > UINT_MAX || gen < 0) {
771d06c4e1fSotto warnx("gen set beyond 32-bit range of field (%llx)", gen);
772df930be7Sderaadt return(1);
773df930be7Sderaadt }
774c913562aSmillert DIP_SET(curinode, di_gen, gen);
775df930be7Sderaadt inodirty();
776df930be7Sderaadt printactive();
777df930be7Sderaadt return rval;
778df930be7Sderaadt }
779df930be7Sderaadt
CMDFUNCSTART(linkcount)780df930be7Sderaadt CMDFUNCSTART(linkcount)
781df930be7Sderaadt {
782df930be7Sderaadt int rval = 1;
783df930be7Sderaadt int lcnt;
784df930be7Sderaadt char *cp;
785df930be7Sderaadt
786df930be7Sderaadt if (!checkactive())
787df930be7Sderaadt return 1;
788df930be7Sderaadt
789df930be7Sderaadt lcnt = strtol(argv[1], &cp, 0);
790df930be7Sderaadt if (cp == argv[1] || *cp != '\0' ) {
791df930be7Sderaadt warnx("bad link count `%s'", argv[1]);
792df930be7Sderaadt return 1;
793df930be7Sderaadt }
794df930be7Sderaadt if (lcnt > USHRT_MAX || lcnt < 0) {
79546347781Smpech warnx("max link count is %d", USHRT_MAX);
796df930be7Sderaadt return 1;
797df930be7Sderaadt }
798df930be7Sderaadt
799c913562aSmillert DIP_SET(curinode, di_nlink, lcnt);
800df930be7Sderaadt inodirty();
801df930be7Sderaadt printactive();
802df930be7Sderaadt return rval;
803df930be7Sderaadt }
804df930be7Sderaadt
CMDFUNCSTART(chowner)805df930be7Sderaadt CMDFUNCSTART(chowner)
806df930be7Sderaadt {
807df930be7Sderaadt int rval = 1;
8087212eb4eSderaadt uid_t uid;
809df930be7Sderaadt char *cp;
810df930be7Sderaadt
811df930be7Sderaadt if (!checkactive())
812df930be7Sderaadt return 1;
813df930be7Sderaadt
814df930be7Sderaadt uid = strtoul(argv[1], &cp, 0);
815df930be7Sderaadt if (cp == argv[1] || *cp != '\0' ) {
816df930be7Sderaadt /* try looking up name */
817a0f924b8Smillert if (uid_from_user(argv[1], &uid) == -1) {
818df930be7Sderaadt warnx("bad uid `%s'", argv[1]);
819df930be7Sderaadt return 1;
820df930be7Sderaadt }
821df930be7Sderaadt }
822df930be7Sderaadt
823c913562aSmillert DIP_SET(curinode, di_uid, uid);
824df930be7Sderaadt inodirty();
825df930be7Sderaadt printactive();
826df930be7Sderaadt return rval;
827df930be7Sderaadt }
828df930be7Sderaadt
CMDFUNCSTART(chgroup)829df930be7Sderaadt CMDFUNCSTART(chgroup)
830df930be7Sderaadt {
831df930be7Sderaadt int rval = 1;
8327212eb4eSderaadt gid_t gid;
833df930be7Sderaadt char *cp;
834df930be7Sderaadt struct group *grp;
835df930be7Sderaadt
836df930be7Sderaadt if (!checkactive())
837df930be7Sderaadt return 1;
838df930be7Sderaadt
839df930be7Sderaadt gid = strtoul(argv[1], &cp, 0);
840df930be7Sderaadt if (cp == argv[1] || *cp != '\0' ) {
84100829d25Smillert if ((grp = getgrnam(argv[1]))) {
842df930be7Sderaadt gid = grp->gr_gid;
843df930be7Sderaadt } else {
844df930be7Sderaadt warnx("bad gid `%s'", argv[1]);
845df930be7Sderaadt return 1;
846df930be7Sderaadt }
847df930be7Sderaadt }
848df930be7Sderaadt
849c913562aSmillert DIP_SET(curinode, di_gid, gid);
850df930be7Sderaadt inodirty();
851df930be7Sderaadt printactive();
852df930be7Sderaadt return rval;
853df930be7Sderaadt }
854df930be7Sderaadt
85500829d25Smillert static int
dotime(char * name,time_t * rsec,int32_t * rnsec)856904f6f58Sotto dotime(char *name, time_t *rsec, int32_t *rnsec)
857df930be7Sderaadt {
858df930be7Sderaadt char *p, *val;
859df930be7Sderaadt struct tm t;
860904f6f58Sotto time_t sec;
861df930be7Sderaadt int32_t nsec;
8628809fabbSderaadt
863df930be7Sderaadt p = strchr(name, '.');
864df930be7Sderaadt if (p) {
865df930be7Sderaadt *p = '\0';
866df930be7Sderaadt nsec = strtoul(++p, &val, 0);
867df930be7Sderaadt if (val == p || *val != '\0' || nsec >= 1000000000 || nsec < 0) {
868df930be7Sderaadt warnx("invalid nanoseconds");
869df930be7Sderaadt goto badformat;
870df930be7Sderaadt }
871df930be7Sderaadt } else
872df930be7Sderaadt nsec = 0;
8738809fabbSderaadt
874df930be7Sderaadt if (strlen(name) != 14) {
875df930be7Sderaadt badformat:
876df930be7Sderaadt warnx("date format: YYYYMMDDHHMMSS[.nsec]");
877df930be7Sderaadt return 1;
878df930be7Sderaadt }
879df930be7Sderaadt
880df930be7Sderaadt for (p = name; *p; p++)
881df930be7Sderaadt if (*p < '0' || *p > '9')
882df930be7Sderaadt goto badformat;
883df930be7Sderaadt
884df930be7Sderaadt p = name;
885df930be7Sderaadt #define VAL() ((*p++) - '0')
88688d10243Sderaadt bzero(&t, sizeof t);
887df930be7Sderaadt t.tm_year = VAL();
888df930be7Sderaadt t.tm_year = VAL() + t.tm_year * 10;
889df930be7Sderaadt t.tm_year = VAL() + t.tm_year * 10;
890df930be7Sderaadt t.tm_year = VAL() + t.tm_year * 10 - 1900;
891df930be7Sderaadt t.tm_mon = VAL();
892df930be7Sderaadt t.tm_mon = VAL() + t.tm_mon * 10 - 1;
893df930be7Sderaadt t.tm_mday = VAL();
894df930be7Sderaadt t.tm_mday = VAL() + t.tm_mday * 10;
895df930be7Sderaadt t.tm_hour = VAL();
896df930be7Sderaadt t.tm_hour = VAL() + t.tm_hour * 10;
897df930be7Sderaadt t.tm_min = VAL();
898df930be7Sderaadt t.tm_min = VAL() + t.tm_min * 10;
899df930be7Sderaadt t.tm_sec = VAL();
900df930be7Sderaadt t.tm_sec = VAL() + t.tm_sec * 10;
901df930be7Sderaadt t.tm_isdst = -1;
902df930be7Sderaadt
903df930be7Sderaadt sec = mktime(&t);
904df930be7Sderaadt if (sec == -1) {
905df930be7Sderaadt warnx("date/time out of range");
906df930be7Sderaadt return 1;
907df930be7Sderaadt }
908df930be7Sderaadt *rsec = sec;
909df930be7Sderaadt *rnsec = nsec;
910df930be7Sderaadt return 0;
911df930be7Sderaadt }
912df930be7Sderaadt
CMDFUNCSTART(chmtime)913df930be7Sderaadt CMDFUNCSTART(chmtime)
914df930be7Sderaadt {
915904f6f58Sotto time_t rsec;
916904f6f58Sotto int32_t nsec;
917c913562aSmillert
918c913562aSmillert if (dotime(argv[1], &rsec, &nsec))
919df930be7Sderaadt return 1;
920c913562aSmillert DIP_SET(curinode, di_mtime, rsec);
921c913562aSmillert DIP_SET(curinode, di_mtimensec, nsec);
922df930be7Sderaadt inodirty();
923df930be7Sderaadt printactive();
924df930be7Sderaadt return 0;
925df930be7Sderaadt }
926df930be7Sderaadt
CMDFUNCSTART(chatime)927df930be7Sderaadt CMDFUNCSTART(chatime)
928df930be7Sderaadt {
929904f6f58Sotto time_t rsec;
930904f6f58Sotto int32_t nsec;
931c913562aSmillert
932c913562aSmillert if (dotime(argv[1], &rsec, &nsec))
933df930be7Sderaadt return 1;
934c913562aSmillert DIP_SET(curinode, di_atime, rsec);
935c913562aSmillert DIP_SET(curinode, di_atimensec, nsec);
936df930be7Sderaadt inodirty();
937df930be7Sderaadt printactive();
938df930be7Sderaadt return 0;
939df930be7Sderaadt }
940df930be7Sderaadt
CMDFUNCSTART(chctime)941df930be7Sderaadt CMDFUNCSTART(chctime)
942df930be7Sderaadt {
943904f6f58Sotto time_t rsec;
944904f6f58Sotto int32_t nsec;
945c913562aSmillert
946c913562aSmillert if (dotime(argv[1], &rsec, &nsec))
947df930be7Sderaadt return 1;
948c913562aSmillert DIP_SET(curinode, di_ctime, rsec);
949c913562aSmillert DIP_SET(curinode, di_ctimensec, nsec);
950df930be7Sderaadt inodirty();
951df930be7Sderaadt printactive();
952df930be7Sderaadt return 0;
953df930be7Sderaadt }
954