| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: fsdb.c,v 1.51 2020/04/05 15:25:40 joerg Exp $ */ | | 1 | /* $NetBSD: fsdb.c,v 1.52 2021/05/29 16:51:25 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 2017 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 2017 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by John T. Kohl. | | 8 | * by John T. Kohl. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -21,27 +21,27 @@ | | | @@ -21,27 +21,27 @@ |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | __RCSID("$NetBSD: fsdb.c,v 1.51 2020/04/05 15:25:40 joerg Exp $"); | | 34 | __RCSID("$NetBSD: fsdb.c,v 1.52 2021/05/29 16:51:25 christos Exp $"); |
35 | #endif /* not lint */ | | 35 | #endif /* not lint */ |
36 | | | 36 | |
37 | #include <sys/types.h> | | 37 | #include <sys/types.h> |
38 | #include <sys/stat.h> | | 38 | #include <sys/stat.h> |
39 | #include <sys/param.h> | | 39 | #include <sys/param.h> |
40 | #include <sys/time.h> | | 40 | #include <sys/time.h> |
41 | #include <sys/mount.h> | | 41 | #include <sys/mount.h> |
42 | #include <ctype.h> | | 42 | #include <ctype.h> |
43 | #include <fcntl.h> | | 43 | #include <fcntl.h> |
44 | #include <grp.h> | | 44 | #include <grp.h> |
45 | #include <histedit.h> | | 45 | #include <histedit.h> |
46 | #include <limits.h> | | 46 | #include <limits.h> |
47 | #include <pwd.h> | | 47 | #include <pwd.h> |
| @@ -127,27 +127,27 @@ struct ufs2_dinode ufs2_zino; | | | @@ -127,27 +127,27 @@ struct ufs2_dinode ufs2_zino; |
127 | struct wrinfo { | | 127 | struct wrinfo { |
128 | off_t size; | | 128 | off_t size; |
129 | off_t written_size; | | 129 | off_t written_size; |
130 | int fd; | | 130 | int fd; |
131 | }; | | 131 | }; |
132 | | | 132 | |
133 | __dead static void usage(void); | | 133 | __dead static void usage(void); |
134 | static int cmdloop(void); | | 134 | static int cmdloop(void); |
135 | static char *prompt(EditLine *); | | 135 | static char *prompt(EditLine *); |
136 | static int scannames(struct inodesc *); | | 136 | static int scannames(struct inodesc *); |
137 | static int dolookup(char *); | | 137 | static int dolookup(char *); |
138 | static int chinumfunc(struct inodesc *); | | 138 | static int chinumfunc(struct inodesc *); |
139 | static int chnamefunc(struct inodesc *); | | 139 | static int chnamefunc(struct inodesc *); |
140 | static int dotime(char *, int32_t *, int32_t *); | | 140 | static int dotime(char *, int64_t *, int32_t *); |
141 | static void print_blks32(int32_t *buf, int size, uint64_t *blknum, struct wrinfo *wrp); | | 141 | static void print_blks32(int32_t *buf, int size, uint64_t *blknum, struct wrinfo *wrp); |
142 | static void print_blks64(int64_t *buf, int size, uint64_t *blknum, struct wrinfo *wrp); | | 142 | static void print_blks64(int64_t *buf, int size, uint64_t *blknum, struct wrinfo *wrp); |
143 | static void print_indirblks32(uint32_t blk, int ind_level, | | 143 | static void print_indirblks32(uint32_t blk, int ind_level, |
144 | uint64_t *blknum, struct wrinfo *wrp); | | 144 | uint64_t *blknum, struct wrinfo *wrp); |
145 | static void print_indirblks64(uint64_t blk, int ind_level, | | 145 | static void print_indirblks64(uint64_t blk, int ind_level, |
146 | uint64_t *blknum, struct wrinfo *wrp); | | 146 | uint64_t *blknum, struct wrinfo *wrp); |
147 | static int compare_blk32(uint32_t *, uint32_t); | | 147 | static int compare_blk32(uint32_t *, uint32_t); |
148 | static int compare_blk64(uint64_t *, uint64_t); | | 148 | static int compare_blk64(uint64_t *, uint64_t); |
149 | static int founddatablk(uint64_t); | | 149 | static int founddatablk(uint64_t); |
150 | static int find_blks32(uint32_t *buf, int size, uint32_t *blknum); | | 150 | static int find_blks32(uint32_t *buf, int size, uint32_t *blknum); |
151 | static int find_blks64(uint64_t *buf, int size, uint64_t *blknum); | | 151 | static int find_blks64(uint64_t *buf, int size, uint64_t *blknum); |
152 | static int find_indirblks32(uint32_t blk, int ind_level, | | 152 | static int find_indirblks32(uint32_t blk, int ind_level, |
153 | uint32_t *blknum); | | 153 | uint32_t *blknum); |
| @@ -232,26 +232,27 @@ CMDFUNC(findblk); /* find block */ | | | @@ -232,26 +232,27 @@ CMDFUNC(findblk); /* find block */ |
232 | CMDFUNC(rm); /* remove name */ | | 232 | CMDFUNC(rm); /* remove name */ |
233 | CMDFUNC(ln); /* add name */ | | 233 | CMDFUNC(ln); /* add name */ |
234 | CMDFUNC(newtype); /* change type */ | | 234 | CMDFUNC(newtype); /* change type */ |
235 | CMDFUNC(chmode); /* change mode */ | | 235 | CMDFUNC(chmode); /* change mode */ |
236 | CMDFUNC(chlen); /* change length */ | | 236 | CMDFUNC(chlen); /* change length */ |
237 | CMDFUNC(chaflags); /* change flags */ | | 237 | CMDFUNC(chaflags); /* change flags */ |
238 | CMDFUNC(chgen); /* change generation */ | | 238 | CMDFUNC(chgen); /* change generation */ |
239 | CMDFUNC(chowner); /* change owner */ | | 239 | CMDFUNC(chowner); /* change owner */ |
240 | CMDFUNC(chgroup); /* Change group */ | | 240 | CMDFUNC(chgroup); /* Change group */ |
241 | CMDFUNC(back); /* pop back to last ino */ | | 241 | CMDFUNC(back); /* pop back to last ino */ |
242 | CMDFUNC(chmtime); /* Change mtime */ | | 242 | CMDFUNC(chmtime); /* Change mtime */ |
243 | CMDFUNC(chctime); /* Change ctime */ | | 243 | CMDFUNC(chctime); /* Change ctime */ |
244 | CMDFUNC(chatime); /* Change atime */ | | 244 | CMDFUNC(chatime); /* Change atime */ |
| | | 245 | CMDFUNC(chbirthtime); /* Change birthtime */ |
245 | CMDFUNC(chinum); /* Change inode # of dirent */ | | 246 | CMDFUNC(chinum); /* Change inode # of dirent */ |
246 | CMDFUNC(chname); /* Change dirname of dirent */ | | 247 | CMDFUNC(chname); /* Change dirname of dirent */ |
247 | | | 248 | |
248 | static struct cmdtable cmds[] = { | | 249 | static struct cmdtable cmds[] = { |
249 | {"help", "Print out help", 1, 1, helpfn}, | | 250 | {"help", "Print out help", 1, 1, helpfn}, |
250 | {"?", "Print out help", 1, 1, helpfn}, | | 251 | {"?", "Print out help", 1, 1, helpfn}, |
251 | {"inode", "Set active inode to INUM", 2, 2, focus}, | | 252 | {"inode", "Set active inode to INUM", 2, 2, focus}, |
252 | {"clri", "Clear inode INUM", 2, 2, zapi}, | | 253 | {"clri", "Clear inode INUM", 2, 2, zapi}, |
253 | {"lookup", "Set active inode by looking up NAME", 2, 2, focusname}, | | 254 | {"lookup", "Set active inode by looking up NAME", 2, 2, focusname}, |
254 | {"cd", "Set active inode by looking up NAME", 2, 2, focusname}, | | 255 | {"cd", "Set active inode by looking up NAME", 2, 2, focusname}, |
255 | {"back", "Go to previous active inode", 1, 1, back}, | | 256 | {"back", "Go to previous active inode", 1, 1, back}, |
256 | {"active", "Print active inode", 1, 1, active}, | | 257 | {"active", "Print active inode", 1, 1, active}, |
257 | {"print", "Print active inode", 1, 1, active}, | | 258 | {"print", "Print active inode", 1, 1, active}, |
| @@ -268,26 +269,28 @@ static struct cmdtable cmds[] = { | | | @@ -268,26 +269,28 @@ static struct cmdtable cmds[] = { |
268 | {"chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum}, | | 269 | {"chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum}, |
269 | {"chname", "Change dir entry number INDEX to NAME", 3, 3, chname}, | | 270 | {"chname", "Change dir entry number INDEX to NAME", 3, 3, chname}, |
270 | {"chtype", "Change type of current inode to TYPE", 2, 2, newtype}, | | 271 | {"chtype", "Change type of current inode to TYPE", 2, 2, newtype}, |
271 | {"chmod", "Change mode of current inode to MODE", 2, 2, chmode}, | | 272 | {"chmod", "Change mode of current inode to MODE", 2, 2, chmode}, |
272 | {"chown", "Change owner of current inode to OWNER", 2, 2, chowner}, | | 273 | {"chown", "Change owner of current inode to OWNER", 2, 2, chowner}, |
273 | {"chlen", "Change length of current inode to LENGTH", 2, 2, chlen}, | | 274 | {"chlen", "Change length of current inode to LENGTH", 2, 2, chlen}, |
274 | {"chgrp", "Change group of current inode to GROUP", 2, 2, chgroup}, | | 275 | {"chgrp", "Change group of current inode to GROUP", 2, 2, chgroup}, |
275 | {"chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags}, | | 276 | {"chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags}, |
276 | {"chgen", "Change generation number of current inode to GEN", 2, 2, | | 277 | {"chgen", "Change generation number of current inode to GEN", 2, 2, |
277 | chgen}, | | 278 | chgen}, |
278 | {"mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime}, | | 279 | {"mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime}, |
279 | {"ctime", "Change ctime of current inode to CTIME", 2, 2, chctime}, | | 280 | {"ctime", "Change ctime of current inode to CTIME", 2, 2, chctime}, |
280 | {"atime", "Change atime of current inode to ATIME", 2, 2, chatime}, | | 281 | {"atime", "Change atime of current inode to ATIME", 2, 2, chatime}, |
| | | 282 | {"birthtime", "Change atime of current inode to BIRTHTIME", 2, 2, |
| | | 283 | chbirthtime}, |
281 | {"quit", "Exit", 1, 1, quit}, | | 284 | {"quit", "Exit", 1, 1, quit}, |
282 | {"q", "Exit", 1, 1, quit}, | | 285 | {"q", "Exit", 1, 1, quit}, |
283 | {"exit", "Exit", 1, 1, quit}, | | 286 | {"exit", "Exit", 1, 1, quit}, |
284 | { .cmd = NULL}, | | 287 | { .cmd = NULL}, |
285 | }; | | 288 | }; |
286 | | | 289 | |
287 | static int | | 290 | static int |
288 | helpfn(int argc, char *argv[]) | | 291 | helpfn(int argc, char *argv[]) |
289 | { | | 292 | { |
290 | struct cmdtable *cmdtp; | | 293 | struct cmdtable *cmdtp; |
291 | | | 294 | |
292 | printf("Commands are:\n%-10s %5s %5s %s\n", | | 295 | printf("Commands are:\n%-10s %5s %5s %s\n", |
293 | "command", "min argc", "max argc", "what"); | | 296 | "command", "min argc", "max argc", "what"); |
| @@ -1347,31 +1350,31 @@ CMDFUNC(chgroup) | | | @@ -1347,31 +1350,31 @@ CMDFUNC(chgroup) |
1347 | return 1; | | 1350 | return 1; |
1348 | } | | 1351 | } |
1349 | } | | 1352 | } |
1350 | if (!is_ufs2 && sblock->fs_old_inodefmt < FS_44INODEFMT) | | 1353 | if (!is_ufs2 && sblock->fs_old_inodefmt < FS_44INODEFMT) |
1351 | curinode->dp1.di_ogid = iswap32(gid); | | 1354 | curinode->dp1.di_ogid = iswap32(gid); |
1352 | else | | 1355 | else |
1353 | DIP_SET(curinode, gid, iswap32(gid)); | | 1356 | DIP_SET(curinode, gid, iswap32(gid)); |
1354 | inodirty(); | | 1357 | inodirty(); |
1355 | printactive(); | | 1358 | printactive(); |
1356 | return 0; | | 1359 | return 0; |
1357 | } | | 1360 | } |
1358 | | | 1361 | |
1359 | static int | | 1362 | static int |
1360 | dotime(char *name, int32_t *rsec, int32_t *rnsec) | | 1363 | dotime(char *name, int64_t *rsec, int32_t *rnsec) |
1361 | { | | 1364 | { |
1362 | char *p, *val; | | 1365 | char *p, *val; |
1363 | struct tm t; | | 1366 | struct tm t; |
1364 | int32_t sec; | | 1367 | int64_t sec; |
1365 | int32_t nsec; | | 1368 | int32_t nsec; |
1366 | p = strchr(name, '.'); | | 1369 | p = strchr(name, '.'); |
1367 | if (p) { | | 1370 | if (p) { |
1368 | *p = '\0'; | | 1371 | *p = '\0'; |
1369 | nsec = strtoul(++p, &val, 0); | | 1372 | nsec = strtoul(++p, &val, 0); |
1370 | if (val == p || *val != '\0' || nsec >= 1000000000 || nsec < 0) { | | 1373 | if (val == p || *val != '\0' || nsec >= 1000000000 || nsec < 0) { |
1371 | warnx("invalid nanoseconds"); | | 1374 | warnx("invalid nanoseconds"); |
1372 | goto badformat; | | 1375 | goto badformat; |
1373 | } | | 1376 | } |
1374 | } else | | 1377 | } else |
1375 | nsec = 0; | | 1378 | nsec = 0; |
1376 | if (strlen(name) != 14) { | | 1379 | if (strlen(name) != 14) { |
1377 | badformat: | | 1380 | badformat: |
| @@ -1395,56 +1398,78 @@ badformat: | | | @@ -1395,56 +1398,78 @@ badformat: |
1395 | t.tm_hour = VAL(); | | 1398 | t.tm_hour = VAL(); |
1396 | t.tm_hour = VAL() + t.tm_hour * 10; | | 1399 | t.tm_hour = VAL() + t.tm_hour * 10; |
1397 | t.tm_min = VAL(); | | 1400 | t.tm_min = VAL(); |
1398 | t.tm_min = VAL() + t.tm_min * 10; | | 1401 | t.tm_min = VAL() + t.tm_min * 10; |
1399 | t.tm_sec = VAL(); | | 1402 | t.tm_sec = VAL(); |
1400 | t.tm_sec = VAL() + t.tm_sec * 10; | | 1403 | t.tm_sec = VAL() + t.tm_sec * 10; |
1401 | t.tm_isdst = -1; | | 1404 | t.tm_isdst = -1; |
1402 | | | 1405 | |
1403 | sec = mktime(&t); | | 1406 | sec = mktime(&t); |
1404 | if (sec == -1) { | | 1407 | if (sec == -1) { |
1405 | warnx("date/time out of range"); | | 1408 | warnx("date/time out of range"); |
1406 | return 1; | | 1409 | return 1; |
1407 | } | | 1410 | } |
1408 | *rsec = iswap32(sec); | | 1411 | *rsec = iswap64(sec); |
1409 | *rnsec = iswap32(nsec); | | 1412 | *rnsec = iswap32(nsec); |
1410 | return 0; | | 1413 | return 0; |
1411 | } | | 1414 | } |
1412 | | | 1415 | |
1413 | CMDFUNC(chmtime) | | 1416 | CMDFUNC(chmtime) |
1414 | { | | 1417 | { |
1415 | int32_t rsec, nsec; | | 1418 | int64_t rsec; |
| | | 1419 | int32_t nsec; |
1416 | | | 1420 | |
1417 | if (dotime(argv[1], &rsec, &nsec)) | | 1421 | if (dotime(argv[1], &rsec, &nsec)) |
1418 | return 1; | | 1422 | return 1; |
1419 | DIP_SET(curinode, mtime, rsec); | | 1423 | DIP_SET(curinode, mtime, rsec); |
1420 | DIP_SET(curinode, mtimensec, nsec); | | 1424 | DIP_SET(curinode, mtimensec, nsec); |
1421 | inodirty(); | | 1425 | inodirty(); |
1422 | printactive(); | | 1426 | printactive(); |
1423 | return 0; | | 1427 | return 0; |
1424 | } | | 1428 | } |
1425 | | | 1429 | |
1426 | CMDFUNC(chatime) | | 1430 | CMDFUNC(chatime) |
1427 | { | | 1431 | { |
1428 | int32_t rsec, nsec; | | 1432 | int64_t rsec; |
| | | 1433 | int32_t nsec; |
1429 | | | 1434 | |
1430 | if (dotime(argv[1], &rsec, &nsec)) | | 1435 | if (dotime(argv[1], &rsec, &nsec)) |
1431 | return 1; | | 1436 | return 1; |
1432 | DIP_SET(curinode, atime, rsec); | | 1437 | DIP_SET(curinode, atime, rsec); |
1433 | DIP_SET(curinode, atimensec, nsec); | | 1438 | DIP_SET(curinode, atimensec, nsec); |
1434 | inodirty(); | | 1439 | inodirty(); |
1435 | printactive(); | | 1440 | printactive(); |
1436 | return 0; | | 1441 | return 0; |
1437 | } | | 1442 | } |
1438 | | | 1443 | |
1439 | CMDFUNC(chctime) | | 1444 | CMDFUNC(chctime) |
1440 | { | | 1445 | { |
1441 | int32_t rsec, nsec; | | 1446 | int64_t rsec; |
| | | 1447 | int32_t nsec; |
1442 | | | 1448 | |
1443 | if (dotime(argv[1], &rsec, &nsec)) | | 1449 | if (dotime(argv[1], &rsec, &nsec)) |
1444 | return 1; | | 1450 | return 1; |
1445 | DIP_SET(curinode, ctime, rsec); | | 1451 | DIP_SET(curinode, ctime, rsec); |
1446 | DIP_SET(curinode, ctimensec, nsec); | | 1452 | DIP_SET(curinode, ctimensec, nsec); |
1447 | inodirty(); | | 1453 | inodirty(); |
1448 | printactive(); | | 1454 | printactive(); |
1449 | return 0; | | 1455 | return 0; |
1450 | } | | 1456 | } |
| | | 1457 | |
| | | 1458 | CMDFUNC(chbirthtime) |
| | | 1459 | { |
| | | 1460 | int64_t rsec; |
| | | 1461 | int32_t nsec; |
| | | 1462 | |
| | | 1463 | if (!is_ufs2) { |
| | | 1464 | warnx("birthtime can only be set in ufs2"); |
| | | 1465 | return 1; |
| | | 1466 | } |
| | | 1467 | |
| | | 1468 | if (dotime(argv[1], &rsec, &nsec)) |
| | | 1469 | return 1; |
| | | 1470 | curinode->dp2.di_birthtime = rsec; |
| | | 1471 | curinode->dp2.di_birthnsec = nsec; |
| | | 1472 | inodirty(); |
| | | 1473 | printactive(); |
| | | 1474 | return 0; |
| | | 1475 | } |