1*0a6a1f1dSLionel Sambuc /* $NetBSD: ffs.c,v 1.64 2015/01/12 19:50:25 christos Exp $ */
29f988b79SJean-Baptiste Boric
39f988b79SJean-Baptiste Boric /*
49f988b79SJean-Baptiste Boric * Copyright (c) 2001 Wasabi Systems, Inc.
59f988b79SJean-Baptiste Boric * All rights reserved.
69f988b79SJean-Baptiste Boric *
79f988b79SJean-Baptiste Boric * Written by Luke Mewburn for Wasabi Systems, Inc.
89f988b79SJean-Baptiste Boric *
99f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
109f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
119f988b79SJean-Baptiste Boric * are met:
129f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
139f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
149f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
159f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
169f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
179f988b79SJean-Baptiste Boric * 3. All advertising materials mentioning features or use of this software
189f988b79SJean-Baptiste Boric * must display the following acknowledgement:
199f988b79SJean-Baptiste Boric * This product includes software developed for the NetBSD Project by
209f988b79SJean-Baptiste Boric * Wasabi Systems, Inc.
219f988b79SJean-Baptiste Boric * 4. The name of Wasabi Systems, Inc. may not be used to endorse
229f988b79SJean-Baptiste Boric * or promote products derived from this software without specific prior
239f988b79SJean-Baptiste Boric * written permission.
249f988b79SJean-Baptiste Boric *
259f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
269f988b79SJean-Baptiste Boric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
279f988b79SJean-Baptiste Boric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
289f988b79SJean-Baptiste Boric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
299f988b79SJean-Baptiste Boric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
309f988b79SJean-Baptiste Boric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
319f988b79SJean-Baptiste Boric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
329f988b79SJean-Baptiste Boric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
339f988b79SJean-Baptiste Boric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
349f988b79SJean-Baptiste Boric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
359f988b79SJean-Baptiste Boric * POSSIBILITY OF SUCH DAMAGE.
369f988b79SJean-Baptiste Boric */
379f988b79SJean-Baptiste Boric /*
389f988b79SJean-Baptiste Boric * Copyright (c) 1982, 1986, 1989, 1993
399f988b79SJean-Baptiste Boric * The Regents of the University of California. All rights reserved.
409f988b79SJean-Baptiste Boric *
419f988b79SJean-Baptiste Boric * Redistribution and use in source and binary forms, with or without
429f988b79SJean-Baptiste Boric * modification, are permitted provided that the following conditions
439f988b79SJean-Baptiste Boric * are met:
449f988b79SJean-Baptiste Boric * 1. Redistributions of source code must retain the above copyright
459f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer.
469f988b79SJean-Baptiste Boric * 2. Redistributions in binary form must reproduce the above copyright
479f988b79SJean-Baptiste Boric * notice, this list of conditions and the following disclaimer in the
489f988b79SJean-Baptiste Boric * documentation and/or other materials provided with the distribution.
499f988b79SJean-Baptiste Boric * 3. Neither the name of the University nor the names of its contributors
509f988b79SJean-Baptiste Boric * may be used to endorse or promote products derived from this software
519f988b79SJean-Baptiste Boric * without specific prior written permission.
529f988b79SJean-Baptiste Boric *
539f988b79SJean-Baptiste Boric * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
549f988b79SJean-Baptiste Boric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
559f988b79SJean-Baptiste Boric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
569f988b79SJean-Baptiste Boric * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
579f988b79SJean-Baptiste Boric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
589f988b79SJean-Baptiste Boric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
599f988b79SJean-Baptiste Boric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
609f988b79SJean-Baptiste Boric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
619f988b79SJean-Baptiste Boric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
629f988b79SJean-Baptiste Boric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
639f988b79SJean-Baptiste Boric * SUCH DAMAGE.
649f988b79SJean-Baptiste Boric *
659f988b79SJean-Baptiste Boric * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
669f988b79SJean-Baptiste Boric */
679f988b79SJean-Baptiste Boric
689f988b79SJean-Baptiste Boric #if HAVE_NBTOOL_CONFIG_H
699f988b79SJean-Baptiste Boric #include "nbtool_config.h"
709f988b79SJean-Baptiste Boric #endif
719f988b79SJean-Baptiste Boric
729f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
739f988b79SJean-Baptiste Boric #if defined(__RCSID) && !defined(__lint)
74*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ffs.c,v 1.64 2015/01/12 19:50:25 christos Exp $");
759f988b79SJean-Baptiste Boric #endif /* !__lint */
769f988b79SJean-Baptiste Boric
779f988b79SJean-Baptiste Boric #include <sys/param.h>
789f988b79SJean-Baptiste Boric
799f988b79SJean-Baptiste Boric #if !HAVE_NBTOOL_CONFIG_H
809f988b79SJean-Baptiste Boric #include <sys/mount.h>
819f988b79SJean-Baptiste Boric #endif
829f988b79SJean-Baptiste Boric
839f988b79SJean-Baptiste Boric #include <assert.h>
849f988b79SJean-Baptiste Boric #include <errno.h>
859f988b79SJean-Baptiste Boric #include <fcntl.h>
869f988b79SJean-Baptiste Boric #include <stdarg.h>
879f988b79SJean-Baptiste Boric #include <stdio.h>
889f988b79SJean-Baptiste Boric #include <stdlib.h>
899f988b79SJean-Baptiste Boric #include <string.h>
909f988b79SJean-Baptiste Boric #include <unistd.h>
919f988b79SJean-Baptiste Boric #include <util.h>
929f988b79SJean-Baptiste Boric
939f988b79SJean-Baptiste Boric #include "makefs.h"
949f988b79SJean-Baptiste Boric #include "ffs.h"
959f988b79SJean-Baptiste Boric
969f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
979f988b79SJean-Baptiste Boric #include <sys/statvfs.h>
989f988b79SJean-Baptiste Boric #endif
999f988b79SJean-Baptiste Boric
1009f988b79SJean-Baptiste Boric #include <ufs/ufs/dinode.h>
1019f988b79SJean-Baptiste Boric #include <ufs/ufs/dir.h>
1029f988b79SJean-Baptiste Boric #include <ufs/ffs/fs.h>
1039f988b79SJean-Baptiste Boric #include <ufs/ufs/ufs_bswap.h>
1049f988b79SJean-Baptiste Boric
1059f988b79SJean-Baptiste Boric #include "ffs/ufs_inode.h"
1069f988b79SJean-Baptiste Boric #include "ffs/newfs_extern.h"
1079f988b79SJean-Baptiste Boric #include "ffs/ffs_extern.h"
1089f988b79SJean-Baptiste Boric
1099f988b79SJean-Baptiste Boric #undef DIP
1109f988b79SJean-Baptiste Boric #define DIP(dp, field) \
1119f988b79SJean-Baptiste Boric ((ffs_opts->version == 1) ? \
1129f988b79SJean-Baptiste Boric (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field)
1139f988b79SJean-Baptiste Boric
1149f988b79SJean-Baptiste Boric /*
1159f988b79SJean-Baptiste Boric * Various file system defaults (cribbed from newfs(8)).
1169f988b79SJean-Baptiste Boric */
1179f988b79SJean-Baptiste Boric #define DFL_FRAGSIZE 1024 /* fragment size */
1189f988b79SJean-Baptiste Boric #define DFL_BLKSIZE 8192 /* block size */
1199f988b79SJean-Baptiste Boric #define DFL_SECSIZE 512 /* sector size */
1209f988b79SJean-Baptiste Boric #define DFL_CYLSPERGROUP 65536 /* cylinders per group */
1219f988b79SJean-Baptiste Boric #define DFL_FRAGSPERINODE 4 /* fragments per inode */
1229f988b79SJean-Baptiste Boric #define DFL_ROTDELAY 0 /* rotational delay */
1239f988b79SJean-Baptiste Boric #define DFL_NRPOS 1 /* rotational positions */
1249f988b79SJean-Baptiste Boric #define DFL_RPM 3600 /* rpm of disk */
1259f988b79SJean-Baptiste Boric #define DFL_NSECTORS 64 /* # of sectors */
1269f988b79SJean-Baptiste Boric #define DFL_NTRACKS 16 /* # of tracks */
1279f988b79SJean-Baptiste Boric
1289f988b79SJean-Baptiste Boric
1299f988b79SJean-Baptiste Boric typedef struct {
1309f988b79SJean-Baptiste Boric u_char *buf; /* buf for directory */
1319f988b79SJean-Baptiste Boric doff_t size; /* full size of buf */
1329f988b79SJean-Baptiste Boric doff_t cur; /* offset of current entry */
1339f988b79SJean-Baptiste Boric } dirbuf_t;
1349f988b79SJean-Baptiste Boric
1359f988b79SJean-Baptiste Boric
1369f988b79SJean-Baptiste Boric static int ffs_create_image(const char *, fsinfo_t *);
1379f988b79SJean-Baptiste Boric static void ffs_dump_fsinfo(fsinfo_t *);
1389f988b79SJean-Baptiste Boric static void ffs_dump_dirbuf(dirbuf_t *, const char *, int);
1399f988b79SJean-Baptiste Boric static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int);
1409f988b79SJean-Baptiste Boric static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
1419f988b79SJean-Baptiste Boric static void ffs_size_dir(fsnode *, fsinfo_t *);
1429f988b79SJean-Baptiste Boric static void ffs_validate(const char *, fsnode *, fsinfo_t *);
1439f988b79SJean-Baptiste Boric static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *);
1449f988b79SJean-Baptiste Boric static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *);
1459f988b79SJean-Baptiste Boric static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *,
1469f988b79SJean-Baptiste Boric fsnode *, fsinfo_t *);
1479f988b79SJean-Baptiste Boric static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
1489f988b79SJean-Baptiste Boric fsnode *, fsinfo_t *);
1499f988b79SJean-Baptiste Boric
1509f988b79SJean-Baptiste Boric
1519f988b79SJean-Baptiste Boric
1529f988b79SJean-Baptiste Boric /* publically visible functions */
1539f988b79SJean-Baptiste Boric void
ffs_prep_opts(fsinfo_t * fsopts)1549f988b79SJean-Baptiste Boric ffs_prep_opts(fsinfo_t *fsopts)
1559f988b79SJean-Baptiste Boric {
1569f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = ecalloc(1, sizeof(*ffs_opts));
1579f988b79SJean-Baptiste Boric
1589f988b79SJean-Baptiste Boric const option_t ffs_options[] = {
1599f988b79SJean-Baptiste Boric { 'b', "bsize", &ffs_opts->bsize, OPT_INT32,
1609f988b79SJean-Baptiste Boric 1, INT_MAX, "block size" },
1619f988b79SJean-Baptiste Boric { 'f', "fsize", &ffs_opts->fsize, OPT_INT32,
1629f988b79SJean-Baptiste Boric 1, INT_MAX, "fragment size" },
1639f988b79SJean-Baptiste Boric { 'd', "density", &ffs_opts->density, OPT_INT32,
1649f988b79SJean-Baptiste Boric 1, INT_MAX, "bytes per inode" },
1659f988b79SJean-Baptiste Boric { 'm', "minfree", &ffs_opts->minfree, OPT_INT32,
1669f988b79SJean-Baptiste Boric 0, 99, "minfree" },
167*0a6a1f1dSLionel Sambuc { 'M', "maxbpg", &ffs_opts->maxbpg, OPT_INT32,
1689f988b79SJean-Baptiste Boric 1, INT_MAX, "max blocks per file in a cg" },
1699f988b79SJean-Baptiste Boric { 'a', "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32,
1709f988b79SJean-Baptiste Boric 1, INT_MAX, "expected average file size" },
1719f988b79SJean-Baptiste Boric { 'n', "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32,
1729f988b79SJean-Baptiste Boric 1, INT_MAX, "expected # of files per directory" },
1739f988b79SJean-Baptiste Boric { 'x', "extent", &ffs_opts->maxbsize, OPT_INT32,
1749f988b79SJean-Baptiste Boric 1, INT_MAX, "maximum # extent size" },
1759f988b79SJean-Baptiste Boric { 'g', "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32,
1769f988b79SJean-Baptiste Boric 1, INT_MAX, "max # of blocks per group" },
1779f988b79SJean-Baptiste Boric { 'v', "version", &ffs_opts->version, OPT_INT32,
1789f988b79SJean-Baptiste Boric 1, 2, "UFS version" },
1799f988b79SJean-Baptiste Boric { 'o', "optimization", NULL, OPT_STRBUF,
1809f988b79SJean-Baptiste Boric 0, 0, "Optimization (time|space)" },
1819f988b79SJean-Baptiste Boric { 'l', "label", ffs_opts->label, OPT_STRARRAY,
1829f988b79SJean-Baptiste Boric 1, sizeof(ffs_opts->label), "UFS label" },
1839f988b79SJean-Baptiste Boric { .name = NULL }
1849f988b79SJean-Baptiste Boric };
1859f988b79SJean-Baptiste Boric
1869f988b79SJean-Baptiste Boric ffs_opts->bsize= -1;
1879f988b79SJean-Baptiste Boric ffs_opts->fsize= -1;
1889f988b79SJean-Baptiste Boric ffs_opts->cpg= -1;
1899f988b79SJean-Baptiste Boric ffs_opts->density= -1;
1909f988b79SJean-Baptiste Boric ffs_opts->minfree= -1;
1919f988b79SJean-Baptiste Boric ffs_opts->optimization= -1;
1929f988b79SJean-Baptiste Boric ffs_opts->maxcontig= -1;
1939f988b79SJean-Baptiste Boric ffs_opts->maxbpg= -1;
1949f988b79SJean-Baptiste Boric ffs_opts->avgfilesize= -1;
1959f988b79SJean-Baptiste Boric ffs_opts->avgfpdir= -1;
1969f988b79SJean-Baptiste Boric ffs_opts->version = 1;
1979f988b79SJean-Baptiste Boric
1989f988b79SJean-Baptiste Boric fsopts->fs_specific = ffs_opts;
1999f988b79SJean-Baptiste Boric fsopts->fs_options = copy_opts(ffs_options);
2009f988b79SJean-Baptiste Boric }
2019f988b79SJean-Baptiste Boric
2029f988b79SJean-Baptiste Boric void
ffs_cleanup_opts(fsinfo_t * fsopts)2039f988b79SJean-Baptiste Boric ffs_cleanup_opts(fsinfo_t *fsopts)
2049f988b79SJean-Baptiste Boric {
2059f988b79SJean-Baptiste Boric free(fsopts->fs_specific);
2069f988b79SJean-Baptiste Boric free(fsopts->fs_options);
2079f988b79SJean-Baptiste Boric }
2089f988b79SJean-Baptiste Boric
2099f988b79SJean-Baptiste Boric int
ffs_parse_opts(const char * option,fsinfo_t * fsopts)2109f988b79SJean-Baptiste Boric ffs_parse_opts(const char *option, fsinfo_t *fsopts)
2119f988b79SJean-Baptiste Boric {
2129f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = fsopts->fs_specific;
2139f988b79SJean-Baptiste Boric option_t *ffs_options = fsopts->fs_options;
2149f988b79SJean-Baptiste Boric char buf[1024];
2159f988b79SJean-Baptiste Boric
2169f988b79SJean-Baptiste Boric int rv;
2179f988b79SJean-Baptiste Boric
2189f988b79SJean-Baptiste Boric assert(option != NULL);
2199f988b79SJean-Baptiste Boric assert(fsopts != NULL);
2209f988b79SJean-Baptiste Boric assert(ffs_opts != NULL);
2219f988b79SJean-Baptiste Boric
2229f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_PARSE_OPTS)
2239f988b79SJean-Baptiste Boric printf("ffs_parse_opts: got `%s'\n", option);
2249f988b79SJean-Baptiste Boric
2259f988b79SJean-Baptiste Boric rv = set_option(ffs_options, option, buf, sizeof(buf));
2269f988b79SJean-Baptiste Boric if (rv == -1)
2279f988b79SJean-Baptiste Boric return 0;
2289f988b79SJean-Baptiste Boric
2299f988b79SJean-Baptiste Boric if (ffs_options[rv].name == NULL)
2309f988b79SJean-Baptiste Boric abort();
2319f988b79SJean-Baptiste Boric
2329f988b79SJean-Baptiste Boric switch (ffs_options[rv].letter) {
2339f988b79SJean-Baptiste Boric case 'o':
2349f988b79SJean-Baptiste Boric if (strcmp(buf, "time") == 0) {
2359f988b79SJean-Baptiste Boric ffs_opts->optimization = FS_OPTTIME;
2369f988b79SJean-Baptiste Boric } else if (strcmp(buf, "space") == 0) {
2379f988b79SJean-Baptiste Boric ffs_opts->optimization = FS_OPTSPACE;
2389f988b79SJean-Baptiste Boric } else {
2399f988b79SJean-Baptiste Boric warnx("Invalid optimization `%s'", buf);
2409f988b79SJean-Baptiste Boric return 0;
2419f988b79SJean-Baptiste Boric }
2429f988b79SJean-Baptiste Boric break;
2439f988b79SJean-Baptiste Boric default:
2449f988b79SJean-Baptiste Boric break;
2459f988b79SJean-Baptiste Boric }
2469f988b79SJean-Baptiste Boric return 1;
2479f988b79SJean-Baptiste Boric }
2489f988b79SJean-Baptiste Boric
2499f988b79SJean-Baptiste Boric
2509f988b79SJean-Baptiste Boric void
ffs_makefs(const char * image,const char * dir,fsnode * root,fsinfo_t * fsopts)2519f988b79SJean-Baptiste Boric ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
2529f988b79SJean-Baptiste Boric {
2539f988b79SJean-Baptiste Boric struct fs *superblock;
2549f988b79SJean-Baptiste Boric struct timeval start;
2559f988b79SJean-Baptiste Boric
2569f988b79SJean-Baptiste Boric assert(image != NULL);
2579f988b79SJean-Baptiste Boric assert(dir != NULL);
2589f988b79SJean-Baptiste Boric assert(root != NULL);
2599f988b79SJean-Baptiste Boric assert(fsopts != NULL);
2609f988b79SJean-Baptiste Boric
2619f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_MAKEFS)
2629f988b79SJean-Baptiste Boric printf("ffs_makefs: image %s directory %s root %p\n",
2639f988b79SJean-Baptiste Boric image, dir, root);
2649f988b79SJean-Baptiste Boric
2659f988b79SJean-Baptiste Boric /* validate tree and options */
2669f988b79SJean-Baptiste Boric TIMER_START(start);
2679f988b79SJean-Baptiste Boric ffs_validate(dir, root, fsopts);
2689f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "ffs_validate");
2699f988b79SJean-Baptiste Boric
2709f988b79SJean-Baptiste Boric printf("Calculated size of `%s': %lld bytes, %lld inodes\n",
2719f988b79SJean-Baptiste Boric image, (long long)fsopts->size, (long long)fsopts->inodes);
2729f988b79SJean-Baptiste Boric
2739f988b79SJean-Baptiste Boric /* create image */
2749f988b79SJean-Baptiste Boric TIMER_START(start);
2759f988b79SJean-Baptiste Boric if (ffs_create_image(image, fsopts) == -1)
2769f988b79SJean-Baptiste Boric errx(1, "Image file `%s' not created.", image);
2779f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "ffs_create_image");
2789f988b79SJean-Baptiste Boric
2799f988b79SJean-Baptiste Boric fsopts->curinode = UFS_ROOTINO;
2809f988b79SJean-Baptiste Boric
2819f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_MAKEFS)
2829f988b79SJean-Baptiste Boric putchar('\n');
2839f988b79SJean-Baptiste Boric
2849f988b79SJean-Baptiste Boric /* populate image */
2859f988b79SJean-Baptiste Boric printf("Populating `%s'\n", image);
2869f988b79SJean-Baptiste Boric TIMER_START(start);
2879f988b79SJean-Baptiste Boric if (! ffs_populate_dir(dir, root, fsopts))
2889f988b79SJean-Baptiste Boric errx(1, "Image file `%s' not populated.", image);
2899f988b79SJean-Baptiste Boric TIMER_RESULTS(start, "ffs_populate_dir");
2909f988b79SJean-Baptiste Boric
2919f988b79SJean-Baptiste Boric /* ensure no outstanding buffers remain */
2929f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_MAKEFS)
2939f988b79SJean-Baptiste Boric bcleanup();
2949f988b79SJean-Baptiste Boric
2959f988b79SJean-Baptiste Boric /* update various superblock parameters */
2969f988b79SJean-Baptiste Boric superblock = fsopts->superblock;
2979f988b79SJean-Baptiste Boric superblock->fs_fmod = 0;
2989f988b79SJean-Baptiste Boric superblock->fs_old_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir;
2999f988b79SJean-Baptiste Boric superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree;
3009f988b79SJean-Baptiste Boric superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree;
3019f988b79SJean-Baptiste Boric superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree;
3029f988b79SJean-Baptiste Boric
3039f988b79SJean-Baptiste Boric /* write out superblock; image is now complete */
3049f988b79SJean-Baptiste Boric ffs_write_superblock(fsopts->superblock, fsopts);
3059f988b79SJean-Baptiste Boric if (close(fsopts->fd) == -1)
3069f988b79SJean-Baptiste Boric err(1, "Closing `%s'", image);
3079f988b79SJean-Baptiste Boric fsopts->fd = -1;
3089f988b79SJean-Baptiste Boric printf("Image `%s' complete\n", image);
3099f988b79SJean-Baptiste Boric }
3109f988b79SJean-Baptiste Boric
3119f988b79SJean-Baptiste Boric /* end of public functions */
3129f988b79SJean-Baptiste Boric
3139f988b79SJean-Baptiste Boric
3149f988b79SJean-Baptiste Boric static void
ffs_validate(const char * dir,fsnode * root,fsinfo_t * fsopts)3159f988b79SJean-Baptiste Boric ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
3169f988b79SJean-Baptiste Boric {
3179f988b79SJean-Baptiste Boric int32_t ncg = 1;
3189f988b79SJean-Baptiste Boric #if notyet
3199f988b79SJean-Baptiste Boric int32_t spc, nspf, ncyl, fssize;
3209f988b79SJean-Baptiste Boric #endif
3219f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = fsopts->fs_specific;
3229f988b79SJean-Baptiste Boric
3239f988b79SJean-Baptiste Boric assert(dir != NULL);
3249f988b79SJean-Baptiste Boric assert(root != NULL);
3259f988b79SJean-Baptiste Boric assert(fsopts != NULL);
3269f988b79SJean-Baptiste Boric assert(ffs_opts != NULL);
3279f988b79SJean-Baptiste Boric
3289f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_VALIDATE) {
3299f988b79SJean-Baptiste Boric printf("ffs_validate: before defaults set:\n");
3309f988b79SJean-Baptiste Boric ffs_dump_fsinfo(fsopts);
3319f988b79SJean-Baptiste Boric }
3329f988b79SJean-Baptiste Boric
3339f988b79SJean-Baptiste Boric /* set FFS defaults */
3349f988b79SJean-Baptiste Boric if (fsopts->sectorsize == -1)
3359f988b79SJean-Baptiste Boric fsopts->sectorsize = DFL_SECSIZE;
3369f988b79SJean-Baptiste Boric if (ffs_opts->fsize == -1)
3379f988b79SJean-Baptiste Boric ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
3389f988b79SJean-Baptiste Boric if (ffs_opts->bsize == -1)
3399f988b79SJean-Baptiste Boric ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize);
3409f988b79SJean-Baptiste Boric if (ffs_opts->cpg == -1)
3419f988b79SJean-Baptiste Boric ffs_opts->cpg = DFL_CYLSPERGROUP;
3429f988b79SJean-Baptiste Boric else
3439f988b79SJean-Baptiste Boric ffs_opts->cpgflg = 1;
3449f988b79SJean-Baptiste Boric /* fsopts->density is set below */
3459f988b79SJean-Baptiste Boric if (ffs_opts->nsectors == -1)
3469f988b79SJean-Baptiste Boric ffs_opts->nsectors = DFL_NSECTORS;
3479f988b79SJean-Baptiste Boric if (ffs_opts->minfree == -1)
3489f988b79SJean-Baptiste Boric ffs_opts->minfree = MINFREE;
3499f988b79SJean-Baptiste Boric if (ffs_opts->optimization == -1)
3509f988b79SJean-Baptiste Boric ffs_opts->optimization = DEFAULTOPT;
3519f988b79SJean-Baptiste Boric if (ffs_opts->maxcontig == -1)
3529f988b79SJean-Baptiste Boric ffs_opts->maxcontig =
3539f988b79SJean-Baptiste Boric MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize);
3549f988b79SJean-Baptiste Boric /* XXX ondisk32 */
3559f988b79SJean-Baptiste Boric if (ffs_opts->maxbpg == -1)
3569f988b79SJean-Baptiste Boric ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t);
3579f988b79SJean-Baptiste Boric if (ffs_opts->avgfilesize == -1)
3589f988b79SJean-Baptiste Boric ffs_opts->avgfilesize = AVFILESIZ;
3599f988b79SJean-Baptiste Boric if (ffs_opts->avgfpdir == -1)
3609f988b79SJean-Baptiste Boric ffs_opts->avgfpdir = AFPDIR;
3619f988b79SJean-Baptiste Boric
3629f988b79SJean-Baptiste Boric /* calculate size of tree */
3639f988b79SJean-Baptiste Boric ffs_size_dir(root, fsopts);
3649f988b79SJean-Baptiste Boric fsopts->inodes += UFS_ROOTINO; /* include first two inodes */
3659f988b79SJean-Baptiste Boric
3669f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_VALIDATE)
3679f988b79SJean-Baptiste Boric printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n",
3689f988b79SJean-Baptiste Boric (long long)fsopts->size, (long long)fsopts->inodes);
3699f988b79SJean-Baptiste Boric
3709f988b79SJean-Baptiste Boric /* add requested slop */
3719f988b79SJean-Baptiste Boric fsopts->size += fsopts->freeblocks;
3729f988b79SJean-Baptiste Boric fsopts->inodes += fsopts->freefiles;
3739f988b79SJean-Baptiste Boric if (fsopts->freefilepc > 0)
3749f988b79SJean-Baptiste Boric fsopts->inodes =
3759f988b79SJean-Baptiste Boric fsopts->inodes * (100 + fsopts->freefilepc) / 100;
3769f988b79SJean-Baptiste Boric if (fsopts->freeblockpc > 0)
3779f988b79SJean-Baptiste Boric fsopts->size =
3789f988b79SJean-Baptiste Boric fsopts->size * (100 + fsopts->freeblockpc) / 100;
3799f988b79SJean-Baptiste Boric
3809f988b79SJean-Baptiste Boric /* add space needed for superblocks */
3819f988b79SJean-Baptiste Boric /*
3829f988b79SJean-Baptiste Boric * The old SBOFF (SBLOCK_UFS1) is used here because makefs is
3839f988b79SJean-Baptiste Boric * typically used for small filesystems where space matters.
3849f988b79SJean-Baptiste Boric * XXX make this an option.
3859f988b79SJean-Baptiste Boric */
3869f988b79SJean-Baptiste Boric fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
3879f988b79SJean-Baptiste Boric /* add space needed to store inodes, x3 for blockmaps, etc */
3889f988b79SJean-Baptiste Boric if (ffs_opts->version == 1)
3899f988b79SJean-Baptiste Boric fsopts->size += ncg * DINODE1_SIZE *
3909f988b79SJean-Baptiste Boric roundup(fsopts->inodes / ncg,
3919f988b79SJean-Baptiste Boric ffs_opts->bsize / DINODE1_SIZE);
3929f988b79SJean-Baptiste Boric else
3939f988b79SJean-Baptiste Boric fsopts->size += ncg * DINODE2_SIZE *
3949f988b79SJean-Baptiste Boric roundup(fsopts->inodes / ncg,
3959f988b79SJean-Baptiste Boric ffs_opts->bsize / DINODE2_SIZE);
3969f988b79SJean-Baptiste Boric
3979f988b79SJean-Baptiste Boric /* add minfree */
3989f988b79SJean-Baptiste Boric if (ffs_opts->minfree > 0)
3999f988b79SJean-Baptiste Boric fsopts->size =
4009f988b79SJean-Baptiste Boric fsopts->size * (100 + ffs_opts->minfree) / 100;
4019f988b79SJean-Baptiste Boric /*
4029f988b79SJean-Baptiste Boric * XXX any other fs slop to add, such as csum's, bitmaps, etc ??
4039f988b79SJean-Baptiste Boric */
4049f988b79SJean-Baptiste Boric
4059f988b79SJean-Baptiste Boric if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */
4069f988b79SJean-Baptiste Boric fsopts->size = fsopts->minsize;
4079f988b79SJean-Baptiste Boric
4089f988b79SJean-Baptiste Boric /* round up to the next block */
4099f988b79SJean-Baptiste Boric fsopts->size = roundup(fsopts->size, ffs_opts->bsize);
4109f988b79SJean-Baptiste Boric
4119f988b79SJean-Baptiste Boric /* calculate density if necessary */
4129f988b79SJean-Baptiste Boric if (ffs_opts->density == -1)
4139f988b79SJean-Baptiste Boric ffs_opts->density = fsopts->size / fsopts->inodes + 1;
4149f988b79SJean-Baptiste Boric
4159f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_VALIDATE) {
4169f988b79SJean-Baptiste Boric printf("ffs_validate: after defaults set:\n");
4179f988b79SJean-Baptiste Boric ffs_dump_fsinfo(fsopts);
4189f988b79SJean-Baptiste Boric printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n",
4199f988b79SJean-Baptiste Boric dir, (long long)fsopts->size, (long long)fsopts->inodes);
4209f988b79SJean-Baptiste Boric }
4219f988b79SJean-Baptiste Boric /* now check calculated sizes vs requested sizes */
4229f988b79SJean-Baptiste Boric if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) {
4239f988b79SJean-Baptiste Boric errx(1, "`%s' size of %lld is larger than the maxsize of %lld.",
4249f988b79SJean-Baptiste Boric dir, (long long)fsopts->size, (long long)fsopts->maxsize);
4259f988b79SJean-Baptiste Boric }
4269f988b79SJean-Baptiste Boric }
4279f988b79SJean-Baptiste Boric
4289f988b79SJean-Baptiste Boric
4299f988b79SJean-Baptiste Boric static void
ffs_dump_fsinfo(fsinfo_t * f)4309f988b79SJean-Baptiste Boric ffs_dump_fsinfo(fsinfo_t *f)
4319f988b79SJean-Baptiste Boric {
4329f988b79SJean-Baptiste Boric
4339f988b79SJean-Baptiste Boric ffs_opt_t *fs = f->fs_specific;
4349f988b79SJean-Baptiste Boric
4359f988b79SJean-Baptiste Boric printf("fsopts at %p\n", f);
4369f988b79SJean-Baptiste Boric
4379f988b79SJean-Baptiste Boric printf("\tsize %lld, inodes %lld, curinode %u\n",
4389f988b79SJean-Baptiste Boric (long long)f->size, (long long)f->inodes, f->curinode);
4399f988b79SJean-Baptiste Boric
4409f988b79SJean-Baptiste Boric printf("\tminsize %lld, maxsize %lld\n",
4419f988b79SJean-Baptiste Boric (long long)f->minsize, (long long)f->maxsize);
4429f988b79SJean-Baptiste Boric printf("\tfree files %lld, freefile %% %d\n",
4439f988b79SJean-Baptiste Boric (long long)f->freefiles, f->freefilepc);
4449f988b79SJean-Baptiste Boric printf("\tfree blocks %lld, freeblock %% %d\n",
4459f988b79SJean-Baptiste Boric (long long)f->freeblocks, f->freeblockpc);
4469f988b79SJean-Baptiste Boric printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize);
4479f988b79SJean-Baptiste Boric
4489f988b79SJean-Baptiste Boric printf("\tbsize %d, fsize %d, cpg %d, density %d\n",
4499f988b79SJean-Baptiste Boric fs->bsize, fs->fsize, fs->cpg, fs->density);
4509f988b79SJean-Baptiste Boric printf("\tnsectors %d, rpm %d, minfree %d\n",
4519f988b79SJean-Baptiste Boric fs->nsectors, fs->rpm, fs->minfree);
4529f988b79SJean-Baptiste Boric printf("\tmaxcontig %d, maxbpg %d\n",
4539f988b79SJean-Baptiste Boric fs->maxcontig, fs->maxbpg);
4549f988b79SJean-Baptiste Boric printf("\toptimization %s\n",
4559f988b79SJean-Baptiste Boric fs->optimization == FS_OPTSPACE ? "space" : "time");
4569f988b79SJean-Baptiste Boric }
4579f988b79SJean-Baptiste Boric
4589f988b79SJean-Baptiste Boric
4599f988b79SJean-Baptiste Boric static int
ffs_create_image(const char * image,fsinfo_t * fsopts)4609f988b79SJean-Baptiste Boric ffs_create_image(const char *image, fsinfo_t *fsopts)
4619f988b79SJean-Baptiste Boric {
4629f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
4639f988b79SJean-Baptiste Boric struct statvfs sfs;
4649f988b79SJean-Baptiste Boric #endif
4659f988b79SJean-Baptiste Boric struct fs *fs;
4669f988b79SJean-Baptiste Boric char *buf;
4679f988b79SJean-Baptiste Boric int i, bufsize;
4689f988b79SJean-Baptiste Boric off_t bufrem;
4699f988b79SJean-Baptiste Boric int oflags = O_RDWR | O_CREAT;
4709f988b79SJean-Baptiste Boric
4719f988b79SJean-Baptiste Boric assert (image != NULL);
4729f988b79SJean-Baptiste Boric assert (fsopts != NULL);
4739f988b79SJean-Baptiste Boric
4749f988b79SJean-Baptiste Boric /* create image */
4759f988b79SJean-Baptiste Boric if (fsopts->offset == 0)
4769f988b79SJean-Baptiste Boric oflags |= O_TRUNC;
4779f988b79SJean-Baptiste Boric if ((fsopts->fd = open(image, oflags, 0666)) == -1) {
4789f988b79SJean-Baptiste Boric warn("Can't open `%s' for writing", image);
4799f988b79SJean-Baptiste Boric return (-1);
4809f988b79SJean-Baptiste Boric }
4819f988b79SJean-Baptiste Boric
4829f988b79SJean-Baptiste Boric /* zero image */
4839f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
4849f988b79SJean-Baptiste Boric if (fstatvfs(fsopts->fd, &sfs) == -1) {
4859f988b79SJean-Baptiste Boric #endif
4869f988b79SJean-Baptiste Boric bufsize = 8192;
4879f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
4889f988b79SJean-Baptiste Boric warn("can't fstatvfs `%s', using default %d byte chunk",
4899f988b79SJean-Baptiste Boric image, bufsize);
4909f988b79SJean-Baptiste Boric } else
4919f988b79SJean-Baptiste Boric bufsize = sfs.f_iosize;
4929f988b79SJean-Baptiste Boric #endif
4939f988b79SJean-Baptiste Boric bufrem = fsopts->size;
4949f988b79SJean-Baptiste Boric
4959f988b79SJean-Baptiste Boric if (fsopts->sparse) {
4969f988b79SJean-Baptiste Boric if (ftruncate(fsopts->fd, bufrem) == -1) {
4979f988b79SJean-Baptiste Boric printf ("ERROR in truncate. Sparse option disabled\n");
4989f988b79SJean-Baptiste Boric fsopts->sparse = 0;
4999f988b79SJean-Baptiste Boric } else {
5009f988b79SJean-Baptiste Boric bufrem = 0; /* File truncated at bufrem. Remaining is 0 */
5019f988b79SJean-Baptiste Boric buf = NULL;
5029f988b79SJean-Baptiste Boric }
5039f988b79SJean-Baptiste Boric }
5049f988b79SJean-Baptiste Boric
5059f988b79SJean-Baptiste Boric if (fsopts->offset != 0)
5069f988b79SJean-Baptiste Boric if (lseek(fsopts->fd, fsopts->offset, SEEK_SET) == -1) {
5079f988b79SJean-Baptiste Boric warn("can't seek");
5089f988b79SJean-Baptiste Boric return -1;
5099f988b79SJean-Baptiste Boric }
5109f988b79SJean-Baptiste Boric
5119f988b79SJean-Baptiste Boric if ((debug & DEBUG_FS_CREATE_IMAGE) && fsopts->sparse == 0)
5129f988b79SJean-Baptiste Boric printf(
5139f988b79SJean-Baptiste Boric "zero-ing image `%s', %lld sectors, using %d byte chunks\n",
5149f988b79SJean-Baptiste Boric image, (long long)bufrem, bufsize);
5159f988b79SJean-Baptiste Boric if (bufrem > 0)
5169f988b79SJean-Baptiste Boric buf = ecalloc(1, bufsize);
5179f988b79SJean-Baptiste Boric while (bufrem > 0) {
5189f988b79SJean-Baptiste Boric i = write(fsopts->fd, buf, MIN(bufsize, bufrem));
5199f988b79SJean-Baptiste Boric if (i == -1) {
5209f988b79SJean-Baptiste Boric warn("zeroing image, %lld bytes to go",
5219f988b79SJean-Baptiste Boric (long long)bufrem);
5229f988b79SJean-Baptiste Boric free(buf);
5239f988b79SJean-Baptiste Boric return (-1);
5249f988b79SJean-Baptiste Boric }
5259f988b79SJean-Baptiste Boric bufrem -= i;
5269f988b79SJean-Baptiste Boric }
5279f988b79SJean-Baptiste Boric if (buf)
5289f988b79SJean-Baptiste Boric free(buf);
5299f988b79SJean-Baptiste Boric
5309f988b79SJean-Baptiste Boric /* make the file system */
5319f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_CREATE_IMAGE)
5329f988b79SJean-Baptiste Boric printf("calling mkfs(\"%s\", ...)\n", image);
5339f988b79SJean-Baptiste Boric fs = ffs_mkfs(image, fsopts);
5349f988b79SJean-Baptiste Boric fsopts->superblock = (void *)fs;
5359f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_CREATE_IMAGE) {
5369f988b79SJean-Baptiste Boric time_t t;
5379f988b79SJean-Baptiste Boric
5389f988b79SJean-Baptiste Boric t = (time_t)((struct fs *)fsopts->superblock)->fs_time;
5399f988b79SJean-Baptiste Boric printf("mkfs returned %p; fs_time %s",
5409f988b79SJean-Baptiste Boric fsopts->superblock, ctime(&t));
5419f988b79SJean-Baptiste Boric printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n",
5429f988b79SJean-Baptiste Boric (long long)fs->fs_cstotal.cs_nbfree,
5439f988b79SJean-Baptiste Boric (long long)fs->fs_cstotal.cs_nffree,
5449f988b79SJean-Baptiste Boric (long long)fs->fs_cstotal.cs_nifree,
5459f988b79SJean-Baptiste Boric (long long)fs->fs_cstotal.cs_ndir);
5469f988b79SJean-Baptiste Boric }
5479f988b79SJean-Baptiste Boric
5489f988b79SJean-Baptiste Boric if ((off_t)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO) < fsopts->inodes) {
5499f988b79SJean-Baptiste Boric warnx(
5509f988b79SJean-Baptiste Boric "Image file `%s' has %lld free inodes; %lld are required.",
5519f988b79SJean-Baptiste Boric image,
5529f988b79SJean-Baptiste Boric (long long)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO),
5539f988b79SJean-Baptiste Boric (long long)fsopts->inodes);
5549f988b79SJean-Baptiste Boric return (-1);
5559f988b79SJean-Baptiste Boric }
5569f988b79SJean-Baptiste Boric return (fsopts->fd);
5579f988b79SJean-Baptiste Boric }
5589f988b79SJean-Baptiste Boric
5599f988b79SJean-Baptiste Boric
5609f988b79SJean-Baptiste Boric static void
ffs_size_dir(fsnode * root,fsinfo_t * fsopts)5619f988b79SJean-Baptiste Boric ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
5629f988b79SJean-Baptiste Boric {
5639f988b79SJean-Baptiste Boric struct direct tmpdir;
5649f988b79SJean-Baptiste Boric fsnode * node;
5659f988b79SJean-Baptiste Boric int curdirsize, this;
5669f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = fsopts->fs_specific;
5679f988b79SJean-Baptiste Boric
5689f988b79SJean-Baptiste Boric /* node may be NULL (empty directory) */
5699f988b79SJean-Baptiste Boric assert(fsopts != NULL);
5709f988b79SJean-Baptiste Boric assert(ffs_opts != NULL);
5719f988b79SJean-Baptiste Boric
5729f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_SIZE_DIR)
5739f988b79SJean-Baptiste Boric printf("ffs_size_dir: entry: bytes %lld inodes %lld\n",
5749f988b79SJean-Baptiste Boric (long long)fsopts->size, (long long)fsopts->inodes);
5759f988b79SJean-Baptiste Boric
5769f988b79SJean-Baptiste Boric #define ADDDIRENT(e) do { \
5779f988b79SJean-Baptiste Boric tmpdir.d_namlen = strlen((e)); \
5789f988b79SJean-Baptiste Boric this = UFS_DIRSIZ(0, &tmpdir, 0); \
5799f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
5809f988b79SJean-Baptiste Boric printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \
5819f988b79SJean-Baptiste Boric e, tmpdir.d_namlen, this, curdirsize); \
5829f988b79SJean-Baptiste Boric if (this + curdirsize > roundup(curdirsize, UFS_DIRBLKSIZ)) \
5839f988b79SJean-Baptiste Boric curdirsize = roundup(curdirsize, UFS_DIRBLKSIZ); \
5849f988b79SJean-Baptiste Boric curdirsize += this; \
5859f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
5869f988b79SJean-Baptiste Boric printf("ADDDIRENT: now: %s (%d) this %d cur %d\n", \
5879f988b79SJean-Baptiste Boric e, tmpdir.d_namlen, this, curdirsize); \
5889f988b79SJean-Baptiste Boric } while (0);
5899f988b79SJean-Baptiste Boric
5909f988b79SJean-Baptiste Boric /*
5919f988b79SJean-Baptiste Boric * XXX this needs to take into account extra space consumed
5929f988b79SJean-Baptiste Boric * by indirect blocks, etc.
5939f988b79SJean-Baptiste Boric */
5949f988b79SJean-Baptiste Boric #define ADDSIZE(x) do { \
5959f988b79SJean-Baptiste Boric fsopts->size += roundup((x), ffs_opts->fsize); \
5969f988b79SJean-Baptiste Boric } while (0);
5979f988b79SJean-Baptiste Boric
5989f988b79SJean-Baptiste Boric curdirsize = 0;
5999f988b79SJean-Baptiste Boric for (node = root; node != NULL; node = node->next) {
6009f988b79SJean-Baptiste Boric ADDDIRENT(node->name);
6019f988b79SJean-Baptiste Boric if (node == root) { /* we're at "." */
6029f988b79SJean-Baptiste Boric assert(strcmp(node->name, ".") == 0);
6039f988b79SJean-Baptiste Boric ADDDIRENT("..");
6049f988b79SJean-Baptiste Boric } else if ((node->inode->flags & FI_SIZED) == 0) {
6059f988b79SJean-Baptiste Boric /* don't count duplicate names */
6069f988b79SJean-Baptiste Boric node->inode->flags |= FI_SIZED;
6079f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_SIZE_DIR_NODE)
6089f988b79SJean-Baptiste Boric printf("ffs_size_dir: `%s' size %lld\n",
6099f988b79SJean-Baptiste Boric node->name,
6109f988b79SJean-Baptiste Boric (long long)node->inode->st.st_size);
6119f988b79SJean-Baptiste Boric fsopts->inodes++;
6129f988b79SJean-Baptiste Boric if (node->type == S_IFREG)
6139f988b79SJean-Baptiste Boric ADDSIZE(node->inode->st.st_size);
6149f988b79SJean-Baptiste Boric if (node->type == S_IFLNK) {
6159f988b79SJean-Baptiste Boric size_t slen;
6169f988b79SJean-Baptiste Boric
6179f988b79SJean-Baptiste Boric slen = strlen(node->symlink) + 1;
6189f988b79SJean-Baptiste Boric if (slen >= (ffs_opts->version == 1 ?
6199f988b79SJean-Baptiste Boric UFS1_MAXSYMLINKLEN :
6209f988b79SJean-Baptiste Boric UFS2_MAXSYMLINKLEN))
6219f988b79SJean-Baptiste Boric ADDSIZE(slen);
6229f988b79SJean-Baptiste Boric }
6239f988b79SJean-Baptiste Boric }
6249f988b79SJean-Baptiste Boric if (node->type == S_IFDIR)
6259f988b79SJean-Baptiste Boric ffs_size_dir(node->child, fsopts);
6269f988b79SJean-Baptiste Boric }
6279f988b79SJean-Baptiste Boric ADDSIZE(curdirsize);
6289f988b79SJean-Baptiste Boric
6299f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_SIZE_DIR)
6309f988b79SJean-Baptiste Boric printf("ffs_size_dir: exit: size %lld inodes %lld\n",
6319f988b79SJean-Baptiste Boric (long long)fsopts->size, (long long)fsopts->inodes);
6329f988b79SJean-Baptiste Boric }
6339f988b79SJean-Baptiste Boric
6349f988b79SJean-Baptiste Boric static void *
ffs_build_dinode1(struct ufs1_dinode * dinp,dirbuf_t * dbufp,fsnode * cur,fsnode * root,fsinfo_t * fsopts)6359f988b79SJean-Baptiste Boric ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
6369f988b79SJean-Baptiste Boric fsnode *root, fsinfo_t *fsopts)
6379f988b79SJean-Baptiste Boric {
6389f988b79SJean-Baptiste Boric size_t slen;
6399f988b79SJean-Baptiste Boric void *membuf;
6409f988b79SJean-Baptiste Boric
6419f988b79SJean-Baptiste Boric memset(dinp, 0, sizeof(*dinp));
6429f988b79SJean-Baptiste Boric dinp->di_mode = cur->inode->st.st_mode;
6439f988b79SJean-Baptiste Boric dinp->di_nlink = cur->inode->nlink;
6449f988b79SJean-Baptiste Boric dinp->di_size = cur->inode->st.st_size;
6459f988b79SJean-Baptiste Boric dinp->di_atime = cur->inode->st.st_atime;
6469f988b79SJean-Baptiste Boric dinp->di_mtime = cur->inode->st.st_mtime;
6479f988b79SJean-Baptiste Boric dinp->di_ctime = cur->inode->st.st_ctime;
6489f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_ST_MTIMENSEC
6499f988b79SJean-Baptiste Boric dinp->di_atimensec = cur->inode->st.st_atimensec;
6509f988b79SJean-Baptiste Boric dinp->di_mtimensec = cur->inode->st.st_mtimensec;
6519f988b79SJean-Baptiste Boric dinp->di_ctimensec = cur->inode->st.st_ctimensec;
6529f988b79SJean-Baptiste Boric #endif
6539f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_ST_FLAGS
6549f988b79SJean-Baptiste Boric dinp->di_flags = cur->inode->st.st_flags;
6559f988b79SJean-Baptiste Boric #endif
6569f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_ST_GEN
6579f988b79SJean-Baptiste Boric dinp->di_gen = cur->inode->st.st_gen;
6589f988b79SJean-Baptiste Boric #endif
6599f988b79SJean-Baptiste Boric dinp->di_uid = cur->inode->st.st_uid;
6609f988b79SJean-Baptiste Boric dinp->di_gid = cur->inode->st.st_gid;
6619f988b79SJean-Baptiste Boric /* not set: di_db, di_ib, di_blocks, di_spare */
6629f988b79SJean-Baptiste Boric
6639f988b79SJean-Baptiste Boric membuf = NULL;
6649f988b79SJean-Baptiste Boric if (cur == root) { /* "."; write dirbuf */
6659f988b79SJean-Baptiste Boric membuf = dbufp->buf;
6669f988b79SJean-Baptiste Boric dinp->di_size = dbufp->size;
6679f988b79SJean-Baptiste Boric } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
6689f988b79SJean-Baptiste Boric dinp->di_size = 0; /* a device */
6699f988b79SJean-Baptiste Boric dinp->di_rdev =
6709f988b79SJean-Baptiste Boric ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
6719f988b79SJean-Baptiste Boric } else if (S_ISLNK(cur->type)) { /* symlink */
6729f988b79SJean-Baptiste Boric slen = strlen(cur->symlink);
6739f988b79SJean-Baptiste Boric if (slen < UFS1_MAXSYMLINKLEN) { /* short link */
6749f988b79SJean-Baptiste Boric memcpy(dinp->di_db, cur->symlink, slen);
6759f988b79SJean-Baptiste Boric } else
6769f988b79SJean-Baptiste Boric membuf = cur->symlink;
6779f988b79SJean-Baptiste Boric dinp->di_size = slen;
6789f988b79SJean-Baptiste Boric }
6799f988b79SJean-Baptiste Boric return membuf;
6809f988b79SJean-Baptiste Boric }
6819f988b79SJean-Baptiste Boric
6829f988b79SJean-Baptiste Boric static void *
ffs_build_dinode2(struct ufs2_dinode * dinp,dirbuf_t * dbufp,fsnode * cur,fsnode * root,fsinfo_t * fsopts)6839f988b79SJean-Baptiste Boric ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
6849f988b79SJean-Baptiste Boric fsnode *root, fsinfo_t *fsopts)
6859f988b79SJean-Baptiste Boric {
6869f988b79SJean-Baptiste Boric size_t slen;
6879f988b79SJean-Baptiste Boric void *membuf;
6889f988b79SJean-Baptiste Boric
6899f988b79SJean-Baptiste Boric memset(dinp, 0, sizeof(*dinp));
6909f988b79SJean-Baptiste Boric dinp->di_mode = cur->inode->st.st_mode;
6919f988b79SJean-Baptiste Boric dinp->di_nlink = cur->inode->nlink;
6929f988b79SJean-Baptiste Boric dinp->di_size = cur->inode->st.st_size;
6939f988b79SJean-Baptiste Boric dinp->di_atime = cur->inode->st.st_atime;
6949f988b79SJean-Baptiste Boric dinp->di_mtime = cur->inode->st.st_mtime;
6959f988b79SJean-Baptiste Boric dinp->di_ctime = cur->inode->st.st_ctime;
6969f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_ST_MTIMENSEC
6979f988b79SJean-Baptiste Boric dinp->di_atimensec = cur->inode->st.st_atimensec;
6989f988b79SJean-Baptiste Boric dinp->di_mtimensec = cur->inode->st.st_mtimensec;
6999f988b79SJean-Baptiste Boric dinp->di_ctimensec = cur->inode->st.st_ctimensec;
7009f988b79SJean-Baptiste Boric #endif
7019f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_ST_FLAGS
7029f988b79SJean-Baptiste Boric dinp->di_flags = cur->inode->st.st_flags;
7039f988b79SJean-Baptiste Boric #endif
7049f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_ST_GEN
7059f988b79SJean-Baptiste Boric dinp->di_gen = cur->inode->st.st_gen;
7069f988b79SJean-Baptiste Boric #endif
7079f988b79SJean-Baptiste Boric #if HAVE_STRUCT_STAT_BIRTHTIME
7089f988b79SJean-Baptiste Boric dinp->di_birthtime = cur->inode->st.st_birthtime;
7099f988b79SJean-Baptiste Boric dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
7109f988b79SJean-Baptiste Boric #endif
7119f988b79SJean-Baptiste Boric dinp->di_uid = cur->inode->st.st_uid;
7129f988b79SJean-Baptiste Boric dinp->di_gid = cur->inode->st.st_gid;
7139f988b79SJean-Baptiste Boric /* not set: di_db, di_ib, di_blocks, di_spare */
7149f988b79SJean-Baptiste Boric
7159f988b79SJean-Baptiste Boric membuf = NULL;
7169f988b79SJean-Baptiste Boric if (cur == root) { /* "."; write dirbuf */
7179f988b79SJean-Baptiste Boric membuf = dbufp->buf;
7189f988b79SJean-Baptiste Boric dinp->di_size = dbufp->size;
7199f988b79SJean-Baptiste Boric } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
7209f988b79SJean-Baptiste Boric dinp->di_size = 0; /* a device */
7219f988b79SJean-Baptiste Boric dinp->di_rdev =
7229f988b79SJean-Baptiste Boric ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap);
7239f988b79SJean-Baptiste Boric } else if (S_ISLNK(cur->type)) { /* symlink */
7249f988b79SJean-Baptiste Boric slen = strlen(cur->symlink);
7259f988b79SJean-Baptiste Boric if (slen < UFS2_MAXSYMLINKLEN) { /* short link */
7269f988b79SJean-Baptiste Boric memcpy(dinp->di_db, cur->symlink, slen);
7279f988b79SJean-Baptiste Boric } else
7289f988b79SJean-Baptiste Boric membuf = cur->symlink;
7299f988b79SJean-Baptiste Boric dinp->di_size = slen;
7309f988b79SJean-Baptiste Boric }
7319f988b79SJean-Baptiste Boric return membuf;
7329f988b79SJean-Baptiste Boric }
7339f988b79SJean-Baptiste Boric
7349f988b79SJean-Baptiste Boric static int
ffs_populate_dir(const char * dir,fsnode * root,fsinfo_t * fsopts)7359f988b79SJean-Baptiste Boric ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
7369f988b79SJean-Baptiste Boric {
7379f988b79SJean-Baptiste Boric fsnode *cur;
7389f988b79SJean-Baptiste Boric dirbuf_t dirbuf;
7399f988b79SJean-Baptiste Boric union dinode din;
7409f988b79SJean-Baptiste Boric void *membuf;
7419f988b79SJean-Baptiste Boric char path[MAXPATHLEN + 1];
7429f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = fsopts->fs_specific;
7439f988b79SJean-Baptiste Boric
7449f988b79SJean-Baptiste Boric assert(dir != NULL);
7459f988b79SJean-Baptiste Boric assert(root != NULL);
7469f988b79SJean-Baptiste Boric assert(fsopts != NULL);
7479f988b79SJean-Baptiste Boric assert(ffs_opts != NULL);
7489f988b79SJean-Baptiste Boric
7499f988b79SJean-Baptiste Boric (void)memset(&dirbuf, 0, sizeof(dirbuf));
7509f988b79SJean-Baptiste Boric
7519f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_POPULATE)
7529f988b79SJean-Baptiste Boric printf("ffs_populate_dir: PASS 1 dir %s node %p\n", dir, root);
7539f988b79SJean-Baptiste Boric
7549f988b79SJean-Baptiste Boric /*
7559f988b79SJean-Baptiste Boric * pass 1: allocate inode numbers, build directory `file'
7569f988b79SJean-Baptiste Boric */
7579f988b79SJean-Baptiste Boric for (cur = root; cur != NULL; cur = cur->next) {
7589f988b79SJean-Baptiste Boric if ((cur->inode->flags & FI_ALLOCATED) == 0) {
7599f988b79SJean-Baptiste Boric cur->inode->flags |= FI_ALLOCATED;
7609f988b79SJean-Baptiste Boric if (cur == root && cur->parent != NULL)
7619f988b79SJean-Baptiste Boric cur->inode->ino = cur->parent->inode->ino;
7629f988b79SJean-Baptiste Boric else {
7639f988b79SJean-Baptiste Boric cur->inode->ino = fsopts->curinode;
7649f988b79SJean-Baptiste Boric fsopts->curinode++;
7659f988b79SJean-Baptiste Boric }
7669f988b79SJean-Baptiste Boric }
7679f988b79SJean-Baptiste Boric ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
7689f988b79SJean-Baptiste Boric if (cur == root) { /* we're at "."; add ".." */
7699f988b79SJean-Baptiste Boric ffs_make_dirbuf(&dirbuf, "..",
7709f988b79SJean-Baptiste Boric cur->parent == NULL ? cur : cur->parent->first,
7719f988b79SJean-Baptiste Boric fsopts->needswap);
7729f988b79SJean-Baptiste Boric root->inode->nlink++; /* count my parent's link */
7739f988b79SJean-Baptiste Boric } else if (cur->child != NULL)
7749f988b79SJean-Baptiste Boric root->inode->nlink++; /* count my child's link */
7759f988b79SJean-Baptiste Boric
7769f988b79SJean-Baptiste Boric /*
7779f988b79SJean-Baptiste Boric * XXX possibly write file and long symlinks here,
7789f988b79SJean-Baptiste Boric * ensuring that blocks get written before inodes?
7799f988b79SJean-Baptiste Boric * otoh, this isn't a real filesystem, so who
7809f988b79SJean-Baptiste Boric * cares about ordering? :-)
7819f988b79SJean-Baptiste Boric */
7829f988b79SJean-Baptiste Boric }
7839f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_POPULATE_DIRBUF)
7849f988b79SJean-Baptiste Boric ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap);
7859f988b79SJean-Baptiste Boric
7869f988b79SJean-Baptiste Boric /*
7879f988b79SJean-Baptiste Boric * pass 2: write out dirbuf, then non-directories at this level
7889f988b79SJean-Baptiste Boric */
7899f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_POPULATE)
7909f988b79SJean-Baptiste Boric printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
7919f988b79SJean-Baptiste Boric for (cur = root; cur != NULL; cur = cur->next) {
7929f988b79SJean-Baptiste Boric if (cur->inode->flags & FI_WRITTEN)
7939f988b79SJean-Baptiste Boric continue; /* skip hard-linked entries */
7949f988b79SJean-Baptiste Boric cur->inode->flags |= FI_WRITTEN;
7959f988b79SJean-Baptiste Boric
7969f988b79SJean-Baptiste Boric if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root,
7979f988b79SJean-Baptiste Boric cur->path, cur->name) >= sizeof(path))
7989f988b79SJean-Baptiste Boric errx(1, "Pathname too long.");
7999f988b79SJean-Baptiste Boric
8009f988b79SJean-Baptiste Boric if (cur->child != NULL)
8019f988b79SJean-Baptiste Boric continue; /* child creates own inode */
8029f988b79SJean-Baptiste Boric
8039f988b79SJean-Baptiste Boric /* build on-disk inode */
8049f988b79SJean-Baptiste Boric if (ffs_opts->version == 1)
8059f988b79SJean-Baptiste Boric membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur,
8069f988b79SJean-Baptiste Boric root, fsopts);
8079f988b79SJean-Baptiste Boric else
8089f988b79SJean-Baptiste Boric membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur,
8099f988b79SJean-Baptiste Boric root, fsopts);
8109f988b79SJean-Baptiste Boric
8119f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_POPULATE_NODE) {
8129f988b79SJean-Baptiste Boric printf("ffs_populate_dir: writing ino %d, %s",
8139f988b79SJean-Baptiste Boric cur->inode->ino, inode_type(cur->type));
8149f988b79SJean-Baptiste Boric if (cur->inode->nlink > 1)
8159f988b79SJean-Baptiste Boric printf(", nlink %d", cur->inode->nlink);
8169f988b79SJean-Baptiste Boric putchar('\n');
8179f988b79SJean-Baptiste Boric }
8189f988b79SJean-Baptiste Boric
8199f988b79SJean-Baptiste Boric if (membuf != NULL) {
8209f988b79SJean-Baptiste Boric ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
8219f988b79SJean-Baptiste Boric } else if (S_ISREG(cur->type)) {
8229f988b79SJean-Baptiste Boric ffs_write_file(&din, cur->inode->ino, path, fsopts);
8239f988b79SJean-Baptiste Boric } else {
8249f988b79SJean-Baptiste Boric assert (! S_ISDIR(cur->type));
8259f988b79SJean-Baptiste Boric ffs_write_inode(&din, cur->inode->ino, fsopts);
8269f988b79SJean-Baptiste Boric }
8279f988b79SJean-Baptiste Boric }
8289f988b79SJean-Baptiste Boric
8299f988b79SJean-Baptiste Boric /*
8309f988b79SJean-Baptiste Boric * pass 3: write out sub-directories
8319f988b79SJean-Baptiste Boric */
8329f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_POPULATE)
8339f988b79SJean-Baptiste Boric printf("ffs_populate_dir: PASS 3 dir %s\n", dir);
8349f988b79SJean-Baptiste Boric for (cur = root; cur != NULL; cur = cur->next) {
8359f988b79SJean-Baptiste Boric if (cur->child == NULL)
8369f988b79SJean-Baptiste Boric continue;
8379f988b79SJean-Baptiste Boric if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir,
8389f988b79SJean-Baptiste Boric cur->name) >= sizeof(path))
8399f988b79SJean-Baptiste Boric errx(1, "Pathname too long.");
8409f988b79SJean-Baptiste Boric if (! ffs_populate_dir(path, cur->child, fsopts))
8419f988b79SJean-Baptiste Boric return (0);
8429f988b79SJean-Baptiste Boric }
8439f988b79SJean-Baptiste Boric
8449f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_POPULATE)
8459f988b79SJean-Baptiste Boric printf("ffs_populate_dir: DONE dir %s\n", dir);
8469f988b79SJean-Baptiste Boric
8479f988b79SJean-Baptiste Boric /* cleanup */
8489f988b79SJean-Baptiste Boric if (dirbuf.buf != NULL)
8499f988b79SJean-Baptiste Boric free(dirbuf.buf);
8509f988b79SJean-Baptiste Boric return (1);
8519f988b79SJean-Baptiste Boric }
8529f988b79SJean-Baptiste Boric
8539f988b79SJean-Baptiste Boric
8549f988b79SJean-Baptiste Boric static void
ffs_write_file(union dinode * din,uint32_t ino,void * buf,fsinfo_t * fsopts)8559f988b79SJean-Baptiste Boric ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
8569f988b79SJean-Baptiste Boric {
8579f988b79SJean-Baptiste Boric int isfile, ffd;
8589f988b79SJean-Baptiste Boric char *fbuf, *p;
8599f988b79SJean-Baptiste Boric off_t bufleft, chunk, offset;
8609f988b79SJean-Baptiste Boric ssize_t nread;
8619f988b79SJean-Baptiste Boric struct inode in;
8629f988b79SJean-Baptiste Boric struct buf * bp;
8639f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = fsopts->fs_specific;
8649f988b79SJean-Baptiste Boric struct vnode vp = { fsopts, NULL };
8659f988b79SJean-Baptiste Boric
8669f988b79SJean-Baptiste Boric assert (din != NULL);
8679f988b79SJean-Baptiste Boric assert (buf != NULL);
8689f988b79SJean-Baptiste Boric assert (fsopts != NULL);
8699f988b79SJean-Baptiste Boric assert (ffs_opts != NULL);
8709f988b79SJean-Baptiste Boric
8719f988b79SJean-Baptiste Boric isfile = S_ISREG(DIP(din, mode));
8729f988b79SJean-Baptiste Boric fbuf = NULL;
8739f988b79SJean-Baptiste Boric ffd = -1;
8749f988b79SJean-Baptiste Boric p = NULL;
8759f988b79SJean-Baptiste Boric
8769f988b79SJean-Baptiste Boric in.i_fs = (struct fs *)fsopts->superblock;
8779f988b79SJean-Baptiste Boric in.i_devvp = &vp;
8789f988b79SJean-Baptiste Boric
8799f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_WRITE_FILE) {
8809f988b79SJean-Baptiste Boric printf(
8819f988b79SJean-Baptiste Boric "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld",
8829f988b79SJean-Baptiste Boric ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT),
8839f988b79SJean-Baptiste Boric (long long)DIP(din, size));
8849f988b79SJean-Baptiste Boric if (isfile)
8859f988b79SJean-Baptiste Boric printf(", file '%s'\n", (char *)buf);
8869f988b79SJean-Baptiste Boric else
8879f988b79SJean-Baptiste Boric printf(", buffer %p\n", buf);
8889f988b79SJean-Baptiste Boric }
8899f988b79SJean-Baptiste Boric
8909f988b79SJean-Baptiste Boric in.i_number = ino;
8919f988b79SJean-Baptiste Boric in.i_size = DIP(din, size);
8929f988b79SJean-Baptiste Boric if (ffs_opts->version == 1)
8939f988b79SJean-Baptiste Boric memcpy(&in.i_din.ffs1_din, &din->ffs1_din,
8949f988b79SJean-Baptiste Boric sizeof(in.i_din.ffs1_din));
8959f988b79SJean-Baptiste Boric else
8969f988b79SJean-Baptiste Boric memcpy(&in.i_din.ffs2_din, &din->ffs2_din,
8979f988b79SJean-Baptiste Boric sizeof(in.i_din.ffs2_din));
8989f988b79SJean-Baptiste Boric
8999f988b79SJean-Baptiste Boric if (DIP(din, size) == 0)
9009f988b79SJean-Baptiste Boric goto write_inode_and_leave; /* mmm, cheating */
9019f988b79SJean-Baptiste Boric
9029f988b79SJean-Baptiste Boric if (isfile) {
9039f988b79SJean-Baptiste Boric fbuf = emalloc(ffs_opts->bsize);
9049f988b79SJean-Baptiste Boric if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) {
9059f988b79SJean-Baptiste Boric warn("Can't open `%s' for reading", (char *)buf);
9069f988b79SJean-Baptiste Boric goto leave_ffs_write_file;
9079f988b79SJean-Baptiste Boric }
9089f988b79SJean-Baptiste Boric } else {
9099f988b79SJean-Baptiste Boric p = buf;
9109f988b79SJean-Baptiste Boric }
9119f988b79SJean-Baptiste Boric
9129f988b79SJean-Baptiste Boric chunk = 0;
9139f988b79SJean-Baptiste Boric for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) {
9149f988b79SJean-Baptiste Boric chunk = MIN(bufleft, ffs_opts->bsize);
9159f988b79SJean-Baptiste Boric if (!isfile)
9169f988b79SJean-Baptiste Boric ;
9179f988b79SJean-Baptiste Boric else if ((nread = read(ffd, fbuf, chunk)) == -1)
9189f988b79SJean-Baptiste Boric err(EXIT_FAILURE, "Reading `%s', %lld bytes to go",
9199f988b79SJean-Baptiste Boric (char *)buf, (long long)bufleft);
9209f988b79SJean-Baptiste Boric else if (nread != chunk)
9219f988b79SJean-Baptiste Boric errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, "
9229f988b79SJean-Baptiste Boric "read %zd bytes, expected %ju bytes, does "
9239f988b79SJean-Baptiste Boric "metalog size= attribute mismatch source size?",
9249f988b79SJean-Baptiste Boric (char *)buf, (long long)bufleft, nread,
9259f988b79SJean-Baptiste Boric (uintmax_t)chunk);
9269f988b79SJean-Baptiste Boric else
9279f988b79SJean-Baptiste Boric p = fbuf;
9289f988b79SJean-Baptiste Boric offset = DIP(din, size) - bufleft;
9299f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_WRITE_FILE_BLOCK)
9309f988b79SJean-Baptiste Boric printf(
9319f988b79SJean-Baptiste Boric "ffs_write_file: write %p offset %lld size %lld left %lld\n",
9329f988b79SJean-Baptiste Boric p, (long long)offset,
9339f988b79SJean-Baptiste Boric (long long)chunk, (long long)bufleft);
9349f988b79SJean-Baptiste Boric /*
9359f988b79SJean-Baptiste Boric * XXX if holey support is desired, do the check here
9369f988b79SJean-Baptiste Boric *
9379f988b79SJean-Baptiste Boric * XXX might need to write out last bit in fragroundup
9389f988b79SJean-Baptiste Boric * sized chunk. however, ffs_balloc() handles this for us
9399f988b79SJean-Baptiste Boric */
9409f988b79SJean-Baptiste Boric errno = ffs_balloc(&in, offset, chunk, &bp);
9419f988b79SJean-Baptiste Boric bad_ffs_write_file:
9429f988b79SJean-Baptiste Boric if (errno != 0)
9439f988b79SJean-Baptiste Boric err(1,
9449f988b79SJean-Baptiste Boric "Writing inode %d (%s), bytes %lld + %lld",
9459f988b79SJean-Baptiste Boric ino,
9469f988b79SJean-Baptiste Boric isfile ? (char *)buf :
9479f988b79SJean-Baptiste Boric inode_type(DIP(din, mode) & S_IFMT),
9489f988b79SJean-Baptiste Boric (long long)offset, (long long)chunk);
9499f988b79SJean-Baptiste Boric memcpy(bp->b_data, p, chunk);
9509f988b79SJean-Baptiste Boric errno = bwrite(bp);
9519f988b79SJean-Baptiste Boric if (errno != 0)
9529f988b79SJean-Baptiste Boric goto bad_ffs_write_file;
9539f988b79SJean-Baptiste Boric if (!isfile)
9549f988b79SJean-Baptiste Boric p += chunk;
9559f988b79SJean-Baptiste Boric }
9569f988b79SJean-Baptiste Boric
9579f988b79SJean-Baptiste Boric write_inode_and_leave:
9589f988b79SJean-Baptiste Boric ffs_write_inode(&in.i_din, in.i_number, fsopts);
9599f988b79SJean-Baptiste Boric
9609f988b79SJean-Baptiste Boric leave_ffs_write_file:
9619f988b79SJean-Baptiste Boric if (fbuf)
9629f988b79SJean-Baptiste Boric free(fbuf);
9639f988b79SJean-Baptiste Boric if (ffd != -1)
9649f988b79SJean-Baptiste Boric close(ffd);
9659f988b79SJean-Baptiste Boric }
9669f988b79SJean-Baptiste Boric
9679f988b79SJean-Baptiste Boric
9689f988b79SJean-Baptiste Boric static void
ffs_dump_dirbuf(dirbuf_t * dbuf,const char * dir,int needswap)9699f988b79SJean-Baptiste Boric ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
9709f988b79SJean-Baptiste Boric {
9719f988b79SJean-Baptiste Boric doff_t i;
9729f988b79SJean-Baptiste Boric struct direct *de;
9739f988b79SJean-Baptiste Boric uint16_t reclen;
9749f988b79SJean-Baptiste Boric
9759f988b79SJean-Baptiste Boric assert (dbuf != NULL);
9769f988b79SJean-Baptiste Boric assert (dir != NULL);
9779f988b79SJean-Baptiste Boric printf("ffs_dump_dirbuf: dir %s size %d cur %d\n",
9789f988b79SJean-Baptiste Boric dir, dbuf->size, dbuf->cur);
9799f988b79SJean-Baptiste Boric
9809f988b79SJean-Baptiste Boric for (i = 0; i < dbuf->size; ) {
9819f988b79SJean-Baptiste Boric de = (struct direct *)(dbuf->buf + i);
9829f988b79SJean-Baptiste Boric reclen = ufs_rw16(de->d_reclen, needswap);
9839f988b79SJean-Baptiste Boric printf(
9849f988b79SJean-Baptiste Boric " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n",
9859f988b79SJean-Baptiste Boric ufs_rw32(de->d_fileno, needswap),
9869f988b79SJean-Baptiste Boric inode_type(DTTOIF(de->d_type)), i, reclen,
9879f988b79SJean-Baptiste Boric de->d_namlen, de->d_name);
9889f988b79SJean-Baptiste Boric i += reclen;
9899f988b79SJean-Baptiste Boric assert(reclen > 0);
9909f988b79SJean-Baptiste Boric }
9919f988b79SJean-Baptiste Boric }
9929f988b79SJean-Baptiste Boric
9939f988b79SJean-Baptiste Boric static void
ffs_make_dirbuf(dirbuf_t * dbuf,const char * name,fsnode * node,int needswap)9949f988b79SJean-Baptiste Boric ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
9959f988b79SJean-Baptiste Boric {
9969f988b79SJean-Baptiste Boric struct direct de, *dp;
9979f988b79SJean-Baptiste Boric uint16_t llen, reclen;
9989f988b79SJean-Baptiste Boric u_char *newbuf;
9999f988b79SJean-Baptiste Boric
10009f988b79SJean-Baptiste Boric assert (dbuf != NULL);
10019f988b79SJean-Baptiste Boric assert (name != NULL);
10029f988b79SJean-Baptiste Boric assert (node != NULL);
10039f988b79SJean-Baptiste Boric /* create direct entry */
10049f988b79SJean-Baptiste Boric (void)memset(&de, 0, sizeof(de));
10059f988b79SJean-Baptiste Boric de.d_fileno = ufs_rw32(node->inode->ino, needswap);
10069f988b79SJean-Baptiste Boric de.d_type = IFTODT(node->type);
10079f988b79SJean-Baptiste Boric de.d_namlen = (uint8_t)strlen(name);
10089f988b79SJean-Baptiste Boric strcpy(de.d_name, name);
10099f988b79SJean-Baptiste Boric reclen = UFS_DIRSIZ(0, &de, needswap);
10109f988b79SJean-Baptiste Boric de.d_reclen = ufs_rw16(reclen, needswap);
10119f988b79SJean-Baptiste Boric
10129f988b79SJean-Baptiste Boric dp = (struct direct *)(dbuf->buf + dbuf->cur);
10139f988b79SJean-Baptiste Boric llen = 0;
10149f988b79SJean-Baptiste Boric if (dp != NULL)
10159f988b79SJean-Baptiste Boric llen = UFS_DIRSIZ(0, dp, needswap);
10169f988b79SJean-Baptiste Boric
10179f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_MAKE_DIRBUF)
10189f988b79SJean-Baptiste Boric printf(
10199f988b79SJean-Baptiste Boric "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n"
10209f988b79SJean-Baptiste Boric " ino %d type %d reclen %d namlen %d name %.30s\n",
10219f988b79SJean-Baptiste Boric dbuf->size, dbuf->cur, llen,
10229f988b79SJean-Baptiste Boric ufs_rw32(de.d_fileno, needswap), de.d_type, reclen,
10239f988b79SJean-Baptiste Boric de.d_namlen, de.d_name);
10249f988b79SJean-Baptiste Boric
10259f988b79SJean-Baptiste Boric if (reclen + dbuf->cur + llen > roundup(dbuf->size, UFS_DIRBLKSIZ)) {
10269f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_MAKE_DIRBUF)
10279f988b79SJean-Baptiste Boric printf("ffs_make_dirbuf: growing buf to %d\n",
10289f988b79SJean-Baptiste Boric dbuf->size + UFS_DIRBLKSIZ);
10299f988b79SJean-Baptiste Boric newbuf = erealloc(dbuf->buf, dbuf->size + UFS_DIRBLKSIZ);
10309f988b79SJean-Baptiste Boric dbuf->buf = newbuf;
10319f988b79SJean-Baptiste Boric dbuf->size += UFS_DIRBLKSIZ;
10329f988b79SJean-Baptiste Boric memset(dbuf->buf + dbuf->size - UFS_DIRBLKSIZ, 0, UFS_DIRBLKSIZ);
10339f988b79SJean-Baptiste Boric dbuf->cur = dbuf->size - UFS_DIRBLKSIZ;
10349f988b79SJean-Baptiste Boric } else if (dp) { /* shrink end of previous */
10359f988b79SJean-Baptiste Boric dp->d_reclen = ufs_rw16(llen,needswap);
10369f988b79SJean-Baptiste Boric dbuf->cur += llen;
10379f988b79SJean-Baptiste Boric }
10389f988b79SJean-Baptiste Boric dp = (struct direct *)(dbuf->buf + dbuf->cur);
10399f988b79SJean-Baptiste Boric memcpy(dp, &de, reclen);
10409f988b79SJean-Baptiste Boric dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap);
10419f988b79SJean-Baptiste Boric }
10429f988b79SJean-Baptiste Boric
10439f988b79SJean-Baptiste Boric /*
10449f988b79SJean-Baptiste Boric * cribbed from sys/ufs/ffs/ffs_alloc.c
10459f988b79SJean-Baptiste Boric */
10469f988b79SJean-Baptiste Boric static void
ffs_write_inode(union dinode * dp,uint32_t ino,const fsinfo_t * fsopts)10479f988b79SJean-Baptiste Boric ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
10489f988b79SJean-Baptiste Boric {
10499f988b79SJean-Baptiste Boric char *buf;
10509f988b79SJean-Baptiste Boric struct ufs1_dinode *dp1;
10519f988b79SJean-Baptiste Boric struct ufs2_dinode *dp2, *dip;
10529f988b79SJean-Baptiste Boric struct cg *cgp;
10539f988b79SJean-Baptiste Boric struct fs *fs;
10549f988b79SJean-Baptiste Boric int cg, cgino, i;
10559f988b79SJean-Baptiste Boric daddr_t d;
10569f988b79SJean-Baptiste Boric char sbbuf[FFS_MAXBSIZE];
10579f988b79SJean-Baptiste Boric uint32_t initediblk;
10589f988b79SJean-Baptiste Boric ffs_opt_t *ffs_opts = fsopts->fs_specific;
10599f988b79SJean-Baptiste Boric
10609f988b79SJean-Baptiste Boric assert (dp != NULL);
10619f988b79SJean-Baptiste Boric assert (ino > 0);
10629f988b79SJean-Baptiste Boric assert (fsopts != NULL);
10639f988b79SJean-Baptiste Boric assert (ffs_opts != NULL);
10649f988b79SJean-Baptiste Boric
10659f988b79SJean-Baptiste Boric fs = (struct fs *)fsopts->superblock;
10669f988b79SJean-Baptiste Boric cg = ino_to_cg(fs, ino);
10679f988b79SJean-Baptiste Boric cgino = ino % fs->fs_ipg;
10689f988b79SJean-Baptiste Boric if (debug & DEBUG_FS_WRITE_INODE)
10699f988b79SJean-Baptiste Boric printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n",
10709f988b79SJean-Baptiste Boric dp, ino, cg, cgino);
10719f988b79SJean-Baptiste Boric
10729f988b79SJean-Baptiste Boric ffs_rdfs(FFS_FSBTODB(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
10739f988b79SJean-Baptiste Boric fsopts);
10749f988b79SJean-Baptiste Boric cgp = (struct cg *)sbbuf;
10759f988b79SJean-Baptiste Boric if (!cg_chkmagic(cgp, fsopts->needswap))
10769f988b79SJean-Baptiste Boric errx(1, "ffs_write_inode: cg %d: bad magic number", cg);
10779f988b79SJean-Baptiste Boric
10789f988b79SJean-Baptiste Boric assert (isclr(cg_inosused(cgp, fsopts->needswap), cgino));
10799f988b79SJean-Baptiste Boric
10809f988b79SJean-Baptiste Boric buf = emalloc(fs->fs_bsize);
10819f988b79SJean-Baptiste Boric dp1 = (struct ufs1_dinode *)buf;
10829f988b79SJean-Baptiste Boric dp2 = (struct ufs2_dinode *)buf;
10839f988b79SJean-Baptiste Boric
10849f988b79SJean-Baptiste Boric if (fs->fs_cstotal.cs_nifree == 0)
10859f988b79SJean-Baptiste Boric errx(1, "ffs_write_inode: fs out of inodes for ino %u",
10869f988b79SJean-Baptiste Boric ino);
10879f988b79SJean-Baptiste Boric if (fs->fs_cs(fs, cg).cs_nifree == 0)
10889f988b79SJean-Baptiste Boric errx(1,
10899f988b79SJean-Baptiste Boric "ffs_write_inode: cg %d out of inodes for ino %u",
10909f988b79SJean-Baptiste Boric cg, ino);
10919f988b79SJean-Baptiste Boric setbit(cg_inosused(cgp, fsopts->needswap), cgino);
10929f988b79SJean-Baptiste Boric ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap);
10939f988b79SJean-Baptiste Boric fs->fs_cstotal.cs_nifree--;
10949f988b79SJean-Baptiste Boric fs->fs_cs(fs, cg).cs_nifree--;
10959f988b79SJean-Baptiste Boric if (S_ISDIR(DIP(dp, mode))) {
10969f988b79SJean-Baptiste Boric ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap);
10979f988b79SJean-Baptiste Boric fs->fs_cstotal.cs_ndir++;
10989f988b79SJean-Baptiste Boric fs->fs_cs(fs, cg).cs_ndir++;
10999f988b79SJean-Baptiste Boric }
11009f988b79SJean-Baptiste Boric
11019f988b79SJean-Baptiste Boric /*
11029f988b79SJean-Baptiste Boric * Initialize inode blocks on the fly for UFS2.
11039f988b79SJean-Baptiste Boric */
11049f988b79SJean-Baptiste Boric initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
11059f988b79SJean-Baptiste Boric if (ffs_opts->version == 2 &&
11069f988b79SJean-Baptiste Boric (uint32_t)(cgino + FFS_INOPB(fs)) > initediblk &&
11079f988b79SJean-Baptiste Boric initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
11089f988b79SJean-Baptiste Boric memset(buf, 0, fs->fs_bsize);
11099f988b79SJean-Baptiste Boric dip = (struct ufs2_dinode *)buf;
11109f988b79SJean-Baptiste Boric srandom(time(NULL));
11119f988b79SJean-Baptiste Boric for (i = 0; i < FFS_INOPB(fs); i++) {
11129f988b79SJean-Baptiste Boric dip->di_gen = random() / 2 + 1;
11139f988b79SJean-Baptiste Boric dip++;
11149f988b79SJean-Baptiste Boric }
11159f988b79SJean-Baptiste Boric ffs_wtfs(FFS_FSBTODB(fs, ino_to_fsba(fs,
11169f988b79SJean-Baptiste Boric cg * fs->fs_ipg + initediblk)),
11179f988b79SJean-Baptiste Boric fs->fs_bsize, buf, fsopts);
11189f988b79SJean-Baptiste Boric initediblk += FFS_INOPB(fs);
11199f988b79SJean-Baptiste Boric cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap);
11209f988b79SJean-Baptiste Boric }
11219f988b79SJean-Baptiste Boric
11229f988b79SJean-Baptiste Boric
11239f988b79SJean-Baptiste Boric ffs_wtfs(FFS_FSBTODB(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
11249f988b79SJean-Baptiste Boric fsopts);
11259f988b79SJean-Baptiste Boric
11269f988b79SJean-Baptiste Boric /* now write inode */
11279f988b79SJean-Baptiste Boric d = FFS_FSBTODB(fs, ino_to_fsba(fs, ino));
11289f988b79SJean-Baptiste Boric ffs_rdfs(d, fs->fs_bsize, buf, fsopts);
11299f988b79SJean-Baptiste Boric if (fsopts->needswap) {
11309f988b79SJean-Baptiste Boric if (ffs_opts->version == 1)
11319f988b79SJean-Baptiste Boric ffs_dinode1_swap(&dp->ffs1_din,
11329f988b79SJean-Baptiste Boric &dp1[ino_to_fsbo(fs, ino)]);
11339f988b79SJean-Baptiste Boric else
11349f988b79SJean-Baptiste Boric ffs_dinode2_swap(&dp->ffs2_din,
11359f988b79SJean-Baptiste Boric &dp2[ino_to_fsbo(fs, ino)]);
11369f988b79SJean-Baptiste Boric } else {
11379f988b79SJean-Baptiste Boric if (ffs_opts->version == 1)
11389f988b79SJean-Baptiste Boric dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din;
11399f988b79SJean-Baptiste Boric else
11409f988b79SJean-Baptiste Boric dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din;
11419f988b79SJean-Baptiste Boric }
11429f988b79SJean-Baptiste Boric ffs_wtfs(d, fs->fs_bsize, buf, fsopts);
11439f988b79SJean-Baptiste Boric free(buf);
11449f988b79SJean-Baptiste Boric }
11459f988b79SJean-Baptiste Boric
11469f988b79SJean-Baptiste Boric void
panic(const char * fmt,...)11479f988b79SJean-Baptiste Boric panic(const char *fmt, ...)
11489f988b79SJean-Baptiste Boric {
11499f988b79SJean-Baptiste Boric va_list ap;
11509f988b79SJean-Baptiste Boric
11519f988b79SJean-Baptiste Boric va_start(ap, fmt);
11529f988b79SJean-Baptiste Boric vwarnx(fmt, ap);
11539f988b79SJean-Baptiste Boric va_end(ap);
11549f988b79SJean-Baptiste Boric exit(1);
11559f988b79SJean-Baptiste Boric }
1156