Annotation of XNU/bsd/hfs/hfs_search.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 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: /*     @(#)hfs_search.c
        !            23:  *
        !            24:  *     (c) 1997-2000   Apple Computer, Inc.  All Rights Reserved
        !            25:  *     
        !            26:  *
        !            27:  *     MODIFICATION HISTORY:
        !            28:  *      04-May-1999    Don Brady               Split off from hfs_vnodeops.c.
        !            29:  */
        !            30: 
        !            31: #include <sys/param.h>
        !            32: #include <sys/systm.h>
        !            33: #include <sys/kernel.h>
        !            34: #include <sys/file.h>
        !            35: #include <sys/buf.h>
        !            36: #include <sys/proc.h>
        !            37: #include <sys/conf.h>
        !            38: #include <mach/machine/vm_types.h>
        !            39: #include <sys/vnode.h>
        !            40: #include <sys/malloc.h>
        !            41: #include <sys/signalvar.h>
        !            42: #include <sys/attr.h>
        !            43: 
        !            44: #include "hfs.h"
        !            45: #include "hfs_dbg.h"
        !            46: #include "hfscommon/headers/FileMgrInternal.h"
        !            47: #include "hfscommon/headers/CatalogPrivate.h"
        !            48: #include "hfscommon/headers/HFSUnicodeWrappers.h"
        !            49: 
        !            50: 
        !            51: /* Private description used in hfs_search */
        !            52: struct SearchState {
        !            53:        long            searchBits;
        !            54:        BTreeIterator   btreeIterator;
        !            55:        short           vRefNum;        /* Volume reference of volume being searched */
        !            56:        char            isHFSPlus;      /* True if volume is HFS */
        !            57:        char            pad1[3];        /* long align the structure */
        !            58: };
        !            59: typedef struct SearchState SearchState;
        !            60: 
        !            61: 
        !            62: static int UnpackSearchAttributeBlock(struct vnode *vp, struct attrlist        *alist, searchinfospec_t *searchInfo, void *attributeBuffer);
        !            63: 
        !            64: Boolean CheckCriteria( ExtendedVCB *vcb, const SearchState *searchState, u_long searchBits, struct attrlist *attrList, CatalogRecord   *catalogRecord, CatalogKey *key, searchinfospec_t *searchInfo1, searchinfospec_t *searchInfo2 );
        !            65: 
        !            66: static int InsertMatch( struct vnode *vp, struct uio *a_uio, CatalogRecord *catalogRecord, CatalogKey *key, struct attrlist *returnAttrList, void *attributesBuffer, void *variableBuffer, u_long bufferSize, u_long * nummatches );
        !            67: 
        !            68: static Boolean CompareRange(u_long val, u_long low, u_long high);
        !            69: static Boolean CompareWideRange(u_int64_t val, u_int64_t low, u_int64_t high);
        !            70: 
        !            71: static Boolean CompareRange( u_long val, u_long low, u_long high )
        !            72: {
        !            73:        return( (val >= low) && (val <= high) );
        !            74: }
        !            75: 
        !            76: static Boolean CompareWideRange( u_int64_t val, u_int64_t low, u_int64_t high )
        !            77: {
        !            78:        return( (val >= low) && (val <= high) );
        !            79: }
        !            80: //#define CompareRange(val, low, high) ((val >= low) && (val <= high))
        !            81: 
        !            82: 
        !            83: 
        !            84: /************************************************************************/
        !            85: /*     Entry for searchfs()                                                                                            */
        !            86: /************************************************************************/
        !            87: 
        !            88: #define        errSearchBufferFull     101     /* Internal search errors */
        !            89: /*
        !            90: #
        !            91: #% searchfs    vp      L L L
        !            92: #
        !            93: vop_searchfs {
        !            94:     IN struct vnode *vp;
        !            95:     IN off_t length;
        !            96:     IN int flags;
        !            97:     IN struct ucred *cred;
        !            98:     IN struct proc *p;
        !            99: };
        !           100: */
        !           101: 
        !           102: int
        !           103: hfs_search( ap )
        !           104: struct vop_searchfs_args *ap; /*
        !           105:  struct vnodeop_desc *a_desc;
        !           106:  struct vnode *a_vp;
        !           107:  void *a_searchparams1;
        !           108:  void *a_searchparams2;
        !           109:  struct attrlist *a_searchattrs;
        !           110:  u_long a_maxmatches;
        !           111:  struct timeval *a_timelimit;
        !           112:  struct attrlist *a_returnattrs;
        !           113:  u_long *a_nummatches;
        !           114:  u_long a_scriptcode;
        !           115:  u_long a_options;
        !           116:  struct uio *a_uio;
        !           117:  struct searchstate *a_searchstate;
        !           118: */
        !           119: {
        !           120:        CatalogRecord           catalogRecord;
        !           121:        BTreeKey                        *key;
        !           122:        FSBufferDescriptor      btRecord;
        !           123:        FCB*                            catalogFCB;
        !           124:        SearchState                     *searchState;
        !           125:        searchinfospec_t        searchInfo1;
        !           126:        searchinfospec_t        searchInfo2;
        !           127:        void                            *attributesBuffer;
        !           128:        void                            *variableBuffer;
        !           129:        short                           recordSize;
        !           130:        short                           operation;
        !           131:        u_long                          fixedBlockSize;
        !           132:        u_long                          eachReturnBufferSize;
        !           133:        struct proc                     *p = current_proc();
        !           134:        u_long                          nodesToCheck = 30;      /* After we search 30 nodes we must give up time */
        !           135:        u_long                          lastNodeNum = 0XFFFFFFFF;
        !           136:        ExtendedVCB                     *vcb = VTOVCB(ap->a_vp);
        !           137:        int                                     err = E_NONE;
        !           138: 
        !           139:        /* XXX Parameter check a_searchattrs? */
        !           140: 
        !           141:        *(ap->a_nummatches) = 0;
        !           142: 
        !           143:        if ( ap->a_options & ~SRCHFS_VALIDOPTIONSMASK )
        !           144:                return( EINVAL );
        !           145: 
        !           146:        if (ap->a_uio->uio_resid <= 0)
        !           147:                return (EINVAL);
        !           148: 
        !           149:        searchState = (SearchState *)ap->a_searchstate;
        !           150: 
        !           151:        /*
        !           152:         * Check if this is the first time we are being called.
        !           153:         * If it is, allocate SearchState and we'll move it to the users space on exit
        !           154:         */
        !           155:        if ( ap->a_options & SRCHFS_START ) {
        !           156:                bzero( (caddr_t)searchState, sizeof(SearchState) );
        !           157:                searchState->isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord );
        !           158:                operation = kBTreeFirstRecord;
        !           159:                ap->a_options &= ~SRCHFS_START;
        !           160:        } else {
        !           161:                operation = kBTreeCurrentRecord;
        !           162:        }
        !           163: 
        !           164:        /* UnPack the search boundries, searchInfo1, searchInfo2 */
        !           165:        err = UnpackSearchAttributeBlock( ap->a_vp, ap->a_searchattrs, &searchInfo1, ap->a_searchparams1 );
        !           166:        if (err) return err;
        !           167:        err = UnpackSearchAttributeBlock( ap->a_vp, ap->a_searchattrs, &searchInfo2, ap->a_searchparams2 );
        !           168:        if (err) return err;
        !           169: 
        !           170:        btRecord.itemCount = 1;
        !           171:        btRecord.itemSize = sizeof( catalogRecord );
        !           172:        btRecord.bufferAddress = &catalogRecord;
        !           173:        catalogFCB = VTOFCB( vcb->catalogRefNum );
        !           174:        key = (BTreeKey*) &(searchState->btreeIterator.key);
        !           175:        fixedBlockSize = sizeof(u_long) + AttributeBlockSize( ap->a_returnattrs );      /* u_long for length longword */
        !           176:        eachReturnBufferSize = fixedBlockSize;
        !           177:        
        !           178:        if ( ap->a_returnattrs->commonattr & ATTR_CMN_NAME )    /* XXX should be more robust! */
        !           179:                eachReturnBufferSize += NAME_MAX + 1;
        !           180: 
        !           181:        MALLOC( attributesBuffer, void *, eachReturnBufferSize, M_TEMP, M_WAITOK );
        !           182:        variableBuffer = (void*)((char*) attributesBuffer + fixedBlockSize);
        !           183: 
        !           184:        /* Lock catalog b-tree */
        !           185:        err = hfs_metafilelocking( VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_SHARED, p );
        !           186:        if ( err != E_NONE ) {
        !           187:                goto ExitThisRoutine;
        !           188:        };
        !           189: 
        !           190:        /*
        !           191:         * Iterate over all the catalog btree records
        !           192:         */
        !           193:        
        !           194:        err = BTIterateRecord( catalogFCB, operation, &(searchState->btreeIterator), &btRecord, &recordSize );
        !           195: 
        !           196:        while( err == E_NONE ) {
        !           197:                if ( CheckCriteria( vcb, searchState, ap->a_options, ap->a_searchattrs, &catalogRecord,
        !           198:                    (CatalogKey *)key, &searchInfo1, &searchInfo2 ) == true ) {
        !           199:                        err = InsertMatch(ap->a_vp, ap->a_uio, &catalogRecord, (CatalogKey *)key,
        !           200:                                          ap->a_returnattrs, attributesBuffer, variableBuffer,
        !           201:                                          eachReturnBufferSize, ap->a_nummatches);
        !           202:                        if ( err != E_NONE )
        !           203:                                break;
        !           204:                }
        !           205:                
        !           206:                err = BTIterateRecord( catalogFCB, kBTreeNextRecord, &(searchState->btreeIterator), &btRecord, &recordSize );
        !           207:                
        !           208:                        if  ( *(ap->a_nummatches) >= ap->a_maxmatches )
        !           209:                                break;
        !           210: 
        !           211:                if ( searchState->btreeIterator.hint.nodeNum != lastNodeNum ) {
        !           212:                        lastNodeNum = searchState->btreeIterator.hint.nodeNum;
        !           213:                        if ( --nodesToCheck == 0 )
        !           214:                                break;  /* We must leave the kernel to give up time */
        !           215:                }
        !           216:        }
        !           217: 
        !           218:        /* Unlock catalog b-tree */
        !           219:        (void) hfs_metafilelocking( VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, p );
        !           220: 
        !           221: 
        !           222:        if ( err == E_NONE ) {
        !           223:                err = EAGAIN;   /* signal to the user to call searchfs again */
        !           224:        } else if ( err == errSearchBufferFull ) {
        !           225:                if ( *(ap->a_nummatches) > 0 )
        !           226:                        err = EAGAIN;
        !           227:                else
        !           228:                        err = ENOBUFS;
        !           229:        } else if ( err == btNotFound ) {
        !           230:                err = E_NONE;   /* the entire disk has been searched */
        !           231:        }
        !           232: 
        !           233: ExitThisRoutine:
        !           234:         FREE( attributesBuffer, M_TEMP );
        !           235: 
        !           236:        return( err );
        !           237: }
        !           238: 
        !           239: 
        !           240: static Boolean
        !           241: CompareMasked(const UInt32 *thisValue, const UInt32 *compareData,
        !           242:                                                         const UInt32 *compareMask, UInt32 count)
        !           243: {
        !           244:        Boolean matched;
        !           245:        UInt32  i;
        !           246:        
        !           247:        matched = true;         /* Assume it will all match */
        !           248:        
        !           249:        for (i=0; i<count; i++) {
        !           250:                if (((*thisValue++ ^ *compareData++) & *compareMask++) != 0) {
        !           251:                        matched = false;
        !           252:                        break;
        !           253:                }
        !           254:        }
        !           255:        
        !           256:        return matched;
        !           257: }
        !           258: 
        !           259: 
        !           260: static Boolean
        !           261: ComparePartialUnicodeName (register ConstUniCharArrayPtr str, register ItemCount s_len,
        !           262:                           register ConstUniCharArrayPtr find, register ItemCount f_len )
        !           263: {
        !           264:        if (f_len == 0 || s_len == 0)
        !           265:                return FALSE;
        !           266: 
        !           267:        do {
        !           268:                if (s_len-- < f_len)
        !           269:                        return FALSE;
        !           270:        } while (FastUnicodeCompare(str++, f_len, find, f_len) != 0);
        !           271: 
        !           272:        return TRUE;
        !           273: }
        !           274: 
        !           275: 
        !           276: static Boolean
        !           277: ComparePartialPascalName ( register ConstStr31Param str, register ConstStr31Param find )
        !           278: {
        !           279:        register u_char s_len = str[0];
        !           280:        register u_char f_len = find[0];
        !           281:        register u_char *tsp;
        !           282:        Str31 tmpstr;
        !           283: 
        !           284:        if (f_len == 0 || s_len == 0)
        !           285:                return FALSE;
        !           286: 
        !           287:        bcopy(str, tmpstr, s_len + 1);
        !           288:        tsp = &tmpstr[0];
        !           289: 
        !           290:        while (s_len-- >= f_len) {
        !           291:                *tsp = f_len;
        !           292: 
        !           293:                if (FastRelString(tsp++, find) == 0)
        !           294:                        return TRUE;
        !           295:        }
        !           296: 
        !           297:        return FALSE;
        !           298: }
        !           299: 
        !           300: 
        !           301: Boolean
        !           302: CheckCriteria( ExtendedVCB *vcb, const SearchState *searchState, u_long searchBits,
        !           303:                struct attrlist *attrList, CatalogRecord *catalogRecord, CatalogKey *key,
        !           304:                searchinfospec_t  *searchInfo1, searchinfospec_t *searchInfo2 )
        !           305: {
        !           306:        Boolean matched;
        !           307:        CatalogNodeData catData;
        !           308:        attrgroup_t searchAttributes;
        !           309:        
        !           310:        switch ( catalogRecord->recordType ) {
        !           311:        case kHFSFolderRecord:
        !           312:        case kHFSPlusFolderRecord:
        !           313:                if ( (searchBits & SRCHFS_MATCHDIRS) == 0 ) {   /* If we are NOT searching folders */
        !           314:                        matched = false;
        !           315:                        goto TestDone;
        !           316:                }
        !           317:                break;
        !           318:                        
        !           319:        case kHFSFileRecord:
        !           320:        case kHFSPlusFileRecord:
        !           321:                if ( (searchBits & SRCHFS_MATCHFILES) == 0 ) {  /* If we are NOT searching files */
        !           322:                        matched = false;
        !           323:                        goto TestDone;
        !           324:                }
        !           325:                break;
        !           326: 
        !           327:        default:        /* Never match a thread record or any other type. */
        !           328:                return( false );        /* Not a file or folder record, so can't search it */
        !           329:        }
        !           330:        
        !           331:        /* Change the catalog record data into a single common form */
        !           332:        matched = true;         /* Assume we got a match */
        !           333:        catData.cnd_type = 0;   /* mark this record as not in use */
        !           334:        CopyCatalogNodeData( vcb, catalogRecord, &catData );
        !           335: 
        !           336:        /* First, attempt to match the name -- either partial or complete */
        !           337:        if ( attrList->commonattr & ATTR_CMN_NAME ) {
        !           338:                if ( searchState->isHFSPlus ) {
        !           339:                        /* Check for partial/full HFS Plus name match */
        !           340: 
        !           341:                        if ( searchBits & SRCHFS_MATCHPARTIALNAMES ) {
        !           342:                                matched = ComparePartialUnicodeName(key->hfsPlus.nodeName.unicode,
        !           343:                                                                    key->hfsPlus.nodeName.length,
        !           344:                                                                    (UniChar*)searchInfo1->name,
        !           345:                                                                    searchInfo1->nameLength );
        !           346:                        } else /* full HFS Plus name match */ { 
        !           347:                                matched = (FastUnicodeCompare(key->hfsPlus.nodeName.unicode,
        !           348:                                                              key->hfsPlus.nodeName.length,
        !           349:                                                              (UniChar*)searchInfo1->name,
        !           350:                                                              searchInfo1->nameLength ) == 0);
        !           351:                        }
        !           352:                } else {
        !           353:                        /* Check for partial/full HFS name match */
        !           354: 
        !           355:                        if ( searchBits & SRCHFS_MATCHPARTIALNAMES )
        !           356:                                matched = ComparePartialPascalName(key->hfs.nodeName, (u_char*)searchInfo1->name);
        !           357:                        else /* full HFS name match */
        !           358:                                matched = (FastRelString(key->hfs.nodeName, (u_char*)searchInfo1->name) == 0);
        !           359:                }
        !           360:                
        !           361:                if ( matched == false || (searchBits & ~SRCHFS_MATCHPARTIALNAMES) == 0 )
        !           362:                        goto TestDone;  /* no match, or nothing more to compare */
        !           363:        }
        !           364:        
        !           365:        
        !           366:        /* Now that we have a record worth searching, see if it matches the search attributes */
        !           367:        if ( (catData.cnd_type == kCatalogFileNode) && ((attrList->fileattr & ATTR_FILE_VALIDMASK) != 0) )
        !           368:        {
        !           369:                searchAttributes = attrList->fileattr;
        !           370: 
        !           371:                /* File logical length (data fork) */
        !           372:                if ( searchAttributes & ATTR_FILE_DATALENGTH ) {
        !           373:                        matched = CompareWideRange(
        !           374:                            catData.cnd_datafork.logicalSize,
        !           375:                            searchInfo1->f.dataLogicalLength,
        !           376:                            searchInfo2->f.dataLogicalLength);
        !           377:                        if (matched == false) goto TestDone;
        !           378:                }
        !           379: 
        !           380:                /* File physical length (data fork) */
        !           381:                if ( searchAttributes & ATTR_FILE_DATAALLOCSIZE ) {
        !           382:                        matched = CompareWideRange(
        !           383:                            catData.cnd_datafork.totalBlocks * vcb->blockSize,
        !           384:                            searchInfo1->f.dataPhysicalLength,
        !           385:                            searchInfo2->f.dataPhysicalLength);
        !           386:                        if (matched == false) goto TestDone;
        !           387:                }
        !           388: 
        !           389:                /* File logical length (resource fork) */
        !           390:                if ( searchAttributes & ATTR_FILE_RSRCLENGTH ) {
        !           391:                        matched = CompareWideRange(
        !           392:                            catData.cnd_rsrcfork.logicalSize,
        !           393:                            searchInfo1->f.resourceLogicalLength,
        !           394:                            searchInfo2->f.resourceLogicalLength);
        !           395:                        if (matched == false) goto TestDone;
        !           396:                }
        !           397:                
        !           398:                /* File physical length (resource fork) */
        !           399:                if ( searchAttributes & ATTR_FILE_RSRCALLOCSIZE ) {
        !           400:                        matched = CompareWideRange(
        !           401:                            catData.cnd_rsrcfork.totalBlocks * vcb->blockSize,
        !           402:                            searchInfo1->f.resourcePhysicalLength,
        !           403:                            searchInfo2->f.resourcePhysicalLength);
        !           404:                        if (matched == false) goto TestDone;
        !           405:                }
        !           406:                
        !           407:                /* File logical length (resource + data fork) */
        !           408:                if ( searchAttributes & ATTR_FILE_TOTALSIZE ) {
        !           409:                        matched = CompareWideRange(
        !           410:                            catData.cnd_rsrcfork.logicalSize +
        !           411:                                catData.cnd_datafork.logicalSize, 
        !           412:                                                searchInfo1->f.resourceLogicalLength + searchInfo1->f.dataLogicalLength, 
        !           413:                            searchInfo2->f.resourceLogicalLength + searchInfo2->f.dataLogicalLength);
        !           414:                        if (matched == false) goto TestDone;
        !           415:                }
        !           416:                
        !           417:                /* File physical length (resource + data fork) */
        !           418:                if ( searchAttributes & ATTR_FILE_TOTALSIZE ) {
        !           419:                        matched = CompareWideRange(
        !           420:                            (catData.cnd_rsrcfork.totalBlocks +
        !           421:                            catData.cnd_datafork.totalBlocks) * vcb->blockSize, 
        !           422:                                                searchInfo1->f.resourcePhysicalLength + searchInfo1->f.dataPhysicalLength, 
        !           423:                                                searchInfo2->f.resourcePhysicalLength + searchInfo2->f.dataPhysicalLength );
        !           424:                        if (matched == false) goto TestDone;
        !           425:                }
        !           426:        }
        !           427:        /*
        !           428:         * Check the directory attributes
        !           429:         */
        !           430:        else if ( (catData.cnd_type == kCatalogFolderNode) && ((attrList->dirattr & ATTR_DIR_VALIDMASK) != 0) )
        !           431:        {
        !           432:                searchAttributes = attrList->dirattr;
        !           433:                
        !           434:                /* Directory valence */
        !           435:                if ( searchAttributes & ATTR_DIR_ENTRYCOUNT ) {
        !           436:                        matched = CompareRange(catData.cnd_valence, searchInfo1->d.numFiles, searchInfo2->d.numFiles );
        !           437:                        if (matched == false) goto TestDone;
        !           438:                }
        !           439:        }
        !           440:        
        !           441:        /*
        !           442:         * Check the common attributes
        !           443:         */
        !           444:        searchAttributes = attrList->commonattr;
        !           445:        if ( (searchAttributes & ATTR_CMN_VALIDMASK) != 0 ) {
        !           446: 
        !           447:                /* Parent ID */
        !           448:                if ( searchAttributes & ATTR_CMN_PAROBJID ) {
        !           449:                        HFSCatalogNodeID parentID;
        !           450:                        
        !           451:                        if (searchState->isHFSPlus)
        !           452:                                parentID = key->hfsPlus.parentID;
        !           453:                        else
        !           454:                                parentID = key->hfs.parentID;
        !           455:                                
        !           456:                        matched = CompareRange( parentID, searchInfo1->parentDirID, searchInfo2->parentDirID );
        !           457:                        if (matched == false) goto TestDone;
        !           458:                }
        !           459: 
        !           460:                /* Finder Info & Extended Finder Info where extFinderInfo is last 32 bytes */
        !           461:                if ( searchAttributes & ATTR_CMN_FNDRINFO ) {
        !           462:                        UInt32 *thisValue;
        !           463:                        thisValue = (UInt32 *) &catData.cnd_finderInfo;
        !           464: 
        !           465:                        /* 
        !           466:                         * Note: ioFlFndrInfo and ioDrUsrWds have the same offset in search info, so
        !           467:                         * no need to test the object type here.
        !           468:                         */
        !           469:                        matched = CompareMasked( thisValue, (UInt32 *) &searchInfo1->finderInfo, (UInt32 *) &searchInfo2->finderInfo, 8 ); /* 8 * UInt32 */
        !           470:                        if (matched == false) goto TestDone;
        !           471:                }
        !           472: 
        !           473:                /* Create date */
        !           474:                if ( searchAttributes & ATTR_CMN_CRTIME ) {
        !           475:                        matched = CompareRange(to_bsd_time(catData.cnd_createDate),
        !           476:                            searchInfo1->creationDate.tv_sec,  searchInfo2->creationDate.tv_sec );
        !           477:                        if (matched == false) goto TestDone;
        !           478:                }
        !           479:        
        !           480:                /* Mod date */
        !           481:                if ( searchAttributes & ATTR_CMN_MODTIME ) {
        !           482:                        matched = CompareRange(to_bsd_time(catData.cnd_contentModDate),
        !           483:                            searchInfo1->modificationDate.tv_sec, searchInfo2->modificationDate.tv_sec );
        !           484:                        if (matched == false) goto TestDone;
        !           485:                }
        !           486:        
        !           487:                /* Backup date */
        !           488:                if ( searchAttributes & ATTR_CMN_BKUPTIME ) {
        !           489:                        matched = CompareRange(to_bsd_time(catData.cnd_backupDate),
        !           490:                            searchInfo1->lastBackupDate.tv_sec, searchInfo2->lastBackupDate.tv_sec );
        !           491:                        if (matched == false) goto TestDone;
        !           492:                }
        !           493:        
        !           494:        }
        !           495: 
        !           496:        
        !           497: TestDone:
        !           498:        /*
        !           499:         * Finally, determine whether we need to negate the sense of the match
        !           500:         * (i.e. find all objects that DON'T match).
        !           501:         */
        !           502:        if ( searchBits & SRCHFS_NEGATEPARAMS )
        !           503:                matched = !matched;
        !           504:        
        !           505:        return( matched );
        !           506: }
        !           507: 
        !           508: 
        !           509: /*
        !           510:  * Adds another record to the packed array for output
        !           511:  */
        !           512: static int
        !           513: InsertMatch( struct vnode *root_vp, struct uio *a_uio, CatalogRecord *catalogRecord,
        !           514:                CatalogKey *key, struct attrlist *returnAttrList, void *attributesBuffer,
        !           515:                void *variableBuffer, u_long bufferSize, u_long * nummatches )
        !           516: {
        !           517:        int err;
        !           518:        void *rovingAttributesBuffer;
        !           519:        void *rovingVariableBuffer;
        !           520:        struct hfsCatalogInfo catalogInfo;
        !           521:        u_long packedBufferSize;
        !           522:        ExtendedVCB *vcb = VTOVCB(root_vp);
        !           523:        Boolean isHFSPlus = vcb->vcbSigWord == kHFSPlusSigWord;
        !           524:        u_long privateDir = VTOHFS(root_vp)->hfs_private_metadata_dir;
        !           525: 
        !           526:        rovingAttributesBuffer = (char*)attributesBuffer + sizeof(u_long); /* Reserve space for length field */
        !           527:        rovingVariableBuffer = variableBuffer;
        !           528: 
        !           529:        CopyCatalogNodeData( vcb, catalogRecord, &catalogInfo.nodeData );
        !           530: 
        !           531:        catalogInfo.spec.parID = isHFSPlus ? key->hfsPlus.parentID : key->hfs.parentID;
        !           532: 
        !           533:        /* hide open files that have been deleted */
        !           534:        if (catalogInfo.spec.parID == privateDir)
        !           535:                return (0);
        !           536: 
        !           537:        /* hide our private meta data directory */
        !           538:        if (catalogInfo.nodeData.cnd_nodeID == privateDir)
        !           539:                return (0);
        !           540: 
        !           541:        if ( returnAttrList->commonattr & ATTR_CMN_NAME )
        !           542:        {
        !           543:                ByteCount actualDstLen;
        !           544: 
        !           545:                /* Return result in UTF-8 */
        !           546:                if ( isHFSPlus ) {
        !           547:                        err = ConvertUnicodeToUTF8( key->hfsPlus.nodeName.length * sizeof(UniChar),
        !           548:                                                        key->hfsPlus.nodeName.unicode,
        !           549:                                                        sizeof(catalogInfo.spec.name),
        !           550:                                                        &actualDstLen,
        !           551:                                                        catalogInfo.spec.name);
        !           552:                 } else {
        !           553:                        err = hfs_to_utf8(vcb, key->hfs.nodeName,
        !           554:                                          sizeof(catalogInfo.spec.name),
        !           555:                                          &actualDstLen, catalogInfo.spec.name);
        !           556:                }
        !           557:        }
        !           558: 
        !           559:        PackCatalogInfoAttributeBlock( returnAttrList,root_vp, &catalogInfo, &rovingAttributesBuffer, &rovingVariableBuffer );
        !           560: 
        !           561:        packedBufferSize = (char*)rovingVariableBuffer - (char*)attributesBuffer;
        !           562: 
        !           563:        if ( packedBufferSize > a_uio->uio_resid )
        !           564:                return( errSearchBufferFull );
        !           565: 
        !           566:        (* nummatches)++;
        !           567:        
        !           568:        *((u_long *)attributesBuffer) = packedBufferSize;       /* Store length of fixed + var block */
        !           569:        
        !           570:        err = uiomove( (caddr_t)attributesBuffer, packedBufferSize, a_uio );    /* XXX should be packedBufferSize */
        !           571:        
        !           572:        return( err );
        !           573: }
        !           574: 
        !           575: 
        !           576: static int
        !           577: UnpackSearchAttributeBlock( struct vnode *vp, struct attrlist  *alist, searchinfospec_t *searchInfo, void *attributeBuffer )
        !           578: {
        !           579:        attrgroup_t             a;
        !           580:        u_long                  bufferSize;
        !           581: 
        !           582:     DBG_ASSERT(searchInfo != NULL);
        !           583: 
        !           584:        bufferSize = *((u_long *)attributeBuffer);
        !           585:        if (bufferSize == 0)
        !           586:                return (EINVAL);        /* XXX -DJB is a buffer size of zero ever valid for searchfs? */
        !           587: 
        !           588:        ++((u_long *)attributeBuffer);  /* advance past the size */
        !           589:        
        !           590:        /* 
        !           591:         * UnPack common attributes
        !           592:         */
        !           593:        a = alist->commonattr;
        !           594:        if ( a != 0 ) {
        !           595:                if ( a & ATTR_CMN_NAME ) {
        !           596:                        char *s = (char*) attributeBuffer + ((attrreference_t *) attributeBuffer)->attr_dataoffset;
        !           597:                        size_t len = ((attrreference_t *) attributeBuffer)->attr_length;
        !           598: 
        !           599:                        if (len > sizeof(searchInfo->name))
        !           600:                                return (EINVAL);
        !           601: 
        !           602:                        if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
        !           603:                                ByteCount actualDstLen;
        !           604:                                /* Convert name to Unicode to match HFS Plus B-Tree names */
        !           605: 
        !           606:                                if (len > 0) {
        !           607:                                        if (ConvertUTF8ToUnicode(len-1, s, sizeof(searchInfo->name),
        !           608:                                                        &actualDstLen, (UniChar*)searchInfo->name) != 0)
        !           609:                                                return (EINVAL);
        !           610: 
        !           611: 
        !           612:                                        searchInfo->nameLength = actualDstLen / sizeof(UniChar);
        !           613:                                } else {
        !           614:                                        searchInfo->nameLength = 0;
        !           615:                                }
        !           616:                                ++((attrreference_t *)attributeBuffer);
        !           617: 
        !           618:                        } else {
        !           619:                                /* Convert name to pascal string to match HFS B-Tree names */
        !           620: 
        !           621:                                if (len > 0) {
        !           622:                                        if (utf8_to_hfs(VTOVCB(vp), len-1, s, (u_char*)searchInfo->name) != 0)
        !           623:                                                return (EINVAL);
        !           624: 
        !           625:                                        searchInfo->nameLength = searchInfo->name[0];
        !           626:                                } else {
        !           627:                                        searchInfo->name[0] = searchInfo->nameLength = 0;
        !           628:                                }
        !           629:                                ++((attrreference_t *)attributeBuffer);
        !           630:                        }
        !           631:                }
        !           632:                if ( a & ATTR_CMN_PAROBJID ) {
        !           633:                        searchInfo->parentDirID = ((fsobj_id_t *) attributeBuffer)->fid_objno;  /* ignore fid_generation */
        !           634:                        ++((fsobj_id_t *)attributeBuffer);
        !           635:                }
        !           636:                if ( a & ATTR_CMN_CRTIME ) {
        !           637:                        searchInfo->creationDate = *((struct timespec *)attributeBuffer);
        !           638:                        ++((struct timespec *)attributeBuffer);
        !           639:                }
        !           640:                if ( a & ATTR_CMN_MODTIME ) {
        !           641:                        searchInfo->modificationDate = *((struct timespec *)attributeBuffer);
        !           642:                        ++((struct timespec *)attributeBuffer);
        !           643:                }
        !           644:                if ( a & ATTR_CMN_BKUPTIME ) {
        !           645:                        searchInfo->lastBackupDate = *((struct timespec *)attributeBuffer);
        !           646:                        ++((struct timespec *)attributeBuffer);
        !           647:                }
        !           648:                if ( a & ATTR_CMN_FNDRINFO ) {
        !           649:                   bcopy( attributeBuffer, searchInfo->finderInfo, sizeof(u_long) * 8 );
        !           650:                   attributeBuffer += (sizeof(u_long) * 8 );
        !           651:                }
        !           652:        }
        !           653: 
        !           654:        a = alist->dirattr;
        !           655:        if ( a != 0 ) {
        !           656:                if ( a & ATTR_DIR_ENTRYCOUNT ) {
        !           657:                        searchInfo->d.numFiles = *((u_long *)attributeBuffer);
        !           658:                        ++((u_long *)attributeBuffer);
        !           659:                }
        !           660:        }
        !           661: 
        !           662:        a = alist->fileattr;
        !           663:        if ( a != 0 ) {
        !           664:                if ( a & ATTR_FILE_DATALENGTH ) {
        !           665:                        searchInfo->f.dataLogicalLength = *((off_t *)attributeBuffer);
        !           666:                        ++((off_t *)attributeBuffer);
        !           667:                }
        !           668:                if ( a & ATTR_FILE_DATAALLOCSIZE ) {
        !           669:                        searchInfo->f.dataPhysicalLength = *((off_t *)attributeBuffer);
        !           670:                        ++((off_t *)attributeBuffer);
        !           671:                }
        !           672:                if ( a & ATTR_FILE_RSRCLENGTH ) {
        !           673:                        searchInfo->f.resourceLogicalLength = *((off_t *)attributeBuffer);
        !           674:                        ++((off_t *)attributeBuffer);
        !           675:                }
        !           676:                if ( a & ATTR_FILE_RSRCALLOCSIZE ) {
        !           677:                        searchInfo->f.resourcePhysicalLength = *((off_t *)attributeBuffer);
        !           678:                        ++((off_t *)attributeBuffer);
        !           679:                }
        !           680:        }
        !           681: 
        !           682:        return (0);
        !           683: }
        !           684: 
        !           685: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.