2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSBTreeSupport.cpp
39 #include "AFSCommon.h"
42 AFSLocateCaseSensitiveDirEntry( IN AFSDirectoryCB *RootNode,
44 IN OUT AFSDirectoryCB **DirEntry)
47 NTSTATUS ntStatus = STATUS_SUCCESS;
48 AFSDirectoryCB *pEntry = NULL;
49 AFSDirectoryCB *pCurrentEntry = NULL;
51 pCurrentEntry = RootNode;
59 // If the rootnode passed is null then the directory is empty
65 try_return( ntStatus = STATUS_INVALID_PARAMETER);
69 // If the requestor is looking for the root node itself, then return it.
72 if( RootNode->CaseSensitiveTreeEntry.HashIndex == Index)
77 try_return( ntStatus);
81 // Loop through the nodes in the tree
84 while( pCurrentEntry != NULL)
88 // Greater values are to the right link.
91 if( Index > pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
95 // Go to the next RIGHT entry, if there is one
98 if( pCurrentEntry->CaseSensitiveTreeEntry.rightLink != NULL)
101 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.rightLink;
107 // Came to the end of the branch so bail
110 pCurrentEntry = NULL;
115 else if( Index < pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
119 // Go to the next LEFT entry, if one exists
122 if( pCurrentEntry->CaseSensitiveTreeEntry.leftLink != NULL)
125 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.leftLink;
131 // End of the branch ...
134 pCurrentEntry = NULL;
146 *DirEntry = pCurrentEntry;
161 AFSLocateCaseInsensitiveDirEntry( IN AFSDirectoryCB *RootNode,
163 IN OUT AFSDirectoryCB **DirEntry)
166 NTSTATUS ntStatus = STATUS_SUCCESS;
167 AFSDirectoryCB *pEntry = NULL;
168 AFSDirectoryCB *pCurrentEntry = NULL;
170 pCurrentEntry = RootNode;
178 // If the rootnode passed is null then the directory is empty
181 if( RootNode == NULL)
184 try_return( ntStatus = STATUS_INVALID_PARAMETER);
188 // If the requestor is looking for the root node itself, then return it.
191 if( RootNode->CaseInsensitiveTreeEntry.HashIndex == Index)
194 *DirEntry = RootNode;
196 try_return( ntStatus);
200 // Loop through the nodes in the tree
203 while( pCurrentEntry != NULL)
207 // Greater values are to the right link.
210 if( Index > pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
214 // Go to the next RIGHT entry, if there is one
217 if( pCurrentEntry->CaseInsensitiveTreeEntry.rightLink != NULL)
220 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.rightLink;
226 // Came to the end of the branch so bail
229 pCurrentEntry = NULL;
234 else if( Index < pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
238 // Go to the next LEFT entry, if one exists
241 if( pCurrentEntry->CaseInsensitiveTreeEntry.leftLink != NULL)
244 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.leftLink;
250 // End of the branch ...
253 pCurrentEntry = NULL;
265 *DirEntry = pCurrentEntry;
280 AFSInsertCaseSensitiveDirEntry( IN AFSDirectoryCB *RootNode,
281 IN AFSDirectoryCB *DirEntry)
284 NTSTATUS ntStatus = STATUS_SUCCESS;
285 AFSDirectoryCB *pCurrentEntry = NULL;
287 pCurrentEntry = RootNode;
293 // If we have no root node then we can;t start the search.
296 if( pCurrentEntry == NULL)
299 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
300 AFS_TRACE_LEVEL_WARNING,
301 "AFSInsertCaseSensitiveDirEntry Invalid root node\n");
303 try_return( ntStatus = STATUS_UNSUCCESSFUL);
307 // Locate the branch end to insert the node
310 while( pCurrentEntry != NULL)
314 // Greater vlued indices are to the right link
317 if( DirEntry->CaseSensitiveTreeEntry.HashIndex > pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
321 // Go to the next RIGHT entry, if it exists
324 if( pCurrentEntry->CaseSensitiveTreeEntry.rightLink != NULL)
326 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.rightLink;
332 // Located the end of the branch line so insert the node
335 pCurrentEntry->CaseSensitiveTreeEntry.rightLink = (void *)DirEntry;
337 DirEntry->CaseSensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
342 else if( DirEntry->CaseSensitiveTreeEntry.HashIndex < pCurrentEntry->CaseSensitiveTreeEntry.HashIndex)
346 // Go to the next LEFT entry, if it exists
349 if( pCurrentEntry->CaseSensitiveTreeEntry.leftLink != NULL)
351 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseSensitiveTreeEntry.leftLink;
357 // Located the branch line end so insert the node here
360 pCurrentEntry->CaseSensitiveTreeEntry.leftLink = (void *)DirEntry;
362 DirEntry->CaseSensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
370 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
371 AFS_TRACE_LEVEL_WARNING,
372 "AFSInsertCaseSensitiveDirEntry Attempt to re-insert a CRC %I64X\n",
373 DirEntry->CaseSensitiveTreeEntry.HashIndex);
377 ntStatus = STATUS_UNSUCCESSFUL;
392 AFSInsertCaseInsensitiveDirEntry( IN AFSDirectoryCB *RootNode,
393 IN AFSDirectoryCB *DirEntry)
396 NTSTATUS ntStatus = STATUS_SUCCESS;
397 AFSDirectoryCB *pCurrentEntry = NULL;
399 pCurrentEntry = RootNode;
405 // If we have no root node then we can;t start the search.
408 if( pCurrentEntry == NULL)
411 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
412 AFS_TRACE_LEVEL_WARNING,
413 "AFSInsertCaseInsensitiveDirEntry Invalid root node\n");
415 try_return( ntStatus = STATUS_UNSUCCESSFUL);
419 // Locate the branch end to insert the node
422 while( pCurrentEntry != NULL)
426 // Greater vlued indices are to the right link
429 if( DirEntry->CaseInsensitiveTreeEntry.HashIndex > pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
433 // Go to the next RIGHT entry, if it exists
436 if( pCurrentEntry->CaseInsensitiveTreeEntry.rightLink != NULL)
438 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.rightLink;
444 // Located the end of the branch line so insert the node
447 pCurrentEntry->CaseInsensitiveTreeEntry.rightLink = (void *)DirEntry;
449 DirEntry->CaseInsensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
451 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
456 else if( DirEntry->CaseInsensitiveTreeEntry.HashIndex < pCurrentEntry->CaseInsensitiveTreeEntry.HashIndex)
460 // Go to the next LEFT entry, if it exists
463 if( pCurrentEntry->CaseInsensitiveTreeEntry.leftLink != NULL)
465 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveTreeEntry.leftLink;
471 // Located the branch line end so insert the node here
474 pCurrentEntry->CaseInsensitiveTreeEntry.leftLink = (void *)DirEntry;
476 DirEntry->CaseInsensitiveTreeEntry.parentLink = (void *)pCurrentEntry;
478 SetFlag( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
487 // Inser the the entry at the end of the insensitive list
490 while( pCurrentEntry->CaseInsensitiveList.fLink != NULL)
493 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->CaseInsensitiveList.fLink;
496 pCurrentEntry->CaseInsensitiveList.fLink = (void *)DirEntry;
498 DirEntry->CaseInsensitiveList.bLink = (void *)pCurrentEntry;
513 AFSRemoveCaseSensitiveDirEntry( IN AFSDirectoryCB **RootNode,
514 IN AFSDirectoryCB *DirEntry)
517 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
518 AFSDirectoryCB *pRightNode = NULL;
519 AFSDirectoryCB *pLeftNode = NULL;
520 AFSDirectoryCB *pCurrentNode = NULL;
521 AFSDirectoryCB *pParentNode = NULL;
523 pRightNode = (AFSDirectoryCB *)DirEntry->CaseSensitiveTreeEntry.rightLink;
524 pLeftNode = (AFSDirectoryCB *)DirEntry->CaseSensitiveTreeEntry.leftLink;
525 pParentNode = (AFSDirectoryCB *)DirEntry->CaseSensitiveTreeEntry.parentLink;
530 if( (pRightNode == NULL) && (pLeftNode == NULL))
533 if( pParentNode != NULL)
536 if( pParentNode->CaseSensitiveTreeEntry.leftLink == DirEntry)
539 pParentNode->CaseSensitiveTreeEntry.leftLink = NULL;
544 pParentNode->CaseSensitiveTreeEntry.rightLink = NULL;
551 // Removing the top node
560 if( pRightNode != NULL)
563 if( pParentNode != NULL)
566 // Replace the parent node where this entry was.
567 if( pParentNode->CaseSensitiveTreeEntry.rightLink == DirEntry)
570 pParentNode->CaseSensitiveTreeEntry.rightLink = pRightNode;
575 pParentNode->CaseSensitiveTreeEntry.leftLink = pRightNode;
581 *RootNode = pRightNode;
583 pRightNode->CaseSensitiveTreeEntry.parentLink = NULL;
586 pRightNode->CaseSensitiveTreeEntry.parentLink = pParentNode;
589 if( pLeftNode != NULL)
592 // To connect the left node, we must walk the chain of the
593 // right nodes left side until we reach the end.
594 // At the end attach the leftNode
595 if( pRightNode != NULL)
598 pCurrentNode = pRightNode;
600 while( pCurrentNode->CaseSensitiveTreeEntry.leftLink != NULL)
603 pCurrentNode = (AFSDirectoryCB *)pCurrentNode->CaseSensitiveTreeEntry.leftLink;
606 pCurrentNode->CaseSensitiveTreeEntry.leftLink = pLeftNode;
608 pLeftNode->CaseSensitiveTreeEntry.parentLink = pCurrentNode;
613 if( pParentNode != NULL)
616 // This is where we have a left node with no right node.
617 // So, attach the left node to the parent of
618 // the removed nodes branch
619 if( pParentNode->CaseSensitiveTreeEntry.rightLink == DirEntry)
622 pParentNode->CaseSensitiveTreeEntry.rightLink = pLeftNode;
627 pParentNode->CaseSensitiveTreeEntry.leftLink = pLeftNode;
630 pLeftNode->CaseSensitiveTreeEntry.parentLink = pParentNode;
635 *RootNode = pLeftNode;
637 pLeftNode->CaseSensitiveTreeEntry.parentLink = NULL;
644 // Cleanup the just removed node
647 DirEntry->CaseSensitiveTreeEntry.leftLink = NULL;
648 DirEntry->CaseSensitiveTreeEntry.parentLink = NULL;
649 DirEntry->CaseSensitiveTreeEntry.rightLink = NULL;
651 ntStatus = STATUS_SUCCESS;
658 AFSRemoveCaseInsensitiveDirEntry( IN AFSDirectoryCB **RootNode,
659 IN AFSDirectoryCB *DirEntry)
662 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
663 AFSDirectoryCB *pRightNode = NULL;
664 AFSDirectoryCB *pLeftNode = NULL;
665 AFSDirectoryCB *pCurrentNode = NULL;
666 AFSDirectoryCB *pParentNode = NULL;
667 AFSDirectoryCB *pNewHeadEntry = NULL;
669 pRightNode = (AFSDirectoryCB *)DirEntry->CaseInsensitiveTreeEntry.rightLink;
670 pLeftNode = (AFSDirectoryCB *)DirEntry->CaseInsensitiveTreeEntry.leftLink;
671 pParentNode = (AFSDirectoryCB *)DirEntry->CaseInsensitiveTreeEntry.parentLink;
677 // If this is not a head of list entry then just update the pointers for it
680 if( !BooleanFlagOn( DirEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD))
683 ((AFSDirectoryCB *)DirEntry->CaseInsensitiveList.bLink)->CaseInsensitiveList.fLink = DirEntry->CaseInsensitiveList.fLink;
685 if( DirEntry->CaseInsensitiveList.fLink != NULL)
688 ((AFSDirectoryCB *)DirEntry->CaseInsensitiveList.fLink)->CaseInsensitiveList.bLink = DirEntry->CaseInsensitiveList.bLink;
691 try_return( ntStatus);
694 if( DirEntry->CaseInsensitiveList.fLink != NULL)
698 // Removing the head of a list of entries so just update pointers
701 pNewHeadEntry = (AFSDirectoryCB *)DirEntry->CaseInsensitiveList.fLink;
703 if( pParentNode != NULL)
706 if( pParentNode->CaseInsensitiveTreeEntry.rightLink == DirEntry)
708 pParentNode->CaseInsensitiveTreeEntry.rightLink = (void *)pNewHeadEntry;
712 pParentNode->CaseInsensitiveTreeEntry.leftLink = (void *)pNewHeadEntry;
717 *RootNode = pNewHeadEntry;
720 if( pRightNode != NULL)
723 pRightNode->CaseInsensitiveTreeEntry.parentLink = (void *)pNewHeadEntry;
726 if( pLeftNode != NULL)
729 pLeftNode->CaseInsensitiveTreeEntry.parentLink = (void *)pNewHeadEntry;
732 pNewHeadEntry->CaseInsensitiveList.bLink = NULL;
734 pNewHeadEntry->CaseInsensitiveTreeEntry.parentLink = pParentNode;
736 pNewHeadEntry->CaseInsensitiveTreeEntry.leftLink = pLeftNode;
738 pNewHeadEntry->CaseInsensitiveTreeEntry.rightLink = pRightNode;
740 SetFlag( pNewHeadEntry->Flags, AFS_DIR_ENTRY_CASE_INSENSTIVE_LIST_HEAD);
742 try_return( ntStatus);
745 if( (pRightNode == NULL) && (pLeftNode == NULL))
748 if( pParentNode != NULL)
751 if( pParentNode->CaseInsensitiveTreeEntry.leftLink == DirEntry)
754 pParentNode->CaseInsensitiveTreeEntry.leftLink = NULL;
759 pParentNode->CaseInsensitiveTreeEntry.rightLink = NULL;
766 // Removing the top node
775 if( pRightNode != NULL)
778 if( pParentNode != NULL)
781 // Replace the parent node where this entry was.
782 if( pParentNode->CaseInsensitiveTreeEntry.rightLink == DirEntry)
785 pParentNode->CaseInsensitiveTreeEntry.rightLink = pRightNode;
790 pParentNode->CaseInsensitiveTreeEntry.leftLink = pRightNode;
796 *RootNode = pRightNode;
798 pRightNode->CaseInsensitiveTreeEntry.parentLink = NULL;
801 pRightNode->CaseInsensitiveTreeEntry.parentLink = pParentNode;
804 if( pLeftNode != NULL)
807 // To connect the left node, we must walk the chain of the
808 // right nodes left side until we reach the end.
809 // At the end attach the leftNode
810 if( pRightNode != NULL)
813 pCurrentNode = pRightNode;
815 while( pCurrentNode->CaseInsensitiveTreeEntry.leftLink != NULL)
818 pCurrentNode = (AFSDirectoryCB *)pCurrentNode->CaseInsensitiveTreeEntry.leftLink;
821 pCurrentNode->CaseInsensitiveTreeEntry.leftLink = pLeftNode;
823 pLeftNode->CaseInsensitiveTreeEntry.parentLink = pCurrentNode;
828 if( pParentNode != NULL)
831 // This is where we have a left node with no right node.
832 // So, attach the left node to the parent of
833 // the removed nodes branch
834 if( pParentNode->CaseInsensitiveTreeEntry.rightLink == DirEntry)
837 pParentNode->CaseInsensitiveTreeEntry.rightLink = pLeftNode;
842 pParentNode->CaseInsensitiveTreeEntry.leftLink = pLeftNode;
845 pLeftNode->CaseInsensitiveTreeEntry.parentLink = pParentNode;
850 *RootNode = pLeftNode;
852 pLeftNode->CaseInsensitiveTreeEntry.parentLink = NULL;
861 // Cleanup the just removed node
864 DirEntry->CaseInsensitiveTreeEntry.leftLink = NULL;
865 DirEntry->CaseInsensitiveTreeEntry.parentLink = NULL;
866 DirEntry->CaseInsensitiveTreeEntry.rightLink = NULL;
868 DirEntry->CaseInsensitiveList.bLink = NULL;
869 DirEntry->CaseInsensitiveList.fLink = NULL;
871 ntStatus = STATUS_SUCCESS;
878 AFSLocateShortNameDirEntry( IN AFSDirectoryCB *RootNode,
880 IN OUT AFSDirectoryCB **DirEntry)
883 NTSTATUS ntStatus = STATUS_SUCCESS;
884 AFSDirectoryCB *pEntry = NULL;
885 AFSDirectoryCB *pCurrentEntry = NULL;
887 pCurrentEntry = RootNode;
895 // If the rootnode passed is null then the directory is empty
898 if( RootNode == NULL)
901 try_return( ntStatus = STATUS_INVALID_PARAMETER);
905 // If the requestor is looking for the root node itself, then return it.
908 if( RootNode->Type.Data.ShortNameTreeEntry.HashIndex == Index)
911 *DirEntry = RootNode;
913 try_return( ntStatus);
917 // Loop through the nodes in the tree
920 while( pCurrentEntry != NULL)
924 // Greater values are to the right link.
927 if( Index > pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
931 // Go to the next RIGHT entry, if there is one
934 if( pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink != NULL)
937 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink;
943 // Came to the end of the branch so bail
946 pCurrentEntry = NULL;
951 else if( Index < pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
955 // Go to the next LEFT entry, if one exists
958 if( pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink != NULL)
961 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink;
967 // End of the branch ...
970 pCurrentEntry = NULL;
982 *DirEntry = pCurrentEntry;
997 AFSInsertShortNameDirEntry( IN AFSDirectoryCB *RootNode,
998 IN AFSDirectoryCB *DirEntry)
1001 NTSTATUS ntStatus = STATUS_SUCCESS;
1002 AFSDirectoryCB *pCurrentEntry = NULL;
1004 pCurrentEntry = RootNode;
1010 // If we have no root node then we can;t start the search.
1013 if( pCurrentEntry == NULL)
1016 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1017 AFS_TRACE_LEVEL_WARNING,
1018 "AFSInsertShortNameDirEntry Invalid root node\n");
1020 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1024 // Locate the branch end to insert the node
1027 while( pCurrentEntry != NULL)
1031 // Greater valued indices are to the right link
1034 if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex > pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
1038 // Go to the next RIGHT entry, if it exists
1041 if( pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink != NULL)
1043 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink;
1049 // Located the end of the branch line so insert the node
1052 pCurrentEntry->Type.Data.ShortNameTreeEntry.rightLink = (void *)DirEntry;
1054 DirEntry->Type.Data.ShortNameTreeEntry.parentLink = (void *)pCurrentEntry;
1059 else if( DirEntry->Type.Data.ShortNameTreeEntry.HashIndex < pCurrentEntry->Type.Data.ShortNameTreeEntry.HashIndex)
1063 // Go to the next LEFT entry, if it exists
1066 if( pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink != NULL)
1068 pCurrentEntry = (AFSDirectoryCB *)pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink;
1074 // Located the branch line end so insert the node here
1077 pCurrentEntry->Type.Data.ShortNameTreeEntry.leftLink = (void *)DirEntry;
1079 DirEntry->Type.Data.ShortNameTreeEntry.parentLink = (void *)pCurrentEntry;
1100 AFSRemoveShortNameDirEntry( IN AFSDirectoryCB **RootNode,
1101 IN AFSDirectoryCB *DirEntry)
1104 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1105 AFSDirectoryCB *pRightNode = NULL;
1106 AFSDirectoryCB *pLeftNode = NULL;
1107 AFSDirectoryCB *pCurrentNode = NULL;
1108 AFSDirectoryCB *pParentNode = NULL;
1110 pRightNode = (AFSDirectoryCB *)DirEntry->Type.Data.ShortNameTreeEntry.rightLink;
1111 pLeftNode = (AFSDirectoryCB *)DirEntry->Type.Data.ShortNameTreeEntry.leftLink;
1112 pParentNode = (AFSDirectoryCB *)DirEntry->Type.Data.ShortNameTreeEntry.parentLink;
1117 if( (pRightNode == NULL) && (pLeftNode == NULL))
1120 if( pParentNode != NULL)
1123 if( pParentNode->Type.Data.ShortNameTreeEntry.leftLink == DirEntry)
1126 pParentNode->Type.Data.ShortNameTreeEntry.leftLink = NULL;
1131 pParentNode->Type.Data.ShortNameTreeEntry.rightLink = NULL;
1138 // Removing the top node
1147 if( pRightNode != NULL)
1150 if( pParentNode != NULL)
1153 // Replace the parent node where this entry was.
1154 if( pParentNode->Type.Data.ShortNameTreeEntry.rightLink == DirEntry)
1157 pParentNode->Type.Data.ShortNameTreeEntry.rightLink = pRightNode;
1162 pParentNode->Type.Data.ShortNameTreeEntry.leftLink = pRightNode;
1168 *RootNode = pRightNode;
1170 pRightNode->Type.Data.ShortNameTreeEntry.parentLink = NULL;
1173 pRightNode->Type.Data.ShortNameTreeEntry.parentLink = pParentNode;
1176 if( pLeftNode != NULL)
1179 // To connect the left node, we must walk the chain of the
1180 // right nodes left side until we reach the end.
1181 // At the end attach the leftNode
1182 if( pRightNode != NULL)
1185 pCurrentNode = pRightNode;
1187 while( pCurrentNode->Type.Data.ShortNameTreeEntry.leftLink != NULL)
1190 pCurrentNode = (AFSDirectoryCB *)pCurrentNode->Type.Data.ShortNameTreeEntry.leftLink;
1193 pCurrentNode->Type.Data.ShortNameTreeEntry.leftLink = pLeftNode;
1195 pLeftNode->Type.Data.ShortNameTreeEntry.parentLink = pCurrentNode;
1200 if( pParentNode != NULL)
1203 // This is where we have a left node with no right node.
1204 // So, attach the left node to the parent of
1205 // the removed nodes branch
1206 if( pParentNode->Type.Data.ShortNameTreeEntry.rightLink == DirEntry)
1209 pParentNode->Type.Data.ShortNameTreeEntry.rightLink = pLeftNode;
1214 pParentNode->Type.Data.ShortNameTreeEntry.leftLink = pLeftNode;
1217 pLeftNode->Type.Data.ShortNameTreeEntry.parentLink = pParentNode;
1222 *RootNode = pLeftNode;
1224 pLeftNode->Type.Data.ShortNameTreeEntry.parentLink = NULL;
1231 // Cleanup the just removed node
1234 DirEntry->Type.Data.ShortNameTreeEntry.leftLink = NULL;
1235 DirEntry->Type.Data.ShortNameTreeEntry.parentLink = NULL;
1236 DirEntry->Type.Data.ShortNameTreeEntry.rightLink = NULL;
1238 ntStatus = STATUS_SUCCESS;
1245 AFSLocateHashEntry( IN AFSBTreeEntry *TopNode,
1246 IN ULONGLONG HashIndex,
1247 IN OUT AFSBTreeEntry **TreeEntry)
1250 NTSTATUS ntStatus = STATUS_SUCCESS;
1251 AFSBTreeEntry *pEntry = NULL;
1252 AFSBTreeEntry *pCurrentEntry = NULL;
1254 pCurrentEntry = TopNode;
1260 // If the rootnode passed is null then the directory is empty
1263 if( TopNode == NULL)
1266 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1270 // If the requestor is looking for the root node itself, then return it.
1273 if( TopNode->HashIndex == HashIndex)
1276 *TreeEntry = TopNode;
1278 try_return( ntStatus);
1282 // Loop through the nodes in the tree
1285 while( pCurrentEntry != NULL)
1289 // Greater values are to the right link.
1292 if( HashIndex > pCurrentEntry->HashIndex)
1296 // Go to the next RIGHT entry, if there is one
1299 if( pCurrentEntry->rightLink != NULL)
1302 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink;
1308 // Came to the end of the branch so bail
1311 pCurrentEntry = NULL;
1316 else if( HashIndex < pCurrentEntry->HashIndex)
1320 // Go to the next LEFT entry, if one exists
1323 if( pCurrentEntry->leftLink != NULL)
1326 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink;
1332 // End of the branch ...
1335 pCurrentEntry = NULL;
1347 *TreeEntry = pCurrentEntry;
1362 AFSInsertHashEntry( IN AFSBTreeEntry *TopNode,
1363 IN AFSBTreeEntry *FileIDEntry)
1366 NTSTATUS ntStatus = STATUS_SUCCESS;
1367 AFSBTreeEntry *pCurrentEntry = NULL;
1369 pCurrentEntry = TopNode;
1375 // If we have no root node then we can;t start the search.
1378 if( pCurrentEntry == NULL)
1381 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1382 AFS_TRACE_LEVEL_WARNING,
1383 "AFSInsertHashEntry Invalid root node\n");
1385 try_return( ntStatus = STATUS_UNSUCCESSFUL);
1389 // Locate the branch end to insert the node
1392 while( pCurrentEntry != NULL)
1396 // Greater vlued indices are to the right link
1399 if( FileIDEntry->HashIndex > pCurrentEntry->HashIndex)
1403 // Go to the next RIGHT entry, if it exists
1406 if( pCurrentEntry->rightLink != NULL)
1408 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink;
1414 // Located the end of the branch line so insert the node
1417 pCurrentEntry->rightLink = (void *)FileIDEntry;
1419 FileIDEntry->parentLink = (void *)pCurrentEntry;
1424 else if( FileIDEntry->HashIndex < pCurrentEntry->HashIndex)
1428 // Go to the next LEFT entry, if it exists
1431 if( pCurrentEntry->leftLink != NULL)
1433 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink;
1439 // Located the branch line end so insert the node here
1442 pCurrentEntry->leftLink = (void *)FileIDEntry;
1444 FileIDEntry->parentLink = (void *)pCurrentEntry;
1452 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
1453 AFS_TRACE_LEVEL_WARNING,
1454 "AFSInsertHashEntry Attempt to re-insert a CRC %I64X\n",
1455 FileIDEntry->HashIndex);
1459 ntStatus = STATUS_UNSUCCESSFUL;
1474 AFSRemoveHashEntry( IN AFSBTreeEntry **TopNode,
1475 IN AFSBTreeEntry *FileIDEntry)
1478 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
1479 AFSBTreeEntry *pRightNode = NULL;
1480 AFSBTreeEntry *pLeftNode = NULL;
1481 AFSBTreeEntry *pCurrentNode = NULL;
1482 AFSBTreeEntry *pParentNode = NULL;
1484 pRightNode = (AFSBTreeEntry *)FileIDEntry->rightLink;
1485 pLeftNode = (AFSBTreeEntry *)FileIDEntry->leftLink;
1486 pParentNode = (AFSBTreeEntry *)FileIDEntry->parentLink;
1491 if( (pRightNode == NULL) && (pLeftNode == NULL))
1494 if( pParentNode != NULL)
1497 if( pParentNode->leftLink == FileIDEntry)
1500 pParentNode->leftLink = NULL;
1505 pParentNode->rightLink = NULL;
1512 // Removing the top node
1521 if( pRightNode != NULL)
1524 if( pParentNode != NULL)
1527 // Replace the parent node where this entry was.
1528 if( pParentNode->rightLink == FileIDEntry)
1531 pParentNode->rightLink = pRightNode;
1536 pParentNode->leftLink = pRightNode;
1542 *TopNode = pRightNode;
1544 pRightNode->parentLink = NULL;
1547 pRightNode->parentLink = pParentNode;
1550 if( pLeftNode != NULL)
1553 // To connect the left node, we must walk the chain of the
1554 // right nodes left side until we reach the end.
1555 // At the end attach the leftNode
1556 if( pRightNode != NULL)
1559 pCurrentNode = pRightNode;
1561 while( pCurrentNode->leftLink != NULL)
1564 pCurrentNode = (AFSBTreeEntry *)pCurrentNode->leftLink;
1567 pCurrentNode->leftLink = pLeftNode;
1569 pLeftNode->parentLink = pCurrentNode;
1574 if( pParentNode != NULL)
1577 // This is where we have a left node with no right node.
1578 // So, attach the left node to the parent of
1579 // the removed nodes branch
1580 if( pParentNode->rightLink == FileIDEntry)
1583 pParentNode->rightLink = pLeftNode;
1588 pParentNode->leftLink = pLeftNode;
1591 pLeftNode->parentLink = pParentNode;
1596 *TopNode = pLeftNode;
1598 pLeftNode->parentLink = NULL;
1605 // Cleanup the just removed node
1608 FileIDEntry->leftLink = NULL;
1609 FileIDEntry->parentLink = NULL;
1610 FileIDEntry->rightLink = NULL;
1612 ntStatus = STATUS_SUCCESS;