| 1 | /*	$NetBSD: libhfs.h,v 1.9 2023/03/01 16:21:14 riastradh Exp $	*/ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 2005, 2007 The NetBSD Foundation, Inc. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * This code is derived from software contributed to The NetBSD Foundation |
| 8 | * by Yevgeny Binder, Dieter Baron, and Pelle Johansson. |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions |
| 12 | * are met: |
| 13 | * 1. Redistributions of source code must retain the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer. |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer in the |
| 17 | * documentation and/or other materials provided with the distribution. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
| 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 | * POSSIBILITY OF SUCH DAMAGE. |
| 30 | */ |
| 31 | |
| 32 | #ifndef _FS_HFS_LIBHFS_H_ |
| 33 | #define _FS_HFS_LIBHFS_H_ |
| 34 | |
| 35 | #include <sys/endian.h> |
| 36 | #include <sys/param.h> |
| 37 | #include <sys/mount.h>	/* needs to go after sys/param.h or compile fails */ |
| 38 | #include <sys/types.h> |
| 39 | #if defined(_KERNEL) |
| 40 | #include <sys/kernel.h> |
| 41 | #include <sys/systm.h> |
| 42 | #include <sys/fcntl.h> |
| 43 | #endif /* defined(_KERNEL) */ |
| 44 | |
| 45 | #if !defined(_KERNEL) && !defined(STANDALONE) |
| 46 | #include <fcntl.h> |
| 47 | #include <iconv.h> |
| 48 | #include <stdarg.h> |
| 49 | #include <stdint.h> |
| 50 | #include <stdio.h> |
| 51 | #include <stdlib.h> |
| 52 | #include <unistd.h> |
| 53 | #endif /* !defined(_KERNEL) && !defined(STANDALONE) */ |
| 54 | |
| 55 | #define max(A,B) ((A) > (B) ? (A):(B)) |
| 56 | #define min(A,B) ((A) < (B) ? (A):(B)) |
| 57 | |
| 58 | |
| 59 | /* Macros to handle errors in this library. Not recommended outside libhfs.c */ |
| 60 | #define HFS_LIBERR(format, ...) \ |
| 61 | 	do{ hfslib_error(format, __FILE__, __LINE__, ##__VA_ARGS__); \ |
| 62 | 		goto error; } while(/*CONSTCOND*/ 0) |
| 63 | |
| 64 | #if 0 |
| 65 | #pragma mark Constants (on-disk) |
| 66 | #endif |
| 67 | |
| 68 | |
| 69 | enum { |
| 70 | 	HFS_SIG_HFSP	= 0x482B,	/* 'H+' */ |
| 71 | 	HFS_SIG_HFSX	= 0x4858,	/* 'HX' */ |
| 72 | 	HFS_SIG_HFS	= 0x4244	/* 'BD' */ |
| 73 | }; /* volume signatures */ |
| 74 | |
| 75 | typedef enum { |
| 76 | 							/* bits 0-6 are reserved */ |
| 77 | 	HFS_VOL_HWLOCK			= 7, |
| 78 | 	HFS_VOL_UNMOUNTED		= 8, |
| 79 | 	HFS_VOL_BADBLOCKS		= 9, |
| 80 | 	HFS_VOL_NOCACHE		= 10, |
| 81 | 	HFS_VOL_DIRTY			= 11, |
| 82 | 	HFS_VOL_CNIDS_RECYCLED	= 12, |
| 83 | 	HFS_VOL_JOURNALED		= 13, |
| 84 | 							/* bit 14 is reserved */ |
| 85 | 	HFS_VOL_SWLOCK			= 15 |
| 86 | 							/* bits 16-31 are reserved */ |
| 87 | } hfs_volume_attribute_bit; /* volume header attribute bits */ |
| 88 | |
| 89 | typedef enum { |
| 90 | 	HFS_LEAFNODE	= -1, |
| 91 | 	HFS_INDEXNODE	= 0, |
| 92 | 	HFS_HEADERNODE	= 1, |
| 93 | 	HFS_MAPNODE	= 2 |
| 94 | } hfs_node_kind; /* btree node kinds */ |
| 95 | |
| 96 | enum { |
| 97 | 	HFS_BAD_CLOSE_MASK			= 0x00000001, |
| 98 | 	HFS_BIG_KEYS_MASK			= 0x00000002, |
| 99 | 	HFS_VAR_INDEX_KEYS_MASK	= 0x00000004 |
| 100 | }; /* btree header attribute masks */ |
| 101 | |
| 102 | typedef enum { |
| 103 | 	HFS_CNID_ROOT_PARENT	= 1, |
| 104 | 	HFS_CNID_ROOT_FOLDER	= 2, |
| 105 | 	HFS_CNID_EXTENTS		= 3, |
| 106 | 	HFS_CNID_CATALOG		= 4, |
| 107 | 	HFS_CNID_BADBLOCKS		= 5, |
| 108 | 	HFS_CNID_ALLOCATION	= 6, |
| 109 | 	HFS_CNID_STARTUP		= 7, |
| 110 | 	HFS_CNID_ATTRIBUTES	= 8, |
| 111 | 								/* CNIDs 9-13 are reserved */ |
| 112 | 	HFS_CNID_REPAIR		= 14, |
| 113 | 	HFS_CNID_TEMP			= 15, |
| 114 | 	HFS_CNID_USER			= 16 |
| 115 | } hfs_special_cnid; /* special CNID values */ |
| 116 | |
| 117 | typedef enum { |
| 118 | 	HFS_REC_FLDR			= 0x0001, |
| 119 | 	HFS_REC_FILE			= 0x0002, |
| 120 | 	HFS_REC_FLDR_THREAD	= 0x0003, |
| 121 | 	HFS_REC_FILE_THREAD	= 0x0004 |
| 122 | } hfs_catalog_rec_kind; /* catalog record types */ |
| 123 | |
| 124 | enum { |
| 125 | 	HFS_JOURNAL_ON_DISK_MASK		= 0x00000001, /* journal on same volume */ |
| 126 | 	HFS_JOURNAL_ON_OTHER_MASK		= 0x00000002, /* journal elsewhere */ |
| 127 | 	HFS_JOURNAL_NEEDS_INIT_MASK	= 0x00000004 |
| 128 | }; /* journal flag masks */ |
| 129 | |
| 130 | enum { |
| 131 | 	HFS_JOURNAL_HEADER_MAGIC	= 0x4a4e4c78, |
| 132 | 	HFS_JOURNAL_ENDIAN_MAGIC	= 0x12345678 |
| 133 | }; /* journal magic numbers */ |
| 134 | |
| 135 | enum { |
| 136 | 	HFS_DATAFORK	= 0x00, |
| 137 | 	HFS_RSRCFORK	= 0xFF |
| 138 | }; /* common fork types */ |
| 139 | |
| 140 | enum { |
| 141 | 	HFS_KEY_CASEFOLD	= 0xCF, |
| 142 | 	HFS_KEY_BINARY		= 0XBC |
| 143 | }; /* catalog key comparison method types */ |
| 144 | |
| 145 | enum { |
| 146 | 	HFS_MIN_CAT_KEY_LEN	= 6, |
| 147 | 	HFS_MAX_CAT_KEY_LEN	= 516, |
| 148 | 	HFS_MAX_EXT_KEY_LEN	= 10 |
| 149 | }; |
| 150 | |
| 151 | enum { |
| 152 | 	HFS_HARD_LINK_FILE_TYPE = 0x686C6E6B, /* 'hlnk' */ |
| 153 | 	HFS_HFSLUS_CREATOR = 0x6866732B /* 'hfs+' */ |
| 154 | }; |
| 155 | |
| 156 | |
| 157 | #if 0 |
| 158 | #pragma mark - |
| 159 | #pragma mark Constants (custom) |
| 160 | #endif |
| 161 | |
| 162 | |
| 163 | /* number of bytes between start of volume and volume header */ |
| 164 | #define HFS_VOLUME_HEAD_RESERVE_SIZE	1024 |
| 165 | |
| 166 | typedef enum { |
| 167 | 	HFS_CATALOG_FILE = 1, |
| 168 | 	HFS_EXTENTS_FILE = 2, |
| 169 | 	HFS_ATTRIBUTES_FILE = 3 |
| 170 | } hfs_btree_file_type; /* btree file kinds */ |
| 171 | |
| 172 | |
| 173 | #if 0 |
| 174 | #pragma mark - |
| 175 | #pragma mark On-Disk Types (Mac OS specific) |
| 176 | #endif |
| 177 | |
| 178 | typedef uint32_t	hfs_macos_type_code; /* four 1-byte char field */ |
| 179 | |
| 180 | typedef struct { |
| 181 | 	int16_t	v; |
| 182 | 	int16_t	h; |
| 183 | } hfs_macos_point_t; |
| 184 | |
| 185 | typedef struct { |
| 186 | 	int16_t	t;	/* top */ |
| 187 | 	int16_t	l;	/* left */ |
| 188 | 	int16_t	b;	/* bottom */ |
| 189 | 	int16_t	r;	/* right */ |
| 190 | } hfs_macos_rect_t; |
| 191 | |
| 192 | typedef struct { |
| 193 | 	hfs_macos_type_code	file_type; |
| 194 | 	hfs_macos_type_code	file_creator; |
| 195 | 	uint16_t				finder_flags; |
| 196 | 	hfs_macos_point_t	location; |
| 197 | 	uint16_t				reserved; |
| 198 | } hfs_macos_file_info_t; |
| 199 | |
| 200 | typedef struct { |
| 201 | 	int16_t	reserved[4]; |
| 202 | 	uint16_t	extended_finder_flags; |
| 203 | 	int16_t	reserved2; |
| 204 | 	int32_t	put_away_folder_cnid; |
| 205 | } hfs_macos_extended_file_info_t; |
| 206 | |
| 207 | typedef struct { |
| 208 | 	hfs_macos_rect_t		window_bounds; |
| 209 | 	uint16_t				finder_flags; |
| 210 | 	hfs_macos_point_t	location; |
| 211 | 	uint16_t				reserved; |
| 212 | } hfs_macos_folder_info_t; |
| 213 | |
| 214 | typedef struct { |
| 215 | 	hfs_macos_point_t	scroll_position; |
| 216 | 	int32_t				reserved; |
| 217 | 	uint16_t				extended_finder_flags; |
| 218 | 	int16_t				reserved2; |
| 219 | 	int32_t				put_away_folder_cnid; |
| 220 | } hfs_macos_extended_folder_info_t; |
| 221 | |
| 222 | |
| 223 | #if 0 |
| 224 | #pragma mark - |
| 225 | #pragma mark On-Disk Types |
| 226 | #endif |
| 227 | |
| 228 | typedef uint16_t unichar_t; |
| 229 | |
| 230 | typedef uint32_t hfs_cnid_t; |
| 231 | |
| 232 | typedef struct { |
| 233 | 	uint16_t	length; |
| 234 | 	unichar_t	unicode[255]; |
| 235 | } hfs_unistr255_t; |
| 236 | |
| 237 | typedef struct { |
| 238 | 	uint32_t	start_block; |
| 239 | 	uint32_t	block_count; |
| 240 | } hfs_extent_descriptor_t; |
| 241 | |
| 242 | typedef hfs_extent_descriptor_t hfs_extent_record_t[8]; |
| 243 | |
| 244 | typedef struct hfs_fork_t { |
| 245 | 	uint64_t				logical_size; |
| 246 | 	uint32_t				clump_size; |
| 247 | 	uint32_t				total_blocks; |
| 248 | 	hfs_extent_record_t	extents; |
| 249 | } hfs_fork_t; |
| 250 | |
| 251 | typedef struct { |
| 252 | 	uint16_t	signature; |
| 253 | 	uint16_t	version; |
| 254 | 	uint32_t	attributes; |
| 255 | 	uint32_t	last_mounting_version; |
| 256 | 	uint32_t	journal_info_block; |
| 257 | |
| 258 | 	uint32_t	date_created; |
| 259 | 	uint32_t	date_modified; |
| 260 | 	uint32_t	date_backedup; |
| 261 | 	uint32_t	date_checked; |
| 262 | |
| 263 | 	uint32_t	file_count; |
| 264 | 	uint32_t	folder_count; |
| 265 | |
| 266 | 	uint32_t	block_size; |
| 267 | 	uint32_t	total_blocks; |
| 268 | 	uint32_t	free_blocks; |
| 269 | |
| 270 | 	uint32_t	next_alloc_block; |
| 271 | 	uint32_t	rsrc_clump_size; |
| 272 | 	uint32_t	data_clump_size; |
| 273 | 	hfs_cnid_t	next_cnid; |
| 274 | |
| 275 | 	uint32_t	write_count; |
| 276 | 	uint64_t	encodings; |
| 277 | |
| 278 | 	uint32_t	finder_info[8]; |
| 279 | |
| 280 | 	hfs_fork_t	allocation_file; |
| 281 | 	hfs_fork_t	extents_file; |
| 282 | 	hfs_fork_t	catalog_file; |
| 283 | 	hfs_fork_t	attributes_file; |
| 284 | 	hfs_fork_t	startup_file; |
| 285 | } hfs_volume_header_t; |
| 286 | |
| 287 | typedef struct { |
| 288 | 	uint32_t	flink; |
| 289 | 	uint32_t	blink; |
| 290 | 	int8_t		kind; |
| 291 | 	uint8_t		height; |
| 292 | 	uint16_t	num_recs; |
| 293 | 	uint16_t	reserved; |
| 294 | } hfs_node_descriptor_t; |
| 295 | |
| 296 | typedef struct { |
| 297 | 	uint16_t	tree_depth; |
| 298 | 	uint32_t	root_node; |
| 299 | 	uint32_t	leaf_recs; |
| 300 | 	uint32_t	first_leaf; |
| 301 | 	uint32_t	last_leaf; |
| 302 | 	uint16_t	node_size; |
| 303 | 	uint16_t	max_key_len; |
| 304 | 	uint32_t	total_nodes; |
| 305 | 	uint32_t	free_nodes; |
| 306 | 	uint16_t	reserved; |
| 307 | 	uint32_t	clump_size;		/* misaligned */ |
| 308 | 	uint8_t		btree_type; |
| 309 | 	uint8_t		keycomp_type; |
| 310 | 	uint32_t	attributes;		/* long aligned again */ |
| 311 | 	uint32_t	reserved2[16]; |
| 312 | } hfs_header_record_t; |
| 313 | |
| 314 | typedef struct { |
| 315 | 	uint16_t			key_len; |
| 316 | 	hfs_cnid_t			parent_cnid; |
| 317 | 	hfs_unistr255_t	name; |
| 318 | } hfs_catalog_key_t; |
| 319 | |
| 320 | typedef struct { |
| 321 | 	uint16_t	key_length; |
| 322 | 	uint8_t		fork_type; |
| 323 | 	uint8_t		padding; |
| 324 | 	hfs_cnid_t	file_cnid; |
| 325 | 	uint32_t	start_block; |
| 326 | } hfs_extent_key_t; |
| 327 | |
| 328 | typedef struct { |
| 329 | 	uint32_t	owner_id; |
| 330 | 	uint32_t	group_id; |
| 331 | 	uint8_t		admin_flags; |
| 332 | 	uint8_t		owner_flags; |
| 333 | 	uint16_t	file_mode; |
| 334 | 	union { |
| 335 | 		uint32_t	inode_num; |
| 336 | 		uint32_t	link_count; |
| 337 | 		uint32_t	raw_device; |
| 338 | 	} special; |
| 339 | } hfs_bsd_data_t; |
| 340 | |
| 341 | typedef struct { |
| 342 | 	int16_t			rec_type; |
| 343 | 	uint16_t		flags; |
| 344 | 	uint32_t		valence; |
| 345 | 	hfs_cnid_t		cnid; |
| 346 | 	uint32_t		date_created; |
| 347 | 	uint32_t		date_content_mod; |
| 348 | 	uint32_t		date_attrib_mod; |
| 349 | 	uint32_t		date_accessed; |
| 350 | 	uint32_t		date_backedup; |
| 351 | 	hfs_bsd_data_t						bsd; |
| 352 | 	hfs_macos_folder_info_t			user_info; |
| 353 | 	hfs_macos_extended_folder_info_t	finder_info; |
| 354 | 	uint32_t		text_encoding; |
| 355 | 	uint32_t		reserved; |
| 356 | } hfs_folder_record_t; |
| 357 | |
| 358 | typedef struct { |
| 359 | 	int16_t			rec_type; |
| 360 | 	uint16_t		flags; |
| 361 | 	uint32_t		reserved; |
| 362 | 	hfs_cnid_t		cnid; |
| 363 | 	uint32_t		date_created; |
| 364 | 	uint32_t		date_content_mod; |
| 365 | 	uint32_t		date_attrib_mod; |
| 366 | 	uint32_t		date_accessed; |
| 367 | 	uint32_t		date_backedup; |
| 368 | 	hfs_bsd_data_t						bsd; |
| 369 | 	hfs_macos_file_info_t				user_info; |
| 370 | 	hfs_macos_extended_file_info_t		finder_info; |
| 371 | 	uint32_t		text_encoding; |
| 372 | 	uint32_t		reserved2; |
| 373 | 	hfs_fork_t		data_fork; |
| 374 | 	hfs_fork_t		rsrc_fork; |
| 375 | } hfs_file_record_t; |
| 376 | |
| 377 | typedef struct { |
| 378 | 	int16_t				rec_type; |
| 379 | 	int16_t				reserved; |
| 380 | 	hfs_cnid_t			parent_cnid; |
| 381 | 	hfs_unistr255_t	name; |
| 382 | } hfs_thread_record_t; |
| 383 | |
| 384 | typedef struct { |
| 385 | 	uint32_t	flags; |
| 386 | 	uint32_t	device_signature[8]; |
| 387 | 	uint64_t	offset; |
| 388 | 	uint64_t	size; |
| 389 | 	uint64_t	reserved[32]; |
| 390 | } hfs_journal_info_t; |
| 391 | |
| 392 | typedef struct { |
| 393 | 	uint32_t	magic; |
| 394 | 	uint32_t	endian; |
| 395 | 	uint64_t	start; |
| 396 | 	uint64_t	end; |
| 397 | 	uint64_t	size; |
| 398 | 	uint32_t	blocklist_header_size; |
| 399 | 	uint32_t	checksum; |
| 400 | 	uint32_t	journal_header_size; |
| 401 | } hfs_journal_header_t; |
| 402 | |
| 403 | /* plain HFS structures needed for hfs wrapper support */ |
| 404 | |
| 405 | typedef struct { |
| 406 | 	uint16_t start_block; |
| 407 | 	uint16_t block_count; |
| 408 | } hfs_hfs_extent_descriptor_t; |
| 409 | |
| 410 | typedef hfs_hfs_extent_descriptor_t hfs_hfs_extent_record_t[3]; |
| 411 | |
| 412 | typedef struct { |
| 413 | 	uint16_t signature; |
| 414 | 	uint32_t date_created; |
| 415 | 	uint32_t date_modified; |
| 416 | 	uint16_t attributes; |
| 417 | 	uint16_t root_file_count; |
| 418 | 	uint16_t volume_bitmap; |
| 419 | 	uint16_t next_alloc_block; |
| 420 | 	uint16_t total_blocks; |
| 421 | 	uint32_t block_size; |
| 422 | 	uint32_t clump_size; |
| 423 | 	uint16_t first_block; |
| 424 | 	hfs_cnid_t next_cnid; |
| 425 | 	uint16_t free_blocks; |
| 426 | 	unsigned char volume_name[28]; |
| 427 | 	uint32_t date_backedup; |
| 428 | 	uint16_t backup_seqnum; |
| 429 | 	uint32_t write_count; |
| 430 | 	uint32_t extents_clump_size; |
| 431 | 	uint32_t catalog_clump_size; |
| 432 | 	uint16_t root_folder_count; |
| 433 | 	uint32_t file_count; |
| 434 | 	uint32_t folder_count; |
| 435 | 	uint32_t finder_info[8]; |
| 436 | 	uint16_t embedded_signature; |
| 437 | 	hfs_hfs_extent_descriptor_t embedded_extent; |
| 438 | 	uint32_t extents_size; |
| 439 | 	hfs_hfs_extent_record_t extents_extents; |
| 440 | 	uint32_t catalog_size; |
| 441 | 	hfs_hfs_extent_record_t catalog_extents; |
| 442 | } hfs_hfs_master_directory_block_t; |
| 443 | |
| 444 | #if 0 |
| 445 | #pragma mark - |
| 446 | #pragma mark Custom Types |
| 447 | #endif |
| 448 | |
| 449 | typedef struct { |
| 450 | 	hfs_volume_header_t	vh;		/* volume header */ |
| 451 | 	hfs_header_record_t	chr;	/* catalog file header node record*/ |
| 452 | 	hfs_header_record_t	ehr;	/* extent overflow file header node record*/ |
| 453 | 	uint8_t	catkeysizefieldsize;	/* size of catalog file key_len field in |
| 454 | 									 * bytes (1 or 2); always 2 for HFS+ */ |
| 455 | 	uint8_t	extkeysizefieldsize;	/* size of extent file key_len field in |
| 456 | 									 * bytes (1 or 2); always 2 for HFS+ */ |
| 457 | 	hfs_unistr255_t		name;	/* volume name */ |
| 458 | |
| 459 | 	/* pointer to catalog file key comparison function */ |
| 460 | 	int (*keycmp) (const void*, const void*); |
| 461 | |
| 462 | 	int						journaled;	/* 1 if volume is journaled, else 0 */ |
| 463 | 	hfs_journal_info_t		jib;	/* journal info block */ |
| 464 | 	hfs_journal_header_t	jh;		/* journal header */ |
| 465 | |
| 466 | 	uint64_t offset;	/* offset, in bytes, of HFS+ volume */ |
| 467 | 	int		readonly;	/* 0 if mounted r/w, 1 if mounted r/o */ |
| 468 | 	void*	cbdata;		/* application-specific data; allocated, defined and |
| 469 | 						 * used (if desired) by the program, usually within |
| 470 | 						 * callback routines */ |
| 471 | } hfs_volume; |
| 472 | |
| 473 | typedef union { |
| 474 | 	/* for leaf nodes */ |
| 475 | 	int16_t					type; /* type of record: folder, file, or thread */ |
| 476 | 	hfs_folder_record_t	folder; |
| 477 | 	hfs_file_record_t		file; |
| 478 | 	hfs_thread_record_t	thread; |
| 479 | |
| 480 | 	/* for pointer nodes */ |
| 481 | 	/* (using this large union for just one tiny field is not memory-efficient, |
| 482 | 	 *	 so change this if it becomes problematic) */ |
| 483 | 	uint32_t	child;	/* node number of this node's child node */ |
| 484 | } hfs_catalog_keyed_record_t; |
| 485 | |
| 486 | /* |
| 487 | * These arguments are passed among libhfs without any inspection. This struct |
| 488 | * is accepted by all public functions of libhfs, and passed to each callback. |
| 489 | * An application dereferences each pointer to its own specific struct of |
| 490 | * arguments. Callbacks must be prepared to deal with NULL values for any of |
| 491 | * these fields (by providing default values to be used in lieu of that |
| 492 | * argument). However, a NULL pointer to this struct is an error. |
| 493 | * |
| 494 | * It was decided to make one unified argument structure, rather than many |
| 495 | * separate, operand-specific structures, because, when this structure is passed |
| 496 | * to a public function (e.g., hfslib_open_volume()), the function may make |
| 497 | * several calls (and subcalls) to various facilities, e.g., read(), malloc(), |
| 498 | * and free(), all of which require their own particular arguments. The |
| 499 | * facilities to be used are quite impractical to foreshadow, so the application |
| 500 | * takes care of all possible calls at once. This also reinforces the idea that |
| 501 | * a public call is an umbrella to a set of system calls, and all of these calls |
| 502 | * must be passed arguments which do not change within the context of this |
| 503 | * umbrella. (E.g., if a public function makes two calls to read(), one call |
| 504 | * should not be passed a uid of root and the other passed a uid of daemon.) |
| 505 | */ |
| 506 | typedef struct { |
| 507 | 	/* The 'error' function does not take an argument. All others do. */ |
| 508 | |
| 509 | 	void*	allocmem; |
| 510 | 	void*	reallocmem; |
| 511 | 	void*	freemem; |
| 512 | 	void*	openvol; |
| 513 | 	void*	closevol; |
| 514 | 	void*	read; |
| 515 | } hfs_callback_args; |
| 516 | |
| 517 | typedef struct { |
| 518 | 	/* error(in_format, in_file, in_line, in_args) */ |
| 519 | 	void (*error) (const char*, const char*, int, va_list); |
| 520 | |
| 521 | 	/* allocmem(in_size, cbargs) */ |
| 522 | 	void* (*allocmem) (size_t, hfs_callback_args*); |
| 523 | |
| 524 | 	/* reallocmem(in_ptr, in_size, cbargs) */ |
| 525 | 	void* (*reallocmem) (void*, size_t, hfs_callback_args*); |
| 526 | |
| 527 | 	/* freemem(in_ptr, cbargs) */ |
| 528 | 	void (*freemem) (void*, hfs_callback_args*); |
| 529 | |
| 530 | 	/* openvol(in_volume, in_devicepath, cbargs) |
| 531 | 	 * returns 0 on success */ |
| 532 | 	int (*openvol) (hfs_volume*, const char*, hfs_callback_args*); |
| 533 | |
| 534 | 	/* closevol(in_volume, cbargs) */ |
| 535 | 	void (*closevol) (hfs_volume*, hfs_callback_args*); |
| 536 | |
| 537 | 	/* read(in_volume, out_buffer, in_length, in_offset, cbargs) |
| 538 | 	 * returns 0 on success */ |
| 539 | 	int (*read) (hfs_volume*, void*, uint64_t, uint64_t, |
| 540 | 		hfs_callback_args*); |
| 541 | } hfs_callbacks; |
| 542 | |
| 543 | extern hfs_callbacks	hfs_gcb;	/* global callbacks */ |
| 544 | |
| 545 | /* |
| 546 | * global case folding table |
| 547 | * (lazily initialized; see comments at bottom of hfs_open_volume()) |
| 548 | */ |
| 549 | extern unichar_t* hfs_gcft; |
| 550 | |
| 551 | #if 0 |
| 552 | #pragma mark - |
| 553 | #pragma mark Functions |
| 554 | #endif |
| 555 | |
| 556 | void hfslib_init(hfs_callbacks*); |
| 557 | void hfslib_done(void); |
| 558 | void hfslib_init_cbargs(hfs_callback_args*); |
| 559 | |
| 560 | int hfslib_open_volume(const char*, int, hfs_volume*, |
| 561 | 	hfs_callback_args*); |
| 562 | void hfslib_close_volume(hfs_volume*, hfs_callback_args*); |
| 563 | |
| 564 | int hfslib_path_to_cnid(hfs_volume*, hfs_cnid_t, char**, uint16_t*, |
| 565 | 	hfs_callback_args*); |
| 566 | hfs_cnid_t hfslib_find_parent_thread(hfs_volume*, hfs_cnid_t, |
| 567 | 	hfs_thread_record_t*, hfs_callback_args*); |
| 568 | int hfslib_find_catalog_record_with_cnid(hfs_volume*, hfs_cnid_t, |
| 569 | 	hfs_catalog_keyed_record_t*, hfs_catalog_key_t*, hfs_callback_args*); |
| 570 | int hfslib_find_catalog_record_with_key(hfs_volume*, hfs_catalog_key_t*, |
| 571 | 	hfs_catalog_keyed_record_t*, hfs_callback_args*); |
| 572 | int hfslib_find_extent_record_with_key(hfs_volume*, hfs_extent_key_t*, |
| 573 | 	hfs_extent_record_t*, hfs_callback_args*); |
| 574 | int hfslib_get_directory_contents(hfs_volume*, hfs_cnid_t, |
| 575 | 	hfs_catalog_keyed_record_t**, hfs_unistr255_t**, uint32_t*, |
| 576 | 	hfs_callback_args*); |
| 577 | int hfslib_is_journal_clean(hfs_volume*); |
| 578 | int hfslib_is_private_file(hfs_catalog_key_t*); |
| 579 | |
| 580 | int hfslib_get_hardlink(hfs_volume *, uint32_t, |
| 581 | 			 hfs_catalog_keyed_record_t *, hfs_callback_args *); |
| 582 | |
| 583 | size_t hfslib_read_volume_header(void*, hfs_volume_header_t*); |
| 584 | size_t hfslib_read_master_directory_block(void*, |
| 585 | 	hfs_hfs_master_directory_block_t*); |
| 586 | size_t hfslib_reada_node(void*, hfs_node_descriptor_t*, void***, uint16_t**, |
| 587 | 	hfs_btree_file_type, hfs_volume*, hfs_callback_args*); |
| 588 | size_t hfslib_reada_node_offsets(void*, uint16_t*, uint16_t); |
| 589 | size_t hfslib_read_header_node(void**, uint16_t*, uint16_t, |
| 590 | 	hfs_header_record_t*, void*, void*); |
| 591 | size_t hfslib_read_catalog_keyed_record(void*, hfs_catalog_keyed_record_t*, |
| 592 | 	int16_t*, hfs_catalog_key_t*, hfs_volume*); |
| 593 | size_t hfslib_read_extent_record(void*, hfs_extent_record_t*, hfs_node_kind, |
| 594 | 	hfs_extent_key_t*, hfs_volume*); |
| 595 | void hfslib_free_recs(void***, uint16_t**, uint16_t*, hfs_callback_args*); |
| 596 | |
| 597 | size_t hfslib_read_fork_descriptor(void*, hfs_fork_t*); |
| 598 | size_t hfslib_read_extent_descriptors(void*, hfs_extent_record_t*); |
| 599 | size_t hfslib_read_unistr255(void*, hfs_unistr255_t*); |
| 600 | size_t hfslib_read_bsd_data(void*, hfs_bsd_data_t*); |
| 601 | size_t hfslib_read_file_userinfo(void*, hfs_macos_file_info_t*); |
| 602 | size_t hfslib_read_file_finderinfo(void*, hfs_macos_extended_file_info_t*); |
| 603 | size_t hfslib_read_folder_userinfo(void*, hfs_macos_folder_info_t*); |
| 604 | size_t hfslib_read_folder_finderinfo(void*, hfs_macos_extended_folder_info_t*); |
| 605 | size_t hfslib_read_journal_info(void*, hfs_journal_info_t*); |
| 606 | size_t hfslib_read_journal_header(void*, hfs_journal_header_t*); |
| 607 | |
| 608 | uint16_t hfslib_make_catalog_key(hfs_cnid_t, uint16_t, unichar_t*, |
| 609 | 	hfs_catalog_key_t*); |
| 610 | uint16_t hfslib_make_extent_key(hfs_cnid_t, uint8_t, uint32_t, |
| 611 | 	hfs_extent_key_t*); |
| 612 | uint16_t hfslib_get_file_extents(hfs_volume*, hfs_cnid_t, uint8_t, |
| 613 | 	hfs_extent_descriptor_t**, hfs_callback_args*); |
| 614 | int hfslib_readd_with_extents(hfs_volume*, void*, uint64_t*, uint64_t, |
| 615 | 	uint64_t, hfs_extent_descriptor_t*, uint16_t, hfs_callback_args*); |
| 616 | |
| 617 | int hfslib_compare_catalog_keys_cf(const void*, const void*); |
| 618 | int hfslib_compare_catalog_keys_bc(const void*, const void*); |
| 619 | int hfslib_compare_extent_keys(const void*, const void*); |
| 620 | |
| 621 | |
| 622 | /* callback wrappers */ |
| 623 | void hfslib_error(const char*, const char*, int, ...) __attribute__ ((format (printf, 1, 4))); |
| 624 | void* hfslib_malloc(size_t, hfs_callback_args*); |
| 625 | void* hfslib_realloc(void*, size_t, hfs_callback_args*); |
| 626 | void hfslib_free(void*, hfs_callback_args*); |
| 627 | int hfslib_openvoldevice(hfs_volume*, const char*, hfs_callback_args*); |
| 628 | void hfslib_closevoldevice(hfs_volume*, hfs_callback_args*); |
| 629 | int hfslib_readd(hfs_volume*, void*, uint64_t, uint64_t, hfs_callback_args*); |
| 630 | |
| 631 | #endif /* !_FS_HFS_LIBHFS_H_ */ |