/* * linux/fs/hfs/hfs.h * * Copyright (C) 1995-1997 Paul H. Hargrove * This file may be distributed under the terms of the GNU Public License. * * "XXX" in a comment is a note to myself to consider changing something. */ #ifndef _HFS_H #define _HFS_H #include #define HFS_NEW(X) ((X) = hfs_malloc(sizeof(*(X)))) #define HFS_DELETE(X) do { hfs_free((X), sizeof(*(X))); (X) = NULL; } \ while (0) /* offsets to various blocks */ #define HFS_DD_BLK 0 /* Driver Descriptor block */ #define HFS_PMAP_BLK 1 /* First block of partition map */ #define HFS_MDB_BLK 2 /* Block (w/i partition) of MDB */ /* magic numbers for various disk blocks */ #define HFS_DRVR_DESC_MAGIC 0x4552 /* "ER": driver descriptor map */ #define HFS_OLD_PMAP_MAGIC 0x5453 /* "TS": old-type partition map */ #define HFS_NEW_PMAP_MAGIC 0x504D /* "PM": new-type partition map */ #define HFS_SUPER_MAGIC 0x4244 /* "BD": HFS MDB (super block) */ #define HFS_MFS_SUPER_MAGIC 0xD2D7 /* MFS MDB (super block) */ /* magic numbers for various internal structures */ #define HFS_FILE_MAGIC 0x4801 #define HFS_DIR_MAGIC 0x4802 #define HFS_MDB_MAGIC 0x4803 #define HFS_EXT_MAGIC 0x4804 /* XXX currently unused */ #define HFS_BREC_MAGIC 0x4811 /* XXX currently unused */ #define HFS_BTREE_MAGIC 0x4812 #define HFS_BNODE_MAGIC 0x4813 /* various FIXED size parameters */ #define HFS_SECTOR_SIZE 512 /* size of an HFS sector */ #define HFS_SECTOR_SIZE_BITS 9 /* log_2(HFS_SECTOR_SIZE) */ #define HFS_NAMELEN 31 /* maximum length of an HFS filename */ #define HFS_NAMEMAX (3*31) /* max size of ENCODED filename */ #define HFS_BM_MAXBLOCKS (16) /* max number of bitmap blocks */ #define HFS_BM_BPB (8*HFS_SECTOR_SIZE) /* number of bits per bitmap block */ #define HFS_MAX_VALENCE 32767U #define HFS_FORK_MAX (0x7FFFFFFF) /* Meanings of the drAtrb field of the MDB, * Reference: _Inside Macintosh: Files_ p. 2-61 */ #define HFS_SB_ATTRIB_HLOCK 0x0080 #define HFS_SB_ATTRIB_CLEAN 0x0100 #define HFS_SB_ATTRIB_SPARED 0x0200 #define HFS_SB_ATTRIB_SLOCK 0x8000 /* 2**16 - 1 */ #define HFS_USHRT_MAX 65535 /* Some special File ID numbers */ #define HFS_POR_CNID 1 /* Parent Of the Root */ #define HFS_ROOT_CNID 2 /* ROOT directory */ #define HFS_EXT_CNID 3 /* EXTents B-tree */ #define HFS_CAT_CNID 4 /* CATalog B-tree */ #define HFS_BAD_CNID 5 /* BAD blocks file */ #define HFS_ALLOC_CNID 6 /* ALLOCation file (HFS+) */ #define HFS_START_CNID 7 /* STARTup file (HFS+) */ #define HFS_ATTR_CNID 8 /* ATTRibutes file (HFS+) */ #define HFS_EXCH_CNID 15 /* ExchangeFiles temp id */ /* values for hfs_cat_rec.cdrType */ #define HFS_CDR_DIR 0x01 /* folder (directory) */ #define HFS_CDR_FIL 0x02 /* file */ #define HFS_CDR_THD 0x03 /* folder (directory) thread */ #define HFS_CDR_FTH 0x04 /* file thread */ /* legal values for hfs_ext_key.FkType and hfs_file.fork */ #define HFS_FK_DATA 0x00 #define HFS_FK_RSRC 0xFF /* bits in hfs_fil_entry.Flags */ #define HFS_FIL_LOCK 0x01 /* locked */ #define HFS_FIL_THD 0x02 /* file thread */ #define HFS_FIL_DOPEN 0x04 /* data fork open */ #define HFS_FIL_ROPEN 0x08 /* resource fork open */ #define HFS_FIL_DIR 0x10 /* directory (always clear) */ #define HFS_FIL_RSRV1 0x20 /* reserved */ #define HFS_FIL_NOCOPY 0x40 /* copy-protected file */ #define HFS_FIL_USED 0x80 /* open */ /* bits in hfs_dir_entry.Flags. dirflags is 16 bits. */ #define HFS_DIR_LOCK 0x01 /* locked */ #define HFS_DIR_THD 0x02 /* directory thread */ #define HFS_DIR_INEXPFOLDER 0x04 /* in a shared area */ #define HFS_DIR_MOUNTED 0x08 /* mounted */ #define HFS_DIR_DIR 0x10 /* directory (always set) */ #define HFS_DIR_EXPFOLDER 0x20 /* share point */ #define HFS_DIR_RSRV1 0x40 /* reserved */ #define HFS_DIR_RSRV2 0x80 /* reserved */ /* Access types used when requesting access to a B-node */ #define HFS_LOCK_NONE 0x0000 /* Illegal */ #define HFS_LOCK_READ 0x0001 /* read-only access */ #define HFS_LOCK_RESRV 0x0002 /* might potentially modify */ #define HFS_LOCK_WRITE 0x0003 /* will modify now (exclusive access) */ #define HFS_LOCK_MASK 0x000f /* Flags field of the hfs_path_elem */ #define HFS_BPATH_FIRST 0x0100 #define HFS_BPATH_OVERFLOW 0x0200 #define HFS_BPATH_UNDERFLOW 0x0400 #define HFS_BPATH_MASK 0x0f00 /* Flags for hfs_bfind() */ #define HFS_BFIND_EXACT 0x0010 #define HFS_BFIND_LOCK 0x0020 /* Modes for hfs_bfind() */ #define HFS_BFIND_WRITE (HFS_LOCK_RESRV|HFS_BFIND_EXACT|HFS_BFIND_LOCK) #define HFS_BFIND_READ_EQ (HFS_LOCK_READ|HFS_BFIND_EXACT) #define HFS_BFIND_READ_LE (HFS_LOCK_READ) #define HFS_BFIND_INSERT (HFS_LOCK_RESRV|HFS_BPATH_FIRST|HFS_BPATH_OVERFLOW) #define HFS_BFIND_DELETE \ (HFS_LOCK_RESRV|HFS_BFIND_EXACT|HFS_BPATH_FIRST|HFS_BPATH_UNDERFLOW) /*======== HFS structures as they appear on the disk ========*/ /* Pascal-style string of up to 31 characters */ struct hfs_name { hfs_byte_t Len; hfs_byte_t Name[31]; }; typedef struct { hfs_word_t v; hfs_word_t h; } hfs_point_t; typedef struct { hfs_word_t top; hfs_word_t left; hfs_word_t bottom; hfs_word_t right; } hfs_rect_t; typedef struct { hfs_lword_t fdType; hfs_lword_t fdCreator; hfs_word_t fdFlags; hfs_point_t fdLocation; hfs_word_t fdFldr; } hfs_finfo_t; typedef struct { hfs_word_t fdIconID; hfs_byte_t fdUnused[8]; hfs_word_t fdComment; hfs_lword_t fdPutAway; } hfs_fxinfo_t; typedef struct { hfs_rect_t frRect; hfs_word_t frFlags; hfs_point_t frLocation; hfs_word_t frView; } hfs_dinfo_t; typedef struct { hfs_point_t frScroll; hfs_lword_t frOpenChain; hfs_word_t frUnused; hfs_word_t frComment; hfs_lword_t frPutAway; } hfs_dxinfo_t; union hfs_finder_info { struct { hfs_finfo_t finfo; hfs_fxinfo_t fxinfo; } file; struct { hfs_dinfo_t dinfo; hfs_dxinfo_t dxinfo; } dir; }; /* A btree record key on disk */ struct hfs_bkey { hfs_byte_t KeyLen; /* number of bytes in the key */ hfs_byte_t value[1]; /* (KeyLen) bytes of key */ }; /* Cast to a pointer to a generic bkey */ #define HFS_BKEY(X) (((void)((X)->KeyLen)), ((struct hfs_bkey *)(X))) /* The key used in the catalog b-tree: */ struct hfs_cat_key { hfs_byte_t KeyLen; /* number of bytes in the key */ hfs_byte_t Resrv1; /* padding */ hfs_lword_t ParID; /* CNID of the parent dir */ struct hfs_name CName; /* The filename of the entry */ }; /* The key used in the extents b-tree: */ struct hfs_ext_key { hfs_byte_t KeyLen; /* number of bytes in the key */ hfs_byte_t FkType; /* HFS_FK_{DATA,RSRC} */ hfs_lword_t FNum; /* The File ID of the file */ hfs_word_t FABN; /* allocation blocks number*/ }; /*======== Data structures kept in memory ========*/ /* * struct hfs_mdb * * The fields from the MDB of an HFS filesystem */ struct hfs_mdb { int magic; /* A magic number */ unsigned char vname[28]; /* The volume name */ hfs_sysmdb sys_mdb; /* superblock */ hfs_buffer buf; /* The hfs_buffer holding the real superblock (aka VIB or MDB) */ hfs_buffer alt_buf; /* The hfs_buffer holding the alternate superblock */ hfs_buffer bitmap[16]; /* The hfs_buffer holding the allocation bitmap */ struct hfs_btree * ext_tree; /* Information about the extents b-tree */ struct hfs_btree * cat_tree; /* Information about the catalog b-tree */ hfs_u32 file_count; /* The number of regular files in the filesystem */ hfs_u32 dir_count; /* The number of directories in the filesystem */ hfs_u32 next_id; /* The next available file id number */ hfs_u32 clumpablks; /* The number of allocation blocks to try to add when extending a file */ hfs_u32 write_count; /* The number of MDB writes (a sort of version number) */ hfs_u32 fs_start; /* The first 512-byte block represented in the bitmap */ hfs_u32 create_date; /* In network byte-order */ hfs_u32 modify_date; /* In network byte-order */ hfs_u32 backup_date; /* In network byte-order */ hfs_u16 root_files; /* The number of regular (non-directory) files in the root directory */ hfs_u16 root_dirs; /* The number of directories in the root directory */ hfs_u16 fs_ablocks; /* The number of allocation blocks in the filesystem */ hfs_u16 free_ablocks; /* The number of unused allocation blocks in the filesystem */ hfs_u32 alloc_blksz; /* The number of 512-byte blocks per "allocation block" */ hfs_u16 attrib; /* Attribute word */ hfs_wait_queue rename_wait; int rename_lock; hfs_wait_queue bitmap_wait; int bitmap_lock; struct list_head entry_dirty; }; /* * struct hfs_extent * * The offset to allocation block mapping for a given file is * contained in a series of these structures. Each (struct * hfs_extent) records up to three runs of contiguous allocation * blocks. An allocation block is a contiguous group of physical * blocks. */ struct hfs_extent { int magic; /* A magic number */ unsigned short start; /* Where in the file this record begins (in allocation blocks) */ unsigned short end; /* Where in the file this record ends (in allocation blocks) */ unsigned short block[3]; /* The allocation block on disk which begins this extent */ unsigned short length[3]; /* The number of allocation blocks in this extent */ struct hfs_extent *next; /* Next extent record for this file */ struct hfs_extent *prev; /* Previous extent record for this file */ int count; /* Number of times it is used */ }; /* * struct hfs_dir * * This structure holds information specific * to a directory in an HFS filesystem. */ struct hfs_dir { int magic; /* A magic number */ hfs_u16 flags; hfs_u16 dirs; /* Number of directories in this one */ hfs_u16 files; /* Number of files in this directory */ int readers; hfs_wait_queue read_wait; int writers; hfs_wait_queue write_wait; }; /* * struct hfs_fork * * This structure holds the information * specific to a single fork of a file. */ struct hfs_fork { struct hfs_cat_entry *entry; /* The file this fork is part of */ struct hfs_extent first; /* The first extent record for this fork */ struct hfs_extent *cache; /* The most-recently accessed extent record for this fork */ hfs_u32 lsize; /* The logical size in bytes */ hfs_u32 psize; /* The phys size (512-byte blocks) */ hfs_u8 fork; /* Which fork is this? */ }; /* * struct hfs_file * * This structure holds information specific * to a file in an HFS filesystem. */ struct hfs_file { int magic; struct hfs_fork data_fork; struct hfs_fork rsrc_fork; hfs_u16 clumpablks; hfs_u8 flags; }; /* * struct hfs_file * * This structure holds information about a * file or directory in an HFS filesystem. * * 'wait' must remain 1st and 'hash' 2nd since we do some pointer arithmetic. */ struct hfs_cat_entry { hfs_wait_queue wait; struct list_head hash; struct list_head list; struct hfs_mdb *mdb; hfs_sysentry sys_entry; struct hfs_cat_key key; union hfs_finder_info info; hfs_u32 cnid; /* In network byte-order */ hfs_u32 create_date; /* In network byte-order */ hfs_u32 modify_date; /* In network byte-order */ hfs_u32 backup_date; /* In network byte-order */ unsigned short count; unsigned long state; hfs_u8 type; union { struct hfs_dir dir; struct hfs_file file; } u; }; /* hfs entry state bits */ #define HFS_DIRTY 1 #define HFS_KEYDIRTY 2 #define HFS_LOCK 4 #define HFS_DELETED 8 /* * struct hfs_bnode_ref * * A pointer to a (struct hfs_bnode) and the type of lock held on it. */ struct hfs_bnode_ref { struct hfs_bnode *bn; int lock_type; }; /* * struct hfs_belem * * An element of the path from the root of a B-tree to a leaf. * Includes the reference to a (struct hfs_bnode), the index of * the appropriate record in that node, and some flags. */ struct hfs_belem { struct hfs_bnode_ref bnr; int record; int flags; }; /* * struct hfs_brec * * The structure returned by hfs_bfind() to describe the requested record. */ struct hfs_brec { int keep_flags; struct hfs_btree *tree; struct hfs_belem *top; struct hfs_belem *bottom; struct hfs_belem elem[9]; struct hfs_bkey *key; void *data; /* The actual data */ }; /*================ Function prototypes ================*/ /* bdelete.c */ extern int hfs_bdelete(struct hfs_btree *, const struct hfs_bkey *); /* bfind.c */ extern void hfs_brec_relse(struct hfs_brec *, struct hfs_belem *); extern int hfs_bsucc(struct hfs_brec *, int); extern int hfs_bfind(struct hfs_brec *, struct hfs_btree *, const struct hfs_bkey *, int); /* binsert.c */ extern int hfs_binsert(struct hfs_btree *, const struct hfs_bkey *, const void *, hfs_u16); /* bitmap.c */ extern hfs_u16 hfs_vbm_count_free(const struct hfs_mdb *, hfs_u16); extern hfs_u16 hfs_vbm_search_free(const struct hfs_mdb *, hfs_u16 *); extern int hfs_set_vbm_bits(struct hfs_mdb *, hfs_u16, hfs_u16); extern int hfs_clear_vbm_bits(struct hfs_mdb *, hfs_u16, hfs_u16); /* bitops.c */ extern hfs_u32 hfs_find_zero_bit(const hfs_u32 *, hfs_u32, hfs_u32); extern hfs_u32 hfs_count_zero_bits(const hfs_u32 *, hfs_u32, hfs_u32); /* btree.c */ extern struct hfs_btree *hfs_btree_init(struct hfs_mdb *, ino_t, hfs_byte_t *, hfs_u32, hfs_u32); extern void hfs_btree_free(struct hfs_btree *); extern void hfs_btree_commit(struct hfs_btree *, hfs_byte_t *, hfs_lword_t); /* catalog.c */ extern void hfs_cat_init(void); extern void hfs_cat_put(struct hfs_cat_entry *); extern void hfs_cat_mark_dirty(struct hfs_cat_entry *); extern struct hfs_cat_entry *hfs_cat_get(struct hfs_mdb *, const struct hfs_cat_key *); extern void hfs_cat_invalidate(struct hfs_mdb *); extern void hfs_cat_commit(struct hfs_mdb *); extern void hfs_cat_free(void); extern int hfs_cat_compare(const struct hfs_cat_key *, const struct hfs_cat_key *); extern void hfs_cat_build_key(hfs_u32, const struct hfs_name *, struct hfs_cat_key *); extern struct hfs_cat_entry *hfs_cat_parent(struct hfs_cat_entry *); extern int hfs_cat_open(struct hfs_cat_entry *, struct hfs_brec *); extern int hfs_cat_next(struct hfs_cat_entry *, struct hfs_brec *, hfs_u16, hfs_u32 *, hfs_u8 *); extern void hfs_cat_close(struct hfs_cat_entry *, struct hfs_brec *); extern int hfs_cat_create(struct hfs_cat_entry *, struct hfs_cat_key *, hfs_u8, hfs_u32, hfs_u32, struct hfs_cat_entry **); extern int hfs_cat_mkdir(struct hfs_cat_entry *, struct hfs_cat_key *, struct hfs_cat_entry **); extern int hfs_cat_delete(struct hfs_cat_entry *, struct hfs_cat_entry *, int); extern int hfs_cat_move(struct hfs_cat_entry *, struct hfs_cat_entry *, struct hfs_cat_entry *, struct hfs_cat_key *, struct hfs_cat_entry **); /* extent.c */ extern int hfs_ext_compare(const struct hfs_ext_key *, const struct hfs_ext_key *); extern void hfs_extent_in(struct hfs_fork *, const hfs_byte_t *); extern void hfs_extent_out(const struct hfs_fork *, hfs_byte_t *); extern int hfs_extent_map(struct hfs_fork *, int, int); extern void hfs_extent_adj(struct hfs_fork *); extern void hfs_extent_free(struct hfs_fork *); /* mdb.c */ extern struct hfs_mdb *hfs_mdb_get(hfs_sysmdb, int, hfs_s32); extern void hfs_mdb_commit(struct hfs_mdb *, int); extern void hfs_mdb_put(struct hfs_mdb *, int); /* part_tbl.c */ extern int hfs_part_find(hfs_sysmdb, int, int, hfs_s32 *, hfs_s32 *); /* string.c */ extern unsigned int hfs_strhash(const unsigned char *, unsigned int); extern int hfs_strcmp(const unsigned char *, unsigned int, const unsigned char *, unsigned int); extern int hfs_streq(const unsigned char *, unsigned int, const unsigned char *, unsigned int); extern void hfs_tolower(unsigned char *, int); static __inline__ struct dentry *hfs_lookup_dentry(struct dentry *base, const char *name, const int len) { struct qstr this; this.name = name; this.len = len; this.hash = hfs_strhash(name, len); return d_lookup(base, &this); } /* drop a dentry for one of the special directories. * it's in the form of base/name/dentry. */ static __inline__ void hfs_drop_special(struct dentry *base, const struct hfs_name *name, struct dentry *dentry) { struct dentry *dparent, *de; dparent = hfs_lookup_dentry(base, name->Name, name->Len); if (dparent) { de = hfs_lookup_dentry(dparent, dentry->d_name.name, dentry->d_name.len); if (de) { if (!de->d_inode) d_drop(de); dput(de); } dput(dparent); } } extern struct dentry_operations hfs_dentry_operations; #endif