1/* 2 * Copyright (c) 2000-2012 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 29#ifndef __HFS__ 30#define __HFS__ 31 32/* If set to 1, enables the code to allocate blocks from the start 33 * of the disk instead of the nextAllocation for sparse devices like 34 * sparse disk images or sparsebundle images. The free extent cache 35 * for such volumes is also maintained based on the start block instead 36 * of number of contiguous allocation blocks. These devices prefer 37 * allocation of blocks near the start of the disk to avoid the 38 * increasing the image size, but it can also result in file fragmentation. 39 */ 40#define HFS_SPARSE_DEV 1 41 42#if DEBUG 43#define HFS_CHECK_LOCK_ORDER 1 44#endif 45 46#include <sys/appleapiopts.h> 47 48#ifdef KERNEL 49#ifdef __APPLE_API_PRIVATE 50#include <sys/param.h> 51#include <sys/queue.h> 52#include <sys/mount.h> 53#include <sys/vnode.h> 54#include <sys/quota.h> 55#include <sys/dirent.h> 56#include <sys/event.h> 57#include <sys/disk.h> 58#include <kern/thread_call.h> 59 60#include <kern/locks.h> 61 62#include <vfs/vfs_journal.h> 63 64#include <hfs/hfs_format.h> 65#include <hfs/hfs_catalog.h> 66#include <hfs/hfs_cnode.h> 67#include <hfs/hfs_macos_defs.h> 68#include <hfs/hfs_encodings.h> 69#include <hfs/hfs_hotfiles.h> 70 71#if CONFIG_PROTECT 72/* Forward declare the cprotect struct */ 73struct cprotect; 74#endif 75 76/* 77 * Just reported via MIG interface. 78 */ 79#define VERSION_STRING "hfs-2 (4-12-99)" 80 81#define HFS_LINK_MAX 32767 82 83#define HFS_MAX_DEFERED_ALLOC (1024*1024) 84 85// 400 megs is a "big" file (i.e. one that when deleted 86// would touch enough data that we should break it into 87// multiple separate transactions) 88#define HFS_BIGFILE_SIZE (400LL * 1024LL * 1024LL) 89 90 91enum { kMDBSize = 512 }; /* Size of I/O transfer to read entire MDB */ 92 93enum { kMasterDirectoryBlock = 2 }; /* MDB offset on disk in 512-byte blocks */ 94enum { kMDBOffset = kMasterDirectoryBlock * 512 }; /* MDB offset on disk in bytes */ 95 96#define kRootDirID kHFSRootFolderID 97 98 99/* number of locked buffer caches to hold for b-tree meta data */ 100#define kMaxLockedMetaBuffers 32 101 102extern struct timezone gTimeZone; 103 104 105/* How many free extents to cache per volume */ 106#define kMaxFreeExtents 10 107 108/* 109 * HFS_MINFREE gives the minimum acceptable percentage 110 * of file system blocks which may be free (but this 111 * minimum will never exceed HFS_MAXRESERVE bytes). If 112 * the free block count drops below this level only the 113 * superuser may continue to allocate blocks. 114 */ 115#define HFS_MINFREE 1 116#define HFS_MAXRESERVE ((u_int64_t)(250*1024*1024)) 117#define HFS_BT_MAXRESERVE ((u_int64_t)(10*1024*1024)) 118 119/* 120 * The system distinguishes between the desirable low-disk 121 * notifiaction levels for root volumes and non-root volumes. 122 * The various thresholds are computed as a fraction of the 123 * volume size, all capped at a certain fixed level 124 */ 125 126#define HFS_ROOTVERYLOWDISKTRIGGERFRACTION 5 127#define HFS_ROOTVERYLOWDISKTRIGGERLEVEL ((u_int64_t)(512*1024*1024)) 128#define HFS_ROOTLOWDISKTRIGGERFRACTION 10 129#define HFS_ROOTLOWDISKTRIGGERLEVEL ((u_int64_t)(1024*1024*1024)) 130#define HFS_ROOTLOWDISKSHUTOFFFRACTION 11 131#define HFS_ROOTLOWDISKSHUTOFFLEVEL ((u_int64_t)(1024*1024*1024 + 250*1024*1024)) 132 133#define HFS_VERYLOWDISKTRIGGERFRACTION 1 134#define HFS_VERYLOWDISKTRIGGERLEVEL ((u_int64_t)(100*1024*1024)) 135#define HFS_LOWDISKTRIGGERFRACTION 2 136#define HFS_LOWDISKTRIGGERLEVEL ((u_int64_t)(150*1024*1024)) 137#define HFS_LOWDISKSHUTOFFFRACTION 3 138#define HFS_LOWDISKSHUTOFFLEVEL ((u_int64_t)(200*1024*1024)) 139 140/* Internal Data structures*/ 141 142/* This structure describes the HFS specific mount structure data. */ 143typedef struct hfsmount { 144 u_int32_t hfs_flags; /* see below */ 145 146 /* Physical Description */ 147 u_int32_t hfs_logical_block_size; /* Logical block size of the disk as reported by ioctl(DKIOCGETBLOCKSIZE), always a multiple of 512 */ 148 daddr64_t hfs_logical_block_count; /* Number of logical blocks on the disk */ 149 u_int64_t hfs_logical_bytes; /* Number of bytes on the disk device this HFS is mounted on (blockcount * blocksize) */ 150 daddr64_t hfs_alt_id_sector; /* location of alternate VH/MDB */ 151 u_int32_t hfs_physical_block_size; /* Physical block size of the disk as reported by ioctl(DKIOCGETPHYSICALBLOCKSIZE) */ 152 u_int32_t hfs_log_per_phys; /* Number of logical blocks per physical block size */ 153 154 /* Access to VFS and devices */ 155 struct mount *hfs_mp; /* filesystem vfs structure */ 156 struct vnode *hfs_devvp; /* block device mounted vnode */ 157 struct vnode * hfs_extents_vp; 158 struct vnode * hfs_catalog_vp; 159 struct vnode * hfs_allocation_vp; 160 struct vnode * hfs_attribute_vp; 161 struct vnode * hfs_startup_vp; 162 struct vnode * hfs_attrdata_vp; /* pseudo file */ 163 struct cnode * hfs_extents_cp; 164 struct cnode * hfs_catalog_cp; 165 struct cnode * hfs_allocation_cp; 166 struct cnode * hfs_attribute_cp; 167 struct cnode * hfs_startup_cp; 168 dev_t hfs_raw_dev; /* device mounted */ 169 u_int32_t hfs_logBlockSize; /* Size of buffer cache buffer for I/O */ 170 171 /* Default values for HFS standard and non-init access */ 172 uid_t hfs_uid; /* uid to set as owner of the files */ 173 gid_t hfs_gid; /* gid to set as owner of the files */ 174 mode_t hfs_dir_mask; /* mask to and with directory protection bits */ 175 mode_t hfs_file_mask; /* mask to and with file protection bits */ 176 u_int32_t hfs_encoding; /* Default encoding for non hfs+ volumes */ 177 178 /* Persistent fields (on disk, dynamic) */ 179 time_t hfs_mtime; /* file system last modification time */ 180 u_int32_t hfs_filecount; /* number of files in file system */ 181 u_int32_t hfs_dircount; /* number of directories in file system */ 182 u_int32_t freeBlocks; /* free allocation blocks */ 183 u_int32_t nextAllocation; /* start of next allocation search */ 184 u_int32_t sparseAllocation; /* start of allocations for sparse devices */ 185 u_int32_t vcbNxtCNID; /* next unused catalog node ID - protected by catalog lock */ 186 u_int32_t vcbWrCnt; /* file system write count */ 187 u_int64_t encodingsBitmap; /* in-use encodings */ 188 u_int16_t vcbNmFls; /* HFS Only - root dir file count */ 189 u_int16_t vcbNmRtDirs; /* HFS Only - root dir directory count */ 190 191 /* Persistent fields (on disk, static) */ 192 u_int16_t vcbSigWord; 193 int16_t vcbFlags; /* Runtime flag to indicate if volume is dirty/clean */ 194 u_int32_t vcbAtrb; 195 u_int32_t vcbJinfoBlock; 196 u_int32_t localCreateDate;/* volume create time from volume header (For HFS+, value is in local time) */ 197 time_t hfs_itime; /* file system creation time (creation date of the root folder) */ 198 time_t hfs_btime; /* file system last backup time */ 199 u_int32_t blockSize; /* size of allocation blocks */ 200 u_int32_t totalBlocks; /* total allocation blocks */ 201 u_int32_t allocLimit; /* Do not allocate this block or beyond */ 202 /* 203 * NOTE: When resizing a volume to make it smaller, allocLimit is set to the allocation 204 * block number which will contain the new alternate volume header. At all other times, 205 * allocLimit is set to totalBlocks. The allocation code uses allocLimit instead of 206 * totalBlocks to limit which blocks may be allocated, so that during a resize, we don't 207 * put new content into the blocks we're trying to truncate away. 208 */ 209 int32_t vcbClpSiz; 210 u_int32_t vcbFndrInfo[8]; 211 int16_t vcbVBMSt; /* HFS only */ 212 int16_t vcbAlBlSt; /* HFS only */ 213 214 /* vcb stuff */ 215 u_int8_t vcbVN[256]; /* volume name in UTF-8 */ 216 u_int32_t volumeNameEncodingHint; 217 u_int32_t hfsPlusIOPosOffset; /* Disk block where HFS+ starts */ 218 u_int32_t vcbVBMIOSize; /* volume bitmap I/O size */ 219 220 /* cache of largest known free extents */ 221 u_int32_t vcbFreeExtCnt; 222 HFSPlusExtentDescriptor vcbFreeExt[kMaxFreeExtents]; 223 lck_spin_t vcbFreeExtLock; 224 225 /* Summary Table */ 226 u_int8_t *hfs_summary_table; /* Each bit is 1 vcbVBMIOSize of bitmap, byte indexed */ 227 u_int32_t hfs_summary_size; /* number of BITS in summary table defined above (not bytes!) */ 228 u_int32_t hfs_summary_bytes; /* number of BYTES in summary table */ 229 230 u_int32_t scan_var; /* For initializing the summary table */ 231 232 233 u_int32_t reserveBlocks; /* free block reserve */ 234 u_int32_t loanedBlocks; /* blocks on loan for delayed allocations */ 235 236 237 /* 238 * HFS+ Private system directories (two). Any access 239 * (besides looking at the cd_cnid) requires holding 240 * the Catalog File lock. 241 */ 242 struct cat_desc hfs_private_desc[2]; 243 struct cat_attr hfs_private_attr[2]; 244 245 u_int32_t hfs_metadata_createdate; 246 hfs_to_unicode_func_t hfs_get_unicode; 247 unicode_to_hfs_func_t hfs_get_hfsname; 248 249 /* Quota variables: */ 250 struct quotafile hfs_qfiles[MAXQUOTAS]; /* quota files */ 251 252 /* Journaling variables: */ 253 void *jnl; // the journal for this volume (if one exists) 254 struct vnode *jvp; // device where the journal lives (may be equal to devvp) 255 u_int32_t jnl_start; // start block of the journal file (so we don't delete it) 256 u_int32_t jnl_size; 257 u_int32_t hfs_jnlfileid; 258 u_int32_t hfs_jnlinfoblkid; 259 lck_rw_t hfs_global_lock; 260 u_int32_t hfs_global_lock_nesting; 261 void* hfs_global_lockowner; 262 263 /* Notification variables: */ 264 u_int32_t hfs_notification_conditions; 265 u_int32_t hfs_freespace_notify_dangerlimit; 266 u_int32_t hfs_freespace_notify_warninglimit; 267 u_int32_t hfs_freespace_notify_desiredlevel; 268 269 /* time mounted and last mounted mod time "snapshot" */ 270 time_t hfs_mount_time; 271 time_t hfs_last_mounted_mtime; 272 273 /* Metadata allocation zone variables: */ 274 u_int32_t hfs_metazone_start; 275 u_int32_t hfs_metazone_end; 276 u_int32_t hfs_hotfile_start; 277 u_int32_t hfs_hotfile_end; 278 u_int32_t hfs_min_alloc_start; 279 u_int32_t hfs_freed_block_count; 280 int hfs_hotfile_freeblks; 281 int hfs_hotfile_maxblks; 282 int hfs_overflow_maxblks; 283 int hfs_catalog_maxblks; 284 285 /* Hot File Clustering variables: */ 286 lck_mtx_t hfc_mutex; /* serialize hot file stages */ 287 enum hfc_stage hfc_stage; /* what are we up to... */ 288 time_t hfc_timebase; /* recording period start time */ 289 time_t hfc_timeout; /* recording period stop time */ 290 void * hfc_recdata; /* recording data (opaque) */ 291 int hfc_maxfiles; /* maximum files to track */ 292 struct vnode * hfc_filevp; 293 294#if HFS_SPARSE_DEV 295 /* Sparse device variables: */ 296 struct vnode * hfs_backingfs_rootvp; 297 u_int32_t hfs_last_backingstatfs; 298 int hfs_sparsebandblks; 299 u_int64_t hfs_backingfs_maxblocks; 300#endif 301 size_t hfs_max_inline_attrsize; 302 303 lck_mtx_t hfs_mutex; /* protects access to hfsmount data */ 304 void *hfs_freezing_proc; /* who froze the fs */ 305 void *hfs_downgrading_proc; /* process who's downgrading to rdonly */ 306 lck_rw_t hfs_insync; /* protects sync/freeze interaction */ 307 308 /* Resize variables: */ 309 u_int32_t hfs_resize_blocksmoved; 310 u_int32_t hfs_resize_totalblocks; 311 u_int32_t hfs_resize_progress; 312#if CONFIG_PROTECT 313 struct cprotect *hfs_resize_cpentry; 314 u_int16_t hfs_running_cp_major_vers; 315 uint32_t default_cp_class; 316#endif 317 318 319 /* Per mount cnode hash variables: */ 320 lck_mtx_t hfs_chash_mutex; /* protects access to cnode hash table */ 321 u_long hfs_cnodehash; /* size of cnode hash table - 1 */ 322 LIST_HEAD(cnodehashhead, cnode) *hfs_cnodehashtbl; /* base of cnode hash */ 323 324 /* Per mount fileid hash variables (protected by catalog lock!) */ 325 u_long hfs_idhash; /* size of cnid/fileid hash table -1 */ 326 LIST_HEAD(idhashhead, cat_preflightid) *hfs_idhashtbl; /* base of ID hash */ 327 328 // Records the oldest outstanding sync request 329 struct timeval hfs_sync_req_oldest; 330 331 // Records whether a sync has been queued or is in progress 332 boolean_t hfs_sync_incomplete; 333 334 thread_call_t hfs_syncer; // removeable devices get sync'ed by this guy 335 336 /* Records the syncer thread so that we can avoid the syncer 337 queing more syncs. */ 338 thread_t hfs_syncer_thread; 339 340 // Not currently used except for debugging purposes 341 uint32_t hfs_active_threads; 342} hfsmount_t; 343 344/* 345 * HFS_META_DELAY is a duration (in usecs) used for triggering the 346 * hfs_syncer() routine. We will back off if writes are in 347 * progress, but... 348 * HFS_MAX_META_DELAY is the maximum time we will allow the 349 * syncer to be delayed. 350 */ 351enum { 352 HFS_META_DELAY = 100 * 1000, // 0.1 secs 353 HFS_MAX_META_DELAY = 5000 * 1000 // 5 secs 354}; 355 356typedef hfsmount_t ExtendedVCB; 357 358/* Aliases for legacy (Mac OS 9) field names */ 359#define vcbLsMod hfs_mtime 360#define vcbVolBkUp hfs_btime 361#define extentsRefNum hfs_extents_vp 362#define catalogRefNum hfs_catalog_vp 363#define allocationsRefNum hfs_allocation_vp 364#define vcbFilCnt hfs_filecount 365#define vcbDirCnt hfs_dircount 366 367/* Inline functions to set/reset vcbFlags. Upper 8 bits indicate if the volume 368 * header/VCB is clean/dirty --- if set, volume header is dirty, and 369 * if clear, volume header is clean. This value is checked to determine 370 * if the in-memory copy of volume header should be flushed to the disk 371 * or not. 372 */ 373/* Set runtime flag to indicate that volume is dirty */ 374static __inline__ void MarkVCBDirty(ExtendedVCB *vcb) 375{ 376 vcb->vcbFlags |= 0xFF00; 377} 378 379/* Clear runtime flag to indicate that volume is dirty */ 380static __inline__ void MarkVCBClean(ExtendedVCB *vcb) 381{ 382 vcb->vcbFlags &= 0x00FF; 383} 384 385/* Check runtime flag to determine if the volume is dirty or not */ 386static __inline__ Boolean IsVCBDirty(ExtendedVCB *vcb) 387{ 388 return (vcb->vcbFlags & 0xFF00 ? true : false); 389} 390 391/* 392 * There are two private directories in HFS+. 393 * 394 * One contains inodes for files that are hardlinked or open/unlinked. 395 * The other contains inodes for directories that are hardlinked. 396 */ 397enum privdirtype {FILE_HARDLINKS, DIR_HARDLINKS}; 398 399#define HFS_ALLOCATOR_SCAN_INFLIGHT 0x0001 /* scan started */ 400 401/* HFS mount point flags */ 402#define HFS_READ_ONLY 0x00001 403#define HFS_UNKNOWN_PERMS 0x00002 404#define HFS_WRITEABLE_MEDIA 0x00004 405#define HFS_CLEANED_ORPHANS 0x00008 406#define HFS_X 0x00010 407#define HFS_CASE_SENSITIVE 0x00020 408#define HFS_STANDARD 0x00040 409#define HFS_METADATA_ZONE 0x00080 410#define HFS_FRAGMENTED_FREESPACE 0x00100 411#define HFS_NEED_JNL_RESET 0x00200 412#define HFS_HAS_SPARSE_DEVICE 0x00400 413#define HFS_RESIZE_IN_PROGRESS 0x00800 414#define HFS_QUOTAS 0x01000 415#define HFS_CREATING_BTREE 0x02000 416/* When set, do not update nextAllocation in the mount structure */ 417#define HFS_SKIP_UPDATE_NEXT_ALLOCATION 0x04000 418/* When set, the file system supports extent-based extended attributes */ 419#define HFS_XATTR_EXTENTS 0x08000 420#define HFS_FOLDERCOUNT 0x10000 421/* When set, the file system exists on a virtual device, like disk image */ 422#define HFS_VIRTUAL_DEVICE 0x20000 423/* When set, we're in hfs_changefs, so hfs_sync should do nothing. */ 424#define HFS_IN_CHANGEFS 0x40000 425/* When set, we are in process of downgrading or have downgraded to read-only, 426 * so hfs_start_transaction should return EROFS. 427 */ 428#define HFS_RDONLY_DOWNGRADE 0x80000 429#define HFS_DID_CONTIG_SCAN 0x100000 430#define HFS_UNMAP 0x200000 431#define HFS_SSD 0x400000 432#define HFS_SUMMARY_TABLE 0x800000 433#define HFS_CS 0x1000000 434 435 436/* Macro to update next allocation block in the HFS mount structure. If 437 * the HFS_SKIP_UPDATE_NEXT_ALLOCATION is set, do not update 438 * nextAllocation block. 439 */ 440#define HFS_UPDATE_NEXT_ALLOCATION(hfsmp, new_nextAllocation) \ 441 { \ 442 if ((hfsmp->hfs_flags & HFS_SKIP_UPDATE_NEXT_ALLOCATION) == 0)\ 443 hfsmp->nextAllocation = new_nextAllocation; \ 444 } \ 445 446/* Macro for incrementing and decrementing the folder count in a cnode 447 * attribute only if the HFS_FOLDERCOUNT bit is set in the mount flags 448 * and kHFSHasFolderCount bit is set in the cnode flags. Currently these 449 * bits are only set for case sensitive HFS+ volumes. 450 */ 451#define INC_FOLDERCOUNT(hfsmp, cattr) \ 452 if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \ 453 (cattr.ca_recflags & kHFSHasFolderCountMask)) { \ 454 cattr.ca_dircount++; \ 455 } \ 456 457#define DEC_FOLDERCOUNT(hfsmp, cattr) \ 458 if ((hfsmp->hfs_flags & HFS_FOLDERCOUNT) && \ 459 (cattr.ca_recflags & kHFSHasFolderCountMask) && \ 460 (cattr.ca_dircount > 0)) { \ 461 cattr.ca_dircount--; \ 462 } \ 463 464typedef struct filefork FCB; 465 466/* 467 * Macros for creating item names for our special/private directories. 468 */ 469#define MAKE_INODE_NAME(name, size, linkno) \ 470 (void) snprintf((name), size, "%s%d", HFS_INODE_PREFIX, (linkno)) 471#define HFS_INODE_PREFIX_LEN 5 472 473#define MAKE_DIRINODE_NAME(name, size, linkno) \ 474 (void) snprintf((name), size, "%s%d", HFS_DIRINODE_PREFIX, (linkno)) 475#define HFS_DIRINODE_PREFIX_LEN 4 476 477#define MAKE_DELETED_NAME(NAME, size, FID) \ 478 (void) snprintf((NAME), size, "%s%d", HFS_DELETE_PREFIX, (FID)) 479#define HFS_DELETE_PREFIX_LEN 4 480 481 482#define HFS_AVERAGE_NAME_SIZE 22 483#define AVERAGE_HFSDIRENTRY_SIZE (8+HFS_AVERAGE_NAME_SIZE+4) 484 485#define STD_DIRENT_LEN(namlen) \ 486 ((sizeof(struct dirent) - (NAME_MAX+1)) + (((namlen)+1 + 3) &~ 3)) 487 488#define EXT_DIRENT_LEN(namlen) \ 489 ((sizeof(struct direntry) + (namlen) - (MAXPATHLEN-1) + 7) & ~7) 490 491 492enum { kHFSPlusMaxFileNameBytes = kHFSPlusMaxFileNameChars * 3 }; 493 494 495/* macro to determine if hfs or hfsplus */ 496#define ISHFSPLUS(VCB) ((VCB)->vcbSigWord == kHFSPlusSigWord) 497#define ISHFS(VCB) ((VCB)->vcbSigWord == kHFSSigWord) 498 499 500/* 501 * Various ways to acquire a VFS mount point pointer: 502 */ 503#define VTOVFS(VP) vnode_mount((VP)) 504#define HFSTOVFS(HFSMP) ((HFSMP)->hfs_mp) 505#define VCBTOVFS(VCB) HFSTOVFS(VCB) 506 507/* 508 * Various ways to acquire an HFS mount point pointer: 509 */ 510#define VTOHFS(VP) ((struct hfsmount *)vfs_fsprivate(vnode_mount((VP)))) 511#define VFSTOHFS(MP) ((struct hfsmount *)vfs_fsprivate((MP))) 512#define VCBTOHFS(VCB) (VCB) 513#define FCBTOHFS(FCB) ((struct hfsmount *)vfs_fsprivate(vnode_mount((FCB)->ff_cp->c_vp))) 514 515/* 516 * Various ways to acquire a VCB (legacy) pointer: 517 */ 518#define VTOVCB(VP) VTOHFS(VP) 519#define VFSTOVCB(MP) VFSTOHFS(MP) 520#define HFSTOVCB(HFSMP) (HFSMP) 521#define FCBTOVCB(FCB) FCBTOHFS(FCB) 522 523 524#define E_NONE 0 525#define kHFSBlockSize 512 526 527/* 528 * Macros for getting the MDB/VH sector and offset 529 */ 530#define HFS_PRI_SECTOR(blksize) (1024 / (blksize)) 531#define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0) 532 533#define HFS_ALT_SECTOR(blksize, blkcnt) (((blkcnt) - 1) - (512 / (blksize))) 534#define HFS_ALT_OFFSET(blksize) ((blksize) > 1024 ? (blksize) - 1024 : 0) 535 536/* Convert the logical sector number to be aligned on physical block size boundary. 537 * We are assuming the partition is a multiple of physical block size. 538 */ 539#define HFS_PHYSBLK_ROUNDDOWN(sector_num, log_per_phys) ((sector_num / log_per_phys) * log_per_phys) 540 541/* 542 * HFS specific fcntl()'s 543 */ 544#define HFS_GET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00004) 545#define HFS_SET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00005) 546/* See HFSIOC_EXT_BULKACCESS and friends for HFS specific fsctls*/ 547 548 549 550/* 551 * This is the straight GMT conversion constant: 552 * 00:00:00 January 1, 1970 - 00:00:00 January 1, 1904 553 * (3600 * 24 * ((365 * (1970 - 1904)) + (((1970 - 1904) / 4) + 1))) 554 */ 555#define MAC_GMT_FACTOR 2082844800UL 556 557 558/***************************************************************************** 559 FUNCTION PROTOTYPES 560******************************************************************************/ 561 562/***************************************************************************** 563 hfs_vnop_xxx functions from different files 564******************************************************************************/ 565int hfs_vnop_readdirattr(struct vnop_readdirattr_args *); /* in hfs_attrlist.c */ 566 567int hfs_vnop_inactive(struct vnop_inactive_args *); /* in hfs_cnode.c */ 568int hfs_vnop_reclaim(struct vnop_reclaim_args *); /* in hfs_cnode.c */ 569 570int hfs_set_backingstore (struct vnode *vp, int val); /* in hfs_cnode.c */ 571int hfs_is_backingstore (struct vnode *vp, int *val); /* in hfs_cnode.c */ 572 573int hfs_vnop_link(struct vnop_link_args *); /* in hfs_link.c */ 574 575int hfs_vnop_lookup(struct vnop_lookup_args *); /* in hfs_lookup.c */ 576 577int hfs_vnop_search(struct vnop_searchfs_args *); /* in hfs_search.c */ 578 579int hfs_vnop_read(struct vnop_read_args *); /* in hfs_readwrite.c */ 580int hfs_vnop_write(struct vnop_write_args *); /* in hfs_readwrite.c */ 581int hfs_vnop_ioctl(struct vnop_ioctl_args *); /* in hfs_readwrite.c */ 582int hfs_vnop_select(struct vnop_select_args *); /* in hfs_readwrite.c */ 583int hfs_vnop_strategy(struct vnop_strategy_args *); /* in hfs_readwrite.c */ 584int hfs_vnop_allocate(struct vnop_allocate_args *); /* in hfs_readwrite.c */ 585int hfs_vnop_pagein(struct vnop_pagein_args *); /* in hfs_readwrite.c */ 586int hfs_vnop_pageout(struct vnop_pageout_args *); /* in hfs_readwrite.c */ 587int hfs_vnop_bwrite(struct vnop_bwrite_args *); /* in hfs_readwrite.c */ 588int hfs_vnop_blktooff(struct vnop_blktooff_args *); /* in hfs_readwrite.c */ 589int hfs_vnop_offtoblk(struct vnop_offtoblk_args *); /* in hfs_readwrite.c */ 590int hfs_vnop_blockmap(struct vnop_blockmap_args *); /* in hfs_readwrite.c */ 591 592int hfs_vnop_getxattr(struct vnop_getxattr_args *); /* in hfs_xattr.c */ 593int hfs_vnop_setxattr(struct vnop_setxattr_args *); /* in hfs_xattr.c */ 594int hfs_vnop_removexattr(struct vnop_removexattr_args *); /* in hfs_xattr.c */ 595int hfs_vnop_listxattr(struct vnop_listxattr_args *); /* in hfs_xattr.c */ 596#if NAMEDSTREAMS 597extern int hfs_vnop_getnamedstream(struct vnop_getnamedstream_args*); 598extern int hfs_vnop_makenamedstream(struct vnop_makenamedstream_args*); 599extern int hfs_vnop_removenamedstream(struct vnop_removenamedstream_args*); 600#endif 601 602 603/***************************************************************************** 604 Functions from MacOSStubs.c 605******************************************************************************/ 606time_t to_bsd_time(u_int32_t hfs_time); 607 608u_int32_t to_hfs_time(time_t bsd_time); 609 610 611/***************************************************************************** 612 Functions from hfs_encodinghint.c 613******************************************************************************/ 614u_int32_t hfs_pickencoding(const u_int16_t *src, int len); 615 616u_int32_t hfs_getencodingbias(void); 617 618void hfs_setencodingbias(u_int32_t bias); 619 620 621/***************************************************************************** 622 Functions from hfs_encodings.c 623******************************************************************************/ 624void hfs_converterinit(void); 625 626int hfs_relconverter (u_int32_t encoding); 627 628int hfs_getconverter(u_int32_t encoding, hfs_to_unicode_func_t *get_unicode, 629 unicode_to_hfs_func_t *get_hfsname); 630 631#if CONFIG_HFS_STD 632int hfs_to_utf8(ExtendedVCB *vcb, const Str31 hfs_str, ByteCount maxDstLen, 633 ByteCount *actualDstLen, unsigned char* dstStr); 634 635int utf8_to_hfs(ExtendedVCB *vcb, ByteCount srcLen, const unsigned char* srcStr, 636 Str31 dstStr); 637 638int mac_roman_to_utf8(const Str31 hfs_str, ByteCount maxDstLen, ByteCount *actualDstLen, 639 unsigned char* dstStr); 640 641int utf8_to_mac_roman(ByteCount srcLen, const unsigned char* srcStr, Str31 dstStr); 642 643int mac_roman_to_unicode(const Str31 hfs_str, UniChar *uni_str, u_int32_t maxCharLen, u_int32_t *usedCharLen); 644 645int unicode_to_hfs(ExtendedVCB *vcb, ByteCount srcLen, u_int16_t* srcStr, Str31 dstStr, int retry); 646#endif 647 648/***************************************************************************** 649 Functions from hfs_notifications.c 650******************************************************************************/ 651void hfs_generate_volume_notifications(struct hfsmount *hfsmp); 652 653 654/***************************************************************************** 655 Functions from hfs_readwrite.c 656******************************************************************************/ 657extern int hfs_relocate(struct vnode *, u_int32_t, kauth_cred_t, struct proc *); 658 659/* Flags for HFS truncate */ 660#define HFS_TRUNCATE_SKIPUPDATE 0x00000001 661#define HFS_TRUNCATE_SKIPTIMES 0x00000002 /* implied by skipupdate; it is a subset */ 662 663extern int hfs_truncate(struct vnode *, off_t, int, int, int, vfs_context_t); 664 665extern int hfs_release_storage (struct hfsmount *hfsmp, struct filefork *datafork, 666 struct filefork *rsrcfork, u_int32_t fileid); 667 668extern int hfs_prepare_release_storage (struct hfsmount *hfsmp, struct vnode *vp); 669 670extern int hfs_bmap(struct vnode *, daddr_t, struct vnode **, daddr64_t *, unsigned int *); 671 672extern int hfs_fsync(struct vnode *, int, int, struct proc *); 673 674extern int hfs_access(struct vnode *, mode_t, kauth_cred_t, struct proc *); 675 676extern int hfs_removeallattr(struct hfsmount *hfsmp, u_int32_t fileid); 677 678extern int hfs_set_volxattr(struct hfsmount *hfsmp, unsigned int xattrtype, int state); 679 680extern int hfs_isallocated(struct hfsmount *hfsmp, u_int32_t startingBlock, u_int32_t numBlocks); 681 682extern int hfs_count_allocated(struct hfsmount *hfsmp, u_int32_t startBlock, 683 u_int32_t numBlocks, u_int32_t *alloc_count); 684 685extern int hfs_isrbtree_active (struct hfsmount *hfsmp); 686 687 688/***************************************************************************** 689 Functions from hfs_vfsops.c 690******************************************************************************/ 691int hfs_mountroot(mount_t mp, vnode_t rvp, vfs_context_t context); 692 693/* used as a callback by the journaling code */ 694extern void hfs_sync_metadata(void *arg); 695 696extern int hfs_vget(struct hfsmount *, cnid_t, struct vnode **, int, int); 697 698extern void hfs_setencodingbits(struct hfsmount *hfsmp, u_int32_t encoding); 699 700enum volop {VOL_UPDATE, VOL_MKDIR, VOL_RMDIR, VOL_MKFILE, VOL_RMFILE}; 701extern int hfs_volupdate(struct hfsmount *hfsmp, enum volop op, int inroot); 702 703int hfs_flushvolumeheader(struct hfsmount *hfsmp, int waitfor, int altflush); 704#define HFS_ALTFLUSH 1 705 706extern int hfs_extendfs(struct hfsmount *, u_int64_t, vfs_context_t); 707extern int hfs_truncatefs(struct hfsmount *, u_int64_t, vfs_context_t); 708extern int hfs_resize_progress(struct hfsmount *, u_int32_t *); 709 710/* If a runtime corruption is detected, mark the volume inconsistent 711 * bit in the volume attributes. 712 */ 713void hfs_mark_volume_inconsistent(struct hfsmount *hfsmp); 714 715void hfs_scan_blocks (struct hfsmount *hfsmp); 716 717/***************************************************************************** 718 Functions from hfs_vfsutils.c 719******************************************************************************/ 720u_int32_t BestBlockSizeFit(u_int32_t allocationBlockSize, 721 u_int32_t blockSizeLimit, 722 u_int32_t baseMultiple); 723 724#if CONFIG_HFS_STD 725OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, 726 struct proc *p); 727#endif 728OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, 729 off_t embeddedOffset, u_int64_t disksize, struct proc *p, void *args, kauth_cred_t cred); 730 731extern int hfsUnmount(struct hfsmount *hfsmp, struct proc *p); 732 733extern int overflow_extents(struct filefork *fp); 734 735extern int hfs_owner_rights(struct hfsmount *hfsmp, uid_t cnode_uid, kauth_cred_t cred, 736 struct proc *p, int invokesuperuserstatus); 737 738extern int check_for_tracked_file(struct vnode *vp, time_t ctime, uint64_t op_type, void *arg); 739extern int check_for_dataless_file(struct vnode *vp, uint64_t op_type); 740extern int hfs_generate_document_id(struct hfsmount *hfsmp, uint32_t *docid); 741 742 743/* 744 * Journal lock function prototypes 745 */ 746int hfs_lock_global (struct hfsmount *hfsmp, enum hfs_locktype locktype); 747void hfs_unlock_global (struct hfsmount *hfsmp); 748 749/* HFS mount lock/unlock prototypes */ 750void hfs_lock_mount (struct hfsmount *hfsmp); 751void hfs_unlock_mount (struct hfsmount *hfsmp); 752 753 754/* HFS System file locking */ 755#define SFL_CATALOG 0x0001 756#define SFL_EXTENTS 0x0002 757#define SFL_BITMAP 0x0004 758#define SFL_ATTRIBUTE 0x0008 759#define SFL_STARTUP 0x0010 760#define SFL_VALIDMASK (SFL_CATALOG | SFL_EXTENTS | SFL_BITMAP | SFL_ATTRIBUTE | SFL_STARTUP) 761 762extern int hfs_systemfile_lock(struct hfsmount *, int, enum hfs_locktype); 763extern void hfs_systemfile_unlock(struct hfsmount *, int); 764 765extern u_int32_t GetFileInfo(ExtendedVCB *vcb, u_int32_t dirid, const char *name, 766 struct cat_attr *fattr, struct cat_fork *forkinfo); 767 768extern void hfs_remove_orphans(struct hfsmount *); 769 770u_int32_t GetLogicalBlockSize(struct vnode *vp); 771 772extern u_int32_t hfs_freeblks(struct hfsmount * hfsmp, int wantreserve); 773 774short MacToVFSError(OSErr err); 775 776void hfs_metadatazone_init(struct hfsmount *hfsmp, int disable); 777 778/* HFS directory hint functions. */ 779extern directoryhint_t * hfs_getdirhint(struct cnode *, int, int); 780extern void hfs_reldirhint(struct cnode *, directoryhint_t *); 781extern void hfs_reldirhints(struct cnode *, int); 782extern void hfs_insertdirhint(struct cnode *, directoryhint_t *); 783 784extern int hfs_namecmp(const u_int8_t *str1, size_t len1, const u_int8_t *str2, size_t len2); 785 786extern int hfs_early_journal_init(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, 787 void *_args, off_t embeddedOffset, daddr64_t mdb_offset, 788 HFSMasterDirectoryBlock *mdbp, kauth_cred_t cred); 789 790extern int hfs_virtualmetafile(struct cnode *); 791 792extern int hfs_start_transaction(struct hfsmount *hfsmp); 793extern int hfs_end_transaction(struct hfsmount *hfsmp); 794extern int hfs_journal_flush(struct hfsmount *hfsmp, boolean_t wait_for_IO); 795extern void hfs_syncer_lock(struct hfsmount *hfsmp); 796extern void hfs_syncer_unlock(struct hfsmount *hfsmp); 797extern void hfs_syncer_wait(struct hfsmount *hfsmp); 798extern void hfs_syncer_wakeup(struct hfsmount *hfsmp); 799extern void hfs_syncer_queue(thread_call_t syncer); 800extern void hfs_sync_ejectable(struct hfsmount *hfsmp); 801 802extern void hfs_trim_callback(void *arg, uint32_t extent_count, const dk_extent_t *extents); 803 804/* Erase unused Catalog nodes due to <rdar://problem/6947811>. */ 805extern int hfs_erase_unused_nodes(struct hfsmount *hfsmp); 806 807extern uint64_t hfs_usecs_to_deadline(uint64_t usecs); 808 809 810/***************************************************************************** 811 Functions from hfs_vnops.c 812******************************************************************************/ 813int hfs_write_access(struct vnode *vp, kauth_cred_t cred, struct proc *p, Boolean considerFlags); 814 815int hfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct proc *p); 816 817int hfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred, struct proc *p); 818 819#define kMaxSecsForFsync 5 820#define HFS_SYNCTRANS 1 821extern int hfs_btsync(struct vnode *vp, int sync_transaction); 822 823extern void replace_desc(struct cnode *cp, struct cat_desc *cdp); 824 825extern int hfs_vgetrsrc(struct hfsmount *hfsmp, struct vnode *vp, 826 struct vnode **rvpp, int can_drop_lock, int error_on_unlink); 827 828extern int hfs_update(struct vnode *, int); 829 830 831/***************************************************************************** 832 Functions from hfs_xattr.c 833******************************************************************************/ 834 835/* 836 * Maximum extended attribute size supported for all extended attributes except 837 * resource fork and finder info. 838 */ 839#define HFS_XATTR_MAXSIZE INT32_MAX 840 841/* Number of bits used to represent maximum extended attribute size */ 842#define HFS_XATTR_SIZE_BITS 31 843 844int hfs_attrkeycompare(HFSPlusAttrKey *searchKey, HFSPlusAttrKey *trialKey); 845int hfs_buildattrkey(u_int32_t fileID, const char *attrname, HFSPlusAttrKey *key); 846void hfs_xattr_init(struct hfsmount * hfsmp); 847int file_attribute_exist(struct hfsmount *hfsmp, uint32_t fileID); 848int init_attrdata_vnode(struct hfsmount *hfsmp); 849int hfs_getxattr_internal(struct cnode *, struct vnop_getxattr_args *, 850 struct hfsmount *, u_int32_t); 851int hfs_setxattr_internal(struct cnode *, caddr_t, size_t, 852 struct vnop_setxattr_args *, struct hfsmount *, u_int32_t); 853 854 855 856/***************************************************************************** 857 Functions from hfs_link.c 858******************************************************************************/ 859 860extern int hfs_unlink(struct hfsmount *hfsmp, struct vnode *dvp, struct vnode *vp, 861 struct componentname *cnp, int skip_reserve); 862extern int hfs_lookup_siblinglinks(struct hfsmount *hfsmp, cnid_t linkfileid, 863 cnid_t *prevlinkid, cnid_t *nextlinkid); 864extern int hfs_lookup_lastlink(struct hfsmount *hfsmp, cnid_t linkfileid, 865 cnid_t *nextlinkid, struct cat_desc *cdesc); 866extern void hfs_privatedir_init(struct hfsmount *, enum privdirtype); 867 868extern void hfs_savelinkorigin(cnode_t *cp, cnid_t parentcnid); 869extern void hfs_relorigins(struct cnode *cp); 870extern void hfs_relorigin(struct cnode *cp, cnid_t parentcnid); 871extern int hfs_haslinkorigin(cnode_t *cp); 872extern cnid_t hfs_currentparent(cnode_t *cp); 873extern cnid_t hfs_currentcnid(cnode_t *cp); 874 875 876#endif /* __APPLE_API_PRIVATE */ 877#endif /* KERNEL */ 878#endif /* __HFS__ */ 879