Thu Jun 9 21:23:30 2011 UTC ()
fix compilation.


(christos)
diff -r1.16 -r1.17 src/sbin/fsck/fsutil.h
diff -r1.22 -r1.23 src/sbin/fsck_msdos/main.c
diff -r1.40 -r1.41 src/sbin/fsdb/fsdb.c

cvs diff -r1.16 -r1.17 src/sbin/fsck/fsutil.h (switch to unified diff)

--- src/sbin/fsck/fsutil.h 2011/06/09 19:57:50 1.16
+++ src/sbin/fsck/fsutil.h 2011/06/09 21:23:29 1.17
@@ -1,64 +1,65 @@ @@ -1,64 +1,65 @@
1/* $NetBSD: fsutil.h,v 1.16 2011/06/09 19:57:50 christos Exp $ */ 1/* $NetBSD: fsutil.h,v 1.17 2011/06/09 21:23:29 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996 Christos Zoulas. All rights reserved. 4 * Copyright (c) 1996 Christos Zoulas. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27#include <stdarg.h> 27#include <stdarg.h>
 28#include <signal.h>
28 29
29void errexit(const char *, ...) 30void errexit(const char *, ...)
30 __attribute__((__noreturn__,__format__(__printf__,1,2)));  31 __attribute__((__noreturn__,__format__(__printf__,1,2)));
31void pfatal(const char *, ...) 32void pfatal(const char *, ...)
32 __attribute__((__format__(__printf__,1,2)));  33 __attribute__((__format__(__printf__,1,2)));
33void pwarn(const char *, ...) 34void pwarn(const char *, ...)
34 __attribute__((__format__(__printf__,1,2)));  35 __attribute__((__format__(__printf__,1,2)));
35void perr(const char *, ...) 36void perr(const char *, ...)
36 __attribute__((__format__(__printf__,1,2)));  37 __attribute__((__format__(__printf__,1,2)));
37void panic(const char *, ...) 38void panic(const char *, ...)
38 __attribute__((__noreturn__,__format__(__printf__,1,2)));  39 __attribute__((__noreturn__,__format__(__printf__,1,2)));
39void vmsg(int, const char *, va_list) 40void vmsg(int, const char *, va_list)
40 __attribute__((__format__(__printf__,2,0))); 41 __attribute__((__format__(__printf__,2,0)));
41const char *rawname(const char *); 42const char *rawname(const char *);
42const char *unrawname(const char *); 43const char *unrawname(const char *);
43const char *blockcheck(const char *); 44const char *blockcheck(const char *);
44const char *cdevname(void); 45const char *cdevname(void);
45void setcdevname(const char *, int); 46void setcdevname(const char *, int);
46int hotroot(void); 47int hotroot(void);
47const char *print_mtime(time_t); 48const char *print_mtime(time_t);
48 49
49#define CHECK_PREEN 1 50#define CHECK_PREEN 1
50#define CHECK_VERBOSE 2 51#define CHECK_VERBOSE 2
51#define CHECK_DEBUG 4 52#define CHECK_DEBUG 4
52#define CHECK_FORCE 8 53#define CHECK_FORCE 8
53#define CHECK_PROGRESS 16 54#define CHECK_PROGRESS 16
54#define CHECK_NOFIX 32 55#define CHECK_NOFIX 32
55 56
56struct fstab; 57struct fstab;
57int checkfstab(int, int, void *(*)(struct fstab *),  58int checkfstab(int, int, void *(*)(struct fstab *),
58 int (*) (const char *, const char *, const char *, void *, pid_t *)); 59 int (*) (const char *, const char *, const char *, void *, pid_t *));
59 60
60void (*ckfinish)(int); 61void (*ckfinish)(int);
61volatile sig_atomic_t returntosingle; 62volatile sig_atomic_t returntosingle;
62void catch(int); 63void catch(int);
63void catchquit(int); 64void catchquit(int);
64void voidquit(int); 65void voidquit(int);

cvs diff -r1.22 -r1.23 src/sbin/fsck_msdos/main.c (switch to unified diff)

--- src/sbin/fsck_msdos/main.c 2010/04/11 08:23:52 1.22
+++ src/sbin/fsck_msdos/main.c 2011/06/09 21:23:29 1.23
@@ -1,184 +1,178 @@ @@ -1,184 +1,178 @@
1/* $NetBSD: main.c,v 1.22 2010/04/11 08:23:52 hannken Exp $ */ 1/* $NetBSD: main.c,v 1.23 2011/06/09 21:23:29 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (C) 1995 Wolfgang Solfrank 4 * Copyright (C) 1995 Wolfgang Solfrank
5 * Copyright (c) 1995 Martin Husemann 5 * Copyright (c) 1995 Martin Husemann
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30#ifndef lint 30#ifndef lint
31__RCSID("$NetBSD: main.c,v 1.22 2010/04/11 08:23:52 hannken Exp $"); 31__RCSID("$NetBSD: main.c,v 1.23 2011/06/09 21:23:29 christos Exp $");
32#endif /* not lint */ 32#endif /* not lint */
33 33
34#include <stdlib.h> 34#include <stdlib.h>
35#include <string.h> 35#include <string.h>
36#include <stdio.h> 36#include <stdio.h>
37#include <unistd.h> 37#include <unistd.h>
38#include <err.h> 38#include <err.h>
39#include <errno.h> 39#include <errno.h>
40#include <stdarg.h> 40#include <stdarg.h>
41#include <signal.h> 41#include <signal.h>
42 42
43#include "fsutil.h" 43#include "fsutil.h"
44#include "snapshot.h" 44#include "snapshot.h"
45#include "ext.h" 45#include "ext.h"
46#include "exitvalues.h" 46#include "exitvalues.h"
47 47
48int alwaysno; /* assume "no" for all questions */ 48int alwaysno; /* assume "no" for all questions */
49int alwaysyes; /* assume "yes" for all questions */ 49int alwaysyes; /* assume "yes" for all questions */
50int preen; /* set when preening */ 50int preen; /* set when preening */
51int rdonly; /* device is opened read only (supersedes above) */ 51int rdonly; /* device is opened read only (supersedes above) */
52 52
53static void usage(void) __dead; 53static void usage(void) __dead;
54 54
55static void 55static void
56usage(void) 56usage(void)
57{ 57{
58 (void)fprintf(stderr, 58 (void)fprintf(stderr,
59 "Usage: %s [-fnpy] [-x snap_backup] filesystem ... \n", 59 "Usage: %s [-fnpy] [-x snap_backup] filesystem ... \n",
60 getprogname()); 60 getprogname());
61 exit(FSCK_EXIT_USAGE); 61 exit(FSCK_EXIT_USAGE);
62} 62}
63 63
64static void 
65catch(int n) 
66{ 
67 exit(FSCK_EXIT_SIGNALLED); 
68} 
69 
70int 64int
71main(int argc, char **argv) 65main(int argc, char **argv)
72{ 66{
73 int ret = FSCK_EXIT_OK, erg; 67 int ret = FSCK_EXIT_OK, erg;
74 int ch, snapfd; 68 int ch, snapfd;
75 char *snap_backup = NULL, *snap_dev; 69 char *snap_backup = NULL, *snap_dev;
76 70
77 while ((ch = getopt(argc, argv, "pPqynfx:")) != -1) { 71 while ((ch = getopt(argc, argv, "pPqynfx:")) != -1) {
78 switch (ch) { 72 switch (ch) {
79 case 'f': 73 case 'f':
80 /* 74 /*
81 * We are always forced, since we don't 75 * We are always forced, since we don't
82 * have a clean flag 76 * have a clean flag
83 */ 77 */
84 break; 78 break;
85 case 'n': 79 case 'n':
86 alwaysno = 1; 80 alwaysno = 1;
87 alwaysyes = preen = 0; 81 alwaysyes = preen = 0;
88 break; 82 break;
89 case 'y': 83 case 'y':
90 alwaysyes = 1; 84 alwaysyes = 1;
91 alwaysno = preen = 0; 85 alwaysno = preen = 0;
92 break; 86 break;
93 87
94 case 'p': 88 case 'p':
95 preen = 1; 89 preen = 1;
96 alwaysyes = alwaysno = 0; 90 alwaysyes = alwaysno = 0;
97 break; 91 break;
98 92
99 case 'P': /* Progress meter not implemented. */ 93 case 'P': /* Progress meter not implemented. */
100 break; 94 break;
101 95
102 case 'q': /* Quiet not implemented. */ 96 case 'q': /* Quiet not implemented. */
103 break; 97 break;
104 98
105 case 'x': 99 case 'x':
106 snap_backup = optarg; 100 snap_backup = optarg;
107 break; 101 break;
108 102
109 default: 103 default:
110 usage(); 104 usage();
111 break; 105 break;
112 } 106 }
113 } 107 }
114 if (snap_backup != NULL && (!alwaysno || alwaysyes)) { 108 if (snap_backup != NULL && (!alwaysno || alwaysyes)) {
115 warnx("Cannot use -x without -n\n"); 109 warnx("Cannot use -x without -n\n");
116 snap_backup = NULL; 110 snap_backup = NULL;
117 } 111 }
118 argc -= optind; 112 argc -= optind;
119 argv += optind; 113 argv += optind;
120 114
121 if (!argc) 115 if (!argc)
122 usage(); 116 usage();
123 117
124 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 118 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
125 (void) signal(SIGINT, catch); 119 (void) signal(SIGINT, catch);
126 if (preen) 120 if (preen)
127 (void) signal(SIGQUIT, catch); 121 (void) signal(SIGQUIT, catch);
128 122
129 while (--argc >= 0) { 123 while (--argc >= 0) {
130 setcdevname(*argv, preen); 124 setcdevname(*argv, preen);
131 if (snap_backup != NULL) { 125 if (snap_backup != NULL) {
132 snapfd = snap_open(*argv, snap_backup, NULL, &snap_dev); 126 snapfd = snap_open(*argv, snap_backup, NULL, &snap_dev);
133 if (snapfd < 0) { 127 if (snapfd < 0) {
134 warn("can't take snapshot of %s", *argv); 128 warn("can't take snapshot of %s", *argv);
135 erg = checkfilesys(*argv); 129 erg = checkfilesys(*argv);
136 } else { 130 } else {
137 erg = checkfilesys(snap_dev); 131 erg = checkfilesys(snap_dev);
138 close(snapfd); 132 close(snapfd);
139 } 133 }
140 argv++; 134 argv++;
141 } else 135 } else
142 erg = checkfilesys(*argv++); 136 erg = checkfilesys(*argv++);
143 if (erg > ret) 137 if (erg > ret)
144 ret = erg; 138 ret = erg;
145 } 139 }
146 140
147 return ret; 141 return ret;
148} 142}
149 143
150 144
151/*VARARGS*/ 145/*VARARGS*/
152int 146int
153ask(int def, const char *fmt, ...) 147ask(int def, const char *fmt, ...)
154{ 148{
155 va_list ap; 149 va_list ap;
156 150
157 char prompt[256]; 151 char prompt[256];
158 int c; 152 int c;
159 153
160 if (preen) { 154 if (preen) {
161 if (rdonly) 155 if (rdonly)
162 def = 0; 156 def = 0;
163 if (def) 157 if (def)
164 printf("FIXED\n"); 158 printf("FIXED\n");
165 return def; 159 return def;
166 } 160 }
167 161
168 va_start(ap, fmt); 162 va_start(ap, fmt);
169 vsnprintf(prompt, sizeof(prompt), fmt, ap); 163 vsnprintf(prompt, sizeof(prompt), fmt, ap);
170 va_end(ap); 164 va_end(ap);
171 if (alwaysyes || rdonly) { 165 if (alwaysyes || rdonly) {
172 printf("%s? %s\n", prompt, rdonly ? "no" : "yes"); 166 printf("%s? %s\n", prompt, rdonly ? "no" : "yes");
173 return !rdonly; 167 return !rdonly;
174 } 168 }
175 do { 169 do {
176 printf("%s? [yn] ", prompt); 170 printf("%s? [yn] ", prompt);
177 fflush(stdout); 171 fflush(stdout);
178 c = getchar(); 172 c = getchar();
179 while (c != '\n' && getchar() != '\n') 173 while (c != '\n' && getchar() != '\n')
180 if (feof(stdin)) 174 if (feof(stdin))
181 return 0; 175 return 0;
182 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N'); 176 } while (c != 'y' && c != 'Y' && c != 'n' && c != 'N');
183 return c == 'y' || c == 'Y'; 177 return c == 'y' || c == 'Y';
184} 178}

cvs diff -r1.40 -r1.41 src/sbin/fsdb/fsdb.c (switch to unified diff)

--- src/sbin/fsdb/fsdb.c 2011/06/09 19:57:53 1.40
+++ src/sbin/fsdb/fsdb.c 2011/06/09 21:23:30 1.41
@@ -1,1141 +1,1141 @@ @@ -1,1141 +1,1141 @@
1/* $NetBSD: fsdb.c,v 1.40 2011/06/09 19:57:53 christos Exp $ */ 1/* $NetBSD: fsdb.c,v 1.41 2011/06/09 21:23:30 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 4 * Copyright (c) 1996 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
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.40 2011/06/09 19:57:53 christos Exp $"); 34__RCSID("$NetBSD: fsdb.c,v 1.41 2011/06/09 21:23:30 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>
48#include <stdio.h> 48#include <stdio.h>
49#include <stdlib.h> 49#include <stdlib.h>
50#include <string.h> 50#include <string.h>
51#include <time.h> 51#include <time.h>
52#include <unistd.h> 52#include <unistd.h>
53#include <err.h> 53#include <err.h>
54 54
55#include <ufs/ufs/dinode.h> 55#include <ufs/ufs/dinode.h>
56#include <ufs/ufs/dir.h> 56#include <ufs/ufs/dir.h>
57#include <ufs/ffs/fs.h> 57#include <ufs/ffs/fs.h>
58#include <ufs/ffs/ffs_extern.h> 58#include <ufs/ffs/ffs_extern.h>
59 59
60#include "fsdb.h" 60#include "fsdb.h"
61#include "fsck.h" 61#include "fsck.h"
62#include "extern.h" 62#include "extern.h"
63 63
64static void usage(void); 64static void usage(void);
65static int cmdloop(void); 65static int cmdloop(void);
66static char *prompt(EditLine *); 66static char *prompt(EditLine *);
67static int scannames(struct inodesc *); 67static int scannames(struct inodesc *);
68static int dolookup(char *); 68static int dolookup(char *);
69static int chinumfunc(struct inodesc *); 69static int chinumfunc(struct inodesc *);
70static int chnamefunc(struct inodesc *); 70static int chnamefunc(struct inodesc *);
71static int dotime(char *, int32_t *, int32_t *); 71static int dotime(char *, int32_t *, int32_t *);
72static void print_blks32(int32_t *buf, int size, uint64_t *blknum); 72static void print_blks32(int32_t *buf, int size, uint64_t *blknum);
73static void print_blks64(int64_t *buf, int size, uint64_t *blknum); 73static void print_blks64(int64_t *buf, int size, uint64_t *blknum);
74static void print_indirblks32(uint32_t blk, int ind_level, 74static void print_indirblks32(uint32_t blk, int ind_level,
75 uint64_t *blknum); 75 uint64_t *blknum);
76static void print_indirblks64(uint64_t blk, int ind_level, 76static void print_indirblks64(uint64_t blk, int ind_level,
77 uint64_t *blknum); 77 uint64_t *blknum);
78static int compare_blk32(uint32_t *, uint32_t); 78static int compare_blk32(uint32_t *, uint32_t);
79static int compare_blk64(uint64_t *, uint64_t); 79static int compare_blk64(uint64_t *, uint64_t);
80static int founddatablk(uint64_t); 80static int founddatablk(uint64_t);
81static int find_blks32(uint32_t *buf, int size, uint32_t *blknum); 81static int find_blks32(uint32_t *buf, int size, uint32_t *blknum);
82static int find_blks64(uint64_t *buf, int size, uint64_t *blknum); 82static int find_blks64(uint64_t *buf, int size, uint64_t *blknum);
83static int find_indirblks32(uint32_t blk, int ind_level, 83static int find_indirblks32(uint32_t blk, int ind_level,
84 uint32_t *blknum); 84 uint32_t *blknum);
85static int find_indirblks64(uint64_t blk, int ind_level, 85static int find_indirblks64(uint64_t blk, int ind_level,
86 uint64_t *blknum); 86 uint64_t *blknum);
87 87
88union dinode *curinode; 88union dinode *curinode;
89ino_t curinum; 89ino_t curinum;
90 90
91static void 91static void
92usage(void) 92usage(void)
93{ 93{
94 errx(1, "usage: %s [-dFn] -f <fsname>", getprogname()); 94 errx(1, "usage: %s [-dFn] -f <fsname>", getprogname());
95} 95}
96/* 96/*
97 * We suck in lots of fsck code, and just pick & choose the stuff we want. 97 * We suck in lots of fsck code, and just pick & choose the stuff we want.
98 * 98 *
99 * fsreadfd is set up to read from the file system, fswritefd to write to 99 * fsreadfd is set up to read from the file system, fswritefd to write to
100 * the file system. 100 * the file system.
101 */ 101 */
102int 102int
103main(int argc, char *argv[]) 103main(int argc, char *argv[])
104{ 104{
105 int ch, rval; 105 int ch, rval;
106 char *fsys = NULL; 106 char *fsys = NULL;
107 107
108 forceimage = 0; 108 forceimage = 0;
109 debug = 0; 109 debug = 0;
110 isappleufs = 0; 110 isappleufs = 0;
111 while ((ch = getopt(argc, argv, "dFf:n")) != -1) { 111 while ((ch = getopt(argc, argv, "dFf:n")) != -1) {
112 switch (ch) { 112 switch (ch) {
113 case 'd': 113 case 'd':
114 debug++; 114 debug++;
115 break; 115 break;
116 case 'F': 116 case 'F':
117 forceimage = 1; 117 forceimage = 1;
118 break; 118 break;
119 case 'f': 119 case 'f':
120 fsys = optarg; 120 fsys = optarg;
121 break; 121 break;
122 case 'n': 122 case 'n':
123 nflag++; 123 nflag++;
124 break; 124 break;
125 default: 125 default:
126 usage(); 126 usage();
127 } 127 }
128 } 128 }
129 if (fsys == NULL) 129 if (fsys == NULL)
130 usage(); 130 usage();
131 endian = 0; 131 endian = 0;
132 if (setup(fsys, fsys) <= 0) 132 if (setup(fsys, fsys) <= 0)
133 errx(1, "cannot set up file system `%s'", fsys); 133 errx(1, "cannot set up file system `%s'", fsys);
134 printf("Editing file system `%s'\nLast Mounted on %s\n", fsys, 134 printf("Editing file system `%s'\nLast Mounted on %s\n", fsys,
135 sblock->fs_fsmnt); 135 sblock->fs_fsmnt);
136 rval = cmdloop(); 136 rval = cmdloop();
137 if (nflag) 137 if (nflag)
138 exit(rval); 138 exit(rval);
139 sblock->fs_clean = 0; /* mark it dirty */ 139 sblock->fs_clean = 0; /* mark it dirty */
140 sbdirty(); 140 sbdirty();
141 markclean = 0; 141 markclean = 0;
142 ckfini(); 142 ckfini(1);
143 printf("*** FILE SYSTEM MARKED DIRTY\n"); 143 printf("*** FILE SYSTEM MARKED DIRTY\n");
144 printf("*** BE SURE TO RUN FSCK TO CLEAN UP ANY DAMAGE\n"); 144 printf("*** BE SURE TO RUN FSCK TO CLEAN UP ANY DAMAGE\n");
145 printf("*** IF IT WAS MOUNTED, RE-MOUNT WITH -u -o reload\n"); 145 printf("*** IF IT WAS MOUNTED, RE-MOUNT WITH -u -o reload\n");
146 exit(rval); 146 exit(rval);
147} 147}
148 148
149#define CMDFUNC(func) static int func (int argc, char *argv[]) 149#define CMDFUNC(func) static int func (int argc, char *argv[])
150#define CMDFUNCSTART(func) static int func(argc, argv) \ 150#define CMDFUNCSTART(func) static int func(argc, argv) \
151 int argc; \ 151 int argc; \
152 char *argv[]; 152 char *argv[];
153 153
154CMDFUNC(helpfn); 154CMDFUNC(helpfn);
155CMDFUNC(focus); /* focus on inode */ 155CMDFUNC(focus); /* focus on inode */
156CMDFUNC(active); /* print active inode */ 156CMDFUNC(active); /* print active inode */
157CMDFUNC(focusname); /* focus by name */ 157CMDFUNC(focusname); /* focus by name */
158CMDFUNC(zapi); /* clear inode */ 158CMDFUNC(zapi); /* clear inode */
159CMDFUNC(uplink); /* incr link */ 159CMDFUNC(uplink); /* incr link */
160CMDFUNC(downlink); /* decr link */ 160CMDFUNC(downlink); /* decr link */
161CMDFUNC(linkcount); /* set link count */ 161CMDFUNC(linkcount); /* set link count */
162CMDFUNC(quit); /* quit */ 162CMDFUNC(quit); /* quit */
163CMDFUNC(ls); /* list directory */ 163CMDFUNC(ls); /* list directory */
164CMDFUNC(blks); /* list blocks */ 164CMDFUNC(blks); /* list blocks */
165CMDFUNC(findblk); /* find block */ 165CMDFUNC(findblk); /* find block */
166CMDFUNC(rm); /* remove name */ 166CMDFUNC(rm); /* remove name */
167CMDFUNC(ln); /* add name */ 167CMDFUNC(ln); /* add name */
168CMDFUNC(newtype); /* change type */ 168CMDFUNC(newtype); /* change type */
169CMDFUNC(chmode); /* change mode */ 169CMDFUNC(chmode); /* change mode */
170CMDFUNC(chlen); /* change length */ 170CMDFUNC(chlen); /* change length */
171CMDFUNC(chaflags); /* change flags */ 171CMDFUNC(chaflags); /* change flags */
172CMDFUNC(chgen); /* change generation */ 172CMDFUNC(chgen); /* change generation */
173CMDFUNC(chowner); /* change owner */ 173CMDFUNC(chowner); /* change owner */
174CMDFUNC(chgroup); /* Change group */ 174CMDFUNC(chgroup); /* Change group */
175CMDFUNC(back); /* pop back to last ino */ 175CMDFUNC(back); /* pop back to last ino */
176CMDFUNC(chmtime); /* Change mtime */ 176CMDFUNC(chmtime); /* Change mtime */
177CMDFUNC(chctime); /* Change ctime */ 177CMDFUNC(chctime); /* Change ctime */
178CMDFUNC(chatime); /* Change atime */ 178CMDFUNC(chatime); /* Change atime */
179CMDFUNC(chinum); /* Change inode # of dirent */ 179CMDFUNC(chinum); /* Change inode # of dirent */
180CMDFUNC(chname); /* Change dirname of dirent */ 180CMDFUNC(chname); /* Change dirname of dirent */
181 181
182static struct cmdtable cmds[] = { 182static struct cmdtable cmds[] = {
183 {"help", "Print out help", 1, 1, helpfn}, 183 {"help", "Print out help", 1, 1, helpfn},
184 {"?", "Print out help", 1, 1, helpfn}, 184 {"?", "Print out help", 1, 1, helpfn},
185 {"inode", "Set active inode to INUM", 2, 2, focus}, 185 {"inode", "Set active inode to INUM", 2, 2, focus},
186 {"clri", "Clear inode INUM", 2, 2, zapi}, 186 {"clri", "Clear inode INUM", 2, 2, zapi},
187 {"lookup", "Set active inode by looking up NAME", 2, 2, focusname}, 187 {"lookup", "Set active inode by looking up NAME", 2, 2, focusname},
188 {"cd", "Set active inode by looking up NAME", 2, 2, focusname}, 188 {"cd", "Set active inode by looking up NAME", 2, 2, focusname},
189 {"back", "Go to previous active inode", 1, 1, back}, 189 {"back", "Go to previous active inode", 1, 1, back},
190 {"active", "Print active inode", 1, 1, active}, 190 {"active", "Print active inode", 1, 1, active},
191 {"print", "Print active inode", 1, 1, active}, 191 {"print", "Print active inode", 1, 1, active},
192 {"uplink", "Increment link count", 1, 1, uplink}, 192 {"uplink", "Increment link count", 1, 1, uplink},
193 {"downlink", "Decrement link count", 1, 1, downlink}, 193 {"downlink", "Decrement link count", 1, 1, downlink},
194 {"linkcount", "Set link count to COUNT", 2, 2, linkcount}, 194 {"linkcount", "Set link count to COUNT", 2, 2, linkcount},
195 {"ls", "List current inode as directory", 1, 1, ls}, 195 {"ls", "List current inode as directory", 1, 1, ls},
196 {"blks", "List current inode's data blocks", 1, 1, blks}, 196 {"blks", "List current inode's data blocks", 1, 1, blks},
197 {"findblk", "Find inode owning disk block(s)", 2, 33, findblk}, 197 {"findblk", "Find inode owning disk block(s)", 2, 33, findblk},
198 {"rm", "Remove NAME from current inode directory", 2, 2, rm}, 198 {"rm", "Remove NAME from current inode directory", 2, 2, rm},
199 {"del", "Remove NAME from current inode directory", 2, 2, rm}, 199 {"del", "Remove NAME from current inode directory", 2, 2, rm},
200 {"ln", "Hardlink INO into current inode directory as NAME", 3, 3, ln}, 200 {"ln", "Hardlink INO into current inode directory as NAME", 3, 3, ln},
201 {"chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum}, 201 {"chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum},
202 {"chname", "Change dir entry number INDEX to NAME", 3, 3, chname}, 202 {"chname", "Change dir entry number INDEX to NAME", 3, 3, chname},
203 {"chtype", "Change type of current inode to TYPE", 2, 2, newtype}, 203 {"chtype", "Change type of current inode to TYPE", 2, 2, newtype},
204 {"chmod", "Change mode of current inode to MODE", 2, 2, chmode}, 204 {"chmod", "Change mode of current inode to MODE", 2, 2, chmode},
205 {"chown", "Change owner of current inode to OWNER", 2, 2, chowner}, 205 {"chown", "Change owner of current inode to OWNER", 2, 2, chowner},
206 {"chlen", "Change length of current inode to LENGTH", 2, 2, chlen}, 206 {"chlen", "Change length of current inode to LENGTH", 2, 2, chlen},
207 {"chgrp", "Change group of current inode to GROUP", 2, 2, chgroup}, 207 {"chgrp", "Change group of current inode to GROUP", 2, 2, chgroup},
208 {"chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags}, 208 {"chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags},
209 {"chgen", "Change generation number of current inode to GEN", 2, 2, 209 {"chgen", "Change generation number of current inode to GEN", 2, 2,
210 chgen}, 210 chgen},
211 {"mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime}, 211 {"mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime},
212 {"ctime", "Change ctime of current inode to CTIME", 2, 2, chctime}, 212 {"ctime", "Change ctime of current inode to CTIME", 2, 2, chctime},
213 {"atime", "Change atime of current inode to ATIME", 2, 2, chatime}, 213 {"atime", "Change atime of current inode to ATIME", 2, 2, chatime},
214 {"quit", "Exit", 1, 1, quit}, 214 {"quit", "Exit", 1, 1, quit},
215 {"q", "Exit", 1, 1, quit}, 215 {"q", "Exit", 1, 1, quit},
216 {"exit", "Exit", 1, 1, quit}, 216 {"exit", "Exit", 1, 1, quit},
217 { .cmd = NULL}, 217 { .cmd = NULL},
218}; 218};
219 219
220static int 220static int
221helpfn(int argc, char *argv[]) 221helpfn(int argc, char *argv[])
222{ 222{
223 struct cmdtable *cmdtp; 223 struct cmdtable *cmdtp;
224 224
225 printf("Commands are:\n%-10s %5s %5s %s\n", 225 printf("Commands are:\n%-10s %5s %5s %s\n",
226 "command", "min argc", "max argc", "what"); 226 "command", "min argc", "max argc", "what");
227 227
228 for (cmdtp = cmds; cmdtp->cmd; cmdtp++) 228 for (cmdtp = cmds; cmdtp->cmd; cmdtp++)
229 printf("%-10s %5u %5u %s\n", 229 printf("%-10s %5u %5u %s\n",
230 cmdtp->cmd, cmdtp->minargc, cmdtp->maxargc, cmdtp->helptxt); 230 cmdtp->cmd, cmdtp->minargc, cmdtp->maxargc, cmdtp->helptxt);
231 return 0; 231 return 0;
232} 232}
233 233
234static char * 234static char *
235prompt(EditLine *el) 235prompt(EditLine *el)
236{ 236{
237 static char pstring[64]; 237 static char pstring[64];
238 snprintf(pstring, sizeof(pstring), "fsdb (inum: %llu)> ", 238 snprintf(pstring, sizeof(pstring), "fsdb (inum: %llu)> ",
239 (unsigned long long)curinum); 239 (unsigned long long)curinum);
240 return pstring; 240 return pstring;
241} 241}
242 242
243 243
244static int 244static int
245cmdloop(void) 245cmdloop(void)
246{ 246{
247 char *line; 247 char *line;
248 const char *elline; 248 const char *elline;
249 int cmd_argc, rval = 0, known; 249 int cmd_argc, rval = 0, known;
250#define scratch known 250#define scratch known
251 char **cmd_argv; 251 char **cmd_argv;
252 struct cmdtable *cmdp; 252 struct cmdtable *cmdp;
253 History *hist; 253 History *hist;
254 HistEvent he; 254 HistEvent he;
255 EditLine *elptr; 255 EditLine *elptr;
256 256
257 curinode = ginode(ROOTINO); 257 curinode = ginode(ROOTINO);
258 curinum = ROOTINO; 258 curinum = ROOTINO;
259 printactive(); 259 printactive();
260 260
261 hist = history_init(); 261 hist = history_init();
262 history(hist, &he, H_SETSIZE, 100); /* 100 elt history buffer */ 262 history(hist, &he, H_SETSIZE, 100); /* 100 elt history buffer */
263 263
264 elptr = el_init(getprogname(), stdin, stdout, stderr); 264 elptr = el_init(getprogname(), stdin, stdout, stderr);
265 el_set(elptr, EL_EDITOR, "emacs"); 265 el_set(elptr, EL_EDITOR, "emacs");
266 el_set(elptr, EL_PROMPT, prompt); 266 el_set(elptr, EL_PROMPT, prompt);
267 el_set(elptr, EL_HIST, history, hist); 267 el_set(elptr, EL_HIST, history, hist);
268 el_source(elptr, NULL); 268 el_source(elptr, NULL);
269 269
270 while ((elline = el_gets(elptr, &scratch)) != NULL && scratch != 0) { 270 while ((elline = el_gets(elptr, &scratch)) != NULL && scratch != 0) {
271 if (debug) 271 if (debug)
272 printf("command `%s'\n", elline); 272 printf("command `%s'\n", elline);
273 273
274 history(hist, &he, H_ENTER, elline); 274 history(hist, &he, H_ENTER, elline);
275 275
276 line = strdup(elline); 276 line = strdup(elline);
277 cmd_argv = crack(line, &cmd_argc); 277 cmd_argv = crack(line, &cmd_argc);
278 if (cmd_argc) { 278 if (cmd_argc) {
279 /* 279 /*
280 * el_parse returns -1 to signal that it's not been 280 * el_parse returns -1 to signal that it's not been
281 * handled internally. 281 * handled internally.
282 */ 282 */
283 if (el_parse(elptr, cmd_argc, 283 if (el_parse(elptr, cmd_argc,
284 (const char **)cmd_argv) != -1) 284 (const char **)cmd_argv) != -1)
285 continue; 285 continue;
286 known = 0; 286 known = 0;
287 for (cmdp = cmds; cmdp->cmd; cmdp++) { 287 for (cmdp = cmds; cmdp->cmd; cmdp++) {
288 if (!strcmp(cmdp->cmd, cmd_argv[0])) { 288 if (!strcmp(cmdp->cmd, cmd_argv[0])) {
289 if (cmd_argc >= cmdp->minargc && 289 if (cmd_argc >= cmdp->minargc &&
290 cmd_argc <= cmdp->maxargc) 290 cmd_argc <= cmdp->maxargc)
291 rval = 291 rval =
292 (*cmdp->handler)(cmd_argc, 292 (*cmdp->handler)(cmd_argc,
293 cmd_argv); 293 cmd_argv);
294 else 294 else
295 rval = argcount(cmdp, cmd_argc, 295 rval = argcount(cmdp, cmd_argc,
296 cmd_argv); 296 cmd_argv);
297 known = 1; 297 known = 1;
298 break; 298 break;
299 } 299 }
300 } 300 }
301 if (!known) 301 if (!known)
302 warnx("unknown command `%s'", cmd_argv[0]), 302 warnx("unknown command `%s'", cmd_argv[0]),
303 rval = 1; 303 rval = 1;
304 } else 304 } else
305 rval = 0; 305 rval = 0;
306 free(line); 306 free(line);
307 if (rval < 0) 307 if (rval < 0)
308 return rval; 308 return rval;
309 if (rval) 309 if (rval)
310 warnx("rval was %d", rval); 310 warnx("rval was %d", rval);
311 } 311 }
312 el_end(elptr); 312 el_end(elptr);
313 history_end(hist); 313 history_end(hist);
314 return rval; 314 return rval;
315} 315}
316 316
317static ino_t ocurrent; 317static ino_t ocurrent;
318 318
319#define GETINUM(ac,inum) inum = strtoull(argv[ac], &cp, 0); \ 319#define GETINUM(ac,inum) inum = strtoull(argv[ac], &cp, 0); \
320 if (inum < ROOTINO || inum >= maxino || cp == argv[ac] || *cp != '\0' ) { \ 320 if (inum < ROOTINO || inum >= maxino || cp == argv[ac] || *cp != '\0' ) { \
321 printf("inode %llu out of range; range is [%llu,%llu]\n", \ 321 printf("inode %llu out of range; range is [%llu,%llu]\n", \
322 (unsigned long long)inum, (unsigned long long)ROOTINO, \ 322 (unsigned long long)inum, (unsigned long long)ROOTINO, \
323 (unsigned long long)maxino); \ 323 (unsigned long long)maxino); \
324 return 1; \ 324 return 1; \
325 } 325 }
326 326
327/* 327/*
328 * Focus on given inode number 328 * Focus on given inode number
329 */ 329 */
330CMDFUNCSTART(focus) 330CMDFUNCSTART(focus)
331{ 331{
332 ino_t inum; 332 ino_t inum;
333 char *cp; 333 char *cp;
334 334
335 GETINUM(1, inum); 335 GETINUM(1, inum);
336 curinode = ginode(inum); 336 curinode = ginode(inum);
337 ocurrent = curinum; 337 ocurrent = curinum;
338 curinum = inum; 338 curinum = inum;
339 printactive(); 339 printactive();
340 return 0; 340 return 0;
341} 341}
342 342
343CMDFUNCSTART(back) 343CMDFUNCSTART(back)
344{ 344{
345 curinum = ocurrent; 345 curinum = ocurrent;
346 curinode = ginode(curinum); 346 curinode = ginode(curinum);
347 printactive(); 347 printactive();
348 return 0; 348 return 0;
349} 349}
350 350
351CMDFUNCSTART(zapi) 351CMDFUNCSTART(zapi)
352{ 352{
353 ino_t inum; 353 ino_t inum;
354 union dinode *dp; 354 union dinode *dp;
355 char *cp; 355 char *cp;
356 356
357 GETINUM(1, inum); 357 GETINUM(1, inum);
358 dp = ginode(inum); 358 dp = ginode(inum);
359 clearinode(dp); 359 clearinode(dp);
360 inodirty(); 360 inodirty();
361 if (curinode) /* re-set after potential change */ 361 if (curinode) /* re-set after potential change */
362 curinode = ginode(curinum); 362 curinode = ginode(curinum);
363 return 0; 363 return 0;
364} 364}
365 365
366CMDFUNCSTART(active) 366CMDFUNCSTART(active)
367{ 367{
368 printactive(); 368 printactive();
369 return 0; 369 return 0;
370} 370}
371 371
372CMDFUNCSTART(quit) 372CMDFUNCSTART(quit)
373{ 373{
374 return -1; 374 return -1;
375} 375}
376 376
377CMDFUNCSTART(uplink) 377CMDFUNCSTART(uplink)
378{ 378{
379 int16_t nlink; 379 int16_t nlink;
380 380
381 if (!checkactive()) 381 if (!checkactive())
382 return 1; 382 return 1;
383 nlink = iswap16(DIP(curinode, nlink)); 383 nlink = iswap16(DIP(curinode, nlink));
384 nlink++; 384 nlink++;
385 DIP_SET(curinode, nlink, iswap16(nlink)); 385 DIP_SET(curinode, nlink, iswap16(nlink));
386 printf("inode %llu link count now %d\n", (unsigned long long)curinum, 386 printf("inode %llu link count now %d\n", (unsigned long long)curinum,
387 nlink); 387 nlink);
388 inodirty(); 388 inodirty();
389 return 0; 389 return 0;
390} 390}
391 391
392CMDFUNCSTART(downlink) 392CMDFUNCSTART(downlink)
393{ 393{
394 int16_t nlink; 394 int16_t nlink;
395 395
396 if (!checkactive()) 396 if (!checkactive())
397 return 1; 397 return 1;
398 nlink = iswap16(DIP(curinode, nlink)); 398 nlink = iswap16(DIP(curinode, nlink));
399 nlink--; 399 nlink--;
400 DIP_SET(curinode, nlink, iswap16(nlink)); 400 DIP_SET(curinode, nlink, iswap16(nlink));
401 printf("inode %llu link count now %d\n", (unsigned long long)curinum, 401 printf("inode %llu link count now %d\n", (unsigned long long)curinum,
402 nlink); 402 nlink);
403 inodirty(); 403 inodirty();
404 return 0; 404 return 0;
405} 405}
406 406
407static const char *typename[] = { 407static const char *typename[] = {
408 "unknown", 408 "unknown",
409 "fifo", 409 "fifo",
410 "char special", 410 "char special",
411 "unregistered #3", 411 "unregistered #3",
412 "directory", 412 "directory",
413 "unregistered #5", 413 "unregistered #5",
414 "blk special", 414 "blk special",
415 "unregistered #7", 415 "unregistered #7",
416 "regular", 416 "regular",
417 "unregistered #9", 417 "unregistered #9",
418 "symlink", 418 "symlink",
419 "unregistered #11", 419 "unregistered #11",
420 "socket", 420 "socket",
421 "unregistered #13", 421 "unregistered #13",
422 "whiteout", 422 "whiteout",
423}; 423};
424 424
425static int slot; 425static int slot;
426 426
427static int 427static int
428scannames(struct inodesc *idesc) 428scannames(struct inodesc *idesc)
429{ 429{
430 struct direct *dirp = idesc->id_dirp; 430 struct direct *dirp = idesc->id_dirp;
431 431
432 printf("slot %d ino %d reclen %d: %s, `%.*s'\n", 432 printf("slot %d ino %d reclen %d: %s, `%.*s'\n",
433 slot++, iswap32(dirp->d_ino), iswap16(dirp->d_reclen), 433 slot++, iswap32(dirp->d_ino), iswap16(dirp->d_reclen),
434 typename[dirp->d_type], 434 typename[dirp->d_type],
435 dirp->d_namlen, dirp->d_name); 435 dirp->d_namlen, dirp->d_name);
436 return (KEEPON); 436 return (KEEPON);
437} 437}
438 438
439CMDFUNCSTART(ls) 439CMDFUNCSTART(ls)
440{ 440{
441 struct inodesc idesc; 441 struct inodesc idesc;
442 checkactivedir(); /* let it go on anyway */ 442 checkactivedir(); /* let it go on anyway */
443 443
444 slot = 0; 444 slot = 0;
445 idesc.id_number = curinum; 445 idesc.id_number = curinum;
446 idesc.id_func = scannames; 446 idesc.id_func = scannames;
447 idesc.id_type = DATA; 447 idesc.id_type = DATA;
448 idesc.id_fix = IGNORE; 448 idesc.id_fix = IGNORE;
449 ckinode(curinode, &idesc); 449 ckinode(curinode, &idesc);
450 curinode = ginode(curinum); 450 curinode = ginode(curinum);
451 451
452 return 0; 452 return 0;
453} 453}
454 454
455CMDFUNCSTART(blks) 455CMDFUNCSTART(blks)
456{ 456{
457 uint64_t blkno = 0; 457 uint64_t blkno = 0;
458 int i, type; 458 int i, type;
459 if (!curinode) { 459 if (!curinode) {
460 warnx("no current inode"); 460 warnx("no current inode");
461 return 0; 461 return 0;
462 } 462 }
463 type = iswap16(DIP(curinode, mode)) & IFMT; 463 type = iswap16(DIP(curinode, mode)) & IFMT;
464 if (type != IFDIR && type != IFREG) { 464 if (type != IFDIR && type != IFREG) {
465 warnx("inode %llu not a file or directory", 465 warnx("inode %llu not a file or directory",
466 (unsigned long long)curinum); 466 (unsigned long long)curinum);
467 return 0; 467 return 0;
468 } 468 }
469 if (is_ufs2) { 469 if (is_ufs2) {
470 printf("I=%llu %lld blocks\n", (unsigned long long)curinum, 470 printf("I=%llu %lld blocks\n", (unsigned long long)curinum,
471 (long long)(iswap64(curinode->dp2.di_blocks))); 471 (long long)(iswap64(curinode->dp2.di_blocks)));
472 } else { 472 } else {
473 printf("I=%llu %d blocks\n", (unsigned long long)curinum, 473 printf("I=%llu %d blocks\n", (unsigned long long)curinum,
474 iswap32(curinode->dp1.di_blocks)); 474 iswap32(curinode->dp1.di_blocks));
475 } 475 }
476 printf("Direct blocks:\n"); 476 printf("Direct blocks:\n");
477 if (is_ufs2) 477 if (is_ufs2)
478 print_blks64(curinode->dp2.di_db, NDADDR, &blkno); 478 print_blks64(curinode->dp2.di_db, NDADDR, &blkno);
479 else 479 else
480 print_blks32(curinode->dp1.di_db, NDADDR, &blkno); 480 print_blks32(curinode->dp1.di_db, NDADDR, &blkno);
481 481
482 if (is_ufs2) { 482 if (is_ufs2) {
483 for (i = 0; i < NIADDR; i++) 483 for (i = 0; i < NIADDR; i++)
484 print_indirblks64(iswap64(curinode->dp2.di_ib[i]), i, 484 print_indirblks64(iswap64(curinode->dp2.di_ib[i]), i,
485 &blkno); 485 &blkno);
486 } else { 486 } else {
487 for (i = 0; i < NIADDR; i++) 487 for (i = 0; i < NIADDR; i++)
488 print_indirblks32(iswap32(curinode->dp1.di_ib[i]), i, 488 print_indirblks32(iswap32(curinode->dp1.di_ib[i]), i,
489 &blkno); 489 &blkno);
490 } 490 }
491 return 0; 491 return 0;
492} 492}
493 493
494static int findblk_numtofind; 494static int findblk_numtofind;
495static int wantedblksize; 495static int wantedblksize;
496CMDFUNCSTART(findblk) 496CMDFUNCSTART(findblk)
497{ 497{
498 ino_t inum, inosused; 498 ino_t inum, inosused;
499 uint32_t *wantedblk32 = NULL; 499 uint32_t *wantedblk32 = NULL;
500 uint64_t *wantedblk64 = NULL; 500 uint64_t *wantedblk64 = NULL;
501 struct cg *cgp = cgrp; 501 struct cg *cgp = cgrp;
502 int i, c; 502 int i, c;
503 503
504 ocurrent = curinum; 504 ocurrent = curinum;
505 wantedblksize = (argc - 1); 505 wantedblksize = (argc - 1);
506 if (is_ufs2) { 506 if (is_ufs2) {
507 wantedblk64 = malloc(sizeof(uint64_t) * wantedblksize); 507 wantedblk64 = malloc(sizeof(uint64_t) * wantedblksize);
508 if (wantedblk64 == NULL) { 508 if (wantedblk64 == NULL) {
509 perror("malloc"); 509 perror("malloc");
510 return 1; 510 return 1;
511 } 511 }
512 memset(wantedblk64, 0, sizeof(uint64_t) * wantedblksize); 512 memset(wantedblk64, 0, sizeof(uint64_t) * wantedblksize);
513 for (i = 1; i < argc; i++) 513 for (i = 1; i < argc; i++)
514 wantedblk64[i - 1] = 514 wantedblk64[i - 1] =
515 dbtofsb(sblock, strtoull(argv[i], NULL, 0));  515 dbtofsb(sblock, strtoull(argv[i], NULL, 0));
516 } else { 516 } else {
517 wantedblk32 = malloc(sizeof(uint32_t) * wantedblksize); 517 wantedblk32 = malloc(sizeof(uint32_t) * wantedblksize);
518 if (wantedblk32 == NULL) { 518 if (wantedblk32 == NULL) {
519 perror("malloc"); 519 perror("malloc");
520 return 1; 520 return 1;
521 } 521 }
522 memset(wantedblk32, 0, sizeof(uint32_t) * wantedblksize); 522 memset(wantedblk32, 0, sizeof(uint32_t) * wantedblksize);
523 for (i = 1; i < argc; i++) 523 for (i = 1; i < argc; i++)
524 wantedblk32[i - 1] = 524 wantedblk32[i - 1] =
525 dbtofsb(sblock, strtoull(argv[i], NULL, 0));  525 dbtofsb(sblock, strtoull(argv[i], NULL, 0));
526 } 526 }
527 findblk_numtofind = wantedblksize; 527 findblk_numtofind = wantedblksize;
528 for (c = 0; c < sblock->fs_ncg; c++) { 528 for (c = 0; c < sblock->fs_ncg; c++) {
529 inum = c * sblock->fs_ipg; 529 inum = c * sblock->fs_ipg;
530 getblk(&cgblk, cgtod(sblock, c), sblock->fs_cgsize); 530 getblk(&cgblk, cgtod(sblock, c), sblock->fs_cgsize);
531 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 531 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize);
532 if (needswap) 532 if (needswap)
533 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 533 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock);
534 if (is_ufs2) 534 if (is_ufs2)
535 inosused = cgp->cg_initediblk; 535 inosused = cgp->cg_initediblk;
536 else 536 else
537 inosused = sblock->fs_ipg; 537 inosused = sblock->fs_ipg;
538 for (; inosused > 0; inum++, inosused--) { 538 for (; inosused > 0; inum++, inosused--) {
539 if (inum < ROOTINO) 539 if (inum < ROOTINO)
540 continue; 540 continue;
541 if (is_ufs2 ? compare_blk64(wantedblk64, 541 if (is_ufs2 ? compare_blk64(wantedblk64,
542 ino_to_fsba(sblock, inum)) : 542 ino_to_fsba(sblock, inum)) :
543 compare_blk32(wantedblk32, 543 compare_blk32(wantedblk32,
544 ino_to_fsba(sblock, inum))) { 544 ino_to_fsba(sblock, inum))) {
545 printf("block %llu: inode block (%llu-%llu)\n", 545 printf("block %llu: inode block (%llu-%llu)\n",
546 (unsigned long long)fsbtodb(sblock, 546 (unsigned long long)fsbtodb(sblock,
547 ino_to_fsba(sblock, inum)), 547 ino_to_fsba(sblock, inum)),
548 (unsigned long long) 548 (unsigned long long)
549 (inum / INOPB(sblock)) * INOPB(sblock), 549 (inum / INOPB(sblock)) * INOPB(sblock),
550 (unsigned long long) 550 (unsigned long long)
551 (inum / INOPB(sblock) + 1) * INOPB(sblock)); 551 (inum / INOPB(sblock) + 1) * INOPB(sblock));
552 findblk_numtofind--; 552 findblk_numtofind--;
553 if (findblk_numtofind == 0) 553 if (findblk_numtofind == 0)
554 goto end; 554 goto end;
555 } 555 }
556 curinum = inum; 556 curinum = inum;
557 curinode = ginode(inum); 557 curinode = ginode(inum);
558 switch (iswap16(DIP(curinode, mode)) & IFMT) { 558 switch (iswap16(DIP(curinode, mode)) & IFMT) {
559 case IFDIR: 559 case IFDIR:
560 case IFREG: 560 case IFREG:
561 if (DIP(curinode, blocks) == 0) 561 if (DIP(curinode, blocks) == 0)
562 continue; 562 continue;
563 break; 563 break;
564 case IFLNK: 564 case IFLNK:
565 { 565 {
566 uint64_t size = iswap64(DIP(curinode, size)); 566 uint64_t size = iswap64(DIP(curinode, size));
567 if (size > 0 && 567 if (size > 0 &&
568 size < (uint64_t)sblock->fs_maxsymlinklen && 568 size < (uint64_t)sblock->fs_maxsymlinklen &&
569 DIP(curinode, blocks) == 0) 569 DIP(curinode, blocks) == 0)
570 continue; 570 continue;
571 else 571 else
572 break; 572 break;
573 } 573 }
574 default: 574 default:
575 continue; 575 continue;
576 } 576 }
577 if (is_ufs2 ? 577 if (is_ufs2 ?
578 find_blks64(curinode->dp2.di_db, NDADDR, 578 find_blks64(curinode->dp2.di_db, NDADDR,
579 wantedblk64) :  579 wantedblk64) :
580 find_blks32(curinode->dp1.di_db, NDADDR, 580 find_blks32(curinode->dp1.di_db, NDADDR,
581 wantedblk32)) 581 wantedblk32))
582 goto end; 582 goto end;
583 for (i = 0; i < NIADDR; i++) { 583 for (i = 0; i < NIADDR; i++) {
584 if (is_ufs2 ? 584 if (is_ufs2 ?
585 compare_blk64(wantedblk64, 585 compare_blk64(wantedblk64,
586 iswap64(curinode->dp2.di_ib[i])) : 586 iswap64(curinode->dp2.di_ib[i])) :
587 compare_blk32(wantedblk32, 587 compare_blk32(wantedblk32,
588 iswap32(curinode->dp1.di_ib[i]))) 588 iswap32(curinode->dp1.di_ib[i])))
589 if (founddatablk(is_ufs2 ? 589 if (founddatablk(is_ufs2 ?
590 iswap64(curinode->dp2.di_ib[i]) : 590 iswap64(curinode->dp2.di_ib[i]) :
591 iswap32(curinode->dp1.di_ib[i]))) 591 iswap32(curinode->dp1.di_ib[i])))
592 goto end; 592 goto end;
593 if (is_ufs2 ? (curinode->dp2.di_ib[i] != 0) : 593 if (is_ufs2 ? (curinode->dp2.di_ib[i] != 0) :
594 (curinode->dp1.di_ib[i] != 0)) 594 (curinode->dp1.di_ib[i] != 0))
595 if (is_ufs2 ? 595 if (is_ufs2 ?
596 find_indirblks64( 596 find_indirblks64(
597 iswap64(curinode->dp2.di_ib[i]), 597 iswap64(curinode->dp2.di_ib[i]),
598 i, wantedblk64) : 598 i, wantedblk64) :
599 find_indirblks32( 599 find_indirblks32(
600 iswap32(curinode->dp1.di_ib[i]), 600 iswap32(curinode->dp1.di_ib[i]),
601 i, wantedblk32)) 601 i, wantedblk32))
602 goto end; 602 goto end;
603 } 603 }
604 } 604 }
605 } 605 }
606end: 606end:
607 if (wantedblk32) 607 if (wantedblk32)
608 free(wantedblk32); 608 free(wantedblk32);
609 if (wantedblk64) 609 if (wantedblk64)
610 free(wantedblk64); 610 free(wantedblk64);
611 curinum = ocurrent; 611 curinum = ocurrent;
612 curinode = ginode(curinum); 612 curinode = ginode(curinum);
613 return 0; 613 return 0;
614} 614}
615 615
616static int 616static int
617compare_blk32(uint32_t *wantedblk, uint32_t curblk) 617compare_blk32(uint32_t *wantedblk, uint32_t curblk)
618{ 618{
619 int i; 619 int i;
620 for (i = 0; i < wantedblksize; i++) { 620 for (i = 0; i < wantedblksize; i++) {
621 if (wantedblk[i] != 0 && wantedblk[i] == curblk) { 621 if (wantedblk[i] != 0 && wantedblk[i] == curblk) {
622 wantedblk[i] = 0; 622 wantedblk[i] = 0;
623 return 1; 623 return 1;
624 } 624 }
625 } 625 }
626 return 0; 626 return 0;
627} 627}
628 628
629static int 629static int
630compare_blk64(uint64_t *wantedblk, uint64_t curblk) 630compare_blk64(uint64_t *wantedblk, uint64_t curblk)
631{ 631{
632 int i; 632 int i;
633 for (i = 0; i < wantedblksize; i++) { 633 for (i = 0; i < wantedblksize; i++) {
634 if (wantedblk[i] != 0 && wantedblk[i] == curblk) { 634 if (wantedblk[i] != 0 && wantedblk[i] == curblk) {
635 wantedblk[i] = 0; 635 wantedblk[i] = 0;
636 return 1; 636 return 1;
637 } 637 }
638 } 638 }
639 return 0; 639 return 0;
640} 640}
641 641
642static int 642static int
643founddatablk(uint64_t blk) 643founddatablk(uint64_t blk)
644{ 644{
645 printf("%llu: data block of inode %llu\n", 645 printf("%llu: data block of inode %llu\n",
646 (unsigned long long)fsbtodb(sblock, blk), 646 (unsigned long long)fsbtodb(sblock, blk),
647 (unsigned long long)curinum); 647 (unsigned long long)curinum);
648 findblk_numtofind--; 648 findblk_numtofind--;
649 if (findblk_numtofind == 0) 649 if (findblk_numtofind == 0)
650 return 1; 650 return 1;
651 return 0; 651 return 0;
652} 652}
653 653
654static int 654static int
655find_blks32(uint32_t *buf, int size, uint32_t *wantedblk) 655find_blks32(uint32_t *buf, int size, uint32_t *wantedblk)
656{ 656{
657 int blk; 657 int blk;
658 for(blk = 0; blk < size; blk++) { 658 for(blk = 0; blk < size; blk++) {
659 if (buf[blk] == 0) 659 if (buf[blk] == 0)
660 continue; 660 continue;
661 if (compare_blk32(wantedblk, iswap32(buf[blk]))) { 661 if (compare_blk32(wantedblk, iswap32(buf[blk]))) {
662 if (founddatablk(iswap32(buf[blk]))) 662 if (founddatablk(iswap32(buf[blk])))
663 return 1; 663 return 1;
664 } 664 }
665 } 665 }
666 return 0; 666 return 0;
667} 667}
668 668
669static int 669static int
670find_indirblks32(uint32_t blk, int ind_level, uint32_t *wantedblk) 670find_indirblks32(uint32_t blk, int ind_level, uint32_t *wantedblk)
671{ 671{
672#define MAXNINDIR (MAXBSIZE / sizeof(uint32_t)) 672#define MAXNINDIR (MAXBSIZE / sizeof(uint32_t))
673 uint32_t idblk[MAXNINDIR]; 673 uint32_t idblk[MAXNINDIR];
674 size_t i; 674 size_t i;
675 675
676 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk), 676 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk),
677 (int)sblock->fs_bsize); 677 (int)sblock->fs_bsize);
678 if (ind_level <= 0) { 678 if (ind_level <= 0) {
679 if (find_blks32(idblk, 679 if (find_blks32(idblk,
680 sblock->fs_bsize / sizeof(uint32_t), wantedblk)) 680 sblock->fs_bsize / sizeof(uint32_t), wantedblk))
681 return 1; 681 return 1;
682 } else { 682 } else {
683 ind_level--; 683 ind_level--;
684 for (i = 0; i < sblock->fs_bsize / sizeof(uint32_t); i++) { 684 for (i = 0; i < sblock->fs_bsize / sizeof(uint32_t); i++) {
685 if (compare_blk32(wantedblk, iswap32(idblk[i]))) { 685 if (compare_blk32(wantedblk, iswap32(idblk[i]))) {
686 if (founddatablk(iswap32(idblk[i]))) 686 if (founddatablk(iswap32(idblk[i])))
687 return 1; 687 return 1;
688 } 688 }
689 if(idblk[i] != 0) 689 if(idblk[i] != 0)
690 if (find_indirblks32(iswap32(idblk[i]), 690 if (find_indirblks32(iswap32(idblk[i]),
691 ind_level, wantedblk)) 691 ind_level, wantedblk))
692 return 1; 692 return 1;
693 } 693 }
694 } 694 }
695#undef MAXNINDIR 695#undef MAXNINDIR
696 return 0; 696 return 0;
697} 697}
698 698
699 699
700static int 700static int
701find_blks64(uint64_t *buf, int size, uint64_t *wantedblk) 701find_blks64(uint64_t *buf, int size, uint64_t *wantedblk)
702{ 702{
703 int blk; 703 int blk;
704 for(blk = 0; blk < size; blk++) { 704 for(blk = 0; blk < size; blk++) {
705 if (buf[blk] == 0) 705 if (buf[blk] == 0)
706 continue; 706 continue;
707 if (compare_blk64(wantedblk, iswap64(buf[blk]))) { 707 if (compare_blk64(wantedblk, iswap64(buf[blk]))) {
708 if (founddatablk(iswap64(buf[blk]))) 708 if (founddatablk(iswap64(buf[blk])))
709 return 1; 709 return 1;
710 } 710 }
711 } 711 }
712 return 0; 712 return 0;
713} 713}
714 714
715static int 715static int
716find_indirblks64(uint64_t blk, int ind_level, uint64_t *wantedblk) 716find_indirblks64(uint64_t blk, int ind_level, uint64_t *wantedblk)
717{ 717{
718#define MAXNINDIR (MAXBSIZE / sizeof(uint64_t)) 718#define MAXNINDIR (MAXBSIZE / sizeof(uint64_t))
719 uint64_t idblk[MAXNINDIR]; 719 uint64_t idblk[MAXNINDIR];
720 size_t i; 720 size_t i;
721 721
722 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk), 722 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk),
723 (int)sblock->fs_bsize); 723 (int)sblock->fs_bsize);
724 if (ind_level <= 0) { 724 if (ind_level <= 0) {
725 if (find_blks64(idblk, 725 if (find_blks64(idblk,
726 sblock->fs_bsize / sizeof(uint64_t), wantedblk)) 726 sblock->fs_bsize / sizeof(uint64_t), wantedblk))
727 return 1; 727 return 1;
728 } else { 728 } else {
729 ind_level--; 729 ind_level--;
730 for (i = 0; i < sblock->fs_bsize / sizeof(uint64_t); i++) { 730 for (i = 0; i < sblock->fs_bsize / sizeof(uint64_t); i++) {
731 if (compare_blk64(wantedblk, iswap64(idblk[i]))) { 731 if (compare_blk64(wantedblk, iswap64(idblk[i]))) {
732 if (founddatablk(iswap64(idblk[i]))) 732 if (founddatablk(iswap64(idblk[i])))
733 return 1; 733 return 1;
734 } 734 }
735 if(idblk[i] != 0) 735 if(idblk[i] != 0)
736 if (find_indirblks64(iswap64(idblk[i]), 736 if (find_indirblks64(iswap64(idblk[i]),
737 ind_level, wantedblk)) 737 ind_level, wantedblk))
738 return 1; 738 return 1;
739 } 739 }
740 } 740 }
741#undef MAXNINDIR 741#undef MAXNINDIR
742 return 0; 742 return 0;
743} 743}
744 744
745 745
746#define CHARS_PER_LINES 70 746#define CHARS_PER_LINES 70
747 747
748static void 748static void
749print_blks32(int32_t *buf, int size, uint64_t *blknum) 749print_blks32(int32_t *buf, int size, uint64_t *blknum)
750{ 750{
751 int chars; 751 int chars;
752 char prbuf[CHARS_PER_LINES+1]; 752 char prbuf[CHARS_PER_LINES+1];
753 int blk; 753 int blk;
754  754
755 chars = 0; 755 chars = 0;
756 for(blk = 0; blk < size; blk++, (*blknum)++) { 756 for(blk = 0; blk < size; blk++, (*blknum)++) {
757 if (buf[blk] == 0) 757 if (buf[blk] == 0)
758 continue; 758 continue;
759 snprintf(prbuf, CHARS_PER_LINES, "%d ", iswap32(buf[blk])); 759 snprintf(prbuf, CHARS_PER_LINES, "%d ", iswap32(buf[blk]));
760 if ((chars + strlen(prbuf)) > CHARS_PER_LINES) { 760 if ((chars + strlen(prbuf)) > CHARS_PER_LINES) {
761 printf("\n"); 761 printf("\n");
762 chars = 0; 762 chars = 0;
763 } 763 }
764 if (chars == 0) 764 if (chars == 0)
765 printf("%" PRIu64 ": ", *blknum); 765 printf("%" PRIu64 ": ", *blknum);
766 printf("%s", prbuf); 766 printf("%s", prbuf);
767 chars += strlen(prbuf); 767 chars += strlen(prbuf);
768 } 768 }
769 printf("\n"); 769 printf("\n");
770} 770}
771 771
772static void 772static void
773print_blks64(int64_t *buf, int size, uint64_t *blknum) 773print_blks64(int64_t *buf, int size, uint64_t *blknum)
774{ 774{
775 int chars; 775 int chars;
776 char prbuf[CHARS_PER_LINES+1]; 776 char prbuf[CHARS_PER_LINES+1];
777 int blk; 777 int blk;
778  778
779 chars = 0; 779 chars = 0;
780 for(blk = 0; blk < size; blk++, (*blknum)++) { 780 for(blk = 0; blk < size; blk++, (*blknum)++) {
781 if (buf[blk] == 0) 781 if (buf[blk] == 0)
782 continue; 782 continue;
783 snprintf(prbuf, CHARS_PER_LINES, "%lld ", 783 snprintf(prbuf, CHARS_PER_LINES, "%lld ",
784 (long long)iswap64(buf[blk])); 784 (long long)iswap64(buf[blk]));
785 if ((chars + strlen(prbuf)) > CHARS_PER_LINES) { 785 if ((chars + strlen(prbuf)) > CHARS_PER_LINES) {
786 printf("\n"); 786 printf("\n");
787 chars = 0; 787 chars = 0;
788 } 788 }
789 if (chars == 0) 789 if (chars == 0)
790 printf("%" PRIu64 ": ", *blknum); 790 printf("%" PRIu64 ": ", *blknum);
791 printf("%s", prbuf); 791 printf("%s", prbuf);
792 chars += strlen(prbuf); 792 chars += strlen(prbuf);
793 } 793 }
794 printf("\n"); 794 printf("\n");
795} 795}
796 796
797#undef CHARS_PER_LINES 797#undef CHARS_PER_LINES
798 798
799static void 799static void
800print_indirblks32(uint32_t blk, int ind_level, uint64_t *blknum) 800print_indirblks32(uint32_t blk, int ind_level, uint64_t *blknum)
801{ 801{
802#define MAXNINDIR (MAXBSIZE / sizeof(int32_t)) 802#define MAXNINDIR (MAXBSIZE / sizeof(int32_t))
803 const int ptrperblk_shift = sblock->fs_bshift - 2; 803 const int ptrperblk_shift = sblock->fs_bshift - 2;
804 const int ptrperblk = 1 << ptrperblk_shift; 804 const int ptrperblk = 1 << ptrperblk_shift;
805 int32_t idblk[MAXNINDIR]; 805 int32_t idblk[MAXNINDIR];
806 int i; 806 int i;
807 807
808 if (blk == 0) { 808 if (blk == 0) {
809 *blknum += (uint64_t)ptrperblk << (ptrperblk_shift * ind_level); 809 *blknum += (uint64_t)ptrperblk << (ptrperblk_shift * ind_level);
810 return; 810 return;
811 } 811 }
812  812
813 printf("Indirect block %lld (level %d):\n", (long long)blk, 813 printf("Indirect block %lld (level %d):\n", (long long)blk,
814 ind_level+1); 814 ind_level+1);
815 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk), 815 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk),
816 (int)sblock->fs_bsize); 816 (int)sblock->fs_bsize);
817 if (ind_level <= 0) { 817 if (ind_level <= 0) {
818 print_blks32(idblk, ptrperblk, blknum); 818 print_blks32(idblk, ptrperblk, blknum);
819 } else { 819 } else {
820 ind_level--; 820 ind_level--;
821 for (i = 0; i < ptrperblk; i++) 821 for (i = 0; i < ptrperblk; i++)
822 print_indirblks32(iswap32(idblk[i]), ind_level, blknum); 822 print_indirblks32(iswap32(idblk[i]), ind_level, blknum);
823 } 823 }
824#undef MAXNINDIR 824#undef MAXNINDIR
825} 825}
826 826
827static void 827static void
828print_indirblks64(uint64_t blk, int ind_level, uint64_t *blknum) 828print_indirblks64(uint64_t blk, int ind_level, uint64_t *blknum)
829{ 829{
830#define MAXNINDIR (MAXBSIZE / sizeof(int64_t)) 830#define MAXNINDIR (MAXBSIZE / sizeof(int64_t))
831 const int ptrperblk_shift = sblock->fs_bshift - 3; 831 const int ptrperblk_shift = sblock->fs_bshift - 3;
832 const int ptrperblk = 1 << ptrperblk_shift; 832 const int ptrperblk = 1 << ptrperblk_shift;
833 int64_t idblk[MAXNINDIR]; 833 int64_t idblk[MAXNINDIR];
834 int i; 834 int i;
835 835
836 if (blk == 0) { 836 if (blk == 0) {
837 *blknum += (uint64_t)ptrperblk << (ptrperblk_shift * ind_level); 837 *blknum += (uint64_t)ptrperblk << (ptrperblk_shift * ind_level);
838 return; 838 return;
839 } 839 }
840  840
841 printf("Indirect block %lld (level %d):\n", (long long)blk, 841 printf("Indirect block %lld (level %d):\n", (long long)blk,
842 ind_level+1); 842 ind_level+1);
843 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk), 843 bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk),
844 (int)sblock->fs_bsize); 844 (int)sblock->fs_bsize);
845 if (ind_level <= 0) { 845 if (ind_level <= 0) {
846 print_blks64(idblk, ptrperblk, blknum); 846 print_blks64(idblk, ptrperblk, blknum);
847 } else { 847 } else {
848 ind_level--; 848 ind_level--;
849 for (i = 0; i < ptrperblk; i++) 849 for (i = 0; i < ptrperblk; i++)
850 print_indirblks64(iswap64(idblk[i]), ind_level, blknum); 850 print_indirblks64(iswap64(idblk[i]), ind_level, blknum);
851 } 851 }
852#undef MAXNINDIR 852#undef MAXNINDIR
853} 853}
854 854
855static int 855static int
856dolookup(char *name) 856dolookup(char *name)
857{ 857{
858 struct inodesc idesc; 858 struct inodesc idesc;
859 859
860 if (!checkactivedir()) 860 if (!checkactivedir())
861 return 0; 861 return 0;
862 idesc.id_number = curinum; 862 idesc.id_number = curinum;
863 idesc.id_func = findino; 863 idesc.id_func = findino;
864 idesc.id_name = name; 864 idesc.id_name = name;
865 idesc.id_type = DATA; 865 idesc.id_type = DATA;
866 idesc.id_fix = IGNORE; 866 idesc.id_fix = IGNORE;
867 if (ckinode(curinode, &idesc) & FOUND) { 867 if (ckinode(curinode, &idesc) & FOUND) {
868 curinum = idesc.id_parent; 868 curinum = idesc.id_parent;
869 curinode = ginode(curinum); 869 curinode = ginode(curinum);
870 printactive(); 870 printactive();
871 return 1; 871 return 1;
872 } else { 872 } else {
873 warnx("name `%s' not found in current inode directory", name); 873 warnx("name `%s' not found in current inode directory", name);
874 return 0; 874 return 0;
875 } 875 }
876} 876}
877 877
878CMDFUNCSTART(focusname) 878CMDFUNCSTART(focusname)
879{ 879{
880 char *p, *val; 880 char *p, *val;
881 881
882 if (!checkactive()) 882 if (!checkactive())
883 return 1; 883 return 1;
884 884
885 ocurrent = curinum; 885 ocurrent = curinum;
886 886
887 if (argv[1][0] == '/') { 887 if (argv[1][0] == '/') {
888 curinum = ROOTINO; 888 curinum = ROOTINO;
889 curinode = ginode(ROOTINO); 889 curinode = ginode(ROOTINO);
890 } else { 890 } else {
891 if (!checkactivedir()) 891 if (!checkactivedir())
892 return 1; 892 return 1;
893 } 893 }
894 for (p = argv[1]; p != NULL;) { 894 for (p = argv[1]; p != NULL;) {
895 while ((val = strsep(&p, "/")) != NULL && *val == '\0'); 895 while ((val = strsep(&p, "/")) != NULL && *val == '\0');
896 if (val) { 896 if (val) {
897 printf("component `%s': ", val); 897 printf("component `%s': ", val);
898 fflush(stdout); 898 fflush(stdout);
899 if (!dolookup(val)) { 899 if (!dolookup(val)) {
900 curinode = ginode(curinum); 900 curinode = ginode(curinum);
901 return (1); 901 return (1);
902 } 902 }
903 } 903 }
904 } 904 }
905 return 0; 905 return 0;
906} 906}
907 907
908CMDFUNCSTART(ln) 908CMDFUNCSTART(ln)
909{ 909{
910 ino_t inum; 910 ino_t inum;
911 int rval; 911 int rval;
912 char *cp; 912 char *cp;
913 913
914 GETINUM(1, inum); 914 GETINUM(1, inum);
915 915
916 if (!checkactivedir()) 916 if (!checkactivedir())
917 return 1; 917 return 1;
918 rval = makeentry(curinum, inum, argv[2]); 918 rval = makeentry(curinum, inum, argv[2]);
919 if (rval) 919 if (rval)
920 printf("Ino %llu entered as `%s'\n", (unsigned long long)inum, 920 printf("Ino %llu entered as `%s'\n", (unsigned long long)inum,
921 argv[2]); 921 argv[2]);
922 else 922 else
923 printf("could not enter name? weird.\n"); 923 printf("could not enter name? weird.\n");
924 curinode = ginode(curinum); 924 curinode = ginode(curinum);
925 return rval; 925 return rval;
926} 926}
927 927
928CMDFUNCSTART(rm) 928CMDFUNCSTART(rm)
929{ 929{
930 int rval; 930 int rval;
931 931
932 if (!checkactivedir()) 932 if (!checkactivedir())
933 return 1; 933 return 1;
934 rval = changeino(curinum, argv[1], 0); 934 rval = changeino(curinum, argv[1], 0);
935 if (rval & ALTERED) { 935 if (rval & ALTERED) {
936 printf("Name `%s' removed\n", argv[1]); 936 printf("Name `%s' removed\n", argv[1]);
937 return 0; 937 return 0;
938 } else { 938 } else {
939 printf("could not remove name? weird.\n"); 939 printf("could not remove name? weird.\n");
940 return 1; 940 return 1;
941 } 941 }
942} 942}
943 943
944static long slotcount, desired; 944static long slotcount, desired;
945 945
946static int 946static int
947chinumfunc(struct inodesc *idesc) 947chinumfunc(struct inodesc *idesc)
948{ 948{
949 struct direct *dirp = idesc->id_dirp; 949 struct direct *dirp = idesc->id_dirp;
950 950
951 if (slotcount++ == desired) { 951 if (slotcount++ == desired) {
952 dirp->d_ino = iswap32(idesc->id_parent); 952 dirp->d_ino = iswap32(idesc->id_parent);
953 return STOP | ALTERED | FOUND; 953 return STOP | ALTERED | FOUND;
954 } 954 }
955 return KEEPON; 955 return KEEPON;
956} 956}
957 957
958CMDFUNCSTART(chinum) 958CMDFUNCSTART(chinum)
959{ 959{
960 char *cp; 960 char *cp;
961 ino_t inum; 961 ino_t inum;
962 struct inodesc idesc; 962 struct inodesc idesc;
963 963
964 slotcount = 0; 964 slotcount = 0;
965 if (!checkactivedir()) 965 if (!checkactivedir())
966 return 1; 966 return 1;
967 GETINUM(2, inum); 967 GETINUM(2, inum);
968 968
969 desired = strtol(argv[1], &cp, 0); 969 desired = strtol(argv[1], &cp, 0);
970 if (cp == argv[1] || *cp != '\0' || desired < 0) { 970 if (cp == argv[1] || *cp != '\0' || desired < 0) {
971 printf("invalid slot number `%s'\n", argv[1]); 971 printf("invalid slot number `%s'\n", argv[1]);
972 return 1; 972 return 1;
973 } 973 }
974 idesc.id_number = curinum; 974 idesc.id_number = curinum;
975 idesc.id_func = chinumfunc; 975 idesc.id_func = chinumfunc;
976 idesc.id_fix = IGNORE; 976 idesc.id_fix = IGNORE;
977 idesc.id_type = DATA; 977 idesc.id_type = DATA;
978 idesc.id_parent = inum; /* XXX convenient hiding place */ 978 idesc.id_parent = inum; /* XXX convenient hiding place */
979 979
980 if (ckinode(curinode, &idesc) & FOUND) 980 if (ckinode(curinode, &idesc) & FOUND)
981 return 0; 981 return 0;
982 else { 982 else {
983 warnx("no %sth slot in current directory", argv[1]); 983 warnx("no %sth slot in current directory", argv[1]);
984 return 1; 984 return 1;
985 } 985 }
986} 986}
987 987
988static int 988static int
989chnamefunc(struct inodesc *idesc) 989chnamefunc(struct inodesc *idesc)
990{ 990{
991 struct direct *dirp = idesc->id_dirp; 991 struct direct *dirp = idesc->id_dirp;
992 struct direct testdir; 992 struct direct testdir;
993 993
994 if (slotcount++ == desired) { 994 if (slotcount++ == desired) {
995 /* will name fit? */ 995 /* will name fit? */
996 testdir.d_namlen = strlen(idesc->id_name); 996 testdir.d_namlen = strlen(idesc->id_name);
997 if (DIRSIZ(NEWDIRFMT, &testdir, 0) <= iswap16(dirp->d_reclen)) { 997 if (DIRSIZ(NEWDIRFMT, &testdir, 0) <= iswap16(dirp->d_reclen)) {
998 dirp->d_namlen = testdir.d_namlen; 998 dirp->d_namlen = testdir.d_namlen;
999 strlcpy(dirp->d_name, idesc->id_name, 999 strlcpy(dirp->d_name, idesc->id_name,
1000 sizeof(dirp->d_name)); 1000 sizeof(dirp->d_name));
1001 return STOP | ALTERED | FOUND; 1001 return STOP | ALTERED | FOUND;
1002 } else 1002 } else
1003 return STOP | FOUND; /* won't fit, so give up */ 1003 return STOP | FOUND; /* won't fit, so give up */
1004 } 1004 }
1005 return KEEPON; 1005 return KEEPON;
1006} 1006}
1007 1007
1008CMDFUNCSTART(chname) 1008CMDFUNCSTART(chname)
1009{ 1009{
1010 int rval; 1010 int rval;
1011 char *cp; 1011 char *cp;
1012 struct inodesc idesc; 1012 struct inodesc idesc;
1013 1013
1014 slotcount = 0; 1014 slotcount = 0;
1015 if (!checkactivedir()) 1015 if (!checkactivedir())
1016 return 1; 1016 return 1;
1017 1017
1018 desired = strtoul(argv[1], &cp, 0); 1018 desired = strtoul(argv[1], &cp, 0);
1019 if (cp == argv[1] || *cp != '\0') { 1019 if (cp == argv[1] || *cp != '\0') {
1020 printf("invalid slot number `%s'\n", argv[1]); 1020 printf("invalid slot number `%s'\n", argv[1]);
1021 return 1; 1021 return 1;
1022 } 1022 }
1023 idesc.id_number = curinum; 1023 idesc.id_number = curinum;
1024 idesc.id_func = chnamefunc; 1024 idesc.id_func = chnamefunc;
1025 idesc.id_fix = IGNORE; 1025 idesc.id_fix = IGNORE;
1026 idesc.id_type = DATA; 1026 idesc.id_type = DATA;
1027 idesc.id_name = argv[2]; 1027 idesc.id_name = argv[2];
1028 1028
1029 rval = ckinode(curinode, &idesc); 1029 rval = ckinode(curinode, &idesc);
1030 if ((rval & (FOUND | ALTERED)) == (FOUND | ALTERED)) 1030 if ((rval & (FOUND | ALTERED)) == (FOUND | ALTERED))
1031 return 0; 1031 return 0;
1032 else 1032 else
1033 if (rval & FOUND) { 1033 if (rval & FOUND) {
1034 warnx("new name `%s' does not fit in slot %s", 1034 warnx("new name `%s' does not fit in slot %s",
1035 argv[2], argv[1]); 1035 argv[2], argv[1]);
1036 return 1; 1036 return 1;
1037 } else { 1037 } else {
1038 warnx("no %sth slot in current directory", argv[1]); 1038 warnx("no %sth slot in current directory", argv[1]);
1039 return 1; 1039 return 1;
1040 } 1040 }
1041} 1041}
1042 1042
1043static struct typemap { 1043static struct typemap {
1044 const char *typename; 1044 const char *typename;
1045 int typebits; 1045 int typebits;
1046} typenamemap[] = { 1046} typenamemap[] = {
1047 { "file", IFREG }, 1047 { "file", IFREG },
1048 { "dir", IFDIR }, 1048 { "dir", IFDIR },
1049 { "socket", IFSOCK }, 1049 { "socket", IFSOCK },
1050 { "fifo", IFIFO }, 1050 { "fifo", IFIFO },
1051}; 1051};
1052 1052
1053CMDFUNCSTART(newtype) 1053CMDFUNCSTART(newtype)
1054{ 1054{
1055 int type; 1055 int type;
1056 uint16_t mode; 1056 uint16_t mode;
1057 struct typemap *tp; 1057 struct typemap *tp;
1058 1058
1059 if (!checkactive()) 1059 if (!checkactive())
1060 return 1; 1060 return 1;
1061 mode = iswap16(DIP(curinode, mode)); 1061 mode = iswap16(DIP(curinode, mode));
1062 type = mode & IFMT; 1062 type = mode & IFMT;
1063 for (tp = typenamemap; 1063 for (tp = typenamemap;
1064 tp < &typenamemap[sizeof(typenamemap) / sizeof(*typenamemap)]; 1064 tp < &typenamemap[sizeof(typenamemap) / sizeof(*typenamemap)];
1065 tp++) { 1065 tp++) {
1066 if (!strcmp(argv[1], tp->typename)) { 1066 if (!strcmp(argv[1], tp->typename)) {
1067 printf("setting type to %s\n", tp->typename); 1067 printf("setting type to %s\n", tp->typename);
1068 type = tp->typebits; 1068 type = tp->typebits;
1069 break; 1069 break;
1070 } 1070 }
1071 } 1071 }
1072 if (tp == &typenamemap[sizeof(typenamemap) / sizeof(*typenamemap)]) { 1072 if (tp == &typenamemap[sizeof(typenamemap) / sizeof(*typenamemap)]) {
1073 warnx("type `%s' not known", argv[1]); 1073 warnx("type `%s' not known", argv[1]);
1074 warnx("try one of `file', `dir', `socket', `fifo'"); 1074 warnx("try one of `file', `dir', `socket', `fifo'");
1075 return 1; 1075 return 1;
1076 } 1076 }
1077 DIP_SET(curinode, mode, iswap16((mode & ~IFMT) | type)); 1077 DIP_SET(curinode, mode, iswap16((mode & ~IFMT) | type));
1078 inodirty(); 1078 inodirty();
1079 printactive(); 1079 printactive();
1080 return 0; 1080 return 0;
1081} 1081}
1082 1082
1083CMDFUNCSTART(chmode) 1083CMDFUNCSTART(chmode)
1084{ 1084{
1085 long modebits; 1085 long modebits;
1086 char *cp; 1086 char *cp;
1087 uint16_t mode; 1087 uint16_t mode;
1088 1088
1089 if (!checkactive()) 1089 if (!checkactive())
1090 return 1; 1090 return 1;
1091 1091
1092 modebits = strtol(argv[1], &cp, 8); 1092 modebits = strtol(argv[1], &cp, 8);
1093 if (cp == argv[1] || *cp != '\0') { 1093 if (cp == argv[1] || *cp != '\0') {
1094 warnx("bad modebits `%s'", argv[1]); 1094 warnx("bad modebits `%s'", argv[1]);
1095 return 1; 1095 return 1;
1096 } 1096 }
1097 mode = iswap16(DIP(curinode, mode)); 1097 mode = iswap16(DIP(curinode, mode));
1098 DIP_SET(curinode, mode, iswap16((mode & ~07777) | modebits)); 1098 DIP_SET(curinode, mode, iswap16((mode & ~07777) | modebits));
1099 inodirty(); 1099 inodirty();
1100 printactive(); 1100 printactive();
1101 return 0; 1101 return 0;
1102} 1102}
1103 1103
1104CMDFUNCSTART(chlen) 1104CMDFUNCSTART(chlen)
1105{ 1105{
1106 long len; 1106 long len;
1107 char *cp; 1107 char *cp;
1108 1108
1109 if (!checkactive()) 1109 if (!checkactive())
1110 return 1; 1110 return 1;
1111 1111
1112 len = strtol(argv[1], &cp, 0); 1112 len = strtol(argv[1], &cp, 0);
1113 if (cp == argv[1] || *cp != '\0' || len < 0) { 1113 if (cp == argv[1] || *cp != '\0' || len < 0) {
1114 warnx("bad length '%s'", argv[1]); 1114 warnx("bad length '%s'", argv[1]);
1115 return 1; 1115 return 1;
1116 } 1116 }
1117 DIP_SET(curinode, size, iswap64(len)); 1117 DIP_SET(curinode, size, iswap64(len));
1118 inodirty(); 1118 inodirty();
1119 printactive(); 1119 printactive();
1120 return 0; 1120 return 0;
1121} 1121}
1122 1122
1123CMDFUNCSTART(chaflags) 1123CMDFUNCSTART(chaflags)
1124{ 1124{
1125 u_long flags; 1125 u_long flags;
1126 char *cp; 1126 char *cp;
1127 1127
1128 if (!checkactive()) 1128 if (!checkactive())
1129 return 1; 1129 return 1;
1130 1130
1131 flags = strtoul(argv[1], &cp, 0); 1131 flags = strtoul(argv[1], &cp, 0);
1132 if (cp == argv[1] || *cp != '\0') { 1132 if (cp == argv[1] || *cp != '\0') {
1133 warnx("bad flags `%s'", argv[1]); 1133 warnx("bad flags `%s'", argv[1]);
1134 return 1; 1134 return 1;
1135 } 1135 }
1136 if (flags > UINT_MAX) { 1136 if (flags > UINT_MAX) {
1137 warnx("flags set beyond 32-bit range of field (0x%lx)", 1137 warnx("flags set beyond 32-bit range of field (0x%lx)",
1138 flags); 1138 flags);
1139 return (1); 1139 return (1);
1140 } 1140 }
1141 DIP_SET(curinode, flags, iswap32(flags)); 1141 DIP_SET(curinode, flags, iswap32(flags));