1 /* Copyright © 2017-2018 Apple Inc. All rights reserved.
6 * Created by Or Haimovich on 18/3/18.
9 #ifndef lf_hfs_catalog_h
10 #define lf_hfs_catalog_h
12 #include "lf_hfs_format.h"
13 #include "lf_hfs_locks.h"
15 #include <sys/queue.h>
17 #define HFS_IDHASH_DEFAULT (64)
20 * Catalog Operations Hint
22 * lower 16 bits: count of B-tree insert operations
23 * upper 16 bits: count of B-tree delete operations
26 #define CAT_DELETE 0x00010000
27 #define CAT_CREATE 0x00000002
28 #define CAT_RENAME 0x00010002
29 #define CAT_EXCHANGE 0x00010002
34 uint64_t uBufferResid
;
36 } ReadDirBuff_s
, *ReadDirBuff_t
;
38 #define READDIR_BUF_OFFSET(buf) (buf->uBufferSize - buf->uBufferResid)
42 * The cat_desc, cat_attr, and cat_fork structures are
43 * use to import/export data to/from the Catalog file.
44 * The fields in these structures are always in BSD
45 * runtime format (e.g. dates and names).
48 typedef u_int32_t cnid_t
;
51 * Catalog Node Descriptor (runtime)
54 u_int8_t cd_flags
; /* see below (8 bits) */
55 u_int8_t cd_encoding
; /* name encoding */
56 int16_t cd_namelen
; /* length of cnode name */
57 cnid_t cd_parentcnid
; /* parent directory CNID */
58 u_int32_t cd_hint
; /* catalog file hint */
59 cnid_t cd_cnid
; /* cnode id (for getattrlist) */
60 const u_int8_t
*cd_nameptr
; /* pointer to cnode name */
65 * CD_EOF is used by hfs_vnop_readdir / cat_getdirentries to indicate EOF was
66 * encountered during a directory enumeration. When this flag is observed
67 * on the next call to hfs_vnop_readdir it tells the caller that there's no
68 * need to descend into the catalog as EOF was encountered during the last call.
69 * This flag should only be set on the descriptor embedded in the directoryhint.
72 #define CD_HASBUF 0x01 /* allocated filename buffer */
73 #define CD_DECOMPOSED 0x02 /* name is fully decomposed */
74 #define CD_EOF 0x04 /* see above */
75 #define CD_ISMETA 0x40 /* describes a metadata file */
76 #define CD_ISDIR 0x80 /* describes a directory */
79 * Catalog Node Attributes (runtime)
82 cnid_t ca_fileid
; /* inode number (for stat) normally == cnid */
83 mode_t ca_mode
; /* file access mode and type (16 bits) */
84 u_int16_t ca_recflags
; /* catalog record flags (16 bit integer) */
85 u_int32_t ca_linkcount
; /* real hard link count */
86 uid_t ca_uid
; /* file owner */
87 gid_t ca_gid
; /* file group */
89 dev_t cau_rdev
; /* special file device (VBLK or VCHAR only) */
90 u_int32_t cau_linkref
; /* hardlink reference number */
92 time_t ca_atime
; /* last access time */
93 time_t ca_atimeondisk
; /* access time value on disk */
94 time_t ca_mtime
; /* last data modification time */
95 time_t ca_ctime
; /* last file status change */
96 time_t ca_itime
; /* file initialization time */
97 time_t ca_btime
; /* last backup time */
98 u_int32_t ca_flags
; /* status flags (chflags) */
100 u_int32_t cau_blocks
; /* total file blocks used (rsrc + data) */
101 u_int32_t cau_entries
; /* total directory entries (valence) */
104 u_int32_t cau_dircount
; /* count of sub dirs (for posix nlink) */
105 u_int32_t cau_firstlink
; /* first hardlink link (files only) */
108 u_int8_t ca_finderinfo
[32]; /* Opaque Finder information */
110 FndrFileInfo ca_finderfileinfo
;
111 struct FndrExtendedFileInfo ca_finderextendedfileinfo
;
114 FndrDirInfo ca_finderdirinfo
;
115 struct FndrExtendedDirInfo ca_finderextendeddirinfo
;
120 /* Aliases for common fields */
121 #define ca_rdev ca_union1.cau_rdev
122 #define ca_linkref ca_union1.cau_linkref
123 #define ca_blocks ca_union2.cau_blocks
124 #define ca_entries ca_union2.cau_entries
125 #define ca_dircount ca_union3.cau_dircount
126 #define ca_firstlink ca_union3.cau_firstlink
127 #define ca_bsdflags ca_flags
130 * Catalog Node Fork (runtime)
132 * NOTE: this is not the same as a struct HFSPlusForkData
134 * NOTE: if cf_new_size > cf_size, then a write is in progress and is extending
135 * the EOF; the new EOF will be cf_new_size. Writes and pageouts may validly
136 * write up to cf_new_size, but reads should only read up to cf_size. When
137 * an extending write is not in progress, cf_new_size is zero.
141 off_t cf_size
; /* fork's logical size in bytes */
142 off_t cf_new_size
; /* fork's logical size after write completes */
144 u_int32_t cfu_clump
; /* fork's clump size in bytes (sys files only) */
145 u_int64_t cfu_bytesread
; /* bytes read from this fork */
147 u_int32_t cf_vblocks
; /* virtual (unalloated) blocks */
148 u_int32_t cf_blocks
; /* total blocks used by this fork */
149 struct HFSPlusExtentDescriptor cf_extents
[8]; /* initial set of extents */
152 * NOTE: If you change this structure, make sure you change you change
157 #define cf_clump cf_union.cfu_clump
158 #define cf_bytesread cf_union.cfu_bytesread
160 #define HFS_MAXDIRHINTS 32
161 #define HFS_DIRHINT_TTL 45
163 #define HFS_INDEX_MASK 0x03ffffff
164 #define HFS_INDEX_BITS 26
166 /* Finder Info's file type and creator for directory hard link alias */
168 kHFSAliasType
= 0x66647270, /* 'fdrp' */
169 kHFSAliasCreator
= 0x4D414353 /* 'MACS' */
174 * Used to hold state across directory enumerations.
177 struct directoryhint
{
178 TAILQ_ENTRY(directoryhint
) dh_link
; /* chain */
179 int dh_index
; /* index into directory (zero relative) */
180 u_int32_t dh_threadhint
; /* node hint of a directory's thread record */
182 struct cat_desc dh_desc
; /* entry's descriptor */
184 typedef struct directoryhint directoryhint_t
;
187 * The size of cat_cookie_t must match the size of
188 * the nreserve struct (in BTreeNodeReserve.c).
190 typedef struct cat_cookie_t
{
191 #if defined(__LP64__)
198 /* Universal catalog key */
200 HFSPlusCatalogKey hfsPlus
;
202 typedef union CatalogKey CatalogKey
;
204 /* Universal catalog data record */
205 union CatalogRecord
{
207 HFSPlusCatalogFolder hfsPlusFolder
;
208 HFSPlusCatalogFile hfsPlusFile
;
209 HFSPlusCatalogThread hfsPlusThread
;
211 typedef union CatalogRecord CatalogRecord
;
216 * A cat_entry is used for bulk enumerations (hfs_readdirattr).
219 struct cat_desc ce_desc
;
220 struct cat_attr ce_attr
;
223 u_int32_t ce_datablks
;
224 u_int32_t ce_rsrcblks
;
228 * Catalog Node Entry List
230 * A cat_entrylist is a list of Catalog Node Entries.
232 struct cat_entrylist
{
233 u_int32_t maxentries
; /* number of entries requested */
234 u_int32_t realentries
; /* number of valid entries returned */
235 u_int32_t skipentries
; /* number of entries skipped (reserved HFS+ files) */
236 struct cat_entry entry
[1]; /* array of entries */
239 #define CE_LIST_SIZE(entries) \
240 sizeof (*ce_list) + (((entries) - 1) * sizeof (struct cat_entry))
243 typedef struct cat_preflightid
{
245 LIST_ENTRY(cat_preflightid
) id_hash
;
248 void hfs_idhash_init (struct hfsmount
*hfsmp
);
249 void hfs_idhash_destroy (struct hfsmount
*hfsmp
);
251 int cat_binarykeycompare( HFSPlusCatalogKey
*searchKey
, HFSPlusCatalogKey
*trialKey
);
252 int CompareExtendedCatalogKeys( HFSPlusCatalogKey
*searchKey
, HFSPlusCatalogKey
*trialKey
);
253 void cat_releasedesc( struct cat_desc
*descp
);
254 int cat_lookup(struct hfsmount
*hfsmp
, struct cat_desc
*descp
, int wantrsrc
,
255 struct cat_desc
*outdescp
, struct cat_attr
*attrp
,
256 struct cat_fork
*forkp
, cnid_t
*desc_cnid
);
257 int cat_idlookup(struct hfsmount
*hfsmp
, cnid_t cnid
, int allow_system_files
, int wantrsrc
,
258 struct cat_desc
*outdescp
, struct cat_attr
*attrp
, struct cat_fork
*forkp
);
259 int cat_lookupmangled(struct hfsmount
*hfsmp
, struct cat_desc
*descp
, int wantrsrc
,
260 struct cat_desc
*outdescp
, struct cat_attr
*attrp
, struct cat_fork
*forkp
);
261 int cat_findname(struct hfsmount
*hfsmp
, cnid_t cnid
, struct cat_desc
*outdescp
);
262 int cat_getdirentries(struct hfsmount
*hfsmp
, u_int32_t entrycnt
, directoryhint_t
*dirhint
,
263 ReadDirBuff_s
* psReadDirBuffer
, int flags
, int *items
, bool *eofflag
, UVFSDirEntry
* psDotDotEntry
);
264 int cat_getentriesattr(struct hfsmount
*hfsmp
, directoryhint_t
*dirhint
, struct cat_entrylist
*ce_list
,
266 bool IsEntryAJnlFile(struct hfsmount
*hfsmp
, cnid_t cnid
);
267 int cat_preflight(struct hfsmount
*hfsmp
, uint32_t ops
, cat_cookie_t
*cookie
);
268 void cat_postflight(struct hfsmount
*hfsmp
, cat_cookie_t
*cookie
);
269 int cat_rename ( struct hfsmount
* hfsmp
, struct cat_desc
* from_cdp
, struct cat_desc
* todir_cdp
,
270 struct cat_desc
* to_cdp
, struct cat_desc
* out_cdp
);
271 int cat_delete(struct hfsmount
*hfsmp
, struct cat_desc
*descp
, struct cat_attr
*attrp
);
272 int cat_update(struct hfsmount
*hfsmp
, struct cat_desc
*descp
, struct cat_attr
*attrp
,
273 const struct cat_fork
*dataforkp
, const struct cat_fork
*rsrcforkp
);
274 int cat_acquire_cnid (struct hfsmount
*hfsmp
, cnid_t
*new_cnid
);
275 int cat_create(struct hfsmount
*hfsmp
, cnid_t new_fileid
, struct cat_desc
*descp
, struct cat_attr
*attrp
, struct cat_desc
*out_descp
);
276 int cat_set_childlinkbit(struct hfsmount
*hfsmp
, cnid_t cnid
);
277 int cat_check_link_ancestry(struct hfsmount
*hfsmp
, cnid_t cnid
, cnid_t pointed_at_cnid
);
279 // ------------------------------ Hard-Link Related ------------------------------
281 #define HFS_IGNORABLE_LINK 0x00000001
283 int cat_deletelink(struct hfsmount
*hfsmp
, struct cat_desc
*descp
);
284 int cat_update_siblinglinks(struct hfsmount
*hfsmp
, cnid_t linkfileid
, cnid_t prevlinkid
, cnid_t nextlinkid
);
285 int cat_lookup_lastlink(struct hfsmount
*hfsmp
, cnid_t linkfileid
, cnid_t
*lastlink
, struct cat_desc
*cdesc
);
286 int cat_resolvelink(struct hfsmount
*hfsmp
, u_int32_t linkref
, int isdirlink
, struct HFSPlusCatalogFile
*recp
);
287 int cat_lookuplink(struct hfsmount
*hfsmp
, struct cat_desc
*descp
, cnid_t
*linkfileid
, cnid_t
*prevlinkid
, cnid_t
*nextlinkid
);
288 void cat_convertattr(struct hfsmount
*hfsmp
, CatalogRecord
* recp
, struct cat_attr
*attrp
, struct cat_fork
*datafp
, struct cat_fork
*rsrcfp
);
289 int cat_createlink(struct hfsmount
*hfsmp
, struct cat_desc
*descp
, struct cat_attr
*attrp
, cnid_t nextlinkid
, cnid_t
*linkfileid
);
290 #endif /* lf_hfs_catalog_h */