15978408cSSascha Wildner /* $NetBSD: makefs.h,v 1.20 2008/12/28 21:51:46 christos Exp $ */ 25978408cSSascha Wildner 35978408cSSascha Wildner /*- 45978408cSSascha Wildner * SPDX-License-Identifier: BSD-4-Clause 55978408cSSascha Wildner * 65978408cSSascha Wildner * Copyright (c) 2001 Wasabi Systems, Inc. 75978408cSSascha Wildner * All rights reserved. 85978408cSSascha Wildner * 95978408cSSascha Wildner * Written by Luke Mewburn for Wasabi Systems, Inc. 105978408cSSascha Wildner * 115978408cSSascha Wildner * Redistribution and use in source and binary forms, with or without 125978408cSSascha Wildner * modification, are permitted provided that the following conditions 135978408cSSascha Wildner * are met: 145978408cSSascha Wildner * 1. Redistributions of source code must retain the above copyright 155978408cSSascha Wildner * notice, this list of conditions and the following disclaimer. 165978408cSSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 175978408cSSascha Wildner * notice, this list of conditions and the following disclaimer in the 185978408cSSascha Wildner * documentation and/or other materials provided with the distribution. 195978408cSSascha Wildner * 3. All advertising materials mentioning features or use of this software 205978408cSSascha Wildner * must display the following acknowledgement: 215978408cSSascha Wildner * This product includes software developed for the NetBSD Project by 225978408cSSascha Wildner * Wasabi Systems, Inc. 235978408cSSascha Wildner * 4. The name of Wasabi Systems, Inc. may not be used to endorse 245978408cSSascha Wildner * or promote products derived from this software without specific prior 255978408cSSascha Wildner * written permission. 265978408cSSascha Wildner * 275978408cSSascha Wildner * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 285978408cSSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 295978408cSSascha Wildner * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 305978408cSSascha Wildner * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 315978408cSSascha Wildner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 325978408cSSascha Wildner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 335978408cSSascha Wildner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 345978408cSSascha Wildner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 355978408cSSascha Wildner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 365978408cSSascha Wildner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 375978408cSSascha Wildner * POSSIBILITY OF SUCH DAMAGE. 385978408cSSascha Wildner * 395978408cSSascha Wildner * $FreeBSD: head/usr.sbin/makefs/makefs.h 326276 2017-11-27 15:37:16Z pfg $ 405978408cSSascha Wildner */ 415978408cSSascha Wildner 425978408cSSascha Wildner #ifndef _MAKEFS_H 435978408cSSascha Wildner #define _MAKEFS_H 445978408cSSascha Wildner 455978408cSSascha Wildner #include <sys/stat.h> 465978408cSSascha Wildner #include <err.h> 475978408cSSascha Wildner 485978408cSSascha Wildner /* 495978408cSSascha Wildner * fsnode - 505978408cSSascha Wildner * a component of the tree; contains a filename, a pointer to 515978408cSSascha Wildner * fsinode, optional symlink name, and tree pointers 525978408cSSascha Wildner * 535978408cSSascha Wildner * fsinode - 545978408cSSascha Wildner * equivalent to an inode, containing target file system inode number, 555978408cSSascha Wildner * refcount (nlink), and stat buffer 565978408cSSascha Wildner * 575978408cSSascha Wildner * A tree of fsnodes looks like this: 585978408cSSascha Wildner * 595978408cSSascha Wildner * name "." "bin" "netbsd" 605978408cSSascha Wildner * type S_IFDIR S_IFDIR S_IFREG 615978408cSSascha Wildner * next > > NULL 625978408cSSascha Wildner * parent NULL NULL NULL 635978408cSSascha Wildner * child NULL v 645978408cSSascha Wildner * 655978408cSSascha Wildner * name "." "ls" 665978408cSSascha Wildner * type S_IFDIR S_IFREG 675978408cSSascha Wildner * next > NULL 685978408cSSascha Wildner * parent ^ ^ (to "bin") 695978408cSSascha Wildner * child NULL NULL 705978408cSSascha Wildner * 715978408cSSascha Wildner * Notes: 725978408cSSascha Wildner * - first always points to first entry, at current level, which 735978408cSSascha Wildner * must be "." when the tree has been built; during build it may 745978408cSSascha Wildner * not be if "." hasn't yet been found by readdir(2). 755978408cSSascha Wildner */ 765978408cSSascha Wildner 775978408cSSascha Wildner enum fi_flags { 785978408cSSascha Wildner FI_SIZED = 1<<0, /* inode sized */ 795978408cSSascha Wildner FI_ALLOCATED = 1<<1, /* fsinode->ino allocated */ 805978408cSSascha Wildner FI_WRITTEN = 1<<2, /* inode written */ 815978408cSSascha Wildner }; 825978408cSSascha Wildner 835978408cSSascha Wildner typedef struct { 845978408cSSascha Wildner uint32_t ino; /* inode number used on target fs */ 855978408cSSascha Wildner uint32_t nlink; /* number of links to this entry */ 865978408cSSascha Wildner enum fi_flags flags; /* flags used by fs specific code */ 87*3bffb051STomohiro Kusumi void *param; /* for use by individual fs impls */ 885978408cSSascha Wildner struct stat st; /* stat entry */ 895978408cSSascha Wildner } fsinode; 905978408cSSascha Wildner 915978408cSSascha Wildner typedef struct _fsnode { 925978408cSSascha Wildner struct _fsnode *parent; /* parent (NULL if root) */ 935978408cSSascha Wildner struct _fsnode *child; /* child (if type == S_IFDIR) */ 945978408cSSascha Wildner struct _fsnode *next; /* next */ 955978408cSSascha Wildner struct _fsnode *first; /* first node of current level (".") */ 965978408cSSascha Wildner uint32_t type; /* type of entry */ 975978408cSSascha Wildner fsinode *inode; /* actual inode data */ 985978408cSSascha Wildner char *symlink; /* symlink target */ 995978408cSSascha Wildner char *contents; /* file to provide contents */ 1005978408cSSascha Wildner const char *root; /* root path */ 1015978408cSSascha Wildner char *path; /* directory name */ 1025978408cSSascha Wildner char *name; /* file name */ 1035978408cSSascha Wildner int flags; /* misc flags */ 1045978408cSSascha Wildner } fsnode; 1055978408cSSascha Wildner 1065978408cSSascha Wildner #define FSNODE_F_HASSPEC 0x01 /* fsnode has a spec entry */ 1075978408cSSascha Wildner #define FSNODE_F_OPTIONAL 0x02 /* fsnode is optional */ 1085978408cSSascha Wildner 1095978408cSSascha Wildner /* 1105978408cSSascha Wildner * option_t - contains option name, description, pointer to location to store 1115978408cSSascha Wildner * result, and range checks for the result. Used to simplify fs specific 1125978408cSSascha Wildner * option setting 1135978408cSSascha Wildner */ 1145978408cSSascha Wildner typedef enum { 1155978408cSSascha Wildner OPT_STRARRAY, 1165978408cSSascha Wildner OPT_STRPTR, 1175978408cSSascha Wildner OPT_STRBUF, 1185978408cSSascha Wildner OPT_BOOL, 1195978408cSSascha Wildner OPT_INT8, 1205978408cSSascha Wildner OPT_INT16, 1215978408cSSascha Wildner OPT_INT32, 1225978408cSSascha Wildner OPT_INT64 1235978408cSSascha Wildner } opttype_t; 1245978408cSSascha Wildner 1255978408cSSascha Wildner typedef struct { 1265978408cSSascha Wildner char letter; /* option letter NUL for none */ 1275978408cSSascha Wildner const char *name; /* option name */ 1285978408cSSascha Wildner void *value; /* where to stuff the value */ 1295978408cSSascha Wildner opttype_t type; /* type of entry */ 1305978408cSSascha Wildner long long minimum; /* minimum for value */ 1315978408cSSascha Wildner long long maximum; /* maximum for value */ 1325978408cSSascha Wildner const char *desc; /* option description */ 1335978408cSSascha Wildner } option_t; 1345978408cSSascha Wildner 1355978408cSSascha Wildner /* 1365978408cSSascha Wildner * fsinfo_t - contains various settings and parameters pertaining to 1375978408cSSascha Wildner * the image, including current settings, global options, and fs 1385978408cSSascha Wildner * specific options 1395978408cSSascha Wildner */ 1405978408cSSascha Wildner typedef struct makefs_fsinfo { 1415978408cSSascha Wildner /* current settings */ 1425978408cSSascha Wildner off_t size; /* total size */ 1435978408cSSascha Wildner off_t inodes; /* number of inodes */ 1445978408cSSascha Wildner uint32_t curinode; /* current inode */ 1455978408cSSascha Wildner 1465978408cSSascha Wildner /* image settings */ 1475978408cSSascha Wildner int fd; /* file descriptor of image */ 1485978408cSSascha Wildner void *superblock; /* superblock */ 1495978408cSSascha Wildner int onlyspec; /* only add entries in specfile */ 1505978408cSSascha Wildner 1515978408cSSascha Wildner 1525978408cSSascha Wildner /* global options */ 1535978408cSSascha Wildner off_t minsize; /* minimum size image should be */ 1545978408cSSascha Wildner off_t maxsize; /* maximum size image can be */ 1555978408cSSascha Wildner off_t freefiles; /* free file entries to leave */ 1565978408cSSascha Wildner off_t freeblocks; /* free blocks to leave */ 1575978408cSSascha Wildner off_t offset; /* offset from start of file */ 1585978408cSSascha Wildner off_t roundup; /* round image size up to this value */ 1595978408cSSascha Wildner int freefilepc; /* free file % */ 1605978408cSSascha Wildner int freeblockpc; /* free block % */ 1615978408cSSascha Wildner int needswap; /* non-zero if byte swapping needed */ 1625978408cSSascha Wildner int sectorsize; /* sector size */ 1635978408cSSascha Wildner int sparse; /* sparse image, don't fill it with zeros */ 1645978408cSSascha Wildner 1655978408cSSascha Wildner void *fs_specific; /* File system specific additions. */ 1665978408cSSascha Wildner option_t *fs_options; /* File system specific options */ 1675978408cSSascha Wildner } fsinfo_t; 1685978408cSSascha Wildner 1695978408cSSascha Wildner 1705978408cSSascha Wildner void apply_specfile(const char *, const char *, fsnode *, int); 1715978408cSSascha Wildner void dump_fsnodes(fsnode *); 1725978408cSSascha Wildner const char * inode_type(mode_t); 1735978408cSSascha Wildner fsnode * read_mtree(const char *, fsnode *); 1745978408cSSascha Wildner int set_option(const option_t *, const char *, char *, size_t); 1755978408cSSascha Wildner int set_option_var(const option_t *, const char *, const char *, 1765978408cSSascha Wildner char *, size_t); 1775978408cSSascha Wildner fsnode * walk_dir(const char *, const char *, fsnode *, fsnode *); 1785978408cSSascha Wildner void free_fsnodes(fsnode *); 1795978408cSSascha Wildner option_t * copy_opts(const option_t *); 1805978408cSSascha Wildner 1815978408cSSascha Wildner #define DECLARE_FUN(fs) \ 1825978408cSSascha Wildner void fs ## _prep_opts(fsinfo_t *); \ 1835978408cSSascha Wildner int fs ## _parse_opts(const char *, fsinfo_t *); \ 1845978408cSSascha Wildner void fs ## _cleanup_opts(fsinfo_t *); \ 1855978408cSSascha Wildner void fs ## _makefs(const char *, const char *, fsnode *, fsinfo_t *) 1865978408cSSascha Wildner 1875978408cSSascha Wildner DECLARE_FUN(ffs); 1885978408cSSascha Wildner DECLARE_FUN(cd9660); 18920f6ddd0STomohiro Kusumi DECLARE_FUN(msdos); 1902d60b848STomohiro Kusumi DECLARE_FUN(hammer2); 1915978408cSSascha Wildner 1925978408cSSascha Wildner extern u_int debug; 1935978408cSSascha Wildner extern int dupsok; 1945978408cSSascha Wildner extern struct timespec start_time; 1955978408cSSascha Wildner extern struct stat stampst; 1965978408cSSascha Wildner 1975978408cSSascha Wildner /* 1985978408cSSascha Wildner * If -x is specified, we want to exclude nodes which do not appear 1995978408cSSascha Wildner * in the spec file. 2005978408cSSascha Wildner */ 2015978408cSSascha Wildner #define FSNODE_EXCLUDE_P(opts, fsnode) \ 2025978408cSSascha Wildner ((opts)->onlyspec != 0 && ((fsnode)->flags & FSNODE_F_HASSPEC) == 0) 2035978408cSSascha Wildner 2045978408cSSascha Wildner #define DEBUG_TIME 0x00000001 2055978408cSSascha Wildner /* debug bits 1..3 unused at this time */ 2065978408cSSascha Wildner #define DEBUG_WALK_DIR 0x00000010 2075978408cSSascha Wildner #define DEBUG_WALK_DIR_NODE 0x00000020 2085978408cSSascha Wildner #define DEBUG_WALK_DIR_LINKCHECK 0x00000040 2095978408cSSascha Wildner #define DEBUG_DUMP_FSNODES 0x00000080 2105978408cSSascha Wildner #define DEBUG_DUMP_FSNODES_VERBOSE 0x00000100 2115978408cSSascha Wildner #define DEBUG_FS_PARSE_OPTS 0x00000200 2125978408cSSascha Wildner #define DEBUG_FS_MAKEFS 0x00000400 2135978408cSSascha Wildner #define DEBUG_FS_VALIDATE 0x00000800 2145978408cSSascha Wildner #define DEBUG_FS_CREATE_IMAGE 0x00001000 2155978408cSSascha Wildner #define DEBUG_FS_SIZE_DIR 0x00002000 2165978408cSSascha Wildner #define DEBUG_FS_SIZE_DIR_NODE 0x00004000 2175978408cSSascha Wildner #define DEBUG_FS_SIZE_DIR_ADD_DIRENT 0x00008000 2185978408cSSascha Wildner #define DEBUG_FS_POPULATE 0x00010000 2195978408cSSascha Wildner #define DEBUG_FS_POPULATE_DIRBUF 0x00020000 2205978408cSSascha Wildner #define DEBUG_FS_POPULATE_NODE 0x00040000 2215978408cSSascha Wildner #define DEBUG_FS_WRITE_FILE 0x00080000 2225978408cSSascha Wildner #define DEBUG_FS_WRITE_FILE_BLOCK 0x00100000 2235978408cSSascha Wildner #define DEBUG_FS_MAKE_DIRBUF 0x00200000 2245978408cSSascha Wildner #define DEBUG_FS_WRITE_INODE 0x00400000 2255978408cSSascha Wildner #define DEBUG_BUF_BREAD 0x00800000 2265978408cSSascha Wildner #define DEBUG_BUF_BWRITE 0x01000000 2275978408cSSascha Wildner #define DEBUG_BUF_GETBLK 0x02000000 2285978408cSSascha Wildner #define DEBUG_APPLY_SPECFILE 0x04000000 2295978408cSSascha Wildner #define DEBUG_APPLY_SPECENTRY 0x08000000 2305978408cSSascha Wildner #define DEBUG_APPLY_SPECONLY 0x10000000 23120f6ddd0STomohiro Kusumi #define DEBUG_MSDOSFS 0x20000000 2325978408cSSascha Wildner 2335978408cSSascha Wildner 2345978408cSSascha Wildner #define TIMER_START(x) \ 2355978408cSSascha Wildner if (debug & DEBUG_TIME) \ 2365978408cSSascha Wildner gettimeofday(&(x), NULL) 2375978408cSSascha Wildner 2385978408cSSascha Wildner #define TIMER_RESULTS(x,d) \ 2395978408cSSascha Wildner if (debug & DEBUG_TIME) { \ 2405978408cSSascha Wildner struct timeval end, td; \ 2415978408cSSascha Wildner gettimeofday(&end, NULL); \ 2425978408cSSascha Wildner timersub(&end, &(x), &td); \ 2435978408cSSascha Wildner printf("%s took %lld.%06ld seconds\n", \ 2445978408cSSascha Wildner (d), (long long)td.tv_sec, \ 2455978408cSSascha Wildner (long)td.tv_usec); \ 2465978408cSSascha Wildner } 2475978408cSSascha Wildner 2485978408cSSascha Wildner 2495978408cSSascha Wildner #ifndef DEFAULT_FSTYPE 2505978408cSSascha Wildner #define DEFAULT_FSTYPE "ffs" 2515978408cSSascha Wildner #endif 2525978408cSSascha Wildner 2535978408cSSascha Wildner 2545978408cSSascha Wildner /* 2555978408cSSascha Wildner * ffs specific settings 2565978408cSSascha Wildner * --------------------- 2575978408cSSascha Wildner */ 2585978408cSSascha Wildner 2595978408cSSascha Wildner #define FFS_EI /* for opposite endian support in ffs headers */ 2605978408cSSascha Wildner 2615978408cSSascha Wildner /* 2625978408cSSascha Wildner * Write-arounds/compat shims for endian-agnostic support. 2635978408cSSascha Wildner * These belong in the kernel if/when it's possible to mount 2645978408cSSascha Wildner * filesystems w/ either byte order. 2655978408cSSascha Wildner */ 2665978408cSSascha Wildner 2675978408cSSascha Wildner /* 2685978408cSSascha Wildner * File system internal flags, also in fs_flags. 2695978408cSSascha Wildner * (Pick highest number to avoid conflicts with others) 2705978408cSSascha Wildner */ 2715978408cSSascha Wildner #define FS_SWAPPED 0x80000000 /* file system is endian swapped */ 2725978408cSSascha Wildner #define FS_INTERNAL 0x80000000 /* mask for internal flags */ 2735978408cSSascha Wildner 2745978408cSSascha Wildner #define FS_ISCLEAN 1 2755978408cSSascha Wildner 2765978408cSSascha Wildner #define DINODE1_SIZE (sizeof(struct ufs1_dinode)) 277811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */ 2785978408cSSascha Wildner #define DINODE2_SIZE (sizeof(struct ufs2_dinode)) 279811c2036SSascha Wildner #endif 2805978408cSSascha Wildner 281811c2036SSascha Wildner #ifndef __DragonFly__ 2825978408cSSascha Wildner #define UFS1_MAXSYMLINKLEN ((UFS_NDADDR + UFS_NIADDR) * sizeof(ufs1_daddr_t)) 283811c2036SSascha Wildner #endif 284811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */ 2855978408cSSascha Wildner #define UFS2_MAXSYMLINKLEN ((UFS_NDADDR + UFS_NIADDR) * sizeof(ufs2_daddr_t)) 286811c2036SSascha Wildner #endif 2875978408cSSascha Wildner 2885978408cSSascha Wildner #if (BYTE_ORDER == LITTLE_ENDIAN) 2895978408cSSascha Wildner #define DIRSIZ_SWAP(oldfmt, dp, needswap) \ 2905978408cSSascha Wildner (((oldfmt) && !(needswap)) ? \ 2915978408cSSascha Wildner DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen)) 2925978408cSSascha Wildner #else 2935978408cSSascha Wildner #define DIRSIZ_SWAP(oldfmt, dp, needswap) \ 2945978408cSSascha Wildner (((oldfmt) && (needswap)) ? \ 2955978408cSSascha Wildner DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen)) 2965978408cSSascha Wildner #endif 2975978408cSSascha Wildner 2985978408cSSascha Wildner #define cg_chkmagic_swap(cgp, ns) \ 2995978408cSSascha Wildner (ufs_rw32((cgp)->cg_magic, (ns)) == CG_MAGIC) 3005978408cSSascha Wildner #define cg_inosused_swap(cgp, ns) \ 3015978408cSSascha Wildner ((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_iusedoff, (ns)))) 3025978408cSSascha Wildner #define cg_blksfree_swap(cgp, ns) \ 3035978408cSSascha Wildner ((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_freeoff, (ns)))) 3045978408cSSascha Wildner #define cg_clustersfree_swap(cgp, ns) \ 3055978408cSSascha Wildner ((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_clusteroff, (ns)))) 3065978408cSSascha Wildner #define cg_clustersum_swap(cgp, ns) \ 3075978408cSSascha Wildner ((int32_t *)((uintptr_t)(cgp) + ufs_rw32((cgp)->cg_clustersumoff, ns))) 3085978408cSSascha Wildner 3095978408cSSascha Wildner struct fs; 310c3ba2018STomohiro Kusumi void ffs_fragacct_swap(struct fs *, int, uint32_t [], int, int); 3115978408cSSascha Wildner 3125978408cSSascha Wildner fsinode *link_check(fsinode *); 3135978408cSSascha Wildner 3145978408cSSascha Wildner #endif /* _MAKEFS_H */ 315