vaseboot/include/VasEBoot/hfsplus.h

258 lines
7.4 KiB
C

/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2008,2009,2012,2013 Free Software Foundation, Inc.
*
* VasEBoot is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VasEBoot 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 General Public License
* along with VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/types.h>
#include <VasEBoot/disk.h>
#define VasEBoot_HFSPLUS_MAGIC 0x482B
#define VasEBoot_HFSPLUSX_MAGIC 0x4858
#define VasEBoot_HFSPLUS_SBLOCK 2
/* A HFS+ extent. */
struct VasEBoot_hfsplus_extent
{
/* The first block of a file on disk. */
VasEBoot_uint32_t start;
/* The amount of blocks described by this extent. */
VasEBoot_uint32_t count;
} VasEBoot_PACKED;
/* The descriptor of a fork. */
struct VasEBoot_hfsplus_forkdata
{
VasEBoot_uint64_t size;
VasEBoot_uint32_t clumpsize;
VasEBoot_uint32_t blocks;
struct VasEBoot_hfsplus_extent extents[8];
} VasEBoot_PACKED;
/* The HFS+ Volume Header. */
struct VasEBoot_hfsplus_volheader
{
VasEBoot_uint16_t magic;
VasEBoot_uint16_t version;
VasEBoot_uint32_t attributes;
VasEBoot_uint8_t unused1[12];
VasEBoot_uint32_t utime;
VasEBoot_uint8_t unused2[16];
VasEBoot_uint32_t blksize;
VasEBoot_uint8_t unused3[36];
VasEBoot_uint32_t ppc_bootdir;
VasEBoot_uint32_t intel_bootfile;
/* Folder opened when disk is mounted. Unused by VasEBoot. */
VasEBoot_uint32_t showfolder;
VasEBoot_uint32_t os9folder;
VasEBoot_uint8_t unused4[4];
VasEBoot_uint32_t osxfolder;
VasEBoot_uint64_t num_serial;
struct VasEBoot_hfsplus_forkdata allocations_file;
struct VasEBoot_hfsplus_forkdata extents_file;
struct VasEBoot_hfsplus_forkdata catalog_file;
struct VasEBoot_hfsplus_forkdata attr_file;
struct VasEBoot_hfsplus_forkdata startup_file;
} VasEBoot_PACKED;
struct VasEBoot_hfsplus_compress_index
{
VasEBoot_uint32_t start;
VasEBoot_uint32_t size;
};
struct VasEBoot_hfsplus_file
{
struct VasEBoot_hfsplus_data *data;
struct VasEBoot_hfsplus_extent extents[8];
struct VasEBoot_hfsplus_extent resource_extents[8];
VasEBoot_uint64_t size;
VasEBoot_uint64_t resource_size;
VasEBoot_uint32_t fileid;
VasEBoot_int32_t mtime;
int compressed;
char *cbuf;
void *file;
struct VasEBoot_hfsplus_compress_index *compress_index;
VasEBoot_uint32_t cbuf_block;
VasEBoot_uint32_t compress_index_size;
};
struct VasEBoot_hfsplus_btree
{
VasEBoot_uint32_t root;
VasEBoot_size_t nodesize;
/* Catalog file node. */
struct VasEBoot_hfsplus_file file;
};
/* Information about a "mounted" HFS+ filesystem. */
struct VasEBoot_hfsplus_data
{
struct VasEBoot_hfsplus_volheader volheader;
VasEBoot_disk_t disk;
unsigned int log2blksize;
struct VasEBoot_hfsplus_btree catalog_tree;
struct VasEBoot_hfsplus_btree extoverflow_tree;
struct VasEBoot_hfsplus_btree attr_tree;
struct VasEBoot_hfsplus_file dirroot;
struct VasEBoot_hfsplus_file opened_file;
/* This is the offset into the physical disk for an embedded HFS+
filesystem (one inside a plain HFS wrapper). */
VasEBoot_disk_addr_t embedded_offset;
int case_sensitive;
};
/* Internal representation of a catalog key. */
struct VasEBoot_hfsplus_catkey_internal
{
VasEBoot_uint32_t parent;
const VasEBoot_uint16_t *name;
VasEBoot_size_t namelen;
};
/* Internal representation of an extent overflow key. */
struct VasEBoot_hfsplus_extkey_internal
{
VasEBoot_uint32_t fileid;
VasEBoot_uint32_t start;
VasEBoot_uint8_t type;
};
struct VasEBoot_hfsplus_attrkey
{
VasEBoot_uint16_t keylen;
VasEBoot_uint16_t unknown1[1];
VasEBoot_uint32_t cnid;
VasEBoot_uint16_t unknown2[2];
VasEBoot_uint16_t namelen;
VasEBoot_uint16_t name[0];
} VasEBoot_PACKED;
struct VasEBoot_hfsplus_attrkey_internal
{
VasEBoot_uint32_t cnid;
const VasEBoot_uint16_t *name;
VasEBoot_size_t namelen;
};
struct VasEBoot_hfsplus_key_internal
{
union
{
struct VasEBoot_hfsplus_extkey_internal extkey;
struct VasEBoot_hfsplus_catkey_internal catkey;
struct VasEBoot_hfsplus_attrkey_internal attrkey;
};
};
/* The on disk layout of a catalog key. */
struct VasEBoot_hfsplus_catkey
{
VasEBoot_uint16_t keylen;
VasEBoot_uint32_t parent;
VasEBoot_uint16_t namelen;
VasEBoot_uint16_t name[0];
} VasEBoot_PACKED;
/* The on disk layout of an extent overflow file key. */
struct VasEBoot_hfsplus_extkey
{
VasEBoot_uint16_t keylen;
VasEBoot_uint8_t type;
VasEBoot_uint8_t unused;
VasEBoot_uint32_t fileid;
VasEBoot_uint32_t start;
} VasEBoot_PACKED;
struct VasEBoot_hfsplus_key
{
union
{
struct VasEBoot_hfsplus_extkey extkey;
struct VasEBoot_hfsplus_catkey catkey;
struct VasEBoot_hfsplus_attrkey attrkey;
VasEBoot_uint16_t keylen;
};
} VasEBoot_PACKED;
struct VasEBoot_hfsplus_btnode
{
VasEBoot_uint32_t next;
VasEBoot_uint32_t prev;
VasEBoot_int8_t type;
VasEBoot_uint8_t height;
VasEBoot_uint16_t count;
VasEBoot_uint16_t unused;
} VasEBoot_PACKED;
/* Return the offset of the record with the index INDEX, in the node
NODE which is part of the B+ tree BTREE. */
static inline VasEBoot_uint16_t
VasEBoot_hfsplus_btree_recoffset (struct VasEBoot_hfsplus_btree *btree,
struct VasEBoot_hfsplus_btnode *node, unsigned index)
{
char *cnode = (char *) node;
void *recptr;
if (btree->nodesize < index * sizeof (VasEBoot_uint16_t) + 2)
index = 0;
recptr = (&cnode[btree->nodesize - index * sizeof (VasEBoot_uint16_t) - 2]);
return VasEBoot_be_to_cpu16 (VasEBoot_get_unaligned16 (recptr));
}
/* Return a pointer to the record with the index INDEX, in the node
NODE which is part of the B+ tree BTREE. */
static inline struct VasEBoot_hfsplus_key *
VasEBoot_hfsplus_btree_recptr (struct VasEBoot_hfsplus_btree *btree,
struct VasEBoot_hfsplus_btnode *node, unsigned index)
{
char *cnode = (char *) node;
VasEBoot_uint16_t offset;
offset = VasEBoot_hfsplus_btree_recoffset (btree, node, index);
if (offset > btree->nodesize - sizeof (struct VasEBoot_hfsplus_key))
offset = 0;
return (struct VasEBoot_hfsplus_key *) &cnode[offset];
}
extern VasEBoot_err_t (*VasEBoot_hfsplus_open_compressed) (struct VasEBoot_hfsplus_file *node);
extern VasEBoot_ssize_t (*VasEBoot_hfsplus_read_compressed) (struct VasEBoot_hfsplus_file *node,
VasEBoot_off_t pos,
VasEBoot_size_t len,
char *buf);
VasEBoot_ssize_t
VasEBoot_hfsplus_read_file (struct VasEBoot_hfsplus_file *node,
VasEBoot_disk_read_hook_t read_hook, void *read_hook_data,
VasEBoot_off_t pos, VasEBoot_size_t len, char *buf);
VasEBoot_err_t
VasEBoot_hfsplus_btree_search (struct VasEBoot_hfsplus_btree *btree,
struct VasEBoot_hfsplus_key_internal *key,
int (*compare_keys) (struct VasEBoot_hfsplus_key *keya,
struct VasEBoot_hfsplus_key_internal *keyb),
struct VasEBoot_hfsplus_btnode **matchnode,
VasEBoot_off_t *keyoffset);
VasEBoot_err_t
VasEBoot_mac_bless_inode (VasEBoot_device_t dev, VasEBoot_uint32_t inode, int is_dir,
int intel);
VasEBoot_err_t
VasEBoot_mac_bless_file (VasEBoot_device_t dev, const char *path_in, int intel);