#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/file.h>
#include <sys/buf.h>
#include <sys/proc.h>
#include <sys/conf.h>
#include <mach/machine/vm_types.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/signalvar.h>
#include <sys/attr.h>
#include <sys/utfconv.h>
#include "hfs.h"
#include "hfs_dbg.h"
#include "hfscommon/headers/FileMgrInternal.h"
#include "hfscommon/headers/CatalogPrivate.h"
#include "hfscommon/headers/HFSUnicodeWrappers.h"
#include "hfscommon/headers/BTreesPrivate.h"
#include "hfscommon/headers/BTreeScanner.h"
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 lookForDup);
static int CheckAccess(CatalogNodeData *cnp, CatalogKey *key, struct proc *p);
static int InsertMatch(struct vnode *vp, struct uio *a_uio, CatalogNodeData *cnp,
CatalogKey *key, struct attrlist *returnAttrList,
void *attributesBuffer, void *variableBuffer,
u_long bufferSize, u_long * nummatches );
static Boolean CompareRange(u_long val, u_long low, u_long high);
static Boolean CompareWideRange(u_int64_t val, u_int64_t low, u_int64_t high);
static Boolean CompareRange( u_long val, u_long low, u_long high )
{
return( (val >= low) && (val <= high) );
}
static Boolean CompareWideRange( u_int64_t val, u_int64_t low, u_int64_t high )
{
return( (val >= low) && (val <= high) );
}
static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus );
#define errSearchBufferFull 101
int
hfs_search( ap )
struct vop_searchfs_args *ap;
{
FCB* catalogFCB;
searchinfospec_t searchInfo1;
searchinfospec_t searchInfo2;
void *attributesBuffer;
void *variableBuffer;
short recordSize;
short operation;
u_long fixedBlockSize;
u_long eachReturnBufferSize;
struct proc *p = current_proc();
CatalogNodeData myCNodeData;
CatalogNodeData * myCNodeDataPtr;
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;
int isHFSPlus;
*(ap->a_nummatches) = 0;
if ( ap->a_options & ~SRCHFS_VALIDOPTIONSMASK )
return( EINVAL );
if (ap->a_uio->uio_resid <= 0)
return (EINVAL);
isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
err = UnpackSearchAttributeBlock( ap->a_vp, ap->a_searchattrs, &searchInfo1, ap->a_searchparams1 );
if (err) return err;
err = UnpackSearchAttributeBlock( ap->a_vp, ap->a_searchattrs, &searchInfo2, ap->a_searchparams2 );
if (err) return err;
fixedBlockSize = sizeof(u_long) + AttributeBlockSize( ap->a_returnattrs );
eachReturnBufferSize = fixedBlockSize;
if ( ap->a_returnattrs->commonattr & ATTR_CMN_NAME )
eachReturnBufferSize += kHFSPlusMaxFileNameBytes + 1;
MALLOC( attributesBuffer, void *, eachReturnBufferSize, M_TEMP, M_WAITOK );
variableBuffer = (void*)((char*) attributesBuffer + fixedBlockSize);
err = hfs_metafilelocking( VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_SHARED, p );
if ( err != E_NONE ) {
goto ExitThisRoutine;
};
catalogFCB = VTOFCB( vcb->catalogRefNum );
myCurrentKeyPtr = NULL;
myCurrentDataPtr = NULL;
myCatPositionPtr = (CatPosition *)ap->a_searchstate;
if (ap->a_options & SRCHFS_START) {
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
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 ) {
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 {
err = BTScanInitialize(catalogFCB, myCatPositionPtr->nextNode,
myCatPositionPtr->nextRecord,
myCatPositionPtr->recordsFound,
kCatSearchBufferSize,
&myBTScanState);
#if 0
if (err == 0
&& myCatPositionPtr->writeCount != myBTScanState.btcb->writeCount) {
myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount;
err = EBUSY;
}
#endif
}
(void) hfs_metafilelocking(VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, p);
if (err)
goto ExitThisRoutine;
if ( doQuickExit )
goto QuickExit;
for (;;) {
struct timeval myCurrentTime;
struct timeval myElapsedTime;
err = BTScanNextRecord(&myBTScanState, timerExpired,
(void **)&myCurrentKeyPtr, (void **)&myCurrentDataPtr,
NULL);
if (err)
break;
if ( isHFSPlus ) {
myCNodeDataPtr = (CatalogNodeData *) myCurrentDataPtr;
} else {
CopyCatalogNodeData( vcb, myCurrentDataPtr, &myCNodeData );
myCNodeDataPtr = &myCNodeData;
}
if (CheckCriteria(vcb, ap->a_options, ap->a_searchattrs, myCNodeDataPtr,
myCurrentKeyPtr, &searchInfo1, &searchInfo2, true) &&
CheckAccess(myCNodeDataPtr, myCurrentKeyPtr, ap->a_uio->uio_procp)) {
err = InsertMatch(ap->a_vp, ap->a_uio, myCNodeDataPtr,
myCurrentKeyPtr, ap->a_returnattrs,
attributesBuffer, variableBuffer,
eachReturnBufferSize, ap->a_nummatches);
if (err) {
--myBTScanState.recordsFound;
--myBTScanState.recordNum;
break;
}
if (*(ap->a_nummatches) >= ap->a_maxmatches)
break;
}
myCurrentTime = time;
timersub(&myCurrentTime, &myBTScanState.startTime, &myElapsedTime);
if (myElapsedTime.tv_sec > 0
|| myElapsedTime.tv_usec >= kMaxMicroSecsInKernel) {
timerExpired = true;
}
}
QuickExit:
myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount;
BTScanTerminate(&myBTScanState, &myCatPositionPtr->nextNode,
&myCatPositionPtr->nextRecord,
&myCatPositionPtr->recordsFound);
if ( err == E_NONE ) {
err = EAGAIN;
} else if ( err == errSearchBufferFull ) {
if ( *(ap->a_nummatches) > 0 )
err = EAGAIN;
else
err = ENOBUFS;
} else if ( err == btNotFound ) {
err = E_NONE;
} else if ( err == fsBTTimeOutErr ) {
err = EAGAIN;
}
ExitThisRoutine:
FREE( attributesBuffer, M_TEMP );
return (MacToVFSError(err));
}
static Boolean
CompareMasked(const UInt32 *thisValue, const UInt32 *compareData,
const UInt32 *compareMask, UInt32 count)
{
Boolean matched;
UInt32 i;
matched = true;
for (i=0; i<count; i++) {
if (((*thisValue++ ^ *compareData++) & *compareMask++) != 0) {
matched = false;
break;
}
}
return matched;
}
static Boolean
ComparePartialUnicodeName (register ConstUniCharArrayPtr str, register ItemCount s_len,
register ConstUniCharArrayPtr find, register ItemCount f_len )
{
if (f_len == 0 || s_len == 0)
return FALSE;
do {
if (s_len-- < f_len)
return FALSE;
} while (FastUnicodeCompare(str++, f_len, find, f_len) != 0);
return TRUE;
}
static Boolean
ComparePartialPascalName ( register ConstStr31Param str, register ConstStr31Param find )
{
register u_char s_len = str[0];
register u_char f_len = find[0];
register u_char *tsp;
Str31 tmpstr;
if (f_len == 0 || s_len == 0)
return FALSE;
bcopy(str, tmpstr, s_len + 1);
tsp = &tmpstr[0];
while (s_len-- >= f_len) {
*tsp = f_len;
if (FastRelString(tsp++, find) == 0)
return TRUE;
}
return FALSE;
}
static int
CheckAccess(CatalogNodeData *cnp, CatalogKey *key, struct proc *p)
{
return (1);
}
Boolean
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;
attrgroup_t searchAttributes;
isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
switch (cnp->cnd_type) {
case kCatalogFolderNode:
if ( (searchBits & SRCHFS_MATCHDIRS) == 0 ) {
matched = false;
goto TestDone;
}
break;
case kCatalogFileNode:
if ( (searchBits & SRCHFS_MATCHFILES) == 0 ) {
matched = false;
goto TestDone;
}
break;
default:
return( false );
}
matched = true;
atleastone = false;
if ( attrList->commonattr & ATTR_CMN_NAME ) {
if (isHFSPlus) {
if ( searchBits & SRCHFS_MATCHPARTIALNAMES ) {
matched = ComparePartialUnicodeName(key->hfsPlus.nodeName.unicode,
key->hfsPlus.nodeName.length,
(UniChar*)searchInfo1->name,
searchInfo1->nameLength );
} else {
matched = (FastUnicodeCompare(key->hfsPlus.nodeName.unicode,
key->hfsPlus.nodeName.length,
(UniChar*)searchInfo1->name,
searchInfo1->nameLength ) == 0);
}
} else {
if ( searchBits & SRCHFS_MATCHPARTIALNAMES )
matched = ComparePartialPascalName(key->hfs.nodeName, (u_char*)searchInfo1->name);
else
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;
atleastone = true;
}
if (cnp->cnd_type == kCatalogFileNode) {
if ((attrList->fileattr & ~ATTR_FILE_VALIDMASK) != 0) {
matched = false;
goto TestDone;
}
else if ((attrList->fileattr & ATTR_FILE_VALIDMASK) != 0) {
searchAttributes = attrList->fileattr;
if ( searchAttributes & ATTR_FILE_DATALENGTH ) {
matched = CompareWideRange(
cnp->cnd_datafork.logicalSize,
searchInfo1->f.dataLogicalLength,
searchInfo2->f.dataLogicalLength);
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_FILE_DATAALLOCSIZE ) {
matched = CompareWideRange(
cnp->cnd_datafork.totalBlocks * vcb->blockSize,
searchInfo1->f.dataPhysicalLength,
searchInfo2->f.dataPhysicalLength);
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_FILE_RSRCLENGTH ) {
matched = CompareWideRange(
cnp->cnd_rsrcfork.logicalSize,
searchInfo1->f.resourceLogicalLength,
searchInfo2->f.resourceLogicalLength);
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_FILE_RSRCALLOCSIZE ) {
matched = CompareWideRange(
cnp->cnd_rsrcfork.totalBlocks * vcb->blockSize,
searchInfo1->f.resourcePhysicalLength,
searchInfo2->f.resourcePhysicalLength);
if (matched == false) goto TestDone;
atleastone = true;
}
}
else {
atleastone = true;
}
}
else if (cnp->cnd_type == kCatalogFolderNode) {
if ((attrList->dirattr & ~ATTR_DIR_VALIDMASK) != 0) {
matched = false;
goto TestDone;
}
else if ((attrList->dirattr & ATTR_DIR_VALIDMASK) != 0) {
searchAttributes = attrList->dirattr;
if ( searchAttributes & ATTR_DIR_ENTRYCOUNT ) {
matched = CompareRange(cnp->cnd_valence, searchInfo1->d.numFiles, searchInfo2->d.numFiles );
if (matched == false) goto TestDone;
atleastone = true;
}
}
else {
atleastone = true;
}
}
searchAttributes = attrList->commonattr;
if ( (searchAttributes & ATTR_CMN_VALIDMASK) != 0 ) {
if ( searchAttributes & ATTR_CMN_OBJID ) {
matched = CompareRange( cnp->cnd_nodeID, searchInfo1->nodeID, searchInfo2->nodeID );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_PAROBJID ) {
HFSCatalogNodeID parentID;
if (isHFSPlus)
parentID = key->hfsPlus.parentID;
else
parentID = key->hfs.parentID;
matched = CompareRange( parentID, searchInfo1->parentDirID, searchInfo2->parentDirID );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_FNDRINFO ) {
UInt32 *thisValue;
thisValue = (UInt32 *) &cnp->cnd_finderInfo;
matched = CompareMasked( thisValue, (UInt32 *) &searchInfo1->finderInfo,
(UInt32 *) &searchInfo2->finderInfo, 8 );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_CRTIME ) {
matched = CompareRange(to_bsd_time(cnp->cnd_createDate),
searchInfo1->creationDate.tv_sec, searchInfo2->creationDate.tv_sec );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_MODTIME ) {
matched = CompareRange(to_bsd_time(cnp->cnd_contentModDate),
searchInfo1->modificationDate.tv_sec, searchInfo2->modificationDate.tv_sec );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_CHGTIME ) {
matched = CompareRange(to_bsd_time(cnp->cnd_attributeModDate),
searchInfo1->changeDate.tv_sec, searchInfo2->changeDate.tv_sec );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_BKUPTIME ) {
matched = CompareRange(to_bsd_time(cnp->cnd_backupDate),
searchInfo1->lastBackupDate.tv_sec, searchInfo2->lastBackupDate.tv_sec );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_OWNERID ) {
matched = CompareRange( cnp->cnd_ownerID, searchInfo1->uid, searchInfo2->uid );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_GRPID ) {
matched = CompareRange( cnp->cnd_groupID, searchInfo1->gid, searchInfo2->gid );
if (matched == false) goto TestDone;
atleastone = true;
}
if ( searchAttributes & ATTR_CMN_ACCESSMASK ) {
matched = CompareRange( (u_long)cnp->cnd_mode,
(u_long)searchInfo1->mask, (u_long)searchInfo2->mask );
if (matched == false) goto TestDone;
atleastone = true;
}
}
if (! atleastone)
matched = false;
TestDone:
if ( searchBits & SRCHFS_NEGATEPARAMS )
matched = !matched;
return( matched );
}
static int
InsertMatch( struct vnode *root_vp, struct uio *a_uio, CatalogNodeData *cnp,
CatalogKey *key, struct attrlist *returnAttrList, void *attributesBuffer,
void *variableBuffer, u_long bufferSize, u_long * nummatches )
{
int err;
void *rovingAttributesBuffer;
void *rovingVariableBuffer;
struct hfsCatalogInfo catalogInfo;
u_long packedBufferSize;
ExtendedVCB *vcb = VTOVCB(root_vp);
Boolean isHFSPlus = vcb->vcbSigWord == kHFSPlusSigWord;
u_long privateDir = VTOHFS(root_vp)->hfs_private_metadata_dir;
rovingAttributesBuffer = (char*)attributesBuffer + sizeof(u_long);
rovingVariableBuffer = variableBuffer;
INIT_CATALOGDATA(&catalogInfo.nodeData, 0);
catalogInfo.nodeData.cnd_iNodeNumCopy = 0;
bcopy(cnp, &catalogInfo.nodeData, (cnp->cnd_type == kCatalogFileNode) ?
sizeof(HFSPlusCatalogFile) : sizeof(HFSPlusCatalogFolder));
catalogInfo.nodeData.cnm_parID = isHFSPlus ? key->hfsPlus.parentID : key->hfs.parentID;
if ((privateDir != 0) && (catalogInfo.nodeData.cnm_parID == privateDir))
return (0);
if ((privateDir != 0) && (catalogInfo.nodeData.cnd_nodeID == privateDir))
return (0);
if ( returnAttrList->commonattr & ATTR_CMN_NAME ) {
size_t utf8len = 0;
catalogInfo.nodeData.cnm_nameptr = catalogInfo.nodeData.cnm_namespace;
if ( isHFSPlus ) {
err = utf8_encodestr(key->hfsPlus.nodeName.unicode,
key->hfsPlus.nodeName.length * sizeof(UniChar),
catalogInfo.nodeData.cnm_namespace,
&utf8len,
MAXHFSVNODELEN + 1, ':', 0);
if (err == ENAMETOOLONG) {
utf8len = utf8_encodelen(key->hfsPlus.nodeName.unicode,
key->hfsPlus.nodeName.length * sizeof(UniChar), ':', 0);
MALLOC(catalogInfo.nodeData.cnm_nameptr, char *, utf8len+1, M_TEMP, M_WAITOK);
catalogInfo.nodeData.cnm_flags |= kCatNameIsAllocated;
err = utf8_encodestr(key->hfsPlus.nodeName.unicode,
key->hfsPlus.nodeName.length * sizeof(UniChar),
catalogInfo.nodeData.cnm_nameptr,
&utf8len,
utf8len + 1, ':', 0);
}
} else {
err = hfs_to_utf8(vcb,
key->hfs.nodeName,
MAXHFSVNODELEN + 1,
(ByteCount*) &utf8len,
catalogInfo.nodeData.cnm_namespace);
if (err == ENAMETOOLONG) {
MALLOC(catalogInfo.nodeData.cnm_nameptr, char *, utf8len+1, M_TEMP, M_WAITOK);
catalogInfo.nodeData.cnm_flags |= kCatNameIsAllocated;
err = hfs_to_utf8(vcb,
key->hfs.nodeName,
utf8len + 1,
(ByteCount*) &utf8len,
catalogInfo.nodeData.cnm_nameptr);
} else if (err) {
err = mac_roman_to_utf8(key->hfs.nodeName, MAXHFSVNODELEN + 1,
(ByteCount*) &utf8len,
catalogInfo.nodeData.cnm_namespace);
}
}
catalogInfo.nodeData.cnm_length = utf8len;
if (err && (catalogInfo.nodeData.cnm_flags & kCatNameIsAllocated))
{
DisposePtr(catalogInfo.nodeData.cnm_nameptr);
catalogInfo.nodeData.cnm_flags &= ~kCatNameIsAllocated;
catalogInfo.nodeData.cnm_nameptr = catalogInfo.nodeData.cnm_namespace;
catalogInfo.nodeData.cnm_namespace[0] = 0;
}
}
PackCatalogInfoAttributeBlock( returnAttrList,root_vp, &catalogInfo, &rovingAttributesBuffer, &rovingVariableBuffer );
CLEAN_CATALOGDATA(&catalogInfo.nodeData);
packedBufferSize = (char*)rovingVariableBuffer - (char*)attributesBuffer;
if ( packedBufferSize > a_uio->uio_resid )
return( errSearchBufferFull );
(* nummatches)++;
*((u_long *)attributesBuffer) = packedBufferSize;
err = uiomove( (caddr_t)attributesBuffer, packedBufferSize, a_uio );
return( err );
}
static int
UnpackSearchAttributeBlock( struct vnode *vp, struct attrlist *alist, searchinfospec_t *searchInfo, void *attributeBuffer )
{
attrgroup_t a;
u_long bufferSize;
DBG_ASSERT(searchInfo != NULL);
bufferSize = *((u_long *)attributeBuffer);
if (bufferSize == 0)
return (EINVAL);
++((u_long *)attributeBuffer);
a = alist->commonattr;
if ( a != 0 ) {
if ( a & ATTR_CMN_NAME ) {
char *s = (char*) attributeBuffer + ((attrreference_t *) attributeBuffer)->attr_dataoffset;
size_t len = ((attrreference_t *) attributeBuffer)->attr_length;
if (len > sizeof(searchInfo->name))
return (EINVAL);
if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
size_t ucslen;
if (len > 0) {
if (utf8_decodestr(s, len-1, (UniChar*)searchInfo->name, &ucslen,
sizeof(searchInfo->name), ':', UTF_DECOMPOSED))
return (EINVAL);
searchInfo->nameLength = ucslen / sizeof(UniChar);
} else {
searchInfo->nameLength = 0;
}
++((attrreference_t *)attributeBuffer);
} else {
if (len > 0) {
if (utf8_to_hfs(VTOVCB(vp), len-1, s, (u_char*)searchInfo->name) != 0)
return (EINVAL);
searchInfo->nameLength = searchInfo->name[0];
} else {
searchInfo->name[0] = searchInfo->nameLength = 0;
}
++((attrreference_t *)attributeBuffer);
}
}
if ( a & ATTR_CMN_OBJID ) {
searchInfo->nodeID = ((fsobj_id_t *) attributeBuffer)->fid_objno;
++((fsobj_id_t *)attributeBuffer);
}
if ( a & ATTR_CMN_PAROBJID ) {
searchInfo->parentDirID = ((fsobj_id_t *) attributeBuffer)->fid_objno;
++((fsobj_id_t *)attributeBuffer);
}
if ( a & ATTR_CMN_CRTIME ) {
searchInfo->creationDate = *((struct timespec *)attributeBuffer);
++((struct timespec *)attributeBuffer);
}
if ( a & ATTR_CMN_MODTIME ) {
searchInfo->modificationDate = *((struct timespec *)attributeBuffer);
++((struct timespec *)attributeBuffer);
}
if ( a & ATTR_CMN_CHGTIME ) {
searchInfo->changeDate = *((struct timespec *)attributeBuffer);
++((struct timespec *)attributeBuffer);
}
if ( a & ATTR_CMN_BKUPTIME ) {
searchInfo->lastBackupDate = *((struct timespec *)attributeBuffer);
++((struct timespec *)attributeBuffer);
}
if ( a & ATTR_CMN_FNDRINFO ) {
bcopy( attributeBuffer, searchInfo->finderInfo, sizeof(u_long) * 8 );
(u_long *)attributeBuffer += 8;
}
if ( a & ATTR_CMN_BKUPTIME ) {
searchInfo->lastBackupDate = *((struct timespec *)attributeBuffer);
++((struct timespec *)attributeBuffer);
}
if ( a & ATTR_CMN_OWNERID ) {
searchInfo->uid = *((uid_t *)attributeBuffer);
++((uid_t *)attributeBuffer);
}
if ( a & ATTR_CMN_GRPID ) {
searchInfo->gid = *((gid_t *)attributeBuffer);
++((gid_t *)attributeBuffer);
}
if ( a & ATTR_CMN_ACCESSMASK ) {
searchInfo->mask = *((mode_t *)attributeBuffer);
++((mode_t *)attributeBuffer);
}
}
a = alist->dirattr;
if ( a != 0 ) {
if ( a & ATTR_DIR_ENTRYCOUNT ) {
searchInfo->d.numFiles = *((u_long *)attributeBuffer);
++((u_long *)attributeBuffer);
}
}
a = alist->fileattr;
if ( a != 0 ) {
if ( a & ATTR_FILE_DATALENGTH ) {
searchInfo->f.dataLogicalLength = *((off_t *)attributeBuffer);
++((off_t *)attributeBuffer);
}
if ( a & ATTR_FILE_DATAALLOCSIZE ) {
searchInfo->f.dataPhysicalLength = *((off_t *)attributeBuffer);
++((off_t *)attributeBuffer);
}
if ( a & ATTR_FILE_RSRCLENGTH ) {
searchInfo->f.resourceLogicalLength = *((off_t *)attributeBuffer);
++((off_t *)attributeBuffer);
}
if ( a & ATTR_FILE_RSRCALLOCSIZE ) {
searchInfo->f.resourcePhysicalLength = *((off_t *)attributeBuffer);
++((off_t *)attributeBuffer);
}
}
return (0);
}
static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus )
{
if ( searchInfoPtr->name == NULL )
return( false );
if (isHFSPlus) {
HFSUniStr255 myName = {
7,
{
'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 );
}