2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #pragma segment Catalog
25 #include <sys/param.h>
26 #include <sys/utfconv.h>
28 #include "../../hfs_endian.h"
30 #include "../headers/FileMgrInternal.h"
31 #include "../headers/BTreesInternal.h"
32 #include "../headers/CatalogPrivate.h"
33 #include "../headers/HFSUnicodeWrappers.h"
38 extern SInt32
FastRelString( ConstStr255Param str1
, ConstStr255Param str2
);
41 //_________________________________________________________________________________
44 // CompareCatalogKeys - Compares two catalog keys.
46 //_________________________________________________________________________________
51 GetDirEntrySize(BTreeIterator
*bip
, ExtendedVCB
* vol
)
56 UInt8 name
[kdirentMaxNameBytes
+ 1];
59 ckp
= (CatalogKey
*) &bip
->key
;
61 if (vol
->vcbSigWord
== kHFSPlusSigWord
) {
62 cnp
= (CatalogName
*) &ckp
->hfsPlus
.nodeName
;
63 utf8chars
= utf8_encodelen(cnp
->ustr
.unicode
,
64 cnp
->ustr
.length
* sizeof(UniChar
), ':', 0);
65 if (utf8chars
> kdirentMaxNameBytes
)
66 utf8chars
= kdirentMaxNameBytes
;
68 cnp
= (CatalogName
*) ckp
->hfs
.nodeName
;
69 result
= hfs_to_utf8(vol
, cnp
->pstr
, kdirentMaxNameBytes
+ 1,
73 * When an HFS name cannot be encoded with the current
74 * volume encoding we use MacRoman as a fallback.
76 result
= mac_roman_to_utf8(cnp
->pstr
, MAXHFSVNODELEN
+ 1,
81 return DIRENTRY_SIZE(utf8chars
);
84 * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
86 * This is assuming maxinum size of a name is 255 (kdirentMaxNameBytes), which is incorrect.
87 * Any caller of this has to make sure names > 255 are mangled!!!!!!!!
91 PositionIterator(CatalogIterator
*cip
, UInt32 offset
, BTreeIterator
*bip
, UInt16
*op
)
93 #define CAT_START_OFFSET (2 * sizeof(struct hfsdotentry))
98 /* are we past the end of a directory? */
99 if (cip
->folderID
!= cip
->parentID
)
103 fcb
= GetFileControlBlock(vol
->catalogRefNum
);
105 /* make a btree iterator from catalog iterator */
106 UpdateBtreeIterator(cip
, bip
);
108 if (cip
->currentOffset
== offset
) {
109 *op
= kBTreeCurrentRecord
;
111 } else if (cip
->nextOffset
== offset
) {
112 *op
= kBTreeNextRecord
;
114 } else { /* start from beginning */
115 *op
= kBTreeNextRecord
;
117 /* Position iterator at the folder's thread record */
118 result
= BTSearchRecord(fcb
, bip
, NULL
, NULL
, bip
);
122 /* find offset (note: n^2 / 2) */
123 if (offset
> CAT_START_OFFSET
) {
124 HFSCatalogNodeID pid
, *idp
;
125 UInt32 curOffset
, nextOffset
;
127 /* get first record (ie offset 24) */
128 result
= BTIterateRecord( fcb
, kBTreeNextRecord
, bip
, NULL
, NULL
);
132 if (vol
->vcbSigWord
== kHFSPlusSigWord
)
133 idp
= &((CatalogKey
*) &bip
->key
)->hfsPlus
.parentID
;
135 idp
= &((CatalogKey
*) &bip
->key
)->hfs
.parentID
;
139 curOffset
= CAT_START_OFFSET
;
140 nextOffset
= CAT_START_OFFSET
+ GetDirEntrySize(bip
, vol
);
142 while (nextOffset
< offset
) {
143 result
= BTIterateRecord( fcb
, kBTreeNextRecord
, bip
, NULL
, NULL
);
147 /* check for parent change */
149 result
= cmNotFound
; /* offset past end of directory */
153 curOffset
= nextOffset
;
154 nextOffset
+= GetDirEntrySize(bip
, vol
);
157 if (nextOffset
!= offset
) {
162 UpdateCatalogIterator(bip
, cip
);
163 cip
->currentOffset
= curOffset
;
164 cip
->nextOffset
= nextOffset
;
169 if (result
== btNotFound
)
174 } /* end PositionIterator */
177 //_________________________________________________________________________________
178 // Routine: CompareCatalogKeys
180 // Function: Compares two catalog keys (a search key and a trial key).
182 // Result: +n search key > trial key
183 // 0 search key = trial key
184 // -n search key < trial key
185 //_________________________________________________________________________________
188 CompareCatalogKeys(HFSCatalogKey
*searchKey
, HFSCatalogKey
*trialKey
)
190 HFSCatalogNodeID searchParentID
, trialParentID
;
193 searchParentID
= searchKey
->parentID
;
194 trialParentID
= trialKey
->parentID
;
196 if ( searchParentID
> trialParentID
) // parent dirID is unsigned
198 else if ( searchParentID
< trialParentID
)
200 else // parent dirID's are equal, compare names
201 result
= FastRelString(searchKey
->nodeName
, trialKey
->nodeName
);
207 //_________________________________________________________________________________
208 // Routine: CompareExtendedCatalogKeys
210 // Function: Compares two large catalog keys (a search key and a trial key).
212 // Result: +n search key > trial key
213 // 0 search key = trial key
214 // -n search key < trial key
215 //_________________________________________________________________________________
218 CompareExtendedCatalogKeys(HFSPlusCatalogKey
*searchKey
, HFSPlusCatalogKey
*trialKey
)
221 HFSCatalogNodeID searchParentID
, trialParentID
;
223 searchParentID
= searchKey
->parentID
;
224 trialParentID
= trialKey
->parentID
;
226 if ( searchParentID
> trialParentID
) // parent node IDs are unsigned
230 else if ( searchParentID
< trialParentID
)
234 else // parent node ID's are equal, compare names
236 if ( searchKey
->nodeName
.length
== 0 || trialKey
->nodeName
.length
== 0 )
237 result
= searchKey
->nodeName
.length
- trialKey
->nodeName
.length
;
239 result
= FastUnicodeCompare(&searchKey
->nodeName
.unicode
[0], searchKey
->nodeName
.length
,
240 &trialKey
->nodeName
.unicode
[0], trialKey
->nodeName
.length
);