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