Bug Summary

File:src/usr.sbin/makefs/ffs.c
Warning:line 762, column 2
Value stored to 'chunk' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ffs.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/makefs/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/makefs -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/makefs/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/makefs/ffs.c
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
108typedef 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
115static int ffs_create_image(const char *, fsinfo_t *);
116static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *);
117static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
118static void ffs_size_dir(fsnode *, fsinfo_t *);
119static void ffs_validate(const char *, fsnode *, fsinfo_t *);
120static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *);
121static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *);
122static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *,
123 fsnode *, fsinfo_t *);
124static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
125 fsnode *, fsinfo_t *);
126
127
128
129 /* publicly visible functions */
130void
131ffs_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
168void
169ffs_cleanup_opts(fsinfo_t *fsopts)
170{
171 free(fsopts->fs_specific);
172 free(fsopts->fs_options);
173}
174
175int
176ffs_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
218void
219ffs_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
298static void
299ffs_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
410static int
411ffs_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
477static void
478ffs_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
533static void *
534ffs_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
575static void *
576ffs_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
617static int
618ffs_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
715static void
716ffs_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
812static void
813ffs_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 */
853static void
854ffs_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}