2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #pragma segment Catalog
28 #include <sys/param.h>
29 #include <sys/utfconv.h>
31 #include "../../hfs_endian.h"
33 #include "../headers/FileMgrInternal.h"
34 #include "../headers/BTreesInternal.h"
35 #include "../headers/CatalogPrivate.h"
36 #include "../headers/HFSUnicodeWrappers.h"
41 extern SInt32
FastRelString( ConstStr255Param str1
, ConstStr255Param str2
);
44 //_________________________________________________________________________________
47 // CompareCatalogKeys - Compares two catalog keys.
49 //_________________________________________________________________________________
54 GetDirEntrySize(BTreeIterator
*bip
, ExtendedVCB
* vol
)
59 UInt8 name
[kdirentMaxNameBytes
+ 1];
62 ckp
= (CatalogKey
*) &bip
->key
;
64 if (vol
->vcbSigWord
== kHFSPlusSigWord
) {
65 cnp
= (CatalogName
*) &ckp
->hfsPlus
.nodeName
;
66 utf8chars
= utf8_encodelen(cnp
->ustr
.unicode
,
67 cnp
->ustr
.length
* sizeof(UniChar
), ':', 0);
68 if (utf8chars
> kdirentMaxNameBytes
)
69 utf8chars
= kdirentMaxNameBytes
;
71 cnp
= (CatalogName
*) ckp
->hfs
.nodeName
;
72 result
= hfs_to_utf8(vol
, cnp
->pstr
, kdirentMaxNameBytes
+ 1,
76 * When an HFS name cannot be encoded with the current
77 * volume encoding we use MacRoman as a fallback.
79 result
= mac_roman_to_utf8(cnp
->pstr
, MAXHFSVNODELEN
+ 1,
84 return DIRENTRY_SIZE(utf8chars
);
87 * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
89 * This is assuming maxinum size of a name is 255 (kdirentMaxNameBytes), which is incorrect.
90 * Any caller of this has to make sure names > 255 are mangled!!!!!!!!
94 PositionIterator(CatalogIterator
*cip
, UInt32 offset
, BTreeIterator
*bip
, UInt16
*op
)
96 #define CAT_START_OFFSET (2 * sizeof(struct hfsdotentry))
101 /* are we past the end of a directory? */
102 if (cip
->folderID
!= cip
->parentID
)
106 fcb
= GetFileControlBlock(vol
->catalogRefNum
);
108 /* make a btree iterator from catalog iterator */
109 UpdateBtreeIterator(cip
, bip
);
111 if (cip
->currentOffset
== offset
) {
112 *op
= kBTreeCurrentRecord
;
114 } else if (cip
->nextOffset
== offset
) {
115 *op
= kBTreeNextRecord
;
117 } else { /* start from beginning */
118 *op
= kBTreeNextRecord
;
120 /* Position iterator at the folder's thread record */
121 result
= BTSearchRecord(fcb
, bip
, NULL
, NULL
, bip
);
125 /* find offset (note: n^2 / 2) */
126 if (offset
> CAT_START_OFFSET
) {
127 HFSCatalogNodeID pid
, *idp
;
128 UInt32 curOffset
, nextOffset
;
130 /* get first record (ie offset 24) */
131 result
= BTIterateRecord( fcb
, kBTreeNextRecord
, bip
, NULL
, NULL
);
135 if (vol
->vcbSigWord
== kHFSPlusSigWord
)
136 idp
= &((CatalogKey
*) &bip
->key
)->hfsPlus
.parentID
;
138 idp
= &((CatalogKey
*) &bip
->key
)->hfs
.parentID
;
142 curOffset
= CAT_START_OFFSET
;
143 nextOffset
= CAT_START_OFFSET
+ GetDirEntrySize(bip
, vol
);
145 while (nextOffset
< offset
) {
146 result
= BTIterateRecord( fcb
, kBTreeNextRecord
, bip
, NULL
, NULL
);
150 /* check for parent change */
152 result
= cmNotFound
; /* offset past end of directory */
156 curOffset
= nextOffset
;
157 nextOffset
+= GetDirEntrySize(bip
, vol
);
160 if (nextOffset
!= offset
) {
165 UpdateCatalogIterator(bip
, cip
);
166 cip
->currentOffset
= curOffset
;
167 cip
->nextOffset
= nextOffset
;
172 if (result
== btNotFound
)
177 } /* end PositionIterator */
180 //_________________________________________________________________________________
181 // Routine: CompareCatalogKeys
183 // Function: Compares two catalog keys (a search key and a trial key).
185 // Result: +n search key > trial key
186 // 0 search key = trial key
187 // -n search key < trial key
188 //_________________________________________________________________________________
191 CompareCatalogKeys(HFSCatalogKey
*searchKey
, HFSCatalogKey
*trialKey
)
193 HFSCatalogNodeID searchParentID
, trialParentID
;
196 searchParentID
= searchKey
->parentID
;
197 trialParentID
= trialKey
->parentID
;
199 if ( searchParentID
> trialParentID
) // parent dirID is unsigned
201 else if ( searchParentID
< trialParentID
)
203 else // parent dirID's are equal, compare names
204 result
= FastRelString(searchKey
->nodeName
, trialKey
->nodeName
);
210 //_________________________________________________________________________________
211 // Routine: CompareExtendedCatalogKeys
213 // Function: Compares two large catalog keys (a search key and a trial key).
215 // Result: +n search key > trial key
216 // 0 search key = trial key
217 // -n search key < trial key
218 //_________________________________________________________________________________
221 CompareExtendedCatalogKeys(HFSPlusCatalogKey
*searchKey
, HFSPlusCatalogKey
*trialKey
)
224 HFSCatalogNodeID searchParentID
, trialParentID
;
226 searchParentID
= searchKey
->parentID
;
227 trialParentID
= trialKey
->parentID
;
229 if ( searchParentID
> trialParentID
) // parent node IDs are unsigned
233 else if ( searchParentID
< trialParentID
)
237 else // parent node ID's are equal, compare names
239 if ( searchKey
->nodeName
.length
== 0 || trialKey
->nodeName
.length
== 0 )
240 result
= searchKey
->nodeName
.length
- trialKey
->nodeName
.length
;
242 result
= FastUnicodeCompare(&searchKey
->nodeName
.unicode
[0], searchKey
->nodeName
.length
,
243 &trialKey
->nodeName
.unicode
[0], trialKey
->nodeName
.length
);