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);
}
//#define CompareRange(val, low, high) ((val >= low) && (val <= high))
+static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus );
/************************************************************************/
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;
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,
(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
}
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,
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 */
}
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;
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 */
}
+/* 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 */
+
+