PageRenderTime 63ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/darwin/xnu/bsd/hfs/hfscommon/Catalog/Catalog.c

https://gitlab.com/stallmanifold/hfs-freebsd
C | 245 lines | 134 code | 49 blank | 62 comment | 38 complexity | a030500390391bdeae1295fdfaaa181e MD5 | raw file
  1. /*
  2. * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
  3. *
  4. * @APPLE_LICENSE_HEADER_START@
  5. *
  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.
  11. *
  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
  18. * under the License.
  19. *
  20. * @APPLE_LICENSE_HEADER_END@
  21. */
  22. #pragma segment Catalog
  23. #include <sys/param.h>
  24. #include <sys/utfconv.h>
  25. #include "../../hfs_endian.h"
  26. #include "../headers/FileMgrInternal.h"
  27. #include "../headers/BTreesInternal.h"
  28. #include "../headers/CatalogPrivate.h"
  29. #include "../headers/HFSUnicodeWrappers.h"
  30. // External routines
  31. extern SInt32 FastRelString( ConstStr255Param str1, ConstStr255Param str2 );
  32. //_________________________________________________________________________________
  33. // Exported Routines
  34. //
  35. // CompareCatalogKeys - Compares two catalog keys.
  36. //
  37. //_________________________________________________________________________________
  38. UInt32
  39. GetDirEntrySize(BTreeIterator *bip, ExtendedVCB * vol)
  40. {
  41. CatalogKey * ckp;
  42. CatalogName * cnp;
  43. ByteCount utf8chars;
  44. UInt8 name[kdirentMaxNameBytes + 1];
  45. OSErr result;
  46. ckp = (CatalogKey*) &bip->key;
  47. if (vol->vcbSigWord == kHFSPlusSigWord) {
  48. cnp = (CatalogName*) &ckp->hfsPlus.nodeName;
  49. utf8chars = utf8_encodelen(cnp->ustr.unicode,
  50. cnp->ustr.length * sizeof(UniChar), ':', 0);
  51. if (utf8chars > kdirentMaxNameBytes)
  52. utf8chars = kdirentMaxNameBytes;
  53. } else { /* hfs */
  54. cnp = (CatalogName*) ckp->hfs.nodeName;
  55. result = hfs_to_utf8(vol, cnp->pstr, kdirentMaxNameBytes + 1,
  56. &utf8chars, name);
  57. if (result) {
  58. /*
  59. * When an HFS name cannot be encoded with the current
  60. * volume encoding we use MacRoman as a fallback.
  61. */
  62. result = mac_roman_to_utf8(cnp->pstr, MAXHFSVNODELEN + 1,
  63. &utf8chars, name);
  64. }
  65. }
  66. return DIRENTRY_SIZE(utf8chars);
  67. }
  68. /*
  69. * NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
  70. *
  71. * This is assuming maxinum size of a name is 255 (kdirentMaxNameBytes), which is incorrect.
  72. * Any caller of this has to make sure names > 255 are mangled!!!!!!!!
  73. */
  74. OSErr
  75. PositionIterator(CatalogIterator *cip, UInt32 offset, BTreeIterator *bip, UInt16 *op)
  76. {
  77. #define CAT_START_OFFSET (2 * sizeof(struct hfsdotentry))
  78. ExtendedVCB * vol;
  79. FCB * fcb;
  80. OSErr result = 0;
  81. /* are we past the end of a directory? */
  82. if (cip->folderID != cip->parentID)
  83. return(cmNotFound);
  84. vol = cip->volume;
  85. fcb = GetFileControlBlock(vol->catalogRefNum);
  86. /* make a btree iterator from catalog iterator */
  87. UpdateBtreeIterator(cip, bip);
  88. if (cip->currentOffset == offset) {
  89. *op = kBTreeCurrentRecord;
  90. } else if (cip->nextOffset == offset) {
  91. *op = kBTreeNextRecord;
  92. } else { /* start from beginning */
  93. *op = kBTreeNextRecord;
  94. /* Position iterator at the folder's thread record */
  95. result = BTSearchRecord(fcb, bip, NULL, NULL, bip);
  96. if (result)
  97. goto exit;
  98. /* find offset (note: n^2 / 2) */
  99. if (offset > CAT_START_OFFSET) {
  100. HFSCatalogNodeID pid, *idp;
  101. UInt32 curOffset, nextOffset;
  102. /* get first record (ie offset 24) */
  103. result = BTIterateRecord( fcb, kBTreeNextRecord, bip, NULL, NULL );
  104. if (result)
  105. goto exit;
  106. if (vol->vcbSigWord == kHFSPlusSigWord)
  107. idp = &((CatalogKey*) &bip->key)->hfsPlus.parentID;
  108. else
  109. idp = &((CatalogKey*) &bip->key)->hfs.parentID;
  110. pid = *idp;
  111. curOffset = CAT_START_OFFSET;
  112. nextOffset = CAT_START_OFFSET + GetDirEntrySize(bip, vol);
  113. while (nextOffset < offset) {
  114. result = BTIterateRecord( fcb, kBTreeNextRecord, bip, NULL, NULL );
  115. if (result)
  116. goto exit;
  117. /* check for parent change */
  118. if (pid != *idp) {
  119. result = cmNotFound; /* offset past end of directory */
  120. goto exit;
  121. }
  122. curOffset = nextOffset;
  123. nextOffset += GetDirEntrySize(bip, vol);
  124. };
  125. if (nextOffset != offset) {
  126. result = cmNotFound;
  127. goto exit;
  128. }
  129. UpdateCatalogIterator(bip, cip);
  130. cip->currentOffset = curOffset;
  131. cip->nextOffset = nextOffset;
  132. }
  133. }
  134. exit:
  135. if (result == btNotFound)
  136. result = cmNotFound;
  137. return result;
  138. } /* end PositionIterator */
  139. //_________________________________________________________________________________
  140. // Routine: CompareCatalogKeys
  141. //
  142. // Function: Compares two catalog keys (a search key and a trial key).
  143. //
  144. // Result: +n search key > trial key
  145. // 0 search key = trial key
  146. // -n search key < trial key
  147. //_________________________________________________________________________________
  148. SInt32
  149. CompareCatalogKeys(HFSCatalogKey *searchKey, HFSCatalogKey *trialKey)
  150. {
  151. HFSCatalogNodeID searchParentID, trialParentID;
  152. SInt32 result;
  153. searchParentID = searchKey->parentID;
  154. trialParentID = trialKey->parentID;
  155. if ( searchParentID > trialParentID ) // parent dirID is unsigned
  156. result = 1;
  157. else if ( searchParentID < trialParentID )
  158. result = -1;
  159. else // parent dirID's are equal, compare names
  160. result = FastRelString(searchKey->nodeName, trialKey->nodeName);
  161. return result;
  162. }
  163. //_________________________________________________________________________________
  164. // Routine: CompareExtendedCatalogKeys
  165. //
  166. // Function: Compares two large catalog keys (a search key and a trial key).
  167. //
  168. // Result: +n search key > trial key
  169. // 0 search key = trial key
  170. // -n search key < trial key
  171. //_________________________________________________________________________________
  172. SInt32
  173. CompareExtendedCatalogKeys(HFSPlusCatalogKey *searchKey, HFSPlusCatalogKey *trialKey)
  174. {
  175. SInt32 result;
  176. HFSCatalogNodeID searchParentID, trialParentID;
  177. searchParentID = searchKey->parentID;
  178. trialParentID = trialKey->parentID;
  179. if ( searchParentID > trialParentID ) // parent node IDs are unsigned
  180. {
  181. result = 1;
  182. }
  183. else if ( searchParentID < trialParentID )
  184. {
  185. result = -1;
  186. }
  187. else // parent node ID's are equal, compare names
  188. {
  189. if ( searchKey->nodeName.length == 0 || trialKey->nodeName.length == 0 )
  190. result = searchKey->nodeName.length - trialKey->nodeName.length;
  191. else
  192. result = FastUnicodeCompare(&searchKey->nodeName.unicode[0], searchKey->nodeName.length,
  193. &trialKey->nodeName.unicode[0], trialKey->nodeName.length);
  194. }
  195. return result;
  196. }