| @@ -1,541 +1,545 @@ | | | @@ -1,541 +1,545 @@ |
1 | /* $NetBSD: setup.c,v 1.31 2013/06/23 02:06:04 dholland Exp $ */ | | 1 | /* $NetBSD: setup.c,v 1.31.6.1 2015/04/14 05:15:57 snj Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1980, 1986, 1993 | | 4 | * Copyright (c) 1980, 1986, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
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 | * 3. Neither the name of the University nor the names of its contributors | | 15 | * 3. Neither the name of the University nor the names of its contributors |
16 | * may be used to endorse or promote products derived from this software | | 16 | * may be used to endorse or promote products derived from this software |
17 | * without specific prior written permission. | | 17 | * without specific prior written permission. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1997 Manuel Bouyer. | | 33 | * Copyright (c) 1997 Manuel Bouyer. |
34 | * | | 34 | * |
35 | * Redistribution and use in source and binary forms, with or without | | 35 | * Redistribution and use in source and binary forms, with or without |
36 | * modification, are permitted provided that the following conditions | | 36 | * modification, are permitted provided that the following conditions |
37 | * are met: | | 37 | * are met: |
38 | * 1. Redistributions of source code must retain the above copyright | | 38 | * 1. Redistributions of source code must retain the above copyright |
39 | * notice, this list of conditions and the following disclaimer. | | 39 | * notice, this list of conditions and the following disclaimer. |
40 | * 2. Redistributions in binary form must reproduce the above copyright | | 40 | * 2. Redistributions in binary form must reproduce the above copyright |
41 | * notice, this list of conditions and the following disclaimer in the | | 41 | * notice, this list of conditions and the following disclaimer in the |
42 | * documentation and/or other materials provided with the distribution. | | 42 | * documentation and/or other materials provided with the distribution. |
43 | * | | 43 | * |
44 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 44 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
45 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 45 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
46 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 46 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
47 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 47 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
48 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 48 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
49 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 49 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 50 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 51 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 52 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
53 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 53 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
54 | */ | | 54 | */ |
55 | | | 55 | |
56 | #include <sys/cdefs.h> | | 56 | #include <sys/cdefs.h> |
57 | #ifndef lint | | 57 | #ifndef lint |
58 | #if 0 | | 58 | #if 0 |
59 | static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94"; | | 59 | static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94"; |
60 | #else | | 60 | #else |
61 | __RCSID("$NetBSD: setup.c,v 1.31 2013/06/23 02:06:04 dholland Exp $"); | | 61 | __RCSID("$NetBSD: setup.c,v 1.31.6.1 2015/04/14 05:15:57 snj Exp $"); |
62 | #endif | | 62 | #endif |
63 | #endif /* not lint */ | | 63 | #endif /* not lint */ |
64 | | | 64 | |
65 | #define FSTYPENAMES | | 65 | #define FSTYPENAMES |
66 | #include <sys/param.h> | | 66 | #include <sys/param.h> |
67 | #include <sys/time.h> | | 67 | #include <sys/time.h> |
68 | #include <ufs/ext2fs/ext2fs_dinode.h> | | 68 | #include <ufs/ext2fs/ext2fs_dinode.h> |
69 | #include <ufs/ext2fs/ext2fs.h> | | 69 | #include <ufs/ext2fs/ext2fs.h> |
70 | #include <sys/stat.h> | | 70 | #include <sys/stat.h> |
71 | #include <sys/ioctl.h> | | 71 | #include <sys/ioctl.h> |
72 | #include <sys/disklabel.h> | | 72 | #include <sys/disklabel.h> |
73 | #include <sys/file.h> | | 73 | #include <sys/file.h> |
74 | | | 74 | |
75 | #include <errno.h> | | 75 | #include <errno.h> |
76 | #include <stdio.h> | | 76 | #include <stdio.h> |
77 | #include <stdlib.h> | | 77 | #include <stdlib.h> |
78 | #include <string.h> | | 78 | #include <string.h> |
79 | #include <ctype.h> | | 79 | #include <ctype.h> |
80 | | | 80 | |
81 | #include "fsck.h" | | 81 | #include "fsck.h" |
82 | #include "extern.h" | | 82 | #include "extern.h" |
83 | #include "fsutil.h" | | 83 | #include "fsutil.h" |
84 | #include "exitvalues.h" | | 84 | #include "exitvalues.h" |
85 | | | 85 | |
86 | void badsb(int, const char *); | | 86 | void badsb(int, const char *); |
87 | int calcsb(const char *, int, struct m_ext2fs *); | | 87 | int calcsb(const char *, int, struct m_ext2fs *); |
88 | static struct disklabel *getdisklabel(const char *, int); | | 88 | static struct disklabel *getdisklabel(const char *, int); |
89 | static int readsb(int); | | 89 | static int readsb(int); |
90 | | | 90 | |
91 | int | | 91 | int |
92 | setup(const char *dev) | | 92 | setup(const char *dev) |
93 | { | | 93 | { |
94 | long cg, asked, i; | | 94 | long cg, asked, i; |
95 | long bmapsize; | | 95 | long bmapsize; |
96 | struct disklabel *lp; | | 96 | struct disklabel *lp; |
97 | off_t sizepb; | | 97 | off_t sizepb; |
98 | struct stat statb; | | 98 | struct stat statb; |
99 | struct m_ext2fs proto; | | 99 | struct m_ext2fs proto; |
100 | int doskipclean; | | 100 | int doskipclean; |
101 | u_int64_t maxfilesize; | | 101 | u_int64_t maxfilesize; |
102 | | | 102 | |
103 | havesb = 0; | | 103 | havesb = 0; |
104 | fswritefd = -1; | | 104 | fswritefd = -1; |
105 | doskipclean = skipclean; | | 105 | doskipclean = skipclean; |
106 | if (stat(dev, &statb) < 0) { | | 106 | if (stat(dev, &statb) < 0) { |
107 | printf("Can't stat %s: %s\n", dev, strerror(errno)); | | 107 | printf("Can't stat %s: %s\n", dev, strerror(errno)); |
108 | return 0; | | 108 | return 0; |
109 | } | | 109 | } |
110 | if (!S_ISCHR(statb.st_mode)) { | | 110 | if (!S_ISCHR(statb.st_mode)) { |
111 | pfatal("%s is not a character device", dev); | | 111 | pfatal("%s is not a character device", dev); |
112 | if (reply("CONTINUE") == 0) | | 112 | if (reply("CONTINUE") == 0) |
113 | return 0; | | 113 | return 0; |
114 | } | | 114 | } |
115 | if ((fsreadfd = open(dev, O_RDONLY)) < 0) { | | 115 | if ((fsreadfd = open(dev, O_RDONLY)) < 0) { |
116 | printf("Can't open %s: %s\n", dev, strerror(errno)); | | 116 | printf("Can't open %s: %s\n", dev, strerror(errno)); |
117 | return 0; | | 117 | return 0; |
118 | } | | 118 | } |
119 | if (preen == 0) | | 119 | if (preen == 0) |
120 | printf("** %s", dev); | | 120 | printf("** %s", dev); |
121 | if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { | | 121 | if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { |
122 | fswritefd = -1; | | 122 | fswritefd = -1; |
123 | if (preen) | | 123 | if (preen) |
124 | pfatal("NO WRITE ACCESS"); | | 124 | pfatal("NO WRITE ACCESS"); |
125 | printf(" (NO WRITE)"); | | 125 | printf(" (NO WRITE)"); |
126 | } | | 126 | } |
127 | if (preen == 0) | | 127 | if (preen == 0) |
128 | printf("\n"); | | 128 | printf("\n"); |
129 | fsmodified = 0; | | 129 | fsmodified = 0; |
130 | lfdir = 0; | | 130 | lfdir = 0; |
131 | initbarea(&sblk); | | 131 | initbarea(&sblk); |
132 | initbarea(&asblk); | | 132 | initbarea(&asblk); |
133 | sblk.b_un.b_buf = malloc(SBSIZE); | | 133 | sblk.b_un.b_buf = malloc(SBSIZE); |
134 | asblk.b_un.b_buf = malloc(SBSIZE); | | 134 | asblk.b_un.b_buf = malloc(SBSIZE); |
135 | if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) | | 135 | if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) |
136 | errexit("cannot allocate space for superblock"); | | 136 | errexit("cannot allocate space for superblock"); |
137 | if ((lp = getdisklabel(NULL, fsreadfd)) != NULL) | | 137 | if ((lp = getdisklabel(NULL, fsreadfd)) != NULL) |
138 | dev_bsize = secsize = lp->d_secsize; | | 138 | dev_bsize = secsize = lp->d_secsize; |
139 | else | | 139 | else |
140 | dev_bsize = secsize = DEV_BSIZE; | | 140 | dev_bsize = secsize = DEV_BSIZE; |
141 | /* | | 141 | /* |
142 | * Read in the superblock, looking for alternates if necessary | | 142 | * Read in the superblock, looking for alternates if necessary |
143 | */ | | 143 | */ |
144 | if (readsb(1) == 0) { | | 144 | if (readsb(1) == 0) { |
145 | if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) | | 145 | if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) |
146 | return 0; | | 146 | return 0; |
147 | if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) | | 147 | if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) |
148 | return 0; | | 148 | return 0; |
149 | for (cg = 1; cg < proto.e2fs_ncg; cg++) { | | 149 | for (cg = 1; cg < proto.e2fs_ncg; cg++) { |
150 | bflag = EXT2_FSBTODB(&proto, | | 150 | bflag = EXT2_FSBTODB(&proto, |
151 | cg * proto.e2fs.e2fs_bpg + | | 151 | cg * proto.e2fs.e2fs_bpg + |
152 | proto.e2fs.e2fs_first_dblock); | | 152 | proto.e2fs.e2fs_first_dblock); |
153 | if (readsb(0) != 0) | | 153 | if (readsb(0) != 0) |
154 | break; | | 154 | break; |
155 | } | | 155 | } |
156 | if (cg >= proto.e2fs_ncg) { | | 156 | if (cg >= proto.e2fs_ncg) { |
157 | printf("%s %s\n%s %s\n%s %s\n", | | 157 | printf("%s %s\n%s %s\n%s %s\n", |
158 | "SEARCH FOR ALTERNATE SUPER-BLOCK", | | 158 | "SEARCH FOR ALTERNATE SUPER-BLOCK", |
159 | "FAILED. YOU MUST USE THE", | | 159 | "FAILED. YOU MUST USE THE", |
160 | "-b OPTION TO FSCK_FFS TO SPECIFY THE", | | 160 | "-b OPTION TO FSCK_FFS TO SPECIFY THE", |
161 | "LOCATION OF AN ALTERNATE", | | 161 | "LOCATION OF AN ALTERNATE", |
162 | "SUPER-BLOCK TO SUPPLY NEEDED", | | 162 | "SUPER-BLOCK TO SUPPLY NEEDED", |
163 | "INFORMATION; SEE fsck_ext2fs(8)."); | | 163 | "INFORMATION; SEE fsck_ext2fs(8)."); |
164 | return 0; | | 164 | return 0; |
165 | } | | 165 | } |
166 | doskipclean = 0; | | 166 | doskipclean = 0; |
167 | pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); | | 167 | pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); |
168 | } | | 168 | } |
169 | if (debug) | | 169 | if (debug) |
170 | printf("state = %d\n", sblock.e2fs.e2fs_state); | | 170 | printf("state = %d\n", sblock.e2fs.e2fs_state); |
171 | if (sblock.e2fs.e2fs_state == E2FS_ISCLEAN) { | | 171 | if (sblock.e2fs.e2fs_state == E2FS_ISCLEAN) { |
172 | if (doskipclean) { | | 172 | if (doskipclean) { |
173 | pwarn("%sile system is clean; not checking\n", | | 173 | pwarn("%sile system is clean; not checking\n", |
174 | preen ? "f" : "** F"); | | 174 | preen ? "f" : "** F"); |
175 | return -1; | | 175 | return -1; |
176 | } | | 176 | } |
177 | if (!preen) | | 177 | if (!preen) |
178 | pwarn("** File system is already clean\n"); | | 178 | pwarn("** File system is already clean\n"); |
179 | } | | 179 | } |
180 | maxfsblock = sblock.e2fs.e2fs_bcount; | | 180 | maxfsblock = sblock.e2fs.e2fs_bcount; |
181 | maxino = sblock.e2fs_ncg * sblock.e2fs.e2fs_ipg; | | 181 | maxino = sblock.e2fs_ncg * sblock.e2fs.e2fs_ipg; |
182 | sizepb = sblock.e2fs_bsize; | | 182 | sizepb = sblock.e2fs_bsize; |
183 | maxfilesize = sblock.e2fs_bsize * EXT2FS_NDADDR - 1; | | 183 | maxfilesize = sblock.e2fs_bsize * EXT2FS_NDADDR - 1; |
184 | for (i = 0; i < EXT2FS_NIADDR; i++) { | | 184 | for (i = 0; i < EXT2FS_NIADDR; i++) { |
185 | sizepb *= EXT2_NINDIR(&sblock); | | 185 | sizepb *= EXT2_NINDIR(&sblock); |
186 | maxfilesize += sizepb; | | 186 | maxfilesize += sizepb; |
187 | } | | 187 | } |
188 | /* | | 188 | /* |
189 | * Check and potentially fix certain fields in the super block. | | 189 | * Check and potentially fix certain fields in the super block. |
190 | */ | | 190 | */ |
191 | if (/* (sblock.e2fs.e2fs_rbcount < 0) || */ | | 191 | if (/* (sblock.e2fs.e2fs_rbcount < 0) || */ |
192 | (sblock.e2fs.e2fs_rbcount > sblock.e2fs.e2fs_bcount)) { | | 192 | (sblock.e2fs.e2fs_rbcount > sblock.e2fs.e2fs_bcount)) { |
193 | pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK", | | 193 | pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK", |
194 | sblock.e2fs.e2fs_rbcount); | | 194 | sblock.e2fs.e2fs_rbcount); |
195 | if (reply("SET TO DEFAULT") == 1) { | | 195 | if (reply("SET TO DEFAULT") == 1) { |
196 | sblock.e2fs.e2fs_rbcount = | | 196 | sblock.e2fs.e2fs_rbcount = |
197 | sblock.e2fs.e2fs_bcount * MINFREE / 100; | | 197 | sblock.e2fs.e2fs_bcount * MINFREE / 100; |
198 | sbdirty(); | | 198 | sbdirty(); |
199 | dirty(&asblk); | | 199 | dirty(&asblk); |
200 | } | | 200 | } |
201 | } | | 201 | } |
202 | if (sblock.e2fs.e2fs_bpg != sblock.e2fs.e2fs_fpg) { | | 202 | if (sblock.e2fs.e2fs_bpg != sblock.e2fs.e2fs_fpg) { |
203 | pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK", | | 203 | pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK", |
204 | sblock.e2fs.e2fs_fpg, sblock.e2fs.e2fs_bpg); | | 204 | sblock.e2fs.e2fs_fpg, sblock.e2fs.e2fs_bpg); |
205 | return 0; | | 205 | return 0; |
206 | } | | 206 | } |
207 | if (asblk.b_dirty && !bflag) { | | 207 | if (asblk.b_dirty && !bflag) { |
208 | copyback_sb(&asblk); | | 208 | copyback_sb(&asblk); |
209 | flush(fswritefd, &asblk); | | 209 | flush(fswritefd, &asblk); |
210 | } | | 210 | } |
211 | /* | | 211 | /* |
212 | * read in the summary info. | | 212 | * read in the summary info. |
213 | */ | | 213 | */ |
214 | | | 214 | |
215 | sblock.e2fs_gd = malloc(sblock.e2fs_ngdb * sblock.e2fs_bsize); | | 215 | sblock.e2fs_gd = malloc(sblock.e2fs_ngdb * sblock.e2fs_bsize); |
216 | if (sblock.e2fs_gd == NULL) | | 216 | if (sblock.e2fs_gd == NULL) |
217 | errexit("out of memory"); | | 217 | errexit("out of memory"); |
218 | asked = 0; | | 218 | asked = 0; |
219 | for (i = 0; i < sblock.e2fs_ngdb; i++) { | | 219 | for (i = 0; i < sblock.e2fs_ngdb; i++) { |
220 | if (bread(fsreadfd, | | 220 | if (bread(fsreadfd, |
221 | (char *)&sblock.e2fs_gd[i * sblock.e2fs_bsize / | | 221 | (char *)&sblock.e2fs_gd[i * sblock.e2fs_bsize / |
222 | sizeof(struct ext2_gd)], | | 222 | sizeof(struct ext2_gd)], |
223 | EXT2_FSBTODB(&sblock, ((sblock.e2fs_bsize > 1024) ? 0 : 1) + | | 223 | EXT2_FSBTODB(&sblock, ((sblock.e2fs_bsize > 1024) ? 0 : 1) + |
224 | i + 1), | | 224 | i + 1), |
225 | sblock.e2fs_bsize) != 0 && !asked) { | | 225 | sblock.e2fs_bsize) != 0 && !asked) { |
226 | pfatal("BAD SUMMARY INFORMATION"); | | 226 | pfatal("BAD SUMMARY INFORMATION"); |
227 | if (reply("CONTINUE") == 0) | | 227 | if (reply("CONTINUE") == 0) |
228 | exit(FSCK_EXIT_CHECK_FAILED); | | 228 | exit(FSCK_EXIT_CHECK_FAILED); |
229 | asked++; | | 229 | asked++; |
230 | } | | 230 | } |
231 | } | | 231 | } |
232 | /* | | 232 | /* |
233 | * allocate and initialize the necessary maps | | 233 | * allocate and initialize the necessary maps |
234 | */ | | 234 | */ |
235 | bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); | | 235 | bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t)); |
236 | blockmap = calloc((unsigned int)bmapsize, sizeof(char)); | | 236 | blockmap = calloc((unsigned int)bmapsize, sizeof(char)); |
237 | if (blockmap == NULL) { | | 237 | if (blockmap == NULL) { |
238 | printf("cannot alloc %u bytes for blockmap\n", | | 238 | printf("cannot alloc %u bytes for blockmap\n", |
239 | (unsigned int)bmapsize); | | 239 | (unsigned int)bmapsize); |
240 | goto badsblabel; | | 240 | goto badsblabel; |
241 | } | | 241 | } |
242 | statemap = calloc((unsigned int)(maxino + 2), sizeof(char)); | | 242 | statemap = calloc((unsigned int)(maxino + 2), sizeof(char)); |
243 | if (statemap == NULL) { | | 243 | if (statemap == NULL) { |
244 | printf("cannot alloc %u bytes for statemap\n", | | 244 | printf("cannot alloc %u bytes for statemap\n", |
245 | (unsigned int)(maxino + 1)); | | 245 | (unsigned int)(maxino + 1)); |
246 | goto badsblabel; | | 246 | goto badsblabel; |
247 | } | | 247 | } |
248 | typemap = calloc((unsigned int)(maxino + 1), sizeof(char)); | | 248 | typemap = calloc((unsigned int)(maxino + 1), sizeof(char)); |
249 | if (typemap == NULL) { | | 249 | if (typemap == NULL) { |
250 | printf("cannot alloc %u bytes for typemap\n", | | 250 | printf("cannot alloc %u bytes for typemap\n", |
251 | (unsigned int)(maxino + 1)); | | 251 | (unsigned int)(maxino + 1)); |
252 | goto badsblabel; | | 252 | goto badsblabel; |
253 | } | | 253 | } |
254 | lncntp = calloc((unsigned)(maxino + 1), sizeof(int16_t)); | | 254 | lncntp = calloc((unsigned)(maxino + 1), sizeof(int16_t)); |
255 | if (lncntp == NULL) { | | 255 | if (lncntp == NULL) { |
256 | printf("cannot alloc %u bytes for lncntp\n", | | 256 | printf("cannot alloc %u bytes for lncntp\n", |
257 | (unsigned int)((maxino + 1) * sizeof(int16_t))); | | 257 | (unsigned int)((maxino + 1) * sizeof(int16_t))); |
258 | goto badsblabel; | | 258 | goto badsblabel; |
259 | } | | 259 | } |
260 | for (numdirs = 0, cg = 0; cg < sblock.e2fs_ncg; cg++) { | | 260 | for (numdirs = 0, cg = 0; cg < sblock.e2fs_ncg; cg++) { |
261 | numdirs += fs2h16(sblock.e2fs_gd[cg].ext2bgd_ndirs); | | 261 | numdirs += fs2h16(sblock.e2fs_gd[cg].ext2bgd_ndirs); |
262 | } | | 262 | } |
263 | inplast = 0; | | 263 | inplast = 0; |
264 | listmax = numdirs + 10; | | 264 | listmax = numdirs + 10; |
265 | inpsort = calloc((unsigned int)listmax, sizeof(struct inoinfo *)); | | 265 | inpsort = calloc((unsigned int)listmax, sizeof(struct inoinfo *)); |
266 | inphead = calloc((unsigned int)numdirs, sizeof(struct inoinfo *)); | | 266 | inphead = calloc((unsigned int)numdirs, sizeof(struct inoinfo *)); |
267 | if (inpsort == NULL || inphead == NULL) { | | 267 | if (inpsort == NULL || inphead == NULL) { |
268 | printf("cannot alloc %u bytes for inphead\n", | | 268 | printf("cannot alloc %u bytes for inphead\n", |
269 | (unsigned int)(numdirs * sizeof(struct inoinfo *))); | | 269 | (unsigned int)(numdirs * sizeof(struct inoinfo *))); |
270 | goto badsblabel; | | 270 | goto badsblabel; |
271 | } | | 271 | } |
272 | bufinit(); | | 272 | bufinit(); |
273 | return 1; | | 273 | return 1; |
274 | | | 274 | |
275 | badsblabel: | | 275 | badsblabel: |
276 | ckfini(0); | | 276 | ckfini(0); |
277 | return 0; | | 277 | return 0; |
278 | } | | 278 | } |
279 | | | 279 | |
280 | /* | | 280 | /* |
281 | * Read in the super block and its summary info, convert to host byte order. | | 281 | * Read in the super block and its summary info, convert to host byte order. |
282 | */ | | 282 | */ |
283 | static int | | 283 | static int |
284 | readsb(int listerr) | | 284 | readsb(int listerr) |
285 | { | | 285 | { |
286 | daddr_t super = bflag ? bflag : SBOFF / dev_bsize; | | 286 | daddr_t super = bflag ? bflag : SBOFF / dev_bsize; |
287 | | | 287 | |
288 | if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super, (long)SBSIZE) != 0) | | 288 | if (bread(fsreadfd, (char *)sblk.b_un.b_fs, super, (long)SBSIZE) != 0) |
289 | return 0; | | 289 | return 0; |
290 | sblk.b_bno = super; | | 290 | sblk.b_bno = super; |
291 | sblk.b_size = SBSIZE; | | 291 | sblk.b_size = SBSIZE; |
292 | | | 292 | |
293 | /* Copy the superblock in memory */ | | 293 | /* Copy the superblock in memory */ |
294 | e2fs_sbload(sblk.b_un.b_fs, &sblock.e2fs); | | 294 | e2fs_sbload(sblk.b_un.b_fs, &sblock.e2fs); |
295 | | | 295 | |
296 | /* | | 296 | /* |
297 | * run a few consistency checks of the super block | | 297 | * run a few consistency checks of the super block |
298 | */ | | 298 | */ |
299 | if (sblock.e2fs.e2fs_magic != E2FS_MAGIC) { | | 299 | if (sblock.e2fs.e2fs_magic != E2FS_MAGIC) { |
300 | badsb(listerr, "MAGIC NUMBER WRONG"); | | 300 | badsb(listerr, "MAGIC NUMBER WRONG"); |
301 | return 0; | | 301 | return 0; |
302 | } | | 302 | } |
303 | if (sblock.e2fs.e2fs_log_bsize > 2) { | | 303 | if (sblock.e2fs.e2fs_log_bsize > 2) { |
304 | badsb(listerr, "BAD LOG_BSIZE"); | | 304 | badsb(listerr, "BAD LOG_BSIZE"); |
305 | return 0; | | 305 | return 0; |
306 | } | | 306 | } |
307 | if (sblock.e2fs.e2fs_rev > E2FS_REV0 && | | 307 | if (sblock.e2fs.e2fs_rev > E2FS_REV0 && |
308 | (!powerof2(sblock.e2fs.e2fs_inode_size) || | | 308 | (!powerof2(sblock.e2fs.e2fs_inode_size) || |
309 | sblock.e2fs.e2fs_inode_size < sizeof(struct ext2fs_dinode) || | | 309 | sblock.e2fs.e2fs_inode_size < sizeof(struct ext2fs_dinode) || |
310 | sblock.e2fs.e2fs_inode_size > | | 310 | sblock.e2fs.e2fs_inode_size > |
311 | (1024 << sblock.e2fs.e2fs_log_bsize))) { | | 311 | (1024 << sblock.e2fs.e2fs_log_bsize))) { |
312 | badsb(listerr, "BAD INODE_SIZE"); | | 312 | badsb(listerr, "BAD INODE_SIZE"); |
313 | return 0; | | 313 | return 0; |
314 | } | | 314 | } |
315 | | | 315 | |
316 | /* compute the dynamic fields of the in-memory sb */ | | 316 | /* compute the dynamic fields of the in-memory sb */ |
317 | /* compute dynamic sb infos */ | | 317 | /* compute dynamic sb infos */ |
318 | sblock.e2fs_ncg = | | 318 | sblock.e2fs_ncg = |
319 | howmany(sblock.e2fs.e2fs_bcount - sblock.e2fs.e2fs_first_dblock, | | 319 | howmany(sblock.e2fs.e2fs_bcount - sblock.e2fs.e2fs_first_dblock, |
320 | sblock.e2fs.e2fs_bpg); | | 320 | sblock.e2fs.e2fs_bpg); |
321 | /* XXX assume hw bsize = 512 */ | | 321 | /* XXX assume hw bsize = 512 */ |
322 | sblock.e2fs_fsbtodb = sblock.e2fs.e2fs_log_bsize + 1; | | 322 | sblock.e2fs_fsbtodb = sblock.e2fs.e2fs_log_bsize + 1; |
323 | sblock.e2fs_bsize = 1024 << sblock.e2fs.e2fs_log_bsize; | | 323 | sblock.e2fs_bsize = 1024 << sblock.e2fs.e2fs_log_bsize; |
324 | sblock.e2fs_bshift = LOG_MINBSIZE + sblock.e2fs.e2fs_log_bsize; | | 324 | sblock.e2fs_bshift = LOG_MINBSIZE + sblock.e2fs.e2fs_log_bsize; |
325 | sblock.e2fs_qbmask = sblock.e2fs_bsize - 1; | | 325 | sblock.e2fs_qbmask = sblock.e2fs_bsize - 1; |
326 | sblock.e2fs_bmask = ~sblock.e2fs_qbmask; | | 326 | sblock.e2fs_bmask = ~sblock.e2fs_qbmask; |
327 | sblock.e2fs_ngdb = howmany(sblock.e2fs_ncg, | | 327 | sblock.e2fs_ngdb = howmany(sblock.e2fs_ncg, |
328 | sblock.e2fs_bsize / sizeof(struct ext2_gd)); | | 328 | sblock.e2fs_bsize / sizeof(struct ext2_gd)); |
329 | sblock.e2fs_ipb = sblock.e2fs_bsize / EXT2_DINODE_SIZE(&sblock); | | 329 | sblock.e2fs_ipb = sblock.e2fs_bsize / EXT2_DINODE_SIZE(&sblock); |
330 | sblock.e2fs_itpg = howmany(sblock.e2fs.e2fs_ipg, sblock.e2fs_ipb); | | 330 | sblock.e2fs_itpg = howmany(sblock.e2fs.e2fs_ipg, sblock.e2fs_ipb); |
331 | | | 331 | |
332 | /* | | 332 | /* |
333 | * Compute block size that the filesystem is based on, | | 333 | * Compute block size that the filesystem is based on, |
334 | * according to fsbtodb, and adjust superblock block number | | 334 | * according to fsbtodb, and adjust superblock block number |
335 | * so we can tell if this is an alternate later. | | 335 | * so we can tell if this is an alternate later. |
336 | */ | | 336 | */ |
337 | super *= dev_bsize; | | 337 | super *= dev_bsize; |
338 | dev_bsize = sblock.e2fs_bsize / EXT2_FSBTODB(&sblock, 1); | | 338 | dev_bsize = sblock.e2fs_bsize / EXT2_FSBTODB(&sblock, 1); |
339 | sblk.b_bno = super / dev_bsize; | | 339 | sblk.b_bno = super / dev_bsize; |
340 | | | 340 | |
341 | if (sblock.e2fs_ncg == 1) { | | 341 | if (sblock.e2fs_ncg == 1) { |
342 | /* no alternate superblock; assume it's okay */ | | 342 | /* no alternate superblock; assume it's okay */ |
343 | havesb = 1; | | 343 | havesb = 1; |
344 | return 1; | | 344 | return 1; |
345 | } | | 345 | } |
346 | getblk(&asblk, 1 * sblock.e2fs.e2fs_bpg + sblock.e2fs.e2fs_first_dblock, | | 346 | getblk(&asblk, 1 * sblock.e2fs.e2fs_bpg + sblock.e2fs.e2fs_first_dblock, |
347 | (long)SBSIZE); | | 347 | (long)SBSIZE); |
348 | if (asblk.b_errs) | | 348 | if (asblk.b_errs) |
349 | return 0; | | 349 | return 0; |
350 | if (bflag) { | | 350 | if (bflag) { |
351 | havesb = 1; | | 351 | havesb = 1; |
352 | return 1; | | 352 | return 1; |
353 | } | | 353 | } |
354 | | | 354 | |
355 | /* | | 355 | /* |
356 | * Set all possible fields that could differ, then do check | | 356 | * Set all possible fields that could differ, then do check |
357 | * of whole super block against an alternate super block. | | 357 | * of whole super block against an alternate super block. |
358 | * When an alternate super-block is specified this check is skipped. | | 358 | * When an alternate super-block is specified this check is skipped. |
359 | */ | | 359 | */ |
360 | asblk.b_un.b_fs->e2fs_rbcount = sblk.b_un.b_fs->e2fs_rbcount; | | 360 | asblk.b_un.b_fs->e2fs_rbcount = sblk.b_un.b_fs->e2fs_rbcount; |
361 | asblk.b_un.b_fs->e2fs_fbcount = sblk.b_un.b_fs->e2fs_fbcount; | | 361 | asblk.b_un.b_fs->e2fs_fbcount = sblk.b_un.b_fs->e2fs_fbcount; |
362 | asblk.b_un.b_fs->e2fs_ficount = sblk.b_un.b_fs->e2fs_ficount; | | 362 | asblk.b_un.b_fs->e2fs_ficount = sblk.b_un.b_fs->e2fs_ficount; |
363 | asblk.b_un.b_fs->e2fs_mtime = sblk.b_un.b_fs->e2fs_mtime; | | 363 | asblk.b_un.b_fs->e2fs_mtime = sblk.b_un.b_fs->e2fs_mtime; |
364 | asblk.b_un.b_fs->e2fs_wtime = sblk.b_un.b_fs->e2fs_wtime; | | 364 | asblk.b_un.b_fs->e2fs_wtime = sblk.b_un.b_fs->e2fs_wtime; |
365 | asblk.b_un.b_fs->e2fs_mnt_count = sblk.b_un.b_fs->e2fs_mnt_count; | | 365 | asblk.b_un.b_fs->e2fs_mnt_count = sblk.b_un.b_fs->e2fs_mnt_count; |
366 | asblk.b_un.b_fs->e2fs_max_mnt_count = | | 366 | asblk.b_un.b_fs->e2fs_max_mnt_count = |
367 | sblk.b_un.b_fs->e2fs_max_mnt_count; | | 367 | sblk.b_un.b_fs->e2fs_max_mnt_count; |
368 | asblk.b_un.b_fs->e2fs_state = sblk.b_un.b_fs->e2fs_state; | | 368 | asblk.b_un.b_fs->e2fs_state = sblk.b_un.b_fs->e2fs_state; |
369 | asblk.b_un.b_fs->e2fs_beh = sblk.b_un.b_fs->e2fs_beh; | | 369 | asblk.b_un.b_fs->e2fs_beh = sblk.b_un.b_fs->e2fs_beh; |
370 | asblk.b_un.b_fs->e2fs_lastfsck = sblk.b_un.b_fs->e2fs_lastfsck; | | 370 | asblk.b_un.b_fs->e2fs_lastfsck = sblk.b_un.b_fs->e2fs_lastfsck; |
371 | asblk.b_un.b_fs->e2fs_fsckintv = sblk.b_un.b_fs->e2fs_fsckintv; | | 371 | asblk.b_un.b_fs->e2fs_fsckintv = sblk.b_un.b_fs->e2fs_fsckintv; |
372 | asblk.b_un.b_fs->e2fs_ruid = sblk.b_un.b_fs->e2fs_ruid; | | 372 | asblk.b_un.b_fs->e2fs_ruid = sblk.b_un.b_fs->e2fs_ruid; |
373 | asblk.b_un.b_fs->e2fs_rgid = sblk.b_un.b_fs->e2fs_rgid; | | 373 | asblk.b_un.b_fs->e2fs_rgid = sblk.b_un.b_fs->e2fs_rgid; |
374 | asblk.b_un.b_fs->e2fs_block_group_nr = | | 374 | asblk.b_un.b_fs->e2fs_block_group_nr = |
375 | sblk.b_un.b_fs->e2fs_block_group_nr; | | 375 | sblk.b_un.b_fs->e2fs_block_group_nr; |
376 | asblk.b_un.b_fs->e2fs_features_rocompat &= ~EXT2F_ROCOMPAT_LARGEFILE; | | 376 | asblk.b_un.b_fs->e2fs_features_rocompat &= ~EXT2F_ROCOMPAT_LARGEFILE; |
377 | asblk.b_un.b_fs->e2fs_features_rocompat |= | | 377 | asblk.b_un.b_fs->e2fs_features_rocompat |= |
378 | sblk.b_un.b_fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE; | | 378 | sblk.b_un.b_fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE; |
379 | if (sblock.e2fs.e2fs_rev > E2FS_REV0 && | | 379 | if (sblock.e2fs.e2fs_rev > E2FS_REV0 && |
380 | ((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) || | | 380 | ((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) || |
381 | (sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP))) { | | 381 | (sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP))) { |
382 | if (debug) { | | 382 | if (debug) { |
383 | printf("compat 0x%08x, incompat 0x%08x, compat_ro " | | 383 | printf("compat 0x%08x, incompat 0x%08x, compat_ro " |
384 | "0x%08x\n", | | 384 | "0x%08x\n", |
385 | sblock.e2fs.e2fs_features_compat, | | 385 | sblock.e2fs.e2fs_features_compat, |
386 | sblock.e2fs.e2fs_features_incompat, | | 386 | sblock.e2fs.e2fs_features_incompat, |
387 | sblock.e2fs.e2fs_features_rocompat); | | 387 | sblock.e2fs.e2fs_features_rocompat); |
388 | } | | 388 | } |
389 | badsb(listerr, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK"); | | 389 | badsb(listerr, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK"); |
390 | return 0; | | 390 | return 0; |
391 | } | | 391 | } |
392 | if (memcmp(sblk.b_un.b_fs, asblk.b_un.b_fs, SBSIZE)) { | | 392 | if (memcmp(sblk.b_un.b_fs, asblk.b_un.b_fs, SBSIZE)) { |
393 | if (debug) { | | 393 | if (debug) { |
394 | u_int32_t *nlp, *olp, *endlp; | | 394 | u_int32_t *nlp, *olp, *endlp; |
395 | | | 395 | |
396 | printf("superblock mismatches\n"); | | 396 | printf("superblock mismatches\n"); |
397 | nlp = (u_int32_t *)asblk.b_un.b_fs; | | 397 | nlp = (u_int32_t *)asblk.b_un.b_fs; |
398 | olp = (u_int32_t *)sblk.b_un.b_fs; | | 398 | olp = (u_int32_t *)sblk.b_un.b_fs; |
399 | endlp = olp + (SBSIZE / sizeof(*olp)); | | 399 | endlp = olp + (SBSIZE / sizeof(*olp)); |
400 | for ( ; olp < endlp; olp++, nlp++) { | | 400 | for ( ; olp < endlp; olp++, nlp++) { |
401 | if (*olp == *nlp) | | 401 | if (*olp == *nlp) |
402 | continue; | | 402 | continue; |
403 | printf("offset %ld, original %ld, " | | 403 | printf("offset %ld, original %ld, " |
404 | "alternate %ld\n", | | 404 | "alternate %ld\n", |
405 | (long)(olp - (u_int32_t *)sblk.b_un.b_fs), | | 405 | (long)(olp - (u_int32_t *)sblk.b_un.b_fs), |
406 | (long)fs2h32(*olp), | | 406 | (long)fs2h32(*olp), |
407 | (long)fs2h32(*nlp)); | | 407 | (long)fs2h32(*nlp)); |
408 | } | | 408 | } |
409 | } | | 409 | } |
410 | badsb(listerr, | | 410 | badsb(listerr, |
411 | "VALUES IN SUPER BLOCK DISAGREE WITH " | | 411 | "VALUES IN SUPER BLOCK DISAGREE WITH " |
412 | "THOSE IN FIRST ALTERNATE"); | | 412 | "THOSE IN FIRST ALTERNATE"); |
413 | return 0; | | 413 | return 0; |
414 | } | | 414 | } |
415 | havesb = 1; | | 415 | havesb = 1; |
416 | return 1; | | 416 | return 1; |
417 | } | | 417 | } |
418 | | | 418 | |
419 | void | | 419 | void |
420 | copyback_sb(struct bufarea *bp) | | 420 | copyback_sb(struct bufarea *bp) |
421 | { | | 421 | { |
422 | /* Copy the in-memory superblock back to buffer */ | | 422 | /* Copy the in-memory superblock back to buffer */ |
423 | bp->b_un.b_fs->e2fs_icount = h2fs32(sblock.e2fs.e2fs_icount); | | 423 | bp->b_un.b_fs->e2fs_icount = h2fs32(sblock.e2fs.e2fs_icount); |
424 | bp->b_un.b_fs->e2fs_bcount = h2fs32(sblock.e2fs.e2fs_bcount); | | 424 | bp->b_un.b_fs->e2fs_bcount = h2fs32(sblock.e2fs.e2fs_bcount); |
425 | bp->b_un.b_fs->e2fs_rbcount = h2fs32(sblock.e2fs.e2fs_rbcount); | | 425 | bp->b_un.b_fs->e2fs_rbcount = h2fs32(sblock.e2fs.e2fs_rbcount); |
426 | bp->b_un.b_fs->e2fs_fbcount = h2fs32(sblock.e2fs.e2fs_fbcount); | | 426 | bp->b_un.b_fs->e2fs_fbcount = h2fs32(sblock.e2fs.e2fs_fbcount); |
427 | bp->b_un.b_fs->e2fs_ficount = h2fs32(sblock.e2fs.e2fs_ficount); | | 427 | bp->b_un.b_fs->e2fs_ficount = h2fs32(sblock.e2fs.e2fs_ficount); |
428 | bp->b_un.b_fs->e2fs_first_dblock = | | 428 | bp->b_un.b_fs->e2fs_first_dblock = |
429 | h2fs32(sblock.e2fs.e2fs_first_dblock); | | 429 | h2fs32(sblock.e2fs.e2fs_first_dblock); |
430 | bp->b_un.b_fs->e2fs_log_bsize = h2fs32(sblock.e2fs.e2fs_log_bsize); | | 430 | bp->b_un.b_fs->e2fs_log_bsize = h2fs32(sblock.e2fs.e2fs_log_bsize); |
431 | bp->b_un.b_fs->e2fs_fsize = h2fs32(sblock.e2fs.e2fs_fsize); | | 431 | bp->b_un.b_fs->e2fs_fsize = h2fs32(sblock.e2fs.e2fs_fsize); |
432 | bp->b_un.b_fs->e2fs_bpg = h2fs32(sblock.e2fs.e2fs_bpg); | | 432 | bp->b_un.b_fs->e2fs_bpg = h2fs32(sblock.e2fs.e2fs_bpg); |
433 | bp->b_un.b_fs->e2fs_fpg = h2fs32(sblock.e2fs.e2fs_fpg); | | 433 | bp->b_un.b_fs->e2fs_fpg = h2fs32(sblock.e2fs.e2fs_fpg); |
434 | bp->b_un.b_fs->e2fs_ipg = h2fs32(sblock.e2fs.e2fs_ipg); | | 434 | bp->b_un.b_fs->e2fs_ipg = h2fs32(sblock.e2fs.e2fs_ipg); |
435 | bp->b_un.b_fs->e2fs_mtime = h2fs32(sblock.e2fs.e2fs_mtime); | | 435 | bp->b_un.b_fs->e2fs_mtime = h2fs32(sblock.e2fs.e2fs_mtime); |
436 | bp->b_un.b_fs->e2fs_wtime = h2fs32(sblock.e2fs.e2fs_wtime); | | 436 | bp->b_un.b_fs->e2fs_wtime = h2fs32(sblock.e2fs.e2fs_wtime); |
437 | bp->b_un.b_fs->e2fs_lastfsck = h2fs32(sblock.e2fs.e2fs_lastfsck); | | 437 | bp->b_un.b_fs->e2fs_lastfsck = h2fs32(sblock.e2fs.e2fs_lastfsck); |
438 | bp->b_un.b_fs->e2fs_fsckintv = h2fs32(sblock.e2fs.e2fs_fsckintv); | | 438 | bp->b_un.b_fs->e2fs_fsckintv = h2fs32(sblock.e2fs.e2fs_fsckintv); |
439 | bp->b_un.b_fs->e2fs_creator = h2fs32(sblock.e2fs.e2fs_creator); | | 439 | bp->b_un.b_fs->e2fs_creator = h2fs32(sblock.e2fs.e2fs_creator); |
440 | bp->b_un.b_fs->e2fs_rev = h2fs32(sblock.e2fs.e2fs_rev); | | 440 | bp->b_un.b_fs->e2fs_rev = h2fs32(sblock.e2fs.e2fs_rev); |
441 | bp->b_un.b_fs->e2fs_mnt_count = h2fs16(sblock.e2fs.e2fs_mnt_count); | | 441 | bp->b_un.b_fs->e2fs_mnt_count = h2fs16(sblock.e2fs.e2fs_mnt_count); |
442 | bp->b_un.b_fs->e2fs_max_mnt_count = | | 442 | bp->b_un.b_fs->e2fs_max_mnt_count = |
443 | h2fs16(sblock.e2fs.e2fs_max_mnt_count); | | 443 | h2fs16(sblock.e2fs.e2fs_max_mnt_count); |
444 | bp->b_un.b_fs->e2fs_magic = h2fs16(sblock.e2fs.e2fs_magic); | | 444 | bp->b_un.b_fs->e2fs_magic = h2fs16(sblock.e2fs.e2fs_magic); |
445 | bp->b_un.b_fs->e2fs_state = h2fs16(sblock.e2fs.e2fs_state); | | 445 | bp->b_un.b_fs->e2fs_state = h2fs16(sblock.e2fs.e2fs_state); |
446 | bp->b_un.b_fs->e2fs_beh = h2fs16(sblock.e2fs.e2fs_beh); | | 446 | bp->b_un.b_fs->e2fs_beh = h2fs16(sblock.e2fs.e2fs_beh); |
447 | bp->b_un.b_fs->e2fs_ruid = h2fs16(sblock.e2fs.e2fs_ruid); | | 447 | bp->b_un.b_fs->e2fs_ruid = h2fs16(sblock.e2fs.e2fs_ruid); |
448 | bp->b_un.b_fs->e2fs_rgid = h2fs16(sblock.e2fs.e2fs_rgid); | | 448 | bp->b_un.b_fs->e2fs_rgid = h2fs16(sblock.e2fs.e2fs_rgid); |
449 | } | | 449 | } |
450 | | | 450 | |
451 | void | | 451 | void |
452 | badsb(int listerr, const char *s) | | 452 | badsb(int listerr, const char *s) |
453 | { | | 453 | { |
454 | | | 454 | |
455 | if (!listerr) | | 455 | if (!listerr) |
456 | return; | | 456 | return; |
457 | if (preen) | | 457 | if (preen) |
458 | printf("%s: ", cdevname()); | | 458 | printf("%s: ", cdevname()); |
459 | pfatal("BAD SUPER BLOCK: %s\n", s); | | 459 | pfatal("BAD SUPER BLOCK: %s\n", s); |
460 | } | | 460 | } |
461 | | | 461 | |
462 | /* | | 462 | /* |
463 | * Calculate a prototype superblock based on information in the disk label. | | 463 | * Calculate a prototype superblock based on information in the disk label. |
464 | * When done the cgsblock macro can be calculated and the fs_ncg field | | 464 | * When done the cgsblock macro can be calculated and the fs_ncg field |
465 | * can be used. Do NOT attempt to use other macros without verifying that | | 465 | * can be used. Do NOT attempt to use other macros without verifying that |
466 | * their needed information is available! | | 466 | * their needed information is available! |
467 | */ | | 467 | */ |
468 | | | 468 | |
469 | int | | 469 | int |
470 | calcsb(const char *dev, int devfd, struct m_ext2fs *fs) | | 470 | calcsb(const char *dev, int devfd, struct m_ext2fs *fs) |
471 | { | | 471 | { |
472 | struct disklabel *lp; | | 472 | struct disklabel *lp; |
473 | struct partition *pp; | | 473 | struct partition *pp; |
474 | char *cp; | | 474 | char *cp; |
475 | | | 475 | |
476 | cp = strchr(dev, '\0'); | | 476 | cp = strchr(dev, '\0'); |
477 | if (cp-- == dev || | | 477 | if (cp-- == dev || |
478 | ((*cp < 'a' || *cp > 'h') && !isdigit((unsigned char)*cp))) { | | 478 | ((*cp < 'a' || *cp > 'h') && !isdigit((unsigned char)*cp))) { |
479 | pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); | | 479 | pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); |
480 | return 0; | | 480 | return 0; |
481 | } | | 481 | } |
482 | lp = getdisklabel(dev, devfd); | | 482 | lp = getdisklabel(dev, devfd); |
483 | if (isdigit((unsigned char)*cp)) | | 483 | if (isdigit((unsigned char)*cp)) |
484 | pp = &lp->d_partitions[0]; | | 484 | pp = &lp->d_partitions[0]; |
485 | else | | 485 | else |
486 | pp = &lp->d_partitions[*cp - 'a']; | | 486 | pp = &lp->d_partitions[*cp - 'a']; |
487 | if (pp->p_fstype != FS_EX2FS) { | | 487 | if (pp->p_fstype != FS_EX2FS) { |
488 | pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n", | | 488 | pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n", |
489 | dev, pp->p_fstype < FSMAXTYPES ? | | 489 | dev, pp->p_fstype < FSMAXTYPES ? |
490 | fstypenames[pp->p_fstype] : "unknown"); | | 490 | fstypenames[pp->p_fstype] : "unknown"); |
491 | return 0; | | 491 | return 0; |
492 | } | | 492 | } |
| | | 493 | if (pp->p_fsize == 0) { |
| | | 494 | pfatal("%s: PARTITION SIZE IS 0\n", dev); |
| | | 495 | return 0; |
| | | 496 | } |
493 | memset(fs, 0, sizeof(struct m_ext2fs)); | | 497 | memset(fs, 0, sizeof(struct m_ext2fs)); |
494 | fs->e2fs_bsize = pp->p_fsize; | | 498 | fs->e2fs_bsize = pp->p_fsize; |
495 | fs->e2fs.e2fs_log_bsize = pp->p_fsize / 1024; | | 499 | fs->e2fs.e2fs_log_bsize = pp->p_fsize / 1024; |
496 | fs->e2fs.e2fs_bcount = (pp->p_size * DEV_BSIZE) / fs->e2fs_bsize; | | 500 | fs->e2fs.e2fs_bcount = (pp->p_size * DEV_BSIZE) / fs->e2fs_bsize; |
497 | fs->e2fs.e2fs_first_dblock = (fs->e2fs.e2fs_log_bsize == 0) ? 1 : 0; | | 501 | fs->e2fs.e2fs_first_dblock = (fs->e2fs.e2fs_log_bsize == 0) ? 1 : 0; |
498 | fs->e2fs.e2fs_bpg = fs->e2fs_bsize * NBBY; | | 502 | fs->e2fs.e2fs_bpg = fs->e2fs_bsize * NBBY; |
499 | fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; | | 503 | fs->e2fs_bshift = LOG_MINBSIZE + fs->e2fs.e2fs_log_bsize; |
500 | fs->e2fs_qbmask = fs->e2fs_bsize - 1; | | 504 | fs->e2fs_qbmask = fs->e2fs_bsize - 1; |
501 | fs->e2fs_bmask = ~fs->e2fs_qbmask; | | 505 | fs->e2fs_bmask = ~fs->e2fs_qbmask; |
502 | fs->e2fs_ncg = | | 506 | fs->e2fs_ncg = |
503 | howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, | | 507 | howmany(fs->e2fs.e2fs_bcount - fs->e2fs.e2fs_first_dblock, |
504 | fs->e2fs.e2fs_bpg); | | 508 | fs->e2fs.e2fs_bpg); |
505 | fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; | | 509 | fs->e2fs_fsbtodb = fs->e2fs.e2fs_log_bsize + 1; |
506 | fs->e2fs_ngdb = howmany(fs->e2fs_ncg, | | 510 | fs->e2fs_ngdb = howmany(fs->e2fs_ncg, |
507 | fs->e2fs_bsize / sizeof(struct ext2_gd)); | | 511 | fs->e2fs_bsize / sizeof(struct ext2_gd)); |
508 | | | 512 | |
509 | return 1; | | 513 | return 1; |
510 | } | | 514 | } |
511 | | | 515 | |
512 | static struct disklabel * | | 516 | static struct disklabel * |
513 | getdisklabel(const char *s, int fd) | | 517 | getdisklabel(const char *s, int fd) |
514 | { | | 518 | { |
515 | static struct disklabel lab; | | 519 | static struct disklabel lab; |
516 | | | 520 | |
517 | if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { | | 521 | if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { |
518 | if (s == NULL) | | 522 | if (s == NULL) |
519 | return NULL; | | 523 | return NULL; |
520 | pwarn("ioctl (GCINFO): %s\n", strerror(errno)); | | 524 | pwarn("ioctl (GCINFO): %s\n", strerror(errno)); |
521 | errexit("%s: can't read disk label", s); | | 525 | errexit("%s: can't read disk label", s); |
522 | } | | 526 | } |
523 | return &lab; | | 527 | return &lab; |
524 | } | | 528 | } |
525 | | | 529 | |
526 | daddr_t | | 530 | daddr_t |
527 | cgoverhead(int c) | | 531 | cgoverhead(int c) |
528 | { | | 532 | { |
529 | int overh; | | 533 | int overh; |
530 | overh = | | 534 | overh = |
531 | 1 /* block bitmap */ + | | 535 | 1 /* block bitmap */ + |
532 | 1 /* inode bitmap */ + | | 536 | 1 /* inode bitmap */ + |
533 | sblock.e2fs_itpg; | | 537 | sblock.e2fs_itpg; |
534 | if (sblock.e2fs.e2fs_rev > E2FS_REV0 && | | 538 | if (sblock.e2fs.e2fs_rev > E2FS_REV0 && |
535 | sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { | | 539 | sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_SPARSESUPER) { |
536 | if (cg_has_sb(c) == 0) | | 540 | if (cg_has_sb(c) == 0) |
537 | return overh; | | 541 | return overh; |
538 | } | | 542 | } |
539 | overh += 1 /* superblock */ + sblock.e2fs_ngdb; | | 543 | overh += 1 /* superblock */ + sblock.e2fs_ngdb; |
540 | return overh; | | 544 | return overh; |
541 | } | | 545 | } |