File: | src/sbin/fsdb/fsdb.c |
Warning: | line 284, column 4 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: fsdb.c,v 1.34 2021/01/27 05:03:25 deraadt Exp $ */ | |||
2 | /* $NetBSD: fsdb.c,v 1.7 1997/01/11 06:50:53 lukem Exp $ */ | |||
3 | ||||
4 | /*- | |||
5 | * Copyright (c) 1996 The NetBSD Foundation, Inc. | |||
6 | * All rights reserved. | |||
7 | * | |||
8 | * This code is derived from software contributed to The NetBSD Foundation | |||
9 | * by John T. Kohl. | |||
10 | * | |||
11 | * Redistribution and use in source and binary forms, with or without | |||
12 | * modification, are permitted provided that the following conditions | |||
13 | * are met: | |||
14 | * 1. Redistributions of source code must retain the above copyright | |||
15 | * notice, this list of conditions and the following disclaimer. | |||
16 | * 2. Redistributions in binary form must reproduce the above copyright | |||
17 | * notice, this list of conditions and the following disclaimer in the | |||
18 | * documentation and/or other materials provided with the distribution. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE | |||
24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
30 | * POSSIBILITY OF SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | #include <sys/stat.h> | |||
34 | #include <sys/time.h> | |||
35 | #include <sys/mount.h> | |||
36 | #include <ctype.h> | |||
37 | #include <err.h> | |||
38 | #include <fcntl.h> | |||
39 | #include <grp.h> | |||
40 | #include <histedit.h> | |||
41 | #include <limits.h> | |||
42 | #include <pwd.h> | |||
43 | #include <stdio.h> | |||
44 | #include <stdlib.h> | |||
45 | #include <string.h> | |||
46 | #include <unistd.h> | |||
47 | ||||
48 | #include <ufs/ufs/dinode.h> | |||
49 | #include <ufs/ufs/dir.h> | |||
50 | #include <ufs/ffs/fs.h> | |||
51 | ||||
52 | #include "fsdb.h" | |||
53 | #include "fsck.h" | |||
54 | #include "extern.h" | |||
55 | ||||
56 | extern char *__progname; /* from crt0.o */ | |||
57 | ||||
58 | int main(int, char *[]); | |||
59 | static void usage(void); | |||
60 | static int cmdloop(void); | |||
61 | static int helpfn(int, char *[]); | |||
62 | static char *prompt(EditLine *); | |||
63 | static int scannames(struct inodesc *); | |||
64 | static int dolookup(char *); | |||
65 | static int chinumfunc(struct inodesc *); | |||
66 | static int chnamefunc(struct inodesc *); | |||
67 | static int dotime(char *, time_t *, int32_t *); | |||
68 | ||||
69 | int returntosingle = 0; | |||
70 | union dinode *curinode; | |||
71 | ino_t curinum; | |||
72 | ||||
73 | struct inostatlist *inostathead; | |||
74 | ||||
75 | struct bufarea bufhead; /* head of list of other blks in filesys */ | |||
76 | struct bufarea sblk; /* file system superblock */ | |||
77 | struct bufarea asblk; /* alternate file system superblock */ | |||
78 | struct bufarea *pdirbp; /* current directory contents */ | |||
79 | struct bufarea *pbp; /* current inode block */ | |||
80 | ||||
81 | struct dups *duplist; /* head of dup list */ | |||
82 | struct dups *muldup; /* end of unique duplicate dup block numbers */ | |||
83 | ||||
84 | struct zlncnt *zlnhead; /* head of zero link count list */ | |||
85 | ||||
86 | struct inoinfo **inphead, **inpsort; | |||
87 | ||||
88 | extern long numdirs, listmax, inplast; | |||
89 | ||||
90 | long secsize; /* actual disk sector size */ | |||
91 | char nflag; /* assume a no response */ | |||
92 | char yflag; /* assume a yes response */ | |||
93 | daddr_t bflag; /* location of alternate super block */ | |||
94 | int debug; /* output debugging info */ | |||
95 | int cvtlevel; /* convert to newer file system format */ | |||
96 | char usedsoftdep; /* just fix soft dependency inconsistencies */ | |||
97 | int preen; /* just fix normal inconsistencies */ | |||
98 | char resolved; /* cleared if unresolved changes => not clean */ | |||
99 | char havesb; /* superblock has been read */ | |||
100 | char skipclean; /* skip clean file systems if preening */ | |||
101 | int fsmodified; /* 1 => write done to file system */ | |||
102 | int fsreadfd; /* file descriptor for reading file system */ | |||
103 | int fswritefd; /* file descriptor for writing file system */ | |||
104 | int rerun; /* rerun fsck. Only used in non-preen mode */ | |||
105 | ||||
106 | daddr_t maxfsblock; /* number of blocks in the file system */ | |||
107 | char *blockmap; /* ptr to primary blk allocation map */ | |||
108 | ino_t maxino; /* number of inodes in file system */ | |||
109 | ino_t lastino; /* last inode in use */ | |||
110 | ||||
111 | ino_t lfdir; /* lost & found directory inode number */ | |||
112 | ||||
113 | daddr_t n_blks; /* number of blocks in use */ | |||
114 | int64_t n_files; /* number of files in use */ | |||
115 | ||||
116 | struct ufs1_dinode ufs1_zino; | |||
117 | struct ufs2_dinode ufs2_zino; | |||
118 | ||||
119 | ||||
120 | static void | |||
121 | usage(void) | |||
122 | { | |||
123 | fprintf(stderr(&__sF[2]), "usage: %s [-d] -f fsname\n", __progname); | |||
124 | exit(1); | |||
125 | } | |||
126 | ||||
127 | /* | |||
128 | * We suck in lots of fsck code, and just pick & choose the stuff we want. | |||
129 | * | |||
130 | * fsreadfd is set up to read from the file system, fswritefd to write to | |||
131 | * the file system. | |||
132 | */ | |||
133 | int | |||
134 | main(int argc, char *argv[]) | |||
135 | { | |||
136 | int ch, rval; | |||
137 | char *fsys = NULL((void *)0); | |||
138 | ||||
139 | while (-1 != (ch = getopt(argc, argv, "f:d"))) { | |||
| ||||
140 | switch (ch) { | |||
141 | case 'f': | |||
142 | fsys = optarg; | |||
143 | break; | |||
144 | case 'd': | |||
145 | debug++; | |||
146 | break; | |||
147 | default: | |||
148 | usage(); | |||
149 | } | |||
150 | } | |||
151 | if (fsys == NULL((void *)0)) | |||
152 | usage(); | |||
153 | if (!setup(fsys, 1)) | |||
154 | errx(1, "cannot set up file system `%s'", fsys); | |||
155 | printf("Editing file system `%s'\nLast Mounted on %s\n", fsys, | |||
156 | sblock(*sblk.b_un.b_fs).fs_fsmnt); | |||
157 | rval = cmdloop(); | |||
158 | sblock(*sblk.b_un.b_fs).fs_clean = 0; /* mark it dirty */ | |||
159 | sbdirty()sblk.b_dirty = 1; | |||
160 | ckfini(0); | |||
161 | printf("*** FILE SYSTEM MARKED DIRTY\n"); | |||
162 | printf("*** BE SURE TO RUN FSCK TO CLEAN UP ANY DAMAGE\n"); | |||
163 | printf("*** IF IT WAS MOUNTED, RE-MOUNT WITH -u -o reload\n"); | |||
164 | exit(rval); | |||
165 | } | |||
166 | ||||
167 | #define CMDFUNC(func)static int func(int argc, char *argv[]) static int func(int argc, char *argv[]) | |||
168 | #define CMDFUNCSTART(func)static int func(int argc, char *argv[]) static int func(int argc, char *argv[]) | |||
169 | ||||
170 | CMDFUNC(helpfn)static int helpfn(int argc, char *argv[]); | |||
171 | CMDFUNC(focus)static int focus(int argc, char *argv[]); /* focus on inode */ | |||
172 | CMDFUNC(active)static int active(int argc, char *argv[]); /* print active inode */ | |||
173 | CMDFUNC(focusname)static int focusname(int argc, char *argv[]); /* focus by name */ | |||
174 | CMDFUNC(zapi)static int zapi(int argc, char *argv[]); /* clear inode */ | |||
175 | CMDFUNC(uplink)static int uplink(int argc, char *argv[]); /* incr link */ | |||
176 | CMDFUNC(downlink)static int downlink(int argc, char *argv[]); /* decr link */ | |||
177 | CMDFUNC(linkcount)static int linkcount(int argc, char *argv[]); /* set link count */ | |||
178 | CMDFUNC(quit)static int quit(int argc, char *argv[]); /* quit */ | |||
179 | CMDFUNC(ls)static int ls(int argc, char *argv[]); /* list directory */ | |||
180 | CMDFUNC(rm)static int rm(int argc, char *argv[]); /* remove name */ | |||
181 | CMDFUNC(ln)static int ln(int argc, char *argv[]); /* add name */ | |||
182 | CMDFUNC(newtype)static int newtype(int argc, char *argv[]); /* change type */ | |||
183 | CMDFUNC(chmode)static int chmode(int argc, char *argv[]); /* change mode */ | |||
184 | CMDFUNC(chlen)static int chlen(int argc, char *argv[]); /* change length */ | |||
185 | CMDFUNC(chaflags)static int chaflags(int argc, char *argv[]); /* change flags */ | |||
186 | CMDFUNC(chgen)static int chgen(int argc, char *argv[]); /* change generation */ | |||
187 | CMDFUNC(chowner)static int chowner(int argc, char *argv[]); /* change owner */ | |||
188 | CMDFUNC(chgroup)static int chgroup(int argc, char *argv[]); /* Change group */ | |||
189 | CMDFUNC(back)static int back(int argc, char *argv[]); /* pop back to last ino */ | |||
190 | CMDFUNC(chmtime)static int chmtime(int argc, char *argv[]); /* Change mtime */ | |||
191 | CMDFUNC(chctime)static int chctime(int argc, char *argv[]); /* Change ctime */ | |||
192 | CMDFUNC(chatime)static int chatime(int argc, char *argv[]); /* Change atime */ | |||
193 | CMDFUNC(chinum)static int chinum(int argc, char *argv[]); /* Change inode # of dirent */ | |||
194 | CMDFUNC(chname)static int chname(int argc, char *argv[]); /* Change dirname of dirent */ | |||
195 | ||||
196 | static struct cmdtable cmds[] = { | |||
197 | { "help", "Print out help", 1, 1, helpfn }, | |||
198 | { "?", "Print out help", 1, 1, helpfn }, | |||
199 | { "inode", "Set active inode to INUM", 2, 2, focus }, | |||
200 | { "clri", "Clear inode INUM", 2, 2, zapi }, | |||
201 | { "lookup", "Set active inode by looking up NAME", 2, 2, focusname }, | |||
202 | { "cd", "Set active inode by looking up NAME", 2, 2, focusname }, | |||
203 | { "back", "Go to previous active inode", 1, 1, back }, | |||
204 | { "active", "Print active inode", 1, 1, active }, | |||
205 | { "print", "Print active inode", 1, 1, active }, | |||
206 | { "uplink", "Increment link count", 1, 1, uplink }, | |||
207 | { "downlink", "Decrement link count", 1, 1, downlink }, | |||
208 | { "linkcount", "Set link count to COUNT", 2, 2, linkcount }, | |||
209 | { "ls", "List current inode as directory", 1, 1, ls }, | |||
210 | { "rm", "Remove NAME from current inode directory", 2, 2, rm }, | |||
211 | { "del", "Remove NAME from current inode directory", 2, 2, rm }, | |||
212 | { "ln", "Hardlink INO into current inode directory as NAME", 3, 3, ln }, | |||
213 | { "chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum }, | |||
214 | { "chname", "Change dir entry number INDEX to NAME", 3, 3, chname }, | |||
215 | { "chtype", "Change type of current inode to TYPE", 2, 2, newtype }, | |||
216 | { "chmod", "Change mode of current inode to MODE", 2, 2, chmode }, | |||
217 | { "chown", "Change owner of current inode to OWNER", 2, 2, chowner }, | |||
218 | { "chlen", "Change length of current inode to LENGTH", 2, 2, chlen }, | |||
219 | { "chgrp", "Change group of current inode to GROUP", 2, 2, chgroup }, | |||
220 | { "chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags }, | |||
221 | { "chgen", "Change generation number of current inode to GEN", 2, 2, chgen }, | |||
222 | { "mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime }, | |||
223 | { "ctime", "Change ctime of current inode to CTIME", 2, 2, chctime }, | |||
224 | { "atime", "Change atime of current inode to ATIME", 2, 2, chatime }, | |||
225 | { "quit", "Exit", 1, 1, quit }, | |||
226 | { "q", "Exit", 1, 1, quit }, | |||
227 | { "exit", "Exit", 1, 1, quit }, | |||
228 | { NULL((void *)0), 0, 0, 0 }, | |||
229 | }; | |||
230 | ||||
231 | static int | |||
232 | helpfn(int argc, char *argv[]) | |||
233 | { | |||
234 | struct cmdtable *cmdtp; | |||
235 | ||||
236 | printf("Commands are:\n%-10s %5s %5s %s\n", | |||
237 | "command", "min argc", "max argc", "what"); | |||
238 | ||||
239 | for (cmdtp = cmds; cmdtp->cmd; cmdtp++) | |||
240 | printf("%-10s %5u %5u %s\n", | |||
241 | cmdtp->cmd, cmdtp->minargc, cmdtp->maxargc, cmdtp->helptxt); | |||
242 | return 0; | |||
243 | } | |||
244 | ||||
245 | static char * | |||
246 | prompt(EditLine *el) | |||
247 | { | |||
248 | static char pstring[64]; | |||
249 | ||||
250 | snprintf(pstring, sizeof(pstring), "fsdb (inum: %llu)> ", | |||
251 | (unsigned long long)curinum); | |||
252 | return pstring; | |||
253 | } | |||
254 | ||||
255 | ||||
256 | static int | |||
257 | cmdloop(void) | |||
258 | { | |||
259 | char *line = NULL((void *)0); | |||
260 | const char *elline; | |||
261 | int cmd_argc, rval = 0, known; | |||
262 | #define scratchknown known | |||
263 | char **cmd_argv; | |||
264 | struct cmdtable *cmdp; | |||
265 | History *hist; | |||
266 | EditLine *elptr; | |||
267 | HistEvent hev; | |||
268 | ||||
269 | curinode = ginode(ROOTINO((ufsino_t)2)); | |||
270 | curinum = ROOTINO((ufsino_t)2); | |||
271 | printactive(); | |||
272 | ||||
273 | hist = history_init(); | |||
274 | history(hist, &hev, H_SETSIZE1, 100); /* 100 elt history buffer */ | |||
275 | ||||
276 | elptr = el_init(__progname, stdin(&__sF[0]), stdout(&__sF[1]), stderr(&__sF[2])); | |||
277 | el_set(elptr, EL_EDITOR2, "emacs"); | |||
278 | el_set(elptr, EL_PROMPT0, prompt); | |||
279 | el_set(elptr, EL_HIST10, history, hist); | |||
280 | el_source(elptr, NULL((void *)0)); | |||
281 | ||||
282 | while ((elline = el_gets(elptr, &scratchknown)) != NULL((void *)0) && scratchknown != 0) { | |||
283 | if (debug) | |||
284 | printf("command `%s'\n", line); | |||
| ||||
285 | ||||
286 | history(hist, &hev, H_ENTER10, elline); | |||
287 | ||||
288 | line = strdup(elline); | |||
289 | if (line == NULL((void *)0)) | |||
290 | errx(1, "out of memory"); | |||
291 | cmd_argv = crack(line, &cmd_argc); | |||
292 | if (cmd_argc) { | |||
293 | /* | |||
294 | * el_parse returns -1 to signal that it's not been handled | |||
295 | * internally. | |||
296 | */ | |||
297 | if (el_parse(elptr, cmd_argc, (const char **)cmd_argv) != -1) | |||
298 | continue; | |||
299 | known = 0; | |||
300 | for (cmdp = cmds; cmdp->cmd; cmdp++) { | |||
301 | if (!strcmp(cmdp->cmd, cmd_argv[0])) { | |||
302 | if (cmd_argc >= cmdp->minargc && | |||
303 | cmd_argc <= cmdp->maxargc) | |||
304 | rval = (*cmdp->handler)(cmd_argc, | |||
305 | cmd_argv); | |||
306 | else | |||
307 | rval = argcount(cmdp, | |||
308 | cmd_argc, cmd_argv); | |||
309 | known = 1; | |||
310 | break; | |||
311 | } | |||
312 | } | |||
313 | if (!known) { | |||
314 | warnx("unknown command `%s'", cmd_argv[0]); | |||
315 | rval = 1; | |||
316 | } | |||
317 | } else | |||
318 | rval = 0; | |||
319 | free(line); | |||
320 | if (rval
| |||
321 | return rval; | |||
322 | if (rval
| |||
323 | warnx("rval was %d", rval); | |||
324 | } | |||
325 | el_end(elptr); | |||
326 | history_end(hist); | |||
327 | return rval; | |||
328 | } | |||
329 | ||||
330 | static ino_t ocurrent; | |||
331 | ||||
332 | #define GETINUM(ac,inum)inum = strtoull(argv[ac], &cp, 0); if (inum < ((ufsino_t )2) || inum > maxino || cp == argv[ac] || *cp != '\0' ) { printf ("inode %llu out of range; range is [%llu,%llu]\n", (unsigned long long)inum, (unsigned long long)((ufsino_t)2), (unsigned long long)maxino); return 1; } inum = strtoull(argv[ac], &cp, 0); \ | |||
333 | if (inum < ROOTINO((ufsino_t)2) || inum > maxino || cp == argv[ac] || *cp != '\0' ) { \ | |||
334 | printf("inode %llu out of range; range is [%llu,%llu]\n", \ | |||
335 | (unsigned long long)inum, (unsigned long long)ROOTINO((ufsino_t)2), \ | |||
336 | (unsigned long long)maxino); \ | |||
337 | return 1; \ | |||
338 | } | |||
339 | ||||
340 | /* | |||
341 | * Focus on given inode number | |||
342 | */ | |||
343 | CMDFUNCSTART(focus)static int focus(int argc, char *argv[]) | |||
344 | { | |||
345 | ino_t inum; | |||
346 | char *cp; | |||
347 | ||||
348 | GETINUM(1,inum)inum = strtoull(argv[1], &cp, 0); if (inum < ((ufsino_t )2) || inum > maxino || cp == argv[1] || *cp != '\0' ) { printf ("inode %llu out of range; range is [%llu,%llu]\n", (unsigned long long)inum, (unsigned long long)((ufsino_t)2), (unsigned long long)maxino); return 1; }; | |||
349 | curinode = ginode(inum); | |||
350 | ocurrent = curinum; | |||
351 | curinum = inum; | |||
352 | printactive(); | |||
353 | return 0; | |||
354 | } | |||
355 | ||||
356 | CMDFUNCSTART(back)static int back(int argc, char *argv[]) | |||
357 | { | |||
358 | curinum = ocurrent; | |||
359 | curinode = ginode(curinum); | |||
360 | printactive(); | |||
361 | return 0; | |||
362 | } | |||
363 | ||||
364 | CMDFUNCSTART(zapi)static int zapi(int argc, char *argv[]) | |||
365 | { | |||
366 | ino_t inum; | |||
367 | union dinode *dp; | |||
368 | char *cp; | |||
369 | ||||
370 | GETINUM(1,inum)inum = strtoull(argv[1], &cp, 0); if (inum < ((ufsino_t )2) || inum > maxino || cp == argv[1] || *cp != '\0' ) { printf ("inode %llu out of range; range is [%llu,%llu]\n", (unsigned long long)inum, (unsigned long long)((ufsino_t)2), (unsigned long long)maxino); return 1; }; | |||
371 | dp = ginode(inum); | |||
372 | clearinode(dp)if ((*sblk.b_un.b_fs).fs_magic == 0x011954) { (dp)->dp1 = ufs1_zino ; } else { (dp)->dp2 = ufs2_zino; }; | |||
373 | inodirty(); | |||
374 | if (curinode) /* re-set after potential change */ | |||
375 | curinode = ginode(curinum); | |||
376 | return 0; | |||
377 | } | |||
378 | ||||
379 | CMDFUNCSTART(active)static int active(int argc, char *argv[]) | |||
380 | { | |||
381 | printactive(); | |||
382 | return 0; | |||
383 | } | |||
384 | ||||
385 | ||||
386 | CMDFUNCSTART(quit)static int quit(int argc, char *argv[]) | |||
387 | { | |||
388 | return -1; | |||
389 | } | |||
390 | ||||
391 | CMDFUNCSTART(uplink)static int uplink(int argc, char *argv[]) | |||
392 | { | |||
393 | if (!checkactive()) | |||
394 | return 1; | |||
395 | DIP_SET(curinode, di_nlink, DIP(curinode, di_nlink) + 1)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( curinode)->dp1.di_nlink : (curinode)->dp2.di_nlink) + 1 ); else (curinode)->dp2.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1.di_nlink : (curinode)-> dp2.di_nlink) + 1); } while (0); | |||
396 | printf("inode %llu link count now %d\n", | |||
397 | (unsigned long long)curinum, DIP(curinode, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1 .di_nlink : (curinode)->dp2.di_nlink)); | |||
398 | inodirty(); | |||
399 | return 0; | |||
400 | } | |||
401 | ||||
402 | CMDFUNCSTART(downlink)static int downlink(int argc, char *argv[]) | |||
403 | { | |||
404 | if (!checkactive()) | |||
405 | return 1; | |||
406 | DIP_SET(curinode, di_nlink, DIP(curinode, di_nlink) - 1)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? ( curinode)->dp1.di_nlink : (curinode)->dp2.di_nlink) - 1 ); else (curinode)->dp2.di_nlink = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1.di_nlink : (curinode)-> dp2.di_nlink) - 1); } while (0); | |||
407 | printf("inode %llu link count now %d\n", | |||
408 | (unsigned long long)curinum, DIP(curinode, di_nlink)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1 .di_nlink : (curinode)->dp2.di_nlink)); | |||
409 | inodirty(); | |||
410 | return 0; | |||
411 | } | |||
412 | ||||
413 | static const char *typename[] = { | |||
414 | "unknown", | |||
415 | "fifo", | |||
416 | "char special", | |||
417 | "unregistered #3", | |||
418 | "directory", | |||
419 | "unregistered #5", | |||
420 | "blk special", | |||
421 | "unregistered #7", | |||
422 | "regular", | |||
423 | "unregistered #9", | |||
424 | "symlink", | |||
425 | "unregistered #11", | |||
426 | "socket", | |||
427 | "unregistered #13", | |||
428 | "whiteout", | |||
429 | }; | |||
430 | ||||
431 | static int slot; | |||
432 | ||||
433 | static int | |||
434 | scannames(struct inodesc *idesc) | |||
435 | { | |||
436 | struct direct *dirp = idesc->id_dirp; | |||
437 | ||||
438 | printf("slot %d ino %llu reclen %d: %s, `%.*s'\n", | |||
439 | slot++, (unsigned long long)dirp->d_ino, dirp->d_reclen, | |||
440 | typename[dirp->d_type], dirp->d_namlen, dirp->d_name); | |||
441 | return (KEEPON0x04); | |||
442 | } | |||
443 | ||||
444 | CMDFUNCSTART(ls)static int ls(int argc, char *argv[]) | |||
445 | { | |||
446 | struct inodesc idesc; | |||
447 | checkactivedir(); /* let it go on anyway */ | |||
448 | ||||
449 | slot = 0; | |||
450 | idesc.id_number = curinum; | |||
451 | idesc.id_func = scannames; | |||
452 | idesc.id_type = DATA1; | |||
453 | idesc.id_fix = IGNORE; | |||
454 | ckinode(curinode, &idesc); | |||
455 | curinode = ginode(curinum); | |||
456 | ||||
457 | return 0; | |||
458 | } | |||
459 | ||||
460 | static int | |||
461 | dolookup(char *name) | |||
462 | { | |||
463 | struct inodesc idesc; | |||
464 | ||||
465 | if (!checkactivedir()) | |||
466 | return 0; | |||
467 | idesc.id_number = curinum; | |||
468 | idesc.id_func = findino; | |||
469 | idesc.id_name = name; | |||
470 | idesc.id_type = DATA1; | |||
471 | idesc.id_fix = IGNORE; | |||
472 | if (ckinode(curinode, &idesc) & FOUND0x10) { | |||
473 | curinum = idesc.id_parent; | |||
474 | curinode = ginode(curinum); | |||
475 | printactive(); | |||
476 | return 1; | |||
477 | } else { | |||
478 | warnx("name `%s' not found in current inode directory", name); | |||
479 | return 0; | |||
480 | } | |||
481 | } | |||
482 | ||||
483 | CMDFUNCSTART(focusname)static int focusname(int argc, char *argv[]) | |||
484 | { | |||
485 | char *p, *val; | |||
486 | ||||
487 | if (!checkactive()) | |||
488 | return 1; | |||
489 | ||||
490 | ocurrent = curinum; | |||
491 | ||||
492 | if (argv[1][0] == '/') { | |||
493 | curinum = ROOTINO((ufsino_t)2); | |||
494 | curinode = ginode(ROOTINO((ufsino_t)2)); | |||
495 | } else { | |||
496 | if (!checkactivedir()) | |||
497 | return 1; | |||
498 | } | |||
499 | for (p = argv[1]; p != NULL((void *)0);) { | |||
500 | while ((val = strsep(&p, "/")) != NULL((void *)0) && *val == '\0') | |||
501 | continue; | |||
502 | if (val) { | |||
503 | printf("component `%s': ", val); | |||
504 | fflush(stdout(&__sF[1])); | |||
505 | if (!dolookup(val)) { | |||
506 | curinode = ginode(curinum); | |||
507 | return(1); | |||
508 | } | |||
509 | } | |||
510 | } | |||
511 | return 0; | |||
512 | } | |||
513 | ||||
514 | CMDFUNCSTART(ln)static int ln(int argc, char *argv[]) | |||
515 | { | |||
516 | ino_t inum; | |||
517 | int rval; | |||
518 | char *cp; | |||
519 | ||||
520 | GETINUM(1,inum)inum = strtoull(argv[1], &cp, 0); if (inum < ((ufsino_t )2) || inum > maxino || cp == argv[1] || *cp != '\0' ) { printf ("inode %llu out of range; range is [%llu,%llu]\n", (unsigned long long)inum, (unsigned long long)((ufsino_t)2), (unsigned long long)maxino); return 1; }; | |||
521 | ||||
522 | if (!checkactivedir()) | |||
523 | return 1; | |||
524 | rval = makeentry(curinum, inum, argv[2]); | |||
525 | if (rval) | |||
526 | printf("Ino %llu entered as `%s'\n", | |||
527 | (unsigned long long)inum, argv[2]); | |||
528 | else | |||
529 | printf("could not enter name? weird.\n"); | |||
530 | curinode = ginode(curinum); | |||
531 | return rval; | |||
532 | } | |||
533 | ||||
534 | CMDFUNCSTART(rm)static int rm(int argc, char *argv[]) | |||
535 | { | |||
536 | int rval; | |||
537 | ||||
538 | if (!checkactivedir()) | |||
539 | return 1; | |||
540 | rval = changeino(curinum, argv[1], 0); | |||
541 | if (rval & ALTERED0x08) { | |||
542 | printf("Name `%s' removed\n", argv[1]); | |||
543 | return 0; | |||
544 | } else { | |||
545 | printf("could not remove name? weird.\n"); | |||
546 | return 1; | |||
547 | } | |||
548 | } | |||
549 | ||||
550 | static long slotcount, desired; | |||
551 | ||||
552 | static int | |||
553 | chinumfunc(struct inodesc *idesc) | |||
554 | { | |||
555 | struct direct *dirp = idesc->id_dirp; | |||
556 | ||||
557 | if (slotcount++ == desired) { | |||
558 | dirp->d_ino = idesc->id_parent; | |||
559 | return STOP0x01|ALTERED0x08|FOUND0x10; | |||
560 | } | |||
561 | return KEEPON0x04; | |||
562 | } | |||
563 | ||||
564 | CMDFUNCSTART(chinum)static int chinum(int argc, char *argv[]) | |||
565 | { | |||
566 | char *cp; | |||
567 | ino_t inum; | |||
568 | struct inodesc idesc; | |||
569 | ||||
570 | slotcount = 0; | |||
571 | if (!checkactivedir()) | |||
572 | return 1; | |||
573 | GETINUM(2,inum)inum = strtoull(argv[2], &cp, 0); if (inum < ((ufsino_t )2) || inum > maxino || cp == argv[2] || *cp != '\0' ) { printf ("inode %llu out of range; range is [%llu,%llu]\n", (unsigned long long)inum, (unsigned long long)((ufsino_t)2), (unsigned long long)maxino); return 1; }; | |||
574 | ||||
575 | desired = strtol(argv[1], &cp, 0); | |||
576 | if (cp == argv[1] || *cp != '\0' || desired < 0) { | |||
577 | printf("invalid slot number `%s'\n", argv[1]); | |||
578 | return 1; | |||
579 | } | |||
580 | ||||
581 | idesc.id_number = curinum; | |||
582 | idesc.id_func = chinumfunc; | |||
583 | idesc.id_fix = IGNORE; | |||
584 | idesc.id_type = DATA1; | |||
585 | idesc.id_parent = inum; /* XXX convenient hiding place */ | |||
586 | ||||
587 | if (ckinode(curinode, &idesc) & FOUND0x10) | |||
588 | return 0; | |||
589 | else { | |||
590 | warnx("no %sth slot in current directory", argv[1]); | |||
591 | return 1; | |||
592 | } | |||
593 | } | |||
594 | ||||
595 | static int | |||
596 | chnamefunc(struct inodesc *idesc) | |||
597 | { | |||
598 | struct direct *dirp = idesc->id_dirp; | |||
599 | struct direct testdir; | |||
600 | ||||
601 | if (slotcount++ == desired) { | |||
602 | /* will name fit? */ | |||
603 | testdir.d_namlen = strlen(idesc->id_name); | |||
604 | if (DIRSIZ(NEWDIRFMT, &testdir)((0) ? ((sizeof(struct direct) - (255 +1)) + (((&testdir) ->d_type+1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1)) + (((&testdir)->d_namlen+1 + 3) &~ 3))) <= dirp->d_reclen) { | |||
605 | dirp->d_namlen = testdir.d_namlen; | |||
606 | strlcpy(dirp->d_name, idesc->id_name, sizeof dirp->d_name); | |||
607 | return STOP0x01|ALTERED0x08|FOUND0x10; | |||
608 | } else | |||
609 | return STOP0x01|FOUND0x10; /* won't fit, so give up */ | |||
610 | } | |||
611 | return KEEPON0x04; | |||
612 | } | |||
613 | ||||
614 | CMDFUNCSTART(chname)static int chname(int argc, char *argv[]) | |||
615 | { | |||
616 | int rval; | |||
617 | char *cp; | |||
618 | struct inodesc idesc; | |||
619 | ||||
620 | slotcount = 0; | |||
621 | if (!checkactivedir()) | |||
622 | return 1; | |||
623 | ||||
624 | desired = strtoul(argv[1], &cp, 0); | |||
625 | if (cp == argv[1] || *cp != '\0') { | |||
626 | printf("invalid slot number `%s'\n", argv[1]); | |||
627 | return 1; | |||
628 | } | |||
629 | ||||
630 | idesc.id_number = curinum; | |||
631 | idesc.id_func = chnamefunc; | |||
632 | idesc.id_fix = IGNORE; | |||
633 | idesc.id_type = DATA1; | |||
634 | idesc.id_name = argv[2]; | |||
635 | ||||
636 | rval = ckinode(curinode, &idesc); | |||
637 | if ((rval & (FOUND0x10|ALTERED0x08)) == (FOUND0x10|ALTERED0x08)) | |||
638 | return 0; | |||
639 | else if (rval & FOUND0x10) { | |||
640 | warnx("new name `%s' does not fit in slot %s", argv[2], argv[1]); | |||
641 | return 1; | |||
642 | } else { | |||
643 | warnx("no %sth slot in current directory", argv[1]); | |||
644 | return 1; | |||
645 | } | |||
646 | } | |||
647 | ||||
648 | static struct typemap { | |||
649 | const char *typename; | |||
650 | int typebits; | |||
651 | } typenamemap[] = { | |||
652 | {"file", IFREG0100000}, | |||
653 | {"dir", IFDIR0040000}, | |||
654 | {"socket", IFSOCK0140000}, | |||
655 | {"fifo", IFIFO0010000}, | |||
656 | }; | |||
657 | ||||
658 | CMDFUNCSTART(newtype)static int newtype(int argc, char *argv[]) | |||
659 | { | |||
660 | int type; | |||
661 | struct typemap *tp; | |||
662 | ||||
663 | if (!checkactive()) | |||
664 | return 1; | |||
665 | type = DIP(curinode, di_mode)(((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1 .di_mode : (curinode)->dp2.di_mode) & IFMT0170000; | |||
666 | for (tp = typenamemap; | |||
667 | tp < &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)]; | |||
668 | tp++) { | |||
669 | if (!strcmp(argv[1], tp->typename)) { | |||
670 | printf("setting type to %s\n", tp->typename); | |||
671 | type = tp->typebits; | |||
672 | break; | |||
673 | } | |||
674 | } | |||
675 | if (tp == &typenamemap[sizeof(typenamemap)/sizeof(*typenamemap)]) { | |||
676 | warnx("type `%s' not known", argv[1]); | |||
677 | warnx("try one of `file', `dir', `socket', `fifo'"); | |||
678 | return 1; | |||
679 | } | |||
680 | DIP_SET(curinode, di_mode, DIP(curinode, di_mode) & ~IFMT)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode )->dp1.di_mode : (curinode)->dp2.di_mode) & ~0170000 ); else (curinode)->dp2.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1.di_mode : (curinode)->dp2 .di_mode) & ~0170000); } while (0); | |||
681 | DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | type)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode )->dp1.di_mode : (curinode)->dp2.di_mode) | type); else (curinode)->dp2.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1.di_mode : (curinode)->dp2. di_mode) | type); } while (0); | |||
682 | inodirty(); | |||
683 | printactive(); | |||
684 | return 0; | |||
685 | } | |||
686 | ||||
687 | CMDFUNCSTART(chmode)static int chmode(int argc, char *argv[]) | |||
688 | { | |||
689 | int rval = 1; | |||
690 | long modebits; | |||
691 | char *cp; | |||
692 | ||||
693 | if (!checkactive()) | |||
694 | return 1; | |||
695 | ||||
696 | modebits = strtol(argv[1], &cp, 8); | |||
697 | if (cp == argv[1] || *cp != '\0' ) { | |||
698 | warnx("bad modebits `%s'", argv[1]); | |||
699 | return 1; | |||
700 | } | |||
701 | ||||
702 | DIP_SET(curinode, di_mode, DIP(curinode, di_mode) & ~07777)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode )->dp1.di_mode : (curinode)->dp2.di_mode) & ~07777) ; else (curinode)->dp2.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1.di_mode : (curinode)->dp2 .di_mode) & ~07777); } while (0); | |||
703 | DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | modebits)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode )->dp1.di_mode : (curinode)->dp2.di_mode) | modebits); else (curinode)->dp2.di_mode = ((((*sblk.b_un.b_fs).fs_magic == 0x011954) ? (curinode)->dp1.di_mode : (curinode)->dp2. di_mode) | modebits); } while (0); | |||
704 | inodirty(); | |||
705 | printactive(); | |||
706 | return rval; | |||
707 | } | |||
708 | ||||
709 | CMDFUNCSTART(chlen)static int chlen(int argc, char *argv[]) | |||
710 | { | |||
711 | int rval = 1; | |||
712 | long len; | |||
713 | char *cp; | |||
714 | ||||
715 | if (!checkactive()) | |||
716 | return 1; | |||
717 | ||||
718 | len = strtol(argv[1], &cp, 0); | |||
719 | if (cp == argv[1] || *cp != '\0' || len < 0) { | |||
720 | warnx("bad length '%s'", argv[1]); | |||
721 | return 1; | |||
722 | } | |||
723 | ||||
724 | DIP_SET(curinode, di_size, len)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_size = (len); else (curinode)->dp2.di_size = (len); } while (0); | |||
725 | inodirty(); | |||
726 | printactive(); | |||
727 | return rval; | |||
728 | } | |||
729 | ||||
730 | CMDFUNCSTART(chaflags)static int chaflags(int argc, char *argv[]) | |||
731 | { | |||
732 | int rval = 1; | |||
733 | u_long flags; | |||
734 | char *cp; | |||
735 | ||||
736 | if (!checkactive()) | |||
737 | return 1; | |||
738 | ||||
739 | flags = strtoul(argv[1], &cp, 0); | |||
740 | if (cp == argv[1] || *cp != '\0' ) { | |||
741 | warnx("bad flags `%s'", argv[1]); | |||
742 | return 1; | |||
743 | } | |||
744 | ||||
745 | if (flags > UINT_MAX(2147483647 *2U +1U)) { | |||
746 | warnx("flags set beyond 32-bit range of field (%lx)", flags); | |||
747 | return(1); | |||
748 | } | |||
749 | DIP_SET(curinode, di_flags, flags)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_flags = (flags); else (curinode)->dp2.di_flags = (flags ); } while (0); | |||
750 | inodirty(); | |||
751 | printactive(); | |||
752 | return rval; | |||
753 | } | |||
754 | ||||
755 | CMDFUNCSTART(chgen)static int chgen(int argc, char *argv[]) | |||
756 | { | |||
757 | int rval = 1; | |||
758 | long long gen; | |||
759 | char *cp; | |||
760 | ||||
761 | if (!checkactive()) | |||
762 | return 1; | |||
763 | ||||
764 | gen = strtoll(argv[1], &cp, 0); | |||
765 | if (cp == argv[1] || *cp != '\0' ) { | |||
766 | warnx("bad gen `%s'", argv[1]); | |||
767 | return 1; | |||
768 | } | |||
769 | ||||
770 | if (gen > UINT_MAX(2147483647 *2U +1U) || gen < 0) { | |||
771 | warnx("gen set beyond 32-bit range of field (%llx)", gen); | |||
772 | return(1); | |||
773 | } | |||
774 | DIP_SET(curinode, di_gen, gen)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_gen = (gen); else (curinode)->dp2.di_gen = (gen); } while (0); | |||
775 | inodirty(); | |||
776 | printactive(); | |||
777 | return rval; | |||
778 | } | |||
779 | ||||
780 | CMDFUNCSTART(linkcount)static int linkcount(int argc, char *argv[]) | |||
781 | { | |||
782 | int rval = 1; | |||
783 | int lcnt; | |||
784 | char *cp; | |||
785 | ||||
786 | if (!checkactive()) | |||
787 | return 1; | |||
788 | ||||
789 | lcnt = strtol(argv[1], &cp, 0); | |||
790 | if (cp == argv[1] || *cp != '\0' ) { | |||
791 | warnx("bad link count `%s'", argv[1]); | |||
792 | return 1; | |||
793 | } | |||
794 | if (lcnt > USHRT_MAX(32767 *2 +1) || lcnt < 0) { | |||
795 | warnx("max link count is %d", USHRT_MAX(32767 *2 +1)); | |||
796 | return 1; | |||
797 | } | |||
798 | ||||
799 | DIP_SET(curinode, di_nlink, lcnt)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_nlink = (lcnt); else (curinode)->dp2.di_nlink = (lcnt ); } while (0); | |||
800 | inodirty(); | |||
801 | printactive(); | |||
802 | return rval; | |||
803 | } | |||
804 | ||||
805 | CMDFUNCSTART(chowner)static int chowner(int argc, char *argv[]) | |||
806 | { | |||
807 | int rval = 1; | |||
808 | uid_t uid; | |||
809 | char *cp; | |||
810 | ||||
811 | if (!checkactive()) | |||
812 | return 1; | |||
813 | ||||
814 | uid = strtoul(argv[1], &cp, 0); | |||
815 | if (cp == argv[1] || *cp != '\0' ) { | |||
816 | /* try looking up name */ | |||
817 | if (uid_from_user(argv[1], &uid) == -1) { | |||
818 | warnx("bad uid `%s'", argv[1]); | |||
819 | return 1; | |||
820 | } | |||
821 | } | |||
822 | ||||
823 | DIP_SET(curinode, di_uid, uid)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_uid = (uid); else (curinode)->dp2.di_uid = (uid); } while (0); | |||
824 | inodirty(); | |||
825 | printactive(); | |||
826 | return rval; | |||
827 | } | |||
828 | ||||
829 | CMDFUNCSTART(chgroup)static int chgroup(int argc, char *argv[]) | |||
830 | { | |||
831 | int rval = 1; | |||
832 | gid_t gid; | |||
833 | char *cp; | |||
834 | struct group *grp; | |||
835 | ||||
836 | if (!checkactive()) | |||
837 | return 1; | |||
838 | ||||
839 | gid = strtoul(argv[1], &cp, 0); | |||
840 | if (cp == argv[1] || *cp != '\0' ) { | |||
841 | if ((grp = getgrnam(argv[1]))) { | |||
842 | gid = grp->gr_gid; | |||
843 | } else { | |||
844 | warnx("bad gid `%s'", argv[1]); | |||
845 | return 1; | |||
846 | } | |||
847 | } | |||
848 | ||||
849 | DIP_SET(curinode, di_gid, gid)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_gid = (gid); else (curinode)->dp2.di_gid = (gid); } while (0); | |||
850 | inodirty(); | |||
851 | printactive(); | |||
852 | return rval; | |||
853 | } | |||
854 | ||||
855 | static int | |||
856 | dotime(char *name, time_t *rsec, int32_t *rnsec) | |||
857 | { | |||
858 | char *p, *val; | |||
859 | struct tm t; | |||
860 | time_t sec; | |||
861 | int32_t nsec; | |||
862 | ||||
863 | p = strchr(name, '.'); | |||
864 | if (p) { | |||
865 | *p = '\0'; | |||
866 | nsec = strtoul(++p, &val, 0); | |||
867 | if (val == p || *val != '\0' || nsec >= 1000000000 || nsec < 0) { | |||
868 | warnx("invalid nanoseconds"); | |||
869 | goto badformat; | |||
870 | } | |||
871 | } else | |||
872 | nsec = 0; | |||
873 | ||||
874 | if (strlen(name) != 14) { | |||
875 | badformat: | |||
876 | warnx("date format: YYYYMMDDHHMMSS[.nsec]"); | |||
877 | return 1; | |||
878 | } | |||
879 | ||||
880 | for (p = name; *p; p++) | |||
881 | if (*p < '0' || *p > '9') | |||
882 | goto badformat; | |||
883 | ||||
884 | p = name; | |||
885 | #define VAL()((*p++) - '0') ((*p++) - '0') | |||
886 | bzero(&t, sizeof t); | |||
887 | t.tm_year = VAL()((*p++) - '0'); | |||
888 | t.tm_year = VAL()((*p++) - '0') + t.tm_year * 10; | |||
889 | t.tm_year = VAL()((*p++) - '0') + t.tm_year * 10; | |||
890 | t.tm_year = VAL()((*p++) - '0') + t.tm_year * 10 - 1900; | |||
891 | t.tm_mon = VAL()((*p++) - '0'); | |||
892 | t.tm_mon = VAL()((*p++) - '0') + t.tm_mon * 10 - 1; | |||
893 | t.tm_mday = VAL()((*p++) - '0'); | |||
894 | t.tm_mday = VAL()((*p++) - '0') + t.tm_mday * 10; | |||
895 | t.tm_hour = VAL()((*p++) - '0'); | |||
896 | t.tm_hour = VAL()((*p++) - '0') + t.tm_hour * 10; | |||
897 | t.tm_min = VAL()((*p++) - '0'); | |||
898 | t.tm_min = VAL()((*p++) - '0') + t.tm_min * 10; | |||
899 | t.tm_sec = VAL()((*p++) - '0'); | |||
900 | t.tm_sec = VAL()((*p++) - '0') + t.tm_sec * 10; | |||
901 | t.tm_isdst = -1; | |||
902 | ||||
903 | sec = mktime(&t); | |||
904 | if (sec == -1) { | |||
905 | warnx("date/time out of range"); | |||
906 | return 1; | |||
907 | } | |||
908 | *rsec = sec; | |||
909 | *rnsec = nsec; | |||
910 | return 0; | |||
911 | } | |||
912 | ||||
913 | CMDFUNCSTART(chmtime)static int chmtime(int argc, char *argv[]) | |||
914 | { | |||
915 | time_t rsec; | |||
916 | int32_t nsec; | |||
917 | ||||
918 | if (dotime(argv[1], &rsec, &nsec)) | |||
919 | return 1; | |||
920 | DIP_SET(curinode, di_mtime, rsec)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_mtime = (rsec); else (curinode)->dp2.di_mtime = (rsec ); } while (0); | |||
921 | DIP_SET(curinode, di_mtimensec, nsec)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_mtimensec = (nsec); else (curinode)->dp2.di_mtimensec = (nsec); } while (0); | |||
922 | inodirty(); | |||
923 | printactive(); | |||
924 | return 0; | |||
925 | } | |||
926 | ||||
927 | CMDFUNCSTART(chatime)static int chatime(int argc, char *argv[]) | |||
928 | { | |||
929 | time_t rsec; | |||
930 | int32_t nsec; | |||
931 | ||||
932 | if (dotime(argv[1], &rsec, &nsec)) | |||
933 | return 1; | |||
934 | DIP_SET(curinode, di_atime, rsec)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_atime = (rsec); else (curinode)->dp2.di_atime = (rsec ); } while (0); | |||
935 | DIP_SET(curinode, di_atimensec, nsec)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_atimensec = (nsec); else (curinode)->dp2.di_atimensec = (nsec); } while (0); | |||
936 | inodirty(); | |||
937 | printactive(); | |||
938 | return 0; | |||
939 | } | |||
940 | ||||
941 | CMDFUNCSTART(chctime)static int chctime(int argc, char *argv[]) | |||
942 | { | |||
943 | time_t rsec; | |||
944 | int32_t nsec; | |||
945 | ||||
946 | if (dotime(argv[1], &rsec, &nsec)) | |||
947 | return 1; | |||
948 | DIP_SET(curinode, di_ctime, rsec)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_ctime = (rsec); else (curinode)->dp2.di_ctime = (rsec ); } while (0); | |||
949 | DIP_SET(curinode, di_ctimensec, nsec)do { if ((*sblk.b_un.b_fs).fs_magic == 0x011954) (curinode)-> dp1.di_ctimensec = (nsec); else (curinode)->dp2.di_ctimensec = (nsec); } while (0); | |||
950 | inodirty(); | |||
951 | printactive(); | |||
952 | return 0; | |||
953 | } |