Wed Jan 23 21:42:23 2013 UTC ()
return the bit of the option set, so that others can act on it.


(christos)
diff -r1.51 -r1.52 src/usr.sbin/makefs/ffs.c
diff -r1.37 -r1.38 src/usr.sbin/makefs/makefs.c
diff -r1.2 -r1.3 src/usr.sbin/makefs/msdos.c

cvs diff -r1.51 -r1.52 src/usr.sbin/makefs/ffs.c (switch to unified diff)

--- src/usr.sbin/makefs/ffs.c 2013/01/23 21:32:32 1.51
+++ src/usr.sbin/makefs/ffs.c 2013/01/23 21:42:22 1.52
@@ -1,1155 +1,1158 @@ @@ -1,1155 +1,1158 @@
1/* $NetBSD: ffs.c,v 1.51 2013/01/23 21:32:32 christos Exp $ */ 1/* $NetBSD: ffs.c,v 1.52 2013/01/23 21:42:22 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Wasabi Systems, Inc. 4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Luke Mewburn for Wasabi Systems, Inc. 7 * Written by Luke Mewburn for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37/* 37/*
38 * Copyright (c) 1982, 1986, 1989, 1993 38 * Copyright (c) 1982, 1986, 1989, 1993
39 * The Regents of the University of California. All rights reserved. 39 * The Regents of the University of California. All rights reserved.
40 * 40 *
41 * Redistribution and use in source and binary forms, with or without 41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions 42 * modification, are permitted provided that the following conditions
43 * are met: 43 * are met:
44 * 1. Redistributions of source code must retain the above copyright 44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer. 45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright 46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the 47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution. 48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors 49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software 50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission. 51 * without specific prior written permission.
52 * 52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE. 63 * SUCH DAMAGE.
64 * 64 *
65 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95 65 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
66 */ 66 */
67 67
68#if HAVE_NBTOOL_CONFIG_H 68#if HAVE_NBTOOL_CONFIG_H
69#include "nbtool_config.h" 69#include "nbtool_config.h"
70#endif 70#endif
71 71
72#include <sys/cdefs.h> 72#include <sys/cdefs.h>
73#if defined(__RCSID) && !defined(__lint) 73#if defined(__RCSID) && !defined(__lint)
74__RCSID("$NetBSD: ffs.c,v 1.51 2013/01/23 21:32:32 christos Exp $"); 74__RCSID("$NetBSD: ffs.c,v 1.52 2013/01/23 21:42:22 christos Exp $");
75#endif /* !__lint */ 75#endif /* !__lint */
76 76
77#include <sys/param.h> 77#include <sys/param.h>
78 78
79#if !HAVE_NBTOOL_CONFIG_H 79#if !HAVE_NBTOOL_CONFIG_H
80#include <sys/mount.h> 80#include <sys/mount.h>
81#endif 81#endif
82 82
83#include <assert.h> 83#include <assert.h>
84#include <errno.h> 84#include <errno.h>
85#include <fcntl.h> 85#include <fcntl.h>
86#include <stdarg.h> 86#include <stdarg.h>
87#include <stdio.h> 87#include <stdio.h>
88#include <stdlib.h> 88#include <stdlib.h>
89#include <string.h> 89#include <string.h>
90#include <unistd.h> 90#include <unistd.h>
91 91
92#include "makefs.h" 92#include "makefs.h"
93#include "ffs.h" 93#include "ffs.h"
94 94
95#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 95#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
96#include <sys/statvfs.h> 96#include <sys/statvfs.h>
97#endif 97#endif
98 98
99#include <ufs/ufs/dinode.h> 99#include <ufs/ufs/dinode.h>
100#include <ufs/ufs/dir.h> 100#include <ufs/ufs/dir.h>
101#include <ufs/ffs/fs.h> 101#include <ufs/ffs/fs.h>
102#include <ufs/ufs/ufs_bswap.h> 102#include <ufs/ufs/ufs_bswap.h>
103 103
104#include "ffs/ufs_inode.h" 104#include "ffs/ufs_inode.h"
105#include "ffs/newfs_extern.h" 105#include "ffs/newfs_extern.h"
106#include "ffs/ffs_extern.h" 106#include "ffs/ffs_extern.h"
107 107
108#undef DIP 108#undef DIP
109#define DIP(dp, field) \ 109#define DIP(dp, field) \
110 ((ffs_opts->version == 1) ? \ 110 ((ffs_opts->version == 1) ? \
111 (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field) 111 (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field)
112 112
113/* 113/*
114 * Various file system defaults (cribbed from newfs(8)). 114 * Various file system defaults (cribbed from newfs(8)).
115 */ 115 */
116#define DFL_FRAGSIZE 1024 /* fragment size */ 116#define DFL_FRAGSIZE 1024 /* fragment size */
117#define DFL_BLKSIZE 8192 /* block size */ 117#define DFL_BLKSIZE 8192 /* block size */
118#define DFL_SECSIZE 512 /* sector size */ 118#define DFL_SECSIZE 512 /* sector size */
119#define DFL_CYLSPERGROUP 65536 /* cylinders per group */ 119#define DFL_CYLSPERGROUP 65536 /* cylinders per group */
120#define DFL_FRAGSPERINODE 4 /* fragments per inode */ 120#define DFL_FRAGSPERINODE 4 /* fragments per inode */
121#define DFL_ROTDELAY 0 /* rotational delay */ 121#define DFL_ROTDELAY 0 /* rotational delay */
122#define DFL_NRPOS 1 /* rotational positions */ 122#define DFL_NRPOS 1 /* rotational positions */
123#define DFL_RPM 3600 /* rpm of disk */ 123#define DFL_RPM 3600 /* rpm of disk */
124#define DFL_NSECTORS 64 /* # of sectors */ 124#define DFL_NSECTORS 64 /* # of sectors */
125#define DFL_NTRACKS 16 /* # of tracks */ 125#define DFL_NTRACKS 16 /* # of tracks */
126 126
127 127
128typedef struct { 128typedef struct {
129 u_char *buf; /* buf for directory */ 129 u_char *buf; /* buf for directory */
130 doff_t size; /* full size of buf */ 130 doff_t size; /* full size of buf */
131 doff_t cur; /* offset of current entry */ 131 doff_t cur; /* offset of current entry */
132} dirbuf_t; 132} dirbuf_t;
133 133
134 134
135static int ffs_create_image(const char *, fsinfo_t *); 135static int ffs_create_image(const char *, fsinfo_t *);
136static void ffs_dump_fsinfo(fsinfo_t *); 136static void ffs_dump_fsinfo(fsinfo_t *);
137static void ffs_dump_dirbuf(dirbuf_t *, const char *, int); 137static void ffs_dump_dirbuf(dirbuf_t *, const char *, int);
138static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int); 138static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int);
139static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *); 139static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
140static void ffs_size_dir(fsnode *, fsinfo_t *); 140static void ffs_size_dir(fsnode *, fsinfo_t *);
141static void ffs_validate(const char *, fsnode *, fsinfo_t *); 141static void ffs_validate(const char *, fsnode *, fsinfo_t *);
142static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *); 142static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *);
143static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *); 143static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *);
144static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *, 144static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *,
145 fsnode *, fsinfo_t *); 145 fsnode *, fsinfo_t *);
146static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *, 146static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
147 fsnode *, fsinfo_t *); 147 fsnode *, fsinfo_t *);
148 148
149 149
150 150
151int sectorsize; /* XXX: for buf.c::getblk() */ 151int sectorsize; /* XXX: for buf.c::getblk() */
152 152
153 /* publically visible functions */ 153 /* publically visible functions */
154 154
155void 155void
156ffs_prep_opts(fsinfo_t *fsopts) 156ffs_prep_opts(fsinfo_t *fsopts)
157{ 157{
158 ffs_opt_t *ffs_opts; 158 ffs_opt_t *ffs_opts;
159 159
160 if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL) 160 if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL)
161 err(1, "Allocating memory for ffs_options"); 161 err(1, "Allocating memory for ffs_options");
162 162
163 fsopts->fs_specific = ffs_opts; 163 fsopts->fs_specific = ffs_opts;
164 164
165 ffs_opts->bsize= -1; 165 ffs_opts->bsize= -1;
166 ffs_opts->fsize= -1; 166 ffs_opts->fsize= -1;
167 ffs_opts->cpg= -1; 167 ffs_opts->cpg= -1;
168 ffs_opts->density= -1; 168 ffs_opts->density= -1;
169 ffs_opts->minfree= -1; 169 ffs_opts->minfree= -1;
170 ffs_opts->optimization= -1; 170 ffs_opts->optimization= -1;
171 ffs_opts->maxcontig= -1; 171 ffs_opts->maxcontig= -1;
172 ffs_opts->maxbpg= -1; 172 ffs_opts->maxbpg= -1;
173 ffs_opts->avgfilesize= -1; 173 ffs_opts->avgfilesize= -1;
174 ffs_opts->avgfpdir= -1; 174 ffs_opts->avgfpdir= -1;
175 ffs_opts->version = 1; 175 ffs_opts->version = 1;
176} 176}
177 177
178void 178void
179ffs_cleanup_opts(fsinfo_t *fsopts) 179ffs_cleanup_opts(fsinfo_t *fsopts)
180{ 180{
181 if (fsopts->fs_specific) 181 if (fsopts->fs_specific)
182 free(fsopts->fs_specific); 182 free(fsopts->fs_specific);
183} 183}
184 184
185int 185int
186ffs_parse_opts(const char *option, fsinfo_t *fsopts) 186ffs_parse_opts(const char *option, fsinfo_t *fsopts)
187{ 187{
188 ffs_opt_t *ffs_opts = fsopts->fs_specific; 188 ffs_opt_t *ffs_opts = fsopts->fs_specific;
189 char optimization[24]; 189 char optimization[24];
190 190
191 option_t ffs_options[] = { 191 option_t ffs_options[] = {
192 { '\0', "bsize", &ffs_opts->bsize, OPT_INT32, 192 { '\0', "bsize", &ffs_opts->bsize, OPT_INT32,
193 1, INT_MAX, "block size" }, 193 1, INT_MAX, "block size" },
194 { '\0', "fsize", &ffs_opts->fsize, OPT_INT32, 194 { '\0', "fsize", &ffs_opts->fsize, OPT_INT32,
195 1, INT_MAX, "fragment size" }, 195 1, INT_MAX, "fragment size" },
196 { '\0', "density", &ffs_opts->density, OPT_INT32, 196 { '\0', "density", &ffs_opts->density, OPT_INT32,
197 1, INT_MAX, "bytes per inode" }, 197 1, INT_MAX, "bytes per inode" },
198 { '\0', "minfree", &ffs_opts->minfree, OPT_INT32, 198 { '\0', "minfree", &ffs_opts->minfree, OPT_INT32,
199 0, 99, "minfree" }, 199 0, 99, "minfree" },
200 { '\0', "maxbpf", &ffs_opts->maxbpg, OPT_INT32, 200 { '\0', "maxbpf", &ffs_opts->maxbpg, OPT_INT32,
201 1, INT_MAX, "max blocks per file in a cg" }, 201 1, INT_MAX, "max blocks per file in a cg" },
202 { '\0', "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32, 202 { '\0', "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32,
203 1, INT_MAX, "expected average file size" }, 203 1, INT_MAX, "expected average file size" },
204 { '\0', "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32, 204 { '\0', "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32,
205 1, INT_MAX, "expected # of files per directory" }, 205 1, INT_MAX, "expected # of files per directory" },
206 { '\0', "extent", &ffs_opts->maxbsize, OPT_INT32, 206 { '\0', "extent", &ffs_opts->maxbsize, OPT_INT32,
207 1, INT_MAX, "maximum # extent size" }, 207 1, INT_MAX, "maximum # extent size" },
208 { '\0', "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32, 208 { '\0', "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32,
209 1, INT_MAX, "max # of blocks per group" }, 209 1, INT_MAX, "max # of blocks per group" },
210 { '\0', "version", &ffs_opts->version, OPT_INT32, 210 { '\0', "version", &ffs_opts->version, OPT_INT32,
211 1, 2, "UFS version" }, 211 1, 2, "UFS version" },
212 { '\0', "optimization", optimization, OPT_STRARRAY, 212 { '\0', "optimization", optimization, OPT_STRARRAY,
213 1, sizeof(optimization), "Optimization (time|space)" }, 213 1, sizeof(optimization), "Optimization (time|space)" },
214 { '\0', "label", ffs_opts->label, OPT_STRARRAY, 214 { '\0', "label", ffs_opts->label, OPT_STRARRAY,
215 1, sizeof(ffs_opts->label), "UFS label" }, 215 1, sizeof(ffs_opts->label), "UFS label" },
216 { .name = NULL } 216 { .name = NULL }
217 }; 217 };
218 218
219 int rv, i; 219 int rv, i;
220 220
221 assert(option != NULL); 221 assert(option != NULL);
222 assert(fsopts != NULL); 222 assert(fsopts != NULL);
223 assert(ffs_opts != NULL); 223 assert(ffs_opts != NULL);
224 224
225 if (debug & DEBUG_FS_PARSE_OPTS) 225 if (debug & DEBUG_FS_PARSE_OPTS)
226 printf("ffs_parse_opts: got `%s'\n", option); 226 printf("ffs_parse_opts: got `%s'\n", option);
227 227
228 rv = set_option(ffs_options, option); 228 rv = set_option(ffs_options, option);
229 if (rv == 0) 229 if (rv == 0)
230 return 0; 230 return 0;
231 231
232 for (i = 0; ffs_options[i].name && (1 << i) != rv; i++) 232 for (i = 0; ffs_options[i].name && (1 << i) != rv; i++)
233 continue; 233 continue;
234 234
 235 if (ffs_options[i].name == NULL)
 236 abort();
 237
235 if (strcmp(ffs_options[i].name, "optimization") == 0) { 238 if (strcmp(ffs_options[i].name, "optimization") == 0) {
236 if (strcmp(optimization, "time") == 0) { 239 if (strcmp(optimization, "time") == 0) {
237 ffs_opts->optimization = FS_OPTTIME; 240 ffs_opts->optimization = FS_OPTTIME;
238 } else if (strcmp(optimization, "space") == 0) { 241 } else if (strcmp(optimization, "space") == 0) {
239 ffs_opts->optimization = FS_OPTSPACE; 242 ffs_opts->optimization = FS_OPTSPACE;
240 } else { 243 } else {
241 warnx("Invalid optimization `%s'", optimization); 244 warnx("Invalid optimization `%s'", optimization);
242 return 0; 245 return 0;
243 } 246 }
244 } 247 }
245 return rv; 248 return rv;
246} 249}
247 250
248 251
249void 252void
250ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) 253ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
251{ 254{
252 struct fs *superblock; 255 struct fs *superblock;
253 struct timeval start; 256 struct timeval start;
254 257
255 assert(image != NULL); 258 assert(image != NULL);
256 assert(dir != NULL); 259 assert(dir != NULL);
257 assert(root != NULL); 260 assert(root != NULL);
258 assert(fsopts != NULL); 261 assert(fsopts != NULL);
259 262
260 if (debug & DEBUG_FS_MAKEFS) 263 if (debug & DEBUG_FS_MAKEFS)
261 printf("ffs_makefs: image %s directory %s root %p\n", 264 printf("ffs_makefs: image %s directory %s root %p\n",
262 image, dir, root); 265 image, dir, root);
263 266
264 /* validate tree and options */ 267 /* validate tree and options */
265 TIMER_START(start); 268 TIMER_START(start);
266 ffs_validate(dir, root, fsopts); 269 ffs_validate(dir, root, fsopts);
267 TIMER_RESULTS(start, "ffs_validate"); 270 TIMER_RESULTS(start, "ffs_validate");
268 271
269 printf("Calculated size of `%s': %lld bytes, %lld inodes\n", 272 printf("Calculated size of `%s': %lld bytes, %lld inodes\n",
270 image, (long long)fsopts->size, (long long)fsopts->inodes); 273 image, (long long)fsopts->size, (long long)fsopts->inodes);
271 274
272 /* create image */ 275 /* create image */
273 TIMER_START(start); 276 TIMER_START(start);
274 if (ffs_create_image(image, fsopts) == -1) 277 if (ffs_create_image(image, fsopts) == -1)
275 errx(1, "Image file `%s' not created.", image); 278 errx(1, "Image file `%s' not created.", image);
276 TIMER_RESULTS(start, "ffs_create_image"); 279 TIMER_RESULTS(start, "ffs_create_image");
277 280
278 fsopts->curinode = UFS_ROOTINO; 281 fsopts->curinode = UFS_ROOTINO;
279 282
280 if (debug & DEBUG_FS_MAKEFS) 283 if (debug & DEBUG_FS_MAKEFS)
281 putchar('\n'); 284 putchar('\n');
282 285
283 /* populate image */ 286 /* populate image */
284 printf("Populating `%s'\n", image); 287 printf("Populating `%s'\n", image);
285 TIMER_START(start); 288 TIMER_START(start);
286 if (! ffs_populate_dir(dir, root, fsopts)) 289 if (! ffs_populate_dir(dir, root, fsopts))
287 errx(1, "Image file `%s' not populated.", image); 290 errx(1, "Image file `%s' not populated.", image);
288 TIMER_RESULTS(start, "ffs_populate_dir"); 291 TIMER_RESULTS(start, "ffs_populate_dir");
289 292
290 /* ensure no outstanding buffers remain */ 293 /* ensure no outstanding buffers remain */
291 if (debug & DEBUG_FS_MAKEFS) 294 if (debug & DEBUG_FS_MAKEFS)
292 bcleanup(); 295 bcleanup();
293 296
294 /* update various superblock parameters */ 297 /* update various superblock parameters */
295 superblock = fsopts->superblock; 298 superblock = fsopts->superblock;
296 superblock->fs_fmod = 0; 299 superblock->fs_fmod = 0;
297 superblock->fs_old_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir; 300 superblock->fs_old_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir;
298 superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree; 301 superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree;
299 superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree; 302 superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree;
300 superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree; 303 superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree;
301 304
302 /* write out superblock; image is now complete */ 305 /* write out superblock; image is now complete */
303 ffs_write_superblock(fsopts->superblock, fsopts); 306 ffs_write_superblock(fsopts->superblock, fsopts);
304 if (close(fsopts->fd) == -1) 307 if (close(fsopts->fd) == -1)
305 err(1, "Closing `%s'", image); 308 err(1, "Closing `%s'", image);
306 fsopts->fd = -1; 309 fsopts->fd = -1;
307 printf("Image `%s' complete\n", image); 310 printf("Image `%s' complete\n", image);
308} 311}
309 312
310 /* end of public functions */ 313 /* end of public functions */
311 314
312 315
313static void 316static void
314ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts) 317ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
315{ 318{
316 int32_t ncg = 1; 319 int32_t ncg = 1;
317#if notyet 320#if notyet
318 int32_t spc, nspf, ncyl, fssize; 321 int32_t spc, nspf, ncyl, fssize;
319#endif 322#endif
320 ffs_opt_t *ffs_opts = fsopts->fs_specific; 323 ffs_opt_t *ffs_opts = fsopts->fs_specific;
321 324
322 assert(dir != NULL); 325 assert(dir != NULL);
323 assert(root != NULL); 326 assert(root != NULL);
324 assert(fsopts != NULL); 327 assert(fsopts != NULL);
325 assert(ffs_opts != NULL); 328 assert(ffs_opts != NULL);
326 329
327 if (debug & DEBUG_FS_VALIDATE) { 330 if (debug & DEBUG_FS_VALIDATE) {
328 printf("ffs_validate: before defaults set:\n"); 331 printf("ffs_validate: before defaults set:\n");
329 ffs_dump_fsinfo(fsopts); 332 ffs_dump_fsinfo(fsopts);
330 } 333 }
331 334
332 /* set FFS defaults */ 335 /* set FFS defaults */
333 if (fsopts->sectorsize == -1) 336 if (fsopts->sectorsize == -1)
334 fsopts->sectorsize = DFL_SECSIZE; 337 fsopts->sectorsize = DFL_SECSIZE;
335 if (ffs_opts->fsize == -1) 338 if (ffs_opts->fsize == -1)
336 ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize); 339 ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
337 if (ffs_opts->bsize == -1) 340 if (ffs_opts->bsize == -1)
338 ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize); 341 ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize);
339 if (ffs_opts->cpg == -1) 342 if (ffs_opts->cpg == -1)
340 ffs_opts->cpg = DFL_CYLSPERGROUP; 343 ffs_opts->cpg = DFL_CYLSPERGROUP;
341 else 344 else
342 ffs_opts->cpgflg = 1; 345 ffs_opts->cpgflg = 1;
343 /* fsopts->density is set below */ 346 /* fsopts->density is set below */
344 if (ffs_opts->nsectors == -1) 347 if (ffs_opts->nsectors == -1)
345 ffs_opts->nsectors = DFL_NSECTORS; 348 ffs_opts->nsectors = DFL_NSECTORS;
346 if (ffs_opts->minfree == -1) 349 if (ffs_opts->minfree == -1)
347 ffs_opts->minfree = MINFREE; 350 ffs_opts->minfree = MINFREE;
348 if (ffs_opts->optimization == -1) 351 if (ffs_opts->optimization == -1)
349 ffs_opts->optimization = DEFAULTOPT; 352 ffs_opts->optimization = DEFAULTOPT;
350 if (ffs_opts->maxcontig == -1) 353 if (ffs_opts->maxcontig == -1)
351 ffs_opts->maxcontig = 354 ffs_opts->maxcontig =
352 MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize); 355 MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize);
353 /* XXX ondisk32 */ 356 /* XXX ondisk32 */
354 if (ffs_opts->maxbpg == -1) 357 if (ffs_opts->maxbpg == -1)
355 ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t); 358 ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t);
356 if (ffs_opts->avgfilesize == -1) 359 if (ffs_opts->avgfilesize == -1)
357 ffs_opts->avgfilesize = AVFILESIZ; 360 ffs_opts->avgfilesize = AVFILESIZ;
358 if (ffs_opts->avgfpdir == -1) 361 if (ffs_opts->avgfpdir == -1)
359 ffs_opts->avgfpdir = AFPDIR; 362 ffs_opts->avgfpdir = AFPDIR;
360 363
361 /* calculate size of tree */ 364 /* calculate size of tree */
362 ffs_size_dir(root, fsopts); 365 ffs_size_dir(root, fsopts);
363 fsopts->inodes += UFS_ROOTINO; /* include first two inodes */ 366 fsopts->inodes += UFS_ROOTINO; /* include first two inodes */
364 367
365 if (debug & DEBUG_FS_VALIDATE) 368 if (debug & DEBUG_FS_VALIDATE)
366 printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n", 369 printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n",
367 (long long)fsopts->size, (long long)fsopts->inodes); 370 (long long)fsopts->size, (long long)fsopts->inodes);
368 371
369 /* add requested slop */ 372 /* add requested slop */
370 fsopts->size += fsopts->freeblocks; 373 fsopts->size += fsopts->freeblocks;
371 fsopts->inodes += fsopts->freefiles; 374 fsopts->inodes += fsopts->freefiles;
372 if (fsopts->freefilepc > 0) 375 if (fsopts->freefilepc > 0)
373 fsopts->inodes = 376 fsopts->inodes =
374 fsopts->inodes * (100 + fsopts->freefilepc) / 100; 377 fsopts->inodes * (100 + fsopts->freefilepc) / 100;
375 if (fsopts->freeblockpc > 0) 378 if (fsopts->freeblockpc > 0)
376 fsopts->size = 379 fsopts->size =
377 fsopts->size * (100 + fsopts->freeblockpc) / 100; 380 fsopts->size * (100 + fsopts->freeblockpc) / 100;
378 381
379 /* add space needed for superblocks */ 382 /* add space needed for superblocks */
380 /* 383 /*
381 * The old SBOFF (SBLOCK_UFS1) is used here because makefs is 384 * The old SBOFF (SBLOCK_UFS1) is used here because makefs is
382 * typically used for small filesystems where space matters. 385 * typically used for small filesystems where space matters.
383 * XXX make this an option. 386 * XXX make this an option.
384 */ 387 */
385 fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg; 388 fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
386 /* add space needed to store inodes, x3 for blockmaps, etc */ 389 /* add space needed to store inodes, x3 for blockmaps, etc */
387 if (ffs_opts->version == 1) 390 if (ffs_opts->version == 1)
388 fsopts->size += ncg * DINODE1_SIZE * 391 fsopts->size += ncg * DINODE1_SIZE *
389 roundup(fsopts->inodes / ncg,  392 roundup(fsopts->inodes / ncg,
390 ffs_opts->bsize / DINODE1_SIZE); 393 ffs_opts->bsize / DINODE1_SIZE);
391 else 394 else
392 fsopts->size += ncg * DINODE2_SIZE * 395 fsopts->size += ncg * DINODE2_SIZE *
393 roundup(fsopts->inodes / ncg,  396 roundup(fsopts->inodes / ncg,
394 ffs_opts->bsize / DINODE2_SIZE); 397 ffs_opts->bsize / DINODE2_SIZE);
395 398
396 /* add minfree */ 399 /* add minfree */
397 if (ffs_opts->minfree > 0) 400 if (ffs_opts->minfree > 0)
398 fsopts->size = 401 fsopts->size =
399 fsopts->size * (100 + ffs_opts->minfree) / 100; 402 fsopts->size * (100 + ffs_opts->minfree) / 100;
400 /* 403 /*
401 * XXX any other fs slop to add, such as csum's, bitmaps, etc ?? 404 * XXX any other fs slop to add, such as csum's, bitmaps, etc ??
402 */ 405 */
403 406
404 if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */ 407 if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */
405 fsopts->size = fsopts->minsize; 408 fsopts->size = fsopts->minsize;
406 409
407 /* round up to the next block */ 410 /* round up to the next block */
408 fsopts->size = roundup(fsopts->size, ffs_opts->bsize); 411 fsopts->size = roundup(fsopts->size, ffs_opts->bsize);
409 412
410 /* calculate density if necessary */ 413 /* calculate density if necessary */
411 if (ffs_opts->density == -1) 414 if (ffs_opts->density == -1)
412 ffs_opts->density = fsopts->size / fsopts->inodes + 1; 415 ffs_opts->density = fsopts->size / fsopts->inodes + 1;
413 416
414 if (debug & DEBUG_FS_VALIDATE) { 417 if (debug & DEBUG_FS_VALIDATE) {
415 printf("ffs_validate: after defaults set:\n"); 418 printf("ffs_validate: after defaults set:\n");
416 ffs_dump_fsinfo(fsopts); 419 ffs_dump_fsinfo(fsopts);
417 printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n", 420 printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n",
418 dir, (long long)fsopts->size, (long long)fsopts->inodes); 421 dir, (long long)fsopts->size, (long long)fsopts->inodes);
419 } 422 }
420 sectorsize = fsopts->sectorsize; /* XXX - see earlier */ 423 sectorsize = fsopts->sectorsize; /* XXX - see earlier */
421 424
422 /* now check calculated sizes vs requested sizes */ 425 /* now check calculated sizes vs requested sizes */
423 if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) { 426 if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) {
424 errx(1, "`%s' size of %lld is larger than the maxsize of %lld.", 427 errx(1, "`%s' size of %lld is larger than the maxsize of %lld.",
425 dir, (long long)fsopts->size, (long long)fsopts->maxsize); 428 dir, (long long)fsopts->size, (long long)fsopts->maxsize);
426 } 429 }
427} 430}
428 431
429 432
430static void 433static void
431ffs_dump_fsinfo(fsinfo_t *f) 434ffs_dump_fsinfo(fsinfo_t *f)
432{ 435{
433 436
434 ffs_opt_t *fs = f->fs_specific; 437 ffs_opt_t *fs = f->fs_specific;
435 438
436 printf("fsopts at %p\n", f); 439 printf("fsopts at %p\n", f);
437 440
438 printf("\tsize %lld, inodes %lld, curinode %u\n", 441 printf("\tsize %lld, inodes %lld, curinode %u\n",
439 (long long)f->size, (long long)f->inodes, f->curinode); 442 (long long)f->size, (long long)f->inodes, f->curinode);
440 443
441 printf("\tminsize %lld, maxsize %lld\n", 444 printf("\tminsize %lld, maxsize %lld\n",
442 (long long)f->minsize, (long long)f->maxsize); 445 (long long)f->minsize, (long long)f->maxsize);
443 printf("\tfree files %lld, freefile %% %d\n", 446 printf("\tfree files %lld, freefile %% %d\n",
444 (long long)f->freefiles, f->freefilepc); 447 (long long)f->freefiles, f->freefilepc);
445 printf("\tfree blocks %lld, freeblock %% %d\n", 448 printf("\tfree blocks %lld, freeblock %% %d\n",
446 (long long)f->freeblocks, f->freeblockpc); 449 (long long)f->freeblocks, f->freeblockpc);
447 printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize); 450 printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize);
448 451
449 printf("\tbsize %d, fsize %d, cpg %d, density %d\n", 452 printf("\tbsize %d, fsize %d, cpg %d, density %d\n",
450 fs->bsize, fs->fsize, fs->cpg, fs->density); 453 fs->bsize, fs->fsize, fs->cpg, fs->density);
451 printf("\tnsectors %d, rpm %d, minfree %d\n", 454 printf("\tnsectors %d, rpm %d, minfree %d\n",
452 fs->nsectors, fs->rpm, fs->minfree); 455 fs->nsectors, fs->rpm, fs->minfree);
453 printf("\tmaxcontig %d, maxbpg %d\n", 456 printf("\tmaxcontig %d, maxbpg %d\n",
454 fs->maxcontig, fs->maxbpg); 457 fs->maxcontig, fs->maxbpg);
455 printf("\toptimization %s\n", 458 printf("\toptimization %s\n",
456 fs->optimization == FS_OPTSPACE ? "space" : "time"); 459 fs->optimization == FS_OPTSPACE ? "space" : "time");
457} 460}
458 461
459 462
460static int 463static int
461ffs_create_image(const char *image, fsinfo_t *fsopts) 464ffs_create_image(const char *image, fsinfo_t *fsopts)
462{ 465{
463#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 466#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
464 struct statvfs sfs; 467 struct statvfs sfs;
465#endif 468#endif
466 struct fs *fs; 469 struct fs *fs;
467 char *buf; 470 char *buf;
468 int i, bufsize; 471 int i, bufsize;
469 off_t bufrem; 472 off_t bufrem;
470 473
471 assert (image != NULL); 474 assert (image != NULL);
472 assert (fsopts != NULL); 475 assert (fsopts != NULL);
473 476
474 /* create image */ 477 /* create image */
475 if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666)) 478 if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666))
476 == -1) { 479 == -1) {
477 warn("Can't open `%s' for writing", image); 480 warn("Can't open `%s' for writing", image);
478 return (-1); 481 return (-1);
479 } 482 }
480 483
481 /* zero image */ 484 /* zero image */
482#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 485#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
483 if (fstatvfs(fsopts->fd, &sfs) == -1) { 486 if (fstatvfs(fsopts->fd, &sfs) == -1) {
484#endif 487#endif
485 bufsize = 8192; 488 bufsize = 8192;
486#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 489#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
487 warn("can't fstatvfs `%s', using default %d byte chunk", 490 warn("can't fstatvfs `%s', using default %d byte chunk",
488 image, bufsize); 491 image, bufsize);
489 } else 492 } else
490 bufsize = sfs.f_iosize; 493 bufsize = sfs.f_iosize;
491#endif 494#endif
492 bufrem = fsopts->size; 495 bufrem = fsopts->size;
493 496
494 if (fsopts->sparse) { 497 if (fsopts->sparse) {
495 if (ftruncate(fsopts->fd, bufrem) == -1) { 498 if (ftruncate(fsopts->fd, bufrem) == -1) {
496 printf ("ERROR in truncate. Sparse option disabled\n"); 499 printf ("ERROR in truncate. Sparse option disabled\n");
497 fsopts->sparse = 0; 500 fsopts->sparse = 0;
498 } else { 501 } else {
499 bufrem = 0; /* File truncated at bufrem. Remaining is 0 */ 502 bufrem = 0; /* File truncated at bufrem. Remaining is 0 */
500 buf = NULL; 503 buf = NULL;
501 } 504 }
502 } 505 }
503 506
504 if ((debug & DEBUG_FS_CREATE_IMAGE) && fsopts->sparse == 0) 507 if ((debug & DEBUG_FS_CREATE_IMAGE) && fsopts->sparse == 0)
505 printf( 508 printf(
506 "zero-ing image `%s', %lld sectors, using %d byte chunks\n", 509 "zero-ing image `%s', %lld sectors, using %d byte chunks\n",
507 image, (long long)bufrem, bufsize); 510 image, (long long)bufrem, bufsize);
508 if ((bufrem > 0) && ((buf = calloc(1, bufsize)) == NULL)) { 511 if ((bufrem > 0) && ((buf = calloc(1, bufsize)) == NULL)) {
509 warn("Can't create buffer for sector"); 512 warn("Can't create buffer for sector");
510 return (-1); 513 return (-1);
511 } 514 }
512 while (bufrem > 0) { 515 while (bufrem > 0) {
513 i = write(fsopts->fd, buf, MIN(bufsize, bufrem)); 516 i = write(fsopts->fd, buf, MIN(bufsize, bufrem));
514 if (i == -1) { 517 if (i == -1) {
515 warn("zeroing image, %lld bytes to go", 518 warn("zeroing image, %lld bytes to go",
516 (long long)bufrem); 519 (long long)bufrem);
517 free(buf); 520 free(buf);
518 return (-1); 521 return (-1);
519 } 522 }
520 bufrem -= i; 523 bufrem -= i;
521 } 524 }
522 if (buf) 525 if (buf)
523 free(buf); 526 free(buf);
524 527
525 /* make the file system */ 528 /* make the file system */
526 if (debug & DEBUG_FS_CREATE_IMAGE) 529 if (debug & DEBUG_FS_CREATE_IMAGE)
527 printf("calling mkfs(\"%s\", ...)\n", image); 530 printf("calling mkfs(\"%s\", ...)\n", image);
528 fs = ffs_mkfs(image, fsopts); 531 fs = ffs_mkfs(image, fsopts);
529 fsopts->superblock = (void *)fs; 532 fsopts->superblock = (void *)fs;
530 if (debug & DEBUG_FS_CREATE_IMAGE) { 533 if (debug & DEBUG_FS_CREATE_IMAGE) {
531 time_t t; 534 time_t t;
532 535
533 t = (time_t)((struct fs *)fsopts->superblock)->fs_time; 536 t = (time_t)((struct fs *)fsopts->superblock)->fs_time;
534 printf("mkfs returned %p; fs_time %s", 537 printf("mkfs returned %p; fs_time %s",
535 fsopts->superblock, ctime(&t)); 538 fsopts->superblock, ctime(&t));
536 printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n", 539 printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n",
537 (long long)fs->fs_cstotal.cs_nbfree, 540 (long long)fs->fs_cstotal.cs_nbfree,
538 (long long)fs->fs_cstotal.cs_nffree, 541 (long long)fs->fs_cstotal.cs_nffree,
539 (long long)fs->fs_cstotal.cs_nifree, 542 (long long)fs->fs_cstotal.cs_nifree,
540 (long long)fs->fs_cstotal.cs_ndir); 543 (long long)fs->fs_cstotal.cs_ndir);
541 } 544 }
542 545
543 if ((off_t)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO) < fsopts->inodes) { 546 if ((off_t)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO) < fsopts->inodes) {
544 warnx( 547 warnx(
545 "Image file `%s' has %lld free inodes; %lld are required.", 548 "Image file `%s' has %lld free inodes; %lld are required.",
546 image, 549 image,
547 (long long)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO), 550 (long long)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO),
548 (long long)fsopts->inodes); 551 (long long)fsopts->inodes);
549 return (-1); 552 return (-1);
550 } 553 }
551 return (fsopts->fd); 554 return (fsopts->fd);
552} 555}
553 556
554 557
555static void 558static void
556ffs_size_dir(fsnode *root, fsinfo_t *fsopts) 559ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
557{ 560{
558 struct direct tmpdir; 561 struct direct tmpdir;
559 fsnode * node; 562 fsnode * node;
560 int curdirsize, this; 563 int curdirsize, this;
561 ffs_opt_t *ffs_opts = fsopts->fs_specific; 564 ffs_opt_t *ffs_opts = fsopts->fs_specific;
562 565
563 /* node may be NULL (empty directory) */ 566 /* node may be NULL (empty directory) */
564 assert(fsopts != NULL); 567 assert(fsopts != NULL);
565 assert(ffs_opts != NULL); 568 assert(ffs_opts != NULL);
566 569
567 if (debug & DEBUG_FS_SIZE_DIR) 570 if (debug & DEBUG_FS_SIZE_DIR)
568 printf("ffs_size_dir: entry: bytes %lld inodes %lld\n", 571 printf("ffs_size_dir: entry: bytes %lld inodes %lld\n",
569 (long long)fsopts->size, (long long)fsopts->inodes); 572 (long long)fsopts->size, (long long)fsopts->inodes);
570 573
571#define ADDDIRENT(e) do { \ 574#define ADDDIRENT(e) do { \
572 tmpdir.d_namlen = strlen((e)); \ 575 tmpdir.d_namlen = strlen((e)); \
573 this = DIRSIZ(0, &tmpdir, 0); \ 576 this = DIRSIZ(0, &tmpdir, 0); \
574 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \ 577 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
575 printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \ 578 printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \
576 e, tmpdir.d_namlen, this, curdirsize); \ 579 e, tmpdir.d_namlen, this, curdirsize); \
577 if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ)) \ 580 if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ)) \
578 curdirsize = roundup(curdirsize, DIRBLKSIZ); \ 581 curdirsize = roundup(curdirsize, DIRBLKSIZ); \
579 curdirsize += this; \ 582 curdirsize += this; \
580 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \ 583 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
581 printf("ADDDIRENT: now: %s (%d) this %d cur %d\n", \ 584 printf("ADDDIRENT: now: %s (%d) this %d cur %d\n", \
582 e, tmpdir.d_namlen, this, curdirsize); \ 585 e, tmpdir.d_namlen, this, curdirsize); \
583} while (0); 586} while (0);
584 587
585 /* 588 /*
586 * XXX this needs to take into account extra space consumed 589 * XXX this needs to take into account extra space consumed
587 * by indirect blocks, etc. 590 * by indirect blocks, etc.
588 */ 591 */
589#define ADDSIZE(x) do { \ 592#define ADDSIZE(x) do { \
590 fsopts->size += roundup((x), ffs_opts->fsize); \ 593 fsopts->size += roundup((x), ffs_opts->fsize); \
591} while (0); 594} while (0);
592 595
593 curdirsize = 0; 596 curdirsize = 0;
594 for (node = root; node != NULL; node = node->next) { 597 for (node = root; node != NULL; node = node->next) {
595 ADDDIRENT(node->name); 598 ADDDIRENT(node->name);
596 if (node == root) { /* we're at "." */ 599 if (node == root) { /* we're at "." */
597 assert(strcmp(node->name, ".") == 0); 600 assert(strcmp(node->name, ".") == 0);
598 ADDDIRENT(".."); 601 ADDDIRENT("..");
599 } else if ((node->inode->flags & FI_SIZED) == 0) { 602 } else if ((node->inode->flags & FI_SIZED) == 0) {
600 /* don't count duplicate names */ 603 /* don't count duplicate names */
601 node->inode->flags |= FI_SIZED; 604 node->inode->flags |= FI_SIZED;
602 if (debug & DEBUG_FS_SIZE_DIR_NODE) 605 if (debug & DEBUG_FS_SIZE_DIR_NODE)
603 printf("ffs_size_dir: `%s' size %lld\n", 606 printf("ffs_size_dir: `%s' size %lld\n",
604 node->name, 607 node->name,
605 (long long)node->inode->st.st_size); 608 (long long)node->inode->st.st_size);
606 fsopts->inodes++; 609 fsopts->inodes++;
607 if (node->type == S_IFREG) 610 if (node->type == S_IFREG)
608 ADDSIZE(node->inode->st.st_size); 611 ADDSIZE(node->inode->st.st_size);
609 if (node->type == S_IFLNK) { 612 if (node->type == S_IFLNK) {
610 size_t slen; 613 size_t slen;
611 614
612 slen = strlen(node->symlink) + 1; 615 slen = strlen(node->symlink) + 1;
613 if (slen >= (ffs_opts->version == 1 ? 616 if (slen >= (ffs_opts->version == 1 ?
614 UFS1_MAXSYMLINKLEN : 617 UFS1_MAXSYMLINKLEN :
615 UFS2_MAXSYMLINKLEN)) 618 UFS2_MAXSYMLINKLEN))
616 ADDSIZE(slen); 619 ADDSIZE(slen);
617 } 620 }
618 } 621 }
619 if (node->type == S_IFDIR) 622 if (node->type == S_IFDIR)
620 ffs_size_dir(node->child, fsopts); 623 ffs_size_dir(node->child, fsopts);
621 } 624 }
622 ADDSIZE(curdirsize); 625 ADDSIZE(curdirsize);
623 626
624 if (debug & DEBUG_FS_SIZE_DIR) 627 if (debug & DEBUG_FS_SIZE_DIR)
625 printf("ffs_size_dir: exit: size %lld inodes %lld\n", 628 printf("ffs_size_dir: exit: size %lld inodes %lld\n",
626 (long long)fsopts->size, (long long)fsopts->inodes); 629 (long long)fsopts->size, (long long)fsopts->inodes);
627} 630}
628 631
629static void * 632static void *
630ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, 633ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
631 fsnode *root, fsinfo_t *fsopts) 634 fsnode *root, fsinfo_t *fsopts)
632{ 635{
633 size_t slen; 636 size_t slen;
634 void *membuf; 637 void *membuf;
635 638
636 memset(dinp, 0, sizeof(*dinp)); 639 memset(dinp, 0, sizeof(*dinp));
637 dinp->di_mode = cur->inode->st.st_mode; 640 dinp->di_mode = cur->inode->st.st_mode;
638 dinp->di_nlink = cur->inode->nlink; 641 dinp->di_nlink = cur->inode->nlink;
639 dinp->di_size = cur->inode->st.st_size; 642 dinp->di_size = cur->inode->st.st_size;
640 dinp->di_atime = cur->inode->st.st_atime; 643 dinp->di_atime = cur->inode->st.st_atime;
641 dinp->di_mtime = cur->inode->st.st_mtime; 644 dinp->di_mtime = cur->inode->st.st_mtime;
642 dinp->di_ctime = cur->inode->st.st_ctime; 645 dinp->di_ctime = cur->inode->st.st_ctime;
643#if HAVE_STRUCT_STAT_ST_MTIMENSEC 646#if HAVE_STRUCT_STAT_ST_MTIMENSEC
644 dinp->di_atimensec = cur->inode->st.st_atimensec; 647 dinp->di_atimensec = cur->inode->st.st_atimensec;
645 dinp->di_mtimensec = cur->inode->st.st_mtimensec; 648 dinp->di_mtimensec = cur->inode->st.st_mtimensec;
646 dinp->di_ctimensec = cur->inode->st.st_ctimensec; 649 dinp->di_ctimensec = cur->inode->st.st_ctimensec;
647#endif 650#endif
648#if HAVE_STRUCT_STAT_ST_FLAGS 651#if HAVE_STRUCT_STAT_ST_FLAGS
649 dinp->di_flags = cur->inode->st.st_flags; 652 dinp->di_flags = cur->inode->st.st_flags;
650#endif 653#endif
651#if HAVE_STRUCT_STAT_ST_GEN 654#if HAVE_STRUCT_STAT_ST_GEN
652 dinp->di_gen = cur->inode->st.st_gen; 655 dinp->di_gen = cur->inode->st.st_gen;
653#endif 656#endif
654 dinp->di_uid = cur->inode->st.st_uid; 657 dinp->di_uid = cur->inode->st.st_uid;
655 dinp->di_gid = cur->inode->st.st_gid; 658 dinp->di_gid = cur->inode->st.st_gid;
656 /* not set: di_db, di_ib, di_blocks, di_spare */ 659 /* not set: di_db, di_ib, di_blocks, di_spare */
657 660
658 membuf = NULL; 661 membuf = NULL;
659 if (cur == root) { /* "."; write dirbuf */ 662 if (cur == root) { /* "."; write dirbuf */
660 membuf = dbufp->buf; 663 membuf = dbufp->buf;
661 dinp->di_size = dbufp->size; 664 dinp->di_size = dbufp->size;
662 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) { 665 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
663 dinp->di_size = 0; /* a device */ 666 dinp->di_size = 0; /* a device */
664 dinp->di_rdev = 667 dinp->di_rdev =
665 ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap); 668 ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
666 } else if (S_ISLNK(cur->type)) { /* symlink */ 669 } else if (S_ISLNK(cur->type)) { /* symlink */
667 slen = strlen(cur->symlink); 670 slen = strlen(cur->symlink);
668 if (slen < UFS1_MAXSYMLINKLEN) { /* short link */ 671 if (slen < UFS1_MAXSYMLINKLEN) { /* short link */
669 memcpy(dinp->di_db, cur->symlink, slen); 672 memcpy(dinp->di_db, cur->symlink, slen);
670 } else 673 } else
671 membuf = cur->symlink; 674 membuf = cur->symlink;
672 dinp->di_size = slen; 675 dinp->di_size = slen;
673 } 676 }
674 return membuf; 677 return membuf;
675} 678}
676 679
677static void * 680static void *
678ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, 681ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
679 fsnode *root, fsinfo_t *fsopts) 682 fsnode *root, fsinfo_t *fsopts)
680{ 683{
681 size_t slen; 684 size_t slen;
682 void *membuf; 685 void *membuf;
683 686
684 memset(dinp, 0, sizeof(*dinp)); 687 memset(dinp, 0, sizeof(*dinp));
685 dinp->di_mode = cur->inode->st.st_mode; 688 dinp->di_mode = cur->inode->st.st_mode;
686 dinp->di_nlink = cur->inode->nlink; 689 dinp->di_nlink = cur->inode->nlink;
687 dinp->di_size = cur->inode->st.st_size; 690 dinp->di_size = cur->inode->st.st_size;
688 dinp->di_atime = cur->inode->st.st_atime; 691 dinp->di_atime = cur->inode->st.st_atime;
689 dinp->di_mtime = cur->inode->st.st_mtime; 692 dinp->di_mtime = cur->inode->st.st_mtime;
690 dinp->di_ctime = cur->inode->st.st_ctime; 693 dinp->di_ctime = cur->inode->st.st_ctime;
691#if HAVE_STRUCT_STAT_ST_MTIMENSEC 694#if HAVE_STRUCT_STAT_ST_MTIMENSEC
692 dinp->di_atimensec = cur->inode->st.st_atimensec; 695 dinp->di_atimensec = cur->inode->st.st_atimensec;
693 dinp->di_mtimensec = cur->inode->st.st_mtimensec; 696 dinp->di_mtimensec = cur->inode->st.st_mtimensec;
694 dinp->di_ctimensec = cur->inode->st.st_ctimensec; 697 dinp->di_ctimensec = cur->inode->st.st_ctimensec;
695#endif 698#endif
696#if HAVE_STRUCT_STAT_ST_FLAGS 699#if HAVE_STRUCT_STAT_ST_FLAGS
697 dinp->di_flags = cur->inode->st.st_flags; 700 dinp->di_flags = cur->inode->st.st_flags;
698#endif 701#endif
699#if HAVE_STRUCT_STAT_ST_GEN 702#if HAVE_STRUCT_STAT_ST_GEN
700 dinp->di_gen = cur->inode->st.st_gen; 703 dinp->di_gen = cur->inode->st.st_gen;
701#endif 704#endif
702#if HAVE_STRUCT_STAT_BIRTHTIME 705#if HAVE_STRUCT_STAT_BIRTHTIME
703 dinp->di_birthtime = cur->inode->st.st_birthtime; 706 dinp->di_birthtime = cur->inode->st.st_birthtime;
704 dinp->di_birthnsec = cur->inode->st.st_birthtimensec; 707 dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
705#endif 708#endif
706 dinp->di_uid = cur->inode->st.st_uid; 709 dinp->di_uid = cur->inode->st.st_uid;
707 dinp->di_gid = cur->inode->st.st_gid; 710 dinp->di_gid = cur->inode->st.st_gid;
708 /* not set: di_db, di_ib, di_blocks, di_spare */ 711 /* not set: di_db, di_ib, di_blocks, di_spare */
709 712
710 membuf = NULL; 713 membuf = NULL;
711 if (cur == root) { /* "."; write dirbuf */ 714 if (cur == root) { /* "."; write dirbuf */
712 membuf = dbufp->buf; 715 membuf = dbufp->buf;
713 dinp->di_size = dbufp->size; 716 dinp->di_size = dbufp->size;
714 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) { 717 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
715 dinp->di_size = 0; /* a device */ 718 dinp->di_size = 0; /* a device */
716 dinp->di_rdev = 719 dinp->di_rdev =
717 ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap); 720 ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap);
718 } else if (S_ISLNK(cur->type)) { /* symlink */ 721 } else if (S_ISLNK(cur->type)) { /* symlink */
719 slen = strlen(cur->symlink); 722 slen = strlen(cur->symlink);
720 if (slen < UFS2_MAXSYMLINKLEN) { /* short link */ 723 if (slen < UFS2_MAXSYMLINKLEN) { /* short link */
721 memcpy(dinp->di_db, cur->symlink, slen); 724 memcpy(dinp->di_db, cur->symlink, slen);
722 } else 725 } else
723 membuf = cur->symlink; 726 membuf = cur->symlink;
724 dinp->di_size = slen; 727 dinp->di_size = slen;
725 } 728 }
726 return membuf; 729 return membuf;
727} 730}
728 731
729static int 732static int
730ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts) 733ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
731{ 734{
732 fsnode *cur; 735 fsnode *cur;
733 dirbuf_t dirbuf; 736 dirbuf_t dirbuf;
734 union dinode din; 737 union dinode din;
735 void *membuf; 738 void *membuf;
736 char path[MAXPATHLEN + 1]; 739 char path[MAXPATHLEN + 1];
737 ffs_opt_t *ffs_opts = fsopts->fs_specific; 740 ffs_opt_t *ffs_opts = fsopts->fs_specific;
738 741
739 assert(dir != NULL); 742 assert(dir != NULL);
740 assert(root != NULL); 743 assert(root != NULL);
741 assert(fsopts != NULL); 744 assert(fsopts != NULL);
742 assert(ffs_opts != NULL); 745 assert(ffs_opts != NULL);
743 746
744 (void)memset(&dirbuf, 0, sizeof(dirbuf)); 747 (void)memset(&dirbuf, 0, sizeof(dirbuf));
745 748
746 if (debug & DEBUG_FS_POPULATE) 749 if (debug & DEBUG_FS_POPULATE)
747 printf("ffs_populate_dir: PASS 1 dir %s node %p\n", dir, root); 750 printf("ffs_populate_dir: PASS 1 dir %s node %p\n", dir, root);
748 751
749 /* 752 /*
750 * pass 1: allocate inode numbers, build directory `file' 753 * pass 1: allocate inode numbers, build directory `file'
751 */ 754 */
752 for (cur = root; cur != NULL; cur = cur->next) { 755 for (cur = root; cur != NULL; cur = cur->next) {
753 if ((cur->inode->flags & FI_ALLOCATED) == 0) { 756 if ((cur->inode->flags & FI_ALLOCATED) == 0) {
754 cur->inode->flags |= FI_ALLOCATED; 757 cur->inode->flags |= FI_ALLOCATED;
755 if (cur == root && cur->parent != NULL) 758 if (cur == root && cur->parent != NULL)
756 cur->inode->ino = cur->parent->inode->ino; 759 cur->inode->ino = cur->parent->inode->ino;
757 else { 760 else {
758 cur->inode->ino = fsopts->curinode; 761 cur->inode->ino = fsopts->curinode;
759 fsopts->curinode++; 762 fsopts->curinode++;
760 } 763 }
761 } 764 }
762 ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap); 765 ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
763 if (cur == root) { /* we're at "."; add ".." */ 766 if (cur == root) { /* we're at "."; add ".." */
764 ffs_make_dirbuf(&dirbuf, "..", 767 ffs_make_dirbuf(&dirbuf, "..",
765 cur->parent == NULL ? cur : cur->parent->first, 768 cur->parent == NULL ? cur : cur->parent->first,
766 fsopts->needswap); 769 fsopts->needswap);
767 root->inode->nlink++; /* count my parent's link */ 770 root->inode->nlink++; /* count my parent's link */
768 } else if (cur->child != NULL) 771 } else if (cur->child != NULL)
769 root->inode->nlink++; /* count my child's link */ 772 root->inode->nlink++; /* count my child's link */
770 773
771 /* 774 /*
772 * XXX possibly write file and long symlinks here, 775 * XXX possibly write file and long symlinks here,
773 * ensuring that blocks get written before inodes? 776 * ensuring that blocks get written before inodes?
774 * otoh, this isn't a real filesystem, so who 777 * otoh, this isn't a real filesystem, so who
775 * cares about ordering? :-) 778 * cares about ordering? :-)
776 */ 779 */
777 } 780 }
778 if (debug & DEBUG_FS_POPULATE_DIRBUF) 781 if (debug & DEBUG_FS_POPULATE_DIRBUF)
779 ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap); 782 ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap);
780 783
781 /* 784 /*
782 * pass 2: write out dirbuf, then non-directories at this level 785 * pass 2: write out dirbuf, then non-directories at this level
783 */ 786 */
784 if (debug & DEBUG_FS_POPULATE) 787 if (debug & DEBUG_FS_POPULATE)
785 printf("ffs_populate_dir: PASS 2 dir %s\n", dir); 788 printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
786 for (cur = root; cur != NULL; cur = cur->next) { 789 for (cur = root; cur != NULL; cur = cur->next) {
787 if (cur->inode->flags & FI_WRITTEN) 790 if (cur->inode->flags & FI_WRITTEN)
788 continue; /* skip hard-linked entries */ 791 continue; /* skip hard-linked entries */
789 cur->inode->flags |= FI_WRITTEN; 792 cur->inode->flags |= FI_WRITTEN;
790 793
791 if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root, 794 if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root,
792 cur->path, cur->name) >= sizeof(path)) 795 cur->path, cur->name) >= sizeof(path))
793 errx(1, "Pathname too long."); 796 errx(1, "Pathname too long.");
794 797
795 if (cur->child != NULL) 798 if (cur->child != NULL)
796 continue; /* child creates own inode */ 799 continue; /* child creates own inode */
797 800
798 /* build on-disk inode */ 801 /* build on-disk inode */
799 if (ffs_opts->version == 1) 802 if (ffs_opts->version == 1)
800 membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur, 803 membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur,
801 root, fsopts); 804 root, fsopts);
802 else 805 else
803 membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur, 806 membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur,
804 root, fsopts); 807 root, fsopts);
805 808
806 if (debug & DEBUG_FS_POPULATE_NODE) { 809 if (debug & DEBUG_FS_POPULATE_NODE) {
807 printf("ffs_populate_dir: writing ino %d, %s", 810 printf("ffs_populate_dir: writing ino %d, %s",
808 cur->inode->ino, inode_type(cur->type)); 811 cur->inode->ino, inode_type(cur->type));
809 if (cur->inode->nlink > 1) 812 if (cur->inode->nlink > 1)
810 printf(", nlink %d", cur->inode->nlink); 813 printf(", nlink %d", cur->inode->nlink);
811 putchar('\n'); 814 putchar('\n');
812 } 815 }
813 816
814 if (membuf != NULL) { 817 if (membuf != NULL) {
815 ffs_write_file(&din, cur->inode->ino, membuf, fsopts); 818 ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
816 } else if (S_ISREG(cur->type)) { 819 } else if (S_ISREG(cur->type)) {
817 ffs_write_file(&din, cur->inode->ino, path, fsopts); 820 ffs_write_file(&din, cur->inode->ino, path, fsopts);
818 } else { 821 } else {
819 assert (! S_ISDIR(cur->type)); 822 assert (! S_ISDIR(cur->type));
820 ffs_write_inode(&din, cur->inode->ino, fsopts); 823 ffs_write_inode(&din, cur->inode->ino, fsopts);
821 } 824 }
822 } 825 }
823 826
824 /* 827 /*
825 * pass 3: write out sub-directories 828 * pass 3: write out sub-directories
826 */ 829 */
827 if (debug & DEBUG_FS_POPULATE) 830 if (debug & DEBUG_FS_POPULATE)
828 printf("ffs_populate_dir: PASS 3 dir %s\n", dir); 831 printf("ffs_populate_dir: PASS 3 dir %s\n", dir);
829 for (cur = root; cur != NULL; cur = cur->next) { 832 for (cur = root; cur != NULL; cur = cur->next) {
830 if (cur->child == NULL) 833 if (cur->child == NULL)
831 continue; 834 continue;
832 if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir, 835 if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir,
833 cur->name) >= sizeof(path)) 836 cur->name) >= sizeof(path))
834 errx(1, "Pathname too long."); 837 errx(1, "Pathname too long.");
835 if (! ffs_populate_dir(path, cur->child, fsopts)) 838 if (! ffs_populate_dir(path, cur->child, fsopts))
836 return (0); 839 return (0);
837 } 840 }
838 841
839 if (debug & DEBUG_FS_POPULATE) 842 if (debug & DEBUG_FS_POPULATE)
840 printf("ffs_populate_dir: DONE dir %s\n", dir); 843 printf("ffs_populate_dir: DONE dir %s\n", dir);
841 844
842 /* cleanup */ 845 /* cleanup */
843 if (dirbuf.buf != NULL) 846 if (dirbuf.buf != NULL)
844 free(dirbuf.buf); 847 free(dirbuf.buf);
845 return (1); 848 return (1);
846} 849}
847 850
848 851
849static void 852static void
850ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts) 853ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
851{ 854{
852 int isfile, ffd; 855 int isfile, ffd;
853 char *fbuf, *p; 856 char *fbuf, *p;
854 off_t bufleft, chunk, offset; 857 off_t bufleft, chunk, offset;
855 ssize_t nread; 858 ssize_t nread;
856 struct inode in; 859 struct inode in;
857 struct buf * bp; 860 struct buf * bp;
858 ffs_opt_t *ffs_opts = fsopts->fs_specific; 861 ffs_opt_t *ffs_opts = fsopts->fs_specific;
859 862
860 assert (din != NULL); 863 assert (din != NULL);
861 assert (buf != NULL); 864 assert (buf != NULL);
862 assert (fsopts != NULL); 865 assert (fsopts != NULL);
863 assert (ffs_opts != NULL); 866 assert (ffs_opts != NULL);
864 867
865 isfile = S_ISREG(DIP(din, mode)); 868 isfile = S_ISREG(DIP(din, mode));
866 fbuf = NULL; 869 fbuf = NULL;
867 ffd = -1; 870 ffd = -1;
868 p = NULL; 871 p = NULL;
869 872
870 in.i_fs = (struct fs *)fsopts->superblock; 873 in.i_fs = (struct fs *)fsopts->superblock;
871 874
872 if (debug & DEBUG_FS_WRITE_FILE) { 875 if (debug & DEBUG_FS_WRITE_FILE) {
873 printf( 876 printf(
874 "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld", 877 "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld",
875 ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT), 878 ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT),
876 (long long)DIP(din, size)); 879 (long long)DIP(din, size));
877 if (isfile) 880 if (isfile)
878 printf(", file '%s'\n", (char *)buf); 881 printf(", file '%s'\n", (char *)buf);
879 else 882 else
880 printf(", buffer %p\n", buf); 883 printf(", buffer %p\n", buf);
881 } 884 }
882 885
883 in.i_number = ino; 886 in.i_number = ino;
884 in.i_size = DIP(din, size); 887 in.i_size = DIP(din, size);
885 if (ffs_opts->version == 1) 888 if (ffs_opts->version == 1)
886 memcpy(&in.i_din.ffs1_din, &din->ffs1_din, 889 memcpy(&in.i_din.ffs1_din, &din->ffs1_din,
887 sizeof(in.i_din.ffs1_din)); 890 sizeof(in.i_din.ffs1_din));
888 else 891 else
889 memcpy(&in.i_din.ffs2_din, &din->ffs2_din, 892 memcpy(&in.i_din.ffs2_din, &din->ffs2_din,
890 sizeof(in.i_din.ffs2_din)); 893 sizeof(in.i_din.ffs2_din));
891 in.i_fd = fsopts->fd; 894 in.i_fd = fsopts->fd;
892 895
893 if (DIP(din, size) == 0) 896 if (DIP(din, size) == 0)
894 goto write_inode_and_leave; /* mmm, cheating */ 897 goto write_inode_and_leave; /* mmm, cheating */
895 898
896 if (isfile) { 899 if (isfile) {
897 if ((fbuf = malloc(ffs_opts->bsize)) == NULL) 900 if ((fbuf = malloc(ffs_opts->bsize)) == NULL)
898 err(1, "Allocating memory for write buffer"); 901 err(1, "Allocating memory for write buffer");
899 if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) { 902 if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) {
900 warn("Can't open `%s' for reading", (char *)buf); 903 warn("Can't open `%s' for reading", (char *)buf);
901 goto leave_ffs_write_file; 904 goto leave_ffs_write_file;
902 } 905 }
903 } else { 906 } else {
904 p = buf; 907 p = buf;
905 } 908 }
906 909
907 chunk = 0; 910 chunk = 0;
908 for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) { 911 for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) {
909 chunk = MIN(bufleft, ffs_opts->bsize); 912 chunk = MIN(bufleft, ffs_opts->bsize);
910 if (!isfile) 913 if (!isfile)
911 ; 914 ;
912 else if ((nread = read(ffd, fbuf, chunk)) == -1) 915 else if ((nread = read(ffd, fbuf, chunk)) == -1)
913 err(EXIT_FAILURE, "Reading `%s', %lld bytes to go", 916 err(EXIT_FAILURE, "Reading `%s', %lld bytes to go",
914 (char *)buf, (long long)bufleft); 917 (char *)buf, (long long)bufleft);
915 else if (nread != chunk) 918 else if (nread != chunk)
916 errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, " 919 errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, "
917 "read %zd bytes, expected %ju bytes, does " 920 "read %zd bytes, expected %ju bytes, does "
918 "metalog size= attribute mismatch source size?", 921 "metalog size= attribute mismatch source size?",
919 (char *)buf, (long long)bufleft, nread, 922 (char *)buf, (long long)bufleft, nread,
920 (uintmax_t)chunk); 923 (uintmax_t)chunk);
921 else 924 else
922 p = fbuf; 925 p = fbuf;
923 offset = DIP(din, size) - bufleft; 926 offset = DIP(din, size) - bufleft;
924 if (debug & DEBUG_FS_WRITE_FILE_BLOCK) 927 if (debug & DEBUG_FS_WRITE_FILE_BLOCK)
925 printf( 928 printf(
926 "ffs_write_file: write %p offset %lld size %lld left %lld\n", 929 "ffs_write_file: write %p offset %lld size %lld left %lld\n",
927 p, (long long)offset, 930 p, (long long)offset,
928 (long long)chunk, (long long)bufleft); 931 (long long)chunk, (long long)bufleft);
929 /* 932 /*
930 * XXX if holey support is desired, do the check here 933 * XXX if holey support is desired, do the check here
931 * 934 *
932 * XXX might need to write out last bit in fragroundup 935 * XXX might need to write out last bit in fragroundup
933 * sized chunk. however, ffs_balloc() handles this for us 936 * sized chunk. however, ffs_balloc() handles this for us
934 */ 937 */
935 errno = ffs_balloc(&in, offset, chunk, &bp); 938 errno = ffs_balloc(&in, offset, chunk, &bp);
936 bad_ffs_write_file: 939 bad_ffs_write_file:
937 if (errno != 0) 940 if (errno != 0)
938 err(1, 941 err(1,
939 "Writing inode %d (%s), bytes %lld + %lld", 942 "Writing inode %d (%s), bytes %lld + %lld",
940 ino, 943 ino,
941 isfile ? (char *)buf : 944 isfile ? (char *)buf :
942 inode_type(DIP(din, mode) & S_IFMT), 945 inode_type(DIP(din, mode) & S_IFMT),
943 (long long)offset, (long long)chunk); 946 (long long)offset, (long long)chunk);
944 memcpy(bp->b_data, p, chunk); 947 memcpy(bp->b_data, p, chunk);
945 errno = bwrite(bp); 948 errno = bwrite(bp);
946 if (errno != 0) 949 if (errno != 0)
947 goto bad_ffs_write_file; 950 goto bad_ffs_write_file;
948 brelse(bp); 951 brelse(bp);
949 if (!isfile) 952 if (!isfile)
950 p += chunk; 953 p += chunk;
951 } 954 }
952  955
953 write_inode_and_leave: 956 write_inode_and_leave:
954 ffs_write_inode(&in.i_din, in.i_number, fsopts); 957 ffs_write_inode(&in.i_din, in.i_number, fsopts);
955 958
956 leave_ffs_write_file: 959 leave_ffs_write_file:
957 if (fbuf) 960 if (fbuf)
958 free(fbuf); 961 free(fbuf);
959 if (ffd != -1) 962 if (ffd != -1)
960 close(ffd); 963 close(ffd);
961} 964}
962 965
963 966
964static void 967static void
965ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap) 968ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
966{ 969{
967 doff_t i; 970 doff_t i;
968 struct direct *de; 971 struct direct *de;
969 uint16_t reclen; 972 uint16_t reclen;
970 973
971 assert (dbuf != NULL); 974 assert (dbuf != NULL);
972 assert (dir != NULL); 975 assert (dir != NULL);
973 printf("ffs_dump_dirbuf: dir %s size %d cur %d\n", 976 printf("ffs_dump_dirbuf: dir %s size %d cur %d\n",
974 dir, dbuf->size, dbuf->cur); 977 dir, dbuf->size, dbuf->cur);
975 978
976 for (i = 0; i < dbuf->size; ) { 979 for (i = 0; i < dbuf->size; ) {
977 de = (struct direct *)(dbuf->buf + i); 980 de = (struct direct *)(dbuf->buf + i);
978 reclen = ufs_rw16(de->d_reclen, needswap); 981 reclen = ufs_rw16(de->d_reclen, needswap);
979 printf( 982 printf(
980 " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n", 983 " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n",
981 ufs_rw32(de->d_fileno, needswap), 984 ufs_rw32(de->d_fileno, needswap),
982 inode_type(DTTOIF(de->d_type)), i, reclen, 985 inode_type(DTTOIF(de->d_type)), i, reclen,
983 de->d_namlen, de->d_name); 986 de->d_namlen, de->d_name);
984 i += reclen; 987 i += reclen;
985 assert(reclen > 0); 988 assert(reclen > 0);
986 } 989 }
987} 990}
988 991
989static void 992static void
990ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap) 993ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
991{ 994{
992 struct direct de, *dp; 995 struct direct de, *dp;
993 uint16_t llen, reclen; 996 uint16_t llen, reclen;
994 u_char *newbuf; 997 u_char *newbuf;
995 998
996 assert (dbuf != NULL); 999 assert (dbuf != NULL);
997 assert (name != NULL); 1000 assert (name != NULL);
998 assert (node != NULL); 1001 assert (node != NULL);
999 /* create direct entry */ 1002 /* create direct entry */
1000 (void)memset(&de, 0, sizeof(de)); 1003 (void)memset(&de, 0, sizeof(de));
1001 de.d_fileno = ufs_rw32(node->inode->ino, needswap); 1004 de.d_fileno = ufs_rw32(node->inode->ino, needswap);
1002 de.d_type = IFTODT(node->type); 1005 de.d_type = IFTODT(node->type);
1003 de.d_namlen = (uint8_t)strlen(name); 1006 de.d_namlen = (uint8_t)strlen(name);
1004 strcpy(de.d_name, name); 1007 strcpy(de.d_name, name);
1005 reclen = DIRSIZ(0, &de, needswap); 1008 reclen = DIRSIZ(0, &de, needswap);
1006 de.d_reclen = ufs_rw16(reclen, needswap); 1009 de.d_reclen = ufs_rw16(reclen, needswap);
1007 1010
1008 dp = (struct direct *)(dbuf->buf + dbuf->cur); 1011 dp = (struct direct *)(dbuf->buf + dbuf->cur);
1009 llen = 0; 1012 llen = 0;
1010 if (dp != NULL) 1013 if (dp != NULL)
1011 llen = DIRSIZ(0, dp, needswap); 1014 llen = DIRSIZ(0, dp, needswap);
1012 1015
1013 if (debug & DEBUG_FS_MAKE_DIRBUF) 1016 if (debug & DEBUG_FS_MAKE_DIRBUF)
1014 printf( 1017 printf(
1015 "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n" 1018 "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n"
1016 " ino %d type %d reclen %d namlen %d name %.30s\n", 1019 " ino %d type %d reclen %d namlen %d name %.30s\n",
1017 dbuf->size, dbuf->cur, llen, 1020 dbuf->size, dbuf->cur, llen,
1018 ufs_rw32(de.d_fileno, needswap), de.d_type, reclen, 1021 ufs_rw32(de.d_fileno, needswap), de.d_type, reclen,
1019 de.d_namlen, de.d_name); 1022 de.d_namlen, de.d_name);
1020 1023
1021 if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) { 1024 if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) {
1022 if (debug & DEBUG_FS_MAKE_DIRBUF) 1025 if (debug & DEBUG_FS_MAKE_DIRBUF)
1023 printf("ffs_make_dirbuf: growing buf to %d\n", 1026 printf("ffs_make_dirbuf: growing buf to %d\n",
1024 dbuf->size + DIRBLKSIZ); 1027 dbuf->size + DIRBLKSIZ);
1025 if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == NULL) 1028 if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == NULL)
1026 err(1, "Allocating memory for directory buffer"); 1029 err(1, "Allocating memory for directory buffer");
1027 dbuf->buf = newbuf; 1030 dbuf->buf = newbuf;
1028 dbuf->size += DIRBLKSIZ; 1031 dbuf->size += DIRBLKSIZ;
1029 memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ); 1032 memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ);
1030 dbuf->cur = dbuf->size - DIRBLKSIZ; 1033 dbuf->cur = dbuf->size - DIRBLKSIZ;
1031 } else if (dp) { /* shrink end of previous */ 1034 } else if (dp) { /* shrink end of previous */
1032 dp->d_reclen = ufs_rw16(llen,needswap); 1035 dp->d_reclen = ufs_rw16(llen,needswap);
1033 dbuf->cur += llen; 1036 dbuf->cur += llen;
1034 } 1037 }
1035 dp = (struct direct *)(dbuf->buf + dbuf->cur); 1038 dp = (struct direct *)(dbuf->buf + dbuf->cur);
1036 memcpy(dp, &de, reclen); 1039 memcpy(dp, &de, reclen);
1037 dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap); 1040 dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap);
1038} 1041}
1039 1042
1040/* 1043/*
1041 * cribbed from sys/ufs/ffs/ffs_alloc.c 1044 * cribbed from sys/ufs/ffs/ffs_alloc.c
1042 */ 1045 */
1043static void 1046static void
1044ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts) 1047ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
1045{ 1048{
1046 char *buf; 1049 char *buf;
1047 struct ufs1_dinode *dp1; 1050 struct ufs1_dinode *dp1;
1048 struct ufs2_dinode *dp2, *dip; 1051 struct ufs2_dinode *dp2, *dip;
1049 struct cg *cgp; 1052 struct cg *cgp;
1050 struct fs *fs; 1053 struct fs *fs;
1051 int cg, cgino, i; 1054 int cg, cgino, i;
1052 daddr_t d; 1055 daddr_t d;
1053 char sbbuf[FFS_MAXBSIZE]; 1056 char sbbuf[FFS_MAXBSIZE];
1054 uint32_t initediblk; 1057 uint32_t initediblk;
1055 ffs_opt_t *ffs_opts = fsopts->fs_specific; 1058 ffs_opt_t *ffs_opts = fsopts->fs_specific;
1056 1059
1057 assert (dp != NULL); 1060 assert (dp != NULL);
1058 assert (ino > 0); 1061 assert (ino > 0);
1059 assert (fsopts != NULL); 1062 assert (fsopts != NULL);
1060 assert (ffs_opts != NULL); 1063 assert (ffs_opts != NULL);
1061 1064
1062 fs = (struct fs *)fsopts->superblock; 1065 fs = (struct fs *)fsopts->superblock;
1063 cg = ino_to_cg(fs, ino); 1066 cg = ino_to_cg(fs, ino);
1064 cgino = ino % fs->fs_ipg; 1067 cgino = ino % fs->fs_ipg;
1065 if (debug & DEBUG_FS_WRITE_INODE) 1068 if (debug & DEBUG_FS_WRITE_INODE)
1066 printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n", 1069 printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n",
1067 dp, ino, cg, cgino); 1070 dp, ino, cg, cgino);
1068 1071
1069 ffs_rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf, 1072 ffs_rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
1070 fsopts); 1073 fsopts);
1071 cgp = (struct cg *)sbbuf; 1074 cgp = (struct cg *)sbbuf;
1072 if (!cg_chkmagic(cgp, fsopts->needswap)) 1075 if (!cg_chkmagic(cgp, fsopts->needswap))
1073 errx(1, "ffs_write_inode: cg %d: bad magic number", cg); 1076 errx(1, "ffs_write_inode: cg %d: bad magic number", cg);
1074 1077
1075 assert (isclr(cg_inosused(cgp, fsopts->needswap), cgino)); 1078 assert (isclr(cg_inosused(cgp, fsopts->needswap), cgino));
1076 1079
1077 buf = malloc(fs->fs_bsize); 1080 buf = malloc(fs->fs_bsize);
1078 if (buf == NULL) 1081 if (buf == NULL)
1079 errx(1, "ffs_write_inode: cg %d: can't alloc inode block", cg); 1082 errx(1, "ffs_write_inode: cg %d: can't alloc inode block", cg);
1080 1083
1081 dp1 = (struct ufs1_dinode *)buf; 1084 dp1 = (struct ufs1_dinode *)buf;
1082 dp2 = (struct ufs2_dinode *)buf; 1085 dp2 = (struct ufs2_dinode *)buf;
1083 1086
1084 if (fs->fs_cstotal.cs_nifree == 0) 1087 if (fs->fs_cstotal.cs_nifree == 0)
1085 errx(1, "ffs_write_inode: fs out of inodes for ino %u", 1088 errx(1, "ffs_write_inode: fs out of inodes for ino %u",
1086 ino); 1089 ino);
1087 if (fs->fs_cs(fs, cg).cs_nifree == 0) 1090 if (fs->fs_cs(fs, cg).cs_nifree == 0)
1088 errx(1, 1091 errx(1,
1089 "ffs_write_inode: cg %d out of inodes for ino %u", 1092 "ffs_write_inode: cg %d out of inodes for ino %u",
1090 cg, ino); 1093 cg, ino);
1091 setbit(cg_inosused(cgp, fsopts->needswap), cgino); 1094 setbit(cg_inosused(cgp, fsopts->needswap), cgino);
1092 ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap); 1095 ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap);
1093 fs->fs_cstotal.cs_nifree--; 1096 fs->fs_cstotal.cs_nifree--;
1094 fs->fs_cs(fs, cg).cs_nifree--; 1097 fs->fs_cs(fs, cg).cs_nifree--;
1095 if (S_ISDIR(DIP(dp, mode))) { 1098 if (S_ISDIR(DIP(dp, mode))) {
1096 ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap); 1099 ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap);
1097 fs->fs_cstotal.cs_ndir++; 1100 fs->fs_cstotal.cs_ndir++;
1098 fs->fs_cs(fs, cg).cs_ndir++;  1101 fs->fs_cs(fs, cg).cs_ndir++;
1099 } 1102 }
1100 1103
1101 /* 1104 /*
1102 * Initialize inode blocks on the fly for UFS2. 1105 * Initialize inode blocks on the fly for UFS2.
1103 */ 1106 */
1104 initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap); 1107 initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
1105 if (ffs_opts->version == 2 && 1108 if (ffs_opts->version == 2 &&
1106 (uint32_t)(cgino + INOPB(fs)) > initediblk && 1109 (uint32_t)(cgino + INOPB(fs)) > initediblk &&
1107 initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) { 1110 initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
1108 memset(buf, 0, fs->fs_bsize); 1111 memset(buf, 0, fs->fs_bsize);
1109 dip = (struct ufs2_dinode *)buf; 1112 dip = (struct ufs2_dinode *)buf;
1110 srandom(time(NULL)); 1113 srandom(time(NULL));
1111 for (i = 0; i < INOPB(fs); i++) { 1114 for (i = 0; i < INOPB(fs); i++) {
1112 dip->di_gen = random() / 2 + 1; 1115 dip->di_gen = random() / 2 + 1;
1113 dip++; 1116 dip++;
1114 } 1117 }
1115 ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs, 1118 ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs,
1116 cg * fs->fs_ipg + initediblk)), 1119 cg * fs->fs_ipg + initediblk)),
1117 fs->fs_bsize, buf, fsopts); 1120 fs->fs_bsize, buf, fsopts);
1118 initediblk += INOPB(fs); 1121 initediblk += INOPB(fs);
1119 cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap); 1122 cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap);
1120 } 1123 }
1121 1124
1122 1125
1123 ffs_wtfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf, 1126 ffs_wtfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
1124 fsopts); 1127 fsopts);
1125 1128
1126 /* now write inode */ 1129 /* now write inode */
1127 d = fsbtodb(fs, ino_to_fsba(fs, ino)); 1130 d = fsbtodb(fs, ino_to_fsba(fs, ino));
1128 ffs_rdfs(d, fs->fs_bsize, buf, fsopts); 1131 ffs_rdfs(d, fs->fs_bsize, buf, fsopts);
1129 if (fsopts->needswap) { 1132 if (fsopts->needswap) {
1130 if (ffs_opts->version == 1) 1133 if (ffs_opts->version == 1)
1131 ffs_dinode1_swap(&dp->ffs1_din, 1134 ffs_dinode1_swap(&dp->ffs1_din,
1132 &dp1[ino_to_fsbo(fs, ino)]); 1135 &dp1[ino_to_fsbo(fs, ino)]);
1133 else 1136 else
1134 ffs_dinode2_swap(&dp->ffs2_din, 1137 ffs_dinode2_swap(&dp->ffs2_din,
1135 &dp2[ino_to_fsbo(fs, ino)]); 1138 &dp2[ino_to_fsbo(fs, ino)]);
1136 } else { 1139 } else {
1137 if (ffs_opts->version == 1) 1140 if (ffs_opts->version == 1)
1138 dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din; 1141 dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din;
1139 else 1142 else
1140 dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din; 1143 dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din;
1141 } 1144 }
1142 ffs_wtfs(d, fs->fs_bsize, buf, fsopts); 1145 ffs_wtfs(d, fs->fs_bsize, buf, fsopts);
1143 free(buf); 1146 free(buf);
1144} 1147}
1145 1148
1146void 1149void
1147panic(const char *fmt, ...) 1150panic(const char *fmt, ...)
1148{ 1151{
1149 va_list ap; 1152 va_list ap;
1150 1153
1151 va_start(ap, fmt); 1154 va_start(ap, fmt);
1152 vwarnx(fmt, ap); 1155 vwarnx(fmt, ap);
1153 va_end(ap); 1156 va_end(ap);
1154 exit(1); 1157 exit(1);
1155} 1158}

cvs diff -r1.37 -r1.38 src/usr.sbin/makefs/makefs.c (switch to unified diff)

--- src/usr.sbin/makefs/makefs.c 2013/01/23 21:32:32 1.37
+++ src/usr.sbin/makefs/makefs.c 2013/01/23 21:42:22 1.38
@@ -1,401 +1,401 @@ @@ -1,401 +1,401 @@
1/* $NetBSD: makefs.c,v 1.37 2013/01/23 21:32:32 christos Exp $ */ 1/* $NetBSD: makefs.c,v 1.38 2013/01/23 21:42:22 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2003 Wasabi Systems, Inc. 4 * Copyright (c) 2001-2003 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Luke Mewburn for Wasabi Systems, Inc. 7 * Written by Luke Mewburn for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#if HAVE_NBTOOL_CONFIG_H 38#if HAVE_NBTOOL_CONFIG_H
39#include "nbtool_config.h" 39#include "nbtool_config.h"
40#endif 40#endif
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43#if defined(__RCSID) && !defined(__lint) 43#if defined(__RCSID) && !defined(__lint)
44__RCSID("$NetBSD: makefs.c,v 1.37 2013/01/23 21:32:32 christos Exp $"); 44__RCSID("$NetBSD: makefs.c,v 1.38 2013/01/23 21:42:22 christos Exp $");
45#endif /* !__lint */ 45#endif /* !__lint */
46 46
47#include <assert.h> 47#include <assert.h>
48#include <ctype.h> 48#include <ctype.h>
49#include <errno.h> 49#include <errno.h>
50#include <limits.h> 50#include <limits.h>
51#include <stdio.h> 51#include <stdio.h>
52#include <stdlib.h> 52#include <stdlib.h>
53#include <string.h> 53#include <string.h>
54#include <unistd.h> 54#include <unistd.h>
55#include <stdbool.h> 55#include <stdbool.h>
56 56
57#include "makefs.h" 57#include "makefs.h"
58#include "mtree.h" 58#include "mtree.h"
59#include "cd9660.h" 59#include "cd9660.h"
60 60
61/* 61/*
62 * list of supported file systems and dispatch functions 62 * list of supported file systems and dispatch functions
63 */ 63 */
64typedef struct { 64typedef struct {
65 const char *type; 65 const char *type;
66 void (*prepare_options)(fsinfo_t *); 66 void (*prepare_options)(fsinfo_t *);
67 int (*parse_options)(const char *, fsinfo_t *); 67 int (*parse_options)(const char *, fsinfo_t *);
68 void (*cleanup_options)(fsinfo_t *); 68 void (*cleanup_options)(fsinfo_t *);
69 void (*make_fs)(const char *, const char *, fsnode *, 69 void (*make_fs)(const char *, const char *, fsnode *,
70 fsinfo_t *); 70 fsinfo_t *);
71} fstype_t; 71} fstype_t;
72 72
73static fstype_t fstypes[] = { 73static fstype_t fstypes[] = {
74#define ENTRY(name) { \ 74#define ENTRY(name) { \
75 # name, name ## _prep_opts, name ## _parse_opts, \ 75 # name, name ## _prep_opts, name ## _parse_opts, \
76 name ## _cleanup_opts, name ## _makefs \ 76 name ## _cleanup_opts, name ## _makefs \
77} 77}
78 ENTRY(ffs), 78 ENTRY(ffs),
79 ENTRY(cd9660), 79 ENTRY(cd9660),
80 ENTRY(chfs), 80 ENTRY(chfs),
81 ENTRY(v7fs), 81 ENTRY(v7fs),
82 ENTRY(msdos), 82 ENTRY(msdos),
83 { .type = NULL }, 83 { .type = NULL },
84}; 84};
85 85
86u_int debug; 86u_int debug;
87struct timespec start_time; 87struct timespec start_time;
88 88
89static fstype_t *get_fstype(const char *); 89static fstype_t *get_fstype(const char *);
90static void usage(void) __dead; 90static void usage(void) __dead;
91 91
92int 92int
93main(int argc, char *argv[]) 93main(int argc, char *argv[])
94{ 94{
95 struct timeval start; 95 struct timeval start;
96 fstype_t *fstype; 96 fstype_t *fstype;
97 fsinfo_t fsoptions; 97 fsinfo_t fsoptions;
98 fsnode *root; 98 fsnode *root;
99 int ch, i, len; 99 int ch, i, len;
100 char *specfile; 100 char *specfile;
101 101
102 setprogname(argv[0]); 102 setprogname(argv[0]);
103 103
104 debug = 0; 104 debug = 0;
105 if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL) 105 if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL)
106 errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE); 106 errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE);
107 107
108 /* set default fsoptions */ 108 /* set default fsoptions */
109 (void)memset(&fsoptions, 0, sizeof(fsoptions)); 109 (void)memset(&fsoptions, 0, sizeof(fsoptions));
110 fsoptions.fd = -1; 110 fsoptions.fd = -1;
111 fsoptions.sectorsize = -1; 111 fsoptions.sectorsize = -1;
112 112
113 if (fstype->prepare_options) 113 if (fstype->prepare_options)
114 fstype->prepare_options(&fsoptions); 114 fstype->prepare_options(&fsoptions);
115 115
116 specfile = NULL; 116 specfile = NULL;
117 if (gettimeofday(&start, NULL) == -1) 117 if (gettimeofday(&start, NULL) == -1)
118 err(1, "Unable to get system time"); 118 err(1, "Unable to get system time");
119 119
120 start_time.tv_sec = start.tv_sec; 120 start_time.tv_sec = start.tv_sec;
121 start_time.tv_nsec = start.tv_usec * 1000; 121 start_time.tv_nsec = start.tv_usec * 1000;
122 122
123 while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:o:s:S:t:xZ")) != -1) { 123 while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:o:s:S:t:xZ")) != -1) {
124 switch (ch) { 124 switch (ch) {
125 125
126 case 'B': 126 case 'B':
127 if (strcmp(optarg, "be") == 0 || 127 if (strcmp(optarg, "be") == 0 ||
128 strcmp(optarg, "4321") == 0 || 128 strcmp(optarg, "4321") == 0 ||
129 strcmp(optarg, "big") == 0) { 129 strcmp(optarg, "big") == 0) {
130#if BYTE_ORDER == LITTLE_ENDIAN 130#if BYTE_ORDER == LITTLE_ENDIAN
131 fsoptions.needswap = 1; 131 fsoptions.needswap = 1;
132#endif 132#endif
133 } else if (strcmp(optarg, "le") == 0 || 133 } else if (strcmp(optarg, "le") == 0 ||
134 strcmp(optarg, "1234") == 0 || 134 strcmp(optarg, "1234") == 0 ||
135 strcmp(optarg, "little") == 0) { 135 strcmp(optarg, "little") == 0) {
136#if BYTE_ORDER == BIG_ENDIAN 136#if BYTE_ORDER == BIG_ENDIAN
137 fsoptions.needswap = 1; 137 fsoptions.needswap = 1;
138#endif 138#endif
139 } else { 139 } else {
140 warnx("Invalid endian `%s'.", optarg); 140 warnx("Invalid endian `%s'.", optarg);
141 usage(); 141 usage();
142 } 142 }
143 break; 143 break;
144 144
145 case 'b': 145 case 'b':
146 len = strlen(optarg) - 1; 146 len = strlen(optarg) - 1;
147 if (optarg[len] == '%') { 147 if (optarg[len] == '%') {
148 optarg[len] = '\0'; 148 optarg[len] = '\0';
149 fsoptions.freeblockpc = 149 fsoptions.freeblockpc =
150 strsuftoll("free block percentage", 150 strsuftoll("free block percentage",
151 optarg, 0, 99); 151 optarg, 0, 99);
152 } else { 152 } else {
153 fsoptions.freeblocks = 153 fsoptions.freeblocks =
154 strsuftoll("free blocks", 154 strsuftoll("free blocks",
155 optarg, 0, LLONG_MAX); 155 optarg, 0, LLONG_MAX);
156 } 156 }
157 break; 157 break;
158 158
159 case 'd': 159 case 'd':
160 debug = strtoll(optarg, NULL, 0); 160 debug = strtoll(optarg, NULL, 0);
161 break; 161 break;
162 162
163 case 'f': 163 case 'f':
164 len = strlen(optarg) - 1; 164 len = strlen(optarg) - 1;
165 if (optarg[len] == '%') { 165 if (optarg[len] == '%') {
166 optarg[len] = '\0'; 166 optarg[len] = '\0';
167 fsoptions.freefilepc = 167 fsoptions.freefilepc =
168 strsuftoll("free file percentage", 168 strsuftoll("free file percentage",
169 optarg, 0, 99); 169 optarg, 0, 99);
170 } else { 170 } else {
171 fsoptions.freefiles = 171 fsoptions.freefiles =
172 strsuftoll("free files", 172 strsuftoll("free files",
173 optarg, 0, LLONG_MAX); 173 optarg, 0, LLONG_MAX);
174 } 174 }
175 break; 175 break;
176 176
177 case 'F': 177 case 'F':
178 specfile = optarg; 178 specfile = optarg;
179 break; 179 break;
180 180
181 case 'M': 181 case 'M':
182 fsoptions.minsize = 182 fsoptions.minsize =
183 strsuftoll("minimum size", optarg, 1LL, LLONG_MAX); 183 strsuftoll("minimum size", optarg, 1LL, LLONG_MAX);
184 break; 184 break;
185 185
186 case 'N': 186 case 'N':
187 if (! setup_getid(optarg)) 187 if (! setup_getid(optarg))
188 errx(1, 188 errx(1,
189 "Unable to use user and group databases in `%s'", 189 "Unable to use user and group databases in `%s'",
190 optarg); 190 optarg);
191 break; 191 break;
192 192
193 case 'm': 193 case 'm':
194 fsoptions.maxsize = 194 fsoptions.maxsize =
195 strsuftoll("maximum size", optarg, 1LL, LLONG_MAX); 195 strsuftoll("maximum size", optarg, 1LL, LLONG_MAX);
196 break; 196 break;
197  197
198 case 'o': 198 case 'o':
199 { 199 {
200 char *p; 200 char *p;
201 201
202 while ((p = strsep(&optarg, ",")) != NULL) { 202 while ((p = strsep(&optarg, ",")) != NULL) {
203 if (*p == '\0') 203 if (*p == '\0')
204 errx(1, "Empty option"); 204 errx(1, "Empty option");
205 if (! fstype->parse_options(p, &fsoptions)) 205 if (! fstype->parse_options(p, &fsoptions))
206 usage(); 206 usage();
207 } 207 }
208 break; 208 break;
209 } 209 }
210 210
211 case 's': 211 case 's':
212 fsoptions.minsize = fsoptions.maxsize = 212 fsoptions.minsize = fsoptions.maxsize =
213 strsuftoll("size", optarg, 1LL, LLONG_MAX); 213 strsuftoll("size", optarg, 1LL, LLONG_MAX);
214 break; 214 break;
215 215
216 case 'S': 216 case 'S':
217 fsoptions.sectorsize = 217 fsoptions.sectorsize =
218 (int)strsuftoll("sector size", optarg, 218 (int)strsuftoll("sector size", optarg,
219 1LL, INT_MAX); 219 1LL, INT_MAX);
220 break; 220 break;
221 221
222 case 't': 222 case 't':
223 /* Check current one and cleanup if necessary. */ 223 /* Check current one and cleanup if necessary. */
224 if (fstype->cleanup_options) 224 if (fstype->cleanup_options)
225 fstype->cleanup_options(&fsoptions); 225 fstype->cleanup_options(&fsoptions);
226 fsoptions.fs_specific = NULL; 226 fsoptions.fs_specific = NULL;
227 if ((fstype = get_fstype(optarg)) == NULL) 227 if ((fstype = get_fstype(optarg)) == NULL)
228 errx(1, "Unknown fs type `%s'.", optarg); 228 errx(1, "Unknown fs type `%s'.", optarg);
229 fstype->prepare_options(&fsoptions); 229 fstype->prepare_options(&fsoptions);
230 break; 230 break;
231 231
232 case 'x': 232 case 'x':
233 fsoptions.onlyspec = 1; 233 fsoptions.onlyspec = 1;
234 break; 234 break;
235 235
236 case 'Z': 236 case 'Z':
237 fsoptions.sparse = 1; 237 fsoptions.sparse = 1;
238 break; 238 break;
239 239
240 case '?': 240 case '?':
241 default: 241 default:
242 usage(); 242 usage();
243 /* NOTREACHED */ 243 /* NOTREACHED */
244 244
245 } 245 }
246 } 246 }
247 if (debug) { 247 if (debug) {
248 printf("debug mask: 0x%08x\n", debug); 248 printf("debug mask: 0x%08x\n", debug);
249 printf("start time: %ld.%ld, %s", 249 printf("start time: %ld.%ld, %s",
250 (long)start_time.tv_sec, (long)start_time.tv_nsec, 250 (long)start_time.tv_sec, (long)start_time.tv_nsec,
251 ctime(&start_time.tv_sec)); 251 ctime(&start_time.tv_sec));
252 } 252 }
253 argc -= optind; 253 argc -= optind;
254 argv += optind; 254 argv += optind;
255 255
256 if (argc < 2) 256 if (argc < 2)
257 usage(); 257 usage();
258 258
259 /* -x must be accompanied by -F */ 259 /* -x must be accompanied by -F */
260 if (fsoptions.onlyspec != 0 && specfile == NULL) 260 if (fsoptions.onlyspec != 0 && specfile == NULL)
261 errx(1, "-x requires -F mtree-specfile."); 261 errx(1, "-x requires -F mtree-specfile.");
262 262
263 /* walk the tree */ 263 /* walk the tree */
264 TIMER_START(start); 264 TIMER_START(start);
265 root = walk_dir(argv[1], ".", NULL, NULL); 265 root = walk_dir(argv[1], ".", NULL, NULL);
266 TIMER_RESULTS(start, "walk_dir"); 266 TIMER_RESULTS(start, "walk_dir");
267 267
268 /* append extra directory */ 268 /* append extra directory */
269 for (i = 2; i < argc; i++) { 269 for (i = 2; i < argc; i++) {
270 struct stat sb; 270 struct stat sb;
271 if (stat(argv[i], &sb) == -1) 271 if (stat(argv[i], &sb) == -1)
272 err(1, "Can't stat `%s'", argv[i]); 272 err(1, "Can't stat `%s'", argv[i]);
273 if (!S_ISDIR(sb.st_mode)) 273 if (!S_ISDIR(sb.st_mode))
274 errx(1, "%s: not a directory", argv[i]); 274 errx(1, "%s: not a directory", argv[i]);
275 TIMER_START(start); 275 TIMER_START(start);
276 root = walk_dir(argv[i], ".", NULL, root); 276 root = walk_dir(argv[i], ".", NULL, root);
277 TIMER_RESULTS(start, "walk_dir2"); 277 TIMER_RESULTS(start, "walk_dir2");
278 } 278 }
279 279
280 if (specfile) { /* apply a specfile */ 280 if (specfile) { /* apply a specfile */
281 TIMER_START(start); 281 TIMER_START(start);
282 apply_specfile(specfile, argv[1], root, fsoptions.onlyspec); 282 apply_specfile(specfile, argv[1], root, fsoptions.onlyspec);
283 TIMER_RESULTS(start, "apply_specfile"); 283 TIMER_RESULTS(start, "apply_specfile");
284 } 284 }
285 285
286 if (debug & DEBUG_DUMP_FSNODES) { 286 if (debug & DEBUG_DUMP_FSNODES) {
287 printf("\nparent: %s\n", argv[1]); 287 printf("\nparent: %s\n", argv[1]);
288 dump_fsnodes(root); 288 dump_fsnodes(root);
289 putchar('\n'); 289 putchar('\n');
290 } 290 }
291 291
292 /* build the file system */ 292 /* build the file system */
293 TIMER_START(start); 293 TIMER_START(start);
294 fstype->make_fs(argv[0], argv[1], root, &fsoptions); 294 fstype->make_fs(argv[0], argv[1], root, &fsoptions);
295 TIMER_RESULTS(start, "make_fs"); 295 TIMER_RESULTS(start, "make_fs");
296 296
297 free_fsnodes(root); 297 free_fsnodes(root);
298 298
299 exit(0); 299 exit(0);
300 /* NOTREACHED */ 300 /* NOTREACHED */
301} 301}
302 302
303int 303int
304set_option(const option_t *options, const char *option) 304set_option(const option_t *options, const char *option)
305{ 305{
306 char *var, *val; 306 char *var, *val;
307 int retval; 307 int retval;
308 308
309 assert(option != NULL); 309 assert(option != NULL);
310 310
311 if ((var = strdup(option)) == NULL) { 311 if ((var = strdup(option)) == NULL) {
312 err(EXIT_FAILURE, "Allocating memory for copy of option string"); 312 err(EXIT_FAILURE, "Allocating memory for copy of option string");
313 } 313 }
314 retval = 0; 314 retval = 0;
315 if ((val = strchr(var, '=')) == NULL) { 315 if ((val = strchr(var, '=')) == NULL) {
316 warnx("Option `%s' doesn't contain a value", var); 316 warnx("Option `%s' doesn't contain a value", var);
317 goto out; 317 goto out;
318 } 318 }
319 *val++ = '\0'; 319 *val++ = '\0';
320 320
321 retval = set_option_var(options, var, val); 321 retval = set_option_var(options, var, val);
322  322
323out: 323out:
324 free(var); 324 free(var);
325 return retval; 325 return retval;
326} 326}
327 327
328int 328int
329set_option_var(const option_t *options, const char *var, const char *val) 329set_option_var(const option_t *options, const char *var, const char *val)
330{ 330{
331 char *s; 331 char *s;
332 size_t i; 332 size_t i;
333 333
334#define NUM(width) *(uint ## width ## _t *)options[i].value = \ 334#define NUM(width) *(uint ## width ## _t *)options[i].value = \
335 (uint ## width ## _t)strsuftoll(options[i].desc, val, \ 335 (uint ## width ## _t)strsuftoll(options[i].desc, val, \
336 options[i].minimum, options[i].maximum); break 336 options[i].minimum, options[i].maximum); break
337 337
338 for (i = 0; options[i].name != NULL; i++) { 338 for (i = 0; options[i].name != NULL; i++) {
339 if (options[i].letter != var[0] || var[1] != '\0') 339 if (options[i].letter != var[0] || var[1] != '\0')
340 continue; 340 continue;
341 else if (strcmp(options[i].name, var) != 0) 341 else if (strcmp(options[i].name, var) != 0)
342 continue; 342 continue;
343 switch (options[i].type) { 343 switch (options[i].type) {
344 case OPT_BOOL: 344 case OPT_BOOL:
345 *(bool *)options[i].value = 1; 345 *(bool *)options[i].value = 1;
346 break; 346 break;
347 case OPT_STRARRAY: 347 case OPT_STRARRAY:
348 strlcpy((void *)options[i].value, val, (size_t) 348 strlcpy((void *)options[i].value, val, (size_t)
349 options[i].maximum); 349 options[i].maximum);
350 break; 350 break;
351 case OPT_STRPTR: 351 case OPT_STRPTR:
352 if ((s = strdup(val)) == NULL) 352 if ((s = strdup(val)) == NULL)
353 err(1, NULL); 353 err(1, NULL);
354 *(char **)options[i].value = s; 354 *(char **)options[i].value = s;
355 break; 355 break;
356 356
357 case OPT_INT64: 357 case OPT_INT64:
358 NUM(64); 358 NUM(64);
359 case OPT_INT32: 359 case OPT_INT32:
360 NUM(32); 360 NUM(32);
361 case OPT_INT16: 361 case OPT_INT16:
362 NUM(16); 362 NUM(16);
363 case OPT_INT8: 363 case OPT_INT8:
364 NUM(8); 364 NUM(8);
365 default: 365 default:
366 warnx("Unknown type %d in option %s", options[i].type, 366 warnx("Unknown type %d in option %s", options[i].type,
367 val); 367 val);
368 return 0; 368 return 0;
369 } 369 }
370 return 1; 370 return 1 << i;
371 } 371 }
372 warnx("Unknown option `%s'", var); 372 warnx("Unknown option `%s'", var);
373 return (0); 373 return (0);
374} 374}
375 375
376 376
377static fstype_t * 377static fstype_t *
378get_fstype(const char *type) 378get_fstype(const char *type)
379{ 379{
380 int i; 380 int i;
381  381
382 for (i = 0; fstypes[i].type != NULL; i++) 382 for (i = 0; fstypes[i].type != NULL; i++)
383 if (strcmp(fstypes[i].type, type) == 0) 383 if (strcmp(fstypes[i].type, type) == 0)
384 return (&fstypes[i]); 384 return (&fstypes[i]);
385 return (NULL); 385 return (NULL);
386} 386}
387 387
388static void 388static void
389usage(void) 389usage(void)
390{ 390{
391 const char *prog; 391 const char *prog;
392 392
393 prog = getprogname(); 393 prog = getprogname();
394 fprintf(stderr, 394 fprintf(stderr,
395"usage: %s [-xZ] [-B endian] [-b free-blocks] [-d debug-mask]\n" 395"usage: %s [-xZ] [-B endian] [-b free-blocks] [-d debug-mask]\n"
396"\t[-F mtree-specfile] [-f free-files] [-M minimum-size]\n" 396"\t[-F mtree-specfile] [-f free-files] [-M minimum-size]\n"
397"\t[-m maximum-size] [-N userdb-dir] [-o fs-options] [-S sector-size]\n" 397"\t[-m maximum-size] [-N userdb-dir] [-o fs-options] [-S sector-size]\n"
398"\t[-s image-size] [-t fs-type] image-file directory [extra-directory ...]\n", 398"\t[-s image-size] [-t fs-type] image-file directory [extra-directory ...]\n",
399 prog); 399 prog);
400 exit(1); 400 exit(1);
401} 401}

cvs diff -r1.2 -r1.3 src/usr.sbin/makefs/msdos.c (switch to unified diff)

--- src/usr.sbin/makefs/msdos.c 2013/01/23 21:32:32 1.2
+++ src/usr.sbin/makefs/msdos.c 2013/01/23 21:42:22 1.3
@@ -1,164 +1,180 @@ @@ -1,164 +1,180 @@
1/* $NetBSD: msdos.c,v 1.2 2013/01/23 21:32:32 christos Exp $ */ 1/* $NetBSD: msdos.c,v 1.3 2013/01/23 21:42:22 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2013 The NetBSD Foundation, Inc. 4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas. 8 * by Christos Zoulas.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The NetBSD Foundation nor the names of its 18 * 3. Neither the name of The NetBSD Foundation nor the names of its
19 * contributors may be used to endorse or promote products derived 19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission. 20 * from this software without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE. 32 * POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34#if HAVE_NBTOOL_CONFIG_H 34#if HAVE_NBTOOL_CONFIG_H
35#include "nbtool_config.h" 35#include "nbtool_config.h"
36#endif 36#endif
37 37
38#include <sys/cdefs.h> 38#include <sys/cdefs.h>
39#if defined(__RCSID) && !defined(__lint) 39#if defined(__RCSID) && !defined(__lint)
40__RCSID("$NetBSD: msdos.c,v 1.2 2013/01/23 21:32:32 christos Exp $"); 40__RCSID("$NetBSD: msdos.c,v 1.3 2013/01/23 21:42:22 christos Exp $");
41#endif /* !__lint */ 41#endif /* !__lint */
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44 44
45#if !HAVE_NBTOOL_CONFIG_H 45#if !HAVE_NBTOOL_CONFIG_H
46#include <sys/mount.h> 46#include <sys/mount.h>
47#endif 47#endif
48 48
49#include <assert.h> 49#include <assert.h>
50#include <errno.h> 50#include <errno.h>
51#include <fcntl.h> 51#include <fcntl.h>
52#include <stdarg.h> 52#include <stdarg.h>
53#include <stdio.h> 53#include <stdio.h>
54#include <stdlib.h> 54#include <stdlib.h>
55#include <string.h> 55#include <string.h>
56#include <unistd.h> 56#include <unistd.h>
57 57
58#include "makefs.h" 58#include "makefs.h"
59#include "mkfs_msdos.h" 59#include "mkfs_msdos.h"
60 60
61void 61void
62msdos_prep_opts(fsinfo_t *fsopts) 62msdos_prep_opts(fsinfo_t *fsopts)
63{ 63{
64 struct msdos_options *msdos_opts; 64 struct msdos_options *msdos_opts;
65 65
66 if ((msdos_opts = calloc(1, sizeof(*msdos_opts))) == NULL) 66 if ((msdos_opts = calloc(1, sizeof(*msdos_opts))) == NULL)
67 err(1, "Allocating memory for msdos_options"); 67 err(1, "Allocating memory for msdos_options");
68 68
69 fsopts->fs_specific = msdos_opts; 69 fsopts->fs_specific = msdos_opts;
70} 70}
71 71
72void 72void
73msdos_cleanup_opts(fsinfo_t *fsopts) 73msdos_cleanup_opts(fsinfo_t *fsopts)
74{ 74{
75 if (fsopts->fs_specific) 75 if (fsopts->fs_specific)
76 free(fsopts->fs_specific); 76 free(fsopts->fs_specific);
77} 77}
78 78
79int 79int
80msdos_parse_opts(const char *option, fsinfo_t *fsopts) 80msdos_parse_opts(const char *option, fsinfo_t *fsopts)
81{ 81{
82 struct msdos_options *msdos_opt = fsopts->fs_specific; 82 struct msdos_options *msdos_opt = fsopts->fs_specific;
83 83
84 option_t msdos_options[] = { 84 option_t msdos_options[] = {
85#define AOPT(_opt, _type, _name, _min, _desc) { \ 85#define AOPT(_opt, _type, _name, _min, _desc) { \
86 .letter = _opt, \ 86 .letter = _opt, \
87 .name = # _name, \ 87 .name = # _name, \
88 .type = _min == -1 ? OPT_STRPTR : \ 88 .type = _min == -1 ? OPT_STRPTR : \
89 (_min == -2 ? OPT_BOOL : \ 89 (_min == -2 ? OPT_BOOL : \
90 (sizeof(_type) == 1 ? OPT_INT8 : \ 90 (sizeof(_type) == 1 ? OPT_INT8 : \
91 (sizeof(_type) == 2 ? OPT_INT16 : \ 91 (sizeof(_type) == 2 ? OPT_INT16 : \
92 (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \ 92 (sizeof(_type) == 4 ? OPT_INT32 : OPT_INT64)))), \
93 .value = &msdos_opt->_name, \ 93 .value = &msdos_opt->_name, \
94 .minimum = _min, \ 94 .minimum = _min, \
95 .maximum = sizeof(_type) == 1 ? 0xff : \ 95 .maximum = sizeof(_type) == 1 ? 0xff : \
96 (sizeof(_type) == 2 ? 0xffff : \ 96 (sizeof(_type) == 2 ? 0xffff : \
97 (sizeof(_type) == 4 ? 0xffffffff : 0xffffffffffffffffLL)), \ 97 (sizeof(_type) == 4 ? 0xffffffff : 0xffffffffffffffffLL)), \
98 .desc = _desc, \ 98 .desc = _desc, \
99}, 99},
100ALLOPTS 100ALLOPTS
101#undef AOPT  101#undef AOPT
102 { .name = NULL } 102 { .name = NULL }
103 }; 103 };
 104 int i, rv;
104 105
105 assert(option != NULL); 106 assert(option != NULL);
106 assert(fsopts != NULL); 107 assert(fsopts != NULL);
107 assert(msdos_opt != NULL); 108 assert(msdos_opt != NULL);
108 109
109 if (debug & DEBUG_FS_PARSE_OPTS) 110 if (debug & DEBUG_FS_PARSE_OPTS)
110 printf("msdos_parse_opts: got `%s'\n", option); 111 printf("msdos_parse_opts: got `%s'\n", option);
111 112
112 return set_option(msdos_options, option); 113 rv = set_option(msdos_options, option);
 114 if (rv == 0)
 115 return rv;
 116
 117 for (i = 0; msdos_options[i].name != NULL && (1 << i) != rv; i++)
 118 break;
 119 if (msdos_options[i].name == NULL)
 120 abort();
 121
 122 if (strcmp(msdos_options[i].name, "volume_id") == 0)
 123 msdos_opt->volume_id_set = 1;
 124 else if (strcmp(msdos_options[i].name, "media_descriptor") == 0)
 125 msdos_opt->media_descriptor_set = 1;
 126 else if (strcmp(msdos_options[i].name, "hidden_sectors") == 0)
 127 msdos_opt->hidden_sectors_set = 1;
 128 return rv;
113} 129}
114 130
115 131
116void 132void
117msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) 133msdos_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
118{ 134{
119#ifdef notyet 135#ifdef notyet
120 struct fs *superblock; 136 struct fs *superblock;
121 struct timeval start; 137 struct timeval start;
122 138
123 assert(image != NULL); 139 assert(image != NULL);
124 assert(dir != NULL); 140 assert(dir != NULL);
125 assert(root != NULL); 141 assert(root != NULL);
126 assert(fsopts != NULL); 142 assert(fsopts != NULL);
127 143
128 if (debug & DEBUG_FS_MAKEFS) 144 if (debug & DEBUG_FS_MAKEFS)
129 printf("msdos_makefs: image %s directory %s root %p\n", 145 printf("msdos_makefs: image %s directory %s root %p\n",
130 image, dir, root); 146 image, dir, root);
131 147
132 /* validate tree and options */ 148 /* validate tree and options */
133 TIMER_START(start); 149 TIMER_START(start);
134 msdos_validate(dir, root, fsopts); 150 msdos_validate(dir, root, fsopts);
135 TIMER_RESULTS(start, "msdos_validate"); 151 TIMER_RESULTS(start, "msdos_validate");
136 152
137 printf("Calculated size of `%s': %lld bytes, %lld inodes\n", 153 printf("Calculated size of `%s': %lld bytes, %lld inodes\n",
138 image, (long long)fsopts->size, (long long)fsopts->inodes); 154 image, (long long)fsopts->size, (long long)fsopts->inodes);
139 155
140 /* create image */ 156 /* create image */
141 TIMER_START(start); 157 TIMER_START(start);
142 if (msdos_create_image(image, fsopts) == -1) 158 if (msdos_create_image(image, fsopts) == -1)
143 errx(1, "Image file `%s' not created.", image); 159 errx(1, "Image file `%s' not created.", image);
144 TIMER_RESULTS(start, "msdos_create_image"); 160 TIMER_RESULTS(start, "msdos_create_image");
145 161
146 fsopts->curinode = ROOTINO; 162 fsopts->curinode = ROOTINO;
147 163
148 if (debug & DEBUG_FS_MAKEFS) 164 if (debug & DEBUG_FS_MAKEFS)
149 putchar('\n'); 165 putchar('\n');
150 166
151 /* populate image */ 167 /* populate image */
152 printf("Populating `%s'\n", image); 168 printf("Populating `%s'\n", image);
153 TIMER_START(start); 169 TIMER_START(start);
154 if (! msdos_populate_dir(dir, root, fsopts)) 170 if (! msdos_populate_dir(dir, root, fsopts))
155 errx(1, "Image file `%s' not populated.", image); 171 errx(1, "Image file `%s' not populated.", image);
156 TIMER_RESULTS(start, "msdos_populate_dir"); 172 TIMER_RESULTS(start, "msdos_populate_dir");
157 173
158 /* ensure no outstanding buffers remain */ 174 /* ensure no outstanding buffers remain */
159 if (debug & DEBUG_FS_MAKEFS) 175 if (debug & DEBUG_FS_MAKEFS)
160 bcleanup(); 176 bcleanup();
161 177
162 printf("Image `%s' complete\n", image); 178 printf("Image `%s' complete\n", image);
163#endif 179#endif
164} 180}