Annotation of kernel/bsd/hfs/hfs_vfsutils.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*     @(#)hfs_vfsutils.c      4.0
        !            26: *
        !            27: *      (c) 1997-1999 Apple Computer, Inc.  All Rights Reserved
        !            28: *
        !            29: *      hfs_vfsutils.c -- Routines that go between the HFS layer and the VFS.
        !            30: *
        !            31: *      Change History (most recent first):
        !            32: *
        !            33: *       1-Mar-1999     Scott Roberts   Dont double MALLOC on long names.
        !            34: *      23-Feb-1999     Pat Dirks               Change incrementing of meta refcount to be done BEFORE lock is acquired.
        !            35: *       2-Feb-1999     Pat Dirks               For volume ATTR_CMN_SCRIPT use vcb->volumeNameEncodingHint instead of 0.
        !            36: *      18-Jan-1999     Pat Dirks               Changed CopyCatalogToHFSNode to start with ACCESSPERMS instead of adding
        !            37: *                                                              write access only for unlocked files (now handled via IMMUTABLE setting)
        !            38: *       7-Dec-1998 Pat Dirks           Changed PackCatalogInfoFileAttributeBlock to return proper I/O block size.
        !            39: *       7-Dec-1998     Don Brady               Pack the real text encoding instead of zero.
        !            40: *      16-Dec-1998     Don Brady               Use the root's crtime intead of vcb create time for getattrlist.
        !            41: *      16-Dec-1998     Don Brady               Use the root's crtime intead of vcb create time for getattrlist.
        !            42: *       2-Dec-1998     Scott Roberts   Copy the mdbVN correctly into the vcb.
        !            43: *    3-Dec-1998 Pat Dirks              Added support for ATTR_VOL_MOUNTFLAGS.
        !            44: *      20-Nov-1998     Don Brady               Add support for UTF-8 names.
        !            45: *   18-Nov-1998        Pat Dirks               Changed UnpackCommonAttributeBlock to call wait for hfs_chflags to update catalog entry when changing flags
        !            46: *   13-Nov-1998 Pat Dirks       Changed BestBlockSizeFit to try PAGE_SIZE only and skip check for MAXBSIZE.
        !            47: *      10-Nov-1998     Pat Dirks               Changed CopyCatalogToHFSNode to ensure consistency between lock flag and IMMUTABLE bits.
        !            48: *   10-Nov-1998        Pat Dirks               Added MapFileOffset(), LogicalBlockSize() and UpdateBlockMappingTable() routines.
        !            49: *      18-Nov-1998     Pat Dirks               Changed PackVolAttributeBlock to return proper logical block size
        !            50: *                               for ATTR_VOL_IOBLOCKSIZE attribute.
        !            51: *       3-Nov-1998     Umesh Vaishampayan      Changes to deal with "struct timespec"
        !            52: *                                                              change in the kernel.   
        !            53: *      23-Sep-1998     Don Brady               In UnpackCommonAttributeBlock simplified setting of gid, uid and mode.
        !            54: *   10-Nov-1998        Pat Dirks               Added MapFileOffset(), LogicalBlockSize() and UpdateBlockMappingTable() routines.
        !            55: *      17-Sep-1998     Pat Dirks               Changed BestBlockSizeFit to try MAXBSIZE and PAGE_SIZE first.
        !            56: *       8-Sep-1998     Don Brady               Fix CopyVNodeToCatalogNode to use h_mtime for contentModDate (instead of h_ctime).
        !            57: *       4-Sep-1998     Pat Dirks               Added BestBlockSizeFit routine.
        !            58: *      18-Aug-1998     Don Brady               Change DEBUG_BREAK_MSG to a DBG_UTILS in MacToVFSError (radar #2262802).
        !            59: *      30-Jun-1998     Don Brady               Add calls to MacToVFSError to hfs/hfsplus mount routines (for radar #2249539).
        !            60: *      22-Jun-1998     Don Brady               Add more error cases to MacToVFSError; all HFS Common errors are negative.
        !            61: *                                                              Changed hfsDelete to call DeleteFile for files.
        !            62: *       4-Jun-1998     Pat Dirks               Changed incorrect references to 'vcbAlBlkSize' to 'blockSize';
        !            63: *                                                              Added hfsCreateFileID.
        !            64: *       4-Jun-1998     Don Brady               Add hfsMoveRename to replace hfsMove and hfsRename. Use VPUT/VRELE macros
        !            65: *                                                              instead of vput/vrele to catch bad ref counts.
        !            66: *      28-May-1998     Pat Dirks               Adjusted for change in definition of ATTR_CMN_NAME and removed ATTR_CMN_RAWDEVICE.
        !            67: *       7-May-1998     Don Brady               Added check for NULL vp to hfs_metafilelocking (radar #2233832).
        !            68: *      24-Apr-1998     Pat Dirks               Fixed AttributeBlockSize to return only length of variable attribute block.
        !            69: *      4/21/1998       Don Brady               Add SUPPORTS_MAC_ALIASES conditional (for radar #2225419).
        !            70: *      4/21/1998       Don Brady               Map cmNotEmpty errors to ENOTEMPTY (radar #2229259).
        !            71: *      4/21/1998       Don Brady               Fix up time/date conversions.
        !            72: *      4/20/1998       Don Brady               Remove course-grained hfs metadata locking.
        !            73: *      4/18/1998       Don Brady               Add VCB locking.
        !            74: *      4/17/1998       Pat Dirks               Fixed PackFileAttributeBlock to return more up-to-date EOF/PEOF info from vnode.
        !            75: *      4/15/1998       Don Brady               Add hasOverflowExtents and hfs_metafilelocking. Use ExtendBTreeFile instead
        !            76: *                                                              of SetEndOfForkProc. Set forktype for system files.
        !            77: *      4/14/1998       Deric Horn              PackCatalogInfoAttributeBlock(), and related packing routines to
        !            78: *                                                              pack attribute data given hfsCatalogInfo, without the objects vnode;
        !            79: *      4/14/1998       Scott Roberts   Add execute priviledges to all hfs objects.
        !            80: *       4/9/1998       Don Brady               Add MDB/VolumeHeader flushing to hfsUnmount;
        !            81: *       4/8/1998       Don Brady               Make sure vcbVRefNum field gets initialized (use MAKE_VREFNUM).
        !            82: *       4/6/1998       Don Brady               Removed calls to CreateVolumeCatalogCache (obsolete).
        !            83: *      4/06/1998       Scott Roberts   Added complex file support.
        !            84: *      4/02/1998       Don Brady               UpdateCatalogNode now takes parID and name as input.
        !            85: *      3/31/1998       Don Brady               Sync up with final HFSVolumes.h header file.
        !            86: *      3/31/1998       Don Brady               Check result from UFSToHFSStr to make sure hfs/hfs+ names are not greater
        !            87: *                                                              than 31 characters.
        !            88: *      3/30/1998       Don Brady               In InitMetaFileVNode set VSYSTEM bit in vnode's v_flag.
        !            89: *      3/26/1998       Don Brady               Cleaned up hfs_MountXXX routines. Removed CloseBtreeFile and OpenBTreeFile.
        !            90: *                                                              Simplified hfsUnmount (removed MacOS specific code).
        !            91: *      3/17/1998       Don Brady               AttributeBlockSize calculation did not account for the size field (4bytes).
        !            92: *                                                              PackVolCommonAttributes and PackCommonAttributeBlock for ATTR_CMN_NAME
        !            93: *                                                              were not setting up the name correctly.
        !            94: *      3/17/1998       Don Brady               Changed CreateCatalogNode interface to take kCatalogFolderNode and
        !            95: *                                                              kCatalogFileNode as type input. Also, force MountCheck to always run.
        !            96: *      12-nov-1997     Scott Roberts   Initially created file.
        !            97: *      17-Mar-98       ser                             Broke out and created CopyCatalogToHFSNode()
        !            98: *
        !            99: */
        !           100: #include <sys/param.h>
        !           101: #include <sys/systm.h>
        !           102: #include <sys/kernel.h>
        !           103: #include <sys/malloc.h>
        !           104: #include <sys/fcntl.h>
        !           105: #include <sys/uio.h>
        !           106: #include <sys/stat.h>
        !           107: #include <sys/attr.h>
        !           108: #include <sys/mount.h>
        !           109: #include <libkern/libkern.h>
        !           110: #include <mach/machine/simple_lock.h>
        !           111: #include <mach/vm_param.h>
        !           112: #include <kern/mapfs.h>
        !           113: 
        !           114: #include "hfs.h"
        !           115: #include "hfs_dbg.h"
        !           116: 
        !           117: #include "hfscommon/headers/system/MacOSTypes.h"
        !           118: #include "hfscommon/headers/system/MacOSStubs.h"
        !           119: #include "hfscommon/headers/FileMgrInternal.h"
        !           120: #include "hfscommon/headers/BTreesPrivate.h"
        !           121: #include "hfscommon/headers/system/HFSUnicodeWrappers.h"
        !           122: 
        !           123: #define                SUPPORTS_MAC_ALIASES    0
        !           124: #define                kMaxSecsForFsync        5
        !           125: 
        !           126: #define BYPASSBLOCKINGOPTIMIZATION 0
        !           127: 
        !           128: extern int (**hfs_vnodeop_p)();
        !           129: extern int count_lock_queue __P((void));
        !           130: 
        !           131: 
        !           132: OSErr  ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb );
        !           133: Boolean        IsARamDiskDriver( void );
        !           134: UInt16 DivUp( UInt32 byteRun, UInt32 blockSize );
        !           135: 
        !           136: extern struct tm *localtime __P((const time_t *));
        !           137: extern time_t mktime __P((struct tm *));
        !           138: 
        !           139: int memcmp __P((const void *,const void *, size_t));
        !           140: 
        !           141: extern UInt16 CountRootFiles(ExtendedVCB *vcb);
        !           142: extern OSErr GetVolumeNameFromCatalog(ExtendedVCB *vcb);
        !           143: 
        !           144: static int InitMetaFileVNode(struct vnode *vp, u_long eof, u_long clumpSize, void *extents,
        !           145:                                                         HFSCatalogNodeID fileID, void * keyCompareProc);
        !           146: 
        !           147: static void ReleaseMetaFileVNode(struct vnode *vp);
        !           148: 
        !           149: 
        !           150: //*******************************************************************************
        !           151: //     Routine:        hfs_MountHFSVolume
        !           152: //
        !           153: //
        !           154: //*******************************************************************************
        !           155: 
        !           156: OSErr  hfs_MountHFSVolume( register struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, struct proc *p)
        !           157: {
        !           158:     ExtendedVCB                        *vcb = HFSTOVCB(hfsmp);
        !           159:     struct vnode                       *tmpvnode;
        !           160:     OSErr                                      err;
        !           161:     DBG_FUNC_NAME("hfs_MountHFSVolume");
        !           162:     DBG_PRINT_FUNC_NAME();
        !           163: 
        !           164:     if (hfsmp == nil || mdb == nil)                            /* exit if bad paramater */
        !           165:                return (EINVAL);
        !           166: 
        !           167:     err = ValidMasterDirectoryBlock( mdb );            /* make sure this is an HFS disk */
        !           168:     if (err)
        !           169:        return MacToVFSError(err);
        !           170: 
        !           171:     /*
        !           172:      * The MDB seems OK: transfer info from it into VCB
        !           173:         * Note - the VCB starts out clear (all zeros)
        !           174:         *
        !           175:         * vcbSigWord is the start of duplicate mdb/vcb info.
        !           176:      * copy all fields in mdb till the drVN field
        !           177:         */
        !           178: 
        !           179:        DBG_ASSERT((hfsmp->hfs_raw_dev & 0xFFFF0000) == 0);
        !           180:        vcb->vcbVRefNum = MAKE_VREFNUM(hfsmp->hfs_raw_dev);
        !           181:     bcopy( mdb, &(vcb->vcbSigWord),  (Size)(&(mdb->drVN)) - (Size)mdb );
        !           182: 
        !           183:        /*
        !           184:      * Copy the drVN field, which is a Pascal String to the vcb, which is a cstring
        !           185:         */
        !           186: 
        !           187:     bcopy( &mdb->drVN[1], vcb->vcbVN,  mdb->drVN[0]);
        !           188:     vcb->vcbVN[mdb->drVN[0]] = '\0';
        !           189: 
        !           190: 
        !           191:     // Initialize our dirID/nodePtr cache associated with this volume.
        !           192:     err = InitMRUCache( sizeof(UInt32), kDefaultNumMRUCacheBlocks, &(vcb->hintCachePtr) );
        !           193:     ReturnIfError( err );
        !           194: 
        !           195:        /*
        !           196:         * Some fields like vcbNmAlBlks, vcbAlBlkSiz, and vcbFreeBks are just
        !           197:         * around for API compatability and the HFS/HFS Plus code uses new
        !           198:         * ExtendedVCB fields.
        !           199:         * note:  vcbNmAlBlks * vcbAlBlkSiz still gives correct volume size
        !           200:         */
        !           201:     vcb->totalBlocks   =       vcb->vcbNmAlBlks;
        !           202:     vcb->freeBlocks            =       vcb->vcbFreeBks;
        !           203:     vcb->blockSize             =       vcb->vcbAlBlkSiz;
        !           204: 
        !           205:     hfsmp->hfs_log_block_size = BestBlockSizeFit(vcb->blockSize, MAXBSIZE, hfsmp->hfs_phys_block_size);
        !           206: 
        !           207:     // XXX PPD: Should check here for hardware lock flag and set flags in VCB/MP appropriately
        !           208:     if ( IsARamDiskDriver() )
        !           209:       {
        !           210:         vcb->vcbAtrb |= kHFSVolumeNoCacheRequiredMask;         //      yes:�mark VCB as a RAM Disk
        !           211:       }
        !           212: 
        !           213:     //--       copy all fields in mdb between drXTFlSize & drVolBkUp
        !           214:     bcopy( &(mdb->drVolBkUp), &(vcb->vcbVolBkUp), (Size)&(mdb->drXTFlSize) - (Size)&(mdb->drVolBkUp) ); //     66 bytes
        !           215: 
        !           216:     vcb->vcbXTAlBlks   = DivUp( mdb->drXTFlSize, vcb->blockSize );     //      Pick up PEOF of extent B*-Tree
        !           217:     vcb->vcbCTAlBlks   = DivUp( mdb->drCTFlSize, vcb->blockSize );     //      Pick up PEOF of catalog B*-Tree
        !           218:     vcb->nextAllocation        = mdb->drAllocPtr;
        !           219:     vcb->vcbAllocPtr   = 0;                            //      Restart the roving allocation ptr
        !           220:     vcb->vcbWrCnt++;                                   //      Compensate for write of MDB on last flush
        !           221: 
        !           222:        VCB_LOCK_INIT(vcb);
        !           223: 
        !           224:        /*
        !           225:         * Set up Extents B-tree vnode...
        !           226:         */ 
        !           227:        err = GetInitializedVNode(hfsmp, &tmpvnode);
        !           228:        if (err) goto MtVolErr;
        !           229:        err = InitMetaFileVNode(tmpvnode, mdb->drXTFlSize, vcb->vcbXTClpSiz, &mdb->drXTExtRec,
        !           230:                                                        kHFSExtentsFileID, CompareExtentKeys);
        !           231:     if (err) goto MtVolErr;
        !           232: 
        !           233:        /*
        !           234:         * Set up Catalog B-tree vnode...
        !           235:         */ 
        !           236:        err = GetInitializedVNode(hfsmp, &tmpvnode);
        !           237:        if (err) goto MtVolErr;
        !           238:        err = InitMetaFileVNode(tmpvnode, mdb->drCTFlSize, vcb->vcbCTClpSiz, &mdb->drCTExtRec,
        !           239:                                                        kHFSCatalogFileID, CompareCatalogKeys);
        !           240:        if (err) goto MtVolErr;
        !           241: 
        !           242:     if ( !(vcb->vcbAtrb & (short)kHFSVolumeUnmountedMask) )
        !           243:       {
        !           244:         UInt32  consistencyStatus;
        !           245: 
        !           246:         vcb->vcbAtrb &=        ~kHFSVolumeUnmountedMask;                                       //      From now until _Unmount (clear the bit)
        !           247:                DBG_VFS(("hfs_MountHFSVolume: calling MountCheck...\n"));
        !           248:         err = MountCheck(vcb, &consistencyStatus);
        !           249:                DBG_VFS(("hfs_MountHFSVolume: MountCheck returned %d and %08lx\n",err, consistencyStatus));
        !           250:         if ( err )     goto MtChkErr;
        !           251:       }
        !           252:     else
        !           253:       {
        !           254:         vcb->vcbAtrb &=        ~kHFSVolumeUnmountedMask;                                       //      From now until _Unmount (clear the bit)
        !           255:       }
        !           256: 
        !           257:        /*
        !           258:         * all done with b-trees so we can unlock now...
        !           259:         */
        !           260:     VOP_UNLOCK(vcb->catalogRefNum, 0, p);
        !           261:     VOP_UNLOCK(vcb->extentsRefNum, 0, p);
        !           262: 
        !           263:     err = noErr;
        !           264: 
        !           265:     if ( err == noErr )
        !           266:       {
        !           267:         if ( !(vcb->vcbAtrb & kHFSVolumeHardwareLockMask) )            //      if the disk is not write protected
        !           268:           {
        !           269:             MarkVCBDirty( vcb );                                                               //      mark VCB dirty so it will be written
        !           270:           }
        !           271:       }
        !           272:     goto       CmdDone;
        !           273: 
        !           274: 
        !           275: MtChkErr:;
        !           276:     InvalidateCatalogCache( vcb );
        !           277: 
        !           278:        err = EBADF;
        !           279: 
        !           280:     //--       Release any resources allocated so far before exiting with an error:
        !           281: MtVolErr:;
        !           282:        ReleaseMetaFileVNode(vcb->catalogRefNum);
        !           283:        ReleaseMetaFileVNode(vcb->extentsRefNum);
        !           284: 
        !           285: CmdDone:;
        !           286:     return( err );
        !           287: 
        !           288: }
        !           289: 
        !           290: //*******************************************************************************
        !           291: //     Routine:        hfs_MountHFSPlusVolume
        !           292: //
        !           293: //
        !           294: //*******************************************************************************
        !           295: 
        !           296: OSErr hfs_MountHFSPlusVolume( register struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, u_long embBlkOffset, struct proc *p)
        !           297: {
        !           298:     register ExtendedVCB       *vcb;
        !           299:     HFSPlusForkData                    *fdp;
        !           300:     struct vnode                       *tmpvnode;
        !           301:     OSErr                                      retval;
        !           302: 
        !           303:     if (hfsmp == nil || vhp == nil)            /*      exit if bad paramater */
        !           304:                return (EINVAL);
        !           305: 
        !           306:        DBG_VFS(("hfs_MountHFSPlusVolume: signature=0x%x, version=%d, blockSize=%ld\n", vhp->signature, vhp->version, vhp->blockSize));
        !           307: 
        !           308:     retval = ValidVolumeHeader(vhp);   /*      make sure this is an HFS Plus disk */
        !           309:     if (retval)
        !           310:        return MacToVFSError(retval);
        !           311:     
        !           312:     /*
        !           313:      * The VolumeHeader seems OK: transfer info from it into VCB
        !           314:         * Note - the VCB starts out clear (all zeros)
        !           315:         */
        !           316:        vcb = HFSTOVCB(hfsmp);
        !           317: 
        !           318:        DBG_ASSERT((hfsmp->hfs_raw_dev & 0xFFFF0000) == 0);
        !           319:        vcb->vcbVRefNum         =       MAKE_VREFNUM(hfsmp->hfs_raw_dev);
        !           320:        vcb->vcbSigWord         =       vhp->signature;
        !           321:        vcb->vcbCrDate          =       vhp->createDate;                                // NOTE: local time, not GMT!
        !           322:        vcb->vcbLsMod           =       UTCToLocal(vhp->modifyDate);
        !           323:        vcb->vcbAtrb            =       (UInt16) vhp->attributes;               // VCB only uses lower 16 bits
        !           324:        vcb->vcbClpSiz          =       vhp->rsrcClumpSize;
        !           325:        vcb->vcbNxtCNID         =       vhp->nextCatalogID;
        !           326:        vcb->vcbVolBkUp         =       UTCToLocal(vhp->backupDate);
        !           327:        vcb->vcbWrCnt           =       vhp->writeCount;
        !           328:        vcb->vcbXTClpSiz        =       vhp->extentsFile.clumpSize;
        !           329:        vcb->vcbCTClpSiz        =       vhp->catalogFile.clumpSize;
        !           330:        vcb->vcbFilCnt          =       vhp->fileCount;
        !           331:        vcb->vcbDirCnt          =       vhp->folderCount;
        !           332:        
        !           333:        /* copy 32 bytes of Finder info */
        !           334:        bcopy(vhp->finderInfo, vcb->vcbFndrInfo, sizeof(vhp->finderInfo));    
        !           335: 
        !           336:        /*
        !           337:         *      vcbFreeBks is the number of free bytes divided by the (HFS compatible) allocation block size.  Since the
        !           338:         *      number of free bytes could overflow a UInt32, we actually divide both free bytes and allocation block size by
        !           339:         *      512 before doing the division.  This prevents intermediate values from overflowing until the volume size is
        !           340:         *      2 TB.  It's OK to divide by 512 since HFS Plus requires allocation blocks to be a multiple of 512.
        !           341:         */
        !           342:        HFSBlocksFromTotalSectors( (vhp->blockSize / 512) * vhp->totalBlocks, &vcb->vcbAlBlkSiz, &vcb->vcbNmAlBlks );
        !           343: 
        !           344:        vcb->vcbFreeBks = (vhp->freeBlocks * (vhp->blockSize / 512)) / (vcb->vcbAlBlkSiz / 512);
        !           345:        vcb->vcbAlBlSt = 0;             /* hfs+ allocation blocks start at first block of volume */
        !           346:        vcb->vcbWrCnt++;                /* compensate for write of Volume Header on last flush */
        !           347: 
        !           348:        VCB_LOCK_INIT(vcb);
        !           349: 
        !           350:        /*      Now fill in the Extended VCB info */
        !           351:        vcb->nextAllocation                     =       vhp->nextAllocation;
        !           352:        vcb->totalBlocks                        =       vhp->totalBlocks;
        !           353:        vcb->freeBlocks                         =       vhp->freeBlocks;
        !           354:        vcb->blockSize                          =       vhp->blockSize;
        !           355:        vcb->allocationsClumpSize       =       vhp->allocationFile.clumpSize;
        !           356:        vcb->attributesClumpSize        =       vhp->attributesFile.clumpSize;
        !           357:        vcb->checkedDate                        =       vhp->checkedDate;
        !           358:        vcb->encodingsBitmap            =       vhp->encodingsBitmap;
        !           359:        
        !           360:        vcb->vcbAlBlSt                          =       embBlkOffset;
        !           361:        vcb->hfsPlusIOPosOffset         =       embBlkOffset * 512;
        !           362: 
        !           363:     /* Update the logical block size in the mount struct (currently set up from the wrapper MDB)
        !           364:        using the new blocksize value: */
        !           365:     hfsmp->hfs_log_block_size = BestBlockSizeFit(vcb->blockSize, MAXBSIZE, hfsmp->hfs_phys_block_size);
        !           366: 
        !           367:     // XXX PPD: Should check here for hardware lock flag and set flags in VCB/MP appropriately
        !           368:     // vcb->vcbAtrb |= kVolumeHardwareLockMask;        // XXX this line for debugging only!!!!
        !           369: 
        !           370:     if ( IsARamDiskDriver() )
        !           371:                vcb->vcbAtrb |= kHFSVolumeNoCacheRequiredMask;          //      yes:�mark VCB as a RAM Disk
        !           372: 
        !           373:     // Initialize our dirID/nodePtr cache associated with this volume.
        !           374:     retval = InitMRUCache( sizeof(UInt32), kDefaultNumMRUCacheBlocks, &(vcb->hintCachePtr) );
        !           375:     if (retval != noErr) goto ErrorExit;
        !           376: 
        !           377:        /*
        !           378:         * Set up Extents B-tree vnode...
        !           379:         */ 
        !           380:        retval = GetInitializedVNode(hfsmp, &tmpvnode);
        !           381:        if (retval) goto ErrorExit;
        !           382:        fdp = &vhp->extentsFile;
        !           383:        retval = InitMetaFileVNode(tmpvnode, fdp->logicalSize.lo, fdp->clumpSize, &fdp->extents,
        !           384:                                                                kHFSExtentsFileID, CompareExtentKeysPlus);
        !           385:     if (retval) goto ErrorExit;
        !           386: 
        !           387:        /*
        !           388:         * Set up Catalog B-tree vnode...
        !           389:         */ 
        !           390:        retval = GetInitializedVNode(hfsmp, &tmpvnode);
        !           391:        if (retval) goto ErrorExit;
        !           392:        fdp = &vhp->catalogFile;
        !           393:        retval = InitMetaFileVNode(tmpvnode, fdp->logicalSize.lo, fdp->clumpSize, &fdp->extents,
        !           394:                                                                kHFSCatalogFileID, CompareExtendedCatalogKeys);
        !           395:        if (retval) goto ErrorExit;
        !           396: 
        !           397:        /*
        !           398:         * Set up Allocation file vnode...
        !           399:         */  
        !           400:        retval = GetInitializedVNode(hfsmp, &tmpvnode);
        !           401:        if (retval) goto ErrorExit;
        !           402:     VTOH(tmpvnode)->h_meta->h_logBlockSize = kHFSBlockSize;            /* XXX does Allocation use GetBlock? */
        !           403:     VTOH(tmpvnode)->h_meta->h_physBlkPerLogBlk = 1;
        !           404:        fdp = &vhp->allocationFile;
        !           405:        retval = InitMetaFileVNode(tmpvnode, fdp->logicalSize.lo, fdp->clumpSize, &fdp->extents,
        !           406:                                                                kHFSAllocationFileID, NULL);
        !           407:        if (retval) goto ErrorExit;
        !           408:  
        !           409:        /*
        !           410:         * Set up Attribute B-tree vnode (optional)...
        !           411:         */
        !           412:        if (vhp->attributesFile.logicalSize.lo > 0) {
        !           413:                retval = GetInitializedVNode(hfsmp, &tmpvnode);
        !           414:                if (retval) goto ErrorExit;
        !           415:                fdp = &vhp->attributesFile;
        !           416:                retval = InitMetaFileVNode(tmpvnode, fdp->logicalSize.lo, fdp->clumpSize, &fdp->extents,
        !           417:                                                                        kHFSAttributesFileID, CompareAttributeKeys);
        !           418:                if (retval) goto ErrorExit;
        !           419:        }
        !           420: 
        !           421:        /*
        !           422:         * Now that Catalog file is open...
        !           423:         *    get the root file count
        !           424:         *    get the volume name from the catalog
        !           425:         */
        !           426:        vcb->vcbNmFls = CountRootFiles(vcb);    /* set up root file count */
        !           427:        DBG_VFS(("hfs_MountHFSPlusVolume: root file count was %d\n", vcb->vcbNmFls));
        !           428: 
        !           429:        retval = MacToVFSError( GetVolumeNameFromCatalog(vcb) );        
        !           430:     if (retval != noErr) goto ErrorExit;
        !           431: 
        !           432:        /*
        !           433:         * if volume was not cleanly unmounted then do a consistency check
        !           434:         */
        !           435:     if ( !(vcb->vcbAtrb & (short)kHFSVolumeUnmountedMask) )
        !           436:        {
        !           437:                UInt32  consistencyStatus;
        !           438: 
        !           439:         vcb->vcbAtrb &=        ~kHFSVolumeUnmountedMask;                       //      From now until _Unmount (clear the bit)
        !           440:                DBG_VFS(("hfs_MountHFSPlusVolume: calling MountCheck...\n"));
        !           441:                retval = MacToVFSError( MountCheck(vcb, &consistencyStatus) );
        !           442:                DBG_VFS(("hfs_MountHFSPlusVolume: MountCheck returned %d and %08lx\n",retval, consistencyStatus));
        !           443:                if (retval) goto ErrorExit;
        !           444:        }
        !           445:     else
        !           446:        {
        !           447:         vcb->vcbAtrb &=        ~kHFSVolumeUnmountedMask;                       //      From now until _Unmount (clear the bit)
        !           448:        }
        !           449: 
        !           450:        /*
        !           451:         * all done with metadata files so we can unlock now...
        !           452:         */
        !           453:        if (vcb->attributesRefNum != NULL)
        !           454:        VOP_UNLOCK(vcb->attributesRefNum, 0, p);
        !           455:     VOP_UNLOCK(vcb->allocationsRefNum, 0, p);
        !           456:     VOP_UNLOCK(vcb->catalogRefNum, 0, p);
        !           457:     VOP_UNLOCK(vcb->extentsRefNum, 0, p);
        !           458: 
        !           459:        if ( !(vcb->vcbAtrb & kHFSVolumeHardwareLockMask) )             //      if the disk is not write protected
        !           460:        {
        !           461:                MarkVCBDirty( vcb );                                                            //      mark VCB dirty so it will be written
        !           462:        }
        !           463:        
        !           464:        DBG_VFS(("hfs_MountHFSPlusVolume: returning (%d)\n", retval));
        !           465: 
        !           466:        return (0);
        !           467: 
        !           468: 
        !           469: ErrorExit:
        !           470:        /*
        !           471:         * A fatal error occured and the volume cannot be mounted
        !           472:         * release any resources that we aquired...
        !           473:         */
        !           474: 
        !           475:        DBG_VFS(("hfs_MountHFSPlusVolume: fatal error (%d)\n", retval));
        !           476: 
        !           477:     InvalidateCatalogCache(vcb);
        !           478:     
        !           479:        ReleaseMetaFileVNode(vcb->allocationsRefNum);
        !           480:        ReleaseMetaFileVNode(vcb->attributesRefNum);
        !           481:        ReleaseMetaFileVNode(vcb->catalogRefNum);
        !           482:        ReleaseMetaFileVNode(vcb->extentsRefNum);
        !           483: 
        !           484:        return (retval);
        !           485: }
        !           486: 
        !           487: 
        !           488: /*
        !           489:  * ReleaseMetaFileVNode
        !           490:  *
        !           491:  * vp  L - -
        !           492:  */
        !           493: static void ReleaseMetaFileVNode(struct vnode *vp)
        !           494: {
        !           495:        if (vp)
        !           496:        {
        !           497:                FCB *fcb = VTOFCB(vp);
        !           498: 
        !           499:                if (fcb->fcbBTCBPtr != NULL)
        !           500:                        (void) BTClosePath(fcb);        /* ignore errors since there is only one path open */
        !           501: 
        !           502:                /* release the node even if BTClosePath fails */
        !           503:                if (VOP_ISLOCKED(vp))
        !           504:                        VPUT(vp);
        !           505:                else
        !           506:                        VRELE(vp);
        !           507:        }
        !           508: }
        !           509: 
        !           510: 
        !           511: /*
        !           512:  * InitMetaFileVNode
        !           513:  *
        !           514:  * vp  U L L
        !           515:  */
        !           516: static int InitMetaFileVNode(struct vnode *vp, u_long eof, u_long clumpSize, void *extents,
        !           517:                                                         HFSCatalogNodeID fileID, void * keyCompareProc)
        !           518: {
        !           519:        FCB                             *fcb;
        !           520:        ExtendedVCB             *vcb;
        !           521:        int                             result = 0;
        !           522: 
        !           523:        DBG_ASSERT(vp != NULL);
        !           524:     DBG_ASSERT(vp->v_data != NULL);
        !           525:     DBG_ASSERT(VTOH(vp)->h_xfcb->fcb_vp == vp);
        !           526: 
        !           527:        vcb = VTOVCB(vp);
        !           528:        fcb = VTOFCB(vp);
        !           529: 
        !           530:        switch (fileID)
        !           531:        {
        !           532:                case kHFSExtentsFileID:
        !           533:                        vcb->extentsRefNum = vp;
        !           534:                        break;
        !           535: 
        !           536:                case kHFSCatalogFileID:
        !           537:                        vcb->catalogRefNum = vp;
        !           538:                        break;
        !           539: 
        !           540:                case kHFSAttributesFileID:
        !           541:                        vcb->attributesRefNum = vp;
        !           542:                        break;
        !           543: 
        !           544:                case kHFSAllocationFileID:
        !           545:                        vcb->allocationsRefNum = vp;
        !           546:             VTOH(vp)->h_meta->h_logBlockSize = kHFSBlockSize;
        !           547:             VTOH(vp)->h_meta->h_physBlkPerLogBlk = 1;
        !           548:                        break;
        !           549: 
        !           550:                default:
        !           551:                        panic("InitMetaFileVNode: invalid fileID!");
        !           552:        }
        !           553: 
        !           554:        fcb->fcbVPtr = vcb;
        !           555:        fcb->fcbEOF = eof;
        !           556:        fcb->fcbPLen = eof;
        !           557:        fcb->fcbClmpSize = clumpSize;
        !           558:        fcb->fcbFlNm = fileID;
        !           559:     H_FILEID(VTOH(vp)) = fileID;
        !           560:     H_FORKTYPE(VTOH(vp)) = kSysFile;
        !           561: 
        !           562:        if (vcb->vcbSigWord == kHFSPlusSigWord) {
        !           563:        ExtendedFCB             *xfcb;
        !           564: 
        !           565:                xfcb = &(((struct vfsFCB *)(fcb))->fcb_extFCB);         //XXX use a macro instead?!
        !           566:                bcopy(extents, xfcb->extents, sizeof(HFSPlusExtentRecord));
        !           567:        }
        !           568:        else {
        !           569:        bcopy(extents, fcb->fcbExtRec, sizeof(HFSExtentRecord));
        !           570:        }
        !           571: 
        !           572:     /*
        !           573:      * Lock the hfsnode and insert the hfsnode into the hash queue:
        !           574:      */
        !           575:     hfs_vhashins(VTOH(vp));
        !           576:        vp->v_flag |= VSYSTEM;  /* tag our metadata files (used by vflush call) */
        !           577:     
        !           578:     if (keyCompareProc != NULL) {
        !           579:                result = BTOpenPath(fcb,
        !           580:                                                        (KeyCompareProcPtr) keyCompareProc,
        !           581:                                                        GetBTreeBlock,
        !           582:                                                        ReleaseBTreeBlock,
        !           583:                                                        ExtendBTreeFile,
        !           584:                                                        SetBTreeBlockSize);
        !           585:                result = MacToVFSError(result);
        !           586:        }
        !           587: 
        !           588:     return (result);
        !           589: }
        !           590: 
        !           591: 
        !           592: /*************************************************************
        !           593: *
        !           594: * Unmounts a hfs volume.
        !           595: *      At this point vflush() has been called (to dump all non-metadata files)
        !           596: *
        !           597: *************************************************************/
        !           598: 
        !           599: short hfsUnmount( register struct hfsmount *hfsmp, struct proc *p)
        !           600: {
        !           601:     ExtendedVCB        *vcb = HFSTOVCB(hfsmp);
        !           602:     int                        retval = E_NONE;
        !           603: 
        !           604:        (void) DisposeMRUCache(vcb->hintCachePtr);
        !           605:        InvalidateCatalogCache( vcb );
        !           606:        // XXX PPD: Should dispose of any allocated volume cache here: call DisposeVolumeCacheBlocks( vcb )?
        !           607: 
        !           608:        (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_EXCLUSIVE, p);
        !           609:        (void) hfs_metafilelocking(hfsmp, kHFSExtentsFileID, LK_EXCLUSIVE, p);
        !           610: 
        !           611:        if (vcb->vcbSigWord == kHFSPlusSigWord) {
        !           612:                (void) hfs_metafilelocking(hfsmp, kHFSAttributesFileID, LK_EXCLUSIVE, p);
        !           613: 
        !           614:                ReleaseMetaFileVNode(vcb->allocationsRefNum);
        !           615:                ReleaseMetaFileVNode(vcb->attributesRefNum);
        !           616:        }
        !           617: 
        !           618:        ReleaseMetaFileVNode(vcb->catalogRefNum);
        !           619:        ReleaseMetaFileVNode(vcb->extentsRefNum);
        !           620: 
        !           621:        return (retval);
        !           622: }
        !           623: 
        !           624: 
        !           625: /*
        !           626:  * Performs a lookup on the given dirID, name. Returns the catalog info
        !           627:  */
        !           628: /* XXX SER catInfo points to a hint, why do we need to pass one in ? */
        !           629: 
        !           630: short hfsLookup (ExtendedVCB *vcb, UInt32 parentDirID, char *name, short len, UInt32 hint, hfsCatalogInfo *catInfo)
        !           631: {
        !           632:        char tmpname[NAME_MAX + 1]; /* UUU */
        !           633:        OSErr result;
        !           634:        
        !           635:        if (len != -1 ) {
        !           636:                bcopy(name, tmpname, len);
        !           637:                tmpname[len] = '\0';
        !           638:         result = GetCatalogNode(vcb, parentDirID, tmpname, hint, &catInfo->spec, &catInfo->nodeData, &catInfo->hint);
        !           639:        } else
        !           640:         result = GetCatalogNode(vcb, parentDirID, name, hint, &catInfo->spec, &catInfo->nodeData, &catInfo->hint);
        !           641: 
        !           642:        if (result)
        !           643:         DBG_ERR(("on Lookup, GetCatalogNode returned: %d: dirid: %ld name: %s\n", result, parentDirID, name));
        !           644: 
        !           645:        return MacToVFSError(result);
        !           646: }
        !           647: 
        !           648: 
        !           649: 
        !           650: short hfsDelete (ExtendedVCB *vcb, UInt32 parentDirID, StringPtr name, short isfile, UInt32 catalogHint)
        !           651: {
        !           652:     OSErr result = noErr;
        !           653:     
        !           654:     /* XXX have all the file's blocks been flushed/trashed? */
        !           655: 
        !           656:        /*
        !           657:         * DeleteFile will delete the catalog node and then
        !           658:         * free up any disk space used by the file.
        !           659:         */
        !           660:        if (isfile)
        !           661:                result = DeleteFile(vcb, parentDirID, name, catalogHint);
        !           662:        else /* is a directory */
        !           663:                result = DeleteCatalogNode(vcb, parentDirID, name, catalogHint);
        !           664: 
        !           665:     if (result)
        !           666:         DBG_ERR(("on Delete, DeleteFile returned: %d: dirid: %ld name: %s\n", result, parentDirID, name));
        !           667:                
        !           668:        return MacToVFSError(result);
        !           669: }
        !           670: 
        !           671: 
        !           672: short hfsMoveRename (ExtendedVCB *vcb, UInt32 oldDirID, char *oldName, UInt32 newDirID, char *newName, UInt32 *hint)
        !           673: {
        !           674:     OSErr result = noErr;
        !           675: 
        !           676:     result = MoveRenameCatalogNode(vcb, oldDirID,oldName, *hint, newDirID, newName, hint);
        !           677: 
        !           678:     if (result)
        !           679:         DBG_ERR(("on hfsMoveRename, MoveRenameCatalogNode returned: %d: newdirid: %ld newname: %s\n", result, newDirID, newName));
        !           680:         
        !           681: 
        !           682:     return MacToVFSError(result);
        !           683: }
        !           684: 
        !           685: /* XXX SER pass back the hint so other people can use it */
        !           686: 
        !           687: 
        !           688: short hfsCreate(ExtendedVCB *vcb, UInt32 dirID, char *name, int        mode)
        !           689: {
        !           690:     OSErr                              result = noErr;
        !           691:     HFSCatalogNodeID   catalogNodeID;
        !           692:     UInt32                             catalogHint;
        !           693:     UInt32                             type;
        !           694: 
        !           695:        /* just test for directories, the default is to create a file (like symlinks) */
        !           696:        if ((mode & IFMT) == IFDIR)
        !           697:                type = kCatalogFolderNode;
        !           698:        else
        !           699:                type = kCatalogFileNode;
        !           700: 
        !           701:     result = CreateCatalogNode (vcb, dirID, name, type, &catalogNodeID, &catalogHint);
        !           702:  
        !           703:     return MacToVFSError(result);
        !           704: }
        !           705: 
        !           706: 
        !           707: short hfsCreateFileID (ExtendedVCB *vcb, UInt32 parentDirID, StringPtr name, UInt32 catalogHint, UInt32 *fileIDPtr)
        !           708: {
        !           709:     return MacToVFSError(CreateFileIDRef(vcb, parentDirID, name, catalogHint, fileIDPtr));
        !           710: }
        !           711: 
        !           712: 
        !           713: /************************************************************************/
        !           714: /*     hfsGet - Returns a vnode derived from hfs                                                       */
        !           715: /*                                                                                                                                             */
        !           716: /************************************************************************/
        !           717: 
        !           718: short hfsGet( ExtendedVCB *vcb, hfsCatalogInfo *catInfo, UInt8 forkType, struct vnode *dvp, struct vnode **vpp)
        !           719: {
        !           720:     struct hfsnode             *hp;
        !           721:     struct vnode               *vp;
        !           722:     struct vnode               *cp;
        !           723:     struct hfsmount    *hfsmp;
        !           724:     struct hfsfilemeta *fm;
        !           725:     struct mount               *mp;
        !           726:     struct vfsFCB              *xfcb;
        !           727:     dev_t                              dev;
        !           728:     int                                        retval;
        !           729: 
        !           730:     DBG_ASSERT(vcb != NULL);
        !           731:     DBG_ASSERT(catInfo != NULL);
        !           732:     DBG_ASSERT(vpp != NULL);
        !           733: 
        !           734:     hfsmp      = VCBTOHFS(vcb);
        !           735:     mp                 = HFSTOVFS(hfsmp);
        !           736:     dev        = hfsmp->hfs_raw_dev;
        !           737: 
        !           738:     DBG_UTILS(("\thfsGet: On '%s' with forktype of %d, nodeType of 0x%08lX\n", catInfo->spec.name, forkType, (unsigned long)catInfo->nodeData.nodeType));
        !           739: 
        !           740:     /* Must malloc() here, since getnewvnode() can sleep */
        !           741:     MALLOC(hp, struct hfsnode *, sizeof(struct hfsnode), M_HFSNODE, M_WAITOK);
        !           742:     bzero((caddr_t)hp, sizeof(struct hfsnode));
        !           743:     lockinit(&hp->h_lock, PINOD, "hfsnode", 0, 0);
        !           744: 
        !           745:     /* getnewvnode() does a VREF() on the vnode */
        !           746:     /* Allocate a new vnode. */
        !           747:     if ((retval = getnewvnode(VT_HFS, mp, hfs_vnodeop_p, &vp))) {
        !           748:         *vpp = NULL;
        !           749:         goto Err_Exit;
        !           750:     }
        !           751: 
        !           752:     hp->h_vp = vp;                                                                     /* Make HFSTOV work */
        !           753:     hp->h_dev = hfsmp->hfs_raw_dev;
        !           754:     vp->v_data = hp;                                                           /* Make VTOH work */
        !           755:     H_FILEID(hp) = catInfo->nodeData.nodeID;
        !           756:     H_FORKTYPE(hp) = forkType;
        !           757: 
        !           758:     /*
        !           759:      * Lock the hfsnode and insert the hfsnode into the hash queue:
        !           760:      * NOTE: THIS IS DANGEROUS IN CASES WHERE WE NEED TO BACK OUT OF THE CREATION?
        !           761:      */
        !           762:     hfs_vhashins(hp);
        !           763:     hp->h_valid = HFS_VNODE_MAGIC;
        !           764: 
        !           765:     /*
        !           766:      * Allocate and init the right data structs:
        !           767:      */
        !           768:     xfcb = NULL;
        !           769:     if (catInfo->nodeData.nodeType == kCatalogFolderNode)
        !           770:       {
        !           771:         /* Just allocate the data */
        !           772:         MALLOC(fm, struct hfsfilemeta *, sizeof(struct hfsfilemeta), M_HFSNODE, M_WAITOK);
        !           773:         bzero(fm, sizeof(struct hfsfilemeta));
        !           774:         MALLOC(xfcb, struct vfsFCB *, sizeof(struct vfsFCB), M_HFSNODE, M_WAITOK);
        !           775:         bzero(xfcb, sizeof(struct vfsFCB));
        !           776:         fm->h_logBlockSize = hfsmp->hfs_log_block_size;
        !           777:         fm->h_physBlkPerLogBlk =  fm->h_logBlockSize/kHFSBlockSize;
        !           778:       }
        !           779:     else
        !           780:       {
        !           781:         if (forkType==kDirCmplx)
        !           782:           {
        !           783:             /* Just allocate the meta part */
        !           784:             MALLOC(fm, struct hfsfilemeta *, sizeof(struct hfsfilemeta), M_HFSNODE, M_WAITOK);
        !           785:             bzero(fm, sizeof(struct hfsfilemeta));
        !           786:             lockinit(&fm->h_fmetalock, PINOD, "hfsfilemeta", 0, 0);
        !           787:             fm->h_logBlockSize = hfsmp->hfs_log_block_size;
        !           788:             fm->h_physBlkPerLogBlk =  fm->h_logBlockSize/kHFSBlockSize;
        !           789:           }
        !           790:         else
        !           791:           {
        !           792:             Boolean    unlockPar = false;
        !           793:                        
        !           794:                        /* Get the complex vnode, creating it if none existed */
        !           795:             if (dvp->v_type == VCPLX) {
        !           796:                 cp = dvp;
        !           797:             }
        !           798:             else {
        !           799:                 cp = hfs_vhashget(hp->h_dev, H_FILEID(hp), kDirCmplx);
        !           800:                 unlockPar = TRUE;
        !           801:             }
        !           802:             
        !           803:             if (cp == NULL)
        !           804:               {
        !           805:                 if ((retval = hfsGet(vcb, catInfo, kDirCmplx, NULL, &cp)))
        !           806:                   {
        !           807:                     /* Couldn't get a complex node: back out of this vnode's creation
        !           808:                        since an hfs vnode can't stand alone: */
        !           809:                     vp->v_flag |= VSYSTEM;             /* Prevent hfs_lock et al. from going for meta lock... */
        !           810:                     VPUT(vp);
        !           811:                     goto Err_Exit;
        !           812:                   };
        !           813:                 unlockPar = TRUE;
        !           814:               }
        !           815: 
        !           816:             fm = VTOH(cp)->h_meta;
        !           817:                        DBG_ASSERT(fm);
        !           818:             /* Increment the usecount, to make sure it doesnt go away on us */
        !           819:             fm->h_usecount++;
        !           820:             lockmgr(&fm->h_fmetalock, LK_EXCLUSIVE, (struct slock *)0, CURRENT_PROC);
        !           821:             hp->h_relative = cp;
        !           822:             if (forkType == kDataFork)                                 /* Init downlink */
        !           823:                 VTOH(cp)->h_relative = vp;
        !           824:             if (fm->h_fork == NULL)
        !           825:                 fm->h_fork = vp;
        !           826:             else {
        !           827:                 hp->h_sibling = fm->h_fork;
        !           828:                 VTOH(fm->h_fork)->h_sibling = vp;
        !           829:             }
        !           830:             /* Increment the complex usecount, to make sure it doesnt go inactive on us */
        !           831:             VREF(cp);
        !           832:             if  (unlockPar)
        !           833:                 VPUT(cp);
        !           834:           }
        !           835:         MALLOC(xfcb, struct vfsFCB *, sizeof(struct vfsFCB), M_HFSNODE, M_WAITOK);
        !           836:         bzero(xfcb, sizeof(struct vfsFCB));
        !           837:       }
        !           838: 
        !           839:     hp->h_xfcb = xfcb;
        !           840:     hp->h_meta = fm;
        !           841: 
        !           842:     /*
        !           843:      * Finish filling in the record
        !           844:      */
        !           845:     if (xfcb) {
        !           846:         xfcb->fcb_vp = vp;                                     /* Make FCBTOV work */
        !           847:     }
        !           848: 
        !           849:     /*
        !           850:      * Copy the Catalog info to the new macnode
        !           851:      */
        !           852:     CopyCatalogToHFSNode(catInfo, hp);
        !           853: 
        !           854: 
        !           855:        /* Lets do some testing here */
        !           856:     DBG_ASSERT(hp->h_meta);
        !           857:     DBG_ASSERT(VTOH(vp)==hp);
        !           858:     DBG_ASSERT(HTOV(hp)==vp);
        !           859:     if (hp->h_xfcb) {
        !           860:         DBG_ASSERT(VTOH(vp)->h_xfcb->fcb_vp == vp);
        !           861:         DBG_ASSERT(FCBTOV(&hp->h_xfcb->fcb_fcb) == vp);
        !           862:         DBG_ASSERT(FCBTOH(&hp->h_xfcb->fcb_fcb) == hp);
        !           863:         DBG_ASSERT(&hp->h_xfcb->fcb_fcb == VTOFCB(vp));
        !           864:         DBG_ASSERT(&hp->h_xfcb->fcb_fcb == HTOFCB(hp));
        !           865:         DBG_ASSERT(VTOVCB(vp) == FCBTOVCB(&hp->h_xfcb->fcb_fcb));
        !           866:     }
        !           867:     if (hp->h_sibling) {
        !           868:         DBG_ASSERT(VTOH(hp->h_sibling)->h_sibling == vp);
        !           869:         DBG_ASSERT(VTOH(hp->h_sibling)->h_relative == hp->h_relative);
        !           870:         DBG_ASSERT(VTOH(hp->h_sibling)->h_meta == hp->h_meta);
        !           871:     }
        !           872:     if (H_FORKTYPE(hp) == kDirCmplx)   {
        !           873:         DBG_ASSERT(hp->h_meta->h_usecount==0);
        !           874:     }
        !           875:        else {
        !           876:         DBG_ASSERT(hp->h_meta->h_usecount>0 && hp->h_meta->h_usecount<=2);
        !           877:        }
        !           878:        
        !           879:     /*
        !           880:      * Finish inode initialization now that aliasing has been resolved.
        !           881:      */
        !           882:     hp->h_devvp = hfsmp->hfs_devvp;
        !           883:     VREF(hp->h_devvp);
        !           884:     *vpp = vp;
        !           885:     return 0;
        !           886: 
        !           887: Err_Exit:;
        !           888:     FREE (hp, M_HFSNODE);
        !           889:     *vpp = NULL;
        !           890:     return (retval);
        !           891: }
        !           892: 
        !           893: 
        !           894: int hasOverflowExtents(struct hfsnode *hp)
        !           895: {
        !           896:        ExtendedVCB             *vcb = HTOVCB(hp);
        !           897:        FCB                             *fcb = HTOFCB(hp);
        !           898:        u_long                  blocks;
        !           899: 
        !           900:        if (vcb->vcbSigWord == kHFSPlusSigWord)
        !           901:          {
        !           902:                ExtendedFCB *xfcb;
        !           903: 
        !           904:                xfcb = GetParallelFCB(HTOV(hp));
        !           905:                if (xfcb->extents[7].blockCount == 0)
        !           906:                        return false;
        !           907:                
        !           908:                blocks = xfcb->extents[0].blockCount +
        !           909:                                 xfcb->extents[1].blockCount +
        !           910:                                 xfcb->extents[2].blockCount +
        !           911:                                 xfcb->extents[3].blockCount +
        !           912:                                 xfcb->extents[4].blockCount +
        !           913:                                 xfcb->extents[5].blockCount +
        !           914:                                 xfcb->extents[6].blockCount +
        !           915:                                 xfcb->extents[7].blockCount;   
        !           916:          }
        !           917:        else
        !           918:          {
        !           919:                if (fcb->fcbExtRec[2].blockCount == 0)
        !           920:                        return false;
        !           921:                
        !           922:                blocks = fcb->fcbExtRec[0].blockCount +
        !           923:                                 fcb->fcbExtRec[1].blockCount +
        !           924:                                 fcb->fcbExtRec[2].blockCount;  
        !           925:          }
        !           926: 
        !           927:        return ((fcb->fcbPLen / vcb->blockSize) > blocks);
        !           928: }
        !           929: 
        !           930: 
        !           931: int hfs_metafilelocking(struct hfsmount *hfsmp, u_long fileID, u_int flags, struct proc *p)
        !           932: {
        !           933:        ExtendedVCB             *vcb;
        !           934:        struct vnode    *vp = NULL;
        !           935:     struct timeval tv;
        !           936:        int                             numOfLockedBuffs;
        !           937:        int     retval = 0;
        !           938: 
        !           939:        vcb = HFSTOVCB(hfsmp);
        !           940: 
        !           941:     DBG_VFS(("  hfs_metafilelocking: vol: %d, file: %ld %s%s%s\n", vcb->vcbVRefNum, fileID,
        !           942:             ((flags & LK_TYPE_MASK) == LK_RELEASE ? "RELEASE" : ""),
        !           943:             ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE ? "EXCLUSIVE" : ""),
        !           944:             ((flags & LK_TYPE_MASK) == LK_SHARED ? "SHARED" : "") ));
        !           945: 
        !           946:    /*kprintf("file: %ld flags: 0x%x %s%s%s\n",fileID, flags,
        !           947:             ((flags & LK_TYPE_MASK) == LK_RELEASE ? "RELEASE" : ""),
        !           948:             ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE ? "EXCLUSIVE" : ""),
        !           949:             ((flags & LK_TYPE_MASK) == LK_SHARED ? "SHARED" : "") );
        !           950: */
        !           951: 
        !           952:        switch (fileID)
        !           953:        {
        !           954:                case kHFSExtentsFileID:
        !           955:                        vp = vcb->extentsRefNum;
        !           956:                        break;
        !           957: 
        !           958:                case kHFSCatalogFileID:
        !           959:                        vp = vcb->catalogRefNum;
        !           960:                        break;
        !           961: 
        !           962:                case kHFSAttributesFileID:
        !           963:                        if (vcb->vcbSigWord == kHFSPlusSigWord) {
        !           964:                                vp = vcb->attributesRefNum;
        !           965:                                break;
        !           966:                        }
        !           967:                        // fall through for hfs...
        !           968: 
        !           969:                case kHFSAllocationFileID:
        !           970:                        // bitmap is covered by Extents B-tree locking
        !           971:                default:
        !           972:                        panic("hfs_lockmetafile: invalid fileID");
        !           973:        }
        !           974:     /*kprintf("\tBefore: %d\n", lockstatus(&VTOH(vp)->h_lock));
        !           975: */
        !           976:     if (vp != NULL) {
        !           977: 
        !           978:         /* Release, if necesary any locked buffer caches */
        !           979:         if (flags & LK_RELEASE) {
        !           980:             numOfLockedBuffs =  count_lock_queue();
        !           981:             tv = time;
        !           982:             if ((numOfLockedBuffs > 32) || ((numOfLockedBuffs>1) && ((tv.tv_sec - VTOH(vp)->h_lastfsync) > kMaxSecsForFsync))) {
        !           983:                // kprintf("Synching meta deta...locked buffers = %d, fsync gap = %ld\n", numOfLockedBuffs, (tv.tv_sec - VTOH(vp)->h_lastfsync));
        !           984:                 VOP_FSYNC(vp, NOCRED, MNT_NOWAIT, p);
        !           985:             };
        !           986:         };
        !           987: 
        !           988:         retval = lockmgr(&VTOH(vp)->h_lock, flags, &vp->v_interlock, p);
        !           989:     };
        !           990: 
        !           991:        return retval;
        !           992: }
        !           993: 
        !           994: 
        !           995: void CopyVNodeToCatalogNode (struct vnode *vp, struct CatalogNodeData *nodeData)
        !           996: {
        !           997:     ExtendedVCB                        *vcb;
        !           998:     FCB                                                *fcb;
        !           999:     struct hfsnode                     *hp;
        !          1000:     Boolean                                    isHFSPlus, isResource;
        !          1001:     HFSPlusExtentDescriptor    *extents, *parellextents;
        !          1002:     ExtendedFCB                                *extendedFCB;
        !          1003: 
        !          1004:     hp = VTOH(vp);
        !          1005:     vcb = HTOVCB(hp);
        !          1006:     fcb = HTOFCB(hp);
        !          1007:     isResource = (H_FORKTYPE(hp) == kRsrcFork);
        !          1008:     isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
        !          1009: 
        !          1010:     nodeData->contentModDate = to_hfs_time(hp->h_meta->h_mtime);               /* date and time of last fork modification */
        !          1011: 
        !          1012:     DBG_ASSERT(fcb->fcbFlNm == H_FILEID(hp));
        !          1013: 
        !          1014:     if (isHFSPlus) {
        !          1015:         nodeData->attributeModDate = to_hfs_time(hp->h_meta->h_ctime); /* date and time of last modification (any kind) */
        !          1016:         nodeData->accessDate = to_hfs_time(hp->h_meta->h_atime);               /* date and time of last access (Rhapsody only) */
        !          1017:         if (! (hp->h_meta->h_nodeflags & IN_UNSETACCESS)) {
        !          1018:             /* This is a tricky stuff-job: the pflags longword has two bytes of significance and they're
        !          1019:                combined with the mode field to yield a 32-bit permissions field as follows:
        !          1020: 
        !          1021:                                          +------------------------------------+
        !          1022:                    hp->h_meta->h_pflags: |XXXXXXXX|    A    |XXXXXXXX|    B   |
        !          1023:                                          +------------------------------------+
        !          1024: 
        !          1025:                                                             |
        !          1026:                                                             V
        !          1027: 
        !          1028:                                          +------------------------------------+
        !          1029:                             permissions: |    A    |    B   |      mode       |
        !          1030:                                          +------------------------------------+
        !          1031:              */
        !          1032:             nodeData->permissions.permissions = (((hp->h_meta->h_pflags << 8)  & 0xFF000000) | /* A */
        !          1033:                                                  ((hp->h_meta->h_pflags << 16) & 0x00FF0000) | /* B */
        !          1034:                                                  (hp->h_meta->h_mode           & 0x0000FFFF));
        !          1035:             nodeData->permissions.ownerID =  hp->h_meta->h_uid;
        !          1036:             nodeData->permissions.groupID = hp->h_meta->h_gid;
        !          1037:             nodeData->permissions.specialDevice = hp->h_meta->h_rdev;
        !          1038:             };
        !          1039:     };
        !          1040: 
        !          1041:        /* the rest only applies to files */
        !          1042:        if (nodeData->nodeType == kCatalogFileNode) {
        !          1043:         if (hp->h_meta->h_pflags & (SF_IMMUTABLE | UF_IMMUTABLE)) {
        !          1044:             /* The file is locked: set the locked bit in the catalog. */
        !          1045:             nodeData->nodeFlags |= kHFSFileLockedMask;
        !          1046:         } else {
        !          1047:             /* The file is unlocked: make sure the locked bit in the catalog is clear. */
        !          1048:             nodeData->nodeFlags &= ~kHFSFileLockedMask;
        !          1049:         };
        !          1050:                if (isResource) {
        !          1051:                        extents = nodeData->rsrcExtents;
        !          1052:                        nodeData->rsrcLogicalSize = fcb->fcbEOF;
        !          1053:                        nodeData->rsrcPhysicalSize = fcb->fcbPLen;
        !          1054:                } else {
        !          1055:                        extents = nodeData->dataExtents;
        !          1056:                        nodeData->dataLogicalSize = fcb->fcbEOF;
        !          1057:                        nodeData->dataPhysicalSize = fcb->fcbPLen;
        !          1058:                };
        !          1059: 
        !          1060:            /* Copy the extents from their correct location */
        !          1061:            if ( ! isHFSPlus) {
        !          1062:                /* HFS, Copy the extents from the FCB part */
        !          1063:                int i;
        !          1064:                for (i = 0; i < kHFSExtentDensity; ++i) {
        !          1065:                    extents[i].startBlock = (UInt16) (fcb->fcbExtRec[i].startBlock);
        !          1066:                    extents[i].blockCount = (UInt16) (fcb->fcbExtRec[i].blockCount);
        !          1067:                    }
        !          1068:            } else {
        !          1069:                /* HFSPlus, Copy the extents from the parallel extents */
        !          1070:                extendedFCB = GetParallelFCB (HTOV(hp));
        !          1071:                parellextents = extendedFCB->extents;
        !          1072:                bcopy ( parellextents, extents, sizeof(HFSPlusExtentRecord));
        !          1073:            };
        !          1074:        
        !          1075:            if (vp->v_type == VLNK) {
        !          1076:                ((struct FInfo *)(&nodeData->finderInfo))->fdType = kSymLinkFileType;
        !          1077:                ((struct FInfo *)(&nodeData->finderInfo))->fdCreator = kSymLinkCreator;
        !          1078:        
        !          1079:                        /* Set this up as an alias */
        !          1080:                        #if SUPPORTS_MAC_ALIASES
        !          1081:                                ((struct FInfo *)(&nodeData->finderInfo))->fdFlags |= kIsAlias;
        !          1082:                        #endif
        !          1083:                }
        !          1084:        }
        !          1085:  }
        !          1086: 
        !          1087: 
        !          1088: 
        !          1089: void MapFileOffset(struct hfsnode *hp,
        !          1090:                    off_t filePosition,
        !          1091:                    daddr_t *logBlockNumber,
        !          1092:                    long *blockSize,
        !          1093:                    long *blockOffset) {
        !          1094:     off_t extentOffset = filePosition;
        !          1095:     daddr_t precedingBlockCount;
        !          1096:     unsigned long logicalBlockSize = 0;
        !          1097:     unsigned long spaceRemaining;
        !          1098: 
        !          1099:     DBG_IO(("MapFileOffset: hp = 0x%08lX, vp = 0x%08lX ('%s'):\n", (u_long)hp, (u_long)HTOV(hp), H_NAME(hp)));
        !          1100:     // DBG_IO(("\tfilePosition 0x%08lX", (u_long)filePosition));
        !          1101: 
        !          1102:     if (filePosition < hp->h_optimizedblocksizelimit) {
        !          1103:         int extent;
        !          1104: 
        !          1105:         precedingBlockCount = 0;
        !          1106:         for (extent = 0; extent < LOGBLOCKMAPENTRIES; ++extent) {
        !          1107:             if ((hp->h_logicalblocktable[extent].logicalBlockCount > 0) &&
        !          1108:                 (extentOffset < hp->h_logicalblocktable[extent].extentLength)) {
        !          1109:                 logicalBlockSize = MAXLOGBLOCKSIZE;
        !          1110:                 spaceRemaining = hp->h_logicalblocktable[extent].extentLength - ((extentOffset / logicalBlockSize) * logicalBlockSize);
        !          1111:                 *blockSize = MIN(logicalBlockSize, spaceRemaining);
        !          1112:                 // DBG_IO(("\tUsing entry #%d: preceding blocks = 0x%X, position = 0x%8lX:\n",
        !          1113:                 //         extent, precedingBlockCount, (u_long)extentOffset));
        !          1114:                 break;
        !          1115:             };
        !          1116:             precedingBlockCount += hp->h_logicalblocktable[extent].logicalBlockCount;
        !          1117:             extentOffset -= hp->h_logicalblocktable[extent].extentLength;
        !          1118:         };
        !          1119:         DBG_ASSERT(logicalBlockSize > 0);
        !          1120:     } else {
        !          1121:         // DBG_IO(("\tUsing h_uniformblocksizestart = 0x%X and h_optimizedblocksizelimit = 0x%lX:\n",
        !          1122:         //         hp->h_uniformblocksizestart, (u_long)hp->h_optimizedblocksizelimit));
        !          1123:         precedingBlockCount = hp->h_uniformblocksizestart;
        !          1124:         extentOffset -= hp->h_optimizedblocksizelimit;
        !          1125:         logicalBlockSize = hp->h_meta->h_logBlockSize;
        !          1126:         *blockSize = logicalBlockSize;
        !          1127:     };
        !          1128: 
        !          1129:     *logBlockNumber =  precedingBlockCount + (extentOffset / logicalBlockSize);
        !          1130:     *blockOffset = extentOffset % logicalBlockSize;
        !          1131:     DBG_IO(("\tfilePosition 0x%08lX -> logBlockNo = 0x%X, blockSize = 0x%lX, blockOffset = 0x%lX.\n",
        !          1132:                  (u_long)filePosition,
        !          1133:                  *logBlockNumber,
        !          1134:                  *blockSize,
        !          1135:                  *blockOffset));
        !          1136: }
        !          1137: 
        !          1138: 
        !          1139: long LogicalBlockSize(struct hfsnode *hp, daddr_t logicalBlockNumber) {
        !          1140:     if (logicalBlockNumber < hp->h_uniformblocksizestart) {
        !          1141:         off_t fragmentOffset = 0;
        !          1142:         int extent;
        !          1143: 
        !          1144:         for (extent = 0; extent < LOGBLOCKMAPENTRIES; ++extent) {
        !          1145:             if ((hp->h_logicalblocktable[extent].logicalBlockCount > 0) &&
        !          1146:                 (logicalBlockNumber < hp->h_logicalblocktable[extent].logicalBlockCount)) {
        !          1147:                 // *filePosition = fragmentOffset + (logicalBlockNumber * MAXLOGBLOCKSIZE);
        !          1148:                 return MIN(MAXLOGBLOCKSIZE, hp->h_logicalblocktable[extent].extentLength - (logicalBlockNumber * MAXLOGBLOCKSIZE));
        !          1149:             };
        !          1150:             logicalBlockNumber -= hp->h_logicalblocktable[extent].logicalBlockCount;
        !          1151:             fragmentOffset += hp->h_logicalblocktable[extent].extentLength;
        !          1152:         };
        !          1153:     } else {
        !          1154:         // *filePosition = hp->h_optimizedblocksizelimit + ((logicalBlockNumber - hp->h_uniformblocksizestart) * hp->h_meta->h_logBlockSize);
        !          1155:         return hp->h_meta->h_logBlockSize;
        !          1156:     };
        !          1157: 
        !          1158:     DBG_ASSERT(0 /* cannot be reached */);
        !          1159:     return 0;
        !          1160: };
        !          1161: 
        !          1162: 
        !          1163: void UpdateBlockMappingTableEntry(struct hfsnode *hp, int index, daddr_t firstFragmentBlockNumber, long newFragmentLength) {
        !          1164: //  off_t                                      currentFragmentLength;
        !          1165: 
        !          1166:     /* Compute the number of logical blocks, rounding up to include any small trailing fragments: */
        !          1167:     hp->h_logicalblocktable[index].logicalBlockCount = (newFragmentLength + MAXLOGBLOCKSIZE - 1) / MAXLOGBLOCKSIZE;
        !          1168: 
        !          1169:     DBG_IO(("\tblocktable[%d]: length = 0x%lX, # blocks = 0x%lX.\n",
        !          1170:             index,
        !          1171:             newFragmentLength,
        !          1172:             (u_long)hp->h_logicalblocktable[index].logicalBlockCount));
        !          1173: 
        !          1174: #if 0
        !          1175:     currentFragmentLength = hp->h_logicalblocktable[index].extentLength;
        !          1176:     if ((newFragmentLength > currentFragmentLength) && (currentFragmentLength > 0)) {
        !          1177:         daddr_t                                        currentLastBlockNumber;
        !          1178:         long                                   currentLastBlockSize;
        !          1179:         long                                   newLastBlockSize;
        !          1180:         struct buf                             *bp;
        !          1181:         int                                            retval;
        !          1182: 
        !          1183:         currentLastBlockNumber = firstFragmentBlockNumber + (currentFragmentLength / MAXLOGBLOCKSIZE);
        !          1184:         currentLastBlockSize = currentFragmentLength % MAXLOGBLOCKSIZE;
        !          1185:         if (currentLastBlockSize > 0) {
        !          1186:             newLastBlockSize = MIN(MAXLOGBLOCKSIZE,
        !          1187:                                    newFragmentLength -
        !          1188:                                    ((currentLastBlockNumber - firstFragmentBlockNumber) * MAXLOGBLOCKSIZE));
        !          1189:             if (newLastBlockSize != currentLastBlockSize) {
        !          1190:                 DBG_IO(("\t\t(Adjusting block 0x%lX from 0x%lX to 0x%lX...)\n",
        !          1191:                         (unsigned long)currentLastBlockNumber,
        !          1192:                         currentLastBlockSize,
        !          1193:                         newLastBlockSize));
        !          1194:                 retval = bread(HTOV(hp), currentLastBlockNumber, currentLastBlockSize, NOCRED, &bp);
        !          1195:                 if (retval == 0) {
        !          1196:                     bexpand(bp, newLastBlockSize, NULL, RELEASE_BUFFER);
        !          1197:                 } else {
        !          1198:                     DBG_IO(("\t\terror (%d.) acquiring block 0x%lX; bp = 0x%08lX\n",
        !          1199:                             retval,
        !          1200:                             (unsigned long)currentLastBlockNumber,
        !          1201:                             (unsigned long)bp));
        !          1202:                     if (bp) brelse(bp);
        !          1203:                 };
        !          1204:             };
        !          1205:         };
        !          1206:     };
        !          1207: #endif
        !          1208:     hp->h_logicalblocktable[index].extentLength = newFragmentLength;
        !          1209: }
        !          1210: 
        !          1211: 
        !          1212: void UpdateBlockMappingTable(struct hfsnode *hp)
        !          1213: {
        !          1214:     ExtendedVCB                                *vcb = HTOVCB(hp);
        !          1215:     FCB                                                *fcb = HTOFCB(hp);
        !          1216:     ExtendedFCB                                *extendedFCB;
        !          1217:     Boolean                                    isHFSPlus;
        !          1218:     HFSPlusExtentDescriptor *parellextents;
        !          1219:     off_t                                      rangeMappedSoFar;
        !          1220:     u_long                                     logicalBlocksMappedSoFar;
        !          1221:     int                                                i;
        !          1222:     off_t                                      newFragmentLength;
        !          1223: 
        !          1224:     isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
        !          1225:     DBG_IO(("UpdateBlockMappingTable: hp = 0x%08lX, vp = 0x%08lX ('%s'):\n", (u_long)hp, (u_long)HTOV(hp), H_NAME(hp)));
        !          1226:     if (H_FORKTYPE(hp) != kDirCmplx) {
        !          1227:         rangeMappedSoFar = 0;
        !          1228:         logicalBlocksMappedSoFar = 0;
        !          1229: 
        !          1230:         if ( ! isHFSPlus) {
        !          1231:             DBG_ASSERT(kHFSExtentDensity <= LOGBLOCKMAPENTRIES);
        !          1232:             for (i = 0; i < kHFSExtentDensity; ++i) {
        !          1233:                 newFragmentLength = fcb->fcbExtRec[i].blockCount * vcb->blockSize;
        !          1234:                 UpdateBlockMappingTableEntry(hp, i, logicalBlocksMappedSoFar, newFragmentLength);
        !          1235:                 rangeMappedSoFar += newFragmentLength;
        !          1236:                 logicalBlocksMappedSoFar += hp->h_logicalblocktable[i].logicalBlockCount;
        !          1237:             }
        !          1238:             /* Zero out any remaining entries: */
        !          1239:             for (i = kHFSExtentDensity; i < LOGBLOCKMAPENTRIES; ++i) {
        !          1240:                 hp->h_logicalblocktable[i].extentLength = 0;
        !          1241:             };
        !          1242: #if DIAGNOSTIC
        !          1243:             if (rangeMappedSoFar < fcb->fcbPLen) DBG_ASSERT(hp->h_logicalblocktable[kHFSExtentDensity-1].extentLength > 0);
        !          1244: #endif
        !          1245:         } else {
        !          1246:             extendedFCB = GetParallelFCB (FCBTOV(fcb));
        !          1247:             parellextents = extendedFCB->extents;
        !          1248:             for (i = 0; i < kHFSPlusExtentDensity; ++i) {
        !          1249:                 newFragmentLength = parellextents[i].blockCount * vcb->blockSize;
        !          1250:                 UpdateBlockMappingTableEntry(hp, i, logicalBlocksMappedSoFar, newFragmentLength);
        !          1251:                 rangeMappedSoFar += newFragmentLength;
        !          1252:                 logicalBlocksMappedSoFar += hp->h_logicalblocktable[i].logicalBlockCount;
        !          1253:             }
        !          1254:             /* No need to zero out the remaining entries [there are none]: */
        !          1255:             DBG_ASSERT(LOGBLOCKMAPENTRIES <= kHFSPlusExtentDensity);
        !          1256: #if DIAGNOSTIC
        !          1257:             if (rangeMappedSoFar < fcb->fcbPLen) DBG_ASSERT(hp->h_logicalblocktable[kHFSPlusExtentDensity-1].extentLength > 0);
        !          1258: #endif
        !          1259:         };
        !          1260:         
        !          1261:         hp->h_optimizedblocksizelimit = rangeMappedSoFar;
        !          1262:         hp->h_uniformblocksizestart = logicalBlocksMappedSoFar;
        !          1263:         DBG_IO(("\th_optimizedblocksizelimit = 0x%lX, h_uniformblocksizestart = 0x%lX.\n",
        !          1264:                 (u_long)hp->h_optimizedblocksizelimit, (u_long)hp->h_uniformblocksizestart));
        !          1265: 
        !          1266: #if BYPASSBLOCKINGOPTIMIZATION
        !          1267:         hp->h_optimizedblocksizelimit = 0;
        !          1268:         hp->h_uniformblocksizestart = 0;
        !          1269: #endif
        !          1270:     };
        !          1271: }
        !          1272: 
        !          1273: void CopyCatalogToHFSNode(struct hfsCatalogInfo *catalogInfo, struct hfsnode *hp)
        !          1274: {
        !          1275:     FCB                                                *fcb;
        !          1276:        ExtendedVCB                             *vcb = HTOVCB(hp);
        !          1277:     Boolean                                    isHFSPlus, isDirectory, isResource;
        !          1278:     HFSPlusExtentDescriptor    *extents, *parellextents;
        !          1279:     ExtendedFCB                                *extendedFCB;
        !          1280:     ushort                                     finderFlags;
        !          1281:        UInt8                                   forkType;
        !          1282: 
        !          1283:     DBG_ASSERT (hp != NULL);
        !          1284:     DBG_ASSERT (hp->h_valid == HFS_VNODE_MAGIC);
        !          1285:     DBG_ASSERT (hp->h_meta != NULL);
        !          1286: 
        !          1287:     DBG_UTILS(("\tCopying to vnode Ox%08lX: name:%s, type:%d, nodeid:%ld\n", (unsigned long)HTOV(hp), catalogInfo->spec.name, H_FORKTYPE(hp), catalogInfo->nodeData.nodeID));
        !          1288:     forkType           = H_FORKTYPE(hp);
        !          1289:     isResource                 = (forkType == kRsrcFork);
        !          1290:     isDirectory                = (catalogInfo->nodeData.nodeType == kCatalogFolderNode);
        !          1291:     isHFSPlus          = (vcb->vcbSigWord == kHFSPlusSigWord);
        !          1292:     finderFlags        = ((struct FInfo *)(&catalogInfo->nodeData.finderInfo))->fdFlags;
        !          1293:     DBG_UTILS(("\t\t forkType:%d, isResource:%d, isDirectory:%d, isHFSPlus:%d\n", forkType, isResource, isDirectory, isHFSPlus));
        !          1294: 
        !          1295:        /* Copy over the name if NOT set yet */
        !          1296:        if (H_NAME(hp) == NULL) {
        !          1297:            hp->h_meta->h_namelen = strlen(catalogInfo->spec.name);
        !          1298:            if (hp->h_meta->h_namelen <= MAXHFSVNODELEN) {
        !          1299:                H_NAME(hp) = hp->h_meta->h_fileName;
        !          1300:            }
        !          1301:            else {
        !          1302:                MALLOC(H_NAME(hp), char *, hp->h_meta->h_namelen+1, M_HFSNODE, M_WAITOK);
        !          1303:                hp->h_meta->h_nodeflags |= IN_LONGNAME;
        !          1304:            };
        !          1305:        bcopy(catalogInfo->spec.name, H_NAME(hp), hp->h_meta->h_namelen+1);
        !          1306:         }
        !          1307:         else {
        !          1308:                 DBG_ASSERT (hp->h_meta->h_namelen == strlen(catalogInfo->spec.name));
        !          1309:                 DBG_ASSERT (strcmp(H_NAME(hp), catalogInfo->spec.name) == 0);
        !          1310:         };
        !          1311: 
        !          1312:        /* Copy over the dirid, and hint */
        !          1313:     H_FILEID(hp)       = catalogInfo->nodeData.nodeID;
        !          1314:     H_DIRID(hp)                = catalogInfo->spec.parID;
        !          1315:     H_HINT(hp)                 = catalogInfo->hint;
        !          1316: 
        !          1317:     if (hp->h_xfcb != NULL) {
        !          1318: 
        !          1319:         /* Init the fcb */
        !          1320:         fcb                    = HTOFCB(hp);
        !          1321:         fcb->fcbVPtr   = vcb;
        !          1322:         fcb->fcbFlNm   = catalogInfo->nodeData.nodeID;
        !          1323:         fcb->fcbFlags  = catalogInfo->nodeData.nodeFlags;
        !          1324: 
        !          1325:         if (forkType != kDirCmplx) {
        !          1326:             fcb->fcbFlags &= kHFSFileLockedMask;               /* Clear resource, dirty bits */
        !          1327:             if (fcb->fcbFlags != 0)                                            /* if clear, its not locked, then.. */
        !          1328:                 fcb->fcbFlags = fcbFileLockedMask;             /* duplicate the bit for later use */
        !          1329: 
        !          1330:             fcb->fcbClmpSize = vcb->vcbClpSiz; /*XXX why not use the one in catalogInfo? */
        !          1331: 
        !          1332:             if (isResource)    
        !          1333:                 extents = catalogInfo->nodeData.rsrcExtents;
        !          1334:             else
        !          1335:                 extents = catalogInfo->nodeData.dataExtents;
        !          1336: 
        !          1337:             /* Copy the extents to their correct location: */
        !          1338:             if ( ! isHFSPlus) {
        !          1339:                 int i;
        !          1340:                 for (i = 0; i < kHFSExtentDensity; ++i) {
        !          1341:                     fcb->fcbExtRec[i].startBlock = (UInt32) (extents[i].startBlock);
        !          1342:                     fcb->fcbExtRec[i].blockCount = (UInt32) (extents[i].blockCount);
        !          1343:                 }
        !          1344:             } else {
        !          1345:                 /* HFSPlus, Copy the extents to the parallel extents */
        !          1346:                 extendedFCB = GetParallelFCB (FCBTOV(fcb));
        !          1347:                 parellextents = extendedFCB->extents;
        !          1348:                 bcopy (extents, parellextents, sizeof(HFSPlusExtentRecord));
        !          1349:             };
        !          1350:             UpdateBlockMappingTable(hp);
        !          1351: 
        !          1352:             /* the valence field is overloaded to flag files over 2 gig */
        !          1353:             /* since we are working with a single fork, isolate it flags <why?> */
        !          1354:             /*  secondFlags = catalogInfo->nodeData.valence; */
        !          1355: 
        !          1356:             if (isResource)    {       
        !          1357:                 fcb->fcbEOF = catalogInfo->nodeData.rsrcLogicalSize;
        !          1358:                 fcb->fcbPLen = catalogInfo->nodeData.rsrcPhysicalSize;
        !          1359:                 fcb->fcbFlags |= fcbResourceMask;
        !          1360:             }  else {
        !          1361:                 fcb->fcbEOF = catalogInfo->nodeData.dataLogicalSize;
        !          1362:                 fcb->fcbPLen = catalogInfo->nodeData.dataPhysicalSize;
        !          1363:             };
        !          1364:         };
        !          1365:        };
        !          1366: 
        !          1367:     hp->h_meta->h_mtime = to_bsd_time(catalogInfo->nodeData.contentModDate);   /* UNIX-format mod date in seconds */
        !          1368:     hp->h_meta->h_crtime = to_bsd_time(catalogInfo->nodeData.createDate);              /* UNIX-format creation date in secs. */
        !          1369:     hp->h_meta->h_butime = to_bsd_time(catalogInfo->nodeData.backupDate);              /* UNIX-format backup date in secs. */
        !          1370:     if (isHFSPlus) {
        !          1371:         hp->h_meta->h_atime = to_bsd_time(catalogInfo->nodeData.accessDate);   /* UNIX-format mod date in seconds */
        !          1372:         hp->h_meta->h_ctime = to_bsd_time(catalogInfo->nodeData.attributeModDate);     /* UNIX-format status change date */
        !          1373:     }
        !          1374:     else {
        !          1375:         hp->h_meta->h_atime = to_bsd_time(catalogInfo->nodeData.contentModDate); /* UNIX-format mod date in seconds */
        !          1376:         hp->h_meta->h_ctime = to_bsd_time(catalogInfo->nodeData.contentModDate); /* UNIX-format status change date */
        !          1377:     }
        !          1378: 
        !          1379:     /* Now the rest */
        !          1380:     if (isHFSPlus && (catalogInfo->nodeData.permissions.permissions & IFMT)) {
        !          1381:         hp->h_meta->h_uid = catalogInfo->nodeData.permissions.ownerID;
        !          1382:         hp->h_meta->h_gid = catalogInfo->nodeData.permissions.groupID;
        !          1383:         /* The 32-bit permissions field is unpacked to yield the two significant bytes of flags and the
        !          1384:            mode as follows:
        !          1385:                                      +------------------------------------+
        !          1386:                         permissions: |    A    |    B   |      mode       |
        !          1387:                                      +------------------------------------+
        !          1388: 
        !          1389:                                                         |
        !          1390:                                                         V
        !          1391: 
        !          1392:                                      +------------------------------------+
        !          1393:                hp->h_meta->h_pflags: |XXXXXXXX|    A    |XXXXXXXX|    B   |
        !          1394:                                      +------------------------------------+
        !          1395: 
        !          1396:          */
        !          1397:         hp->h_meta->h_pflags = (((catalogInfo->nodeData.permissions.permissions & 0xFF000000) >> 8) |  /* A */
        !          1398:                                 ((catalogInfo->nodeData.permissions.permissions & 0x00FF0000) >> 16)); /* B */
        !          1399:         hp->h_meta->h_mode = (mode_t)(catalogInfo->nodeData.permissions.permissions & 0x0000FFFF);
        !          1400:         hp->h_meta->h_rdev = catalogInfo->nodeData.permissions.specialDevice;
        !          1401:     } else {
        !          1402:         /*
        !          1403:          *     Set the permissions as determined by the mount auguments
        !          1404:          *     but keep in account if the file or folder is hfs locked
        !          1405:          */    
        !          1406:         hp->h_meta->h_nodeflags |= IN_UNSETACCESS;                     
        !          1407:         hp->h_meta->h_uid = HTOHFS(hp)->hfs_uid;
        !          1408:         hp->h_meta->h_gid = HTOHFS(hp)->hfs_gid;
        !          1409:         /* Default access is full read/write/execute: */
        !          1410:         hp->h_meta->h_mode = ACCESSPERMS;      /* 0777: rwxrwxrwx */
        !          1411:         
        !          1412:         /* ... but no more than that permitted by the mount point's: */
        !          1413:         if (isDirectory) {
        !          1414:             hp->h_meta->h_mode &= HTOHFS(hp)->hfs_dir_mask;
        !          1415:                }
        !          1416:                else {
        !          1417:             hp->h_meta->h_mode &= HTOHFS(hp)->hfs_file_mask;
        !          1418:                }
        !          1419:         
        !          1420:         if(isDirectory)
        !          1421:             hp->h_meta->h_mode |= IFDIR;
        !          1422:         else if (SUPPORTS_MAC_ALIASES && (finderFlags & kIsAlias))     /* aliases will be symlinks in the future */
        !          1423:             hp->h_meta->h_mode |= IFLNK;
        !          1424:         else
        !          1425:             hp->h_meta->h_mode |= IFREG;
        !          1426: 
        !          1427:     };
        !          1428: 
        !          1429:     /* Make sure the IMMUTABLE bits are in sync with the locked flag in the catalog: */
        !          1430:     if (!isDirectory) {
        !          1431:         if (catalogInfo->nodeData.nodeFlags & kHFSFileLockedMask) {
        !          1432:             /* The file's supposed to be locked:
        !          1433:                Make sure at least one of the IMMUTABLE bits is set: */
        !          1434:             if ((hp->h_meta->h_pflags & (SF_IMMUTABLE | UF_IMMUTABLE)) == 0) {
        !          1435:                 hp->h_meta->h_pflags |= UF_IMMUTABLE;                          /* Set the user-changable IMMUTABLE bit */
        !          1436:             };
        !          1437:         } else {
        !          1438:             /* The file's supposed to be unlocked: */
        !          1439:             hp->h_meta->h_pflags &= ~(SF_IMMUTABLE | UF_IMMUTABLE);
        !          1440:         };
        !          1441:     };
        !          1442: 
        !          1443:        if (isDirectory)
        !          1444:        hp->h_size = sizeof (hfsdirentry) * (catalogInfo->nodeData.valence + 2);
        !          1445:        else
        !          1446:        hp->h_size = catalogInfo->nodeData.rsrcPhysicalSize + catalogInfo->nodeData.dataPhysicalSize;
        !          1447:        
        !          1448:     /* finish up some vnode stuff */
        !          1449:     /* Set the root flag if necesary */
        !          1450:        switch (hp->h_meta->h_mode & IFMT) {
        !          1451:         case IFDIR:
        !          1452:             HTOV(hp)->v_type = VDIR;
        !          1453:             if (H_FILEID(hp) == kRootDirID)
        !          1454:                 HTOV(hp)->v_flag |= VROOT;
        !          1455:             break;
        !          1456:         case IFREG:
        !          1457:             if (forkType == kDirCmplx)
        !          1458:                 HTOV(hp)->v_type = VCPLX;
        !          1459:             else
        !          1460:                 HTOV(hp)->v_type = VREG;
        !          1461:             break;
        !          1462:         case IFLNK:
        !          1463:             if (forkType == kDirCmplx)
        !          1464:                 HTOV(hp)->v_type = VCPLX;
        !          1465:             else
        !          1466:                HTOV(hp)->v_type = VLNK;
        !          1467:             break;
        !          1468:         default:
        !          1469:             DBG_ASSERT(false);
        !          1470:             HTOV(hp)->v_type = VBAD;
        !          1471:     };         
        !          1472: }
        !          1473: 
        !          1474: int AttributeBlockSize(struct attrlist *attrlist) {
        !          1475:        int size;
        !          1476:        attrgroup_t a;
        !          1477:        
        !          1478: #if ((ATTR_CMN_NAME                    | ATTR_CMN_DEVID                        | ATTR_CMN_FSID                         | ATTR_CMN_OBJTYPE              | \
        !          1479:       ATTR_CMN_OBJTAG          | ATTR_CMN_OBJID                        | ATTR_CMN_OBJPERMANENTID       | ATTR_CMN_PAROBJID             | \
        !          1480:       ATTR_CMN_SCRIPT          | ATTR_CMN_CRTIME                       | ATTR_CMN_MODTIME                      | ATTR_CMN_CHGTIME              | \
        !          1481:       ATTR_CMN_ACCTIME         | ATTR_CMN_BKUPTIME                     | ATTR_CMN_FNDRINFO                     | ATTR_CMN_OWNERID              | \
        !          1482:       ATTR_CMN_GRPID           | ATTR_CMN_ACCESSMASK           | ATTR_CMN_NAMEDATTRCOUNT       | ATTR_CMN_NAMEDATTRLIST| \
        !          1483:       ATTR_CMN_FLAGS) != ATTR_CMN_VALIDMASK)
        !          1484: #error AttributeBlockSize: Missing bits in common mask computation!
        !          1485: #endif
        !          1486:           DBG_ASSERT((attrlist->commonattr & ~ATTR_CMN_VALIDMASK) == 0);
        !          1487: 
        !          1488: #if ((ATTR_VOL_FSTYPE          | ATTR_VOL_SIGNATURE            | ATTR_VOL_SIZE                         | ATTR_VOL_SPACEFREE    | \
        !          1489:       ATTR_VOL_SPACEAVAIL      | ATTR_VOL_MINALLOCATION        | ATTR_VOL_ALLOCATIONCLUMP      | ATTR_VOL_IOBLOCKSIZE  | \
        !          1490:       ATTR_VOL_OBJCOUNT                | ATTR_VOL_FILECOUNT            | ATTR_VOL_DIRCOUNT                     | ATTR_VOL_MAXOBJCOUNT  | \
        !          1491:       ATTR_VOL_MOUNTPOINT      | ATTR_VOL_NAME                         | ATTR_VOL_MOUNTFLAGS       | ATTR_VOL_INFO) != ATTR_VOL_VALIDMASK)
        !          1492: #error AttributeBlockSize: Missing bits in volume mask computation!
        !          1493: #endif
        !          1494:           DBG_ASSERT((attrlist->volattr & ~ATTR_VOL_VALIDMASK) == 0);
        !          1495: 
        !          1496: #if ((ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT) != ATTR_DIR_VALIDMASK)
        !          1497: #error AttributeBlockSize: Missing bits in directory mask computation!
        !          1498: #endif
        !          1499:       DBG_ASSERT((attrlist->dirattr & ~ATTR_DIR_VALIDMASK) == 0);
        !          1500: #if ((ATTR_FILE_LINKCOUNT      | ATTR_FILE_TOTALSIZE           | ATTR_FILE_ALLOCSIZE           | ATTR_FILE_IOBLOCKSIZE         | \
        !          1501:       ATTR_FILE_CLUMPSIZE      | ATTR_FILE_DEVTYPE                     | ATTR_FILE_FILETYPE            | ATTR_FILE_FORKCOUNT           | \
        !          1502:       ATTR_FILE_FORKLIST       | ATTR_FILE_DATALENGTH          | ATTR_FILE_DATAALLOCSIZE       | ATTR_FILE_DATAEXTENTS         | \
        !          1503:       ATTR_FILE_RSRCLENGTH     | ATTR_FILE_RSRCALLOCSIZE       | ATTR_FILE_RSRCEXTENTS) != ATTR_FILE_VALIDMASK)
        !          1504: #error AttributeBlockSize: Missing bits in file mask computation!
        !          1505: #endif
        !          1506:           DBG_ASSERT((attrlist->fileattr & ~ATTR_FILE_VALIDMASK) == 0);
        !          1507: 
        !          1508: #if ((ATTR_FORK_TOTALSIZE | ATTR_FORK_ALLOCSIZE) != ATTR_FORK_VALIDMASK)
        !          1509: #error AttributeBlockSize: Missing bits in fork mask computation!
        !          1510: #endif
        !          1511:       DBG_ASSERT((attrlist->forkattr & ~ATTR_FORK_VALIDMASK) == 0);
        !          1512: 
        !          1513:        size = 0;
        !          1514:        
        !          1515:        if ((a = attrlist->commonattr) != 0) {
        !          1516:         if (a & ATTR_CMN_NAME) size += sizeof(struct attrreference);
        !          1517:                if (a & ATTR_CMN_DEVID) size += sizeof(dev_t);
        !          1518:                if (a & ATTR_CMN_FSID) size += sizeof(fsid_t);
        !          1519:                if (a & ATTR_CMN_OBJTYPE) size += sizeof(fsobj_type_t);
        !          1520:                if (a & ATTR_CMN_OBJTAG) size += sizeof(fsobj_tag_t);
        !          1521:                if (a & ATTR_CMN_OBJID) size += sizeof(fsobj_id_t);
        !          1522:         if (a & ATTR_CMN_OBJPERMANENTID) size += sizeof(fsobj_id_t);
        !          1523:                if (a & ATTR_CMN_PAROBJID) size += sizeof(fsobj_id_t);
        !          1524:                if (a & ATTR_CMN_SCRIPT) size += sizeof(text_encoding_t);
        !          1525:                if (a & ATTR_CMN_CRTIME) size += sizeof(struct timespec);
        !          1526:                if (a & ATTR_CMN_MODTIME) size += sizeof(struct timespec);
        !          1527:                if (a & ATTR_CMN_CHGTIME) size += sizeof(struct timespec);
        !          1528:                if (a & ATTR_CMN_ACCTIME) size += sizeof(struct timespec);
        !          1529:                if (a & ATTR_CMN_BKUPTIME) size += sizeof(struct timespec);
        !          1530:                if (a & ATTR_CMN_FNDRINFO) size += 32 * sizeof(UInt8);
        !          1531:                if (a & ATTR_CMN_OWNERID) size += sizeof(uid_t);
        !          1532:                if (a & ATTR_CMN_GRPID) size += sizeof(gid_t);
        !          1533:                if (a & ATTR_CMN_ACCESSMASK) size += sizeof(u_long);
        !          1534:                if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(u_long);
        !          1535:                if (a & ATTR_CMN_NAMEDATTRLIST) size += sizeof(struct attrreference);
        !          1536:                if (a & ATTR_CMN_FLAGS) size += sizeof(u_long);
        !          1537:        };
        !          1538:        if ((a = attrlist->volattr) != 0) {
        !          1539:                if (a & ATTR_VOL_FSTYPE) size += sizeof(u_long);
        !          1540:                if (a & ATTR_VOL_SIGNATURE) size += sizeof(u_long);
        !          1541:                if (a & ATTR_VOL_SIZE) size += sizeof(off_t);
        !          1542:                if (a & ATTR_VOL_SPACEFREE) size += sizeof(off_t);
        !          1543:                if (a & ATTR_VOL_SPACEAVAIL) size += sizeof(off_t);
        !          1544:                if (a & ATTR_VOL_MINALLOCATION) size += sizeof(off_t);
        !          1545:                if (a & ATTR_VOL_ALLOCATIONCLUMP) size += sizeof(off_t);
        !          1546:                if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(u_long);
        !          1547:                if (a & ATTR_VOL_OBJCOUNT) size += sizeof(u_long);
        !          1548:                if (a & ATTR_VOL_FILECOUNT) size += sizeof(u_long);
        !          1549:                if (a & ATTR_VOL_DIRCOUNT) size += sizeof(u_long);
        !          1550:                if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(u_long);
        !          1551:                if (a & ATTR_VOL_MOUNTPOINT) size += sizeof(struct attrreference);
        !          1552:         if (a & ATTR_VOL_NAME) size += sizeof(struct attrreference);
        !          1553:         if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(u_long);
        !          1554:        };
        !          1555:        if ((a = attrlist->dirattr) != 0) {
        !          1556:                if (a & ATTR_DIR_LINKCOUNT) size += sizeof(u_long);
        !          1557:                if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(u_long);
        !          1558:        };
        !          1559:        if ((a = attrlist->fileattr) != 0) {
        !          1560:                if (a & ATTR_FILE_LINKCOUNT) size += sizeof(u_long);
        !          1561:                if (a & ATTR_FILE_TOTALSIZE) size += sizeof(off_t);
        !          1562:                if (a & ATTR_FILE_ALLOCSIZE) size += sizeof(off_t);
        !          1563:                if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(size_t);
        !          1564:                if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(off_t);
        !          1565:                if (a & ATTR_FILE_DEVTYPE) size += sizeof(u_long);
        !          1566:                if (a & ATTR_FILE_FILETYPE) size += sizeof(u_long);
        !          1567:                if (a & ATTR_FILE_FORKCOUNT) size += sizeof(u_long);
        !          1568:                if (a & ATTR_FILE_FORKLIST) size += sizeof(struct attrreference);
        !          1569:                if (a & ATTR_FILE_DATALENGTH) size += sizeof(off_t);
        !          1570:                if (a & ATTR_FILE_DATAALLOCSIZE) size += sizeof(off_t);
        !          1571:                if (a & ATTR_FILE_DATAEXTENTS) size += sizeof(extentrecord);
        !          1572:                if (a & ATTR_FILE_RSRCLENGTH) size += sizeof(off_t);
        !          1573:                if (a & ATTR_FILE_RSRCALLOCSIZE) size += sizeof(off_t);
        !          1574:                if (a & ATTR_FILE_RSRCEXTENTS) size += sizeof(extentrecord);
        !          1575:        };
        !          1576:        if ((a = attrlist->forkattr) != 0) {
        !          1577:                if (a & ATTR_FORK_TOTALSIZE) size += sizeof(off_t);
        !          1578:                if (a & ATTR_FORK_ALLOCSIZE) size += sizeof(off_t);
        !          1579:        };
        !          1580: 
        !          1581:     return size;
        !          1582: }
        !          1583: 
        !          1584: 
        !          1585: 
        !          1586: void PackVolCommonAttributes(struct attrlist *alist,
        !          1587:                                                         struct vnode *root_vp,
        !          1588:                                                         struct hfsCatalogInfo *root_catInfo,
        !          1589:                                                         void **attrbufptrptr,
        !          1590:                                                         void **varbufptrptr) {
        !          1591:     void *attrbufptr;
        !          1592:     void *varbufptr;
        !          1593:     attrgroup_t a;
        !          1594:     struct hfsnode *root_hp = VTOH(root_vp);
        !          1595:     struct mount *mp = VTOVFS(root_vp);
        !          1596:     struct hfsmount *hfsmp = VTOHFS(root_vp);
        !          1597:     struct ExtendedVCB *vcb = HFSTOVCB(hfsmp);
        !          1598:        u_long attrlength;
        !          1599:        
        !          1600:        attrbufptr = *attrbufptrptr;
        !          1601:        varbufptr = *varbufptrptr;
        !          1602: 
        !          1603:     if ((a = alist->commonattr) != 0) {
        !          1604:         if (a & ATTR_CMN_NAME) {
        !          1605:             attrlength = root_hp->h_meta->h_namelen+1;
        !          1606:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
        !          1607:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1608:             (void) strncpy((unsigned char *)varbufptr, H_NAME(root_hp), attrlength);
        !          1609: 
        !          1610:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1611:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1612:             ++((struct attrreference *)attrbufptr);
        !          1613:         };
        !          1614:                if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = hfsmp->hfs_raw_dev;
        !          1615:                if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = mp->mnt_stat.f_fsid;
        !          1616:                if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = 0;
        !          1617:                if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = VT_HFS;
        !          1618:                if (a & ATTR_CMN_OBJID) {
        !          1619:                        ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
        !          1620:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
        !          1621:                        ++((fsobj_id_t *)attrbufptr);
        !          1622:                };
        !          1623:         if (a & ATTR_CMN_OBJPERMANENTID) {
        !          1624:             ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
        !          1625:             ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
        !          1626:             ++((fsobj_id_t *)attrbufptr);
        !          1627:         };
        !          1628:                if (a & ATTR_CMN_PAROBJID) {
        !          1629:             ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
        !          1630:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
        !          1631:                        ++((fsobj_id_t *)attrbufptr);
        !          1632:                };
        !          1633:                VCB_LOCK(vcb);
        !          1634:         if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = vcb->volumeNameEncodingHint;
        !          1635:                /* NOTE: all VCB dates are in local Mac OS time */
        !          1636:                if (a & ATTR_CMN_CRTIME) {
        !          1637:                        /*
        !          1638:                         * HFS Plus stores the volume create date in *local*
        !          1639:                         * time in the volume header. So don't use the create
        !          1640:                         * date from the vcb. Use the root's crtime instead.
        !          1641:                         */
        !          1642:                        if (vcb->vcbSigWord == kHFSPlusSigWord) {
        !          1643:                                ((struct timespec *)attrbufptr)->tv_sec = root_hp->h_meta->h_crtime;
        !          1644:                        } else {
        !          1645:                                ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbCrDate);
        !          1646:                        }
        !          1647:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1648:                        ++((struct timespec *)attrbufptr);
        !          1649:                };
        !          1650:                if (a & ATTR_CMN_MODTIME) {
        !          1651:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbLsMod);
        !          1652:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1653:                        ++((struct timespec *)attrbufptr);
        !          1654:                };
        !          1655:                if (a & ATTR_CMN_CHGTIME) {
        !          1656:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbLsMod);
        !          1657:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1658:                        ++((struct timespec *)attrbufptr);
        !          1659:                };
        !          1660:                if (a & ATTR_CMN_ACCTIME) {
        !          1661:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbLsMod);
        !          1662:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1663:                        ++((struct timespec *)attrbufptr);
        !          1664:                };
        !          1665:                if (a & ATTR_CMN_BKUPTIME) {
        !          1666:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbVolBkUp);
        !          1667:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1668:                        ++((struct timespec *)attrbufptr);
        !          1669:                };
        !          1670:                if (a & ATTR_CMN_FNDRINFO) {
        !          1671:             bcopy (&vcb->vcbFndrInfo, attrbufptr, sizeof(vcb->vcbFndrInfo));
        !          1672:             attrbufptr += sizeof(vcb->vcbFndrInfo);
        !          1673:                };
        !          1674:                VCB_UNLOCK(vcb);
        !          1675:                if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = root_hp->h_meta->h_uid;
        !          1676:                if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = root_hp->h_meta->h_gid;
        !          1677:                if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)root_hp->h_meta->h_mode;
        !          1678:                if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0;                 /* XXX PPD TBC */
        !          1679:                if (a & ATTR_CMN_NAMEDATTRLIST) {
        !          1680:                        attrlength = 0;
        !          1681:             ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
        !          1682:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1683:                        
        !          1684:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1685:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1686:             ++((struct attrreference *)attrbufptr);
        !          1687:                };
        !          1688:                if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = root_hp->h_meta->h_pflags;
        !          1689:        };
        !          1690:        
        !          1691:        *attrbufptrptr = attrbufptr;
        !          1692:        *varbufptrptr = varbufptr;
        !          1693: }
        !          1694: 
        !          1695: 
        !          1696: 
        !          1697: void PackVolAttributeBlock(struct attrlist *alist,
        !          1698:                                                   struct vnode *root_vp,
        !          1699:                                                   struct hfsCatalogInfo *root_catInfo,
        !          1700:                                                   void **attrbufptrptr,
        !          1701:                                                   void **varbufptrptr) {
        !          1702:     void *attrbufptr;
        !          1703:     void *varbufptr;
        !          1704:     attrgroup_t a;
        !          1705:     struct mount *mp = VTOVFS(root_vp);
        !          1706:     struct hfsmount *hfsmp = VTOHFS(root_vp);
        !          1707:     struct ExtendedVCB *vcb = HFSTOVCB(hfsmp);
        !          1708:        u_long attrlength;
        !          1709:        
        !          1710:        attrbufptr = *attrbufptrptr;
        !          1711:        varbufptr = *varbufptrptr;
        !          1712:        
        !          1713:        if ((a = alist->volattr) != 0) {
        !          1714:                VCB_LOCK(vcb);
        !          1715:                if (a & ATTR_VOL_FSTYPE) *((u_long *)attrbufptr)++ = (u_long)mp->mnt_vfc->vfc_typenum;
        !          1716:                if (a & ATTR_VOL_SIGNATURE) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbSigWord;
        !          1717:         if (a & ATTR_VOL_SIZE) *((off_t *)attrbufptr)++ = (off_t)vcb->totalBlocks * (off_t)vcb->blockSize;
        !          1718:         if (a & ATTR_VOL_SPACEFREE) *((off_t *)attrbufptr)++ = (off_t)vcb->freeBlocks * (off_t)vcb->blockSize;
        !          1719:         if (a & ATTR_VOL_SPACEAVAIL) *((off_t *)attrbufptr)++ = (off_t)vcb->freeBlocks * (off_t)vcb->blockSize;
        !          1720:         if (a & ATTR_VOL_MINALLOCATION) *((off_t *)attrbufptr)++ = (off_t)vcb->blockSize;
        !          1721:                if (a & ATTR_VOL_ALLOCATIONCLUMP) *((off_t *)attrbufptr)++ = (off_t)vcb->allocationsClumpSize;
        !          1722:         if (a & ATTR_VOL_IOBLOCKSIZE) *((u_long *)attrbufptr)++ = (u_long)hfsmp->hfs_log_block_size;
        !          1723:                if (a & ATTR_VOL_OBJCOUNT) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbFilCnt + (u_long)vcb->vcbDirCnt;
        !          1724:                if (a & ATTR_VOL_FILECOUNT) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbFilCnt;
        !          1725:                if (a & ATTR_VOL_DIRCOUNT) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbDirCnt;
        !          1726:                if (a & ATTR_VOL_MAXOBJCOUNT) *((u_long *)attrbufptr)++ = 0xFFFFFFFF;
        !          1727:                if (a & ATTR_VOL_MOUNTPOINT) {
        !          1728:                        attrlength = strlen(hfsmp->hfs_mountpoint) + 1;
        !          1729:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
        !          1730:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1731:                        (void) strcpy((unsigned char *)varbufptr, hfsmp->hfs_mountpoint);
        !          1732:                        
        !          1733:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1734:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1735:             ++((struct attrreference *)attrbufptr);
        !          1736:                };
        !          1737:         if (a & ATTR_VOL_NAME) {
        !          1738:             attrlength = VTOH(root_vp)->h_meta->h_namelen + 1;
        !          1739:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
        !          1740:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1741:             strncpy((char *)varbufptr, H_NAME(VTOH(root_vp)), attrlength);
        !          1742: 
        !          1743:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1744:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1745:             ++((struct attrreference *)attrbufptr);
        !          1746:         };
        !          1747:         if (a & ATTR_VOL_MOUNTFLAGS) *((u_long *)attrbufptr)++ = (u_long)mp->mnt_flag;
        !          1748:                VCB_UNLOCK(vcb);
        !          1749:        };
        !          1750:        
        !          1751:        *attrbufptrptr = attrbufptr;
        !          1752:        *varbufptrptr = varbufptr;
        !          1753: }
        !          1754: 
        !          1755: 
        !          1756: 
        !          1757: 
        !          1758: void PackVolumeInfo(struct attrlist *alist,
        !          1759:                     struct vnode *root_vp,
        !          1760:                     struct hfsCatalogInfo *root_catinfo,
        !          1761:                     void **attrbufptrptr,
        !          1762:                     void **varbufptrptr) {
        !          1763: 
        !          1764:     PackVolCommonAttributes(alist, root_vp, root_catinfo, attrbufptrptr, varbufptrptr);
        !          1765:     PackVolAttributeBlock(alist, root_vp, root_catinfo, attrbufptrptr, varbufptrptr);
        !          1766: };
        !          1767: 
        !          1768: // Pack the common attribute contents of an objects hfsCatalogInfo
        !          1769: void PackCommonCatalogInfoAttributeBlock(struct attrlist               *alist,
        !          1770:                                                                                struct vnode                    *root_vp,
        !          1771:                                                                                struct hfsCatalogInfo   *catalogInfo,
        !          1772:                                                                                void                                    **attrbufptrptr,
        !          1773:                                                                                void                                    **varbufptrptr )
        !          1774: {
        !          1775:        struct hfsnode  *hp;
        !          1776:        void                    *attrbufptr;
        !          1777:        void                    *varbufptr;
        !          1778:        attrgroup_t             a;
        !          1779:        u_long                  attrlength;
        !          1780:        
        !          1781:        hp                      = VTOH(root_vp);
        !          1782:        attrbufptr      = *attrbufptrptr;
        !          1783:        varbufptr       = *varbufptrptr;
        !          1784:        
        !          1785:        if ((a = alist->commonattr) != 0)
        !          1786:        {
        !          1787:                if (a & ATTR_CMN_NAME)                                                                          
        !          1788:             {
        !          1789:             attrlength = strlen(catalogInfo->spec.name) + 1;
        !          1790:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
        !          1791:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1792:             (void) strncpy((unsigned char *)varbufptr, (unsigned char *) &(catalogInfo->spec.name), attrlength);
        !          1793:             // ((char *) varbufptr)[attrlength-1] = 0;                                                                 //      Now it's a C string
        !          1794: 
        !          1795:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1796:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1797:             ++((struct attrreference *)attrbufptr);
        !          1798:             };
        !          1799:                if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++                        = hp->h_dev;
        !          1800:                if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++                        = VTOVFS(root_vp)->mnt_stat.f_fsid;
        !          1801:                if (a & ATTR_CMN_OBJTYPE)
        !          1802:                {
        !          1803:                        if ( catalogInfo->nodeData.nodeType == kCatalogFolderNode )
        !          1804:                                *((fsobj_type_t *)attrbufptr)++ = VDIR;
        !          1805:                        else                                                                                                            //XXX could be more robust in object type handling
        !          1806:                                *((fsobj_type_t *)attrbufptr)++ = VREG;
        !          1807:                }
        !          1808:                if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++         = root_vp->v_tag;
        !          1809:         if (a & ATTR_CMN_OBJID)
        !          1810:         {
        !          1811:             ((fsobj_id_t *)attrbufptr)->fid_objno                                      = catalogInfo->nodeData.nodeID; //      H_FILEID(hp);
        !          1812:             ((fsobj_id_t *)attrbufptr)->fid_generation                         = 0;
        !          1813:             ++((fsobj_id_t *)attrbufptr);
        !          1814:         };
        !          1815:         if (a & ATTR_CMN_OBJPERMANENTID)
        !          1816:         {
        !          1817:             ((fsobj_id_t *)attrbufptr)->fid_objno                                      = catalogInfo->nodeData.nodeID; //      H_FILEID(hp);
        !          1818:             ((fsobj_id_t *)attrbufptr)->fid_generation                         = 0;
        !          1819:             ++((fsobj_id_t *)attrbufptr);
        !          1820:         };
        !          1821:                if (a & ATTR_CMN_PAROBJID)
        !          1822:                {
        !          1823:             ((fsobj_id_t *)attrbufptr)->fid_objno                                      = catalogInfo->spec.parID;              //      H_DIRID(hp);
        !          1824:                        ((fsobj_id_t *)attrbufptr)->fid_generation                              = 0;
        !          1825:                        ++((fsobj_id_t *)attrbufptr);
        !          1826:                };
        !          1827:         if (a & ATTR_CMN_SCRIPT)
        !          1828:          {
        !          1829:            if (HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) {
        !          1830:                        *((text_encoding_t *)attrbufptr)++ = catalogInfo->nodeData.textEncoding;
        !          1831:            } else {
        !          1832:                        *((text_encoding_t *)attrbufptr)++ = 0;
        !          1833:            }
        !          1834:          };
        !          1835:                if (a & ATTR_CMN_CRTIME)
        !          1836:                {
        !          1837:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.createDate);
        !          1838:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
        !          1839:                        ++((struct timespec *)attrbufptr);
        !          1840:                };
        !          1841:                if (a & ATTR_CMN_MODTIME)
        !          1842:                {
        !          1843:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.contentModDate);
        !          1844:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
        !          1845:                        ++((struct timespec *)attrbufptr);
        !          1846:                };
        !          1847:                if (a & ATTR_CMN_CHGTIME)
        !          1848:                {
        !          1849:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.attributeModDate);
        !          1850:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
        !          1851:                        ++((struct timespec *)attrbufptr);
        !          1852:                };
        !          1853:                if (a & ATTR_CMN_ACCTIME)
        !          1854:                {
        !          1855:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.accessDate);
        !          1856:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
        !          1857:                        ++((struct timespec *)attrbufptr);
        !          1858:                };
        !          1859:                if (a & ATTR_CMN_BKUPTIME)
        !          1860:                {
        !          1861:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.backupDate);
        !          1862:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
        !          1863:                        ++((struct timespec *)attrbufptr);
        !          1864:                };
        !          1865:                if (a & ATTR_CMN_FNDRINFO)
        !          1866:                {
        !          1867:                        bcopy (&catalogInfo->nodeData.finderInfo, attrbufptr, sizeof(catalogInfo->nodeData.finderInfo));
        !          1868:                        attrbufptr += sizeof(catalogInfo->nodeData.finderInfo);
        !          1869:                        bcopy (&catalogInfo->nodeData.extFinderInfo, attrbufptr, sizeof(catalogInfo->nodeData.extFinderInfo));
        !          1870:                        attrbufptr += sizeof(catalogInfo->nodeData.extFinderInfo);
        !          1871:                };
        !          1872:                if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++                      = catalogInfo->nodeData.permissions.ownerID;
        !          1873:                if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++                        = catalogInfo->nodeData.permissions.groupID;
        !          1874:                if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++          = (u_long)(mode_t)(catalogInfo->nodeData.permissions.permissions & 0x0000FFFF);
        !          1875:                if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++      = 0;                    /* XXX PPD TBC */
        !          1876:                if (a & ATTR_CMN_NAMEDATTRLIST)
        !          1877:                {
        !          1878:                        attrlength = 0;
        !          1879:                        ((struct attrreference *)attrbufptr)->attr_dataoffset   = 0;
        !          1880:                        ((struct attrreference *)attrbufptr)->attr_length               = attrlength;
        !          1881:                        
        !          1882:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1883:                        varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1884:                        ++((struct attrreference *)attrbufptr);
        !          1885:                };
        !          1886:         if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++                      = (u_long)((((catalogInfo->nodeData.permissions.permissions & 0xFFFF0000) >> 8)  & 0x00FF0000) |
        !          1887:                                                                                (((catalogInfo->nodeData.permissions.permissions & 0xFFFF0000) >> 24) & 0x000000FF));
        !          1888:        };
        !          1889:        
        !          1890:        *attrbufptrptr  = attrbufptr;
        !          1891:        *varbufptrptr   = varbufptr;
        !          1892: }
        !          1893: 
        !          1894: 
        !          1895: void PackCommonAttributeBlock(struct attrlist *alist,
        !          1896:                                                          struct vnode *vp,
        !          1897:                                                          struct hfsCatalogInfo *catInfo,
        !          1898:                                                          void **attrbufptrptr,
        !          1899:                                                          void **varbufptrptr) {
        !          1900:        struct hfsnode *hp;
        !          1901:     void *attrbufptr;
        !          1902:     void *varbufptr;
        !          1903:     attrgroup_t a;
        !          1904:        u_long attrlength;
        !          1905:        
        !          1906:        hp = VTOH(vp);
        !          1907:        
        !          1908:        attrbufptr = *attrbufptrptr;
        !          1909:        varbufptr = *varbufptrptr;
        !          1910:        
        !          1911:     if ((a = alist->commonattr) != 0) {
        !          1912:         if (a & ATTR_CMN_NAME) {
        !          1913:             attrlength = hp->h_meta->h_namelen + 1;
        !          1914:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
        !          1915:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1916:             (void) strncpy((unsigned char *)varbufptr, H_NAME(hp), attrlength);
        !          1917: 
        !          1918:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1919:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1920:             ++((struct attrreference *)attrbufptr);
        !          1921:         };
        !          1922:                if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = hp->h_dev;
        !          1923:                if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = VTOVFS(vp)->mnt_stat.f_fsid;
        !          1924:                if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = vp->v_type;
        !          1925:                if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = vp->v_tag;
        !          1926:         if (a & ATTR_CMN_OBJID)        {
        !          1927:             ((fsobj_id_t *)attrbufptr)->fid_objno = H_FILEID(hp);
        !          1928:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
        !          1929:                        ++((fsobj_id_t *)attrbufptr);
        !          1930:                };
        !          1931:         if (a & ATTR_CMN_OBJPERMANENTID)       {
        !          1932:             ((fsobj_id_t *)attrbufptr)->fid_objno = H_FILEID(hp);
        !          1933:             ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
        !          1934:             ++((fsobj_id_t *)attrbufptr);
        !          1935:         };
        !          1936:                if (a & ATTR_CMN_PAROBJID) {
        !          1937:             ((fsobj_id_t *)attrbufptr)->fid_objno = H_DIRID(hp);
        !          1938:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
        !          1939:                        ++((fsobj_id_t *)attrbufptr);
        !          1940:                };
        !          1941:         if (a & ATTR_CMN_SCRIPT)
        !          1942:          {
        !          1943:            if (HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) {
        !          1944:                        *((text_encoding_t *)attrbufptr)++ = catInfo->nodeData.textEncoding;
        !          1945:            } else {
        !          1946:                        *((text_encoding_t *)attrbufptr)++ = 0;
        !          1947:            }
        !          1948:          };
        !          1949:                if (a & ATTR_CMN_CRTIME) {
        !          1950:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_crtime;
        !          1951:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1952:                        ++((struct timespec *)attrbufptr);
        !          1953:                };
        !          1954:                if (a & ATTR_CMN_MODTIME) {
        !          1955:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_mtime;
        !          1956:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1957:                        ++((struct timespec *)attrbufptr);
        !          1958:                };
        !          1959:                if (a & ATTR_CMN_CHGTIME) {
        !          1960:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_ctime;
        !          1961:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1962:                        ++((struct timespec *)attrbufptr);
        !          1963:                };
        !          1964:                if (a & ATTR_CMN_ACCTIME) {
        !          1965:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_atime;
        !          1966:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1967:                        ++((struct timespec *)attrbufptr);
        !          1968:                };
        !          1969:                if (a & ATTR_CMN_BKUPTIME) {
        !          1970:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_butime;
        !          1971:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
        !          1972:                        ++((struct timespec *)attrbufptr);
        !          1973:                };
        !          1974:                if (a & ATTR_CMN_FNDRINFO) {
        !          1975:             bcopy (&catInfo->nodeData.finderInfo, attrbufptr, sizeof(catInfo->nodeData.finderInfo));
        !          1976:             attrbufptr += sizeof(catInfo->nodeData.finderInfo);
        !          1977:             bcopy (&catInfo->nodeData.extFinderInfo, attrbufptr, sizeof(catInfo->nodeData.extFinderInfo));
        !          1978:             attrbufptr += sizeof(catInfo->nodeData.extFinderInfo);
        !          1979:                };
        !          1980:                if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = hp->h_meta->h_uid;
        !          1981:                if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = hp->h_meta->h_gid;
        !          1982:                if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)hp->h_meta->h_mode;
        !          1983:                if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0;                 /* XXX PPD TBC */
        !          1984:                if (a & ATTR_CMN_NAMEDATTRLIST) {
        !          1985:                        attrlength = 0;
        !          1986:             ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
        !          1987:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          1988:                        
        !          1989:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          1990:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          1991:             ++((struct attrreference *)attrbufptr);
        !          1992:                };
        !          1993:                if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = hp->h_meta->h_pflags;
        !          1994:        };
        !          1995:        
        !          1996:        *attrbufptrptr = attrbufptr;
        !          1997:        *varbufptrptr = varbufptr;
        !          1998: }
        !          1999: 
        !          2000: 
        !          2001: //     Pack the directory attributes given hfsCatalogInfo
        !          2002: void PackCatalogInfoDirAttributeBlock( struct attrlist *alist, struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr )
        !          2003: {
        !          2004:        void            *attrbufptr;
        !          2005:        attrgroup_t     a;
        !          2006:        
        !          2007:        attrbufptr      = *attrbufptrptr;
        !          2008:        a                       = alist->dirattr;
        !          2009:        
        !          2010:        if ( (catInfo->nodeData.nodeType == kCatalogFolderNode) && (a != 0) )
        !          2011:        {
        !          2012:                /* The 'link count' is faked as 1 (the parent entry and ".").  In reality it would include at least  an additional link for the ".." in each subdirectory. */
        !          2013:                if (a & ATTR_DIR_LINKCOUNT) *((u_long *)attrbufptr)++   = 2;
        !          2014:                if (a & ATTR_DIR_ENTRYCOUNT) *((u_long *)attrbufptr)++  = catInfo->nodeData.valence;
        !          2015:        };
        !          2016:        
        !          2017:        *attrbufptrptr = attrbufptr;
        !          2018: }
        !          2019: 
        !          2020: 
        !          2021: void PackDirAttributeBlock(struct attrlist *alist,
        !          2022:                                                   struct vnode *vp,
        !          2023:                                                   struct hfsCatalogInfo *catInfo,
        !          2024:                                                   void **attrbufptrptr,
        !          2025:                                                   void **varbufptrptr) {
        !          2026:     void *attrbufptr;
        !          2027: //     void *varbufptr;
        !          2028:     attrgroup_t a;
        !          2029: //     u_long attrlength;
        !          2030:        
        !          2031:        attrbufptr = *attrbufptrptr;
        !          2032: //     varbufptr = *varbufptrptr;
        !          2033:        
        !          2034:        a = alist->dirattr;
        !          2035:        if ((vp->v_type == VDIR) && (a != 0)) {
        !          2036:                /* The 'link count' is faked as 1 (the parent entry and ".").  In reality it would include at least
        !          2037:                   an additional link for the ".." in each subdirectory. */
        !          2038:                if (a & ATTR_DIR_LINKCOUNT) *((u_long *)attrbufptr)++ = 2;
        !          2039:                if (a & ATTR_DIR_ENTRYCOUNT) *((u_long *)attrbufptr)++ = catInfo->nodeData.valence;
        !          2040:        };
        !          2041:        
        !          2042:        *attrbufptrptr = attrbufptr;
        !          2043: //     *varbufptrptr = varbufptr;
        !          2044: }
        !          2045: 
        !          2046: 
        !          2047: 
        !          2048: //     Pack the file attributes from the hfsCatalogInfo for the file.
        !          2049: void PackCatalogInfoFileAttributeBlock( struct attrlist *alist, struct hfsCatalogInfo *catInfo, struct vnode *root_vp, void **attrbufptrptr, void **varbufptrptr )
        !          2050: {
        !          2051:        void                    *attrbufptr;
        !          2052:        void                    *varbufptr;
        !          2053:        attrgroup_t             a;
        !          2054:        u_long                  attrlength;
        !          2055:        ExtendedVCB             *vcb                    = VTOVCB(root_vp);
        !          2056:        
        !          2057:        attrbufptr      = *attrbufptrptr;
        !          2058:        varbufptr       = *varbufptrptr;
        !          2059:        
        !          2060:        a = alist->fileattr;
        !          2061:        if ( (catInfo->nodeData.nodeType == kCatalogFileNode) && (a != 0) )
        !          2062:        {
        !          2063:                if (a & ATTR_FILE_LINKCOUNT) *((u_long *)attrbufptr)++          = 1;            /* There ARE no hard links... */
        !          2064:                if (a & ATTR_FILE_TOTALSIZE) *((off_t *)attrbufptr)++           = (off_t)catInfo->nodeData.dataLogicalSize + (off_t)catInfo->nodeData.rsrcLogicalSize;
        !          2065:                if (a & ATTR_FILE_ALLOCSIZE) *((off_t *)attrbufptr)++           = (off_t)catInfo->nodeData.dataPhysicalSize + (off_t)catInfo->nodeData.rsrcPhysicalSize;
        !          2066:         if (a & ATTR_FILE_IOBLOCKSIZE) *((u_long *)attrbufptr)++       = (u_long)(VTOHFS(root_vp)->hfs_log_block_size);
        !          2067:                if (a & ATTR_FILE_CLUMPSIZE) *((u_long *)attrbufptr)++          = vcb->vcbClpSiz;       //XXX Yikes, this is just the vcb clump size
        !          2068:                if (a & ATTR_FILE_DEVTYPE) *((u_long *)attrbufptr)++            = (u_long)catInfo->nodeData.permissions.specialDevice;
        !          2069:                if (a & ATTR_FILE_FILETYPE) *((u_long *)attrbufptr)++           = 0;                    /* XXX PPD */
        !          2070:                if (a & ATTR_FILE_FORKCOUNT) *((u_long *)attrbufptr)++          = 2;                    /* XXX PPD */
        !          2071:                if (a & ATTR_FILE_FORKLIST)
        !          2072:                {
        !          2073:                        attrlength = 0;
        !          2074:                        ((struct attrreference *)attrbufptr)->attr_dataoffset   = 0;
        !          2075:                        ((struct attrreference *)attrbufptr)->attr_length               = attrlength;
        !          2076:                        
        !          2077:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          2078:                        varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          2079:                        ++((struct attrreference *)attrbufptr);
        !          2080:                };
        !          2081:                if (a & ATTR_FILE_DATALENGTH) *((off_t *)attrbufptr)++          = (off_t)catInfo->nodeData.dataLogicalSize;
        !          2082:                if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++       = (off_t)catInfo->nodeData.dataPhysicalSize;
        !          2083:                if (a & ATTR_FILE_DATAEXTENTS)
        !          2084:                {
        !          2085:                        bcopy(&catInfo->nodeData.dataExtents, attrbufptr, sizeof(extentrecord));
        !          2086:                        attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
        !          2087:                };
        !          2088:                if (a & ATTR_FILE_RSRCLENGTH) *((off_t *)attrbufptr)++          = (off_t)catInfo->nodeData.rsrcLogicalSize;
        !          2089:                if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++       = (off_t)catInfo->nodeData.rsrcPhysicalSize;
        !          2090:                if (a & ATTR_FILE_RSRCEXTENTS)
        !          2091:                {
        !          2092:                        bcopy(&catInfo->nodeData.rsrcExtents, attrbufptr, sizeof(extentrecord));
        !          2093:                        attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
        !          2094:                };
        !          2095:        };
        !          2096:        
        !          2097:        *attrbufptrptr  = attrbufptr;
        !          2098:        *varbufptrptr   = varbufptr;
        !          2099: }
        !          2100: 
        !          2101: 
        !          2102: void PackFileAttributeBlock(struct attrlist *alist,
        !          2103:                                                        struct vnode *vp,
        !          2104:                                                        struct hfsCatalogInfo *catInfo,
        !          2105:                                                        void **attrbufptrptr,
        !          2106:                                                        void **varbufptrptr) {
        !          2107:     struct hfsnode *hp = VTOH(vp);
        !          2108:     FCB *fcb = HTOFCB(hp);
        !          2109:     ExtendedFCB *extendedFCB;
        !          2110:     HFSPlusExtentDescriptor *parellextents;
        !          2111:        ExtendedVCB *vcb = HTOVCB(hp);
        !          2112:     Boolean isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
        !          2113:     void *attrbufptr = *attrbufptrptr;
        !          2114:     void *varbufptr = *varbufptrptr;
        !          2115:     attrgroup_t a = alist->fileattr;
        !          2116:        u_long attrlength;
        !          2117:        
        !          2118:        if ((vp->v_type == VREG) && (a != 0)) {
        !          2119:                if (a & ATTR_FILE_LINKCOUNT) *((u_long *)attrbufptr)++ = 1;             /* There ARE no hard links... */
        !          2120:                if (a & ATTR_FILE_TOTALSIZE) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataLogicalSize +
        !          2121:                                                                                                                                (off_t)catInfo->nodeData.rsrcLogicalSize;
        !          2122:                if (a & ATTR_FILE_ALLOCSIZE) {
        !          2123:                        switch (H_FORKTYPE(hp)) {
        !          2124:                          case kDataFork:
        !          2125:                                *((off_t *)attrbufptr)++ = (off_t)fcb->fcbPLen + (off_t)catInfo->nodeData.rsrcPhysicalSize;
        !          2126:                          case kRsrcFork:
        !          2127:                                *((off_t *)attrbufptr)++ = (off_t)fcb->fcbPLen + (off_t)catInfo->nodeData.dataPhysicalSize;
        !          2128:                          default:
        !          2129:                                *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataPhysicalSize +
        !          2130:                                                                                   (off_t)catInfo->nodeData.rsrcPhysicalSize;
        !          2131:                  };
        !          2132:                }; 
        !          2133:                if (a & ATTR_FILE_IOBLOCKSIZE) *((u_long *)attrbufptr)++ = hp->h_meta->h_logBlockSize;
        !          2134:                if (a & ATTR_FILE_CLUMPSIZE) *((u_long *)attrbufptr)++ = fcb->fcbClmpSize;
        !          2135:                if (a & ATTR_FILE_DEVTYPE) *((u_long *)attrbufptr)++ = (u_long)catInfo->nodeData.permissions.specialDevice;
        !          2136:                if (a & ATTR_FILE_FILETYPE) *((u_long *)attrbufptr)++ = 0;                      /* XXX PPD */
        !          2137:                if (a & ATTR_FILE_FORKCOUNT) *((u_long *)attrbufptr)++ = 2;                     /* XXX PPD */
        !          2138:                if (a & ATTR_FILE_FORKLIST) {
        !          2139:                        attrlength = 0;
        !          2140:             ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
        !          2141:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
        !          2142:                        
        !          2143:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
        !          2144:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
        !          2145:             ++((struct attrreference *)attrbufptr);
        !          2146:                };
        !          2147:                if (H_FORKTYPE(hp) == kDataFork) {
        !          2148:                        if (a & ATTR_FILE_DATALENGTH)
        !          2149: #if    MACH_NBC
        !          2150:                 if ((vp->v_type == VREG) && vp->v_vm_info && vp->v_vm_info->mapped &&
        !          2151:                     (!vp->v_vm_info->filesize)) {
        !          2152:                     *((off_t *)attrbufptr)++ = vp->v_vm_info->vnode_size;
        !          2153:                 }
        !          2154:                 else
        !          2155: #endif /* MACH_NBC */
        !          2156:                    *((off_t *)attrbufptr)++ = fcb->fcbEOF;
        !          2157:                        if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++ = fcb->fcbPLen;
        !          2158:                        if (a & ATTR_FILE_DATAEXTENTS) {
        !          2159:                            if ( ! isHFSPlus) {
        !          2160:                                /* HFS, Copy the extents from the FCB part */
        !          2161:                                int i;
        !          2162:                                HFSPlusExtentRecord extents;
        !          2163:                                for (i = 0; i < kHFSExtentDensity; ++i) {
        !          2164:                                    extents[i].startBlock = (UInt16) (fcb->fcbExtRec[i].startBlock);
        !          2165:                                    extents[i].blockCount = (UInt16) (fcb->fcbExtRec[i].blockCount);
        !          2166:                                };
        !          2167:                                bcopy ( extents, attrbufptr, sizeof(extentrecord));
        !          2168:                            } else {
        !          2169:                                /* HFSPlus, Copy the extents from the parallel extents */
        !          2170:                                extendedFCB = GetParallelFCB (HTOV(hp));
        !          2171:                                parellextents = extendedFCB->extents;
        !          2172:                                bcopy ( parellextents, attrbufptr, sizeof(extentrecord));
        !          2173:                            };
        !          2174:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
        !          2175:                        };
        !          2176:                } else {
        !          2177:                        if (a & ATTR_FILE_DATALENGTH) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataLogicalSize;
        !          2178:                        if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataPhysicalSize;
        !          2179:                        if (a & ATTR_FILE_DATAEXTENTS) {
        !          2180:                                bcopy(&catInfo->nodeData.dataExtents, attrbufptr, sizeof(extentrecord));
        !          2181:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
        !          2182:                        };
        !          2183:                };
        !          2184:                if (H_FORKTYPE(hp) == kRsrcFork) {
        !          2185:                        if (a & ATTR_FILE_RSRCLENGTH) 
        !          2186: #if    MACH_NBC
        !          2187:                 if ((vp->v_type == VREG) && vp->v_vm_info && vp->v_vm_info->mapped &&
        !          2188:                     (!vp->v_vm_info->filesize)) {
        !          2189:                     *((off_t *)attrbufptr)++ = vp->v_vm_info->vnode_size;
        !          2190:                 }
        !          2191:                 else
        !          2192: #endif /* MACH_NBC */
        !          2193:                    *((off_t *)attrbufptr)++ = fcb->fcbEOF;
        !          2194:                        if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++ = fcb->fcbPLen;
        !          2195:                        if (a & ATTR_FILE_RSRCEXTENTS) {
        !          2196:                            if ( ! isHFSPlus) {
        !          2197:                                /* HFS, Copy the extents from the FCB part */
        !          2198:                                int i;
        !          2199:                                HFSPlusExtentRecord extents;
        !          2200:                                for (i = 0; i < kHFSExtentDensity; ++i) {
        !          2201:                                    extents[i].startBlock = (UInt16) (fcb->fcbExtRec[i].startBlock);
        !          2202:                                    extents[i].blockCount = (UInt16) (fcb->fcbExtRec[i].blockCount);
        !          2203:                                };
        !          2204:                                bcopy ( extents, attrbufptr, sizeof(extentrecord));
        !          2205:                            } else {
        !          2206:                                /* HFSPlus, Copy the extents from the parallel extents */
        !          2207:                                extendedFCB = GetParallelFCB (HTOV(hp));
        !          2208:                                parellextents = extendedFCB->extents;
        !          2209:                                bcopy ( parellextents, attrbufptr, sizeof(extentrecord));
        !          2210:                            };
        !          2211:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
        !          2212:                        };
        !          2213:                } else {
        !          2214:                        if (a & ATTR_FILE_RSRCLENGTH) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.rsrcLogicalSize;
        !          2215:                        if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.rsrcPhysicalSize;
        !          2216:                        if (a & ATTR_FILE_RSRCEXTENTS) {
        !          2217:                                bcopy(&catInfo->nodeData.rsrcExtents, attrbufptr, sizeof(extentrecord));
        !          2218:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
        !          2219:                        };
        !          2220:                };
        !          2221:        };
        !          2222:        
        !          2223:        *attrbufptrptr = attrbufptr;
        !          2224:        *varbufptrptr = varbufptr;
        !          2225: }
        !          2226: 
        !          2227: #if 0
        !          2228: void PackForkAttributeBlock(struct attrlist *alist,
        !          2229:                                                        struct vnode *vp,
        !          2230:                                                        struct hfsCatalogInfo *catInfo,
        !          2231:                                                        void **attrbufptrptr,
        !          2232:                                                        void **varbufptrptr) {
        !          2233:        /* XXX PPD TBC */
        !          2234: }
        !          2235: #endif
        !          2236: 
        !          2237: 
        !          2238: //     This routine takes catInfo, and alist, as inputs and packs it into an attribute block.
        !          2239: void PackCatalogInfoAttributeBlock ( struct attrlist *alist, struct vnode *root_vp, struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr)
        !          2240: {
        !          2241:        //XXX   Preflight that alist only contains bits with fields in catInfo
        !          2242: 
        !          2243:        PackCommonCatalogInfoAttributeBlock( alist, root_vp, catInfo, attrbufptrptr, varbufptrptr );
        !          2244:        
        !          2245:        switch ( catInfo->nodeData.nodeType )
        !          2246:        {
        !          2247:                case kCatalogFolderNode:
        !          2248:                        PackCatalogInfoDirAttributeBlock( alist, catInfo, attrbufptrptr, varbufptrptr );
        !          2249:                        break;
        !          2250:                
        !          2251:                case kCatalogFileNode:
        !          2252:                        PackCatalogInfoFileAttributeBlock( alist, catInfo, root_vp, attrbufptrptr, varbufptrptr );
        !          2253:                        break;
        !          2254:          
        !          2255:                default:        /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR not being handled... */
        !          2256:                        /* XXX PPD - Panic? */
        !          2257:                        break;
        !          2258:        }
        !          2259: }
        !          2260: 
        !          2261: 
        !          2262: 
        !          2263: void PackAttributeBlock(struct attrlist *alist,
        !          2264:                                                struct vnode *vp,
        !          2265:                                                struct hfsCatalogInfo *catInfo,
        !          2266:                                                void **attrbufptrptr,
        !          2267:                                                void **varbufptrptr) {
        !          2268: 
        !          2269: //  DBG_FUNC_NAME("PackAttributeBlock");
        !          2270: 
        !          2271:        if (alist->volattr != 0) {
        !          2272:                DBG_ASSERT((vp->v_flag & VROOT) != 0);
        !          2273:                PackVolumeInfo(alist,vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2274:        } else {
        !          2275:                PackCommonAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2276:                
        !          2277:                switch (vp->v_type) {
        !          2278:                  case VDIR:
        !          2279:                        PackDirAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2280:                        break;
        !          2281:                        
        !          2282:                  case VREG:
        !          2283:           /* case VCPLX: */                    /* XXX PPD TBC */
        !          2284:                        PackFileAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2285:                        break;
        !          2286:                  
        !          2287:        #if 0                                                   /* XXX PPD TBC */
        !          2288:                  case VFORK:
        !          2289:                        PackForkAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2290:                        break;
        !          2291:        #endif
        !          2292:                  
        !          2293:                  /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
        !          2294:                     not being handled...
        !          2295:                   */
        !          2296:                  default:
        !          2297:                        /* XXX PPD - Panic? */
        !          2298:                        break;
        !          2299:                };
        !          2300:        };
        !          2301: };
        !          2302: 
        !          2303: 
        !          2304: 
        !          2305: void UnpackVolumeAttributeBlock(struct attrlist *alist,
        !          2306:                                                                struct vnode *root_vp,
        !          2307:                                                                ExtendedVCB *vcb,
        !          2308:                                                                void **attrbufptrptr,
        !          2309:                                                                void **varbufptrptr) {
        !          2310:        void *attrbufptr = *attrbufptrptr;
        !          2311:        attrgroup_t a;
        !          2312:        text_encoding_t nameEncoding;
        !          2313:        
        !          2314:     if ((alist->commonattr == 0) && (alist->volattr == 0)) {
        !          2315:         return;                /* Get out without dirtying the VCB */
        !          2316:     };
        !          2317: 
        !          2318:     VCB_LOCK(vcb);
        !          2319: 
        !          2320:        a = alist->commonattr;
        !          2321:        
        !          2322:        if (a & ATTR_CMN_SCRIPT) {
        !          2323:                /* XXX PPD No use for this info right now... */
        !          2324:                nameEncoding = *(((text_encoding_t *)attrbufptr)++);
        !          2325: #if DIAGNOSTIC
        !          2326:                a &= ~ATTR_CMN_SCRIPT;
        !          2327: #endif
        !          2328:        };
        !          2329:        if (a & ATTR_CMN_CRTIME) {
        !          2330:                /*
        !          2331:                 * HFS Plus stores the volume create date in *local*
        !          2332:                 * time in the volume header. So don't set the create
        !          2333:                 * date in the vcb. Set the root's crtime instead.
        !          2334:                 */
        !          2335:                if (vcb->vcbSigWord == kHFSPlusSigWord) {
        !          2336:                        VTOH(root_vp)->h_meta->h_crtime =
        !          2337:                                        (UInt32)((struct timespec *)attrbufptr)->tv_sec;
        !          2338:                } else {
        !          2339:                        vcb->vcbCrDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2340:                }
        !          2341:                ++((struct timespec *)attrbufptr);
        !          2342: #if DIAGNOSTIC
        !          2343:                a &= ~ATTR_CMN_CRTIME;
        !          2344: #endif
        !          2345:        };
        !          2346:        if (a & ATTR_CMN_MODTIME) {
        !          2347:                vcb->vcbLsMod = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2348:                ++((struct timespec *)attrbufptr);
        !          2349: #if DIAGNOSTIC
        !          2350:                a &= ~ATTR_CMN_MODTIME;
        !          2351: #endif
        !          2352:        };
        !          2353:        if (a & ATTR_CMN_BKUPTIME) {
        !          2354:                vcb->vcbVolBkUp = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2355:                ++((struct timespec *)attrbufptr);
        !          2356: #if DIAGNOSTIC
        !          2357:                a &= ~ATTR_CMN_BKUPTIME;
        !          2358: #endif
        !          2359:        };
        !          2360:        if (a & ATTR_CMN_FNDRINFO) {
        !          2361:                bcopy (attrbufptr, &vcb->vcbFndrInfo, sizeof(vcb->vcbFndrInfo));
        !          2362:                attrbufptr += sizeof(vcb->vcbFndrInfo);
        !          2363: #if DIAGNOSTIC
        !          2364:                a &= ~ATTR_CMN_FNDRINFO;
        !          2365: #endif
        !          2366:        };
        !          2367:        
        !          2368:        DBG_ASSERT(a == 0);                             /* All common attributes for volumes must've been handled by now... */
        !          2369: 
        !          2370:        a = alist->volattr & ~ATTR_VOL_INFO;
        !          2371:        if (a & ATTR_VOL_NAME) {
        !          2372:         copystr(((char *)attrbufptr) + *((u_long *)attrbufptr), vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
        !          2373:         attrbufptr += sizeof(struct attrreference);
        !          2374: #if DIAGNOSTIC
        !          2375:                a &= ~ATTR_VOL_NAME;
        !          2376: #endif
        !          2377:        };
        !          2378:        
        !          2379:        DBG_ASSERT(a == 0);                             /* All common attributes for volumes must've been handled by now... */
        !          2380: 
        !          2381:     vcb->vcbFlags |= 0xFF00;           // Mark the VCB dirty
        !          2382: 
        !          2383:     VCB_UNLOCK(vcb);
        !          2384: }
        !          2385: 
        !          2386: 
        !          2387: void UnpackCommonAttributeBlock(struct attrlist *alist,
        !          2388:                                                                struct vnode *vp,
        !          2389:                                                                struct hfsCatalogInfo *catInfo,
        !          2390:                                                                void **attrbufptrptr,
        !          2391:                                                                void **varbufptrptr) {
        !          2392:        struct hfsnode *hp = VTOH(vp);
        !          2393:     void *attrbufptr;
        !          2394:     attrgroup_t a;
        !          2395:        
        !          2396:        attrbufptr = *attrbufptrptr;
        !          2397: 
        !          2398:     DBG_ASSERT(catInfo != NULL);
        !          2399:        
        !          2400:        a = alist->commonattr;
        !          2401:        if (a & ATTR_CMN_SCRIPT) {
        !          2402:                /* XXX PPD No use for this info right now... */
        !          2403:                ++((text_encoding_t *)attrbufptr);
        !          2404: #if DIAGNOSTIC
        !          2405:                a &= ~ATTR_CMN_SCRIPT;
        !          2406: #endif
        !          2407:        };
        !          2408:        if (a & ATTR_CMN_CRTIME) {
        !          2409:                catInfo->nodeData.createDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2410:                VTOH(vp)->h_meta->h_crtime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
        !          2411:                ++((struct timespec *)attrbufptr);
        !          2412: #if DIAGNOSTIC
        !          2413:                a &= ~ATTR_CMN_CRTIME;
        !          2414: #endif
        !          2415:        };
        !          2416:        if (a & ATTR_CMN_MODTIME) {
        !          2417:                catInfo->nodeData.contentModDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2418:                VTOH(vp)->h_meta->h_mtime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
        !          2419:                ++((struct timespec *)attrbufptr);
        !          2420: #if DIAGNOSTIC
        !          2421:                a &= ~ATTR_CMN_MODTIME;
        !          2422: #endif
        !          2423:        };
        !          2424:        if (a & ATTR_CMN_CHGTIME) {
        !          2425:                catInfo->nodeData.attributeModDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2426:                VTOH(vp)->h_meta->h_ctime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
        !          2427:                ++((struct timespec *)attrbufptr);
        !          2428: #if DIAGNOSTIC
        !          2429:                a &= ~ATTR_CMN_CHGTIME;
        !          2430: #endif
        !          2431:        };
        !          2432:        if (a & ATTR_CMN_ACCTIME) {
        !          2433:                catInfo->nodeData.accessDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2434:                VTOH(vp)->h_meta->h_atime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
        !          2435:                ++((struct timespec *)attrbufptr);
        !          2436: #if DIAGNOSTIC
        !          2437:                a &= ~ATTR_CMN_ACCTIME;
        !          2438: #endif
        !          2439:        };
        !          2440:        if (a & ATTR_CMN_BKUPTIME) {
        !          2441:                catInfo->nodeData.backupDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
        !          2442:                VTOH(vp)->h_meta->h_butime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
        !          2443:                ++((struct timespec *)attrbufptr);
        !          2444: #if DIAGNOSTIC
        !          2445:                a &= ~ATTR_CMN_BKUPTIME;
        !          2446: #endif
        !          2447:        };
        !          2448:        if (a & ATTR_CMN_FNDRINFO) {
        !          2449:                bcopy (attrbufptr, &catInfo->nodeData.finderInfo, sizeof(catInfo->nodeData.finderInfo));
        !          2450:                attrbufptr += sizeof(catInfo->nodeData.finderInfo);
        !          2451:                bcopy (attrbufptr, &catInfo->nodeData.extFinderInfo, sizeof(catInfo->nodeData.extFinderInfo));
        !          2452:                attrbufptr += sizeof(catInfo->nodeData.extFinderInfo);
        !          2453: #if DIAGNOSTIC
        !          2454:                a &= ~ATTR_CMN_FNDRINFO;
        !          2455: #endif
        !          2456:        };
        !          2457:        if (a & ATTR_CMN_OWNERID) {
        !          2458:         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
        !          2459:                        u_int32_t uid = (u_int32_t)*((uid_t *)attrbufptr)++;
        !          2460:                        if (uid != (uid_t)VNOVAL)
        !          2461:                                hp->h_meta->h_uid = uid;        /* catalog will get updated by hfs_chown() */
        !          2462:         }
        !          2463:                else {
        !          2464:             ((uid_t *)attrbufptr)++;
        !          2465:                }
        !          2466: #if DIAGNOSTIC
        !          2467:                a &= ~ATTR_CMN_OWNERID;
        !          2468: #endif
        !          2469:        };
        !          2470:        if (a & ATTR_CMN_GRPID) {
        !          2471:         u_int32_t gid = (u_int32_t)*((gid_t *)attrbufptr)++;
        !          2472:         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
        !          2473:             if (gid != (gid_t)VNOVAL)
        !          2474:                 hp->h_meta->h_gid = gid;                                       /* catalog will get updated by hfs_chown() */
        !          2475:         };
        !          2476: #if DIAGNOSTIC
        !          2477:                a &= ~ATTR_CMN_GRPID;
        !          2478: #endif
        !          2479:        };
        !          2480:        if (a & ATTR_CMN_ACCESSMASK) {
        !          2481:         u_int16_t mode = (u_int16_t)*((u_long *)attrbufptr)++;
        !          2482:         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
        !          2483:             if (mode != (mode_t)VNOVAL) {
        !          2484:                 hp->h_meta->h_mode &= ~ALLPERMS;
        !          2485:                 hp->h_meta->h_mode |= (mode & ALLPERMS);       /* catalog will get updated by hfs_chmod() */
        !          2486:             }
        !          2487:         };
        !          2488: #if DIAGNOSTIC
        !          2489:                a &= ~ATTR_CMN_ACCESSMASK;
        !          2490: #endif
        !          2491:        };
        !          2492:        if (a & ATTR_CMN_FLAGS) {
        !          2493:                u_long flags = *((u_long *)attrbufptr)++;
        !          2494:         /* Flags are settable only on HFS+ volumes.  A special exception is made for the IMMUTABLE
        !          2495:            flags (SF_IMMUTABLE and UF_IMMUTABLE), which can be set on HFS volumes as well: */
        !          2496:         if ((VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) ||
        !          2497:             ((VTOVCB(vp)->vcbSigWord == kHFSSigWord) && ((flags & ~IMMUTABLE) == 0))) {
        !          2498:             if (flags != (u_long)VNOVAL) {
        !          2499:                 hp->h_meta->h_pflags = flags;                          /* catalog will get updated by hfs_chflags */
        !          2500:             };
        !          2501:         };
        !          2502: #if DIAGNOSTIC
        !          2503:                a &= ~ATTR_CMN_FLAGS;
        !          2504: #endif
        !          2505:        };
        !          2506: 
        !          2507: #if DIAGNOSTIC
        !          2508:        if (a != 0) {
        !          2509:                DEBUG_BREAK_MSG(("UnpackCommonAttributes: unhandled bit: 0x%08X\n", a));
        !          2510:        };
        !          2511: #endif
        !          2512: 
        !          2513:        *attrbufptrptr = attrbufptr;
        !          2514: //     *varbufptrptr = varbufptr;
        !          2515: }
        !          2516: 
        !          2517: 
        !          2518: 
        !          2519: #if 0
        !          2520: void UnpackDirAttributeBlock(struct attrlist *alist,
        !          2521:                                                         struct vnode *vp,
        !          2522:                                                         struct hfsCatalogInfo *catInfo,
        !          2523:                                                         void **attrbufptrptr,
        !          2524:                                                         void **varbufptrptr) {
        !          2525:     void *attrbufptr;
        !          2526:     void *varbufptr;
        !          2527:     attrgroup_t a;
        !          2528:        u_long attrlength;
        !          2529:        
        !          2530:        attrbufptr = *attrbufptrptr;
        !          2531:        varbufptr = *varbufptrptr;
        !          2532:        
        !          2533:        /* XXX PPD TBC */
        !          2534:        
        !          2535:        *attrbufptrptr = attrbufptr;
        !          2536:        *varbufptrptr = varbufptr;
        !          2537: }
        !          2538: #endif
        !          2539: 
        !          2540: 
        !          2541: 
        !          2542: #if 0
        !          2543: void UnpackFileAttributeBlock(struct attrlist *alist,
        !          2544:                                                          struct vnode *vp,
        !          2545:                                                          struct hfsCatalogInfo *catInfo,
        !          2546:                                                          void **attrbufptrptr,
        !          2547:                                                          void **varbufptrptr) {
        !          2548:     void *attrbufptr;
        !          2549:     void *varbufptr;
        !          2550:     attrgroup_t a;
        !          2551:        u_long attrlength;
        !          2552:        
        !          2553:        attrbufptr = *attrbufptrptr;
        !          2554:        varbufptr = *varbufptrptr;
        !          2555:        
        !          2556:        /* XXX PPD TBC */
        !          2557:        
        !          2558:        *attrbufptrptr = attrbufptr;
        !          2559:        *varbufptrptr = varbufptr;
        !          2560: }
        !          2561: #endif
        !          2562: 
        !          2563: 
        !          2564: 
        !          2565: #if 0
        !          2566: void UnpackForkAttributeBlock(struct attrlist *alist,
        !          2567:                                                        struct vnode *vp,
        !          2568:                                                        struct hfsCatalogInfo *catInfo,
        !          2569:                                                        void **attrbufptrptr,
        !          2570:                                                        void **varbufptrptr) {
        !          2571:     void *attrbufptr;
        !          2572:     void *varbufptr;
        !          2573:     attrgroup_t a;
        !          2574:        u_long attrlength;
        !          2575:        
        !          2576:        attrbufptr = *attrbufptrptr;
        !          2577:        varbufptr = *varbufptrptr;
        !          2578:        
        !          2579:        /* XXX PPD TBC */
        !          2580:        
        !          2581:        *attrbufptrptr = attrbufptr;
        !          2582:        *varbufptrptr = varbufptr;
        !          2583: }
        !          2584: #endif
        !          2585: 
        !          2586: 
        !          2587: 
        !          2588: void UnpackAttributeBlock(struct attrlist *alist,
        !          2589:                                                  struct vnode *vp,
        !          2590:                                                  struct hfsCatalogInfo *catInfo,
        !          2591:                                                  void **attrbufptrptr,
        !          2592:                                                  void **varbufptrptr) {
        !          2593: 
        !          2594: 
        !          2595:        if (alist->volattr != 0) {
        !          2596:                UnpackVolumeAttributeBlock(alist, vp, VTOVCB(vp), attrbufptrptr, varbufptrptr);
        !          2597:                return;
        !          2598:        };
        !          2599:        
        !          2600:        /* We're dealing with a vnode object here: */
        !          2601:        UnpackCommonAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2602:        
        !          2603: #if 0
        !          2604:        switch (vp->v_type) {
        !          2605:          case VDIR:
        !          2606:                UnpackDirAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2607:                break;
        !          2608: 
        !          2609:          case VREG:
        !          2610:    /* case VCPLX: */                   /* XXX PPD TBC */
        !          2611:                UnpackFileAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2612:                break;
        !          2613: 
        !          2614:          case VFORK:
        !          2615:                UnpackForkAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
        !          2616:                break;
        !          2617: 
        !          2618:          /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
        !          2619:             not being handled...
        !          2620:           */
        !          2621:          default:
        !          2622:                /* XXX PPD - Panic? */
        !          2623:                break;
        !          2624:        };
        !          2625: #endif
        !          2626: 
        !          2627: };
        !          2628: 
        !          2629: 
        !          2630: unsigned long BestBlockSizeFit(unsigned long allocationBlockSize,
        !          2631:                                unsigned long blockSizeLimit,
        !          2632:                                unsigned long baseMultiple) {
        !          2633:     /*
        !          2634:        Compute the optimal (largest) block size (no larger than allocationBlockSize) that is less than the
        !          2635:        specified limit but still an even multiple of the baseMultiple.
        !          2636:      */
        !          2637:     int baseBlockCount, blockCount;
        !          2638:     unsigned long trialBlockSize;
        !          2639: 
        !          2640:     if (allocationBlockSize % baseMultiple != 0) {
        !          2641:         /*
        !          2642:            Whoops: the allocation blocks aren't even multiples of the specified base:
        !          2643:            no amount of dividing them into even parts will be a multiple, either then!
        !          2644:         */
        !          2645:         return 512;            /* Hope for the best */
        !          2646:     };
        !          2647: 
        !          2648:     /* Try the obvious winner first, to prevent 12K allocation blocks, for instance,
        !          2649:        from being handled as two 6K logical blocks instead of 3 4K logical blocks.
        !          2650:        Even though the former (the result of the loop below) is the larger allocation
        !          2651:        block size, the latter is more efficient: */
        !          2652:     if (allocationBlockSize % PAGE_SIZE == 0) return PAGE_SIZE;
        !          2653: 
        !          2654:     /* No clear winner exists: pick the largest even fraction <= MAXBSIZE: */
        !          2655:     baseBlockCount = allocationBlockSize / baseMultiple;                               /* Now guaranteed to be an even multiple */
        !          2656: 
        !          2657:     for (blockCount = baseBlockCount; blockCount > 0; --blockCount) {
        !          2658:         trialBlockSize = blockCount * baseMultiple;
        !          2659:         if (allocationBlockSize % trialBlockSize == 0) {                               /* An even multiple? */
        !          2660:             if ((trialBlockSize <= blockSizeLimit) &&
        !          2661:                 (trialBlockSize % baseMultiple == 0)) {
        !          2662:                 return trialBlockSize;
        !          2663:             };
        !          2664:         };
        !          2665:     };
        !          2666: 
        !          2667:     /* Note: we should never get here, since blockCount = 1 should always work,
        !          2668:        but this is nice and safe and makes the compiler happy, too ... */
        !          2669:     return 512;
        !          2670: }
        !          2671: 
        !          2672: 
        !          2673: /*
        !          2674:  * Map HFS Common errors (negative) to BSD error codes (positive).
        !          2675:  * Positive errors (ie BSD errors) are passed through unchanged.
        !          2676:  */
        !          2677: short MacToVFSError(OSErr err)
        !          2678: {
        !          2679:     if (err >= 0) {
        !          2680:         if (err > 0) {
        !          2681:             DBG_ERR(("MacToVFSError: passing error #%d unchanged...\n", err));
        !          2682:         };
        !          2683:         return err;
        !          2684:     };
        !          2685: 
        !          2686:     if (err != 0) {
        !          2687:         DBG_ERR(("MacToVFSError: mapping error code %d...\n", err));
        !          2688:     };
        !          2689:     
        !          2690:        switch (err) {
        !          2691:          case dirFulErr:                                                       /*    -33 */
        !          2692:          case dskFulErr:                                                       /*    -34 */
        !          2693:          case btNoSpaceAvail:                                          /* -32733 */
        !          2694:          case fxOvFlErr:                                                       /* -32750 */
        !          2695:                return ENOSPC;                                                  /*    +28 */
        !          2696: 
        !          2697:          case btBadNode:                                                       /* -32731 */
        !          2698:          case ioErr:                                                           /*   -36 */
        !          2699:                return EIO;                                                             /*    +5 */
        !          2700: 
        !          2701:          case badMDBErr:                                                       /*   -60 */
        !          2702:          case fnOpnErr:                                                        /*   -38 */
        !          2703:                return EBADF;                                                   /*    +9 */
        !          2704: 
        !          2705:          case mFulErr:                                                         /*   -41 */
        !          2706:          case memFullErr:                                                      /*  -108 */
        !          2707:                return ENOMEM;                                                  /*   +12 */
        !          2708: 
        !          2709:          case tmfoErr:                                                         /*   -42 */
        !          2710:                /* Consider EMFILE (Too many open files, 24)? */        
        !          2711:                return ENFILE;                                                  /*   +23 */
        !          2712: 
        !          2713:          case nsvErr:                                                          /*   -35 */
        !          2714:          case fnfErr:                                                          /*   -43 */
        !          2715:          case dirNFErr:                                                        /*  -120 */
        !          2716:          case fidNotFound:                                                     /* -1300 */
        !          2717:                return ENOENT;                                                  /*    +2 */
        !          2718: 
        !          2719:          case wPrErr:                                                          /*   -44 */
        !          2720:          case vLckdErr:                                                        /*   -46 */
        !          2721:          case fsDSIntErr:                                                      /*  -127 */
        !          2722:                return EROFS;                                                   /*   +30 */
        !          2723: 
        !          2724:          case opWrErr:                                                         /*   -49 */
        !          2725:          case fLckdErr:                                                        /*   -45 */
        !          2726:                return EACCES;                                                  /*   +13 */
        !          2727: 
        !          2728:          case permErr:                                                         /*   -54 */
        !          2729:          case wrPermErr:                                                       /*   -61 */
        !          2730:                return EPERM;                                                   /*    +1 */
        !          2731: 
        !          2732:          case fBsyErr:                                                         /*   -47 */
        !          2733:                return EBUSY;                                                   /*   +16 */
        !          2734: 
        !          2735:          case dupFNErr:                                                        /*    -48 */
        !          2736:          case fidExists:                                                       /*  -1301 */
        !          2737:          case cmExists:                                                        /* -32718 */
        !          2738:          case btExists:                                                        /* -32734 */
        !          2739:                return EEXIST;                                                  /*    +17 */
        !          2740: 
        !          2741:          case rfNumErr:                                                        /*   -51 */
        !          2742:                return EBADF;                                                   /*    +9 */
        !          2743: 
        !          2744:          case notAFileErr:                                                     /* -1302 */
        !          2745:                return EISDIR;                                                  /*   +21 */
        !          2746: 
        !          2747:          case cmNotFound:                                                      /* -32719 */
        !          2748:          case btNotFound:                                                      /* -32735 */    
        !          2749:                return ENOENT;                                                  /*     28 */
        !          2750: 
        !          2751:          case cmNotEmpty:                                                      /* -32717 */
        !          2752:                return ENOTEMPTY;                                               /*     66 */
        !          2753: 
        !          2754:          case cmFThdDirErr:                                            /* -32714 */
        !          2755:                return EISDIR;                                                  /*     21 */
        !          2756: 
        !          2757:          case fxRangeErr:                                                      /* -32751 */
        !          2758:                return EIO;                                                             /*      5 */
        !          2759: 
        !          2760:          case bdNamErr:                                                        /*   -37 */
        !          2761:                return ENAMETOOLONG;                                    /*    63 */
        !          2762: 
        !          2763:          case eofErr:                                                          /*   -39 */
        !          2764:          case posErr:                                                          /*   -40 */
        !          2765:          case paramErr:                                                        /*   -50 */
        !          2766:          case badMovErr:                                                       /*  -122 */
        !          2767:          case sameFileErr:                                                     /* -1306 */
        !          2768:          case badFidErr:                                                       /* -1307 */
        !          2769:          case fileBoundsErr:                                           /* -1309 */
        !          2770:                return EINVAL;                                                  /*   +22 */
        !          2771: 
        !          2772:          default:
        !          2773:                DBG_UTILS(("Unmapped MacOS error: %d\n", err));
        !          2774:                return EIO;                                                             /*   +5 */
        !          2775:        }
        !          2776: }
        !          2777: 
        !          2778: 
        !          2779: /*
        !          2780:  * All of our debugging functions
        !          2781:  */
        !          2782: 
        !          2783: #if DIAGNOSTIC
        !          2784: 
        !          2785: void debug_vn_status (char* introStr, struct vnode *vn)
        !          2786: {
        !          2787:     DBG_VOP(("%s:\t",introStr));
        !          2788:     if (vn != NULL)
        !          2789:       {
        !          2790:         if (vn->v_tag != VT_HFS)
        !          2791:           {
        !          2792:             DBG_VOP(("NON-HFS VNODE Ox%08lX\n", (unsigned long)vn));
        !          2793:           }
        !          2794:         else if(vn->v_tag==VT_HFS && (vn->v_data==NULL || VTOH((vn))->h_valid != HFS_VNODE_MAGIC))
        !          2795:           {
        !          2796:             DBG_VOP(("BAD VNODE PRIVATE DATA!!!!\n"));
        !          2797:           }
        !          2798:         else
        !          2799:           {
        !          2800:             DBG_VOP(("r: %d & ", vn->v_usecount));
        !          2801:             if (lockstatus(&VTOH(vn)->h_lock))
        !          2802:               {
        !          2803:                 DBG_VOP_CONT(("is L\n"));
        !          2804:               }
        !          2805:             else
        !          2806:               {
        !          2807:                 DBG_VOP_CONT(("is U\n"));
        !          2808:               }
        !          2809:           }
        !          2810:       }
        !          2811:     else
        !          2812:       {
        !          2813:         DBG_VOP(("vnode is NULL\n"));
        !          2814:       };
        !          2815: }
        !          2816: 
        !          2817: void debug_vn_print (char* introStr, struct vnode *vn)
        !          2818: {
        !          2819: //  DBG_FUNC_NAME("DBG_VN_PRINT");
        !          2820:     DBG_ASSERT (vn != NULL);
        !          2821:     DBG_VFS(("%s: ",introStr));
        !          2822:     DBG_VFS_CONT(("vnode: 0x%x is a ", (uint)vn));
        !          2823:     switch (vn->v_tag)
        !          2824:       {
        !          2825:         case VT_UFS:
        !          2826:             DBG_VFS_CONT(("%s","UFS"));
        !          2827:             break;
        !          2828:         case VT_HFS:
        !          2829:             DBG_VFS_CONT(("%s","HFS"));
        !          2830:             break;
        !          2831:         default:
        !          2832:             DBG_VFS_CONT(("%s","UNKNOWN"));
        !          2833:             break;
        !          2834:       }
        !          2835: 
        !          2836:     DBG_VFS_CONT((" vnode\n"));
        !          2837:     if (vn->v_tag==VT_HFS)
        !          2838:       {
        !          2839:         if (vn->v_data==NULL)
        !          2840:           {
        !          2841:             DBG_VFS(("BAD VNODE PRIVATE DATA!!!!\n"));
        !          2842:           }
        !          2843:         else
        !          2844:           {
        !          2845:             DBG_VFS(("     Name: %s Id: %ld ",H_NAME(VTOH(vn)), H_FILEID(VTOH(vn))));
        !          2846:           }
        !          2847:       }
        !          2848:     else
        !          2849:         DBG_VFS(("     "));
        !          2850: 
        !          2851:     DBG_VFS_CONT(("Refcount: %d\n", vn->v_usecount));
        !          2852:     if (VOP_ISLOCKED(vn))
        !          2853:       {
        !          2854:         DBG_VFS(("     The vnode is locked\n"));
        !          2855:       }
        !          2856:     else
        !          2857:       {
        !          2858:         DBG_VFS(("     The vnode is not locked\n"));
        !          2859:       }
        !          2860: }
        !          2861: 
        !          2862: void debug_rename_test_locks (char*                    introStr,
        !          2863:                             struct vnode       *fvp,
        !          2864:                             struct vnode       *fdvp,
        !          2865:                             struct vnode       *tvp,
        !          2866:                             struct vnode       *tdvp,
        !          2867:                             int                                fstatus,
        !          2868:                             int                                fdstatus,
        !          2869:                             int                                tstatus,
        !          2870:                             int                                tdstatus
        !          2871: )
        !          2872: {
        !          2873:     DBG_VOP(("\t%s: ", introStr));
        !          2874:     if (fvp) {if(lockstatus(&VTOH(fvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
        !          2875:     if (fdvp) {if(lockstatus(&VTOH(fdvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
        !          2876:     if (tvp) {if(lockstatus(&VTOH(tvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
        !          2877:     if (tdvp) {if(lockstatus(&VTOH(tdvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
        !          2878:     DBG_VFS_CONT(("\n"));
        !          2879: 
        !          2880:     if (fvp) {
        !          2881:         if (lockstatus(&VTOH(fvp)->h_lock)) {
        !          2882:             if (fstatus==VOPDBG_UNLOCKED) {
        !          2883:                 DBG_VOP(("\tfvp should be NOT LOCKED and it is\n"));
        !          2884:             }
        !          2885:         } else if (fstatus == VOPDBG_LOCKED) {
        !          2886:             DBG_VOP(("\tfvp should be LOCKED and it isnt\n"));
        !          2887:         }
        !          2888:     }
        !          2889: 
        !          2890:     if (fdvp) {
        !          2891:         if (lockstatus(&VTOH(fdvp)->h_lock)) {
        !          2892:             if (fdstatus==VOPDBG_UNLOCKED) {
        !          2893:                 DBG_VOP(("\tfdvp should be NOT LOCKED and it is\n"));
        !          2894:             }
        !          2895:         } else if (fdstatus == VOPDBG_LOCKED) {
        !          2896:             DBG_VOP(("\tfdvp should be LOCKED and it isnt\n"));
        !          2897:         }
        !          2898:     }
        !          2899: 
        !          2900:     if (tvp) {
        !          2901:         if (lockstatus(&VTOH(tvp)->h_lock)) {
        !          2902:             if (tstatus==VOPDBG_UNLOCKED) {
        !          2903:                 DBG_VOP(("\ttvp should be NOT LOCKED and it is\n"));
        !          2904:             }
        !          2905:         } else if (tstatus == VOPDBG_LOCKED) {
        !          2906:             DBG_VOP(("\ttvp should be LOCKED and it isnt\n"));
        !          2907:         }
        !          2908:     }
        !          2909: 
        !          2910:     if (tdvp) {
        !          2911:         if (lockstatus(&VTOH(tdvp)->h_lock)) {
        !          2912:             if (tdstatus==VOPDBG_UNLOCKED) {
        !          2913:                 DBG_VOP(("\ttdvp should be NOT LOCKED and it is\n"));
        !          2914:             }
        !          2915:         } else if (tdstatus == VOPDBG_LOCKED) {
        !          2916:             DBG_VOP(("\ttdvp should be LOCKED and it isnt\n"));
        !          2917: 
        !          2918:         }
        !          2919:     }
        !          2920: 
        !          2921: }
        !          2922: #endif /* DIAGNOSTIC */
        !          2923: 
        !          2924: 
        !          2925: #if DIAGNOSTIC
        !          2926: void debug_check_buffersizes(struct vnode *vp, struct hfsnode *hp, struct buf *bp) {
        !          2927:     DBG_ASSERT(bp->b_validoff == 0);
        !          2928:     DBG_ASSERT(bp->b_dirtyoff == 0);
        !          2929:     if (bp->b_lblkno < hp->h_uniformblocksizestart) {
        !          2930:         DBG_ASSERT((bp->b_bcount == MAXLOGBLOCKSIZE) ||
        !          2931:                    (bp->b_bcount == LogicalBlockSize(hp, bp->b_lblkno)) ||
        !          2932:                    ((bp->b_bcount % 512 == 0) &&
        !          2933:                     (bp->b_validend > 0) &&
        !          2934:                     (bp->b_dirtyend >= 0) &&                                                   /* Could be partial block due to file growth */
        !          2935:                     (bp->b_bcount < LogicalBlockSize(hp, bp->b_lblkno))));
        !          2936:     } else {
        !          2937:         DBG_ASSERT((bp->b_bcount == hp->h_meta->h_logBlockSize) ||
        !          2938:                    ((bp->b_bcount % 512 == 0) &&
        !          2939:                     (bp->b_validend > 0) &&
        !          2940:                     (bp->b_dirtyend > 0) &&
        !          2941:                     (bp->b_bcount < hp->h_meta->h_logBlockSize)));
        !          2942:     };
        !          2943: 
        !          2944:     if (bp->b_validend == 0) {
        !          2945:         DBG_ASSERT(bp->b_dirtyend == 0);
        !          2946:     } else {
        !          2947:         DBG_ASSERT(bp->b_validend == bp->b_bcount);
        !          2948:         DBG_ASSERT(bp->b_dirtyend <= bp->b_bcount);
        !          2949:     };
        !          2950: 
        !          2951:     if ((bp->b_lblkno == 0x21) || (bp->b_lblkno == 0x22)) DBG_ASSERT((hp->h_uniformblocksizestart > 0x21) || (bp->b_bcount != MAXLOGBLOCKSIZE));
        !          2952: }
        !          2953: 
        !          2954: 
        !          2955: void debug_check_blocksizes(struct vnode *vp) {
        !          2956:     struct hfsnode *hp = VTOH(vp);
        !          2957:     struct buf *bp;
        !          2958: 
        !          2959:     if (vp->v_flag & VSYSTEM) return;
        !          2960: 
        !          2961:     for (bp = vp->v_cleanblkhd.lh_first; bp != NULL; bp = bp->b_vnbufs.le_next) {
        !          2962:         debug_check_buffersizes(vp, hp, bp);
        !          2963:     };
        !          2964: 
        !          2965:     for (bp = vp->v_dirtyblkhd.lh_first; bp != NULL; bp = bp->b_vnbufs.le_next) {
        !          2966:         debug_check_buffersizes(vp, hp, bp);
        !          2967:     };
        !          2968: }
        !          2969: 
        !          2970: #endif /* DIAGNOSTIC */

unix.superglobalmegacorp.com

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