Annotation of XNU/bsd/hfs/hfs_search.c, revision 1.1.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.