File: | src/usr.sbin/makefs/ffs.c |
Warning: | line 762, column 2 Value stored to 'chunk' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ffs.c,v 1.36 2022/01/11 05:34:32 jsg Exp $ */ |
2 | /* $NetBSD: ffs.c,v 1.66 2015/12/21 00:58:08 christos Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 2001 Wasabi Systems, Inc. |
6 | * All rights reserved. |
7 | * |
8 | * Written by Luke Mewburn for Wasabi Systems, Inc. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. All advertising materials mentioning features or use of this software |
19 | * must display the following acknowledgement: |
20 | * This product includes software developed for the NetBSD Project by |
21 | * Wasabi Systems, Inc. |
22 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse |
23 | * or promote products derived from this software without specific prior |
24 | * written permission. |
25 | * |
26 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND |
27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
28 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
29 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC |
30 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
36 | * POSSIBILITY OF SUCH DAMAGE. |
37 | */ |
38 | /* |
39 | * Copyright (c) 1982, 1986, 1989, 1993 |
40 | * The Regents of the University of California. All rights reserved. |
41 | * |
42 | * Redistribution and use in source and binary forms, with or without |
43 | * modification, are permitted provided that the following conditions |
44 | * are met: |
45 | * 1. Redistributions of source code must retain the above copyright |
46 | * notice, this list of conditions and the following disclaimer. |
47 | * 2. Redistributions in binary form must reproduce the above copyright |
48 | * notice, this list of conditions and the following disclaimer in the |
49 | * documentation and/or other materials provided with the distribution. |
50 | * 3. Neither the name of the University nor the names of its contributors |
51 | * may be used to endorse or promote products derived from this software |
52 | * without specific prior written permission. |
53 | * |
54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
64 | * SUCH DAMAGE. |
65 | * |
66 | * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95 |
67 | */ |
68 | |
69 | #include <sys/param.h> /* roundup DEV_BSIZE */ |
70 | #include <sys/types.h> |
71 | #include <sys/disklabel.h> |
72 | |
73 | #include <assert.h> |
74 | #include <errno(*__errno()).h> |
75 | #include <fcntl.h> |
76 | #include <stdarg.h> |
77 | #include <stdio.h> |
78 | #include <stdint.h> |
79 | #include <limits.h> |
80 | #include <stdlib.h> |
81 | #include <string.h> |
82 | #include <unistd.h> |
83 | |
84 | #include <ufs/ufs/dinode.h> |
85 | #include <ufs/ufs/dir.h> |
86 | #include <ufs/ffs/fs.h> |
87 | |
88 | #include "ffs/ufs_inode.h" |
89 | #include "ffs/ffs_extern.h" |
90 | |
91 | #include "makefs.h" |
92 | #include "ffs.h" |
93 | #include "ffs/newfs_extern.h" |
94 | |
95 | #undef DIP |
96 | #define DIP(dp, field)((ffs_opts->version == 1) ? (dp)->ffs1_din.di_field : ( dp)->ffs2_din.di_field) \ |
97 | ((ffs_opts->version == 1) ? \ |
98 | (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field) |
99 | |
100 | /* |
101 | * Various file system defaults (cribbed from newfs(8)). |
102 | */ |
103 | #define DFL_FRAGSIZE2048 2048 /* fragment size */ |
104 | #define DFL_BLKSIZE16384 16384 /* block size */ |
105 | #define DFL_SECSIZE512 512 /* sector size */ |
106 | |
107 | |
108 | typedef struct { |
109 | u_char *buf; /* buf for directory */ |
110 | doff_tint32_t size; /* full size of buf */ |
111 | doff_tint32_t cur; /* offset of current entry */ |
112 | } dirbuf_t; |
113 | |
114 | |
115 | static int ffs_create_image(const char *, fsinfo_t *); |
116 | static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *); |
117 | static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *); |
118 | static void ffs_size_dir(fsnode *, fsinfo_t *); |
119 | static void ffs_validate(const char *, fsnode *, fsinfo_t *); |
120 | static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *); |
121 | static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *); |
122 | static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *, |
123 | fsnode *, fsinfo_t *); |
124 | static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *, |
125 | fsnode *, fsinfo_t *); |
126 | |
127 | |
128 | |
129 | /* publicly visible functions */ |
130 | void |
131 | ffs_prep_opts(fsinfo_t *fsopts) |
132 | { |
133 | ffs_opt_t *ffs_opts = ecalloc(1, sizeof(*ffs_opts)); |
134 | |
135 | const option_t ffs_options[] = { |
136 | { "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32, 1, INT_MAX2147483647 }, |
137 | { "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32, 1, INT_MAX2147483647 }, |
138 | { "bsize", &ffs_opts->bsize, OPT_INT32, 1, INT_MAX2147483647 }, |
139 | { "density", &ffs_opts->density, OPT_INT32, 1, INT_MAX2147483647 }, |
140 | { "disklabel", NULL((void*)0), OPT_STRBUF, 0, 0 }, |
141 | { "extent", &ffs_opts->maxbsize, OPT_INT32, 1, INT_MAX2147483647 }, |
142 | { "fsize", &ffs_opts->fsize, OPT_INT32, 1, INT_MAX2147483647 }, |
143 | { "label", ffs_opts->label, OPT_STRARRAY, 1, MAXVOLLEN32 }, |
144 | { "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32, 1, INT_MAX2147483647 }, |
145 | { "maxbpg", &ffs_opts->maxbpg, OPT_INT32, 1, INT_MAX2147483647 }, |
146 | { "minfree", &ffs_opts->minfree, OPT_INT32, 0, 99 }, |
147 | { "optimization", NULL((void*)0), OPT_STRBUF, 0, 0 }, |
148 | { "version", &ffs_opts->version, OPT_INT32, 1, 2 }, |
149 | { .name = NULL((void*)0) } |
150 | }; |
151 | |
152 | ffs_opts->bsize = -1; |
153 | ffs_opts->fsize = -1; |
154 | ffs_opts->density = -1; |
155 | ffs_opts->minfree = MINFREE5; |
156 | ffs_opts->optimization = FS_OPTSPACE1; |
157 | ffs_opts->maxbpg = -1; |
158 | ffs_opts->avgfilesize = AVFILESIZ16384; |
159 | ffs_opts->avgfpdir = AFPDIR64; |
160 | ffs_opts->version = 1; |
161 | ffs_opts->lp = NULL((void*)0); |
162 | ffs_opts->pp = NULL((void*)0); |
163 | |
164 | fsopts->fs_specific = ffs_opts; |
165 | fsopts->fs_options = copy_opts(ffs_options); |
166 | } |
167 | |
168 | void |
169 | ffs_cleanup_opts(fsinfo_t *fsopts) |
170 | { |
171 | free(fsopts->fs_specific); |
172 | free(fsopts->fs_options); |
173 | } |
174 | |
175 | int |
176 | ffs_parse_opts(const char *option, fsinfo_t *fsopts) |
177 | { |
178 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
179 | option_t *ffs_options = fsopts->fs_options; |
180 | char buf[1024]; |
181 | |
182 | int rv; |
183 | |
184 | assert(option != NULL)((option != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 184, __func__, "option != NULL")); |
185 | assert(fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 185, __func__, "fsopts != NULL")); |
186 | assert(ffs_opts != NULL)((ffs_opts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 186, __func__, "ffs_opts != NULL")); |
187 | |
188 | rv = set_option(ffs_options, option, buf, sizeof(buf)); |
189 | if (rv == -1) |
190 | return 0; |
191 | |
192 | if (ffs_options[rv].name == NULL((void*)0)) |
193 | abort(); |
194 | |
195 | if (strcmp(ffs_options[rv].name, "disklabel") == 0) { |
196 | struct disklabel *dp; |
197 | |
198 | dp = getdiskbyname(buf); |
199 | if (dp == NULL((void*)0)) |
200 | errx(1, "unknown disk type: %s", buf); |
201 | |
202 | ffs_opts->lp = emalloc(sizeof(struct disklabel)); |
203 | *ffs_opts->lp = *dp; |
204 | } else if (strcmp(ffs_options[rv].name, "optimization") == 0) { |
205 | if (strcmp(buf, "time") == 0) { |
206 | ffs_opts->optimization = FS_OPTTIME0; |
207 | } else if (strcmp(buf, "space") == 0) { |
208 | ffs_opts->optimization = FS_OPTSPACE1; |
209 | } else { |
210 | warnx("Invalid optimization `%s'", buf); |
211 | return 0; |
212 | } |
213 | } |
214 | return 1; |
215 | } |
216 | |
217 | |
218 | void |
219 | ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) |
220 | { |
221 | struct fs *superblock; |
222 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
223 | |
224 | assert(image != NULL)((image != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 224, __func__, "image != NULL")); |
225 | assert(dir != NULL)((dir != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 225, __func__, "dir != NULL")); |
226 | assert(root != NULL)((root != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 226, __func__, "root != NULL")); |
227 | assert(fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 227, __func__, "fsopts != NULL")); |
228 | |
229 | /* validate tree and options */ |
230 | ffs_validate(dir, root, fsopts); |
231 | |
232 | printf("Calculated size of `%s': %lld bytes, %lld inodes\n", |
233 | image, (long long)fsopts->size, (long long)fsopts->inodes); |
234 | |
235 | /* create image */ |
236 | if (ffs_create_image(image, fsopts) == -1) |
237 | errx(1, "Image file `%s' not created.", image); |
238 | |
239 | fsopts->curinode = ROOTINO((ufsino_t)2); |
240 | |
241 | /* populate image */ |
242 | printf("Populating `%s'\n", image); |
243 | if (! ffs_populate_dir(dir, root, fsopts)) |
244 | errx(1, "Image file `%s' not populated.", image); |
245 | |
246 | bcleanup(); |
247 | |
248 | /* update various superblock parameters */ |
249 | superblock = fsopts->superblock; |
250 | superblock->fs_fmod = 0; |
251 | superblock->fs_ffs1_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir; |
252 | superblock->fs_ffs1_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree; |
253 | superblock->fs_ffs1_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree; |
254 | superblock->fs_ffs1_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree; |
255 | |
256 | /* write out superblock; image is now complete */ |
257 | ffs_write_superblock(fsopts->superblock, fsopts); |
258 | |
259 | if (ffs_opts->lp != NULL((void*)0)) { |
260 | struct disklabel *lp = ffs_opts->lp; |
261 | uint16_t *p, *end, sum = 0; |
262 | ssize_t n; |
263 | uint32_t bpg; |
264 | |
265 | bpg = superblock->fs_fpg / superblock->fs_frag; |
266 | while (bpg > UINT16_MAX0xffff) |
267 | bpg >>= 1; |
268 | ffs_opts->pp->p_cpg = bpg; |
269 | |
270 | lp->d_magic = DISKMAGIC((u_int32_t)0x82564557); |
271 | lp->d_magic2 = DISKMAGIC((u_int32_t)0x82564557); |
272 | arc4random_buf(lp->d_uid, sizeof(lp->d_uid)); |
273 | lp->d_checksum = 0; |
274 | |
275 | p = (uint16_t *)lp; |
276 | end = (uint16_t *)&lp->d_partitions[lp->d_npartitions]; |
277 | while (p < end) |
278 | sum ^= *p++; |
279 | lp->d_checksum = sum; |
280 | |
281 | n = pwrite(fsopts->fd, lp, sizeof(struct disklabel), |
282 | fsopts->offset + LABELSECTOR1 * DEV_BSIZE(1 << 9) + LABELOFFSET0); |
283 | if (n == -1) |
284 | err(1, "failed to write disklabel"); |
285 | else if (n < sizeof(struct disklabel)) |
286 | errx(1, "failed to write disklabel: short write"); |
287 | } |
288 | |
289 | if (close(fsopts->fd) == -1) |
290 | err(1, "Closing `%s'", image); |
291 | fsopts->fd = -1; |
292 | printf("Image `%s' complete\n", image); |
293 | } |
294 | |
295 | /* end of public functions */ |
296 | |
297 | |
298 | static void |
299 | ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts) |
300 | { |
301 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
302 | struct disklabel *lp = ffs_opts->lp; |
303 | struct partition *pp = NULL((void*)0); |
304 | int32_t ncg = 1; |
305 | int i; |
306 | |
307 | assert(dir != NULL)((dir != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 307, __func__, "dir != NULL")); |
308 | assert(root != NULL)((root != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 308, __func__, "root != NULL")); |
309 | assert(fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 309, __func__, "fsopts != NULL")); |
310 | assert(ffs_opts != NULL)((ffs_opts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 310, __func__, "ffs_opts != NULL")); |
311 | |
312 | if (lp != NULL((void*)0)) { |
313 | for (i = 0; i < lp->d_npartitions; i++) { |
314 | pp = &lp->d_partitions[i]; |
315 | if (pp->p_fstype == FS_BSDFFS7 && |
316 | pp->p_offset * lp->d_secsize == fsopts->offset) { |
317 | break; |
318 | } |
319 | } |
320 | if (i == lp->d_npartitions) |
321 | errx(1, "no matching partition found in the disklabel"); |
322 | ffs_opts->pp = pp; |
323 | |
324 | if (pp->p_fragblock == 0) |
325 | errx(1, "fragment size missing in disktab"); |
326 | if (fsopts->freeblocks != 0 || fsopts->freeblockpc != 0 || |
327 | fsopts->freefiles != 0 || fsopts->freefilepc != 0 || |
328 | fsopts->minsize != 0 || fsopts->maxsize != 0 || |
329 | fsopts->sectorsize != -1 || fsopts->size != 0) |
330 | errx(1, "-bfMmSs and disklabel are mutually exclusive"); |
331 | if (ffs_opts->fsize != -1 || ffs_opts->bsize != -1) |
332 | errx(1, "b/fsize and disklabel are mutually exclusive"); |
333 | |
334 | fsopts->sectorsize = lp->d_secsize; |
335 | fsopts->minsize = fsopts->maxsize = |
336 | DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) * lp->d_secsize; |
337 | ffs_opts->fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock)(((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock ) & 0x07) - 1))) == 0 ? 0 : (((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock) >> 3) + 12))) / ((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock ) & 0x07) - 1))))); |
338 | ffs_opts->bsize = DISKLABELV1_FFS_BSIZE(pp->p_fragblock)((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock ) >> 3) + 12))); |
339 | } |
340 | |
341 | /* set FFS defaults */ |
342 | if (fsopts->sectorsize == -1) |
343 | fsopts->sectorsize = DFL_SECSIZE512; |
344 | if (ffs_opts->fsize == -1) |
345 | ffs_opts->fsize = MAXIMUM(DFL_FRAGSIZE, fsopts->sectorsize)(((2048) > (fsopts->sectorsize)) ? (2048) : (fsopts-> sectorsize)); |
346 | if (ffs_opts->bsize == -1) |
347 | ffs_opts->bsize = MINIMUM(DFL_BLKSIZE, 8 * ffs_opts->fsize)(((16384) < (8 * ffs_opts->fsize)) ? (16384) : (8 * ffs_opts ->fsize)); |
348 | /* fsopts->density is set below */ |
349 | /* XXX ondisk32 */ |
350 | if (ffs_opts->maxbpg == -1) |
351 | ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t); |
352 | |
353 | /* calculate size of tree */ |
354 | ffs_size_dir(root, fsopts); |
355 | fsopts->inodes += ROOTINO((ufsino_t)2); /* include first two inodes */ |
356 | |
357 | /* add requested slop */ |
358 | fsopts->size += fsopts->freeblocks; |
359 | fsopts->inodes += fsopts->freefiles; |
360 | if (fsopts->freefilepc > 0) |
361 | fsopts->inodes = |
362 | fsopts->inodes * (100 + fsopts->freefilepc) / 100; |
363 | if (fsopts->freeblockpc > 0) |
364 | fsopts->size = |
365 | fsopts->size * (100 + fsopts->freeblockpc) / 100; |
366 | |
367 | /* add space needed for superblocks */ |
368 | /* |
369 | * The old SBOFF (SBLOCK_UFS1) is used here because makefs is |
370 | * typically used for small filesystems where space matters. |
371 | * XXX make this an option. |
372 | */ |
373 | fsopts->size += (SBLOCK_UFS18192 + SBLOCKSIZE8192) * ncg; |
374 | /* add space needed to store inodes, x3 for blockmaps, etc */ |
375 | if (ffs_opts->version == 1) |
376 | fsopts->size += ncg * sizeof(struct ufs1_dinode) * |
377 | roundup(fsopts->inodes / ncg,((((fsopts->inodes / ncg)+((ffs_opts->bsize / sizeof(struct ufs1_dinode))-1))/(ffs_opts->bsize / sizeof(struct ufs1_dinode )))*(ffs_opts->bsize / sizeof(struct ufs1_dinode))) |
378 | ffs_opts->bsize / sizeof(struct ufs1_dinode))((((fsopts->inodes / ncg)+((ffs_opts->bsize / sizeof(struct ufs1_dinode))-1))/(ffs_opts->bsize / sizeof(struct ufs1_dinode )))*(ffs_opts->bsize / sizeof(struct ufs1_dinode))); |
379 | else |
380 | fsopts->size += ncg * sizeof(struct ufs2_dinode) * |
381 | roundup(fsopts->inodes / ncg,((((fsopts->inodes / ncg)+((ffs_opts->bsize / sizeof(struct ufs2_dinode))-1))/(ffs_opts->bsize / sizeof(struct ufs2_dinode )))*(ffs_opts->bsize / sizeof(struct ufs2_dinode))) |
382 | ffs_opts->bsize / sizeof(struct ufs2_dinode))((((fsopts->inodes / ncg)+((ffs_opts->bsize / sizeof(struct ufs2_dinode))-1))/(ffs_opts->bsize / sizeof(struct ufs2_dinode )))*(ffs_opts->bsize / sizeof(struct ufs2_dinode))); |
383 | |
384 | /* add minfree */ |
385 | if (ffs_opts->minfree > 0) |
386 | fsopts->size = |
387 | fsopts->size * (100 + ffs_opts->minfree) / 100; |
388 | /* |
389 | * XXX any other fs slop to add, such as csum's, bitmaps, etc ?? |
390 | */ |
391 | |
392 | if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */ |
393 | fsopts->size = fsopts->minsize; |
394 | |
395 | /* round up to the next block */ |
396 | fsopts->size = roundup(fsopts->size, ffs_opts->bsize)((((fsopts->size)+((ffs_opts->bsize)-1))/(ffs_opts-> bsize))*(ffs_opts->bsize)); |
397 | |
398 | /* calculate density if necessary */ |
399 | if (ffs_opts->density == -1) |
400 | ffs_opts->density = fsopts->size / fsopts->inodes + 1; |
401 | |
402 | /* now check calculated sizes vs requested sizes */ |
403 | if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) { |
404 | errx(1, "`%s' size of %lld is larger than the maxsize of %lld.", |
405 | dir, (long long)fsopts->size, (long long)fsopts->maxsize); |
406 | } |
407 | } |
408 | |
409 | |
410 | static int |
411 | ffs_create_image(const char *image, fsinfo_t *fsopts) |
412 | { |
413 | struct fs *fs; |
414 | char *buf; |
415 | int i, bufsize; |
416 | off_t bufrem; |
417 | time_t tstamp; |
418 | int oflags = O_RDWR0x0002 | O_CREAT0x0200; |
419 | |
420 | assert (image != NULL)((image != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 420, __func__, "image != NULL")); |
421 | assert (fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 421, __func__, "fsopts != NULL")); |
422 | |
423 | /* create image */ |
424 | if (fsopts->offset == 0) |
425 | oflags |= O_TRUNC0x0400; |
426 | if ((fsopts->fd = open(image, oflags, 0666)) == -1) { |
427 | warn("Can't open `%s' for writing", image); |
428 | return (-1); |
429 | } |
430 | |
431 | /* zero image */ |
432 | bufsize = 8192; |
433 | bufrem = fsopts->size; |
434 | |
435 | if (fsopts->offset != 0) |
436 | if (lseek(fsopts->fd, fsopts->offset, SEEK_SET0) == -1) { |
437 | warn("can't seek"); |
438 | return -1; |
439 | } |
440 | |
441 | if (bufrem > 0) |
442 | buf = ecalloc(1, bufsize); |
443 | while (bufrem > 0) { |
444 | i = write(fsopts->fd, buf, MINIMUM(bufsize, bufrem)(((bufsize) < (bufrem)) ? (bufsize) : (bufrem))); |
445 | if (i == -1) { |
446 | warn("zeroing image, %lld bytes to go", |
447 | (long long)bufrem); |
448 | free(buf); |
449 | return (-1); |
450 | } |
451 | bufrem -= i; |
452 | } |
453 | free(buf); |
454 | |
455 | /* make the file system */ |
456 | if (Tflag) { |
457 | tstamp = stampts; |
458 | srandom_deterministic(stampts); |
459 | } else |
460 | tstamp = start_time.tv_sec; |
461 | |
462 | fs = ffs_mkfs(image, fsopts, tstamp); |
463 | fsopts->superblock = (void *)fs; |
464 | |
465 | if ((off_t)(fs->fs_cstotal.cs_nifree + ROOTINO((ufsino_t)2)) < fsopts->inodes) { |
466 | warnx( |
467 | "Image file `%s' has %lld free inodes; %lld are required.", |
468 | image, |
469 | (long long)(fs->fs_cstotal.cs_nifree + ROOTINO((ufsino_t)2)), |
470 | (long long)fsopts->inodes); |
471 | return (-1); |
472 | } |
473 | return (fsopts->fd); |
474 | } |
475 | |
476 | |
477 | static void |
478 | ffs_size_dir(fsnode *root, fsinfo_t *fsopts) |
479 | { |
480 | struct direct tmpdir; |
481 | fsnode * node; |
482 | int curdirsize, this; |
483 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
484 | |
485 | /* node may be NULL (empty directory) */ |
486 | assert(fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 486, __func__, "fsopts != NULL")); |
487 | assert(ffs_opts != NULL)((ffs_opts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 487, __func__, "ffs_opts != NULL")); |
488 | |
489 | #define ADDDIRENT(e)do { tmpdir.d_namlen = strlen((e)); this = ((0) ? ((sizeof(struct direct) - (255 +1)) + (((&tmpdir)->d_type+1 + 3) & ~ 3)) : ((sizeof(struct direct) - (255 +1)) + (((&tmpdir) ->d_namlen+1 + 3) &~ 3))); if (this + curdirsize > ( (((curdirsize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9)))) curdirsize = ((((curdirsize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9))); curdirsize += this; } while (0); do { \ |
490 | tmpdir.d_namlen = strlen((e)); \ |
491 | this = DIRSIZ(NEWDIRFMT, &tmpdir)((0) ? ((sizeof(struct direct) - (255 +1)) + (((&tmpdir)-> d_type+1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1) ) + (((&tmpdir)->d_namlen+1 + 3) &~ 3))); \ |
492 | if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ)((((curdirsize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9)))) \ |
493 | curdirsize = roundup(curdirsize, DIRBLKSIZ)((((curdirsize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9))); \ |
494 | curdirsize += this; \ |
495 | } while (0); |
496 | |
497 | /* |
498 | * XXX this needs to take into account extra space consumed |
499 | * by indirect blocks, etc. |
500 | */ |
501 | #define ADDSIZE(x)do { fsopts->size += (((((x))+((ffs_opts->fsize)-1))/(ffs_opts ->fsize))*(ffs_opts->fsize)); } while (0); do { \ |
502 | fsopts->size += roundup((x), ffs_opts->fsize)(((((x))+((ffs_opts->fsize)-1))/(ffs_opts->fsize))*(ffs_opts ->fsize)); \ |
503 | } while (0); |
504 | |
505 | curdirsize = 0; |
506 | for (node = root; node != NULL((void*)0); node = node->next) { |
507 | ADDDIRENT(node->name)do { tmpdir.d_namlen = strlen((node->name)); this = ((0) ? ((sizeof(struct direct) - (255 +1)) + (((&tmpdir)->d_type +1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1)) + (( (&tmpdir)->d_namlen+1 + 3) &~ 3))); if (this + curdirsize > ((((curdirsize)+(((1 << 9))-1))/((1 << 9))) *((1 << 9)))) curdirsize = ((((curdirsize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9))); curdirsize += this ; } while (0);; |
508 | if (node == root) { /* we're at "." */ |
509 | assert(strcmp(node->name, ".") == 0)((strcmp(node->name, ".") == 0) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 509, __func__, "strcmp(node->name, \".\") == 0")); |
510 | ADDDIRENT("..")do { tmpdir.d_namlen = strlen(("..")); this = ((0) ? ((sizeof (struct direct) - (255 +1)) + (((&tmpdir)->d_type+1 + 3 ) &~ 3)) : ((sizeof(struct direct) - (255 +1)) + (((& tmpdir)->d_namlen+1 + 3) &~ 3))); if (this + curdirsize > ((((curdirsize)+(((1 << 9))-1))/((1 << 9))) *((1 << 9)))) curdirsize = ((((curdirsize)+(((1 << 9))-1))/((1 << 9)))*((1 << 9))); curdirsize += this ; } while (0);; |
511 | } else if ((node->inode->flags & FI_SIZED) == 0) { |
512 | /* don't count duplicate names */ |
513 | node->inode->flags |= FI_SIZED; |
514 | fsopts->inodes++; |
515 | if (node->type == S_IFREG0100000) |
516 | ADDSIZE(node->inode->st.st_size)do { fsopts->size += (((((node->inode->st.st_size))+ ((ffs_opts->fsize)-1))/(ffs_opts->fsize))*(ffs_opts-> fsize)); } while (0);; |
517 | if (node->type == S_IFLNK0120000) { |
518 | size_t slen; |
519 | |
520 | slen = strlen(node->symlink) + 1; |
521 | if (slen >= (ffs_opts->version == 1 ? |
522 | MAXSYMLINKLEN_UFS1((12 + 3) * sizeof(int32_t)) : |
523 | MAXSYMLINKLEN_UFS2((12 + 3) * sizeof(int64_t)))) |
524 | ADDSIZE(slen)do { fsopts->size += (((((slen))+((ffs_opts->fsize)-1)) /(ffs_opts->fsize))*(ffs_opts->fsize)); } while (0);; |
525 | } |
526 | } |
527 | if (node->type == S_IFDIR0040000) |
528 | ffs_size_dir(node->child, fsopts); |
529 | } |
530 | ADDSIZE(curdirsize)do { fsopts->size += (((((curdirsize))+((ffs_opts->fsize )-1))/(ffs_opts->fsize))*(ffs_opts->fsize)); } while (0 );; |
531 | } |
532 | |
533 | static void * |
534 | ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, |
535 | fsnode *root, fsinfo_t *fsopts) |
536 | { |
537 | size_t slen; |
538 | void *membuf; |
539 | |
540 | memset(dinp, 0, sizeof(*dinp)); |
541 | dinp->di_mode = cur->inode->st.st_mode; |
542 | dinp->di_nlink = cur->inode->nlink; |
543 | dinp->di_size = cur->inode->st.st_size; |
544 | dinp->di_flags = cur->inode->st.st_flags; |
545 | dinp->di_gen = cur->inode->st.st_gen; |
546 | dinp->di_uid = cur->inode->st.st_uid; |
547 | dinp->di_gid = cur->inode->st.st_gid; |
548 | |
549 | dinp->di_atime = cur->inode->st.st_atimest_atim.tv_sec; |
550 | dinp->di_mtime = cur->inode->st.st_mtimest_mtim.tv_sec; |
551 | dinp->di_ctime = cur->inode->st.st_ctimest_ctim.tv_sec; |
552 | dinp->di_atimensec = cur->inode->st.st_atimensecst_atim.tv_nsec; |
553 | dinp->di_mtimensec = cur->inode->st.st_mtimensecst_mtim.tv_nsec; |
554 | dinp->di_ctimensec = cur->inode->st.st_ctimensecst_ctim.tv_nsec; |
555 | /* not set: di_db, di_ib, di_blocks, di_spare */ |
556 | |
557 | membuf = NULL((void*)0); |
558 | if (cur == root) { /* "."; write dirbuf */ |
559 | membuf = dbufp->buf; |
560 | dinp->di_size = dbufp->size; |
561 | } else if (S_ISBLK(cur->type)((cur->type & 0170000) == 0060000) || S_ISCHR(cur->type)((cur->type & 0170000) == 0020000)) { |
562 | dinp->di_size = 0; /* a device */ |
563 | dinp->di_rdevdi_db[0] = cur->inode->st.st_rdev; |
564 | } else if (S_ISLNK(cur->type)((cur->type & 0170000) == 0120000)) { /* symlink */ |
565 | slen = strlen(cur->symlink); |
566 | if (slen < MAXSYMLINKLEN_UFS1((12 + 3) * sizeof(int32_t))) { /* short link */ |
567 | memcpy(dinp->di_db, cur->symlink, slen); |
568 | } else |
569 | membuf = cur->symlink; |
570 | dinp->di_size = slen; |
571 | } |
572 | return membuf; |
573 | } |
574 | |
575 | static void * |
576 | ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, |
577 | fsnode *root, fsinfo_t *fsopts) |
578 | { |
579 | size_t slen; |
580 | void *membuf; |
581 | |
582 | memset(dinp, 0, sizeof(*dinp)); |
583 | dinp->di_mode = cur->inode->st.st_mode; |
584 | dinp->di_nlink = cur->inode->nlink; |
585 | dinp->di_size = cur->inode->st.st_size; |
586 | dinp->di_flags = cur->inode->st.st_flags; |
587 | dinp->di_gen = cur->inode->st.st_gen; |
588 | dinp->di_uid = cur->inode->st.st_uid; |
589 | dinp->di_gid = cur->inode->st.st_gid; |
590 | |
591 | dinp->di_atime = cur->inode->st.st_atimest_atim.tv_sec; |
592 | dinp->di_mtime = cur->inode->st.st_mtimest_mtim.tv_sec; |
593 | dinp->di_ctime = cur->inode->st.st_ctimest_ctim.tv_sec; |
594 | dinp->di_atimensec = cur->inode->st.st_atimensecst_atim.tv_nsec; |
595 | dinp->di_mtimensec = cur->inode->st.st_mtimensecst_mtim.tv_nsec; |
596 | dinp->di_ctimensec = cur->inode->st.st_ctimensecst_ctim.tv_nsec; |
597 | /* not set: di_db, di_ib, di_blocks, di_spare */ |
598 | |
599 | membuf = NULL((void*)0); |
600 | if (cur == root) { /* "."; write dirbuf */ |
601 | membuf = dbufp->buf; |
602 | dinp->di_size = dbufp->size; |
603 | } else if (S_ISBLK(cur->type)((cur->type & 0170000) == 0060000) || S_ISCHR(cur->type)((cur->type & 0170000) == 0020000)) { |
604 | dinp->di_size = 0; /* a device */ |
605 | dinp->di_rdevdi_db[0] = cur->inode->st.st_rdev; |
606 | } else if (S_ISLNK(cur->type)((cur->type & 0170000) == 0120000)) { /* symlink */ |
607 | slen = strlen(cur->symlink); |
608 | if (slen < MAXSYMLINKLEN_UFS2((12 + 3) * sizeof(int64_t))) { /* short link */ |
609 | memcpy(dinp->di_db, cur->symlink, slen); |
610 | } else |
611 | membuf = cur->symlink; |
612 | dinp->di_size = slen; |
613 | } |
614 | return membuf; |
615 | } |
616 | |
617 | static int |
618 | ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts) |
619 | { |
620 | fsnode *cur; |
621 | dirbuf_t dirbuf; |
622 | union dinode din; |
623 | void *membuf; |
624 | char path[PATH_MAX1024 + 1]; |
625 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
626 | |
627 | assert(dir != NULL)((dir != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 627, __func__, "dir != NULL")); |
628 | assert(root != NULL)((root != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 628, __func__, "root != NULL")); |
629 | assert(fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 629, __func__, "fsopts != NULL")); |
630 | assert(ffs_opts != NULL)((ffs_opts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 630, __func__, "ffs_opts != NULL")); |
631 | |
632 | (void)memset(&dirbuf, 0, sizeof(dirbuf)); |
633 | |
634 | /* |
635 | * pass 1: allocate inode numbers, build directory `file' |
636 | */ |
637 | for (cur = root; cur != NULL((void*)0); cur = cur->next) { |
638 | if ((cur->inode->flags & FI_ALLOCATED) == 0) { |
639 | cur->inode->flags |= FI_ALLOCATED; |
640 | if (cur == root && cur->parent != NULL((void*)0)) |
641 | cur->inode->ino = cur->parent->inode->ino; |
642 | else { |
643 | cur->inode->ino = fsopts->curinode; |
644 | fsopts->curinode++; |
645 | } |
646 | } |
647 | ffs_make_dirbuf(&dirbuf, cur->name, cur); |
648 | if (cur == root) { /* we're at "."; add ".." */ |
649 | ffs_make_dirbuf(&dirbuf, "..", |
650 | cur->parent == NULL((void*)0) ? cur : cur->parent->first); |
651 | root->inode->nlink++; /* count my parent's link */ |
652 | } else if (cur->child != NULL((void*)0)) |
653 | root->inode->nlink++; /* count my child's link */ |
654 | |
655 | /* |
656 | * XXX possibly write file and long symlinks here, |
657 | * ensuring that blocks get written before inodes? |
658 | * otoh, this isn't a real filesystem, so who |
659 | * cares about ordering? :-) |
660 | */ |
661 | } |
662 | |
663 | /* |
664 | * pass 2: write out dirbuf, then non-directories at this level |
665 | */ |
666 | for (cur = root; cur != NULL((void*)0); cur = cur->next) { |
667 | if (cur->inode->flags & FI_WRITTEN) |
668 | continue; /* skip hard-linked entries */ |
669 | cur->inode->flags |= FI_WRITTEN; |
670 | |
671 | if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root, |
672 | cur->path, cur->name) >= sizeof(path)) |
673 | errx(1, "Pathname too long."); |
674 | |
675 | if (cur->child != NULL((void*)0)) |
676 | continue; /* child creates own inode */ |
677 | |
678 | /* build on-disk inode */ |
679 | if (ffs_opts->version == 1) |
680 | membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur, |
681 | root, fsopts); |
682 | else |
683 | membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur, |
684 | root, fsopts); |
685 | |
686 | if (membuf != NULL((void*)0)) { |
687 | ffs_write_file(&din, cur->inode->ino, membuf, fsopts); |
688 | } else if (S_ISREG(cur->type)((cur->type & 0170000) == 0100000)) { |
689 | ffs_write_file(&din, cur->inode->ino, path, fsopts); |
690 | } else { |
691 | assert (! S_ISDIR(cur->type))((! ((cur->type & 0170000) == 0040000)) ? (void)0 : __assert2 ("/usr/src/usr.sbin/makefs/ffs.c", 691, __func__, "! S_ISDIR(cur->type)" )); |
692 | ffs_write_inode(&din, cur->inode->ino, fsopts); |
693 | } |
694 | } |
695 | |
696 | /* |
697 | * pass 3: write out sub-directories |
698 | */ |
699 | for (cur = root; cur != NULL((void*)0); cur = cur->next) { |
700 | if (cur->child == NULL((void*)0)) |
701 | continue; |
702 | if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir, |
703 | cur->name) >= sizeof(path)) |
704 | errx(1, "Pathname too long."); |
705 | if (! ffs_populate_dir(path, cur->child, fsopts)) |
706 | return (0); |
707 | } |
708 | |
709 | /* cleanup */ |
710 | free(dirbuf.buf); |
711 | return (1); |
712 | } |
713 | |
714 | |
715 | static void |
716 | ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts) |
717 | { |
718 | int isfile, ffd; |
719 | char *fbuf, *p; |
720 | off_t bufleft, chunk, offset; |
721 | ssize_t nread; |
722 | struct inode in; |
723 | struct mkfsbuf * bp; |
724 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
725 | struct mkfsvnode vp = { fsopts, NULL((void*)0) }; |
726 | |
727 | assert (din != NULL)((din != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 727, __func__, "din != NULL")); |
728 | assert (buf != NULL)((buf != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 728, __func__, "buf != NULL")); |
729 | assert (fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 729, __func__, "fsopts != NULL")); |
730 | assert (ffs_opts != NULL)((ffs_opts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 730, __func__, "ffs_opts != NULL")); |
731 | |
732 | isfile = S_ISREG(DIP(din, mode))((((ffs_opts->version == 1) ? (din)->ffs1_din.di_mode : (din)->ffs2_din.di_mode) & 0170000) == 0100000); |
733 | fbuf = NULL((void*)0); |
734 | ffd = -1; |
735 | p = NULL((void*)0); |
736 | |
737 | in.i_fs = (struct fs *)fsopts->superblock; |
738 | in.i_devvp = &vp; |
739 | |
740 | in.i_number = ino; |
741 | in.i_size = DIP(din, size)((ffs_opts->version == 1) ? (din)->ffs1_din.di_size : ( din)->ffs2_din.di_size); |
742 | if (ffs_opts->version == 1) |
743 | memcpy(&in.i_din.ffs1_din, &din->ffs1_din, |
744 | sizeof(in.i_din.ffs1_din)); |
745 | else |
746 | memcpy(&in.i_din.ffs2_din, &din->ffs2_din, |
747 | sizeof(in.i_din.ffs2_din)); |
748 | |
749 | if (DIP(din, size)((ffs_opts->version == 1) ? (din)->ffs1_din.di_size : ( din)->ffs2_din.di_size) == 0) |
750 | goto write_inode_and_leave; /* mmm, cheating */ |
751 | |
752 | if (isfile) { |
753 | fbuf = emalloc(ffs_opts->bsize); |
754 | if ((ffd = open((char *)buf, O_RDONLY0x0000)) == -1) { |
755 | warn("Can't open `%s' for reading", (char *)buf); |
756 | goto leave_ffs_write_file; |
757 | } |
758 | } else { |
759 | p = buf; |
760 | } |
761 | |
762 | chunk = 0; |
Value stored to 'chunk' is never read | |
763 | for (bufleft = DIP(din, size)((ffs_opts->version == 1) ? (din)->ffs1_din.di_size : ( din)->ffs2_din.di_size); bufleft > 0; bufleft -= chunk) { |
764 | chunk = MINIMUM(bufleft, ffs_opts->bsize)(((bufleft) < (ffs_opts->bsize)) ? (bufleft) : (ffs_opts ->bsize)); |
765 | if (!isfile) |
766 | ; |
767 | else if ((nread = read(ffd, fbuf, chunk)) == -1) |
768 | err(1, "Reading `%s', %lld bytes to go", (char *)buf, |
769 | (long long)bufleft); |
770 | else if (nread != chunk) |
771 | errx(1, "Reading `%s', %lld bytes to go, " |
772 | "read %zd bytes, expected %ju bytes, does " |
773 | "metalog size= attribute mismatch source size?", |
774 | (char *)buf, (long long)bufleft, nread, |
775 | (uintmax_t)chunk); |
776 | else |
777 | p = fbuf; |
778 | offset = DIP(din, size)((ffs_opts->version == 1) ? (din)->ffs1_din.di_size : ( din)->ffs2_din.di_size) - bufleft; |
779 | /* |
780 | * XXX if holey support is desired, do the check here |
781 | * |
782 | * XXX might need to write out last bit in fragroundup |
783 | * sized chunk. however, ffs_balloc() handles this for us |
784 | */ |
785 | errno(*__errno()) = ffs_balloc(&in, offset, chunk, &bp); |
786 | bad_ffs_write_file: |
787 | if (errno(*__errno()) != 0) |
788 | err(1, |
789 | "Writing inode %d (%s), bytes %lld + %lld", |
790 | ino, |
791 | isfile ? (char *)buf : |
792 | inode_type(DIP(din, mode)((ffs_opts->version == 1) ? (din)->ffs1_din.di_mode : ( din)->ffs2_din.di_mode) & S_IFMT0170000), |
793 | (long long)offset, (long long)chunk); |
794 | memcpy(bp->b_data, p, chunk); |
795 | errno(*__errno()) = bwrite(bp); |
796 | if (errno(*__errno()) != 0) |
797 | goto bad_ffs_write_file; |
798 | if (!isfile) |
799 | p += chunk; |
800 | } |
801 | |
802 | write_inode_and_leave: |
803 | ffs_write_inode(&in.i_din, in.i_number, fsopts); |
804 | |
805 | leave_ffs_write_file: |
806 | free(fbuf); |
807 | if (ffd != -1) |
808 | close(ffd); |
809 | } |
810 | |
811 | |
812 | static void |
813 | ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node) |
814 | { |
815 | struct direct de, *dp; |
816 | uint16_t llen; |
817 | u_char *newbuf; |
818 | |
819 | assert (dbuf != NULL)((dbuf != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 819, __func__, "dbuf != NULL")); |
820 | assert (name != NULL)((name != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 820, __func__, "name != NULL")); |
821 | assert (node != NULL)((node != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 821, __func__, "node != NULL")); |
822 | /* create direct entry */ |
823 | (void)memset(&de, 0, sizeof(de)); |
824 | de.d_ino = node->inode->ino; |
825 | de.d_type = IFTODT(node->type)(((node->type) & 0170000) >> 12); |
826 | de.d_namlen = (uint8_t)strlen(name); |
827 | strlcpy(de.d_name, name, sizeof de.d_name); |
828 | de.d_reclen = DIRSIZ(NEWDIRFMT, &de)((0) ? ((sizeof(struct direct) - (255 +1)) + (((&de)-> d_type+1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1) ) + (((&de)->d_namlen+1 + 3) &~ 3))); |
829 | |
830 | dp = (struct direct *)(dbuf->buf + dbuf->cur); |
831 | llen = 0; |
832 | if (dp != NULL((void*)0)) |
833 | llen = DIRSIZ(NEWDIRFMT, dp)((0) ? ((sizeof(struct direct) - (255 +1)) + (((dp)->d_type +1 + 3) &~ 3)) : ((sizeof(struct direct) - (255 +1)) + (( (dp)->d_namlen+1 + 3) &~ 3))); |
834 | |
835 | if (de.d_reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)((((dbuf->size)+(((1 << 9))-1))/((1 << 9)))*(( 1 << 9)))) { |
836 | newbuf = erealloc(dbuf->buf, dbuf->size + DIRBLKSIZ(1 << 9)); |
837 | dbuf->buf = newbuf; |
838 | dbuf->size += DIRBLKSIZ(1 << 9); |
839 | memset(dbuf->buf + dbuf->size - DIRBLKSIZ(1 << 9), 0, DIRBLKSIZ(1 << 9)); |
840 | dbuf->cur = dbuf->size - DIRBLKSIZ(1 << 9); |
841 | } else if (dp) { /* shrink end of previous */ |
842 | dp->d_reclen = llen; |
843 | dbuf->cur += llen; |
844 | } |
845 | dp = (struct direct *)(dbuf->buf + dbuf->cur); |
846 | memcpy(dp, &de, de.d_reclen); |
847 | dp->d_reclen = dbuf->size - dbuf->cur; |
848 | } |
849 | |
850 | /* |
851 | * cribbed from sys/ufs/ffs/ffs_alloc.c |
852 | */ |
853 | static void |
854 | ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts) |
855 | { |
856 | char *buf; |
857 | struct ufs1_dinode *dp1; |
858 | struct ufs2_dinode *dp2, *dip; |
859 | struct cg *cgp; |
860 | struct fs *fs; |
861 | int cg, cgino, i; |
862 | daddr_t d; |
863 | char sbbuf[FFS_MAXBSIZE65536]; |
864 | uint32_t initediblk; |
865 | ffs_opt_t *ffs_opts = fsopts->fs_specific; |
866 | |
867 | assert (dp != NULL)((dp != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 867, __func__, "dp != NULL")); |
868 | assert (ino > 0)((ino > 0) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 868, __func__, "ino > 0")); |
869 | assert (fsopts != NULL)((fsopts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 869, __func__, "fsopts != NULL")); |
870 | assert (ffs_opts != NULL)((ffs_opts != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 870, __func__, "ffs_opts != NULL")); |
871 | |
872 | fs = (struct fs *)fsopts->superblock; |
873 | cg = ino_to_cg(fs, ino)((ino) / (fs)->fs_ipg); |
874 | cgino = ino % fs->fs_ipg; |
875 | |
876 | ffs_rdfs(fsbtodb(fs, cgtod(fs, cg))((((((daddr_t)(fs)->fs_fpg * (cg)) + (fs)->fs_cgoffset * ((cg) & ~((fs)->fs_cgmask))) + (fs)->fs_cblkno)) << (fs)->fs_fsbtodb), (int)fs->fs_cgsize, &sbbuf, |
877 | fsopts); |
878 | cgp = (struct cg *)sbbuf; |
879 | if (!cg_chkmagic(cgp)((cgp)->cg_magic == 0x090255 || ((struct ocg *)(cgp))-> cg_magic == 0x090255)) |
880 | errx(1, "ffs_write_inode: cg %d: bad magic number", cg); |
881 | |
882 | assert (isclr(cg_inosused(cgp), cgino))((((((((cgp)->cg_magic != 0x090255) ? (((struct ocg *)(cgp ))->cg_iused) : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)-> cg_iusedoff))))[(cgino)>>3] & (1<<((cgino)& (8 -1)))) == 0)) ? (void)0 : __assert2("/usr/src/usr.sbin/makefs/ffs.c" , 882, __func__, "isclr(cg_inosused(cgp), cgino)")); |
883 | |
884 | buf = emalloc(fs->fs_bsize); |
885 | dp1 = (struct ufs1_dinode *)buf; |
886 | dp2 = (struct ufs2_dinode *)buf; |
887 | |
888 | if (fs->fs_cstotal.cs_nifree == 0) |
889 | errx(1, "ffs_write_inode: fs out of inodes for ino %u", |
890 | ino); |
891 | if (fs->fs_cs(fs, cg)fs_csp[cg].cs_nifree == 0) |
892 | errx(1, |
893 | "ffs_write_inode: cg %d out of inodes for ino %u", |
894 | cg, ino); |
895 | setbit(cg_inosused(cgp), cgino)(((((cgp)->cg_magic != 0x090255) ? (((struct ocg *)(cgp))-> cg_iused) : ((u_int8_t *)((u_int8_t *)(cgp) + (cgp)->cg_iusedoff ))))[(cgino)>>3] |= 1<<((cgino)&(8 -1))); |
896 | cgp->cg_cs.cs_nifree -= 1; |
897 | fs->fs_cstotal.cs_nifree--; |
898 | fs->fs_cs(fs, cg)fs_csp[cg].cs_nifree--; |
899 | if (S_ISDIR(DIP(dp, mode))((((ffs_opts->version == 1) ? (dp)->ffs1_din.di_mode : ( dp)->ffs2_din.di_mode) & 0170000) == 0040000)) { |
900 | cgp->cg_cs.cs_ndir += 1; |
901 | fs->fs_cstotal.cs_ndir++; |
902 | fs->fs_cs(fs, cg)fs_csp[cg].cs_ndir++; |
903 | } |
904 | |
905 | /* |
906 | * Initialize inode blocks on the fly for UFS2. |
907 | */ |
908 | initediblk = cgp->cg_initediblk; |
909 | if (ffs_opts->version == 2 && |
910 | (uint32_t)(cgino + INOPB(fs)((fs)->fs_inopb)) > initediblk && |
911 | initediblk < cgp->cg_ffs2_niblk) { |
912 | memset(buf, 0, fs->fs_bsize); |
913 | dip = (struct ufs2_dinode *)buf; |
914 | for (i = 0; i < INOPB(fs)((fs)->fs_inopb); i++) { |
915 | dip->di_gen = random() / 2 + 1; |
916 | dip++; |
917 | } |
918 | ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs,((((daddr_t)(((((daddr_t)(fs)->fs_fpg * (((cg * fs->fs_ipg + initediblk) / (fs)->fs_ipg))) + (fs)->fs_cgoffset * ( (((cg * fs->fs_ipg + initediblk) / (fs)->fs_ipg)) & ~((fs)->fs_cgmask))) + (fs)->fs_iblkno) + ((((((cg * fs ->fs_ipg + initediblk) % (fs)->fs_ipg) / ((fs)->fs_inopb ))) << ((fs))->fs_fragshift))))) << (fs)->fs_fsbtodb ) |
919 | cg * fs->fs_ipg + initediblk))((((daddr_t)(((((daddr_t)(fs)->fs_fpg * (((cg * fs->fs_ipg + initediblk) / (fs)->fs_ipg))) + (fs)->fs_cgoffset * ( (((cg * fs->fs_ipg + initediblk) / (fs)->fs_ipg)) & ~((fs)->fs_cgmask))) + (fs)->fs_iblkno) + ((((((cg * fs ->fs_ipg + initediblk) % (fs)->fs_ipg) / ((fs)->fs_inopb ))) << ((fs))->fs_fragshift))))) << (fs)->fs_fsbtodb ), |
920 | fs->fs_bsize, buf, fsopts); |
921 | initediblk += INOPB(fs)((fs)->fs_inopb); |
922 | cgp->cg_initediblk = initediblk; |
923 | } |
924 | |
925 | |
926 | ffs_wtfs(fsbtodb(fs, cgtod(fs, cg))((((((daddr_t)(fs)->fs_fpg * (cg)) + (fs)->fs_cgoffset * ((cg) & ~((fs)->fs_cgmask))) + (fs)->fs_cblkno)) << (fs)->fs_fsbtodb), (int)fs->fs_cgsize, &sbbuf, |
927 | fsopts); |
928 | |
929 | /* now write inode */ |
930 | d = fsbtodb(fs, ino_to_fsba(fs, ino))((((daddr_t)(((((daddr_t)(fs)->fs_fpg * (((ino) / (fs)-> fs_ipg))) + (fs)->fs_cgoffset * ((((ino) / (fs)->fs_ipg )) & ~((fs)->fs_cgmask))) + (fs)->fs_iblkno) + (((( ((ino) % (fs)->fs_ipg) / ((fs)->fs_inopb))) << (( fs))->fs_fragshift))))) << (fs)->fs_fsbtodb); |
931 | ffs_rdfs(d, fs->fs_bsize, buf, fsopts); |
932 | if (ffs_opts->version == 1) |
933 | dp1[ino_to_fsbo(fs, ino)((ino) % ((fs)->fs_inopb))] = dp->ffs1_din; |
934 | else |
935 | dp2[ino_to_fsbo(fs, ino)((ino) % ((fs)->fs_inopb))] = dp->ffs2_din; |
936 | ffs_wtfs(d, fs->fs_bsize, buf, fsopts); |
937 | free(buf); |
938 | } |