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