File: | src/usr.sbin/makefs/ffs.c |
Warning: | line 453, column 2 1st function call argument is an uninitialized value |
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
| |||
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
| |||
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; | |||
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 | } |