| @@ -1,1613 +1,1613 @@ | | | @@ -1,1613 +1,1613 @@ |
1 | /* $NetBSD: mkfs.c,v 1.136 2024/02/22 02:11:29 mrg Exp $ */ | | 1 | /* $NetBSD: mkfs.c,v 1.137 2024/05/10 20:36:34 andvar Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1980, 1989, 1993 | | 4 | * Copyright (c) 1980, 1989, 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) 2002 Networks Associates Technology, Inc. | | 33 | * Copyright (c) 2002 Networks Associates Technology, Inc. |
34 | * All rights reserved. | | 34 | * All rights reserved. |
35 | * | | 35 | * |
36 | * This software was developed for the FreeBSD Project by Marshall | | 36 | * This software was developed for the FreeBSD Project by Marshall |
37 | * Kirk McKusick and Network Associates Laboratories, the Security | | 37 | * Kirk McKusick and Network Associates Laboratories, the Security |
38 | * Research Division of Network Associates, Inc. under DARPA/SPAWAR | | 38 | * Research Division of Network Associates, Inc. under DARPA/SPAWAR |
39 | * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS | | 39 | * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS |
40 | * research program | | 40 | * research program |
41 | * | | 41 | * |
42 | * Redistribution and use in source and binary forms, with or without | | 42 | * Redistribution and use in source and binary forms, with or without |
43 | * modification, are permitted provided that the following conditions | | 43 | * modification, are permitted provided that the following conditions |
44 | * are met: | | 44 | * are met: |
45 | * 1. Redistributions of source code must retain the above copyright | | 45 | * 1. Redistributions of source code must retain the above copyright |
46 | * notice, this list of conditions and the following disclaimer. | | 46 | * notice, this list of conditions and the following disclaimer. |
47 | * 2. Redistributions in binary form must reproduce the above copyright | | 47 | * 2. Redistributions in binary form must reproduce the above copyright |
48 | * notice, this list of conditions and the following disclaimer in the | | 48 | * notice, this list of conditions and the following disclaimer in the |
49 | * documentation and/or other materials provided with the distribution. | | 49 | * documentation and/or other materials provided with the distribution. |
50 | * 3. All advertising materials mentioning features or use of this software | | 50 | * 3. All advertising materials mentioning features or use of this software |
51 | * must display the following acknowledgement: | | 51 | * must display the following acknowledgement: |
52 | * This product includes software developed by the University of | | 52 | * This product includes software developed by the University of |
53 | * California, Berkeley and its contributors. | | 53 | * California, Berkeley and its contributors. |
54 | * 4. Neither the name of the University nor the names of its contributors | | 54 | * 4. Neither the name of the University nor the names of its contributors |
55 | * may be used to endorse or promote products derived from this software | | 55 | * may be used to endorse or promote products derived from this software |
56 | * without specific prior written permission. | | 56 | * without specific prior written permission. |
57 | * | | 57 | * |
58 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 58 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 59 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 60 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 61 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 62 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 63 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 64 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 65 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 66 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 67 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
68 | * SUCH DAMAGE. | | 68 | * SUCH DAMAGE. |
69 | */ | | 69 | */ |
70 | | | 70 | |
71 | #include <sys/cdefs.h> | | 71 | #include <sys/cdefs.h> |
72 | #ifndef lint | | 72 | #ifndef lint |
73 | #if 0 | | 73 | #if 0 |
74 | static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; | | 74 | static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; |
75 | #else | | 75 | #else |
76 | __RCSID("$NetBSD: mkfs.c,v 1.136 2024/02/22 02:11:29 mrg Exp $"); | | 76 | __RCSID("$NetBSD: mkfs.c,v 1.137 2024/05/10 20:36:34 andvar Exp $"); |
77 | #endif | | 77 | #endif |
78 | #endif /* not lint */ | | 78 | #endif /* not lint */ |
79 | | | 79 | |
80 | #include <sys/param.h> | | 80 | #include <sys/param.h> |
81 | #include <sys/mman.h> | | 81 | #include <sys/mman.h> |
82 | #include <sys/time.h> | | 82 | #include <sys/time.h> |
83 | #include <sys/resource.h> | | 83 | #include <sys/resource.h> |
84 | #include <ufs/ufs/dinode.h> | | 84 | #include <ufs/ufs/dinode.h> |
85 | #include <ufs/ufs/dir.h> | | 85 | #include <ufs/ufs/dir.h> |
86 | #include <ufs/ufs/ufs_bswap.h> | | 86 | #include <ufs/ufs/ufs_bswap.h> |
87 | #include <ufs/ufs/quota2.h> | | 87 | #include <ufs/ufs/quota2.h> |
88 | #include <ufs/ffs/fs.h> | | 88 | #include <ufs/ffs/fs.h> |
89 | #include <ufs/ffs/ffs_extern.h> | | 89 | #include <ufs/ffs/ffs_extern.h> |
90 | #include <sys/ioctl.h> | | 90 | #include <sys/ioctl.h> |
91 | #include <sys/disklabel.h> | | 91 | #include <sys/disklabel.h> |
92 | | | 92 | |
93 | #include <err.h> | | 93 | #include <err.h> |
94 | #include <errno.h> | | 94 | #include <errno.h> |
95 | #include <string.h> | | 95 | #include <string.h> |
96 | #include <unistd.h> | | 96 | #include <unistd.h> |
97 | #include <stdlib.h> | | 97 | #include <stdlib.h> |
98 | #include <stddef.h> | | 98 | #include <stddef.h> |
99 | | | 99 | |
100 | #ifndef STANDALONE | | 100 | #ifndef STANDALONE |
101 | #include <stdio.h> | | 101 | #include <stdio.h> |
102 | #endif | | 102 | #endif |
103 | | | 103 | |
104 | #include "extern.h" | | 104 | #include "extern.h" |
105 | | | 105 | |
106 | union dinode { | | 106 | union dinode { |
107 | struct ufs1_dinode dp1; | | 107 | struct ufs1_dinode dp1; |
108 | struct ufs2_dinode dp2; | | 108 | struct ufs2_dinode dp2; |
109 | }; | | 109 | }; |
110 | | | 110 | |
111 | static void initcg(uint32_t, const struct timeval *); | | 111 | static void initcg(uint32_t, const struct timeval *); |
112 | static int fsinit(const struct timeval *, mode_t, uid_t, gid_t); | | 112 | static int fsinit(const struct timeval *, mode_t, uid_t, gid_t); |
113 | union Buffer; | | 113 | union Buffer; |
114 | static int makedir(union Buffer *, struct direct *, int); | | 114 | static int makedir(union Buffer *, struct direct *, int); |
115 | static daddr_t alloc(int, int); | | 115 | static daddr_t alloc(int, int); |
116 | static void iput(union dinode *, ino_t); | | 116 | static void iput(union dinode *, ino_t); |
117 | static void rdfs(daddr_t, int, void *); | | 117 | static void rdfs(daddr_t, int, void *); |
118 | static void wtfs(daddr_t, int, void *); | | 118 | static void wtfs(daddr_t, int, void *); |
119 | static int isblock(struct fs *, unsigned char *, int); | | 119 | static int isblock(struct fs *, unsigned char *, int); |
120 | static void clrblock(struct fs *, unsigned char *, int); | | 120 | static void clrblock(struct fs *, unsigned char *, int); |
121 | static void setblock(struct fs *, unsigned char *, int); | | 121 | static void setblock(struct fs *, unsigned char *, int); |
122 | static int ilog2(int); | | 122 | static int ilog2(int); |
123 | static void zap_old_sblock(int); | | 123 | static void zap_old_sblock(int); |
124 | #ifdef MFS | | 124 | #ifdef MFS |
125 | static void *mkfs_malloc(size_t size); | | 125 | static void *mkfs_malloc(size_t size); |
126 | #endif | | 126 | #endif |
127 | | | 127 | |
128 | /* | | 128 | /* |
129 | * make file system for cylinder-group style file systems | | 129 | * make file system for cylinder-group style file systems |
130 | */ | | 130 | */ |
131 | #define UMASK 0755 | | 131 | #define UMASK 0755 |
132 | | | 132 | |
133 | union { | | 133 | union { |
134 | struct fs fs; | | 134 | struct fs fs; |
135 | char data[SBLOCKSIZE]; | | 135 | char data[SBLOCKSIZE]; |
136 | } *fsun; | | 136 | } *fsun; |
137 | #define sblock fsun->fs | | 137 | #define sblock fsun->fs |
138 | | | 138 | |
139 | union Buffer { | | 139 | union Buffer { |
140 | struct quota2_header q2h; | | 140 | struct quota2_header q2h; |
141 | char data[MAXBSIZE]; | | 141 | char data[MAXBSIZE]; |
142 | }; | | 142 | }; |
143 | | | 143 | |
144 | struct csum *fscs_0; /* first block of cylinder summaries */ | | 144 | struct csum *fscs_0; /* first block of cylinder summaries */ |
145 | struct csum *fscs_next; /* place for next summary */ | | 145 | struct csum *fscs_next; /* place for next summary */ |
146 | struct csum *fscs_end; /* end of summary buffer */ | | 146 | struct csum *fscs_end; /* end of summary buffer */ |
147 | struct csum *fscs_reset; /* place for next summary after write */ | | 147 | struct csum *fscs_reset; /* place for next summary after write */ |
148 | uint fs_csaddr; /* fragment number to write to */ | | 148 | uint fs_csaddr; /* fragment number to write to */ |
149 | | | 149 | |
150 | union { | | 150 | union { |
151 | struct cg cg; | | 151 | struct cg cg; |
152 | char pad[MAXBSIZE]; | | 152 | char pad[MAXBSIZE]; |
153 | } *cgun; | | 153 | } *cgun; |
154 | #define acg cgun->cg | | 154 | #define acg cgun->cg |
155 | | | 155 | |
156 | #define DIP(dp, field) \ | | 156 | #define DIP(dp, field) \ |
157 | ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ | | 157 | ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ |
158 | (dp)->dp1.di_##field : (dp)->dp2.di_##field) | | 158 | (dp)->dp1.di_##field : (dp)->dp2.di_##field) |
159 | | | 159 | |
160 | #define EXT2FS_SBOFF 1024 /* XXX: SBOFF in <ufs/ext2fs/ext2fs.h> */ | | 160 | #define EXT2FS_SBOFF 1024 /* XXX: SBOFF in <ufs/ext2fs/ext2fs.h> */ |
161 | | | 161 | |
162 | char *iobuf; | | 162 | char *iobuf; |
163 | int iobufsize; /* size to end of 2nd inode block */ | | 163 | int iobufsize; /* size to end of 2nd inode block */ |
164 | int iobuf_memsize; /* Actual buffer size */ | | 164 | int iobuf_memsize; /* Actual buffer size */ |
165 | | | 165 | |
166 | int fsi, fso; | | 166 | int fsi, fso; |
167 | | | 167 | |
168 | static void | | 168 | static void |
169 | fserr(int num) | | 169 | fserr(int num) |
170 | { | | 170 | { |
171 | #ifdef GARBAGE | | 171 | #ifdef GARBAGE |
172 | extern int Gflag; | | 172 | extern int Gflag; |
173 | | | 173 | |
174 | if (Gflag) | | 174 | if (Gflag) |
175 | return; | | 175 | return; |
176 | #endif | | 176 | #endif |
177 | exit(num); | | 177 | exit(num); |
178 | } | | 178 | } |
179 | | | 179 | |
180 | void | | 180 | void |
181 | mkfs(const char *fsys, int fi, int fo, | | 181 | mkfs(const char *fsys, int fi, int fo, |
182 | mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) | | 182 | mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) |
183 | { | | 183 | { |
184 | uint fragsperinodeblk, ncg, u; | | 184 | uint fragsperinodeblk, ncg, u; |
185 | uint cgzero; | | 185 | uint cgzero; |
186 | uint64_t inodeblks, cgall; | | 186 | uint64_t inodeblks, cgall; |
187 | uint32_t cylno; | | 187 | uint32_t cylno; |
188 | int i, csfrags; | | 188 | int i, csfrags; |
189 | int inodes_per_cg; | | 189 | int inodes_per_cg; |
190 | struct timeval tv; | | 190 | struct timeval tv; |
191 | long long sizepb; | | 191 | long long sizepb; |
192 | int len, col, delta, fld_width, max_cols; | | 192 | int len, col, delta, fld_width, max_cols; |
193 | struct winsize winsize; | | 193 | struct winsize winsize; |
194 | | | 194 | |
195 | #ifndef STANDALONE | | 195 | #ifndef STANDALONE |
196 | gettimeofday(&tv, NULL); | | 196 | gettimeofday(&tv, NULL); |
197 | #endif | | 197 | #endif |
198 | #ifdef MFS | | 198 | #ifdef MFS |
199 | if (mfs && !Nflag) { | | 199 | if (mfs && !Nflag) { |
200 | if ((membase = mkfs_malloc(fssize * sectorsize)) == NULL) | | 200 | if ((membase = mkfs_malloc(fssize * sectorsize)) == NULL) |
201 | exit(12); | | 201 | exit(12); |
202 | } | | 202 | } |
203 | #endif | | 203 | #endif |
204 | if ((fsun = aligned_alloc(DEV_BSIZE, sizeof(*fsun))) == NULL) | | 204 | if ((fsun = aligned_alloc(DEV_BSIZE, sizeof(*fsun))) == NULL) |
205 | exit(12); | | 205 | exit(12); |
206 | memset(fsun, 0, sizeof(*fsun)); | | 206 | memset(fsun, 0, sizeof(*fsun)); |
207 | if ((cgun = aligned_alloc(DEV_BSIZE, sizeof(*cgun))) == NULL) | | 207 | if ((cgun = aligned_alloc(DEV_BSIZE, sizeof(*cgun))) == NULL) |
208 | exit(12); | | 208 | exit(12); |
209 | memset(cgun, 0, sizeof(*cgun)); | | 209 | memset(cgun, 0, sizeof(*cgun)); |
210 | | | 210 | |
211 | fsi = fi; | | 211 | fsi = fi; |
212 | fso = fo; | | 212 | fso = fo; |
213 | if (Oflag == 0) { | | 213 | if (Oflag == 0) { |
214 | sblock.fs_old_inodefmt = FS_42INODEFMT; | | 214 | sblock.fs_old_inodefmt = FS_42INODEFMT; |
215 | sblock.fs_maxsymlinklen = 0; | | 215 | sblock.fs_maxsymlinklen = 0; |
216 | sblock.fs_old_flags = 0; | | 216 | sblock.fs_old_flags = 0; |
217 | } else { | | 217 | } else { |
218 | sblock.fs_old_inodefmt = FS_44INODEFMT; | | 218 | sblock.fs_old_inodefmt = FS_44INODEFMT; |
219 | sblock.fs_maxsymlinklen = (Oflag == 1 ? UFS1_MAXSYMLINKLEN : | | 219 | sblock.fs_maxsymlinklen = (Oflag == 1 ? UFS1_MAXSYMLINKLEN : |
220 | UFS2_MAXSYMLINKLEN); | | 220 | UFS2_MAXSYMLINKLEN); |
221 | sblock.fs_old_flags = FS_FLAGS_UPDATED; | | 221 | sblock.fs_old_flags = FS_FLAGS_UPDATED; |
222 | if (isappleufs) | | 222 | if (isappleufs) |
223 | sblock.fs_old_flags = 0; | | 223 | sblock.fs_old_flags = 0; |
224 | sblock.fs_flags = 0; | | 224 | sblock.fs_flags = 0; |
225 | } | | 225 | } |
226 | | | 226 | |
227 | /* | | 227 | /* |
228 | * collect and verify the filesystem density info | | 228 | * collect and verify the filesystem density info |
229 | */ | | 229 | */ |
230 | sblock.fs_avgfilesize = avgfilesize; | | 230 | sblock.fs_avgfilesize = avgfilesize; |
231 | sblock.fs_avgfpdir = avgfpdir; | | 231 | sblock.fs_avgfpdir = avgfpdir; |
232 | if (sblock.fs_avgfilesize <= 0) { | | 232 | if (sblock.fs_avgfilesize <= 0) { |
233 | printf("illegal expected average file size %d\n", | | 233 | printf("illegal expected average file size %d\n", |
234 | sblock.fs_avgfilesize); | | 234 | sblock.fs_avgfilesize); |
235 | fserr(14); | | 235 | fserr(14); |
236 | } | | 236 | } |
237 | if (sblock.fs_avgfpdir <= 0) { | | 237 | if (sblock.fs_avgfpdir <= 0) { |
238 | printf("illegal expected number of files per directory %d\n", | | 238 | printf("illegal expected number of files per directory %d\n", |
239 | sblock.fs_avgfpdir); | | 239 | sblock.fs_avgfpdir); |
240 | fserr(15); | | 240 | fserr(15); |
241 | } | | 241 | } |
242 | /* | | 242 | /* |
243 | * collect and verify the block and fragment sizes | | 243 | * collect and verify the block and fragment sizes |
244 | */ | | 244 | */ |
245 | sblock.fs_bsize = bsize; | | 245 | sblock.fs_bsize = bsize; |
246 | sblock.fs_fsize = fsize; | | 246 | sblock.fs_fsize = fsize; |
247 | if (!powerof2(sblock.fs_bsize)) { | | 247 | if (!powerof2(sblock.fs_bsize)) { |
248 | printf("block size must be a power of 2, not %d\n", | | 248 | printf("block size must be a power of 2, not %d\n", |
249 | sblock.fs_bsize); | | 249 | sblock.fs_bsize); |
250 | fserr(16); | | 250 | fserr(16); |
251 | } | | 251 | } |
252 | if (!powerof2(sblock.fs_fsize)) { | | 252 | if (!powerof2(sblock.fs_fsize)) { |
253 | printf("fragment size must be a power of 2, not %d\n", | | 253 | printf("fragment size must be a power of 2, not %d\n", |
254 | sblock.fs_fsize); | | 254 | sblock.fs_fsize); |
255 | fserr(17); | | 255 | fserr(17); |
256 | } | | 256 | } |
257 | if (sblock.fs_fsize < sectorsize) { | | 257 | if (sblock.fs_fsize < sectorsize) { |
258 | printf("fragment size %d is too small, minimum is %d\n", | | 258 | printf("fragment size %d is too small, minimum is %d\n", |
259 | sblock.fs_fsize, sectorsize); | | 259 | sblock.fs_fsize, sectorsize); |
260 | fserr(18); | | 260 | fserr(18); |
261 | } | | 261 | } |
262 | if (sblock.fs_bsize < MINBSIZE) { | | 262 | if (sblock.fs_bsize < MINBSIZE) { |
263 | printf("block size %d is too small, minimum is %d\n", | | 263 | printf("block size %d is too small, minimum is %d\n", |
264 | sblock.fs_bsize, MINBSIZE); | | 264 | sblock.fs_bsize, MINBSIZE); |
265 | fserr(19); | | 265 | fserr(19); |
266 | } | | 266 | } |
267 | if (sblock.fs_bsize > MAXBSIZE) { | | 267 | if (sblock.fs_bsize > MAXBSIZE) { |
268 | printf("block size %d is too large, maximum is %d\n", | | 268 | printf("block size %d is too large, maximum is %d\n", |
269 | sblock.fs_bsize, MAXBSIZE); | | 269 | sblock.fs_bsize, MAXBSIZE); |
270 | fserr(19); | | 270 | fserr(19); |
271 | } | | 271 | } |
272 | if (sblock.fs_bsize < sblock.fs_fsize) { | | 272 | if (sblock.fs_bsize < sblock.fs_fsize) { |
273 | printf("block size (%d) cannot be smaller than fragment size (%d)\n", | | 273 | printf("block size (%d) cannot be smaller than fragment size (%d)\n", |
274 | sblock.fs_bsize, sblock.fs_fsize); | | 274 | sblock.fs_bsize, sblock.fs_fsize); |
275 | fserr(20); | | 275 | fserr(20); |
276 | } | | 276 | } |
277 | | | 277 | |
278 | if (maxbsize < bsize || !powerof2(maxbsize)) { | | 278 | if (maxbsize < bsize || !powerof2(maxbsize)) { |
279 | sblock.fs_maxbsize = sblock.fs_bsize; | | 279 | sblock.fs_maxbsize = sblock.fs_bsize; |
280 | } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) { | | 280 | } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) { |
281 | sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize; | | 281 | sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize; |
282 | } else { | | 282 | } else { |
283 | sblock.fs_maxbsize = maxbsize; | | 283 | sblock.fs_maxbsize = maxbsize; |
284 | } | | 284 | } |
285 | sblock.fs_maxcontig = maxcontig; | | 285 | sblock.fs_maxcontig = maxcontig; |
286 | if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) { | | 286 | if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) { |
287 | sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize; | | 287 | sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize; |
288 | if (verbosity > 0) | | 288 | if (verbosity > 0) |
289 | printf("Maxcontig raised to %d\n", sblock.fs_maxbsize); | | 289 | printf("Maxcontig raised to %d\n", sblock.fs_maxbsize); |
290 | } | | 290 | } |
291 | if (sblock.fs_maxcontig > 1) | | 291 | if (sblock.fs_maxcontig > 1) |
292 | sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG); | | 292 | sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG); |
293 | | | 293 | |
294 | sblock.fs_bmask = ~(sblock.fs_bsize - 1); | | 294 | sblock.fs_bmask = ~(sblock.fs_bsize - 1); |
295 | sblock.fs_fmask = ~(sblock.fs_fsize - 1); | | 295 | sblock.fs_fmask = ~(sblock.fs_fsize - 1); |
296 | sblock.fs_qbmask = ~sblock.fs_bmask; | | 296 | sblock.fs_qbmask = ~sblock.fs_bmask; |
297 | sblock.fs_qfmask = ~sblock.fs_fmask; | | 297 | sblock.fs_qfmask = ~sblock.fs_fmask; |
298 | for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) | | 298 | for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) |
299 | sblock.fs_bshift++; | | 299 | sblock.fs_bshift++; |
300 | for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) | | 300 | for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) |
301 | sblock.fs_fshift++; | | 301 | sblock.fs_fshift++; |
302 | sblock.fs_frag = ffs_numfrags(&sblock, sblock.fs_bsize); | | 302 | sblock.fs_frag = ffs_numfrags(&sblock, sblock.fs_bsize); |
303 | for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) | | 303 | for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) |
304 | sblock.fs_fragshift++; | | 304 | sblock.fs_fragshift++; |
305 | if (sblock.fs_frag > MAXFRAG) { | | 305 | if (sblock.fs_frag > MAXFRAG) { |
306 | printf("fragment size %d is too small, " | | 306 | printf("fragment size %d is too small, " |
307 | "minimum with block size %d is %d\n", | | 307 | "minimum with block size %d is %d\n", |
308 | sblock.fs_fsize, sblock.fs_bsize, | | 308 | sblock.fs_fsize, sblock.fs_bsize, |
309 | sblock.fs_bsize / MAXFRAG); | | 309 | sblock.fs_bsize / MAXFRAG); |
310 | fserr(21); | | 310 | fserr(21); |
311 | } | | 311 | } |
312 | sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize); | | 312 | sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize); |
313 | sblock.fs_size = FFS_DBTOFSB(&sblock, fssize); | | 313 | sblock.fs_size = FFS_DBTOFSB(&sblock, fssize); |
314 | if (Oflag <= 1) { | | 314 | if (Oflag <= 1) { |
315 | if ((uint64_t)sblock.fs_size >= 1ull << 31) { | | 315 | if ((uint64_t)sblock.fs_size >= 1ull << 31) { |
316 | printf("Too many fragments (0x%" PRIx64 | | 316 | printf("Too many fragments (0x%" PRIx64 |
317 | ") for a FFSv1 filesystem\n", sblock.fs_size); | | 317 | ") for a FFSv1 filesystem\n", sblock.fs_size); |
318 | fserr(22); | | 318 | fserr(22); |
319 | } | | 319 | } |
320 | sblock.fs_magic = FS_UFS1_MAGIC; | | 320 | sblock.fs_magic = FS_UFS1_MAGIC; |
321 | sblock.fs_sblockloc = SBLOCK_UFS1; | | 321 | sblock.fs_sblockloc = SBLOCK_UFS1; |
322 | sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t); | | 322 | sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t); |
323 | sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); | | 323 | sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode); |
324 | sblock.fs_old_cgoffset = 0; | | 324 | sblock.fs_old_cgoffset = 0; |
325 | sblock.fs_old_cgmask = 0xffffffff; | | 325 | sblock.fs_old_cgmask = 0xffffffff; |
326 | sblock.fs_old_size = sblock.fs_size; | | 326 | sblock.fs_old_size = sblock.fs_size; |
327 | sblock.fs_old_rotdelay = 0; | | 327 | sblock.fs_old_rotdelay = 0; |
328 | sblock.fs_old_rps = 60; | | 328 | sblock.fs_old_rps = 60; |
329 | sblock.fs_old_nspf = sblock.fs_fsize / sectorsize; | | 329 | sblock.fs_old_nspf = sblock.fs_fsize / sectorsize; |
330 | sblock.fs_old_cpg = 1; | | 330 | sblock.fs_old_cpg = 1; |
331 | sblock.fs_old_interleave = 1; | | 331 | sblock.fs_old_interleave = 1; |
332 | sblock.fs_old_trackskew = 0; | | 332 | sblock.fs_old_trackskew = 0; |
333 | sblock.fs_old_cpc = 0; | | 333 | sblock.fs_old_cpc = 0; |
334 | sblock.fs_old_postblformat = FS_DYNAMICPOSTBLFMT; | | 334 | sblock.fs_old_postblformat = FS_DYNAMICPOSTBLFMT; |
335 | sblock.fs_old_nrpos = 1; | | 335 | sblock.fs_old_nrpos = 1; |
336 | } else { | | 336 | } else { |
337 | sblock.fs_magic = FS_UFS2_MAGIC; | | 337 | sblock.fs_magic = FS_UFS2_MAGIC; |
338 | sblock.fs_sblockloc = SBLOCK_UFS2; | | 338 | sblock.fs_sblockloc = SBLOCK_UFS2; |
339 | sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t); | | 339 | sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t); |
340 | sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); | | 340 | sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); |
341 | } | | 341 | } |
342 | | | 342 | |
343 | sblock.fs_sblkno = | | 343 | sblock.fs_sblkno = |
344 | roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize), | | 344 | roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize), |
345 | sblock.fs_frag); | | 345 | sblock.fs_frag); |
346 | sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + | | 346 | sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + |
347 | roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag)); | | 347 | roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag)); |
348 | sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; | | 348 | sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; |
349 | sblock.fs_maxfilesize = sblock.fs_bsize * UFS_NDADDR - 1; | | 349 | sblock.fs_maxfilesize = sblock.fs_bsize * UFS_NDADDR - 1; |
350 | for (sizepb = sblock.fs_bsize, i = 0; i < UFS_NIADDR; i++) { | | 350 | for (sizepb = sblock.fs_bsize, i = 0; i < UFS_NIADDR; i++) { |
351 | sizepb *= FFS_NINDIR(&sblock); | | 351 | sizepb *= FFS_NINDIR(&sblock); |
352 | sblock.fs_maxfilesize += sizepb; | | 352 | sblock.fs_maxfilesize += sizepb; |
353 | } | | 353 | } |
354 | | | 354 | |
355 | /* | | 355 | /* |
356 | * Calculate the number of blocks to put into each cylinder group. | | 356 | * Calculate the number of blocks to put into each cylinder group. |
357 | * | | 357 | * |
358 | * The cylinder group size is limited because the data structure | | 358 | * The cylinder group size is limited because the data structure |
359 | * must fit into a single block. | | 359 | * must fit into a single block. |
360 | * We try to have as few cylinder groups as possible, with a proviso | | 360 | * We try to have as few cylinder groups as possible, with a proviso |
361 | * that we create at least MINCYLGRPS (==4) except for small | | 361 | * that we create at least MINCYLGRPS (==4) except for small |
362 | * filesystems. | | 362 | * filesystems. |
363 | * | | 363 | * |
364 | * This algorithm works out how many blocks of inodes would be | | 364 | * This algorithm works out how many blocks of inodes would be |
365 | * needed to fill the entire volume at the specified density. | | 365 | * needed to fill the entire volume at the specified density. |
366 | * It then looks at how big the 'cylinder block' would have to | | 366 | * It then looks at how big the 'cylinder block' would have to |
367 | * be and, assuming that it is linearly related to the number | | 367 | * be and, assuming that it is linearly related to the number |
368 | * of inodes and blocks how many cylinder groups are needed to | | 368 | * of inodes and blocks how many cylinder groups are needed to |
369 | * keep the cylinder block below the filesystem block size. | | 369 | * keep the cylinder block below the filesystem block size. |
370 | * | | 370 | * |
371 | * The cylinder groups are then all created with the average size. | | 371 | * The cylinder groups are then all created with the average size. |
372 | * | | 372 | * |
373 | * Space taken by the red tape on cylinder groups other than the | | 373 | * Space taken by the red tape on cylinder groups other than the |
374 | * first is ignored. | | 374 | * first is ignored. |
375 | */ | | 375 | */ |
376 | | | 376 | |
377 | /* There must be space for 1 inode block and 2 data blocks */ | | 377 | /* There must be space for 1 inode block and 2 data blocks */ |
378 | if (sblock.fs_size < sblock.fs_iblkno + 3 * sblock.fs_frag) { | | 378 | if (sblock.fs_size < sblock.fs_iblkno + 3 * sblock.fs_frag) { |
379 | printf("Filesystem size %lld < minimum size of %d\n", | | 379 | printf("Filesystem size %lld < minimum size of %d\n", |
380 | (long long)sblock.fs_size, sblock.fs_iblkno + 3 * sblock.fs_frag); | | 380 | (long long)sblock.fs_size, sblock.fs_iblkno + 3 * sblock.fs_frag); |
381 | fserr(23); | | 381 | fserr(23); |
382 | } | | 382 | } |
383 | if (num_inodes != 0) | | 383 | if (num_inodes != 0) |
384 | inodeblks = howmany(num_inodes, FFS_INOPB(&sblock)); | | 384 | inodeblks = howmany(num_inodes, FFS_INOPB(&sblock)); |
385 | else { | | 385 | else { |
386 | /* | | 386 | /* |
387 | * Calculate 'per inode block' so we can allocate less than | | 387 | * Calculate 'per inode block' so we can allocate less than |
388 | * 1 fragment per inode - useful for /dev. | | 388 | * 1 fragment per inode - useful for /dev. |
389 | */ | | 389 | */ |
390 | fragsperinodeblk = MAX(ffs_numfrags(&sblock, | | 390 | fragsperinodeblk = MAX(ffs_numfrags(&sblock, |
391 | (uint64_t)density * FFS_INOPB(&sblock)), 1); | | 391 | (uint64_t)density * FFS_INOPB(&sblock)), 1); |
392 | inodeblks = (sblock.fs_size - sblock.fs_iblkno) / | | 392 | inodeblks = (sblock.fs_size - sblock.fs_iblkno) / |
393 | (sblock.fs_frag + fragsperinodeblk); | | 393 | (sblock.fs_frag + fragsperinodeblk); |
394 | } | | 394 | } |
395 | if (inodeblks == 0) | | 395 | if (inodeblks == 0) |
396 | inodeblks = 1; | | 396 | inodeblks = 1; |
397 | /* Ensure that there are at least 2 data blocks (or we fail below) */ | | 397 | /* Ensure that there are at least 2 data blocks (or we fail below) */ |
398 | if (inodeblks > (uint64_t)(sblock.fs_size - sblock.fs_iblkno)/sblock.fs_frag - 2) | | 398 | if (inodeblks > (uint64_t)(sblock.fs_size - sblock.fs_iblkno)/sblock.fs_frag - 2) |
399 | inodeblks = (sblock.fs_size-sblock.fs_iblkno)/sblock.fs_frag-2; | | 399 | inodeblks = (sblock.fs_size-sblock.fs_iblkno)/sblock.fs_frag-2; |
400 | /* Even UFS2 limits number of inodes to 2^31 (fs_ipg is int32_t) */ | | 400 | /* Even UFS2 limits number of inodes to 2^31 (fs_ipg is int32_t) */ |
401 | if (inodeblks * FFS_INOPB(&sblock) >= 1ull << 31) | | 401 | if (inodeblks * FFS_INOPB(&sblock) >= 1ull << 31) |
402 | inodeblks = ((1ull << 31) - NBBY) / FFS_INOPB(&sblock); | | 402 | inodeblks = ((1ull << 31) - NBBY) / FFS_INOPB(&sblock); |
403 | /* | | 403 | /* |
404 | * See what would happen if we tried to use 1 cylinder group. | | 404 | * See what would happen if we tried to use 1 cylinder group. |
405 | * Assume space linear, so work out number of cylinder groups needed. | | 405 | * Assume space linear, so work out number of cylinder groups needed. |
406 | */ | | 406 | */ |
407 | cgzero = CGSIZE_IF(&sblock, 0, 0); | | 407 | cgzero = CGSIZE_IF(&sblock, 0, 0); |
408 | cgall = CGSIZE_IF(&sblock, inodeblks * FFS_INOPB(&sblock), sblock.fs_size); | | 408 | cgall = CGSIZE_IF(&sblock, inodeblks * FFS_INOPB(&sblock), sblock.fs_size); |
409 | ncg = howmany(cgall - cgzero, sblock.fs_bsize - cgzero); | | 409 | ncg = howmany(cgall - cgzero, sblock.fs_bsize - cgzero); |
410 | if (ncg < MINCYLGRPS) { | | 410 | if (ncg < MINCYLGRPS) { |
411 | /* | | 411 | /* |
412 | * We would like to allocate MINCLYGRPS cylinder groups, | | 412 | * We would like to allocate MINCLYGRPS cylinder groups, |
413 | * but for small file systems (especially ones with a lot | | 413 | * but for small file systems (especially ones with a lot |
414 | * of inodes) this is not desirable (or possible). | | 414 | * of inodes) this is not desirable (or possible). |
415 | */ | | 415 | */ |
416 | u = sblock.fs_size / 2 / (sblock.fs_iblkno + | | 416 | u = sblock.fs_size / 2 / (sblock.fs_iblkno + |
417 | inodeblks * sblock.fs_frag); | | 417 | inodeblks * sblock.fs_frag); |
418 | if (u > ncg) | | 418 | if (u > ncg) |
419 | ncg = u; | | 419 | ncg = u; |
420 | if (ncg > MINCYLGRPS) | | 420 | if (ncg > MINCYLGRPS) |
421 | ncg = MINCYLGRPS; | | 421 | ncg = MINCYLGRPS; |
422 | if (ncg > inodeblks) | | 422 | if (ncg > inodeblks) |
423 | ncg = inodeblks; | | 423 | ncg = inodeblks; |
424 | } | | 424 | } |
425 | /* | | 425 | /* |
426 | * Put an equal number of blocks in each cylinder group. | | 426 | * Put an equal number of blocks in each cylinder group. |
427 | * Round up so we don't have more fragments in the last CG than | | 427 | * Round up so we don't have more fragments in the last CG than |
428 | * the earlier ones (does that matter?), but kill a block if the | | 428 | * the earlier ones (does that matter?), but kill a block if the |
429 | * CGSIZE becomes too big (only happens if there are a lot of CGs). | | 429 | * CGSIZE becomes too big (only happens if there are a lot of CGs). |
430 | */ | | 430 | */ |
431 | sblock.fs_fpg = roundup(howmany(sblock.fs_size, ncg), sblock.fs_frag); | | 431 | sblock.fs_fpg = roundup(howmany(sblock.fs_size, ncg), sblock.fs_frag); |
432 | /* Round up the fragments/group so the bitmap bytes are full */ | | 432 | /* Round up the fragments/group so the bitmap bytes are full */ |
433 | sblock.fs_fpg = roundup(sblock.fs_fpg, NBBY); | | 433 | sblock.fs_fpg = roundup(sblock.fs_fpg, NBBY); |
434 | inodes_per_cg = ((inodeblks - 1) / ncg + 1) * FFS_INOPB(&sblock); | | 434 | inodes_per_cg = ((inodeblks - 1) / ncg + 1) * FFS_INOPB(&sblock); |
435 | | | 435 | |
436 | i = CGSIZE_IF(&sblock, inodes_per_cg, sblock.fs_fpg); | | 436 | i = CGSIZE_IF(&sblock, inodes_per_cg, sblock.fs_fpg); |
437 | if (i > sblock.fs_bsize) { | | 437 | if (i > sblock.fs_bsize) { |
438 | sblock.fs_fpg -= (i - sblock.fs_bsize) * NBBY; | | 438 | sblock.fs_fpg -= (i - sblock.fs_bsize) * NBBY; |
439 | /* ... and recalculate how many cylinder groups we now need */ | | 439 | /* ... and recalculate how many cylinder groups we now need */ |
440 | ncg = howmany(sblock.fs_size, sblock.fs_fpg); | | 440 | ncg = howmany(sblock.fs_size, sblock.fs_fpg); |
441 | inodes_per_cg = ((inodeblks - 1) / ncg + 1) * FFS_INOPB(&sblock); | | 441 | inodes_per_cg = ((inodeblks - 1) / ncg + 1) * FFS_INOPB(&sblock); |
442 | } | | 442 | } |
443 | sblock.fs_ipg = inodes_per_cg; | | 443 | sblock.fs_ipg = inodes_per_cg; |
444 | /* Sanity check on our sums... */ | | 444 | /* Sanity check on our sums... */ |
445 | if ((int)CGSIZE(&sblock) > sblock.fs_bsize) { | | 445 | if ((int)CGSIZE(&sblock) > sblock.fs_bsize) { |
446 | printf("CGSIZE miscalculated %d > %d\n", | | 446 | printf("CGSIZE miscalculated %d > %d\n", |
447 | (int)CGSIZE(&sblock), sblock.fs_bsize); | | 447 | (int)CGSIZE(&sblock), sblock.fs_bsize); |
448 | fserr(24); | | 448 | fserr(24); |
449 | } | | 449 | } |
450 | | | 450 | |
451 | sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / FFS_INOPF(&sblock); | | 451 | sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / FFS_INOPF(&sblock); |
452 | /* Check that the last cylinder group has enough space for the inodes */ | | 452 | /* Check that the last cylinder group has enough space for the inodes */ |
453 | i = sblock.fs_size - sblock.fs_fpg * (ncg - 1ull); | | 453 | i = sblock.fs_size - sblock.fs_fpg * (ncg - 1ull); |
454 | if (i < sblock.fs_dblkno) { | | 454 | if (i < sblock.fs_dblkno) { |
455 | /* | | 455 | /* |
456 | * Since we make all the cylinder groups the same size, the | | 456 | * Since we make all the cylinder groups the same size, the |
457 | * last will only be small if there are a large number of | | 457 | * last will only be small if there are a large number of |
458 | * cylinder groups. If we pull even a fragment from each | | 458 | * cylinder groups. If we pull even a fragment from each |
459 | * of the other groups then the last CG will be overfull. | | 459 | * of the other groups then the last CG will be overfull. |
460 | * So we just kill the last CG. | | 460 | * So we just kill the last CG. |
461 | */ | | 461 | */ |
462 | ncg--; | | 462 | ncg--; |
463 | sblock.fs_size -= i; | | 463 | sblock.fs_size -= i; |
464 | } | | 464 | } |
465 | sblock.fs_ncg = ncg; | | 465 | sblock.fs_ncg = ncg; |
466 | | | 466 | |
467 | sblock.fs_cgsize = ffs_fragroundup(&sblock, CGSIZE(&sblock)); | | 467 | sblock.fs_cgsize = ffs_fragroundup(&sblock, CGSIZE(&sblock)); |
468 | if (Oflag <= 1) { | | 468 | if (Oflag <= 1) { |
469 | sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf; | | 469 | sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf; |
470 | sblock.fs_old_nsect = sblock.fs_old_spc; | | 470 | sblock.fs_old_nsect = sblock.fs_old_spc; |
471 | sblock.fs_old_npsect = sblock.fs_old_spc; | | 471 | sblock.fs_old_npsect = sblock.fs_old_spc; |
472 | sblock.fs_old_ncyl = sblock.fs_ncg; | | 472 | sblock.fs_old_ncyl = sblock.fs_ncg; |
473 | } | | 473 | } |
474 | | | 474 | |
475 | /* | | 475 | /* |
476 | * Cylinder group summary information for each cylinder is written | | 476 | * Cylinder group summary information for each cylinder is written |
477 | * into the first cylinder group. | | 477 | * into the first cylinder group. |
478 | * Write this fragment by fragment, but doing the first CG last | | 478 | * Write this fragment by fragment, but doing the first CG last |
479 | * (after we've taken stuff off for the structure itself and the | | 479 | * (after we've taken stuff off for the structure itself and the |
480 | * root directory. | | 480 | * root directory. |
481 | */ | | 481 | */ |
482 | sblock.fs_csaddr = cgdmin(&sblock, 0); | | 482 | sblock.fs_csaddr = cgdmin(&sblock, 0); |
483 | sblock.fs_cssize = | | 483 | sblock.fs_cssize = |
484 | ffs_fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); | | 484 | ffs_fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); |
485 | if (512 % sizeof *fscs_0) | | 485 | if (512 % sizeof *fscs_0) |
486 | errx(1, "cylinder group summary doesn't fit in sectors"); | | 486 | errx(1, "cylinder group summary doesn't fit in sectors"); |
487 | fscs_0 = mmap(0, 2 * sblock.fs_fsize, PROT_READ|PROT_WRITE, | | 487 | fscs_0 = mmap(0, 2 * sblock.fs_fsize, PROT_READ|PROT_WRITE, |
488 | MAP_ANON|MAP_PRIVATE, -1, 0); | | 488 | MAP_ANON|MAP_PRIVATE, -1, 0); |
489 | if (fscs_0 == MAP_FAILED) | | 489 | if (fscs_0 == MAP_FAILED) |
490 | exit(39); | | 490 | exit(39); |
491 | memset(fscs_0, 0, 2 * sblock.fs_fsize); | | 491 | memset(fscs_0, 0, 2 * sblock.fs_fsize); |
492 | fs_csaddr = sblock.fs_csaddr; | | 492 | fs_csaddr = sblock.fs_csaddr; |
493 | fscs_next = fscs_0; | | 493 | fscs_next = fscs_0; |
494 | fscs_end = (void *)((char *)fscs_0 + 2 * sblock.fs_fsize); | | 494 | fscs_end = (void *)((char *)fscs_0 + 2 * sblock.fs_fsize); |
495 | fscs_reset = (void *)((char *)fscs_0 + sblock.fs_fsize); | | 495 | fscs_reset = (void *)((char *)fscs_0 + sblock.fs_fsize); |
496 | /* | | 496 | /* |
497 | * fill in remaining fields of the super block | | 497 | * fill in remaining fields of the super block |
498 | */ | | 498 | */ |
499 | sblock.fs_sbsize = ffs_fragroundup(&sblock, sizeof(struct fs)); | | 499 | sblock.fs_sbsize = ffs_fragroundup(&sblock, sizeof(struct fs)); |
500 | if (sblock.fs_sbsize > SBLOCKSIZE) | | 500 | if (sblock.fs_sbsize > SBLOCKSIZE) |
501 | sblock.fs_sbsize = SBLOCKSIZE; | | 501 | sblock.fs_sbsize = SBLOCKSIZE; |
502 | sblock.fs_minfree = minfree; | | 502 | sblock.fs_minfree = minfree; |
503 | sblock.fs_maxcontig = maxcontig; | | 503 | sblock.fs_maxcontig = maxcontig; |
504 | sblock.fs_maxbpg = maxbpg; | | 504 | sblock.fs_maxbpg = maxbpg; |
505 | sblock.fs_optim = opt; | | 505 | sblock.fs_optim = opt; |
506 | sblock.fs_cgrotor = 0; | | 506 | sblock.fs_cgrotor = 0; |
507 | sblock.fs_pendingblocks = 0; | | 507 | sblock.fs_pendingblocks = 0; |
508 | sblock.fs_pendinginodes = 0; | | 508 | sblock.fs_pendinginodes = 0; |
509 | sblock.fs_cstotal.cs_ndir = 0; | | 509 | sblock.fs_cstotal.cs_ndir = 0; |
510 | sblock.fs_cstotal.cs_nbfree = 0; | | 510 | sblock.fs_cstotal.cs_nbfree = 0; |
511 | sblock.fs_cstotal.cs_nifree = 0; | | 511 | sblock.fs_cstotal.cs_nifree = 0; |
512 | sblock.fs_cstotal.cs_nffree = 0; | | 512 | sblock.fs_cstotal.cs_nffree = 0; |
513 | sblock.fs_fmod = 0; | | 513 | sblock.fs_fmod = 0; |
514 | sblock.fs_ronly = 0; | | 514 | sblock.fs_ronly = 0; |
515 | sblock.fs_state = 0; | | 515 | sblock.fs_state = 0; |
516 | sblock.fs_clean = FS_ISCLEAN; | | 516 | sblock.fs_clean = FS_ISCLEAN; |
517 | sblock.fs_ronly = 0; | | 517 | sblock.fs_ronly = 0; |
518 | sblock.fs_id[0] = (long)tv.tv_sec; /* XXXfvdl huh? */ | | 518 | sblock.fs_id[0] = (long)tv.tv_sec; /* XXXfvdl huh? */ |
519 | sblock.fs_id[1] = arc4random() & INT32_MAX; | | 519 | sblock.fs_id[1] = arc4random() & INT32_MAX; |
520 | sblock.fs_fsmnt[0] = '\0'; | | 520 | sblock.fs_fsmnt[0] = '\0'; |
521 | csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); | | 521 | csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize); |
522 | sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno - | | 522 | sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno - |
523 | sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno); | | 523 | sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno); |
524 | sblock.fs_cstotal.cs_nbfree = | | 524 | sblock.fs_cstotal.cs_nbfree = |
525 | ffs_fragstoblks(&sblock, sblock.fs_dsize) - | | 525 | ffs_fragstoblks(&sblock, sblock.fs_dsize) - |
526 | howmany(csfrags, sblock.fs_frag); | | 526 | howmany(csfrags, sblock.fs_frag); |
527 | sblock.fs_cstotal.cs_nffree = | | 527 | sblock.fs_cstotal.cs_nffree = |
528 | ffs_fragnum(&sblock, sblock.fs_size) + | | 528 | ffs_fragnum(&sblock, sblock.fs_size) + |
529 | (ffs_fragnum(&sblock, csfrags) > 0 ? | | 529 | (ffs_fragnum(&sblock, csfrags) > 0 ? |
530 | sblock.fs_frag - ffs_fragnum(&sblock, csfrags) : 0); | | 530 | sblock.fs_frag - ffs_fragnum(&sblock, csfrags) : 0); |
531 | sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO; | | 531 | sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO; |
532 | sblock.fs_cstotal.cs_ndir = 0; | | 532 | sblock.fs_cstotal.cs_ndir = 0; |
533 | sblock.fs_dsize -= csfrags; | | 533 | sblock.fs_dsize -= csfrags; |
534 | sblock.fs_time = tv.tv_sec; | | 534 | sblock.fs_time = tv.tv_sec; |
535 | if (Oflag <= 1) { | | 535 | if (Oflag <= 1) { |
536 | sblock.fs_old_time = tv.tv_sec; | | 536 | sblock.fs_old_time = tv.tv_sec; |
537 | sblock.fs_old_dsize = sblock.fs_dsize; | | 537 | sblock.fs_old_dsize = sblock.fs_dsize; |
538 | sblock.fs_old_csaddr = sblock.fs_csaddr; | | 538 | sblock.fs_old_csaddr = sblock.fs_csaddr; |
539 | sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; | | 539 | sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; |
540 | sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; | | 540 | sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; |
541 | sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; | | 541 | sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; |
542 | sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; | | 542 | sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; |
543 | } | | 543 | } |
544 | /* add quota data in superblock */ | | 544 | /* add quota data in superblock */ |
545 | if (quotas) { | | 545 | if (quotas) { |
546 | sblock.fs_flags |= FS_DOQUOTA2; | | 546 | sblock.fs_flags |= FS_DOQUOTA2; |
547 | sblock.fs_quota_magic = Q2_HEAD_MAGIC; | | 547 | sblock.fs_quota_magic = Q2_HEAD_MAGIC; |
548 | sblock.fs_quota_flags = quotas; | | 548 | sblock.fs_quota_flags = quotas; |
549 | } | | 549 | } |
550 | /* | | 550 | /* |
551 | * Dump out summary information about file system. | | 551 | * Dump out summary information about file system. |
552 | */ | | 552 | */ |
553 | if (verbosity > 0) { | | 553 | if (verbosity > 0) { |
554 | #define B2MBFACTOR (1 / (1024.0 * 1024.0)) | | 554 | #define B2MBFACTOR (1 / (1024.0 * 1024.0)) |
555 | printf("%s: %.1fMB (%lld sectors) block size %d, " | | 555 | printf("%s: %.1fMB (%lld sectors) block size %d, " |
556 | "fragment size %d\n", | | 556 | "fragment size %d\n", |
557 | fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, | | 557 | fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, |
558 | (long long)FFS_FSBTODB(&sblock, sblock.fs_size), | | 558 | (long long)FFS_FSBTODB(&sblock, sblock.fs_size), |
559 | sblock.fs_bsize, sblock.fs_fsize); | | 559 | sblock.fs_bsize, sblock.fs_fsize); |
560 | printf("\tusing %d cylinder groups of %.2fMB, %d blks, " | | 560 | printf("\tusing %d cylinder groups of %.2fMB, %d blks, " |
561 | "%d inodes.\n", | | 561 | "%d inodes.\n", |
562 | sblock.fs_ncg, | | 562 | sblock.fs_ncg, |
563 | (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, | | 563 | (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, |
564 | sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); | | 564 | sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); |
565 | #undef B2MBFACTOR | | 565 | #undef B2MBFACTOR |
566 | } | | 566 | } |
567 | | | 567 | |
568 | /* | | 568 | /* |
569 | * allocate space for superblock, cylinder group map, and | | 569 | * allocate space for superblock, cylinder group map, and |
570 | * two sets of inode blocks. | | 570 | * two sets of inode blocks. |
571 | */ | | 571 | */ |
572 | if (sblock.fs_bsize < SBLOCKSIZE) | | 572 | if (sblock.fs_bsize < SBLOCKSIZE) |
573 | iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; | | 573 | iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; |
574 | else | | 574 | else |
575 | iobufsize = 4 * sblock.fs_bsize; | | 575 | iobufsize = 4 * sblock.fs_bsize; |
576 | iobuf_memsize = iobufsize; | | 576 | iobuf_memsize = iobufsize; |
577 | if (!mfs && sblock.fs_magic == FS_UFS1_MAGIC) { | | 577 | if (!mfs && sblock.fs_magic == FS_UFS1_MAGIC) { |
578 | /* A larger buffer so we can write multiple inode blks */ | | 578 | /* A larger buffer so we can write multiple inode blks */ |
579 | iobuf_memsize += 14 * sblock.fs_bsize; | | 579 | iobuf_memsize += 14 * sblock.fs_bsize; |
580 | } | | 580 | } |
581 | for (;;) { | | 581 | for (;;) { |
582 | iobuf = mmap(0, iobuf_memsize, PROT_READ|PROT_WRITE, | | 582 | iobuf = mmap(0, iobuf_memsize, PROT_READ|PROT_WRITE, |
583 | MAP_ANON|MAP_PRIVATE, -1, 0); | | 583 | MAP_ANON|MAP_PRIVATE, -1, 0); |
584 | if (iobuf != MAP_FAILED) | | 584 | if (iobuf != MAP_FAILED) |
585 | break; | | 585 | break; |
586 | if (iobuf_memsize != iobufsize) { | | 586 | if (iobuf_memsize != iobufsize) { |
587 | /* Try again with the smaller size */ | | 587 | /* Try again with the smaller size */ |
588 | iobuf_memsize = iobufsize; | | 588 | iobuf_memsize = iobufsize; |
589 | continue; | | 589 | continue; |
590 | } | | 590 | } |
591 | printf("Cannot allocate I/O buffer\n"); | | 591 | printf("Cannot allocate I/O buffer\n"); |
592 | exit(38); | | 592 | exit(38); |
593 | } | | 593 | } |
594 | memset(iobuf, 0, iobuf_memsize); | | 594 | memset(iobuf, 0, iobuf_memsize); |
595 | | | 595 | |
596 | /* | | 596 | /* |
597 | * We now start writing to the filesystem | | 597 | * We now start writing to the filesystem |
598 | */ | | 598 | */ |
599 | | | 599 | |
600 | if (!Nflag) { | | 600 | if (!Nflag) { |
601 | /* | | 601 | /* |
602 | * Validate the given file system size. | | 602 | * Validate the given file system size. |
603 | * Verify that its last block can actually be accessed. | | 603 | * Verify that its last block can actually be accessed. |
604 | * Convert to file system fragment sized units. | | 604 | * Convert to file system fragment sized units. |
605 | */ | | 605 | */ |
606 | if (fssize <= 0) { | | 606 | if (fssize <= 0) { |
607 | printf("preposterous size %lld\n", (long long)fssize); | | 607 | printf("preposterous size %lld\n", (long long)fssize); |
608 | fserr(13); | | 608 | fserr(13); |
609 | } | | 609 | } |
610 | wtfs(fssize - 1, sectorsize, iobuf); | | 610 | wtfs(fssize - 1, sectorsize, iobuf); |
611 | | | 611 | |
612 | /* | | 612 | /* |
613 | * Ensure there is nothing that looks like a filesystem | | 613 | * Ensure there is nothing that looks like a filesystem |
614 | * superbock anywhere other than where ours will be. | | 614 | * superblock anywhere other than where ours will be. |
615 | * If fsck finds the wrong one all hell breaks loose! | | 615 | * If fsck finds the wrong one all hell breaks loose! |
616 | */ | | 616 | */ |
617 | for (i = 0; ; i++) { | | 617 | for (i = 0; ; i++) { |
618 | static const int sblocklist[] = SBLOCKSEARCH; | | 618 | static const int sblocklist[] = SBLOCKSEARCH; |
619 | int sblkoff = sblocklist[i]; | | 619 | int sblkoff = sblocklist[i]; |
620 | int sz; | | 620 | int sz; |
621 | if (sblkoff == -1) | | 621 | if (sblkoff == -1) |
622 | break; | | 622 | break; |
623 | /* Remove main superblock */ | | 623 | /* Remove main superblock */ |
624 | zap_old_sblock(sblkoff); | | 624 | zap_old_sblock(sblkoff); |
625 | /* and all possible locations for the first alternate */ | | 625 | /* and all possible locations for the first alternate */ |
626 | sblkoff += SBLOCKSIZE; | | 626 | sblkoff += SBLOCKSIZE; |
627 | for (sz = SBLOCKSIZE; sz <= 0x10000; sz <<= 1) | | 627 | for (sz = SBLOCKSIZE; sz <= 0x10000; sz <<= 1) |
628 | zap_old_sblock(roundup(sblkoff, sz)); | | 628 | zap_old_sblock(roundup(sblkoff, sz)); |
629 | } | | 629 | } |
630 | /* | | 630 | /* |
631 | * Also zap possible Ext2fs magic leftover to prevent | | 631 | * Also zap possible Ext2fs magic leftover to prevent |
632 | * kernel vfs_mountroot() and bootloaders from mis-recognizing | | 632 | * kernel vfs_mountroot() and bootloaders from mis-recognizing |
633 | * this file system as Ext2fs. | | 633 | * this file system as Ext2fs. |
634 | */ | | 634 | */ |
635 | zap_old_sblock(EXT2FS_SBOFF); | | 635 | zap_old_sblock(EXT2FS_SBOFF); |
636 | | | 636 | |
637 | #ifndef NO_APPLE_UFS | | 637 | #ifndef NO_APPLE_UFS |
638 | if (isappleufs) { | | 638 | if (isappleufs) { |
639 | struct appleufslabel appleufs __aligned(DEV_BSIZE); | | 639 | struct appleufslabel appleufs __aligned(DEV_BSIZE); |
640 | ffs_appleufs_set(&appleufs, appleufs_volname, | | 640 | ffs_appleufs_set(&appleufs, appleufs_volname, |
641 | tv.tv_sec, 0); | | 641 | tv.tv_sec, 0); |
642 | wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, | | 642 | wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, |
643 | APPLEUFS_LABEL_SIZE, &appleufs); | | 643 | APPLEUFS_LABEL_SIZE, &appleufs); |
644 | } else if (APPLEUFS_LABEL_SIZE % sectorsize == 0) { | | 644 | } else if (APPLEUFS_LABEL_SIZE % sectorsize == 0) { |
645 | struct appleufslabel appleufs; | | 645 | struct appleufslabel appleufs; |
646 | /* Look for & zap any existing valid apple ufs labels */ | | 646 | /* Look for & zap any existing valid apple ufs labels */ |
647 | rdfs(APPLEUFS_LABEL_OFFSET/sectorsize, | | 647 | rdfs(APPLEUFS_LABEL_OFFSET/sectorsize, |
648 | APPLEUFS_LABEL_SIZE, &appleufs); | | 648 | APPLEUFS_LABEL_SIZE, &appleufs); |
649 | if (ffs_appleufs_validate(fsys, &appleufs, NULL) == 0) { | | 649 | if (ffs_appleufs_validate(fsys, &appleufs, NULL) == 0) { |
650 | memset(&appleufs, 0, sizeof(appleufs)); | | 650 | memset(&appleufs, 0, sizeof(appleufs)); |
651 | wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, | | 651 | wtfs(APPLEUFS_LABEL_OFFSET/sectorsize, |
652 | APPLEUFS_LABEL_SIZE, &appleufs); | | 652 | APPLEUFS_LABEL_SIZE, &appleufs); |
653 | } | | 653 | } |
654 | } | | 654 | } |
655 | #endif | | 655 | #endif |
656 | } | | 656 | } |
657 | | | 657 | |
658 | /* | | 658 | /* |
659 | * Make a copy of the superblock into the buffer that we will be | | 659 | * Make a copy of the superblock into the buffer that we will be |
660 | * writing out in each cylinder group. | | 660 | * writing out in each cylinder group. |
661 | */ | | 661 | */ |
662 | memcpy(iobuf, &sblock, sizeof sblock); | | 662 | memcpy(iobuf, &sblock, sizeof sblock); |
663 | if (needswap) | | 663 | if (needswap) |
664 | ffs_sb_swap(&sblock, (struct fs *)iobuf); | | 664 | ffs_sb_swap(&sblock, (struct fs *)iobuf); |
665 | if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) | | 665 | if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) |
666 | memset(iobuf + offsetof(struct fs, fs_old_postbl_start), | | 666 | memset(iobuf + offsetof(struct fs, fs_old_postbl_start), |
667 | 0xff, 256); | | 667 | 0xff, 256); |
668 | | | 668 | |
669 | if (verbosity >= 3) | | 669 | if (verbosity >= 3) |
670 | printf("super-block backups (for fsck_ffs -b #) at:\n"); | | 670 | printf("super-block backups (for fsck_ffs -b #) at:\n"); |
671 | /* If we are printing more than one line of numbers, line up columns */ | | 671 | /* If we are printing more than one line of numbers, line up columns */ |
672 | fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, | | 672 | fld_width = verbosity < 4 ? 1 : snprintf(NULL, 0, "%" PRIu64, |
673 | (uint64_t)FFS_FSBTODB(&sblock, cgsblock(&sblock, sblock.fs_ncg-1))); | | 673 | (uint64_t)FFS_FSBTODB(&sblock, cgsblock(&sblock, sblock.fs_ncg-1))); |
674 | /* Get terminal width */ | | 674 | /* Get terminal width */ |
675 | if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 && | | 675 | if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 && |
676 | winsize.ws_col != 0) | | 676 | winsize.ws_col != 0) |
677 | max_cols = winsize.ws_col; | | 677 | max_cols = winsize.ws_col; |
678 | else | | 678 | else |
679 | max_cols = 80; | | 679 | max_cols = 80; |
680 | if (Nflag && verbosity == 3) | | 680 | if (Nflag && verbosity == 3) |
681 | /* Leave space to add " ..." after one row of numbers */ | | 681 | /* Leave space to add " ..." after one row of numbers */ |
682 | max_cols -= 4; | | 682 | max_cols -= 4; |
683 | #define BASE 0x10000 /* For some fixed-point maths */ | | 683 | #define BASE 0x10000 /* For some fixed-point maths */ |
684 | col = 0; | | 684 | col = 0; |
685 | delta = verbosity > 2 ? 0 : max_cols * BASE / sblock.fs_ncg; | | 685 | delta = verbosity > 2 ? 0 : max_cols * BASE / sblock.fs_ncg; |
686 | for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { | | 686 | for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { |
687 | fflush(stdout); | | 687 | fflush(stdout); |
688 | initcg(cylno, &tv); | | 688 | initcg(cylno, &tv); |
689 | if (verbosity < 2) | | 689 | if (verbosity < 2) |
690 | continue; | | 690 | continue; |
691 | if (delta > 0) { | | 691 | if (delta > 0) { |
692 | if (Nflag) | | 692 | if (Nflag) |
693 | /* No point doing dots for -N */ | | 693 | /* No point doing dots for -N */ |
694 | break; | | 694 | break; |
695 | /* Print dots scaled to end near RH margin */ | | 695 | /* Print dots scaled to end near RH margin */ |
696 | for (col += delta; col > BASE; col -= BASE) | | 696 | for (col += delta; col > BASE; col -= BASE) |
697 | printf("."); | | 697 | printf("."); |
698 | continue; | | 698 | continue; |
699 | } | | 699 | } |
700 | /* Print superblock numbers */ | | 700 | /* Print superblock numbers */ |
701 | len = printf("%s%*" PRIu64 ",", col ? " " : "", fld_width, | | 701 | len = printf("%s%*" PRIu64 ",", col ? " " : "", fld_width, |
702 | (uint64_t)FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno))); | | 702 | (uint64_t)FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno))); |
703 | col += len; | | 703 | col += len; |
704 | if (col + len < max_cols) | | 704 | if (col + len < max_cols) |
705 | /* Next number fits */ | | 705 | /* Next number fits */ |
706 | continue; | | 706 | continue; |
707 | /* Next number won't fit, need a newline */ | | 707 | /* Next number won't fit, need a newline */ |
708 | if (verbosity <= 3) { | | 708 | if (verbosity <= 3) { |
709 | /* Print dots for subsequent cylinder groups */ | | 709 | /* Print dots for subsequent cylinder groups */ |
710 | delta = sblock.fs_ncg - cylno - 1; | | 710 | delta = sblock.fs_ncg - cylno - 1; |
711 | if (delta != 0) { | | 711 | if (delta != 0) { |
712 | if (Nflag) { | | 712 | if (Nflag) { |
713 | printf(" ..."); | | 713 | printf(" ..."); |
714 | break; | | 714 | break; |
715 | } | | 715 | } |
716 | delta = max_cols * BASE / delta; | | 716 | delta = max_cols * BASE / delta; |
717 | } | | 717 | } |
718 | } | | 718 | } |
719 | col = 0; | | 719 | col = 0; |
720 | printf("\n"); | | 720 | printf("\n"); |
721 | } | | 721 | } |
722 | #undef BASE | | 722 | #undef BASE |
723 | if (col > 0) | | 723 | if (col > 0) |
724 | printf("\n"); | | 724 | printf("\n"); |
725 | if (Nflag) | | 725 | if (Nflag) |
726 | exit(0); | | 726 | exit(0); |
727 | | | 727 | |
728 | /* | | 728 | /* |
729 | * Now construct the initial file system, | | 729 | * Now construct the initial file system, |
730 | */ | | 730 | */ |
731 | if (fsinit(&tv, mfsmode, mfsuid, mfsgid) == 0 && mfs) | | 731 | if (fsinit(&tv, mfsmode, mfsuid, mfsgid) == 0 && mfs) |
732 | errx(1, "Error making filesystem"); | | 732 | errx(1, "Error making filesystem"); |
733 | sblock.fs_time = tv.tv_sec; | | 733 | sblock.fs_time = tv.tv_sec; |
734 | if (Oflag <= 1) { | | 734 | if (Oflag <= 1) { |
735 | sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; | | 735 | sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir; |
736 | sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; | | 736 | sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree; |
737 | sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; | | 737 | sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree; |
738 | sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; | | 738 | sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree; |
739 | } | | 739 | } |
740 | /* | | 740 | /* |
741 | * Write out the super-block and zeros until the first cg info | | 741 | * Write out the super-block and zeros until the first cg info |
742 | */ | | 742 | */ |
743 | i = cgsblock(&sblock, 0) * sblock.fs_fsize - sblock.fs_sblockloc; | | 743 | i = cgsblock(&sblock, 0) * sblock.fs_fsize - sblock.fs_sblockloc; |
744 | if ((size_t)i < sizeof(sblock)) | | 744 | if ((size_t)i < sizeof(sblock)) |
745 | errx(1, "No space for superblock"); | | 745 | errx(1, "No space for superblock"); |
746 | memcpy(iobuf, &sblock, sizeof(sblock)); | | 746 | memcpy(iobuf, &sblock, sizeof(sblock)); |
747 | memset(iobuf + sizeof(sblock), 0, i - sizeof(sblock)); | | 747 | memset(iobuf + sizeof(sblock), 0, i - sizeof(sblock)); |
748 | if (needswap) | | 748 | if (needswap) |
749 | ffs_sb_swap(&sblock, (struct fs *)iobuf); | | 749 | ffs_sb_swap(&sblock, (struct fs *)iobuf); |
750 | if (eaflag) | | 750 | if (eaflag) |
751 | ((struct fs *)iobuf)->fs_magic = FS_UFS2EA_MAGIC; | | 751 | ((struct fs *)iobuf)->fs_magic = FS_UFS2EA_MAGIC; |
752 | if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) | | 752 | if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) |
753 | memset(iobuf + offsetof(struct fs, fs_old_postbl_start), | | 753 | memset(iobuf + offsetof(struct fs, fs_old_postbl_start), |
754 | 0xff, 256); | | 754 | 0xff, 256); |
755 | wtfs(sblock.fs_sblockloc / sectorsize, i, iobuf); | | 755 | wtfs(sblock.fs_sblockloc / sectorsize, i, iobuf); |
756 | | | 756 | |
757 | /* Write out first and last cylinder summary sectors */ | | 757 | /* Write out first and last cylinder summary sectors */ |
758 | if (needswap) | | 758 | if (needswap) |
759 | ffs_csum_swap(fscs_0, fscs_0, sblock.fs_fsize); | | 759 | ffs_csum_swap(fscs_0, fscs_0, sblock.fs_fsize); |
760 | wtfs(FFS_FSBTODB(&sblock, sblock.fs_csaddr), sblock.fs_fsize, fscs_0); | | 760 | wtfs(FFS_FSBTODB(&sblock, sblock.fs_csaddr), sblock.fs_fsize, fscs_0); |
761 | | | 761 | |
762 | if (fscs_next > fscs_reset) { | | 762 | if (fscs_next > fscs_reset) { |
763 | if (needswap) | | 763 | if (needswap) |
764 | ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); | | 764 | ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); |
765 | fs_csaddr++; | | 765 | fs_csaddr++; |
766 | wtfs(FFS_FSBTODB(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); | | 766 | wtfs(FFS_FSBTODB(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); |
767 | } | | 767 | } |
768 | | | 768 | |
769 | /* mfs doesn't need these permanently allocated */ | | 769 | /* mfs doesn't need these permanently allocated */ |
770 | munmap(iobuf, iobuf_memsize); | | 770 | munmap(iobuf, iobuf_memsize); |
771 | munmap(fscs_0, 2 * sblock.fs_fsize); | | 771 | munmap(fscs_0, 2 * sblock.fs_fsize); |
772 | } | | 772 | } |
773 | | | 773 | |
774 | /* | | 774 | /* |
775 | * Initialize a cylinder group. | | 775 | * Initialize a cylinder group. |
776 | */ | | 776 | */ |
777 | void | | 777 | void |
778 | initcg(uint32_t cylno, const struct timeval *tv) | | 778 | initcg(uint32_t cylno, const struct timeval *tv) |
779 | { | | 779 | { |
780 | daddr_t cbase, dmax; | | 780 | daddr_t cbase, dmax; |
781 | uint32_t i, d, dlower, dupper, blkno, u; | | 781 | uint32_t i, d, dlower, dupper, blkno, u; |
782 | struct ufs1_dinode *dp1; | | 782 | struct ufs1_dinode *dp1; |
783 | struct ufs2_dinode *dp2; | | 783 | struct ufs2_dinode *dp2; |
784 | int start; | | 784 | int start; |
785 | | | 785 | |
786 | /* | | 786 | /* |
787 | * Determine block bounds for cylinder group. | | 787 | * Determine block bounds for cylinder group. |
788 | * Allow space for super block summary information in first | | 788 | * Allow space for super block summary information in first |
789 | * cylinder group. | | 789 | * cylinder group. |
790 | */ | | 790 | */ |
791 | cbase = cgbase(&sblock, cylno); | | 791 | cbase = cgbase(&sblock, cylno); |
792 | dmax = cbase + sblock.fs_fpg; | | 792 | dmax = cbase + sblock.fs_fpg; |
793 | if (dmax > sblock.fs_size) | | 793 | if (dmax > sblock.fs_size) |
794 | dmax = sblock.fs_size; | | 794 | dmax = sblock.fs_size; |
795 | dlower = cgsblock(&sblock, cylno) - cbase; | | 795 | dlower = cgsblock(&sblock, cylno) - cbase; |
796 | dupper = cgdmin(&sblock, cylno) - cbase; | | 796 | dupper = cgdmin(&sblock, cylno) - cbase; |
797 | if (cylno == 0) { | | 797 | if (cylno == 0) { |
798 | dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); | | 798 | dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); |
799 | if (dupper >= cgstart(&sblock, cylno + 1)) { | | 799 | if (dupper >= cgstart(&sblock, cylno + 1)) { |
800 | printf("\rToo many cylinder groups to fit summary " | | 800 | printf("\rToo many cylinder groups to fit summary " |
801 | "information into first cylinder group\n"); | | 801 | "information into first cylinder group\n"); |
802 | fserr(40); | | 802 | fserr(40); |
803 | } | | 803 | } |
804 | } | | 804 | } |
805 | memset(&acg, 0, sblock.fs_cgsize); | | 805 | memset(&acg, 0, sblock.fs_cgsize); |
806 | acg.cg_magic = CG_MAGIC; | | 806 | acg.cg_magic = CG_MAGIC; |
807 | acg.cg_cgx = cylno; | | 807 | acg.cg_cgx = cylno; |
808 | acg.cg_ndblk = dmax - cbase; | | 808 | acg.cg_ndblk = dmax - cbase; |
809 | if (sblock.fs_contigsumsize > 0) | | 809 | if (sblock.fs_contigsumsize > 0) |
810 | acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift; | | 810 | acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift; |
811 | start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); | | 811 | start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); |
812 | if (Oflag == 2) { | | 812 | if (Oflag == 2) { |
813 | acg.cg_time = tv->tv_sec; | | 813 | acg.cg_time = tv->tv_sec; |
814 | acg.cg_niblk = sblock.fs_ipg; | | 814 | acg.cg_niblk = sblock.fs_ipg; |
815 | acg.cg_initediblk = sblock.fs_ipg < 2 * FFS_INOPB(&sblock) ? | | 815 | acg.cg_initediblk = sblock.fs_ipg < 2 * FFS_INOPB(&sblock) ? |
816 | sblock.fs_ipg : 2 * FFS_INOPB(&sblock); | | 816 | sblock.fs_ipg : 2 * FFS_INOPB(&sblock); |
817 | acg.cg_iusedoff = start; | | 817 | acg.cg_iusedoff = start; |
818 | } else { | | 818 | } else { |
819 | acg.cg_old_ncyl = sblock.fs_old_cpg; | | 819 | acg.cg_old_ncyl = sblock.fs_old_cpg; |
820 | if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0 && | | 820 | if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0 && |
821 | (cylno == sblock.fs_ncg - 1)) | | 821 | (cylno == sblock.fs_ncg - 1)) |
822 | acg.cg_old_ncyl = | | 822 | acg.cg_old_ncyl = |
823 | sblock.fs_old_ncyl % sblock.fs_old_cpg; | | 823 | sblock.fs_old_ncyl % sblock.fs_old_cpg; |
824 | acg.cg_old_time = tv->tv_sec; | | 824 | acg.cg_old_time = tv->tv_sec; |
825 | acg.cg_old_niblk = sblock.fs_ipg; | | 825 | acg.cg_old_niblk = sblock.fs_ipg; |
826 | acg.cg_old_btotoff = start; | | 826 | acg.cg_old_btotoff = start; |
827 | acg.cg_old_boff = acg.cg_old_btotoff + | | 827 | acg.cg_old_boff = acg.cg_old_btotoff + |
828 | sblock.fs_old_cpg * sizeof(int32_t); | | 828 | sblock.fs_old_cpg * sizeof(int32_t); |
829 | acg.cg_iusedoff = acg.cg_old_boff + | | 829 | acg.cg_iusedoff = acg.cg_old_boff + |
830 | sblock.fs_old_cpg * sizeof(u_int16_t); | | 830 | sblock.fs_old_cpg * sizeof(u_int16_t); |
831 | } | | 831 | } |
832 | acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); | | 832 | acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); |
833 | if (sblock.fs_contigsumsize <= 0) { | | 833 | if (sblock.fs_contigsumsize <= 0) { |
834 | acg.cg_nextfreeoff = acg.cg_freeoff + | | 834 | acg.cg_nextfreeoff = acg.cg_freeoff + |
835 | howmany(sblock.fs_fpg, CHAR_BIT); | | 835 | howmany(sblock.fs_fpg, CHAR_BIT); |
836 | } else { | | 836 | } else { |
837 | acg.cg_clustersumoff = acg.cg_freeoff + | | 837 | acg.cg_clustersumoff = acg.cg_freeoff + |
838 | howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t); | | 838 | howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t); |
839 | if (isappleufs) { | | 839 | if (isappleufs) { |
840 | /* Apple PR2216969 gives rationale for this change. | | 840 | /* Apple PR2216969 gives rationale for this change. |
841 | * I believe they were mistaken, but we need to | | 841 | * I believe they were mistaken, but we need to |
842 | * duplicate it for compatibility. -- dbj@NetBSD.org | | 842 | * duplicate it for compatibility. -- dbj@NetBSD.org |
843 | */ | | 843 | */ |
844 | acg.cg_clustersumoff += sizeof(int32_t); | | 844 | acg.cg_clustersumoff += sizeof(int32_t); |
845 | } | | 845 | } |
846 | acg.cg_clustersumoff = | | 846 | acg.cg_clustersumoff = |
847 | roundup(acg.cg_clustersumoff, sizeof(int32_t)); | | 847 | roundup(acg.cg_clustersumoff, sizeof(int32_t)); |
848 | acg.cg_clusteroff = acg.cg_clustersumoff + | | 848 | acg.cg_clusteroff = acg.cg_clustersumoff + |
849 | (sblock.fs_contigsumsize + 1) * sizeof(int32_t); | | 849 | (sblock.fs_contigsumsize + 1) * sizeof(int32_t); |
850 | acg.cg_nextfreeoff = acg.cg_clusteroff + | | 850 | acg.cg_nextfreeoff = acg.cg_clusteroff + |
851 | howmany(ffs_fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); | | 851 | howmany(ffs_fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); |
852 | } | | 852 | } |
853 | if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { | | 853 | if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { |
854 | printf("Panic: cylinder group too big\n"); | | 854 | printf("Panic: cylinder group too big\n"); |
855 | fserr(37); | | 855 | fserr(37); |
856 | } | | 856 | } |
857 | acg.cg_cs.cs_nifree += sblock.fs_ipg; | | 857 | acg.cg_cs.cs_nifree += sblock.fs_ipg; |
858 | if (cylno == 0) | | 858 | if (cylno == 0) |
859 | for (u = 0; u < UFS_ROOTINO; u++) { | | 859 | for (u = 0; u < UFS_ROOTINO; u++) { |
860 | setbit(cg_inosused(&acg, 0), u); | | 860 | setbit(cg_inosused(&acg, 0), u); |
861 | acg.cg_cs.cs_nifree--; | | 861 | acg.cg_cs.cs_nifree--; |
862 | } | | 862 | } |
863 | if (cylno > 0) { | | 863 | if (cylno > 0) { |
864 | /* | | 864 | /* |
865 | * In cylno 0, beginning space is reserved | | 865 | * In cylno 0, beginning space is reserved |
866 | * for boot and super blocks. | | 866 | * for boot and super blocks. |
867 | */ | | 867 | */ |
868 | for (d = 0, blkno = 0; d < dlower;) { | | 868 | for (d = 0, blkno = 0; d < dlower;) { |
869 | setblock(&sblock, cg_blksfree(&acg, 0), blkno); | | 869 | setblock(&sblock, cg_blksfree(&acg, 0), blkno); |
870 | if (sblock.fs_contigsumsize > 0) | | 870 | if (sblock.fs_contigsumsize > 0) |
871 | setbit(cg_clustersfree(&acg, 0), blkno); | | 871 | setbit(cg_clustersfree(&acg, 0), blkno); |
872 | acg.cg_cs.cs_nbfree++; | | 872 | acg.cg_cs.cs_nbfree++; |
873 | if (Oflag <= 1) { | | 873 | if (Oflag <= 1) { |
874 | int cn = old_cbtocylno(&sblock, d); | | 874 | int cn = old_cbtocylno(&sblock, d); |
875 | old_cg_blktot(&acg, 0)[cn]++; | | 875 | old_cg_blktot(&acg, 0)[cn]++; |
876 | old_cg_blks(&sblock, &acg, | | 876 | old_cg_blks(&sblock, &acg, |
877 | cn, 0)[old_cbtorpos(&sblock, d)]++; | | 877 | cn, 0)[old_cbtorpos(&sblock, d)]++; |
878 | } | | 878 | } |
879 | d += sblock.fs_frag; | | 879 | d += sblock.fs_frag; |
880 | blkno++; | | 880 | blkno++; |
881 | } | | 881 | } |
882 | } | | 882 | } |
883 | if ((i = (dupper & (sblock.fs_frag - 1))) != 0) { | | 883 | if ((i = (dupper & (sblock.fs_frag - 1))) != 0) { |
884 | acg.cg_frsum[sblock.fs_frag - i]++; | | 884 | acg.cg_frsum[sblock.fs_frag - i]++; |
885 | for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { | | 885 | for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { |
886 | setbit(cg_blksfree(&acg, 0), dupper); | | 886 | setbit(cg_blksfree(&acg, 0), dupper); |
887 | acg.cg_cs.cs_nffree++; | | 887 | acg.cg_cs.cs_nffree++; |
888 | } | | 888 | } |
889 | } | | 889 | } |
890 | for (d = dupper, blkno = dupper >> sblock.fs_fragshift; | | 890 | for (d = dupper, blkno = dupper >> sblock.fs_fragshift; |
891 | d + sblock.fs_frag <= acg.cg_ndblk; ) { | | 891 | d + sblock.fs_frag <= acg.cg_ndblk; ) { |
892 | setblock(&sblock, cg_blksfree(&acg, 0), blkno); | | 892 | setblock(&sblock, cg_blksfree(&acg, 0), blkno); |
893 | if (sblock.fs_contigsumsize > 0) | | 893 | if (sblock.fs_contigsumsize > 0) |
894 | setbit(cg_clustersfree(&acg, 0), blkno); | | 894 | setbit(cg_clustersfree(&acg, 0), blkno); |
895 | acg.cg_cs.cs_nbfree++; | | 895 | acg.cg_cs.cs_nbfree++; |
896 | if (Oflag <= 1) { | | 896 | if (Oflag <= 1) { |
897 | int cn = old_cbtocylno(&sblock, d); | | 897 | int cn = old_cbtocylno(&sblock, d); |
898 | old_cg_blktot(&acg, 0)[cn]++; | | 898 | old_cg_blktot(&acg, 0)[cn]++; |
899 | old_cg_blks(&sblock, &acg, | | 899 | old_cg_blks(&sblock, &acg, |
900 | cn, 0)[old_cbtorpos(&sblock, d)]++; | | 900 | cn, 0)[old_cbtorpos(&sblock, d)]++; |
901 | } | | 901 | } |
902 | d += sblock.fs_frag; | | 902 | d += sblock.fs_frag; |
903 | blkno++; | | 903 | blkno++; |
904 | } | | 904 | } |
905 | if (d < acg.cg_ndblk) { | | 905 | if (d < acg.cg_ndblk) { |
906 | acg.cg_frsum[acg.cg_ndblk - d]++; | | 906 | acg.cg_frsum[acg.cg_ndblk - d]++; |
907 | for (; d < acg.cg_ndblk; d++) { | | 907 | for (; d < acg.cg_ndblk; d++) { |
908 | setbit(cg_blksfree(&acg, 0), d); | | 908 | setbit(cg_blksfree(&acg, 0), d); |
909 | acg.cg_cs.cs_nffree++; | | 909 | acg.cg_cs.cs_nffree++; |
910 | } | | 910 | } |
911 | } | | 911 | } |
912 | if (sblock.fs_contigsumsize > 0) { | | 912 | if (sblock.fs_contigsumsize > 0) { |
913 | int32_t *sump = cg_clustersum(&acg, 0); | | 913 | int32_t *sump = cg_clustersum(&acg, 0); |
914 | u_char *mapp = cg_clustersfree(&acg, 0); | | 914 | u_char *mapp = cg_clustersfree(&acg, 0); |
915 | int map = *mapp++; | | 915 | int map = *mapp++; |
916 | int bit = 1; | | 916 | int bit = 1; |
917 | int run = 0; | | 917 | int run = 0; |
918 | | | 918 | |
919 | for (i = 0; i < acg.cg_nclusterblks; i++) { | | 919 | for (i = 0; i < acg.cg_nclusterblks; i++) { |
920 | if ((map & bit) != 0) { | | 920 | if ((map & bit) != 0) { |
921 | run++; | | 921 | run++; |
922 | } else if (run != 0) { | | 922 | } else if (run != 0) { |
923 | if (run > sblock.fs_contigsumsize) | | 923 | if (run > sblock.fs_contigsumsize) |
924 | run = sblock.fs_contigsumsize; | | 924 | run = sblock.fs_contigsumsize; |
925 | sump[run]++; | | 925 | sump[run]++; |
926 | run = 0; | | 926 | run = 0; |
927 | } | | 927 | } |
928 | if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) { | | 928 | if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) { |
929 | bit <<= 1; | | 929 | bit <<= 1; |
930 | } else { | | 930 | } else { |
931 | map = *mapp++; | | 931 | map = *mapp++; |
932 | bit = 1; | | 932 | bit = 1; |
933 | } | | 933 | } |
934 | } | | 934 | } |
935 | if (run != 0) { | | 935 | if (run != 0) { |
936 | if (run > sblock.fs_contigsumsize) | | 936 | if (run > sblock.fs_contigsumsize) |
937 | run = sblock.fs_contigsumsize; | | 937 | run = sblock.fs_contigsumsize; |
938 | sump[run]++; | | 938 | sump[run]++; |
939 | } | | 939 | } |
940 | } | | 940 | } |
941 | *fscs_next++ = acg.cg_cs; | | 941 | *fscs_next++ = acg.cg_cs; |
942 | if (fscs_next == fscs_end) { | | 942 | if (fscs_next == fscs_end) { |
943 | /* write block of cylinder group summary info into cyl 0 */ | | 943 | /* write block of cylinder group summary info into cyl 0 */ |
944 | if (needswap) | | 944 | if (needswap) |
945 | ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); | | 945 | ffs_csum_swap(fscs_reset, fscs_reset, sblock.fs_fsize); |
946 | fs_csaddr++; | | 946 | fs_csaddr++; |
947 | wtfs(FFS_FSBTODB(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); | | 947 | wtfs(FFS_FSBTODB(&sblock, fs_csaddr), sblock.fs_fsize, fscs_reset); |
948 | fscs_next = fscs_reset; | | 948 | fscs_next = fscs_reset; |
949 | memset(fscs_next, 0, sblock.fs_fsize); | | 949 | memset(fscs_next, 0, sblock.fs_fsize); |
950 | } | | 950 | } |
951 | /* | | 951 | /* |
952 | * Write out the duplicate super block, the cylinder group map | | 952 | * Write out the duplicate super block, the cylinder group map |
953 | * and two blocks worth of inodes in a single write. | | 953 | * and two blocks worth of inodes in a single write. |
954 | */ | | 954 | */ |
955 | start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE; | | 955 | start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE; |
956 | memcpy(&iobuf[start], &acg, sblock.fs_cgsize); | | 956 | memcpy(&iobuf[start], &acg, sblock.fs_cgsize); |
957 | if (needswap) | | 957 | if (needswap) |
958 | ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock); | | 958 | ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock); |
959 | start += sblock.fs_bsize; | | 959 | start += sblock.fs_bsize; |
960 | dp1 = (struct ufs1_dinode *)(&iobuf[start]); | | 960 | dp1 = (struct ufs1_dinode *)(&iobuf[start]); |
961 | dp2 = (struct ufs2_dinode *)(&iobuf[start]); | | 961 | dp2 = (struct ufs2_dinode *)(&iobuf[start]); |
962 | for (i = MIN(sblock.fs_ipg, 2) * FFS_INOPB(&sblock); i != 0; i--) { | | 962 | for (i = MIN(sblock.fs_ipg, 2) * FFS_INOPB(&sblock); i != 0; i--) { |
963 | if (sblock.fs_magic == FS_UFS1_MAGIC) { | | 963 | if (sblock.fs_magic == FS_UFS1_MAGIC) { |
964 | /* No need to swap, it'll stay random */ | | 964 | /* No need to swap, it'll stay random */ |
965 | dp1->di_gen = arc4random() & INT32_MAX; | | 965 | dp1->di_gen = arc4random() & INT32_MAX; |
966 | dp1++; | | 966 | dp1++; |
967 | } else { | | 967 | } else { |
968 | dp2->di_gen = arc4random() & INT32_MAX; | | 968 | dp2->di_gen = arc4random() & INT32_MAX; |
969 | dp2++; | | 969 | dp2++; |
970 | } | | 970 | } |
971 | } | | 971 | } |
972 | wtfs(FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf); | | 972 | wtfs(FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf); |
973 | /* | | 973 | /* |
974 | * For the old file system, we have to initialize all the inodes. | | 974 | * For the old file system, we have to initialize all the inodes. |
975 | */ | | 975 | */ |
976 | if (sblock.fs_magic != FS_UFS1_MAGIC) | | 976 | if (sblock.fs_magic != FS_UFS1_MAGIC) |
977 | return; | | 977 | return; |
978 | | | 978 | |
979 | /* Write 'd' (usually 16 * fs_frag) file-system fragments at once */ | | 979 | /* Write 'd' (usually 16 * fs_frag) file-system fragments at once */ |
980 | d = (iobuf_memsize - start) / sblock.fs_bsize * sblock.fs_frag; | | 980 | d = (iobuf_memsize - start) / sblock.fs_bsize * sblock.fs_frag; |
981 | dupper = sblock.fs_ipg / FFS_INOPF(&sblock); | | 981 | dupper = sblock.fs_ipg / FFS_INOPF(&sblock); |
982 | for (i = 2 * sblock.fs_frag; i < dupper; i += d) { | | 982 | for (i = 2 * sblock.fs_frag; i < dupper; i += d) { |
983 | if (d > dupper - i) | | 983 | if (d > dupper - i) |
984 | d = dupper - i; | | 984 | d = dupper - i; |
985 | dp1 = (struct ufs1_dinode *)(&iobuf[start]); | | 985 | dp1 = (struct ufs1_dinode *)(&iobuf[start]); |
986 | do | | 986 | do |
987 | dp1->di_gen = arc4random() & INT32_MAX; | | 987 | dp1->di_gen = arc4random() & INT32_MAX; |
988 | while ((char *)++dp1 < &iobuf[iobuf_memsize]); | | 988 | while ((char *)++dp1 < &iobuf[iobuf_memsize]); |
989 | wtfs(FFS_FSBTODB(&sblock, cgimin(&sblock, cylno) + i), | | 989 | wtfs(FFS_FSBTODB(&sblock, cgimin(&sblock, cylno) + i), |
990 | d * sblock.fs_bsize / sblock.fs_frag, &iobuf[start]); | | 990 | d * sblock.fs_bsize / sblock.fs_frag, &iobuf[start]); |
991 | } | | 991 | } |
992 | } | | 992 | } |
993 | | | 993 | |
994 | /* | | 994 | /* |
995 | * initialize the file system | | 995 | * initialize the file system |
996 | */ | | 996 | */ |
997 | | | 997 | |
998 | #ifdef LOSTDIR | | 998 | #ifdef LOSTDIR |
999 | #define PREDEFDIR 3 | | 999 | #define PREDEFDIR 3 |
1000 | #else | | 1000 | #else |
1001 | #define PREDEFDIR 2 | | 1001 | #define PREDEFDIR 2 |
1002 | #endif | | 1002 | #endif |
1003 | | | 1003 | |
1004 | struct direct root_dir[] = { | | 1004 | struct direct root_dir[] = { |
1005 | { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, | | 1005 | { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, |
1006 | { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, | | 1006 | { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, |
1007 | #ifdef LOSTDIR | | 1007 | #ifdef LOSTDIR |
1008 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, | | 1008 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, |
1009 | #endif | | 1009 | #endif |
1010 | }; | | 1010 | }; |
1011 | struct odirect { | | 1011 | struct odirect { |
1012 | u_int32_t d_ino; | | 1012 | u_int32_t d_ino; |
1013 | u_int16_t d_reclen; | | 1013 | u_int16_t d_reclen; |
1014 | u_int16_t d_namlen; | | 1014 | u_int16_t d_namlen; |
1015 | u_char d_name[FFS_MAXNAMLEN + 1]; | | 1015 | u_char d_name[FFS_MAXNAMLEN + 1]; |
1016 | } oroot_dir[] = { | | 1016 | } oroot_dir[] = { |
1017 | { UFS_ROOTINO, sizeof(struct direct), 1, "." }, | | 1017 | { UFS_ROOTINO, sizeof(struct direct), 1, "." }, |
1018 | { UFS_ROOTINO, sizeof(struct direct), 2, ".." }, | | 1018 | { UFS_ROOTINO, sizeof(struct direct), 2, ".." }, |
1019 | #ifdef LOSTDIR | | 1019 | #ifdef LOSTDIR |
1020 | { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, | | 1020 | { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, |
1021 | #endif | | 1021 | #endif |
1022 | }; | | 1022 | }; |
1023 | #ifdef LOSTDIR | | 1023 | #ifdef LOSTDIR |
1024 | struct direct lost_found_dir[] = { | | 1024 | struct direct lost_found_dir[] = { |
1025 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, | | 1025 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, |
1026 | { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, | | 1026 | { UFS_ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, |
1027 | { 0, DIRBLKSIZ, 0, 0, 0 }, | | 1027 | { 0, DIRBLKSIZ, 0, 0, 0 }, |
1028 | }; | | 1028 | }; |
1029 | struct odirect olost_found_dir[] = { | | 1029 | struct odirect olost_found_dir[] = { |
1030 | { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, | | 1030 | { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, |
1031 | { UFS_ROOTINO, sizeof(struct direct), 2, ".." }, | | 1031 | { UFS_ROOTINO, sizeof(struct direct), 2, ".." }, |
1032 | { 0, DIRBLKSIZ, 0, 0 }, | | 1032 | { 0, DIRBLKSIZ, 0, 0 }, |
1033 | }; | | 1033 | }; |
1034 | #endif | | 1034 | #endif |
1035 | | | 1035 | |
1036 | static void copy_dir(struct direct *, struct direct *); | | 1036 | static void copy_dir(struct direct *, struct direct *); |
1037 | | | 1037 | |
1038 | int | | 1038 | int |
1039 | fsinit(const struct timeval *tv, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) | | 1039 | fsinit(const struct timeval *tv, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) |
1040 | { | | 1040 | { |
1041 | union dinode node; | | 1041 | union dinode node; |
1042 | union Buffer buf __aligned(DEV_BSIZE); | | 1042 | union Buffer buf __aligned(DEV_BSIZE); |
1043 | int i; | | 1043 | int i; |
1044 | int qblocks = 0; | | 1044 | int qblocks = 0; |
1045 | int qinos = 0; | | 1045 | int qinos = 0; |
1046 | uint8_t q2h_hash_shift; | | 1046 | uint8_t q2h_hash_shift; |
1047 | uint16_t q2h_hash_mask; | | 1047 | uint16_t q2h_hash_mask; |
1048 | #ifdef LOSTDIR | | 1048 | #ifdef LOSTDIR |
1049 | int dirblksiz = DIRBLKSIZ; | | 1049 | int dirblksiz = DIRBLKSIZ; |
1050 | if (isappleufs) | | 1050 | if (isappleufs) |
1051 | dirblksiz = APPLEUFS_DIRBLKSIZ; | | 1051 | dirblksiz = APPLEUFS_DIRBLKSIZ; |
1052 | int nextino = LOSTFOUNDINO+1; | | 1052 | int nextino = LOSTFOUNDINO+1; |
1053 | #else | | 1053 | #else |
1054 | int nextino = UFS_ROOTINO+1; | | 1054 | int nextino = UFS_ROOTINO+1; |
1055 | #endif | | 1055 | #endif |
1056 | | | 1056 | |
1057 | /* | | 1057 | /* |
1058 | * initialize the node | | 1058 | * initialize the node |
1059 | */ | | 1059 | */ |
1060 | | | 1060 | |
1061 | #ifdef LOSTDIR | | 1061 | #ifdef LOSTDIR |
1062 | /* | | 1062 | /* |
1063 | * create the lost+found directory | | 1063 | * create the lost+found directory |
1064 | */ | | 1064 | */ |
1065 | memset(&node, 0, sizeof(node)); | | 1065 | memset(&node, 0, sizeof(node)); |
1066 | if (Oflag == 0) { | | 1066 | if (Oflag == 0) { |
1067 | (void)makedir(&buf, (struct direct *)olost_found_dir, 2); | | 1067 | (void)makedir(&buf, (struct direct *)olost_found_dir, 2); |
1068 | for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) | | 1068 | for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) |
1069 | copy_dir((struct direct*)&olost_found_dir[2], | | 1069 | copy_dir((struct direct*)&olost_found_dir[2], |
1070 | (struct direct*)&buf[i]); | | 1070 | (struct direct*)&buf[i]); |
1071 | } else { | | 1071 | } else { |
1072 | (void)makedir(&buf, lost_found_dir, 2); | | 1072 | (void)makedir(&buf, lost_found_dir, 2); |
1073 | for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) | | 1073 | for (i = dirblksiz; i < sblock.fs_bsize; i += dirblksiz) |
1074 | copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]); | | 1074 | copy_dir(&lost_found_dir[2], (struct direct*)&buf[i]); |
1075 | } | | 1075 | } |
1076 | if (sblock.fs_magic == FS_UFS1_MAGIC) { | | 1076 | if (sblock.fs_magic == FS_UFS1_MAGIC) { |
1077 | node.dp1.di_atime = tv->tv_sec; | | 1077 | node.dp1.di_atime = tv->tv_sec; |
1078 | node.dp1.di_atimensec = tv->tv_usec * 1000; | | 1078 | node.dp1.di_atimensec = tv->tv_usec * 1000; |
1079 | node.dp1.di_mtime = tv->tv_sec; | | 1079 | node.dp1.di_mtime = tv->tv_sec; |
1080 | node.dp1.di_mtimensec = tv->tv_usec * 1000; | | 1080 | node.dp1.di_mtimensec = tv->tv_usec * 1000; |
1081 | node.dp1.di_ctime = tv->tv_sec; | | 1081 | node.dp1.di_ctime = tv->tv_sec; |
1082 | node.dp1.di_ctimensec = tv->tv_usec * 1000; | | 1082 | node.dp1.di_ctimensec = tv->tv_usec * 1000; |
1083 | node.dp1.di_mode = IFDIR | UMASK; | | 1083 | node.dp1.di_mode = IFDIR | UMASK; |
1084 | node.dp1.di_nlink = 2; | | 1084 | node.dp1.di_nlink = 2; |
1085 | node.dp1.di_size = sblock.fs_bsize; | | 1085 | node.dp1.di_size = sblock.fs_bsize; |
1086 | node.dp1.di_db[0] = alloc(node.dp1.di_size, node.dp1.di_mode); | | 1086 | node.dp1.di_db[0] = alloc(node.dp1.di_size, node.dp1.di_mode); |
1087 | if (node.dp1.di_db[0] == 0) | | 1087 | if (node.dp1.di_db[0] == 0) |
1088 | return (0); | | 1088 | return (0); |
1089 | node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, | | 1089 | node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, |
1090 | node.dp1.di_size)); | | 1090 | node.dp1.di_size)); |
1091 | qblocks += node.dp1.di_blocks; | | 1091 | qblocks += node.dp1.di_blocks; |
1092 | node.dp1.di_uid = geteuid(); | | 1092 | node.dp1.di_uid = geteuid(); |
1093 | node.dp1.di_gid = getegid(); | | 1093 | node.dp1.di_gid = getegid(); |
1094 | wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), node.dp1.di_size, | | 1094 | wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), node.dp1.di_size, |
1095 | buf); | | 1095 | buf); |
1096 | } else { | | 1096 | } else { |
1097 | node.dp2.di_atime = tv->tv_sec; | | 1097 | node.dp2.di_atime = tv->tv_sec; |
1098 | node.dp2.di_atimensec = tv->tv_usec * 1000; | | 1098 | node.dp2.di_atimensec = tv->tv_usec * 1000; |
1099 | node.dp2.di_mtime = tv->tv_sec; | | 1099 | node.dp2.di_mtime = tv->tv_sec; |
1100 | node.dp2.di_mtimensec = tv->tv_usec * 1000; | | 1100 | node.dp2.di_mtimensec = tv->tv_usec * 1000; |
1101 | node.dp2.di_ctime = tv->tv_sec; | | 1101 | node.dp2.di_ctime = tv->tv_sec; |
1102 | node.dp2.di_ctimensec = tv->tv_usec * 1000; | | 1102 | node.dp2.di_ctimensec = tv->tv_usec * 1000; |
1103 | node.dp2.di_birthtime = tv->tv_sec; | | 1103 | node.dp2.di_birthtime = tv->tv_sec; |
1104 | node.dp2.di_birthnsec = tv->tv_usec * 1000; | | 1104 | node.dp2.di_birthnsec = tv->tv_usec * 1000; |
1105 | node.dp2.di_mode = IFDIR | UMASK; | | 1105 | node.dp2.di_mode = IFDIR | UMASK; |
1106 | node.dp2.di_nlink = 2; | | 1106 | node.dp2.di_nlink = 2; |
1107 | node.dp2.di_size = sblock.fs_bsize; | | 1107 | node.dp2.di_size = sblock.fs_bsize; |
1108 | node.dp2.di_db[0] = alloc(node.dp2.di_size, node.dp2.di_mode); | | 1108 | node.dp2.di_db[0] = alloc(node.dp2.di_size, node.dp2.di_mode); |
1109 | if (node.dp2.di_db[0] == 0) | | 1109 | if (node.dp2.di_db[0] == 0) |
1110 | return (0); | | 1110 | return (0); |
1111 | node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, | | 1111 | node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, |
1112 | node.dp2.di_size)); | | 1112 | node.dp2.di_size)); |
1113 | qblocks += node.dp2.di_blocks; | | 1113 | qblocks += node.dp2.di_blocks; |
1114 | node.dp2.di_uid = geteuid(); | | 1114 | node.dp2.di_uid = geteuid(); |
1115 | node.dp2.di_gid = getegid(); | | 1115 | node.dp2.di_gid = getegid(); |
1116 | wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), node.dp2.di_size, | | 1116 | wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), node.dp2.di_size, |
1117 | buf); | | 1117 | buf); |
1118 | } | | 1118 | } |
1119 | qinos++; | | 1119 | qinos++; |
1120 | iput(&node, LOSTFOUNDINO); | | 1120 | iput(&node, LOSTFOUNDINO); |
1121 | #endif | | 1121 | #endif |
1122 | /* | | 1122 | /* |
1123 | * create the root directory | | 1123 | * create the root directory |
1124 | */ | | 1124 | */ |
1125 | memset(&node, 0, sizeof(node)); | | 1125 | memset(&node, 0, sizeof(node)); |
1126 | if (Oflag <= 1) { | | 1126 | if (Oflag <= 1) { |
1127 | if (mfs) { | | 1127 | if (mfs) { |
1128 | node.dp1.di_mode = IFDIR | mfsmode; | | 1128 | node.dp1.di_mode = IFDIR | mfsmode; |
1129 | node.dp1.di_uid = mfsuid; | | 1129 | node.dp1.di_uid = mfsuid; |
1130 | node.dp1.di_gid = mfsgid; | | 1130 | node.dp1.di_gid = mfsgid; |
1131 | } else { | | 1131 | } else { |
1132 | node.dp1.di_mode = IFDIR | UMASK; | | 1132 | node.dp1.di_mode = IFDIR | UMASK; |
1133 | node.dp1.di_uid = geteuid(); | | 1133 | node.dp1.di_uid = geteuid(); |
1134 | node.dp1.di_gid = getegid(); | | 1134 | node.dp1.di_gid = getegid(); |
1135 | } | | 1135 | } |
1136 | node.dp1.di_nlink = PREDEFDIR; | | 1136 | node.dp1.di_nlink = PREDEFDIR; |
1137 | if (Oflag == 0) | | 1137 | if (Oflag == 0) |
1138 | node.dp1.di_size = makedir(&buf, | | 1138 | node.dp1.di_size = makedir(&buf, |
1139 | (struct direct *)oroot_dir, PREDEFDIR); | | 1139 | (struct direct *)oroot_dir, PREDEFDIR); |
1140 | else | | 1140 | else |
1141 | node.dp1.di_size = makedir(&buf, root_dir, PREDEFDIR); | | 1141 | node.dp1.di_size = makedir(&buf, root_dir, PREDEFDIR); |
1142 | node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode); | | 1142 | node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode); |
1143 | if (node.dp1.di_db[0] == 0) | | 1143 | if (node.dp1.di_db[0] == 0) |
1144 | return (0); | | 1144 | return (0); |
1145 | node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, | | 1145 | node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, |
1146 | node.dp1.di_size)); | | 1146 | node.dp1.di_size)); |
1147 | qblocks += node.dp1.di_blocks; | | 1147 | qblocks += node.dp1.di_blocks; |
1148 | wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), sblock.fs_fsize, &buf); | | 1148 | wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), sblock.fs_fsize, &buf); |
1149 | } else { | | 1149 | } else { |
1150 | if (mfs) { | | 1150 | if (mfs) { |
1151 | node.dp2.di_mode = IFDIR | mfsmode; | | 1151 | node.dp2.di_mode = IFDIR | mfsmode; |
1152 | node.dp2.di_uid = mfsuid; | | 1152 | node.dp2.di_uid = mfsuid; |
1153 | node.dp2.di_gid = mfsgid; | | 1153 | node.dp2.di_gid = mfsgid; |
1154 | } else { | | 1154 | } else { |
1155 | node.dp2.di_mode = IFDIR | UMASK; | | 1155 | node.dp2.di_mode = IFDIR | UMASK; |
1156 | node.dp2.di_uid = geteuid(); | | 1156 | node.dp2.di_uid = geteuid(); |
1157 | node.dp2.di_gid = getegid(); | | 1157 | node.dp2.di_gid = getegid(); |
1158 | } | | 1158 | } |
1159 | node.dp2.di_atime = tv->tv_sec; | | 1159 | node.dp2.di_atime = tv->tv_sec; |
1160 | node.dp2.di_atimensec = tv->tv_usec * 1000; | | 1160 | node.dp2.di_atimensec = tv->tv_usec * 1000; |
1161 | node.dp2.di_mtime = tv->tv_sec; | | 1161 | node.dp2.di_mtime = tv->tv_sec; |
1162 | node.dp2.di_mtimensec = tv->tv_usec * 1000; | | 1162 | node.dp2.di_mtimensec = tv->tv_usec * 1000; |
1163 | node.dp2.di_ctime = tv->tv_sec; | | 1163 | node.dp2.di_ctime = tv->tv_sec; |
1164 | node.dp2.di_ctimensec = tv->tv_usec * 1000; | | 1164 | node.dp2.di_ctimensec = tv->tv_usec * 1000; |
1165 | node.dp2.di_birthtime = tv->tv_sec; | | 1165 | node.dp2.di_birthtime = tv->tv_sec; |
1166 | node.dp2.di_birthnsec = tv->tv_usec * 1000; | | 1166 | node.dp2.di_birthnsec = tv->tv_usec * 1000; |
1167 | node.dp2.di_nlink = PREDEFDIR; | | 1167 | node.dp2.di_nlink = PREDEFDIR; |
1168 | node.dp2.di_size = makedir(&buf, root_dir, PREDEFDIR); | | 1168 | node.dp2.di_size = makedir(&buf, root_dir, PREDEFDIR); |
1169 | node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode); | | 1169 | node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode); |
1170 | if (node.dp2.di_db[0] == 0) | | 1170 | if (node.dp2.di_db[0] == 0) |
1171 | return (0); | | 1171 | return (0); |
1172 | node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, | | 1172 | node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, |
1173 | node.dp2.di_size)); | | 1173 | node.dp2.di_size)); |
1174 | qblocks += node.dp2.di_blocks; | | 1174 | qblocks += node.dp2.di_blocks; |
1175 | wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), sblock.fs_fsize, &buf); | | 1175 | wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), sblock.fs_fsize, &buf); |
1176 | } | | 1176 | } |
1177 | qinos++; | | 1177 | qinos++; |
1178 | iput(&node, UFS_ROOTINO); | | 1178 | iput(&node, UFS_ROOTINO); |
1179 | /* | | 1179 | /* |
1180 | * compute the size of the hash table | | 1180 | * compute the size of the hash table |
1181 | * We know the smallest block size is 4k, so we can use 2k | | 1181 | * We know the smallest block size is 4k, so we can use 2k |
1182 | * for the hash table; as an entry is 8 bytes we can store | | 1182 | * for the hash table; as an entry is 8 bytes we can store |
1183 | * 256 entries. So let start q2h_hash_shift at 8 | | 1183 | * 256 entries. So let start q2h_hash_shift at 8 |
1184 | */ | | 1184 | */ |
1185 | for (q2h_hash_shift = 8; | | 1185 | for (q2h_hash_shift = 8; |
1186 | q2h_hash_shift < 15; | | 1186 | q2h_hash_shift < 15; |
1187 | q2h_hash_shift++) { | | 1187 | q2h_hash_shift++) { |
1188 | if ((sizeof(uint64_t) << (q2h_hash_shift + 1)) + | | 1188 | if ((sizeof(uint64_t) << (q2h_hash_shift + 1)) + |
1189 | sizeof(struct quota2_header) > (u_int)sblock.fs_bsize) | | 1189 | sizeof(struct quota2_header) > (u_int)sblock.fs_bsize) |
1190 | break; | | 1190 | break; |
1191 | } | | 1191 | } |
1192 | q2h_hash_mask = (1 << q2h_hash_shift) - 1; | | 1192 | q2h_hash_mask = (1 << q2h_hash_shift) - 1; |
1193 | for (i = 0; i < MAXQUOTAS; i++) { | | 1193 | for (i = 0; i < MAXQUOTAS; i++) { |
1194 | struct quota2_header *q2h; | | 1194 | struct quota2_header *q2h; |
1195 | struct quota2_entry *q2e; | | 1195 | struct quota2_entry *q2e; |
1196 | uint64_t offset; | | 1196 | uint64_t offset; |
1197 | uid_t uid = (i == USRQUOTA ? geteuid() : getegid()); | | 1197 | uid_t uid = (i == USRQUOTA ? geteuid() : getegid()); |
1198 | | | 1198 | |
1199 | if ((quotas & FS_Q2_DO_TYPE(i)) == 0) | | 1199 | if ((quotas & FS_Q2_DO_TYPE(i)) == 0) |
1200 | continue; | | 1200 | continue; |
1201 | quota2_create_blk0(sblock.fs_bsize, &buf, q2h_hash_shift, | | 1201 | quota2_create_blk0(sblock.fs_bsize, &buf, q2h_hash_shift, |
1202 | i, needswap); | | 1202 | i, needswap); |
1203 | /* grab an entry from header for root dir */ | | 1203 | /* grab an entry from header for root dir */ |
1204 | q2h = &buf.q2h; | | 1204 | q2h = &buf.q2h; |
1205 | offset = ufs_rw64(q2h->q2h_free, needswap); | | 1205 | offset = ufs_rw64(q2h->q2h_free, needswap); |
1206 | q2e = (void *)((char *)&buf + offset); | | 1206 | q2e = (void *)((char *)&buf + offset); |
1207 | q2h->q2h_free = q2e->q2e_next; | | 1207 | q2h->q2h_free = q2e->q2e_next; |
1208 | memcpy(q2e, &q2h->q2h_defentry, sizeof(*q2e)); | | 1208 | memcpy(q2e, &q2h->q2h_defentry, sizeof(*q2e)); |
1209 | q2e->q2e_uid = ufs_rw32(uid, needswap); | | 1209 | q2e->q2e_uid = ufs_rw32(uid, needswap); |
1210 | q2e->q2e_val[QL_BLOCK].q2v_cur = ufs_rw64(qblocks, needswap); | | 1210 | q2e->q2e_val[QL_BLOCK].q2v_cur = ufs_rw64(qblocks, needswap); |
1211 | q2e->q2e_val[QL_FILE].q2v_cur = ufs_rw64(qinos, needswap); | | 1211 | q2e->q2e_val[QL_FILE].q2v_cur = ufs_rw64(qinos, needswap); |
1212 | /* add to the hash entry */ | | 1212 | /* add to the hash entry */ |
1213 | q2e->q2e_next = q2h->q2h_entries[uid & q2h_hash_mask]; | | 1213 | q2e->q2e_next = q2h->q2h_entries[uid & q2h_hash_mask]; |
1214 | q2h->q2h_entries[uid & q2h_hash_mask] = | | 1214 | q2h->q2h_entries[uid & q2h_hash_mask] = |
1215 | ufs_rw64(offset, needswap); | | 1215 | ufs_rw64(offset, needswap); |
1216 | | | 1216 | |
1217 | memset(&node, 0, sizeof(node)); | | 1217 | memset(&node, 0, sizeof(node)); |
1218 | if (sblock.fs_magic == FS_UFS1_MAGIC) { | | 1218 | if (sblock.fs_magic == FS_UFS1_MAGIC) { |
1219 | node.dp1.di_atime = tv->tv_sec; | | 1219 | node.dp1.di_atime = tv->tv_sec; |
1220 | node.dp1.di_atimensec = tv->tv_usec * 1000; | | 1220 | node.dp1.di_atimensec = tv->tv_usec * 1000; |
1221 | node.dp1.di_mtime = tv->tv_sec; | | 1221 | node.dp1.di_mtime = tv->tv_sec; |
1222 | node.dp1.di_mtimensec = tv->tv_usec * 1000; | | 1222 | node.dp1.di_mtimensec = tv->tv_usec * 1000; |
1223 | node.dp1.di_ctime = tv->tv_sec; | | 1223 | node.dp1.di_ctime = tv->tv_sec; |
1224 | node.dp1.di_ctimensec = tv->tv_usec * 1000; | | 1224 | node.dp1.di_ctimensec = tv->tv_usec * 1000; |
1225 | node.dp1.di_mode = IFREG; | | 1225 | node.dp1.di_mode = IFREG; |
1226 | node.dp1.di_nlink = 1; | | 1226 | node.dp1.di_nlink = 1; |
1227 | node.dp1.di_size = sblock.fs_bsize; | | 1227 | node.dp1.di_size = sblock.fs_bsize; |
1228 | node.dp1.di_db[0] = | | 1228 | node.dp1.di_db[0] = |
1229 | alloc(node.dp1.di_size, node.dp1.di_mode); | | 1229 | alloc(node.dp1.di_size, node.dp1.di_mode); |
1230 | if (node.dp1.di_db[0] == 0) | | 1230 | if (node.dp1.di_db[0] == 0) |
1231 | return (0); | | 1231 | return (0); |
1232 | node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, | | 1232 | node.dp1.di_blocks = btodb(ffs_fragroundup(&sblock, |
1233 | node.dp1.di_size)); | | 1233 | node.dp1.di_size)); |
1234 | node.dp1.di_uid = geteuid(); | | 1234 | node.dp1.di_uid = geteuid(); |
1235 | node.dp1.di_gid = getegid(); | | 1235 | node.dp1.di_gid = getegid(); |
1236 | wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), | | 1236 | wtfs(FFS_FSBTODB(&sblock, node.dp1.di_db[0]), |
1237 | node.dp1.di_size, &buf); | | 1237 | node.dp1.di_size, &buf); |
1238 | } else { | | 1238 | } else { |
1239 | node.dp2.di_atime = tv->tv_sec; | | 1239 | node.dp2.di_atime = tv->tv_sec; |
1240 | node.dp2.di_atimensec = tv->tv_usec * 1000; | | 1240 | node.dp2.di_atimensec = tv->tv_usec * 1000; |
1241 | node.dp2.di_mtime = tv->tv_sec; | | 1241 | node.dp2.di_mtime = tv->tv_sec; |
1242 | node.dp2.di_mtimensec = tv->tv_usec * 1000; | | 1242 | node.dp2.di_mtimensec = tv->tv_usec * 1000; |
1243 | node.dp2.di_ctime = tv->tv_sec; | | 1243 | node.dp2.di_ctime = tv->tv_sec; |
1244 | node.dp2.di_ctimensec = tv->tv_usec * 1000; | | 1244 | node.dp2.di_ctimensec = tv->tv_usec * 1000; |
1245 | node.dp2.di_birthtime = tv->tv_sec; | | 1245 | node.dp2.di_birthtime = tv->tv_sec; |
1246 | node.dp2.di_birthnsec = tv->tv_usec * 1000; | | 1246 | node.dp2.di_birthnsec = tv->tv_usec * 1000; |
1247 | node.dp2.di_mode = IFREG; | | 1247 | node.dp2.di_mode = IFREG; |
1248 | node.dp2.di_nlink = 1; | | 1248 | node.dp2.di_nlink = 1; |
1249 | node.dp2.di_size = sblock.fs_bsize; | | 1249 | node.dp2.di_size = sblock.fs_bsize; |
1250 | node.dp2.di_db[0] = | | 1250 | node.dp2.di_db[0] = |
1251 | alloc(node.dp2.di_size, node.dp2.di_mode); | | 1251 | alloc(node.dp2.di_size, node.dp2.di_mode); |
1252 | if (node.dp2.di_db[0] == 0) | | 1252 | if (node.dp2.di_db[0] == 0) |
1253 | return (0); | | 1253 | return (0); |
1254 | node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, | | 1254 | node.dp2.di_blocks = btodb(ffs_fragroundup(&sblock, |
1255 | node.dp2.di_size)); | | 1255 | node.dp2.di_size)); |
1256 | node.dp2.di_uid = geteuid(); | | 1256 | node.dp2.di_uid = geteuid(); |
1257 | node.dp2.di_gid = getegid(); | | 1257 | node.dp2.di_gid = getegid(); |
1258 | wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), | | 1258 | wtfs(FFS_FSBTODB(&sblock, node.dp2.di_db[0]), |
1259 | node.dp2.di_size, &buf); | | 1259 | node.dp2.di_size, &buf); |
1260 | } | | 1260 | } |
1261 | iput(&node, nextino); | | 1261 | iput(&node, nextino); |
1262 | sblock.fs_quotafile[i] = nextino; | | 1262 | sblock.fs_quotafile[i] = nextino; |
1263 | nextino++; | | 1263 | nextino++; |
1264 | } | | 1264 | } |
1265 | return (1); | | 1265 | return (1); |
1266 | } | | 1266 | } |
1267 | | | 1267 | |
1268 | /* | | 1268 | /* |
1269 | * construct a set of directory entries in "buf". | | 1269 | * construct a set of directory entries in "buf". |
1270 | * return size of directory. | | 1270 | * return size of directory. |
1271 | */ | | 1271 | */ |
1272 | int | | 1272 | int |
1273 | makedir(union Buffer *buf, struct direct *protodir, int entries) | | 1273 | makedir(union Buffer *buf, struct direct *protodir, int entries) |
1274 | { | | 1274 | { |
1275 | char *cp; | | 1275 | char *cp; |
1276 | int i, spcleft; | | 1276 | int i, spcleft; |
1277 | int dirblksiz = UFS_DIRBLKSIZ; | | 1277 | int dirblksiz = UFS_DIRBLKSIZ; |
1278 | if (isappleufs) | | 1278 | if (isappleufs) |
1279 | dirblksiz = APPLEUFS_DIRBLKSIZ; | | 1279 | dirblksiz = APPLEUFS_DIRBLKSIZ; |
1280 | | | 1280 | |
1281 | memset(buf, 0, dirblksiz); | | 1281 | memset(buf, 0, dirblksiz); |
1282 | spcleft = dirblksiz; | | 1282 | spcleft = dirblksiz; |
1283 | for (cp = buf->data, i = 0; i < entries - 1; i++) { | | 1283 | for (cp = buf->data, i = 0; i < entries - 1; i++) { |
1284 | protodir[i].d_reclen = UFS_DIRSIZ(Oflag == 0, &protodir[i], 0); | | 1284 | protodir[i].d_reclen = UFS_DIRSIZ(Oflag == 0, &protodir[i], 0); |
1285 | copy_dir(&protodir[i], (struct direct*)cp); | | 1285 | copy_dir(&protodir[i], (struct direct*)cp); |
1286 | cp += protodir[i].d_reclen; | | 1286 | cp += protodir[i].d_reclen; |
1287 | spcleft -= protodir[i].d_reclen; | | 1287 | spcleft -= protodir[i].d_reclen; |
1288 | } | | 1288 | } |
1289 | protodir[i].d_reclen = spcleft; | | 1289 | protodir[i].d_reclen = spcleft; |
1290 | copy_dir(&protodir[i], (struct direct*)cp); | | 1290 | copy_dir(&protodir[i], (struct direct*)cp); |
1291 | return (dirblksiz); | | 1291 | return (dirblksiz); |
1292 | } | | 1292 | } |
1293 | | | 1293 | |
1294 | /* | | 1294 | /* |
1295 | * allocate a block or frag | | 1295 | * allocate a block or frag |
1296 | */ | | 1296 | */ |
1297 | daddr_t | | 1297 | daddr_t |
1298 | alloc(int size, int mode) | | 1298 | alloc(int size, int mode) |
1299 | { | | 1299 | { |
1300 | int i, frag; | | 1300 | int i, frag; |
1301 | daddr_t d, blkno; | | 1301 | daddr_t d, blkno; |
1302 | | | 1302 | |
1303 | rdfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); | | 1303 | rdfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); |
1304 | /* fs -> host byte order */ | | 1304 | /* fs -> host byte order */ |
1305 | if (needswap) | | 1305 | if (needswap) |
1306 | ffs_cg_swap(&acg, &acg, &sblock); | | 1306 | ffs_cg_swap(&acg, &acg, &sblock); |
1307 | if (acg.cg_magic != CG_MAGIC) { | | 1307 | if (acg.cg_magic != CG_MAGIC) { |
1308 | printf("cg 0: bad magic number\n"); | | 1308 | printf("cg 0: bad magic number\n"); |
1309 | return (0); | | 1309 | return (0); |
1310 | } | | 1310 | } |
1311 | if (acg.cg_cs.cs_nbfree == 0) { | | 1311 | if (acg.cg_cs.cs_nbfree == 0) { |
1312 | printf("first cylinder group ran out of space\n"); | | 1312 | printf("first cylinder group ran out of space\n"); |
1313 | return (0); | | 1313 | return (0); |
1314 | } | | 1314 | } |
1315 | for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) | | 1315 | for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) |
1316 | if (isblock(&sblock, cg_blksfree(&acg, 0), | | 1316 | if (isblock(&sblock, cg_blksfree(&acg, 0), |
1317 | d >> sblock.fs_fragshift)) | | 1317 | d >> sblock.fs_fragshift)) |
1318 | goto goth; | | 1318 | goto goth; |
1319 | printf("internal error: can't find block in cyl 0\n"); | | 1319 | printf("internal error: can't find block in cyl 0\n"); |
1320 | return (0); | | 1320 | return (0); |
1321 | goth: | | 1321 | goth: |
1322 | blkno = ffs_fragstoblks(&sblock, d); | | 1322 | blkno = ffs_fragstoblks(&sblock, d); |
1323 | clrblock(&sblock, cg_blksfree(&acg, 0), blkno); | | 1323 | clrblock(&sblock, cg_blksfree(&acg, 0), blkno); |
1324 | if (sblock.fs_contigsumsize > 0) | | 1324 | if (sblock.fs_contigsumsize > 0) |
1325 | clrbit(cg_clustersfree(&acg, 0), blkno); | | 1325 | clrbit(cg_clustersfree(&acg, 0), blkno); |
1326 | acg.cg_cs.cs_nbfree--; | | 1326 | acg.cg_cs.cs_nbfree--; |
1327 | sblock.fs_cstotal.cs_nbfree--; | | 1327 | sblock.fs_cstotal.cs_nbfree--; |
1328 | fscs_0->cs_nbfree--; | | 1328 | fscs_0->cs_nbfree--; |
1329 | if (mode & IFDIR) { | | 1329 | if (mode & IFDIR) { |
1330 | acg.cg_cs.cs_ndir++; | | 1330 | acg.cg_cs.cs_ndir++; |
1331 | sblock.fs_cstotal.cs_ndir++; | | 1331 | sblock.fs_cstotal.cs_ndir++; |
1332 | fscs_0->cs_ndir++; | | 1332 | fscs_0->cs_ndir++; |
1333 | } | | 1333 | } |
1334 | if (Oflag <= 1) { | | 1334 | if (Oflag <= 1) { |
1335 | int cn = old_cbtocylno(&sblock, d); | | 1335 | int cn = old_cbtocylno(&sblock, d); |
1336 | old_cg_blktot(&acg, 0)[cn]--; | | 1336 | old_cg_blktot(&acg, 0)[cn]--; |
1337 | old_cg_blks(&sblock, &acg, | | 1337 | old_cg_blks(&sblock, &acg, |
1338 | cn, 0)[old_cbtorpos(&sblock, d)]--; | | 1338 | cn, 0)[old_cbtorpos(&sblock, d)]--; |
1339 | } | | 1339 | } |
1340 | if (size != sblock.fs_bsize) { | | 1340 | if (size != sblock.fs_bsize) { |
1341 | frag = howmany(size, sblock.fs_fsize); | | 1341 | frag = howmany(size, sblock.fs_fsize); |
1342 | fscs_0->cs_nffree += sblock.fs_frag - frag; | | 1342 | fscs_0->cs_nffree += sblock.fs_frag - frag; |
1343 | sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; | | 1343 | sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; |
1344 | acg.cg_cs.cs_nffree += sblock.fs_frag - frag; | | 1344 | acg.cg_cs.cs_nffree += sblock.fs_frag - frag; |
1345 | acg.cg_frsum[sblock.fs_frag - frag]++; | | 1345 | acg.cg_frsum[sblock.fs_frag - frag]++; |
1346 | for (i = frag; i < sblock.fs_frag; i++) | | 1346 | for (i = frag; i < sblock.fs_frag; i++) |
1347 | setbit(cg_blksfree(&acg, 0), d + i); | | 1347 | setbit(cg_blksfree(&acg, 0), d + i); |
1348 | } | | 1348 | } |
1349 | /* host -> fs byte order */ | | 1349 | /* host -> fs byte order */ |
1350 | if (needswap) | | 1350 | if (needswap) |
1351 | ffs_cg_swap(&acg, &acg, &sblock); | | 1351 | ffs_cg_swap(&acg, &acg, &sblock); |
1352 | wtfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); | | 1352 | wtfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); |
1353 | return (d); | | 1353 | return (d); |
1354 | } | | 1354 | } |
1355 | | | 1355 | |
1356 | /* | | 1356 | /* |
1357 | * Allocate an inode on the disk | | 1357 | * Allocate an inode on the disk |
1358 | */ | | 1358 | */ |
1359 | static void | | 1359 | static void |
1360 | iput(union dinode *ip, ino_t ino) | | 1360 | iput(union dinode *ip, ino_t ino) |
1361 | { | | 1361 | { |
1362 | daddr_t d; | | 1362 | daddr_t d; |
1363 | int i; | | 1363 | int i; |
1364 | struct ufs1_dinode *dp1; | | 1364 | struct ufs1_dinode *dp1; |
1365 | struct ufs2_dinode *dp2; | | 1365 | struct ufs2_dinode *dp2; |
1366 | | | 1366 | |
1367 | rdfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); | | 1367 | rdfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); |
1368 | /* fs -> host byte order */ | | 1368 | /* fs -> host byte order */ |
1369 | if (needswap) | | 1369 | if (needswap) |
1370 | ffs_cg_swap(&acg, &acg, &sblock); | | 1370 | ffs_cg_swap(&acg, &acg, &sblock); |
1371 | if (acg.cg_magic != CG_MAGIC) { | | 1371 | if (acg.cg_magic != CG_MAGIC) { |
1372 | printf("cg 0: bad magic number\n"); | | 1372 | printf("cg 0: bad magic number\n"); |
1373 | fserr(31); | | 1373 | fserr(31); |
1374 | } | | 1374 | } |
1375 | acg.cg_cs.cs_nifree--; | | 1375 | acg.cg_cs.cs_nifree--; |
1376 | setbit(cg_inosused(&acg, 0), ino); | | 1376 | setbit(cg_inosused(&acg, 0), ino); |
1377 | /* host -> fs byte order */ | | 1377 | /* host -> fs byte order */ |
1378 | if (needswap) | | 1378 | if (needswap) |
1379 | ffs_cg_swap(&acg, &acg, &sblock); | | 1379 | ffs_cg_swap(&acg, &acg, &sblock); |
1380 | wtfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); | | 1380 | wtfs(FFS_FSBTODB(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, &acg); |
1381 | sblock.fs_cstotal.cs_nifree--; | | 1381 | sblock.fs_cstotal.cs_nifree--; |
1382 | fscs_0->cs_nifree--; | | 1382 | fscs_0->cs_nifree--; |
1383 | if (ino >= (ino_t)(sblock.fs_ipg * sblock.fs_ncg)) { | | 1383 | if (ino >= (ino_t)(sblock.fs_ipg * sblock.fs_ncg)) { |
1384 | printf("fsinit: inode value out of range (%llu).\n", | | 1384 | printf("fsinit: inode value out of range (%llu).\n", |
1385 | (unsigned long long)ino); | | 1385 | (unsigned long long)ino); |
1386 | fserr(32); | | 1386 | fserr(32); |
1387 | } | | 1387 | } |
1388 | d = FFS_FSBTODB(&sblock, ino_to_fsba(&sblock, ino)); | | 1388 | d = FFS_FSBTODB(&sblock, ino_to_fsba(&sblock, ino)); |
1389 | rdfs(d, sblock.fs_bsize, (char *)iobuf); | | 1389 | rdfs(d, sblock.fs_bsize, (char *)iobuf); |
1390 | if (sblock.fs_magic == FS_UFS1_MAGIC) { | | 1390 | if (sblock.fs_magic == FS_UFS1_MAGIC) { |
1391 | dp1 = (struct ufs1_dinode *)iobuf; | | 1391 | dp1 = (struct ufs1_dinode *)iobuf; |
1392 | dp1 += ino_to_fsbo(&sblock, ino); | | 1392 | dp1 += ino_to_fsbo(&sblock, ino); |
1393 | if (needswap) { | | 1393 | if (needswap) { |
1394 | ffs_dinode1_swap(&ip->dp1, dp1); | | 1394 | ffs_dinode1_swap(&ip->dp1, dp1); |
1395 | /* ffs_dinode1_swap() doesn't swap blocks addrs */ | | 1395 | /* ffs_dinode1_swap() doesn't swap blocks addrs */ |
1396 | for (i=0; i<UFS_NDADDR; i++) | | 1396 | for (i=0; i<UFS_NDADDR; i++) |
1397 | dp1->di_db[i] = bswap32(ip->dp1.di_db[i]); | | 1397 | dp1->di_db[i] = bswap32(ip->dp1.di_db[i]); |
1398 | for (i=0; i<UFS_NIADDR; i++) | | 1398 | for (i=0; i<UFS_NIADDR; i++) |
1399 | dp1->di_ib[i] = bswap32(ip->dp1.di_ib[i]); | | 1399 | dp1->di_ib[i] = bswap32(ip->dp1.di_ib[i]); |
1400 | } else | | 1400 | } else |
1401 | *dp1 = ip->dp1; | | 1401 | *dp1 = ip->dp1; |
1402 | dp1->di_gen = arc4random() & INT32_MAX; | | 1402 | dp1->di_gen = arc4random() & INT32_MAX; |
1403 | } else { | | 1403 | } else { |
1404 | dp2 = (struct ufs2_dinode *)iobuf; | | 1404 | dp2 = (struct ufs2_dinode *)iobuf; |
1405 | dp2 += ino_to_fsbo(&sblock, ino); | | 1405 | dp2 += ino_to_fsbo(&sblock, ino); |
1406 | if (needswap) { | | 1406 | if (needswap) { |
1407 | ffs_dinode2_swap(&ip->dp2, dp2); | | 1407 | ffs_dinode2_swap(&ip->dp2, dp2); |
1408 | for (i=0; i<UFS_NDADDR; i++) | | 1408 | for (i=0; i<UFS_NDADDR; i++) |
1409 | dp2->di_db[i] = bswap64(ip->dp2.di_db[i]); | | 1409 | dp2->di_db[i] = bswap64(ip->dp2.di_db[i]); |
1410 | for (i=0; i<UFS_NIADDR; i++) | | 1410 | for (i=0; i<UFS_NIADDR; i++) |
1411 | dp2->di_ib[i] = bswap64(ip->dp2.di_ib[i]); | | 1411 | dp2->di_ib[i] = bswap64(ip->dp2.di_ib[i]); |
1412 | } else | | 1412 | } else |
1413 | *dp2 = ip->dp2; | | 1413 | *dp2 = ip->dp2; |
1414 | dp2->di_gen = arc4random() & INT32_MAX; | | 1414 | dp2->di_gen = arc4random() & INT32_MAX; |
1415 | } | | 1415 | } |
1416 | wtfs(d, sblock.fs_bsize, iobuf); | | 1416 | wtfs(d, sblock.fs_bsize, iobuf); |
1417 | } | | 1417 | } |
1418 | | | 1418 | |
1419 | /* | | 1419 | /* |
1420 | * read a block from the file system | | 1420 | * read a block from the file system |
1421 | */ | | 1421 | */ |
1422 | void | | 1422 | void |
1423 | rdfs(daddr_t bno, int size, void *bf) | | 1423 | rdfs(daddr_t bno, int size, void *bf) |
1424 | { | | 1424 | { |
1425 | int n; | | 1425 | int n; |
1426 | off_t offset; | | 1426 | off_t offset; |
1427 | | | 1427 | |
1428 | #ifdef MFS | | 1428 | #ifdef MFS |
1429 | if (mfs) { | | 1429 | if (mfs) { |
1430 | if (Nflag) | | 1430 | if (Nflag) |
1431 | memset(bf, 0, size); | | 1431 | memset(bf, 0, size); |
1432 | else | | 1432 | else |
1433 | memmove(bf, membase + bno * sectorsize, size); | | 1433 | memmove(bf, membase + bno * sectorsize, size); |
1434 | return; | | 1434 | return; |
1435 | } | | 1435 | } |
1436 | #endif | | 1436 | #endif |
1437 | offset = bno; | | 1437 | offset = bno; |
1438 | n = pread(fsi, bf, size, offset * sectorsize); | | 1438 | n = pread(fsi, bf, size, offset * sectorsize); |
1439 | if (n != size) { | | 1439 | if (n != size) { |
1440 | printf("rdfs: read error for sector %lld: %s\n", | | 1440 | printf("rdfs: read error for sector %lld: %s\n", |
1441 | (long long)bno, strerror(errno)); | | 1441 | (long long)bno, strerror(errno)); |
1442 | exit(34); | | 1442 | exit(34); |
1443 | } | | 1443 | } |
1444 | } | | 1444 | } |
1445 | | | 1445 | |
1446 | /* | | 1446 | /* |
1447 | * write a block to the file system | | 1447 | * write a block to the file system |
1448 | */ | | 1448 | */ |
1449 | void | | 1449 | void |
1450 | wtfs(daddr_t bno, int size, void *bf) | | 1450 | wtfs(daddr_t bno, int size, void *bf) |
1451 | { | | 1451 | { |
1452 | int n; | | 1452 | int n; |
1453 | off_t offset; | | 1453 | off_t offset; |
1454 | | | 1454 | |
1455 | if (Nflag) | | 1455 | if (Nflag) |
1456 | return; | | 1456 | return; |
1457 | #ifdef MFS | | 1457 | #ifdef MFS |
1458 | if (mfs) { | | 1458 | if (mfs) { |
1459 | memmove(membase + bno * sectorsize, bf, size); | | 1459 | memmove(membase + bno * sectorsize, bf, size); |
1460 | return; | | 1460 | return; |
1461 | } | | 1461 | } |
1462 | #endif | | 1462 | #endif |
1463 | offset = bno; | | 1463 | offset = bno; |
1464 | n = pwrite(fso, bf, size, offset * sectorsize); | | 1464 | n = pwrite(fso, bf, size, offset * sectorsize); |
1465 | if (n != size) { | | 1465 | if (n != size) { |
1466 | printf("wtfs: write error for sector %lld: %s\n", | | 1466 | printf("wtfs: write error for sector %lld: %s\n", |
1467 | (long long)bno, strerror(errno)); | | 1467 | (long long)bno, strerror(errno)); |
1468 | exit(36); | | 1468 | exit(36); |
1469 | } | | 1469 | } |
1470 | } | | 1470 | } |
1471 | | | 1471 | |
1472 | /* | | 1472 | /* |
1473 | * check if a block is available | | 1473 | * check if a block is available |
1474 | */ | | 1474 | */ |
1475 | int | | 1475 | int |
1476 | isblock(struct fs *fs, unsigned char *cp, int h) | | 1476 | isblock(struct fs *fs, unsigned char *cp, int h) |
1477 | { | | 1477 | { |
1478 | unsigned char mask; | | 1478 | unsigned char mask; |
1479 | | | 1479 | |
1480 | switch (fs->fs_fragshift) { | | 1480 | switch (fs->fs_fragshift) { |
1481 | case 3: | | 1481 | case 3: |
1482 | return (cp[h] == 0xff); | | 1482 | return (cp[h] == 0xff); |
1483 | case 2: | | 1483 | case 2: |
1484 | mask = 0x0f << ((h & 0x1) << 2); | | 1484 | mask = 0x0f << ((h & 0x1) << 2); |
1485 | return ((cp[h >> 1] & mask) == mask); | | 1485 | return ((cp[h >> 1] & mask) == mask); |
1486 | case 1: | | 1486 | case 1: |
1487 | mask = 0x03 << ((h & 0x3) << 1); | | 1487 | mask = 0x03 << ((h & 0x3) << 1); |
1488 | return ((cp[h >> 2] & mask) == mask); | | 1488 | return ((cp[h >> 2] & mask) == mask); |
1489 | case 0: | | 1489 | case 0: |
1490 | mask = 0x01 << (h & 0x7); | | 1490 | mask = 0x01 << (h & 0x7); |
1491 | return ((cp[h >> 3] & mask) == mask); | | 1491 | return ((cp[h >> 3] & mask) == mask); |
1492 | default: | | 1492 | default: |
1493 | #ifdef STANDALONE | | 1493 | #ifdef STANDALONE |
1494 | printf("isblock bad fs_fragshift %d\n", fs->fs_fragshift); | | 1494 | printf("isblock bad fs_fragshift %d\n", fs->fs_fragshift); |
1495 | #else | | 1495 | #else |
1496 | fprintf(stderr, "isblock bad fs_fragshift %d\n", | | 1496 | fprintf(stderr, "isblock bad fs_fragshift %d\n", |
1497 | fs->fs_fragshift); | | 1497 | fs->fs_fragshift); |
1498 | #endif | | 1498 | #endif |
1499 | return (0); | | 1499 | return (0); |
1500 | } | | 1500 | } |
1501 | } | | 1501 | } |
1502 | | | 1502 | |
1503 | /* | | 1503 | /* |
1504 | * take a block out of the map | | 1504 | * take a block out of the map |
1505 | */ | | 1505 | */ |
1506 | void | | 1506 | void |
1507 | clrblock(struct fs *fs, unsigned char *cp, int h) | | 1507 | clrblock(struct fs *fs, unsigned char *cp, int h) |
1508 | { | | 1508 | { |
1509 | switch ((fs)->fs_fragshift) { | | 1509 | switch ((fs)->fs_fragshift) { |
1510 | case 3: | | 1510 | case 3: |
1511 | cp[h] = 0; | | 1511 | cp[h] = 0; |
1512 | return; | | 1512 | return; |
1513 | case 2: | | 1513 | case 2: |
1514 | cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); | | 1514 | cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); |
1515 | return; | | 1515 | return; |
1516 | case 1: | | 1516 | case 1: |
1517 | cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); | | 1517 | cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); |
1518 | return; | | 1518 | return; |
1519 | case 0: | | 1519 | case 0: |
1520 | cp[h >> 3] &= ~(0x01 << (h & 0x7)); | | 1520 | cp[h >> 3] &= ~(0x01 << (h & 0x7)); |
1521 | return; | | 1521 | return; |
1522 | default: | | 1522 | default: |
1523 | #ifdef STANDALONE | | 1523 | #ifdef STANDALONE |
1524 | printf("clrblock bad fs_fragshift %d\n", fs->fs_fragshift); | | 1524 | printf("clrblock bad fs_fragshift %d\n", fs->fs_fragshift); |
1525 | #else | | 1525 | #else |
1526 | fprintf(stderr, "clrblock bad fs_fragshift %d\n", | | 1526 | fprintf(stderr, "clrblock bad fs_fragshift %d\n", |
1527 | fs->fs_fragshift); | | 1527 | fs->fs_fragshift); |
1528 | #endif | | 1528 | #endif |
1529 | return; | | 1529 | return; |
1530 | } | | 1530 | } |
1531 | } | | 1531 | } |
1532 | | | 1532 | |
1533 | /* | | 1533 | /* |
1534 | * put a block into the map | | 1534 | * put a block into the map |
1535 | */ | | 1535 | */ |
1536 | void | | 1536 | void |
1537 | setblock(struct fs *fs, unsigned char *cp, int h) | | 1537 | setblock(struct fs *fs, unsigned char *cp, int h) |
1538 | { | | 1538 | { |
1539 | switch (fs->fs_fragshift) { | | 1539 | switch (fs->fs_fragshift) { |
1540 | case 3: | | 1540 | case 3: |
1541 | cp[h] = 0xff; | | 1541 | cp[h] = 0xff; |
1542 | return; | | 1542 | return; |
1543 | case 2: | | 1543 | case 2: |
1544 | cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); | | 1544 | cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); |
1545 | return; | | 1545 | return; |
1546 | case 1: | | 1546 | case 1: |
1547 | cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); | | 1547 | cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); |
1548 | return; | | 1548 | return; |
1549 | case 0: | | 1549 | case 0: |
1550 | cp[h >> 3] |= (0x01 << (h & 0x7)); | | 1550 | cp[h >> 3] |= (0x01 << (h & 0x7)); |
1551 | return; | | 1551 | return; |
1552 | default: | | 1552 | default: |
1553 | #ifdef STANDALONE | | 1553 | #ifdef STANDALONE |
1554 | printf("setblock bad fs_frag %d\n", fs->fs_fragshift); | | 1554 | printf("setblock bad fs_frag %d\n", fs->fs_fragshift); |
1555 | #else | | 1555 | #else |
1556 | fprintf(stderr, "setblock bad fs_fragshift %d\n", | | 1556 | fprintf(stderr, "setblock bad fs_fragshift %d\n", |
1557 | fs->fs_fragshift); | | 1557 | fs->fs_fragshift); |
1558 | #endif | | 1558 | #endif |
1559 | return; | | 1559 | return; |
1560 | } | | 1560 | } |
1561 | } | | 1561 | } |
1562 | | | 1562 | |
1563 | /* copy a direntry to a buffer, in fs byte order */ | | 1563 | /* copy a direntry to a buffer, in fs byte order */ |
1564 | static void | | 1564 | static void |
1565 | copy_dir(struct direct *dir, struct direct *dbuf) | | 1565 | copy_dir(struct direct *dir, struct direct *dbuf) |
1566 | { | | 1566 | { |
1567 | memcpy(dbuf, dir, UFS_DIRSIZ(Oflag == 0, dir, 0)); | | 1567 | memcpy(dbuf, dir, UFS_DIRSIZ(Oflag == 0, dir, 0)); |
1568 | if (needswap) { | | 1568 | if (needswap) { |
1569 | dbuf->d_ino = bswap32(dir->d_ino); | | 1569 | dbuf->d_ino = bswap32(dir->d_ino); |
1570 | dbuf->d_reclen = bswap16(dir->d_reclen); | | 1570 | dbuf->d_reclen = bswap16(dir->d_reclen); |
1571 | if (Oflag == 0) | | 1571 | if (Oflag == 0) |
1572 | ((struct odirect*)dbuf)->d_namlen = | | 1572 | ((struct odirect*)dbuf)->d_namlen = |
1573 | bswap16(((struct odirect*)dir)->d_namlen); | | 1573 | bswap16(((struct odirect*)dir)->d_namlen); |
1574 | } | | 1574 | } |
1575 | } | | 1575 | } |
1576 | | | 1576 | |
1577 | static int | | 1577 | static int |
1578 | ilog2(int val) | | 1578 | ilog2(int val) |
1579 | { | | 1579 | { |
1580 | u_int n; | | 1580 | u_int n; |
1581 | | | 1581 | |
1582 | for (n = 0; n < sizeof(n) * CHAR_BIT; n++) | | 1582 | for (n = 0; n < sizeof(n) * CHAR_BIT; n++) |
1583 | if (1 << n == val) | | 1583 | if (1 << n == val) |
1584 | return (n); | | 1584 | return (n); |
1585 | errx(1, "ilog2: %d is not a power of 2", val); | | 1585 | errx(1, "ilog2: %d is not a power of 2", val); |
1586 | } | | 1586 | } |
1587 | | | 1587 | |
1588 | static void | | 1588 | static void |
1589 | zap_old_sblock(int sblkoff) | | 1589 | zap_old_sblock(int sblkoff) |
1590 | { | | 1590 | { |
1591 | static int cg0_data; | | 1591 | static int cg0_data; |
1592 | uint32_t oldfs[SBLOCKSIZE / 4] __aligned(DEV_BSIZE); | | 1592 | uint32_t oldfs[SBLOCKSIZE / 4] __aligned(DEV_BSIZE); |
1593 | static const struct fsm { | | 1593 | static const struct fsm { |
1594 | uint32_t offset; | | 1594 | uint32_t offset; |
1595 | uint32_t magic; | | 1595 | uint32_t magic; |
1596 | uint32_t mask; | | 1596 | uint32_t mask; |
1597 | } fs_magics[] = { | | 1597 | } fs_magics[] = { |
1598 | {offsetof(struct fs, fs_magic)/4, FS_UFS1_MAGIC, ~0u}, | | 1598 | {offsetof(struct fs, fs_magic)/4, FS_UFS1_MAGIC, ~0u}, |
1599 | {offsetof(struct fs, fs_magic)/4, FS_UFS2_MAGIC, ~0u}, | | 1599 | {offsetof(struct fs, fs_magic)/4, FS_UFS2_MAGIC, ~0u}, |
1600 | {0, 0x70162, ~0u}, /* LFS_MAGIC */ | | 1600 | {0, 0x70162, ~0u}, /* LFS_MAGIC */ |
1601 | {14, 0xef53, 0xffff}, /* EXT2FS (little) */ | | 1601 | {14, 0xef53, 0xffff}, /* EXT2FS (little) */ |
1602 | {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ | | 1602 | {14, 0xef530000, 0xffff0000}, /* EXT2FS (big) */ |
1603 | {.offset = ~0u}, | | 1603 | {.offset = ~0u}, |
1604 | }; | | 1604 | }; |
1605 | const struct fsm *fsm; | | 1605 | const struct fsm *fsm; |
1606 | | | 1606 | |
1607 | if (Nflag) | | 1607 | if (Nflag) |
1608 | return; | | 1608 | return; |
1609 | | | 1609 | |
1610 | if (sblkoff == 0) /* Why did UFS2 add support for this? sigh. */ | | 1610 | if (sblkoff == 0) /* Why did UFS2 add support for this? sigh. */ |
1611 | return; | | 1611 | return; |
1612 | | | 1612 | |
1613 | if (cg0_data == 0) | | 1613 | if (cg0_data == 0) |