]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_search.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_search.c
index df7c233c0aaed68c3d84ee33953f40740b715f47..979e5241472903ccb8b3ac40b7b22e0fdc725e1f 100644 (file)
 
 static int UnpackSearchAttributeBlock(struct vnode *vp, struct attrlist        *alist, searchinfospec_t *searchInfo, void *attributeBuffer);
 
-Boolean CheckCriteria(ExtendedVCB *vcb,
-                       u_long searchBits, struct attrlist *attrList,
-                       CatalogNodeData *cnp, CatalogKey *key,
-                       searchinfospec_t *searchInfo1, searchinfospec_t *searchInfo2);
+Boolean CheckCriteria( ExtendedVCB *vcb,
+                                               u_long searchBits, 
+                                               struct attrlist *attrList,
+                                               CatalogNodeData *cnp, 
+                                               CatalogKey *key,
+                                               searchinfospec_t *searchInfo1, 
+                                               searchinfospec_t *searchInfo2,
+                                               Boolean lookForDup);
 
 static int CheckAccess(CatalogNodeData *cnp, CatalogKey *key, struct proc *p);
 
@@ -79,6 +83,7 @@ static Boolean CompareWideRange( u_int64_t val, u_int64_t low, u_int64_t high )
 }
 //#define CompareRange(val, low, high) ((val >= low) && (val <= high))
 
+static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus );
 
 
 /************************************************************************/
@@ -129,11 +134,12 @@ struct vop_searchfs_args *ap; /*
        struct proc                     *p = current_proc();
        CatalogNodeData         myCNodeData;
        CatalogNodeData *       myCNodeDataPtr;
-       CatalogKey * myCurrentKeyPtr;
-       CatalogRecord * myCurrentDataPtr;
-       CatPosition * myCatPositionPtr;
-       BTScanState myBTScanState;
+       CatalogKey *            myCurrentKeyPtr;
+       CatalogRecord *         myCurrentDataPtr;
+       CatPosition *           myCatPositionPtr;
+       BTScanState             myBTScanState;
        Boolean                         timerExpired = false;
+       Boolean                         doQuickExit = false;
        u_long                          lastNodeNum = 0XFFFFFFFF;
        ExtendedVCB                     *vcb = VTOVCB(ap->a_vp);
        int                                     err = E_NONE;
@@ -179,9 +185,63 @@ struct vop_searchfs_args *ap; /*
 
        if (ap->a_options & SRCHFS_START) {
                /* Starting a new search. */
+               /* make sure our meta data is synced up */
+               err = VOP_FSYNC(vcb->catalogRefNum, NOCRED, MNT_WAIT, p);
                ap->a_options &= ~SRCHFS_START;
                bzero( (caddr_t)myCatPositionPtr, sizeof( *myCatPositionPtr ) );
                err = BTScanInitialize(catalogFCB, 0, 0, 0, kCatSearchBufferSize, &myBTScanState);
+
+#if 1 // Installer workaround
+               // hack to get around installer problems when the installer expects search results 
+               // to be in key order.  At this point the problem appears to be limited to 
+               // searches for "Library".  The idea here is to go get the "Library" at root
+               // and return it first to the caller then continue the search as normal with
+               // the exception of taking care not to return a duplicate hit (see CheckCriteria) 
+               if ( err == E_NONE &&
+                        (ap->a_searchattrs->commonattr & ATTR_CMN_NAME) != 0 &&
+                        IsTargetName( &searchInfo1, isHFSPlus )  )
+               {
+                       CatalogRecord           rec;
+                       BTreeIterator       iterator;
+                       FSBufferDescriptor  btrec;
+                       CatalogKey *            keyp;
+                       UInt16              reclen;
+                       OSErr                           result;
+               
+                       bzero( (caddr_t)&iterator, sizeof( iterator ) );
+                       keyp = (CatalogKey *) &iterator.key;
+                       (void) BuildCatalogKeyUTF8(vcb, kRootDirID, "Library", kUndefinedStrLen, keyp, NULL);
+
+                       btrec.bufferAddress = &rec;
+                       btrec.itemCount = 1;
+                       btrec.itemSize = sizeof( rec );
+
+                       result = BTSearchRecord( catalogFCB, &iterator, kInvalidMRUCacheKey, 
+                                                                        &btrec, &reclen, &iterator );
+                       if ( result == E_NONE ) {
+                               if ( isHFSPlus ) {
+                                       // HFSPlus vols have CatalogRecords that map exactly to CatalogNodeData so there is no need 
+                                       // to copy.
+                                       myCNodeDataPtr = (CatalogNodeData *) &rec;
+                               } else {
+                                       CopyCatalogNodeData( vcb, &rec, &myCNodeData );
+                                       myCNodeDataPtr = &myCNodeData;
+                               }
+                                       
+                               if (CheckCriteria(vcb, ap->a_options, ap->a_searchattrs, myCNodeDataPtr,
+                                                                 keyp, &searchInfo1, &searchInfo2, false) &&
+                                       CheckAccess(myCNodeDataPtr, keyp, ap->a_uio->uio_procp)) {
+               
+                                       result = InsertMatch(ap->a_vp, ap->a_uio, myCNodeDataPtr, 
+                                                                         keyp, ap->a_returnattrs,
+                                                                         attributesBuffer, variableBuffer,
+                                                                         eachReturnBufferSize, ap->a_nummatches);
+                                       if (result == E_NONE && *(ap->a_nummatches) >= ap->a_maxmatches)
+                                               doQuickExit = true;
+                               }
+                       }
+               }
+#endif // Installer workaround
        } else {
                /* Resuming a search. */
                err = BTScanInitialize(catalogFCB, myCatPositionPtr->nextNode, 
@@ -203,7 +263,8 @@ struct vop_searchfs_args *ap; /*
        (void) hfs_metafilelocking(VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, p);
        if (err)
                goto ExitThisRoutine;
-
+       if ( doQuickExit )
+               goto QuickExit;
        /*
         * Check all the catalog btree records...
         *   return the attributes for matching items
@@ -228,7 +289,7 @@ struct vop_searchfs_args *ap; /*
                }
                        
                if (CheckCriteria(vcb, ap->a_options, ap->a_searchattrs, myCNodeDataPtr,
-                                 myCurrentKeyPtr, &searchInfo1, &searchInfo2) &&
+                                 myCurrentKeyPtr, &searchInfo1, &searchInfo2, true) &&
                    CheckAccess(myCNodeDataPtr, myCurrentKeyPtr, ap->a_uio->uio_procp)) {
 
                        err = InsertMatch(ap->a_vp, ap->a_uio, myCNodeDataPtr, 
@@ -261,13 +322,13 @@ struct vop_searchfs_args *ap; /*
                        timerExpired = true;
                }
        }
-
+QuickExit:
        /* Update catalog position */
        myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount;
 
-       BTScanTerminate(&myBTScanState, &myCatPositionPtr->nextNode, 
-                       &myCatPositionPtr->nextRecord, 
-                       &myCatPositionPtr->recordsFound);
+       BTScanTerminate(&myBTScanState, &myCatPositionPtr->nextNode,
+                                       &myCatPositionPtr->nextRecord, 
+                                       &myCatPositionPtr->recordsFound);
 
        if ( err == E_NONE ) {
                err = EAGAIN;   /* signal to the user to call searchfs again */
@@ -360,9 +421,14 @@ CheckAccess(CatalogNodeData *cnp, CatalogKey *key, struct proc *p)
 }
 
 Boolean
-CheckCriteria( ExtendedVCB *vcb, u_long searchBits,
-               struct attrlist *attrList, CatalogNodeData *cnp, CatalogKey *key,
-               searchinfospec_t  *searchInfo1, searchinfospec_t *searchInfo2 )
+CheckCriteria( ExtendedVCB *vcb,
+                               u_long searchBits, 
+                               struct attrlist *attrList,
+                               CatalogNodeData *cnp, 
+                               CatalogKey *key,
+                               searchinfospec_t *searchInfo1, 
+                               searchinfospec_t *searchInfo2,
+                               Boolean lookForDup )
 {
        Boolean matched, atleastone;
        Boolean isHFSPlus;
@@ -416,6 +482,20 @@ CheckCriteria( ExtendedVCB *vcb, u_long searchBits,
                        else /* full HFS name match */
                                matched = (FastRelString(key->hfs.nodeName, (u_char*)searchInfo1->name) == 0);
                }
+
+#if 1 // Installer workaround
+               if ( lookForDup ) {
+                       HFSCatalogNodeID parentID;
+                       if (isHFSPlus)
+                               parentID = key->hfsPlus.parentID;
+                       else
+                               parentID = key->hfs.parentID;
+       
+                       if ( matched && parentID == kRootDirID && 
+                                IsTargetName( searchInfo1, isHFSPlus )  )
+                               matched = false;
+               }
+#endif // Installer workaround
                
                if ( matched == false || (searchBits & ~SRCHFS_MATCHPARTIALNAMES) == 0 )
                        goto TestDone;  /* no match, or nothing more to compare */
@@ -859,3 +939,38 @@ UnpackSearchAttributeBlock( struct vnode *vp, struct attrlist      *alist, searchinfo
 }
 
 
+/* this routine was added as part of the work around where some installers would fail */
+/* because they incorrectly assumed search results were in some kind of order.  */
+/* This routine is used to indentify the problematic target.  At this point we */
+/* only know of one.  This routine could be modified for more (I hope not). */
+static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus )
+{
+       if ( searchInfoPtr->name == NULL )
+               return( false );
+               
+       if (isHFSPlus) {
+               HFSUniStr255 myName = {
+                       7,      /* number of unicode characters */
+                       {
+                               'L','i','b','r','a','r','y'
+                       }
+               };              
+               if ( FastUnicodeCompare( myName.unicode, myName.length,
+                                                                (UniChar*)searchInfoPtr->name,
+                                                                searchInfoPtr->nameLength ) == 0 )  {
+                       return( true );
+               }
+                                                 
+       } else {
+               u_char          myName[32] = {
+                       0x07,'L','i','b','r','a','r','y'
+               };
+               if ( FastRelString(myName, (u_char*)searchInfoPtr->name) == 0 )  {
+                       return( true );
+               }
+       }
+       return( false );
+       
+} /* IsTargetName */
+
+