master
  1/*	$NetBSD: libhfs.h,v 1.8.30.1 2023/07/31 15:47:20 martin 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
 69enum {
 70	HFS_SIG_HFSP	= 0x482B,	/* 'H+' */
 71	HFS_SIG_HFSX	= 0x4858,	/* 'HX' */
 72	HFS_SIG_HFS	= 0x4244	/* 'BD' */
 73}; /* volume signatures */
 74
 75typedef 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
 89typedef 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
 96enum {
 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
102typedef 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
117typedef 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
124enum {
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
130enum {
131	HFS_JOURNAL_HEADER_MAGIC	= 0x4a4e4c78,
132	HFS_JOURNAL_ENDIAN_MAGIC	= 0x12345678
133}; /* journal magic numbers */
134
135enum {
136	HFS_DATAFORK	= 0x00,
137	HFS_RSRCFORK	= 0xFF
138}; /* common fork types */
139
140enum {
141	HFS_KEY_CASEFOLD	= 0xCF,
142	HFS_KEY_BINARY		= 0XBC
143}; /* catalog key comparison method types */
144
145enum {
146	HFS_MIN_CAT_KEY_LEN	= 6,
147	HFS_MAX_CAT_KEY_LEN	= 516,
148	HFS_MAX_EXT_KEY_LEN	= 10
149};
150
151enum {
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
166typedef 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
178typedef uint32_t	hfs_macos_type_code; /* four 1-byte char field */
179
180typedef struct {
181	int16_t	v;
182	int16_t	h;
183} hfs_macos_point_t;
184
185typedef 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
192typedef 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
200typedef 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
207typedef 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
214typedef 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
228typedef uint16_t unichar_t;
229
230typedef uint32_t hfs_cnid_t;
231
232typedef struct {
233	uint16_t	length;
234	unichar_t	unicode[255];
235} hfs_unistr255_t;
236
237typedef struct {
238	uint32_t	start_block;
239	uint32_t	block_count;
240} hfs_extent_descriptor_t;
241
242typedef hfs_extent_descriptor_t hfs_extent_record_t[8];
243
244typedef 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
251typedef 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
287typedef 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
296typedef 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
314typedef struct {
315	uint16_t			key_len;
316	hfs_cnid_t			parent_cnid;
317	hfs_unistr255_t	name;
318} hfs_catalog_key_t;
319
320typedef 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
328typedef 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
341typedef 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
358typedef 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
377typedef 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
384typedef 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
392typedef 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
405typedef struct {
406	uint16_t        start_block;
407	uint16_t        block_count;
408} hfs_hfs_extent_descriptor_t;
409
410typedef hfs_hfs_extent_descriptor_t hfs_hfs_extent_record_t[3];
411
412typedef 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
449typedef 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
473typedef 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 */
506typedef 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
517typedef 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
543extern 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 */
549extern unichar_t* hfs_gcft;
550
551#if 0
552#pragma mark -
553#pragma mark Functions
554#endif
555
556void hfslib_init(hfs_callbacks*);
557void hfslib_done(void);
558void hfslib_init_cbargs(hfs_callback_args*);
559
560int hfslib_open_volume(const char*, int, hfs_volume*,
561	hfs_callback_args*);
562void hfslib_close_volume(hfs_volume*, hfs_callback_args*);
563
564int hfslib_path_to_cnid(hfs_volume*, hfs_cnid_t, char**, uint16_t*,
565	hfs_callback_args*);
566hfs_cnid_t hfslib_find_parent_thread(hfs_volume*, hfs_cnid_t,
567	hfs_thread_record_t*, hfs_callback_args*);
568int hfslib_find_catalog_record_with_cnid(hfs_volume*, hfs_cnid_t,
569	hfs_catalog_keyed_record_t*, hfs_catalog_key_t*, hfs_callback_args*);
570int hfslib_find_catalog_record_with_key(hfs_volume*, hfs_catalog_key_t*,
571	hfs_catalog_keyed_record_t*, hfs_callback_args*);
572int hfslib_find_extent_record_with_key(hfs_volume*, hfs_extent_key_t*,
573	hfs_extent_record_t*, hfs_callback_args*);
574int hfslib_get_directory_contents(hfs_volume*, hfs_cnid_t,
575	hfs_catalog_keyed_record_t**, hfs_unistr255_t**, uint32_t*,
576	hfs_callback_args*);
577int hfslib_is_journal_clean(hfs_volume*);
578int hfslib_is_private_file(hfs_catalog_key_t*);
579
580int hfslib_get_hardlink(hfs_volume *, uint32_t,
581			 hfs_catalog_keyed_record_t *, hfs_callback_args *);
582
583size_t hfslib_read_volume_header(void*, hfs_volume_header_t*);
584size_t hfslib_read_master_directory_block(void*,
585	hfs_hfs_master_directory_block_t*);
586size_t hfslib_reada_node(void*, hfs_node_descriptor_t*, void***, uint16_t**,
587	hfs_btree_file_type, hfs_volume*, hfs_callback_args*);
588size_t hfslib_reada_node_offsets(void*, uint16_t*, uint16_t);
589size_t hfslib_read_header_node(void**, uint16_t*, uint16_t,
590	hfs_header_record_t*, void*, void*);
591size_t hfslib_read_catalog_keyed_record(void*, hfs_catalog_keyed_record_t*,
592	int16_t*, hfs_catalog_key_t*, hfs_volume*);
593size_t hfslib_read_extent_record(void*, hfs_extent_record_t*, hfs_node_kind,
594	hfs_extent_key_t*, hfs_volume*);
595void hfslib_free_recs(void***, uint16_t**, uint16_t*, hfs_callback_args*);
596
597size_t hfslib_read_fork_descriptor(void*, hfs_fork_t*);
598size_t hfslib_read_extent_descriptors(void*, hfs_extent_record_t*);
599size_t hfslib_read_unistr255(void*, hfs_unistr255_t*);
600size_t hfslib_read_bsd_data(void*, hfs_bsd_data_t*);
601size_t hfslib_read_file_userinfo(void*, hfs_macos_file_info_t*);
602size_t hfslib_read_file_finderinfo(void*, hfs_macos_extended_file_info_t*);
603size_t hfslib_read_folder_userinfo(void*, hfs_macos_folder_info_t*);
604size_t hfslib_read_folder_finderinfo(void*, hfs_macos_extended_folder_info_t*);
605size_t hfslib_read_journal_info(void*, hfs_journal_info_t*);
606size_t hfslib_read_journal_header(void*, hfs_journal_header_t*);
607
608uint16_t hfslib_make_catalog_key(hfs_cnid_t, uint16_t, unichar_t*,
609	hfs_catalog_key_t*);
610uint16_t hfslib_make_extent_key(hfs_cnid_t, uint8_t, uint32_t,
611	hfs_extent_key_t*);
612uint16_t hfslib_get_file_extents(hfs_volume*, hfs_cnid_t, uint8_t,
613	hfs_extent_descriptor_t**, hfs_callback_args*);
614int hfslib_readd_with_extents(hfs_volume*, void*, uint64_t*, uint64_t,
615	uint64_t, hfs_extent_descriptor_t*, uint16_t, hfs_callback_args*);
616
617int hfslib_compare_catalog_keys_cf(const void*, const void*);
618int hfslib_compare_catalog_keys_bc(const void*, const void*);
619int hfslib_compare_extent_keys(const void*, const void*);
620
621
622/* callback wrappers */
623void hfslib_error(const char*, const char*, int, ...) __attribute__ ((format (printf, 1, 4)));
624void* hfslib_malloc(size_t, hfs_callback_args*);
625void* hfslib_realloc(void*, size_t, hfs_callback_args*);
626void hfslib_free(void*, hfs_callback_args*);
627int hfslib_openvoldevice(hfs_volume*, const char*, hfs_callback_args*);
628void hfslib_closevoldevice(hfs_volume*, hfs_callback_args*);
629int hfslib_readd(hfs_volume*, void*, uint64_t, uint64_t, hfs_callback_args*);
630
631#endif /* !_FS_HFS_LIBHFS_H_ */