/* SPDX-License-Identifier: LGPL-3.0-or-later */ /* * super.h - This file is part of libsquashfs * * Copyright (C) 2019 David Oberhollenzer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef SQFS_SUPER_H #define SQFS_SUPER_H #include "sqfs/predef.h" /** * @file super.h * * @brief Contains on-disk data structures, identifiers and functions for the * SquashFS super block. */ #define SQFS_MAGIC 0x73717368 #define SQFS_VERSION_MAJOR 4 #define SQFS_VERSION_MINOR 0 #define SQFS_DEVBLK_SIZE 4096 #define SQFS_DEFAULT_BLOCK_SIZE 131072 /** * @struct sqfs_super_t * * @brief The SquashFS super block, located at the beginning of the file system * to describe the layout of the filesystem. */ struct sqfs_super_t { /** * @brief Magic number. Must be set to SQFS_MAGIC. */ sqfs_u32 magic; /** * @brief Total number of inodes. */ sqfs_u32 inode_count; /** * @brief Last time the filesystem was modified. * * This field counts seconds (not counting leap seconds) since 00:00, * Jan 1 1970 UTC. This field is unsigned, so it expires in the year * 2106 (as opposed to 2038). */ sqfs_u32 modification_time; /** * @brief The data block size in bytes. * * Must be a power of 2, no less than 4k and not larger than 1M. */ sqfs_u32 block_size; /** * @brief The number of fragment blocks in the data area. */ sqfs_u32 fragment_entry_count; /** * @brief Identifies the compressor that has been used. * * Valid identifiers are in the @ref E_SQFS_COMPRESSOR enum. */ sqfs_u16 compression_id; /** * @brief The log2 of the block_size field for sanity checking * * Must be no less than 12 and not larger than 20. */ sqfs_u16 block_log; /** * @brief A combination of @ref E_SQFS_SUPER_FLAGS flags * * Most of the flags that can be set here are informative only. */ sqfs_u16 flags; /** * @brief The total number of unique user or group IDs. */ sqfs_u16 id_count; /** * @brief Must be @ref SQFS_VERSION_MAJOR */ sqfs_u16 version_major; /** * @brief Must be @ref SQFS_VERSION_MINOR */ sqfs_u16 version_minor; /** * @brief A reference to the root inode * * The bits 16 to 48 hold an offset that is added to inode_table_start * to get the location of the meta data block containing the inode. * The lower 16 bits hold a byte offset into the uncompressed block. */ sqfs_u64 root_inode_ref; /** * @brief Total size of the file system in bytes, not counting padding */ sqfs_u64 bytes_used; /** * @brief On-disk location of the ID table * * This value must point to a location after the directory table and * (if present) after the export and fragment tables, but before the * xattr table. */ sqfs_u64 id_table_start; /** * @brief On-disk location of the extended attribute table (if present) * * See @ref sqfs_xattr_reader_t for an overview on how SquashFS stores * extended attributes on disk. * * This value must either point to a location after the ID table, or * it must be set to 0xFFFFFFFF to indicate the table is not present. */ sqfs_u64 xattr_id_table_start; /** * @brief On-disk location of the first meta data block containing * the inodes * * This value must point to a location before the directory table. */ sqfs_u64 inode_table_start; /** * @brief On-disk location of the first meta data block containing * the directory entries * * This value must point to a location after the inode table but * before the fragment, export, ID and xattr tables. */ sqfs_u64 directory_table_start; /** * @brief On-disk location of the fragment table (if present) * * This value must either point to a location after the directory * table, but before the export, ID and xattr tables, or it must be * set to 0xFFFFFFFF to indicate that the table is not present. */ sqfs_u64 fragment_table_start; /** * @brief On-disk location of the export table (if present) * * This value must either point to a location after directory table * (and if present after the fragment table), but before the ID table, * or it must be set to 0xFFFFFFFF to indicate that the table is not * present. */ sqfs_u64 export_table_start; }; /** * @enum E_SQFS_COMPRESSOR * * @brief Set in @ref sqfs_super_t to identify the compresser used by the * filesystem. * * Most of the flags that can be set are informative only. */ typedef enum { SQFS_COMP_GZIP = 1, SQFS_COMP_LZMA = 2, SQFS_COMP_LZO = 3, SQFS_COMP_XZ = 4, SQFS_COMP_LZ4 = 5, SQFS_COMP_ZSTD = 6, SQFS_COMP_MIN = 1, SQFS_COMP_MAX = 6, } E_SQFS_COMPRESSOR; /** * @enum E_SQFS_SUPER_FLAGS * * @brief Flags that can be set in @ref sqfs_super flags field. */ typedef enum { /** * @brief Set to indicate that meta data blocks holding the inodes are * stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_INODES = 0x0001, /** * @brief Set to indicate that all data blocks are stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_DATA = 0x0002, /** * @brief Set to indicate that all fragment blocks are stored * uncompressed. */ SQFS_FLAG_UNCOMPRESSED_FRAGMENTS = 0x0008, /** * @brief Set to indicate that there are no fragment blocks. */ SQFS_FLAG_NO_FRAGMENTS = 0x0010, /** * @brief Set to indicate that fragments have been generated for all * files that are not a multiple of the block size in size. */ SQFS_FLAG_ALWAYS_FRAGMENTS = 0x0020, /** * @brief Set to indicate that data blocks have not been deduplicated. */ SQFS_FLAG_DUPLICATES = 0x0040, /** * @brief Set to indicate that an NFS export table is present. */ SQFS_FLAG_EXPORTABLE = 0x0080, /** * @brief Set to indicate that meta data blocks holding extended * attributes are stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_XATTRS = 0x0100, /** * @brief Set to indicate that the filesystem does not * contain extended attributes. */ SQFS_FLAG_NO_XATTRS = 0x0200, /** * @brief Set to indicate that a single, uncompressed meta data block * with compressor options follows the super block. */ SQFS_FLAG_COMPRESSOR_OPTIONS = 0x0400, /** * @brief Set to indicate that meta data blocks holding the IDs are * stored uncompressed. */ SQFS_FLAG_UNCOMPRESSED_IDS = 0x0800, } E_SQFS_SUPER_FLAGS; #ifdef __cplusplus extern "C" { #endif /** * @brief Initialize the SquashFS super block. * * @memberof sqfs_super_t * * @param super A pointer to a super block structure. * @param block_size The uncompressed size of the data blocks in bytes. * @param mtime The modification time stamp to set. * @param compressor The compressor ID to set. * * @return Zero on success, an @ref E_SQFS_ERROR value if one of the * fields does not hold a valid value. */ SQFS_API int sqfs_super_init(sqfs_super_t *super, size_t block_size, sqfs_u32 mtime, E_SQFS_COMPRESSOR compressor); /** * @brief Encode and write a SquashFS super block to disk. * * @memberof sqfs_super_t * * @param super A pointer to the super block structure to write. * @param file A file object through which to access the filesystem image. * * @return Zero on success, an @ref E_SQFS_ERROR value if one of the * fields does not hold a valid value. */ SQFS_API int sqfs_super_write(const sqfs_super_t *super, sqfs_file_t *file); /** * @brief Read a SquashFS super block from disk, decode it and check the fields * * @memberof sqfs_super_t * * @param super A pointer to the super block structure to fill. * @param file A file object through which to access the filesystem image. * * @return Zero on success, an @ref E_SQFS_ERROR value if one of the * fields does not hold a valid value. */ SQFS_API int sqfs_super_read(sqfs_super_t *super, sqfs_file_t *file); #ifdef __cplusplus } #endif #endif /* SQFS_SUPER_H */