1/* 2 * Copyright (c) 2002-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#ifndef __HFS_CATALOG__ 29#define __HFS_CATALOG__ 30 31#include <sys/appleapiopts.h> 32 33#ifdef KERNEL 34#ifdef __APPLE_API_PRIVATE 35#include <sys/vnode.h> 36 37#include <hfs/hfs_format.h> 38 39/* HFS Catalog */ 40 41 42/* 43 * Catalog ADTs 44 * 45 * The cat_desc, cat_attr, and cat_fork structures are 46 * use to import/export data to/from the Catalog file. 47 * The fields in these structures are always in BSD 48 * runtime format (e.g. dates and names). 49 */ 50 51typedef u_int32_t cnid_t; 52 53/* 54 * Catalog Node Descriptor (runtime) 55 */ 56struct cat_desc { 57 u_int8_t cd_flags; /* see below (8 bits) */ 58 u_int8_t cd_encoding; /* name encoding */ 59 int16_t cd_namelen; /* length of cnode name */ 60 cnid_t cd_parentcnid; /* parent directory CNID */ 61 u_int32_t cd_hint; /* catalog file hint */ 62 cnid_t cd_cnid; /* cnode id (for getattrlist) */ 63 const u_int8_t * cd_nameptr; /* pointer to cnode name */ 64}; 65 66/* cd_flags 67 * 68 * CD_EOF is used by hfs_vnop_readdir / cat_getdirentries to indicate EOF was 69 * encountered during a directory enumeration. When this flag is observed 70 * on the next call to hfs_vnop_readdir it tells the caller that there's no 71 * need to descend into the catalog as EOF was encountered during the last call. 72 * This flag should only be set on the descriptor embedded in the directoryhint. 73 */ 74 75#define CD_HASBUF 0x01 /* allocated filename buffer */ 76#define CD_DECOMPOSED 0x02 /* name is fully decomposed */ 77#define CD_EOF 0x04 /* see above */ 78#define CD_ISMETA 0x40 /* describes a metadata file */ 79#define CD_ISDIR 0x80 /* describes a directory */ 80 81/* 82 * Catalog Node Attributes (runtime) 83 */ 84struct cat_attr { 85 cnid_t ca_fileid; /* inode number (for stat) normally == cnid */ 86 mode_t ca_mode; /* file access mode and type (16 bits) */ 87 u_int16_t ca_recflags; /* catalog record flags (16 bit integer) */ 88 u_int32_t ca_linkcount; /* real hard link count */ 89 uid_t ca_uid; /* file owner */ 90 gid_t ca_gid; /* file group */ 91 union { 92 dev_t cau_rdev; /* special file device (VBLK or VCHAR only) */ 93 u_int32_t cau_linkref; /* hardlink reference number */ 94 } ca_union1; 95 time_t ca_atime; /* last access time */ 96 time_t ca_atimeondisk; /* access time value on disk */ 97 time_t ca_mtime; /* last data modification time */ 98 time_t ca_ctime; /* last file status change */ 99 time_t ca_itime; /* file initialization time */ 100 time_t ca_btime; /* last backup time */ 101 u_int32_t ca_flags; /* status flags (chflags) */ 102 union { 103 u_int32_t cau_blocks; /* total file blocks used (rsrc + data) */ 104 u_int32_t cau_entries; /* total directory entries (valence) */ 105 } ca_union2; 106 union { 107 u_int32_t cau_dircount; /* count of sub dirs (for posix nlink) */ 108 u_int32_t cau_firstlink; /* first hardlink link (files only) */ 109 } ca_union3; 110 u_int8_t ca_finderinfo[32]; /* Opaque Finder information */ 111}; 112 113/* Aliases for common fields */ 114#define ca_rdev ca_union1.cau_rdev 115#define ca_linkref ca_union1.cau_linkref 116#define ca_blocks ca_union2.cau_blocks 117#define ca_entries ca_union2.cau_entries 118#define ca_dircount ca_union3.cau_dircount 119#define ca_firstlink ca_union3.cau_firstlink 120 121/* 122 * Catalog Node Fork (runtime) 123 * 124 * NOTE: this is not the same as a struct HFSPlusForkData 125 * 126 * NOTE: if cf_new_size > cf_size, then a write is in progress and is extending 127 * the EOF; the new EOF will be cf_new_size. Writes and pageouts may validly 128 * write up to cf_new_size, but reads should only read up to cf_size. When 129 * an extending write is not in progress, cf_new_size is zero. 130 */ 131struct cat_fork { 132 off_t cf_size; /* fork's logical size in bytes */ 133 off_t cf_new_size; /* fork's logical size after write completes */ 134 union { 135 u_int32_t cfu_clump; /* fork's clump size in bytes (sys files only) */ 136 u_int64_t cfu_bytesread; /* bytes read from this fork */ 137 } cf_union; 138 u_int32_t cf_vblocks; /* virtual (unalloated) blocks */ 139 u_int32_t cf_blocks; /* total blocks used by this fork */ 140 struct HFSPlusExtentDescriptor cf_extents[8]; /* initial set of extents */ 141}; 142 143#define cf_clump cf_union.cfu_clump 144#define cf_bytesread cf_union.cfu_bytesread 145 146 147/* 148 * Directory Hint 149 * Used to hold state across directory enumerations. 150 * 151 */ 152struct directoryhint { 153 TAILQ_ENTRY(directoryhint) dh_link; /* chain */ 154 int dh_index; /* index into directory (zero relative) */ 155 u_int32_t dh_threadhint; /* node hint of a directory's thread record */ 156 u_int32_t dh_time; 157 struct cat_desc dh_desc; /* entry's descriptor */ 158}; 159typedef struct directoryhint directoryhint_t; 160 161/* 162 * HFS_MAXDIRHINTS cannot be larger than 63 without reducing 163 * HFS_INDEX_BITS, because given the 6-bit tag, at most 63 different 164 * tags can exist. When HFS_MAXDIRHINTS is larger than 63, the same 165 * list may contain dirhints of the same tag, and a staled dirhint may 166 * be returned. 167 */ 168#define HFS_MAXDIRHINTS 32 169#define HFS_DIRHINT_TTL 45 170 171#define HFS_INDEX_MASK 0x03ffffff 172#define HFS_INDEX_BITS 26 173 174 175/* 176 * Catalog Node Entry 177 * 178 * A cat_entry is used for bulk enumerations (hfs_readdirattr). 179 */ 180struct cat_entry { 181 struct cat_desc ce_desc; 182 struct cat_attr ce_attr; 183 off_t ce_datasize; 184 off_t ce_rsrcsize; 185 u_int32_t ce_datablks; 186 u_int32_t ce_rsrcblks; 187}; 188 189/* 190 * Starting in 10.5, hfs_vnop_readdirattr() only makes one 191 * call to cat_getentriesattr(). So we increased MAXCATENTRIES 192 * while keeping the total size of the CE LIST buffer <= 8K 193 * (which works out to be 60 entries per call). The 8K limit 194 * keeps the memory coming from a kalloc zone instead of 195 * valuable/fragment-able kernel map space. 196 */ 197#define MAXCATENTRIES \ 198 (1 + (8192 - sizeof (struct cat_entrylist)) / sizeof (struct cat_entry)) 199 200/* 201 * Catalog Node Entry List 202 * 203 * A cat_entrylist is a list of Catalog Node Entries. 204 */ 205struct cat_entrylist { 206 u_int32_t maxentries; /* number of entries requested */ 207 u_int32_t realentries; /* number of valid entries returned */ 208 u_int32_t skipentries; /* number of entries skipped (reserved HFS+ files) */ 209 struct cat_entry entry[1]; /* array of entries */ 210}; 211 212#define CE_LIST_SIZE(entries) \ 213 sizeof (*ce_list) + (((entries) - 1) * sizeof (struct cat_entry)) 214 215 216/* 217 * Catalog Operations Hint 218 * 219 * lower 16 bits: count of B-tree insert operations 220 * upper 16 bits: count of B-tree delete operations 221 * 222 */ 223#define CAT_DELETE 0x00010000 224#define CAT_CREATE 0x00000002 225#define CAT_RENAME 0x00010002 226#define CAT_EXCHANGE 0x00010002 227 228typedef u_int32_t catops_t; 229 230/* 231 * The size of cat_cookie_t much match the size of 232 * the nreserve struct (in BTreeNodeReserve.c). 233 */ 234typedef struct cat_cookie_t { 235#if defined(__LP64__) 236 char opaque[40]; 237#else 238 char opaque[24]; 239#endif 240} cat_cookie_t; 241 242/* Universal catalog key */ 243union CatalogKey { 244 HFSCatalogKey hfs; 245 HFSPlusCatalogKey hfsPlus; 246}; 247typedef union CatalogKey CatalogKey; 248 249/* Universal catalog data record */ 250union CatalogRecord { 251 int16_t recordType; 252 HFSCatalogFolder hfsFolder; 253 HFSCatalogFile hfsFile; 254 HFSCatalogThread hfsThread; 255 HFSPlusCatalogFolder hfsPlusFolder; 256 HFSPlusCatalogFile hfsPlusFile; 257 HFSPlusCatalogThread hfsPlusThread; 258}; 259typedef union CatalogRecord CatalogRecord; 260 261/* Constants for HFS fork types */ 262enum { 263 kHFSDataForkType = 0x0, /* data fork */ 264 kHFSResourceForkType = 0xff /* resource fork */ 265}; 266 267/* 268 * Catalog Interface 269 * 270 * These functions perform a catalog transactions. The 271 * catalog b-tree is abstracted through this interface. 272 * (please don't go around it) 273 */ 274 275struct hfsmount; 276 277extern void cat_releasedesc(struct cat_desc *descp); 278 279extern int cat_create ( struct hfsmount *hfsmp, 280 struct cat_desc *descp, 281 struct cat_attr *attrp, 282 struct cat_desc *out_descp); 283 284extern int cat_delete ( struct hfsmount *hfsmp, 285 struct cat_desc *descp, 286 struct cat_attr *attrp); 287 288extern int cat_lookup ( struct hfsmount *hfsmp, 289 struct cat_desc *descp, 290 int wantrsrc, 291 struct cat_desc *outdescp, 292 struct cat_attr *attrp, 293 struct cat_fork *forkp, 294 cnid_t *desc_cnid); 295 296extern int cat_idlookup (struct hfsmount *hfsmp, 297 cnid_t cnid, 298 int allow_system_files, 299 int wantrsrc, 300 struct cat_desc *outdescp, 301 struct cat_attr *attrp, 302 struct cat_fork *forkp); 303 304extern int cat_findname (struct hfsmount *hfsmp, 305 cnid_t cnid, 306 struct cat_desc *outdescp); 307 308extern int cat_getentriesattr( 309 struct hfsmount *hfsmp, 310 directoryhint_t *dirhint, 311 struct cat_entrylist *ce_list); 312 313extern int cat_rename ( struct hfsmount * hfsmp, 314 struct cat_desc * from_cdp, 315 struct cat_desc * todir_cdp, 316 struct cat_desc * to_cdp, 317 struct cat_desc * cdp); 318 319extern int cat_update ( struct hfsmount *hfsmp, 320 struct cat_desc *descp, 321 struct cat_attr *attrp, 322 struct cat_fork *dataforkp, 323 struct cat_fork *rsrcforkp); 324 325extern int cat_getdirentries( 326 struct hfsmount *hfsmp, 327 u_int32_t entrycnt, 328 directoryhint_t *dirhint, 329 uio_t uio, 330 int extended, 331 int * items, 332 int * eofflag); 333 334extern int cat_insertfilethread ( 335 struct hfsmount *hfsmp, 336 struct cat_desc *descp); 337 338extern int cat_preflight( 339 struct hfsmount *hfsmp, 340 catops_t ops, 341 cat_cookie_t *cookie, 342 struct proc *p); 343 344extern void cat_postflight( 345 struct hfsmount *hfsmp, 346 cat_cookie_t *cookie, 347 struct proc *p); 348 349extern int cat_binarykeycompare( 350 HFSPlusCatalogKey *searchKey, 351 HFSPlusCatalogKey *trialKey); 352 353extern int CompareCatalogKeys( 354 HFSCatalogKey *searchKey, 355 HFSCatalogKey *trialKey); 356 357extern int CompareExtendedCatalogKeys( 358 HFSPlusCatalogKey *searchKey, 359 HFSPlusCatalogKey *trialKey); 360 361extern void cat_convertattr( 362 struct hfsmount *hfsmp, 363 CatalogRecord * recp, 364 struct cat_attr *attrp, 365 struct cat_fork *datafp, 366 struct cat_fork *rsrcfp); 367 368extern int cat_convertkey( 369 struct hfsmount *hfsmp, 370 CatalogKey *key, 371 CatalogRecord * recp, 372 struct cat_desc *descp); 373 374extern int cat_getkeyplusattr( 375 struct hfsmount *hfsmp, 376 cnid_t cnid, 377 CatalogKey *key, 378 struct cat_attr *attrp); 379 380/* Hard link functions. */ 381 382extern int cat_check_link_ancestry( 383 struct hfsmount *hfsmp, 384 cnid_t parentid, 385 cnid_t pointed_at_cnid); 386 387extern int cat_set_childlinkbit( 388 struct hfsmount *hfsmp, 389 cnid_t cnid); 390 391#define HFS_IGNORABLE_LINK 0x00000001 392 393extern int cat_resolvelink( struct hfsmount *hfsmp, 394 u_int32_t linkref, 395 int isdirlink, 396 struct HFSPlusCatalogFile *recp); 397 398extern int cat_createlink( struct hfsmount *hfsmp, 399 struct cat_desc *descp, 400 struct cat_attr *attr, 401 cnid_t nextlinkid, 402 cnid_t *linkfileid); 403 404/* Finder Info's file type and creator for directory hard link alias */ 405enum { 406 kHFSAliasType = 0x66647270, /* 'fdrp' */ 407 kHFSAliasCreator = 0x4D414353 /* 'MACS' */ 408}; 409 410extern int cat_deletelink( struct hfsmount *hfsmp, 411 struct cat_desc *descp); 412 413extern int cat_update_siblinglinks( struct hfsmount *hfsmp, 414 cnid_t linkfileid, 415 cnid_t prevlinkid, 416 cnid_t nextlinkid); 417 418extern int cat_lookuplink( struct hfsmount *hfsmp, 419 struct cat_desc *descp, 420 cnid_t *linkfileid, 421 cnid_t *prevlinkid, 422 cnid_t *nextlinkid); 423 424extern int cat_lookup_siblinglinks( struct hfsmount *hfsmp, 425 cnid_t linkfileid, 426 cnid_t *prevlinkid, 427 cnid_t *nextlinkid); 428 429extern int cat_lookup_dirlink(struct hfsmount *hfsmp, 430 cnid_t dirlink_id, 431 u_int8_t forktype, 432 struct cat_desc *outdescp, 433 struct cat_attr *attrp, 434 struct cat_fork *forkp); 435 436extern int cat_update_dirlink(struct hfsmount *hfsmp, 437 u_int8_t forktype, 438 struct cat_desc *descp, 439 struct cat_attr *attrp, 440 struct cat_fork *rsrcforkp); 441 442#endif /* __APPLE_API_PRIVATE */ 443#endif /* KERNEL */ 444#endif /* __HFS_CATALOG__ */ 445