The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/hfs/hfs_search.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1997-2003 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  *
   25  *      @(#)hfs_search.c
   26  */
   27 
   28 #include <sys/param.h>
   29 #include <sys/systm.h>
   30 #include <sys/kernel.h>
   31 #include <sys/file.h>
   32 #include <sys/buf.h>
   33 #include <sys/proc.h>
   34 #include <sys/conf.h>
   35 #include <mach/machine/vm_types.h>
   36 #include <sys/vnode.h>
   37 #include <sys/malloc.h>
   38 #include <sys/signalvar.h>
   39 #include <sys/attr.h>
   40 #include <sys/utfconv.h>
   41 
   42 #include "hfs.h"
   43 #include "hfs_dbg.h"
   44 #include "hfs_catalog.h"
   45 #include "hfs_attrlist.h"
   46 #include "hfs_endian.h"
   47 
   48 #include "hfscommon/headers/FileMgrInternal.h"
   49 #include "hfscommon/headers/CatalogPrivate.h"
   50 #include "hfscommon/headers/HFSUnicodeWrappers.h"
   51 #include "hfscommon/headers/BTreesPrivate.h"
   52 #include "hfscommon/headers/BTreeScanner.h"
   53 
   54 
   55 /* Search criterea. */
   56 struct directoryInfoSpec
   57 {
   58         u_long          numFiles;
   59 };
   60 
   61 struct fileInfoSpec
   62 {
   63         off_t           dataLogicalLength;
   64         off_t           dataPhysicalLength;
   65         off_t           resourceLogicalLength;
   66         off_t           resourcePhysicalLength;
   67 };
   68 
   69 struct searchinfospec
   70 {
   71         u_char                  name[kHFSPlusMaxFileNameBytes];
   72         u_long                  nameLength;
   73         char                    attributes;             // see IM:Files 2-100
   74         u_long                  nodeID;
   75         u_long                  parentDirID;
   76         struct timespec         creationDate;           
   77         struct timespec         modificationDate;               
   78         struct timespec         changeDate;     
   79         struct timespec         accessDate;             
   80         struct timespec         lastBackupDate; 
   81         u_long                  finderInfo[8];
   82         uid_t                   uid;    
   83         gid_t                   gid;
   84         mode_t                  mask;
   85         struct fileInfoSpec     f;
   86         struct directoryInfoSpec d;
   87 };
   88 typedef struct searchinfospec searchinfospec_t;
   89 
   90 static void ResolveHardlink(ExtendedVCB *vcb, HFSPlusCatalogFile *recp);
   91 
   92 
   93 static int UnpackSearchAttributeBlock(struct vnode *vp, struct attrlist *alist,
   94                 searchinfospec_t *searchInfo, void *attributeBuffer);
   95 
   96 static int CheckCriteria(       ExtendedVCB *vcb, 
   97                                                         u_long searchBits,
   98                                                         struct attrlist *attrList, 
   99                                                         CatalogRecord *rec,
  100                                                         CatalogKey *key, 
  101                                                         searchinfospec_t *searchInfo1,
  102                                                         searchinfospec_t *searchInfo2,
  103                                                         Boolean lookForDup );
  104 
  105 static int CheckAccess(ExtendedVCB *vcb, u_long searchBits, CatalogKey *key, struct proc *p);
  106 
  107 static int InsertMatch(struct vnode *vp, struct uio *a_uio, CatalogRecord *rec,
  108                         CatalogKey *key, struct attrlist *returnAttrList,
  109                         void *attributesBuffer, void *variableBuffer,
  110                         u_long bufferSize, u_long * nummatches );
  111 
  112 static Boolean CompareRange(u_long val, u_long low, u_long high);
  113 static Boolean CompareWideRange(u_int64_t val, u_int64_t low, u_int64_t high);
  114 
  115 static Boolean CompareRange( u_long val, u_long low, u_long high )
  116 {
  117         return( (val >= low) && (val <= high) );
  118 }
  119 
  120 static Boolean CompareWideRange( u_int64_t val, u_int64_t low, u_int64_t high )
  121 {
  122         return( (val >= low) && (val <= high) );
  123 }
  124 //#define CompareRange(val, low, high)  ((val >= low) && (val <= high))
  125                         
  126 #if 1 // Installer workaround (2940423)
  127 static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus );
  128 #endif // Installer workaround
  129 
  130 extern int cat_convertkey(
  131                         struct hfsmount *hfsmp,
  132                         CatalogKey *key,
  133                         CatalogRecord * recp,
  134                         struct cat_desc *descp);
  135 
  136 extern void cat_convertattr(
  137                         struct hfsmount *hfsmp,
  138                         CatalogRecord * recp,
  139                         struct cat_attr *attrp,
  140                         struct cat_fork *datafp,
  141                         struct cat_fork *rsrcfp);
  142 
  143 extern int resolvelink(struct hfsmount *hfsmp, u_long linkref,
  144                         struct HFSPlusCatalogFile *recp);
  145 
  146 /************************************************************************/
  147 /* Entry for searchfs()                                                 */
  148 /************************************************************************/
  149 
  150 #define errSearchBufferFull     101     /* Internal search errors */
  151 /*
  152 #
  153 #% searchfs     vp      L L L
  154 #
  155 vop_searchfs {
  156     IN struct vnode *vp;
  157     IN off_t length;
  158     IN int flags;
  159     IN struct ucred *cred;
  160     IN struct proc *p;
  161 };
  162 */
  163 
  164 __private_extern__
  165 int
  166 hfs_search( ap )
  167         struct vop_searchfs_args *ap; /*
  168                 struct vnodeop_desc *a_desc;
  169                 struct vnode *a_vp;
  170                 void *a_searchparams1;
  171                 void *a_searchparams2;
  172                 struct attrlist *a_searchattrs;
  173                 u_long a_maxmatches;
  174                 struct timeval *a_timelimit;
  175                 struct attrlist *a_returnattrs;
  176                 u_long *a_nummatches;
  177                 u_long a_scriptcode;
  178                 u_long a_options;
  179                 struct uio *a_uio;
  180                 struct searchstate *a_searchstate;
  181         */
  182 {
  183         ExtendedVCB *vcb = VTOVCB(ap->a_vp);
  184         FCB * catalogFCB;
  185         searchinfospec_t searchInfo1;
  186         searchinfospec_t searchInfo2;
  187         void *attributesBuffer;
  188         void *variableBuffer;
  189         u_long fixedBlockSize;
  190         u_long eachReturnBufferSize;
  191         struct proc *p = current_proc();
  192         int err = E_NONE;
  193         int isHFSPlus;
  194         int timerExpired = false;
  195         int doQuickExit = false;
  196         CatalogKey * myCurrentKeyPtr;
  197         CatalogRecord * myCurrentDataPtr;
  198         CatPosition * myCatPositionPtr;
  199         BTScanState myBTScanState;
  200         void *user_start = NULL;
  201         int   user_len;
  202         int32_t searchTime;
  203 
  204         /* XXX Parameter check a_searchattrs? */
  205 
  206         *(ap->a_nummatches) = 0;
  207 
  208         if (ap->a_options & ~SRCHFS_VALIDOPTIONSMASK)
  209                 return (EINVAL);
  210 
  211         /* SRCHFS_SKIPLINKS requires root access.
  212          * This option cannot be used with either
  213          * the ATTR_CMN_NAME or ATTR_CMN_PAROBJID
  214          * attributes.
  215          */
  216         if (ap->a_options & SRCHFS_SKIPLINKS) {
  217                 attrgroup_t attrs;
  218 
  219                 attrs = ap->a_searchattrs->commonattr | ap->a_returnattrs->commonattr;
  220                 if (attrs & (ATTR_CMN_NAME | ATTR_CMN_PAROBJID))
  221                         return (EINVAL);
  222                 if ((err = suser(p->p_ucred, &p->p_acflag)))
  223                         return (err);
  224         }
  225 
  226         if (ap->a_uio->uio_resid <= 0)
  227                 return (EINVAL);
  228 
  229         isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
  230         
  231         searchTime = kMaxMicroSecsInKernel;
  232         if (ap->a_timelimit->tv_sec == 0 &&
  233             ap->a_timelimit->tv_usec > 0 &&
  234             ap->a_timelimit->tv_usec < kMaxMicroSecsInKernel) {
  235                 searchTime = ap->a_timelimit->tv_usec;
  236         }
  237 
  238         /* UnPack the search boundries, searchInfo1, searchInfo2 */
  239         err = UnpackSearchAttributeBlock(ap->a_vp, ap->a_searchattrs,
  240                                 &searchInfo1, ap->a_searchparams1);
  241         if (err) return err;
  242         err = UnpackSearchAttributeBlock(ap->a_vp, ap->a_searchattrs,
  243                                 &searchInfo2, ap->a_searchparams2);
  244         if (err) return err;
  245 
  246         fixedBlockSize = sizeof(u_long) + hfs_attrblksize(ap->a_returnattrs);   /* u_long for length longword */
  247         eachReturnBufferSize = fixedBlockSize;
  248 
  249         if ( ap->a_returnattrs->commonattr & ATTR_CMN_NAME )    /* XXX should be more robust! */
  250                 eachReturnBufferSize += kHFSPlusMaxFileNameBytes + 1;
  251 
  252         MALLOC( attributesBuffer, void *, eachReturnBufferSize, M_TEMP, M_WAITOK );
  253         variableBuffer = (void*)((char*) attributesBuffer + fixedBlockSize);
  254 
  255         // XXXdbg - have to lock the user's buffer so we don't fault
  256         // while holding the shared catalog file lock.  see the comment
  257         // in hfs_readdir() for more details.
  258         //
  259         if (VTOHFS(ap->a_vp)->jnl && ap->a_uio->uio_segflg == UIO_USERSPACE) {
  260                 user_start = ap->a_uio->uio_iov->iov_base;
  261                 user_len   = ap->a_uio->uio_iov->iov_len;
  262 
  263                 if ((err = vslock(user_start, user_len)) != 0) {
  264                         user_start = NULL;
  265                         goto ExitThisRoutine;
  266                 }
  267         }
  268 
  269         /* Lock catalog b-tree */
  270         err = hfs_metafilelocking(VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_SHARED, p);
  271         if (err)
  272                 goto ExitThisRoutine;
  273 
  274         catalogFCB = GetFileControlBlock(vcb->catalogRefNum);
  275         myCurrentKeyPtr = NULL;
  276         myCurrentDataPtr = NULL;
  277         myCatPositionPtr = (CatPosition *)ap->a_searchstate;
  278 
  279         if (ap->a_options & SRCHFS_START) {
  280                 /* Starting a new search. */
  281                 /* Make sure the on-disk Catalog file is current */
  282                 (void) VOP_FSYNC(vcb->catalogRefNum, NOCRED, MNT_WAIT, p);
  283                 if (VTOHFS(ap->a_vp)->jnl) {
  284                     journal_flush(VTOHFS(ap->a_vp)->jnl);
  285                 }
  286 
  287                 ap->a_options &= ~SRCHFS_START;
  288                 bzero( (caddr_t)myCatPositionPtr, sizeof( *myCatPositionPtr ) );
  289                 err = BTScanInitialize(catalogFCB, 0, 0, 0, kCatSearchBufferSize, &myBTScanState);
  290                 
  291 #if 1 // Installer workaround (2940423)
  292                 // hack to get around installer problems when the installer expects search results 
  293                 // to be in key order.  At this point the problem appears to be limited to 
  294                 // searches for "Library".  The idea here is to go get the "Library" at root
  295                 // and return it first to the caller then continue the search as normal with
  296                 // the exception of taking care not to return a duplicate hit (see CheckCriteria) 
  297                 if ( err == E_NONE &&
  298                          (ap->a_searchattrs->commonattr & ATTR_CMN_NAME) != 0 &&
  299                          IsTargetName( &searchInfo1, isHFSPlus )  )
  300                 {
  301                         CatalogRecord           rec;
  302                         BTreeIterator       iterator;
  303                         FSBufferDescriptor  btrec;
  304                         CatalogKey *            keyp;
  305                         UInt16              reclen;
  306                         OSErr                           result;
  307                 
  308                         bzero( (caddr_t)&iterator, sizeof( iterator ) );
  309                         keyp = (CatalogKey *) &iterator.key;
  310                         (void) BuildCatalogKeyUTF8(vcb, kRootDirID, "Library", kUndefinedStrLen, keyp, NULL);
  311 
  312                         btrec.bufferAddress = &rec;
  313                         btrec.itemCount = 1;
  314                         btrec.itemSize = sizeof( rec );
  315 
  316                         result = BTSearchRecord( catalogFCB, &iterator, &btrec, &reclen, &iterator );
  317                         if ( result == E_NONE ) {
  318                                 if (CheckCriteria(vcb, ap->a_options, ap->a_searchattrs, &rec,
  319                                                                   keyp, &searchInfo1, &searchInfo2, false) &&
  320                                         CheckAccess(vcb, ap->a_options, keyp, ap->a_uio->uio_procp)) {
  321                 
  322                                         result = InsertMatch(ap->a_vp, ap->a_uio, &rec, 
  323                                                                           keyp, ap->a_returnattrs,
  324                                                                           attributesBuffer, variableBuffer,
  325                                                                           eachReturnBufferSize, ap->a_nummatches);
  326                                         if (result == E_NONE && *(ap->a_nummatches) >= ap->a_maxmatches)
  327                                                 doQuickExit = true;
  328                                 }
  329                         }
  330                 }
  331 #endif // Installer workaround
  332         } else {
  333                 /* Resuming a search. */
  334                 err = BTScanInitialize(catalogFCB, myCatPositionPtr->nextNode, 
  335                                         myCatPositionPtr->nextRecord, 
  336                                         myCatPositionPtr->recordsFound,
  337                                         kCatSearchBufferSize, 
  338                                         &myBTScanState);
  339                 /* Make sure Catalog hasn't changed. */
  340                 if (err == 0
  341                 &&  myCatPositionPtr->writeCount != myBTScanState.btcb->writeCount) {
  342                         myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount;
  343                         err = EBUSY; /* catChangedErr */
  344                 }
  345         }
  346 
  347         /* Unlock catalog b-tree */
  348         (void) hfs_metafilelocking(VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, p);
  349         if (err)
  350                 goto ExitThisRoutine;
  351 #if 1 // Installer workaround (2940423)
  352         if ( doQuickExit )
  353                 goto QuickExit;
  354 #endif // Installer workaround
  355 
  356         /*
  357          * Check all the catalog btree records...
  358          *   return the attributes for matching items
  359          */
  360         for (;;) {
  361                 struct timeval myCurrentTime;
  362                 struct timeval myElapsedTime;
  363                 
  364                 err = BTScanNextRecord(&myBTScanState, timerExpired, 
  365                         (void **)&myCurrentKeyPtr, (void **)&myCurrentDataPtr, 
  366                         NULL);
  367                 if (err)
  368                         break;
  369 
  370                 /* Resolve any hardlinks */
  371                 if (isHFSPlus && (ap->a_options & SRCHFS_SKIPLINKS) == 0)
  372                         ResolveHardlink(vcb, (HFSPlusCatalogFile *) myCurrentDataPtr);
  373 
  374                 if (CheckCriteria( vcb, ap->a_options, ap->a_searchattrs, myCurrentDataPtr,
  375                                 myCurrentKeyPtr, &searchInfo1, &searchInfo2, true )
  376                 &&  CheckAccess(vcb, ap->a_options, myCurrentKeyPtr, ap->a_uio->uio_procp)) {
  377                         err = InsertMatch(ap->a_vp, ap->a_uio, myCurrentDataPtr, 
  378                                         myCurrentKeyPtr, ap->a_returnattrs,
  379                                         attributesBuffer, variableBuffer,
  380                                         eachReturnBufferSize, ap->a_nummatches);
  381                         if (err) {
  382                                 /*
  383                                  * The last match didn't fit so come back
  384                                  * to this record on the next trip.
  385                                  */
  386                                 --myBTScanState.recordsFound;
  387                                 --myBTScanState.recordNum;
  388                                 break;
  389                         }
  390 
  391                         if (*(ap->a_nummatches) >= ap->a_maxmatches)
  392                                 break;
  393                 }
  394 
  395                 /*
  396                  * Check our elapsed time and bail if we've hit the max.
  397                  * The idea here is to throttle the amount of time we
  398                  * spend in the kernel.
  399                  */
  400                 myCurrentTime = time;
  401                 timersub(&myCurrentTime, &myBTScanState.startTime, &myElapsedTime);
  402                 /* Note: assumes kMaxMicroSecsInKernel is less than 1,000,000 */
  403                 if (myElapsedTime.tv_sec > 0
  404                 ||  myElapsedTime.tv_usec >= searchTime) {
  405                         timerExpired = true;
  406                 }
  407         }
  408 
  409 QuickExit:
  410         /* Update catalog position */
  411         myCatPositionPtr->writeCount = myBTScanState.btcb->writeCount;
  412 
  413         BTScanTerminate(&myBTScanState, &myCatPositionPtr->nextNode, 
  414                         &myCatPositionPtr->nextRecord, 
  415                         &myCatPositionPtr->recordsFound);
  416 
  417         if ( err == E_NONE ) {
  418                 err = EAGAIN;   /* signal to the user to call searchfs again */
  419         } else if ( err == errSearchBufferFull ) {
  420                 if ( *(ap->a_nummatches) > 0 )
  421                         err = EAGAIN;
  422                 else
  423                         err = ENOBUFS;
  424         } else if ( err == btNotFound ) {
  425                 err = E_NONE;   /* the entire disk has been searched */
  426         } else if ( err == fsBTTimeOutErr ) {
  427                 err = EAGAIN;
  428         }
  429 
  430 ExitThisRoutine:
  431         FREE( attributesBuffer, M_TEMP );
  432 
  433         if (VTOHFS(ap->a_vp)->jnl && user_start) {
  434                 vsunlock(user_start, user_len, TRUE);
  435         }
  436 
  437         return (MacToVFSError(err));
  438 }
  439 
  440 
  441 static void
  442 ResolveHardlink(ExtendedVCB *vcb, HFSPlusCatalogFile *recp)
  443 {
  444         if ((recp->recordType == kHFSPlusFileRecord)
  445         &&  (SWAP_BE32(recp->userInfo.fdType) == kHardLinkFileType)
  446         &&  (SWAP_BE32(recp->userInfo.fdCreator) == kHFSPlusCreator)
  447         &&  ((to_bsd_time(recp->createDate) == vcb->vcbCrDate) ||
  448              (to_bsd_time(recp->createDate) == VCBTOHFS(vcb)->hfs_metadata_createdate))) {
  449                 cnid_t saved_cnid;
  450 
  451                 /* Export link's cnid (a unique value) instead of inode's cnid */
  452                 saved_cnid = recp->fileID;
  453                 (void) resolvelink(VCBTOHFS(vcb), recp->bsdInfo.special.iNodeNum, recp);
  454                 recp->fileID = saved_cnid;
  455         }
  456 }
  457 
  458 
  459 static Boolean
  460 CompareMasked(const UInt32 *thisValue, const UInt32 *compareData,
  461                 const UInt32 *compareMask, UInt32 count)
  462 {
  463         Boolean matched;
  464         UInt32  i;
  465         
  466         matched = true;         /* Assume it will all match */
  467         
  468         for (i=0; i<count; i++) {
  469                 if (((*thisValue++ ^ *compareData++) & *compareMask++) != 0) {
  470                         matched = false;
  471                         break;
  472                 }
  473         }
  474         
  475         return matched;
  476 }
  477 
  478 
  479 static Boolean
  480 ComparePartialUnicodeName (register ConstUniCharArrayPtr str, register ItemCount s_len,
  481                            register ConstUniCharArrayPtr find, register ItemCount f_len )
  482 {
  483         if (f_len == 0 || s_len == 0)
  484                 return FALSE;
  485 
  486         do {
  487                 if (s_len-- < f_len)
  488                         return FALSE;
  489         } while (FastUnicodeCompare(str++, f_len, find, f_len) != 0);
  490 
  491         return TRUE;
  492 }
  493 
  494 
  495 static Boolean
  496 ComparePartialPascalName ( register ConstStr31Param str, register ConstStr31Param find )
  497 {
  498         register u_char s_len = str[0];
  499         register u_char f_len = find[0];
  500         register u_char *tsp;
  501         Str31 tmpstr;
  502 
  503         if (f_len == 0 || s_len == 0)
  504                 return FALSE;
  505 
  506         bcopy(str, tmpstr, s_len + 1);
  507         tsp = &tmpstr[0];
  508 
  509         while (s_len-- >= f_len) {
  510                 *tsp = f_len;
  511 
  512                 if (FastRelString(tsp++, find) == 0)
  513                         return TRUE;
  514         }
  515 
  516         return FALSE;
  517 }
  518 
  519 
  520 
  521 static char *extension_table=NULL;
  522 static int   nexts;
  523 static int   max_ext_width;
  524 
  525 static int
  526 extension_cmp(void *a, void *b)
  527 {
  528     return (strlen((char *)a) - strlen((char *)b));
  529 }
  530 
  531 
  532 //
  533 // This is the api LaunchServices uses to inform the kernel
  534 // the list of package extensions to ignore.
  535 //
  536 // Internally we keep the list sorted by the length of the
  537 // the extension (from longest to shortest).  We sort the
  538 // list of extensions so that we can speed up our searches
  539 // when comparing file names -- we only compare extensions
  540 // that could possibly fit into the file name, not all of
  541 // them (i.e. a short 8 character name can't have an 8
  542 // character extension).
  543 //
  544 __private_extern__ int
  545 set_package_extensions_table(void *data, int nentries, int maxwidth)
  546 {
  547     char *new_exts, *ptr;
  548     int error, i, len;
  549     
  550     if (nentries <= 0 || nentries > 1024 || maxwidth <= 0 || maxwidth > 255) {
  551         return EINVAL;
  552     }
  553 
  554     MALLOC(new_exts, char *, nentries * maxwidth, M_TEMP, M_WAITOK);
  555     
  556     error = copyin(data, new_exts, nentries * maxwidth);
  557     if (error) {
  558         FREE(new_exts, M_TEMP);
  559         return error;
  560     }
  561 
  562     if (extension_table) {
  563         FREE(extension_table, M_TEMP);
  564     }
  565     extension_table = new_exts;
  566     nexts           = nentries;
  567     max_ext_width   = maxwidth;
  568 
  569     qsort(extension_table, nexts, maxwidth, extension_cmp);
  570 
  571     return 0;
  572 }
  573 
  574 
  575 static int
  576 is_package_name(char *name, int len)
  577 {
  578     int i, extlen;
  579     char *ptr, *name_ext;
  580     
  581     if (len <= 3) {
  582         return 0;
  583     }
  584 
  585     name_ext = NULL;
  586     for(ptr=name; *ptr != '\0'; ptr++) {
  587         if (*ptr == '.') {
  588             name_ext = ptr;
  589         }
  590     }
  591 
  592     // if there is no "." extension, it can't match
  593     if (name_ext == NULL) {
  594         return 0;
  595     }
  596 
  597     // advance over the "."
  598     name_ext++;
  599 
  600     // now iterate over all the extensions to see if any match
  601     ptr = &extension_table[0];
  602     for(i=0; i < nexts; i++, ptr+=max_ext_width) {
  603         extlen = strlen(ptr);
  604         if (strncmp(name_ext, ptr, extlen) == 0 && name_ext[extlen] == '\0') {
  605             // aha, a match!
  606             return 1;
  607         }
  608     }
  609 
  610     // if we get here, no extension matched
  611     return 0;
  612 }
  613 
  614 //
  615 // Determine if a name is "inappropriate" where the definition
  616 // of "inappropriate" is up to higher level execs.  Currently
  617 // that's limited to /System.
  618 //
  619 static int
  620 is_inappropriate_name(char *name, int len)
  621 {
  622     char *bad_names[] = { "System" };
  623     int   bad_len[]   = {        6 };
  624     int  i;
  625     
  626     for(i=0; i < sizeof(bad_names) / sizeof(bad_names[0]); i++) {
  627         if (len == bad_len[i] && strcmp(name, bad_names[i]) == 0) {
  628             return 1;
  629         }
  630     }
  631 
  632     // if we get here, no name matched
  633     return 0;
  634 }
  635 
  636 
  637 
  638 /*
  639  * Check to see if caller has access rights to this item
  640  */
  641 
  642 static int
  643 CheckAccess(ExtendedVCB *theVCBPtr, u_long searchBits, CatalogKey *theKeyPtr, struct proc *theProcPtr)
  644 {
  645         Boolean                 isHFSPlus;
  646         int                     myErr;
  647         int                     myResult;       
  648         HFSCatalogNodeID        myNodeID;
  649         unsigned long           myPerms;
  650         hfsmount_t *            my_hfsmountPtr;
  651         struct cat_desc         my_cat_desc;
  652         struct cat_attr         my_cat_attr;
  653         struct FndrDirInfo     *finder_info;
  654 
  655         
  656         myResult = 0;   /* default to "no access" */
  657         my_cat_desc.cd_nameptr = NULL;
  658         my_cat_desc.cd_namelen = 0;
  659                 
  660         if ( theProcPtr->p_ucred->cr_uid == 0 ) {
  661                 myResult = 1;   /* allow access */
  662                 goto ExitThisRoutine; /* root always has access */
  663         }
  664 
  665         my_hfsmountPtr = VCBTOHFS( theVCBPtr );
  666         isHFSPlus = ( theVCBPtr->vcbSigWord == kHFSPlusSigWord );
  667         if ( isHFSPlus )
  668                 myNodeID = theKeyPtr->hfsPlus.parentID;
  669         else
  670                 myNodeID = theKeyPtr->hfs.parentID;
  671         
  672         while ( myNodeID >= kRootDirID ) {
  673                 /* now go get catalog data for this directory */
  674                 myErr = hfs_metafilelocking( my_hfsmountPtr, kHFSCatalogFileID, LK_SHARED, theProcPtr );
  675                 if ( myErr )
  676                         goto ExitThisRoutine;   /* no access */
  677         
  678                 myErr = cat_idlookup( my_hfsmountPtr, myNodeID, &my_cat_desc, &my_cat_attr, NULL );
  679                 (void) hfs_metafilelocking( my_hfsmountPtr, kHFSCatalogFileID, LK_RELEASE, theProcPtr );
  680                 if ( myErr )
  681                         goto ExitThisRoutine;   /* no access */
  682 
  683                 if (searchBits & SRCHFS_SKIPPACKAGES) {
  684                     if (is_package_name(my_cat_desc.cd_nameptr, my_cat_desc.cd_namelen)) {
  685                         myResult = 0;
  686                         goto ExitThisRoutine;
  687                     }
  688                 }
  689 
  690                 if (searchBits & SRCHFS_SKIPINAPPROPRIATE) {
  691                     if (   my_cat_desc.cd_parentcnid == kRootDirID
  692                         && is_inappropriate_name(my_cat_desc.cd_nameptr, my_cat_desc.cd_namelen)) {
  693                         myResult = 0;
  694                         goto ExitThisRoutine;
  695                     }
  696                 }
  697 
  698                 finder_info = (struct FndrDirInfo *)&my_cat_attr.ca_finderinfo[0];
  699                 if (   (searchBits & SRCHFS_SKIPINVISIBLE)
  700                     && (SWAP_BE16(finder_info->frFlags) & kIsInvisible)) {
  701                     
  702                     myResult = 0;
  703                     goto ExitThisRoutine;
  704                 }
  705 
  706                 myNodeID = my_cat_desc.cd_parentcnid;   /* move up the hierarchy */
  707                 myPerms = DerivePermissionSummary(my_cat_attr.ca_uid, my_cat_attr.ca_gid, 
  708                                                 my_cat_attr.ca_mode, my_hfsmountPtr->hfs_mp,
  709                                                 theProcPtr->p_ucred, theProcPtr  );
  710 
  711                 cat_releasedesc( &my_cat_desc );
  712                 
  713                 if ( (myPerms & X_OK) == 0 )
  714                         goto ExitThisRoutine;   /* no access */
  715         }
  716         
  717         myResult = 1;   /* allow access */
  718 
  719 ExitThisRoutine:
  720         cat_releasedesc( &my_cat_desc );
  721         return ( myResult );
  722         
  723 }
  724 
  725 static int
  726 CheckCriteria(  ExtendedVCB *vcb, 
  727                                 u_long searchBits,
  728                                 struct attrlist *attrList, 
  729                                 CatalogRecord *rec, 
  730                                 CatalogKey *key,
  731                                 searchinfospec_t  *searchInfo1, 
  732                                 searchinfospec_t *searchInfo2,
  733                                 Boolean lookForDup )
  734 {
  735         Boolean matched, atleastone;
  736         Boolean isHFSPlus;
  737         attrgroup_t searchAttributes;
  738         struct cat_attr c_attr = {0};
  739         struct cat_fork datafork;
  740         struct cat_fork rsrcfork;
  741         
  742         isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
  743 
  744         switch (rec->recordType) {
  745         case kHFSFolderRecord:
  746         case kHFSPlusFolderRecord:
  747                 if ( (searchBits & SRCHFS_MATCHDIRS) == 0 ) {   /* If we are NOT searching folders */
  748                         matched = false;
  749                         goto TestDone;
  750                 }
  751                 break;
  752                         
  753         case kHFSFileRecord:
  754                 if ( (searchBits & SRCHFS_MATCHFILES) == 0 ) {  /* If we are NOT searching files */
  755                         matched = false;
  756                         goto TestDone;
  757                 }
  758                 break;
  759 
  760         case kHFSPlusFileRecord:
  761                 /* Check if hardlink links should be skipped. */
  762                 if (searchBits & SRCHFS_SKIPLINKS) {
  763                         cnid_t parid = key->hfsPlus.parentID;
  764                         HFSPlusCatalogFile *filep = (HFSPlusCatalogFile *)rec;
  765 
  766                         if ((SWAP_BE32(filep->userInfo.fdType) == kHardLinkFileType) &&
  767                             (SWAP_BE32(filep->userInfo.fdCreator) == kHFSPlusCreator)) {
  768                                 return (false); /* skip over link records */
  769                         } else if ((parid == VCBTOHFS(vcb)->hfs_privdir_desc.cd_cnid) &&
  770                                    (filep->bsdInfo.special.linkCount == 0)) {
  771                                 return (false); /* skip over unlinked files */
  772                         }
  773                 } else if (key->hfsPlus.parentID == VCBTOHFS(vcb)->hfs_privdir_desc.cd_cnid) {
  774                         return (false); /* skip over private files */
  775                 }
  776 
  777                 if ( (searchBits & SRCHFS_MATCHFILES) == 0 ) {  /* If we are NOT searching files */
  778                         matched = false;
  779                         goto TestDone;
  780                 }
  781                 break;
  782 
  783         default:        /* Never match a thread record or any other type. */
  784                 return( false );        /* Not a file or folder record, so can't search it */
  785         }
  786         
  787         matched = true;         /* Assume we got a match */
  788         atleastone = false;     /* Dont insert unless we match at least one criteria */
  789         
  790         /* First, attempt to match the name -- either partial or complete */
  791         if ( attrList->commonattr & ATTR_CMN_NAME ) {
  792                 if (isHFSPlus) {
  793                         /* Check for partial/full HFS Plus name match */
  794 
  795                         if ( searchBits & SRCHFS_MATCHPARTIALNAMES ) {
  796                                 matched = ComparePartialUnicodeName(key->hfsPlus.nodeName.unicode,
  797                                                                     key->hfsPlus.nodeName.length,
  798                                                                     (UniChar*)searchInfo1->name,
  799                                                                     searchInfo1->nameLength );
  800                         } else /* full HFS Plus name match */ { 
  801                                 matched = (FastUnicodeCompare(key->hfsPlus.nodeName.unicode,
  802                                                               key->hfsPlus.nodeName.length,
  803                                                               (UniChar*)searchInfo1->name,
  804                                                               searchInfo1->nameLength ) == 0);
  805                         }
  806                 } else {
  807                         /* Check for partial/full HFS name match */
  808 
  809                         if ( searchBits & SRCHFS_MATCHPARTIALNAMES )
  810                                 matched = ComparePartialPascalName(key->hfs.nodeName, (u_char*)searchInfo1->name);
  811                         else /* full HFS name match */
  812                                 matched = (FastRelString(key->hfs.nodeName, (u_char*)searchInfo1->name) == 0);
  813                 }
  814 
  815 #if 1 // Installer workaround (2940423)
  816                 if ( lookForDup ) {
  817                         HFSCatalogNodeID parentID;
  818                         if (isHFSPlus)
  819                                 parentID = key->hfsPlus.parentID;
  820                         else
  821                                 parentID = key->hfs.parentID;
  822         
  823                         if ( matched && parentID == kRootDirID && 
  824                                  IsTargetName( searchInfo1, isHFSPlus )  )
  825                                 matched = false;
  826                 }
  827 #endif // Installer workaround
  828 
  829                 if ( matched == false || (searchBits & ~SRCHFS_MATCHPARTIALNAMES) == 0 )
  830                         goto TestDone;  /* no match, or nothing more to compare */
  831 
  832                 atleastone = true;
  833         }
  834 
  835         /* Convert catalog record into cat_attr format. */
  836         cat_convertattr(VCBTOHFS(vcb), rec, &c_attr, &datafork, &rsrcfork);
  837         
  838         if (searchBits & SRCHFS_SKIPINVISIBLE) {
  839             int flags;
  840             
  841             switch (rec->recordType) {
  842                 case kHFSFolderRecord:
  843                 case kHFSPlusFolderRecord: {
  844                     struct FndrDirInfo *finder_info;
  845                     
  846                     finder_info = (struct FndrDirInfo *)&c_attr.ca_finderinfo[0];
  847                     flags = SWAP_BE16(finder_info->frFlags);
  848                     break;
  849                 }
  850                         
  851                 case kHFSFileRecord:
  852                 case kHFSPlusFileRecord: {
  853                     struct FndrFileInfo *finder_info;
  854                     
  855                     finder_info = (struct FndrFileInfo *)&c_attr.ca_finderinfo[0];
  856                     flags = SWAP_BE16(finder_info->fdFlags);
  857                     break;
  858                 }
  859 
  860                 default: {
  861                     flags = kIsInvisible;
  862                     break;
  863                 }
  864             }
  865                     
  866             if (flags & kIsInvisible) {
  867                 matched = false;
  868                 goto TestDone;
  869             }
  870         }
  871         
  872                     
  873 
  874         /* Now that we have a record worth searching, see if it matches the search attributes */
  875         if (rec->recordType == kHFSFileRecord ||
  876             rec->recordType == kHFSPlusFileRecord) {
  877                 if ((attrList->fileattr & ~ATTR_FILE_VALIDMASK) != 0) { /* attr we do know about  */
  878                         matched = false;
  879                         goto TestDone;
  880                 }
  881                 else if ((attrList->fileattr & ATTR_FILE_VALIDMASK) != 0) {
  882                 searchAttributes = attrList->fileattr;
  883         
  884                 /* File logical length (data fork) */
  885                 if ( searchAttributes & ATTR_FILE_DATALENGTH ) {
  886                         matched = CompareWideRange(
  887                             datafork.cf_size,
  888                             searchInfo1->f.dataLogicalLength,
  889                             searchInfo2->f.dataLogicalLength);
  890                         if (matched == false) goto TestDone;
  891                                 atleastone = true;
  892                 }
  893         
  894                 /* File physical length (data fork) */
  895                 if ( searchAttributes & ATTR_FILE_DATAALLOCSIZE ) {
  896                         matched = CompareWideRange(
  897                             (u_int64_t)datafork.cf_blocks * (u_int64_t)vcb->blockSize,
  898                             searchInfo1->f.dataPhysicalLength,
  899                             searchInfo2->f.dataPhysicalLength);
  900                         if (matched == false) goto TestDone;
  901                                 atleastone = true;
  902                 }
  903 
  904                 /* File logical length (resource fork) */
  905                 if ( searchAttributes & ATTR_FILE_RSRCLENGTH ) {
  906                         matched = CompareWideRange(
  907                             rsrcfork.cf_size,
  908                             searchInfo1->f.resourceLogicalLength,
  909                             searchInfo2->f.resourceLogicalLength);
  910                         if (matched == false) goto TestDone;
  911                                 atleastone = true;
  912                 }
  913                 
  914                 /* File physical length (resource fork) */
  915                 if ( searchAttributes & ATTR_FILE_RSRCALLOCSIZE ) {
  916                         matched = CompareWideRange(
  917                             (u_int64_t)rsrcfork.cf_blocks * (u_int64_t)vcb->blockSize,
  918                             searchInfo1->f.resourcePhysicalLength,
  919                             searchInfo2->f.resourcePhysicalLength);
  920                         if (matched == false) goto TestDone;
  921                                 atleastone = true;
  922                         }
  923                 }
  924                 else {
  925                         atleastone = true;      /* to match SRCHFS_MATCHFILES */
  926                 }
  927         }
  928         /*
  929          * Check the directory attributes
  930          */
  931         else if (rec->recordType == kHFSFolderRecord ||
  932                  rec->recordType == kHFSPlusFolderRecord) {
  933                 if ((attrList->dirattr & ~ATTR_DIR_VALIDMASK) != 0) {   /* attr we do know about  */
  934                         matched = false;
  935                         goto TestDone;
  936                 }
  937                 else if ((attrList->dirattr & ATTR_DIR_VALIDMASK) != 0) {
  938                 searchAttributes = attrList->dirattr;
  939                 
  940                 /* Directory valence */
  941                 if ( searchAttributes & ATTR_DIR_ENTRYCOUNT ) {
  942                         matched = CompareRange(c_attr.ca_entries,
  943                                         searchInfo1->d.numFiles,
  944                                         searchInfo2->d.numFiles );
  945                         if (matched == false) goto TestDone;
  946                                 atleastone = true;
  947                         }
  948                 }
  949                 else {
  950                         atleastone = true;              /* to match SRCHFS_MATCHDIRS */
  951                 }
  952         }
  953         
  954         /*
  955          * Check the common attributes
  956          */
  957         searchAttributes = attrList->commonattr;
  958         if ( (searchAttributes & ATTR_CMN_VALIDMASK) != 0 ) {
  959                 /* node ID */
  960                 if ( searchAttributes & ATTR_CMN_OBJID ) {
  961                         matched = CompareRange(c_attr.ca_fileid,
  962                                         searchInfo1->nodeID,
  963                                         searchInfo2->nodeID );
  964                         if (matched == false) goto TestDone;
  965                         atleastone = true;
  966                 }
  967 
  968                 /* Parent ID */
  969                 if ( searchAttributes & ATTR_CMN_PAROBJID ) {
  970                         HFSCatalogNodeID parentID;
  971                         
  972                         if (isHFSPlus)
  973                                 parentID = key->hfsPlus.parentID;
  974                         else
  975                                 parentID = key->hfs.parentID;
  976                                 
  977                         matched = CompareRange(parentID, searchInfo1->parentDirID,
  978                                         searchInfo2->parentDirID );
  979                         if (matched == false) goto TestDone;
  980                         atleastone = true;
  981                 }
  982 
  983                 /* Finder Info & Extended Finder Info where extFinderInfo is last 32 bytes */
  984                 if ( searchAttributes & ATTR_CMN_FNDRINFO ) {
  985                         UInt32 *thisValue;
  986                         thisValue = (UInt32 *) &c_attr.ca_finderinfo;
  987 
  988                         /* 
  989                          * Note: ioFlFndrInfo and ioDrUsrWds have the same offset in search info, so
  990                          * no need to test the object type here.
  991                          */
  992                         matched = CompareMasked(thisValue,
  993                                         (UInt32 *)&searchInfo1->finderInfo,
  994                                         (UInt32 *) &searchInfo2->finderInfo, 8);
  995                         if (matched == false) goto TestDone;
  996                         atleastone = true;
  997                 }
  998 
  999                 /* Create date */
 1000                 if ( searchAttributes & ATTR_CMN_CRTIME ) {
 1001                         matched = CompareRange(c_attr.ca_itime,
 1002                                         searchInfo1->creationDate.tv_sec,
 1003                                         searchInfo2->creationDate.tv_sec);
 1004                         if (matched == false) goto TestDone;
 1005                         atleastone = true;
 1006                 }
 1007         
 1008                 /* Mod date */
 1009                 if ( searchAttributes & ATTR_CMN_MODTIME ) {
 1010                         matched = CompareRange(c_attr.ca_mtime,
 1011                                         searchInfo1->modificationDate.tv_sec,
 1012                                         searchInfo2->modificationDate.tv_sec);
 1013                         if (matched == false) goto TestDone;
 1014                         atleastone = true;
 1015                 }
 1016         
 1017                 /* Change Time */
 1018                 if ( searchAttributes & ATTR_CMN_CHGTIME ) {
 1019                         matched = CompareRange(c_attr.ca_ctime,
 1020                                         searchInfo1->changeDate.tv_sec,
 1021                                         searchInfo2->changeDate.tv_sec);
 1022                         if (matched == false) goto TestDone;
 1023                         atleastone = true;
 1024                 }
 1025         
 1026                 /* Access date */
 1027                 if ( searchAttributes & ATTR_CMN_ACCTIME ) {
 1028                         matched = CompareRange(c_attr.ca_atime,
 1029                                         searchInfo1->accessDate.tv_sec,
 1030                                         searchInfo2->accessDate.tv_sec);
 1031                         if (matched == false) goto TestDone;
 1032                         atleastone = true;
 1033                 }
 1034 
 1035                 /* Backup date */
 1036                 if ( searchAttributes & ATTR_CMN_BKUPTIME ) {
 1037                         matched = CompareRange(c_attr.ca_btime,
 1038                                         searchInfo1->lastBackupDate.tv_sec,
 1039                                         searchInfo2->lastBackupDate.tv_sec);
 1040                         if (matched == false) goto TestDone;
 1041                         atleastone = true;
 1042                 }
 1043         
 1044                 /* User ID */
 1045                 if ( searchAttributes & ATTR_CMN_OWNERID ) {
 1046                         matched = CompareRange(c_attr.ca_uid,
 1047                                         searchInfo1->uid, searchInfo2->uid);
 1048                         if (matched == false) goto TestDone;
 1049                         atleastone = true;
 1050                 }
 1051 
 1052                 /* Group ID */
 1053                 if ( searchAttributes & ATTR_CMN_GRPID ) {
 1054                         matched = CompareRange(c_attr.ca_gid,
 1055                                         searchInfo1->gid, searchInfo2->gid);
 1056                         if (matched == false) goto TestDone;
 1057                         atleastone = true;
 1058                 }
 1059 
 1060                 /* mode */
 1061                 if ( searchAttributes & ATTR_CMN_ACCESSMASK ) {
 1062                         matched = CompareRange((u_long)c_attr.ca_mode, 
 1063                                         (u_long)searchInfo1->mask,
 1064                                         (u_long)searchInfo2->mask);
 1065                         if (matched == false) goto TestDone;
 1066                         atleastone = true;
 1067                 }
 1068         }
 1069 
 1070         /* If we got here w/o matching any, then set to false */
 1071         if (! atleastone)
 1072                 matched = false;
 1073         
 1074 TestDone:
 1075         /*
 1076          * Finally, determine whether we need to negate the sense of the match
 1077          * (i.e. find all objects that DON'T match).
 1078          */
 1079         if ( searchBits & SRCHFS_NEGATEPARAMS )
 1080                 matched = !matched;
 1081         
 1082         return( matched );
 1083 }
 1084 
 1085 
 1086 /*
 1087  * Adds another record to the packed array for output
 1088  */
 1089 static int
 1090 InsertMatch( struct vnode *root_vp, struct uio *a_uio, CatalogRecord *rec,
 1091                 CatalogKey *key, struct attrlist *returnAttrList, void *attributesBuffer,
 1092                 void *variableBuffer, u_long bufferSize, u_long * nummatches )
 1093 {
 1094         int err;
 1095         void *rovingAttributesBuffer;
 1096         void *rovingVariableBuffer;
 1097         u_long packedBufferSize;
 1098         ExtendedVCB *vcb = VTOVCB(root_vp);
 1099         Boolean isHFSPlus = vcb->vcbSigWord == kHFSPlusSigWord;
 1100         u_long privateDir = VTOHFS(root_vp)->hfs_privdir_desc.cd_cnid;
 1101         struct attrblock attrblk;
 1102         struct cat_desc c_desc = {0};
 1103         struct cat_attr c_attr = {0};
 1104         struct cat_fork datafork;
 1105         struct cat_fork rsrcfork;
 1106 
 1107         rovingAttributesBuffer = (char*)attributesBuffer + sizeof(u_long); /* Reserve space for length field */
 1108         rovingVariableBuffer = variableBuffer;
 1109 
 1110         /* Convert catalog record into cat_attr format. */
 1111         cat_convertattr(VTOHFS(root_vp), rec, &c_attr, &datafork, &rsrcfork);
 1112 
 1113         /* hide our private meta data directory */
 1114         if ((privateDir != 0) && (c_attr.ca_fileid == privateDir)) {
 1115                 err = 0;
 1116                 goto exit;
 1117         }
 1118 
 1119         /* Hide the private journal files */
 1120         if (VTOHFS(root_vp)->jnl &&
 1121             ((c_attr.ca_fileid == VTOHFS(root_vp)->hfs_jnlfileid) ||
 1122              (c_attr.ca_fileid == VTOHFS(root_vp)->hfs_jnlinfoblkid))) {
 1123                 err = 0;
 1124                 goto exit;
 1125         }
 1126 
 1127         if (returnAttrList->commonattr & ATTR_CMN_NAME) {
 1128                 cat_convertkey(VTOHFS(root_vp), key, rec, &c_desc);
 1129         } else {
 1130                 c_desc.cd_cnid = c_attr.ca_fileid;
 1131                 if (isHFSPlus)
 1132                         c_desc.cd_parentcnid = key->hfsPlus.parentID;
 1133                 else
 1134                         c_desc.cd_parentcnid = key->hfs.parentID;
 1135         }
 1136 
 1137         attrblk.ab_attrlist = returnAttrList;
 1138         attrblk.ab_attrbufpp = &rovingAttributesBuffer;
 1139         attrblk.ab_varbufpp = &rovingVariableBuffer;
 1140         attrblk.ab_flags = 0;
 1141         attrblk.ab_blocksize = 0;
 1142 
 1143         hfs_packattrblk(&attrblk, VTOHFS(root_vp), NULL, &c_desc, &c_attr, &datafork, &rsrcfork, a_uio->uio_procp);
 1144 
 1145         packedBufferSize = (char*)rovingVariableBuffer - (char*)attributesBuffer;
 1146 
 1147         if ( packedBufferSize > a_uio->uio_resid )
 1148                 return( errSearchBufferFull );
 1149 
 1150         (* nummatches)++;
 1151         
 1152         *((u_long *)attributesBuffer) = packedBufferSize;       /* Store length of fixed + var block */
 1153         
 1154         err = uiomove( (caddr_t)attributesBuffer, packedBufferSize, a_uio );    /* XXX should be packedBufferSize */
 1155 exit:
 1156         cat_releasedesc(&c_desc);
 1157         
 1158         return( err );
 1159 }
 1160 
 1161 
 1162 static int
 1163 UnpackSearchAttributeBlock( struct vnode *vp, struct attrlist   *alist, searchinfospec_t *searchInfo, void *attributeBuffer )
 1164 {
 1165         attrgroup_t             a;
 1166         u_long                  bufferSize;
 1167 
 1168     DBG_ASSERT(searchInfo != NULL);
 1169 
 1170         bufferSize = *((u_long *)attributeBuffer);
 1171         if (bufferSize == 0)
 1172                 return (EINVAL);        /* XXX -DJB is a buffer size of zero ever valid for searchfs? */
 1173 
 1174         ++((u_long *)attributeBuffer);  /* advance past the size */
 1175         
 1176         /* 
 1177          * UnPack common attributes
 1178          */
 1179         a = alist->commonattr;
 1180         if ( a != 0 ) {
 1181                 if ( a & ATTR_CMN_NAME ) {
 1182                         char *s = (char*) attributeBuffer + ((attrreference_t *) attributeBuffer)->attr_dataoffset;
 1183                         size_t len = ((attrreference_t *) attributeBuffer)->attr_length;
 1184 
 1185                         if (len > sizeof(searchInfo->name))
 1186                                 return (EINVAL);
 1187 
 1188                         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
 1189                                 size_t ucslen;
 1190                                 /* Convert name to Unicode to match HFS Plus B-Tree names */
 1191 
 1192                                 if (len > 0) {
 1193                                         if (utf8_decodestr(s, len-1, (UniChar*)searchInfo->name, &ucslen,
 1194                                             sizeof(searchInfo->name), ':', UTF_DECOMPOSED))
 1195                                                 return (EINVAL);
 1196 
 1197                                         searchInfo->nameLength = ucslen / sizeof(UniChar);
 1198                                 } else {
 1199                                         searchInfo->nameLength = 0;
 1200                                 }
 1201                                 ++((attrreference_t *)attributeBuffer);
 1202 
 1203                         } else {
 1204                                 /* Convert name to pascal string to match HFS B-Tree names */
 1205 
 1206                                 if (len > 0) {
 1207                                         if (utf8_to_hfs(VTOVCB(vp), len-1, s, (u_char*)searchInfo->name) != 0)
 1208                                                 return (EINVAL);
 1209 
 1210                                         searchInfo->nameLength = searchInfo->name[0];
 1211                                 } else {
 1212                                         searchInfo->name[0] = searchInfo->nameLength = 0;
 1213                                 }
 1214                                 ++((attrreference_t *)attributeBuffer);
 1215                         }
 1216                 }
 1217                 if ( a & ATTR_CMN_OBJID ) {
 1218                         searchInfo->nodeID = ((fsobj_id_t *) attributeBuffer)->fid_objno;       /* ignore fid_generation */
 1219                         ++((fsobj_id_t *)attributeBuffer);
 1220                 }
 1221                 if ( a & ATTR_CMN_PAROBJID ) {
 1222                         searchInfo->parentDirID = ((fsobj_id_t *) attributeBuffer)->fid_objno;  /* ignore fid_generation */
 1223                         ++((fsobj_id_t *)attributeBuffer);
 1224                 }
 1225                 if ( a & ATTR_CMN_CRTIME ) {
 1226                         searchInfo->creationDate = *((struct timespec *)attributeBuffer);
 1227                         ++((struct timespec *)attributeBuffer);
 1228                 }
 1229                 if ( a & ATTR_CMN_MODTIME ) {
 1230                         searchInfo->modificationDate = *((struct timespec *)attributeBuffer);
 1231                         ++((struct timespec *)attributeBuffer);
 1232                 }
 1233                 if ( a & ATTR_CMN_CHGTIME ) {
 1234                         searchInfo->changeDate = *((struct timespec *)attributeBuffer);
 1235                         ++((struct timespec *)attributeBuffer);
 1236                 }
 1237                 if ( a & ATTR_CMN_ACCTIME ) {
 1238                         searchInfo->accessDate = *((struct timespec *)attributeBuffer);
 1239                         ++((struct timespec *)attributeBuffer);
 1240                 }
 1241                 if ( a & ATTR_CMN_BKUPTIME ) {
 1242                         searchInfo->lastBackupDate = *((struct timespec *)attributeBuffer);
 1243                         ++((struct timespec *)attributeBuffer);
 1244                 }
 1245                 if ( a & ATTR_CMN_FNDRINFO ) {
 1246                         bcopy( attributeBuffer, searchInfo->finderInfo, sizeof(u_long) * 8 );
 1247                         (u_long *)attributeBuffer += 8;
 1248                 }
 1249                 if ( a & ATTR_CMN_OWNERID ) {
 1250                         searchInfo->uid = *((uid_t *)attributeBuffer);
 1251                         ++((uid_t *)attributeBuffer);
 1252                 }
 1253                 if ( a & ATTR_CMN_GRPID ) {
 1254                         searchInfo->gid = *((gid_t *)attributeBuffer);
 1255                         ++((gid_t *)attributeBuffer);
 1256                 }
 1257                 if ( a & ATTR_CMN_ACCESSMASK ) {
 1258                         searchInfo->mask = *((mode_t *)attributeBuffer);
 1259                         ++((mode_t *)attributeBuffer);
 1260                 }
 1261         }
 1262 
 1263         a = alist->dirattr;
 1264         if ( a != 0 ) {
 1265                 if ( a & ATTR_DIR_ENTRYCOUNT ) {
 1266                         searchInfo->d.numFiles = *((u_long *)attributeBuffer);
 1267                         ++((u_long *)attributeBuffer);
 1268                 }
 1269         }
 1270 
 1271         a = alist->fileattr;
 1272         if ( a != 0 ) {
 1273                 if ( a & ATTR_FILE_DATALENGTH ) {
 1274                         searchInfo->f.dataLogicalLength = *((off_t *)attributeBuffer);
 1275                         ++((off_t *)attributeBuffer);
 1276                 }
 1277                 if ( a & ATTR_FILE_DATAALLOCSIZE ) {
 1278                         searchInfo->f.dataPhysicalLength = *((off_t *)attributeBuffer);
 1279                         ++((off_t *)attributeBuffer);
 1280                 }
 1281                 if ( a & ATTR_FILE_RSRCLENGTH ) {
 1282                         searchInfo->f.resourceLogicalLength = *((off_t *)attributeBuffer);
 1283                         ++((off_t *)attributeBuffer);
 1284                 }
 1285                 if ( a & ATTR_FILE_RSRCALLOCSIZE ) {
 1286                         searchInfo->f.resourcePhysicalLength = *((off_t *)attributeBuffer);
 1287                         ++((off_t *)attributeBuffer);
 1288                 }
 1289         }
 1290 
 1291         return (0);
 1292 }
 1293 
 1294 
 1295 #if 1 // Installer workaround (2940423)
 1296 /* this routine was added as part of the work around where some installers would fail */
 1297 /* because they incorrectly assumed search results were in some kind of order.  */
 1298 /* This routine is used to indentify the problematic target.  At this point we */
 1299 /* only know of one.  This routine could be modified for more (I hope not). */
 1300 static Boolean IsTargetName( searchinfospec_t * searchInfoPtr, Boolean isHFSPlus )
 1301 {
 1302         if ( searchInfoPtr->name == NULL )
 1303                 return( false );
 1304                 
 1305         if (isHFSPlus) {
 1306                 HFSUniStr255 myName = {
 1307                         7,      /* number of unicode characters */
 1308                         {
 1309                                 'L','i','b','r','a','r','y'
 1310                         }
 1311                 };              
 1312                 if ( FastUnicodeCompare( myName.unicode, myName.length,
 1313                                                                  (UniChar*)searchInfoPtr->name,
 1314                                                                  searchInfoPtr->nameLength ) == 0 )  {
 1315                         return( true );
 1316                 }
 1317                                                   
 1318         } else {
 1319                 u_char          myName[32] = {
 1320                         0x07,'L','i','b','r','a','r','y'
 1321                 };
 1322                 if ( FastRelString(myName, (u_char*)searchInfoPtr->name) == 0 )  {
 1323                         return( true );
 1324                 }
 1325         }
 1326         return( false );
 1327         
 1328 } /* IsTargetName */
 1329 #endif // Installer workaround
 1330 

Cache object: bdf2539b408931fd522b494b2354cdd3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.