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

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 */
1.1.1.2 ! root      795:             if ((dvp != NULL) && (dvp->v_type == VCPLX)) {
1.1       root      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 */
1.1.1.2 ! root      819:             if (++fm->h_usecount == 0)
        !           820:                panic("hfsGet: h_usecount");
1.1       root      821:             lockmgr(&fm->h_fmetalock, LK_EXCLUSIVE, (struct slock *)0, CURRENT_PROC);
                    822:             hp->h_relative = cp;
                    823:             if (forkType == kDataFork)                                 /* Init downlink */
                    824:                 VTOH(cp)->h_relative = vp;
                    825:             if (fm->h_fork == NULL)
                    826:                 fm->h_fork = vp;
                    827:             else {
                    828:                 hp->h_sibling = fm->h_fork;
                    829:                 VTOH(fm->h_fork)->h_sibling = vp;
                    830:             }
                    831:             /* Increment the complex usecount, to make sure it doesnt go inactive on us */
                    832:             VREF(cp);
                    833:             if  (unlockPar)
                    834:                 VPUT(cp);
                    835:           }
                    836:         MALLOC(xfcb, struct vfsFCB *, sizeof(struct vfsFCB), M_HFSNODE, M_WAITOK);
                    837:         bzero(xfcb, sizeof(struct vfsFCB));
                    838:       }
                    839: 
                    840:     hp->h_xfcb = xfcb;
                    841:     hp->h_meta = fm;
                    842: 
                    843:     /*
                    844:      * Finish filling in the record
                    845:      */
                    846:     if (xfcb) {
                    847:         xfcb->fcb_vp = vp;                                     /* Make FCBTOV work */
                    848:     }
                    849: 
                    850:     /*
                    851:      * Copy the Catalog info to the new macnode
                    852:      */
                    853:     CopyCatalogToHFSNode(catInfo, hp);
                    854: 
                    855: 
                    856:        /* Lets do some testing here */
                    857:     DBG_ASSERT(hp->h_meta);
                    858:     DBG_ASSERT(VTOH(vp)==hp);
                    859:     DBG_ASSERT(HTOV(hp)==vp);
                    860:     if (hp->h_xfcb) {
                    861:         DBG_ASSERT(VTOH(vp)->h_xfcb->fcb_vp == vp);
                    862:         DBG_ASSERT(FCBTOV(&hp->h_xfcb->fcb_fcb) == vp);
                    863:         DBG_ASSERT(FCBTOH(&hp->h_xfcb->fcb_fcb) == hp);
                    864:         DBG_ASSERT(&hp->h_xfcb->fcb_fcb == VTOFCB(vp));
                    865:         DBG_ASSERT(&hp->h_xfcb->fcb_fcb == HTOFCB(hp));
                    866:         DBG_ASSERT(VTOVCB(vp) == FCBTOVCB(&hp->h_xfcb->fcb_fcb));
                    867:     }
                    868:     if (hp->h_sibling) {
                    869:         DBG_ASSERT(VTOH(hp->h_sibling)->h_sibling == vp);
                    870:         DBG_ASSERT(VTOH(hp->h_sibling)->h_relative == hp->h_relative);
                    871:         DBG_ASSERT(VTOH(hp->h_sibling)->h_meta == hp->h_meta);
                    872:     }
                    873:     if (H_FORKTYPE(hp) == kDirCmplx)   {
                    874:         DBG_ASSERT(hp->h_meta->h_usecount==0);
                    875:     }
                    876:        else {
                    877:         DBG_ASSERT(hp->h_meta->h_usecount>0 && hp->h_meta->h_usecount<=2);
                    878:        }
                    879:        
                    880:     /*
                    881:      * Finish inode initialization now that aliasing has been resolved.
                    882:      */
                    883:     hp->h_devvp = hfsmp->hfs_devvp;
                    884:     VREF(hp->h_devvp);
                    885:     *vpp = vp;
                    886:     return 0;
                    887: 
                    888: Err_Exit:;
                    889:     FREE (hp, M_HFSNODE);
                    890:     *vpp = NULL;
                    891:     return (retval);
                    892: }
                    893: 
                    894: 
                    895: int hasOverflowExtents(struct hfsnode *hp)
                    896: {
                    897:        ExtendedVCB             *vcb = HTOVCB(hp);
                    898:        FCB                             *fcb = HTOFCB(hp);
                    899:        u_long                  blocks;
                    900: 
                    901:        if (vcb->vcbSigWord == kHFSPlusSigWord)
                    902:          {
                    903:                ExtendedFCB *xfcb;
                    904: 
                    905:                xfcb = GetParallelFCB(HTOV(hp));
                    906:                if (xfcb->extents[7].blockCount == 0)
                    907:                        return false;
                    908:                
                    909:                blocks = xfcb->extents[0].blockCount +
                    910:                                 xfcb->extents[1].blockCount +
                    911:                                 xfcb->extents[2].blockCount +
                    912:                                 xfcb->extents[3].blockCount +
                    913:                                 xfcb->extents[4].blockCount +
                    914:                                 xfcb->extents[5].blockCount +
                    915:                                 xfcb->extents[6].blockCount +
                    916:                                 xfcb->extents[7].blockCount;   
                    917:          }
                    918:        else
                    919:          {
                    920:                if (fcb->fcbExtRec[2].blockCount == 0)
                    921:                        return false;
                    922:                
                    923:                blocks = fcb->fcbExtRec[0].blockCount +
                    924:                                 fcb->fcbExtRec[1].blockCount +
                    925:                                 fcb->fcbExtRec[2].blockCount;  
                    926:          }
                    927: 
                    928:        return ((fcb->fcbPLen / vcb->blockSize) > blocks);
                    929: }
                    930: 
                    931: 
                    932: int hfs_metafilelocking(struct hfsmount *hfsmp, u_long fileID, u_int flags, struct proc *p)
                    933: {
                    934:        ExtendedVCB             *vcb;
                    935:        struct vnode    *vp = NULL;
                    936:     struct timeval tv;
                    937:        int                             numOfLockedBuffs;
                    938:        int     retval = 0;
                    939: 
                    940:        vcb = HFSTOVCB(hfsmp);
                    941: 
                    942:     DBG_VFS(("  hfs_metafilelocking: vol: %d, file: %ld %s%s%s\n", vcb->vcbVRefNum, fileID,
                    943:             ((flags & LK_TYPE_MASK) == LK_RELEASE ? "RELEASE" : ""),
                    944:             ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE ? "EXCLUSIVE" : ""),
                    945:             ((flags & LK_TYPE_MASK) == LK_SHARED ? "SHARED" : "") ));
                    946: 
                    947:    /*kprintf("file: %ld flags: 0x%x %s%s%s\n",fileID, flags,
                    948:             ((flags & LK_TYPE_MASK) == LK_RELEASE ? "RELEASE" : ""),
                    949:             ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE ? "EXCLUSIVE" : ""),
                    950:             ((flags & LK_TYPE_MASK) == LK_SHARED ? "SHARED" : "") );
                    951: */
                    952: 
                    953:        switch (fileID)
                    954:        {
                    955:                case kHFSExtentsFileID:
                    956:                        vp = vcb->extentsRefNum;
                    957:                        break;
                    958: 
                    959:                case kHFSCatalogFileID:
                    960:                        vp = vcb->catalogRefNum;
                    961:                        break;
                    962: 
                    963:                case kHFSAttributesFileID:
                    964:                        if (vcb->vcbSigWord == kHFSPlusSigWord) {
                    965:                                vp = vcb->attributesRefNum;
                    966:                                break;
                    967:                        }
                    968:                        // fall through for hfs...
                    969: 
                    970:                case kHFSAllocationFileID:
                    971:                        // bitmap is covered by Extents B-tree locking
                    972:                default:
                    973:                        panic("hfs_lockmetafile: invalid fileID");
                    974:        }
                    975:     /*kprintf("\tBefore: %d\n", lockstatus(&VTOH(vp)->h_lock));
                    976: */
                    977:     if (vp != NULL) {
                    978: 
                    979:         /* Release, if necesary any locked buffer caches */
                    980:         if (flags & LK_RELEASE) {
                    981:             numOfLockedBuffs =  count_lock_queue();
                    982:             tv = time;
                    983:             if ((numOfLockedBuffs > 32) || ((numOfLockedBuffs>1) && ((tv.tv_sec - VTOH(vp)->h_lastfsync) > kMaxSecsForFsync))) {
                    984:                // kprintf("Synching meta deta...locked buffers = %d, fsync gap = %ld\n", numOfLockedBuffs, (tv.tv_sec - VTOH(vp)->h_lastfsync));
                    985:                 VOP_FSYNC(vp, NOCRED, MNT_NOWAIT, p);
                    986:             };
                    987:         };
                    988: 
                    989:         retval = lockmgr(&VTOH(vp)->h_lock, flags, &vp->v_interlock, p);
                    990:     };
                    991: 
                    992:        return retval;
                    993: }
                    994: 
                    995: 
                    996: void CopyVNodeToCatalogNode (struct vnode *vp, struct CatalogNodeData *nodeData)
                    997: {
                    998:     ExtendedVCB                        *vcb;
                    999:     FCB                                                *fcb;
                   1000:     struct hfsnode                     *hp;
                   1001:     Boolean                                    isHFSPlus, isResource;
                   1002:     HFSPlusExtentDescriptor    *extents, *parellextents;
                   1003:     ExtendedFCB                                *extendedFCB;
                   1004: 
                   1005:     hp = VTOH(vp);
                   1006:     vcb = HTOVCB(hp);
                   1007:     fcb = HTOFCB(hp);
                   1008:     isResource = (H_FORKTYPE(hp) == kRsrcFork);
                   1009:     isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
                   1010: 
                   1011:     nodeData->contentModDate = to_hfs_time(hp->h_meta->h_mtime);               /* date and time of last fork modification */
                   1012: 
                   1013:     DBG_ASSERT(fcb->fcbFlNm == H_FILEID(hp));
                   1014: 
                   1015:     if (isHFSPlus) {
                   1016:         nodeData->attributeModDate = to_hfs_time(hp->h_meta->h_ctime); /* date and time of last modification (any kind) */
                   1017:         nodeData->accessDate = to_hfs_time(hp->h_meta->h_atime);               /* date and time of last access (Rhapsody only) */
                   1018:         if (! (hp->h_meta->h_nodeflags & IN_UNSETACCESS)) {
                   1019:             /* This is a tricky stuff-job: the pflags longword has two bytes of significance and they're
                   1020:                combined with the mode field to yield a 32-bit permissions field as follows:
                   1021: 
                   1022:                                          +------------------------------------+
                   1023:                    hp->h_meta->h_pflags: |XXXXXXXX|    A    |XXXXXXXX|    B   |
                   1024:                                          +------------------------------------+
                   1025: 
                   1026:                                                             |
                   1027:                                                             V
                   1028: 
                   1029:                                          +------------------------------------+
                   1030:                             permissions: |    A    |    B   |      mode       |
                   1031:                                          +------------------------------------+
                   1032:              */
                   1033:             nodeData->permissions.permissions = (((hp->h_meta->h_pflags << 8)  & 0xFF000000) | /* A */
                   1034:                                                  ((hp->h_meta->h_pflags << 16) & 0x00FF0000) | /* B */
                   1035:                                                  (hp->h_meta->h_mode           & 0x0000FFFF));
                   1036:             nodeData->permissions.ownerID =  hp->h_meta->h_uid;
                   1037:             nodeData->permissions.groupID = hp->h_meta->h_gid;
                   1038:             nodeData->permissions.specialDevice = hp->h_meta->h_rdev;
                   1039:             };
                   1040:     };
                   1041: 
                   1042:        /* the rest only applies to files */
                   1043:        if (nodeData->nodeType == kCatalogFileNode) {
                   1044:         if (hp->h_meta->h_pflags & (SF_IMMUTABLE | UF_IMMUTABLE)) {
                   1045:             /* The file is locked: set the locked bit in the catalog. */
                   1046:             nodeData->nodeFlags |= kHFSFileLockedMask;
                   1047:         } else {
                   1048:             /* The file is unlocked: make sure the locked bit in the catalog is clear. */
                   1049:             nodeData->nodeFlags &= ~kHFSFileLockedMask;
                   1050:         };
                   1051:                if (isResource) {
                   1052:                        extents = nodeData->rsrcExtents;
                   1053:                        nodeData->rsrcLogicalSize = fcb->fcbEOF;
                   1054:                        nodeData->rsrcPhysicalSize = fcb->fcbPLen;
                   1055:                } else {
                   1056:                        extents = nodeData->dataExtents;
                   1057:                        nodeData->dataLogicalSize = fcb->fcbEOF;
                   1058:                        nodeData->dataPhysicalSize = fcb->fcbPLen;
                   1059:                };
                   1060: 
                   1061:            /* Copy the extents from their correct location */
                   1062:            if ( ! isHFSPlus) {
                   1063:                /* HFS, Copy the extents from the FCB part */
                   1064:                int i;
                   1065:                for (i = 0; i < kHFSExtentDensity; ++i) {
                   1066:                    extents[i].startBlock = (UInt16) (fcb->fcbExtRec[i].startBlock);
                   1067:                    extents[i].blockCount = (UInt16) (fcb->fcbExtRec[i].blockCount);
                   1068:                    }
                   1069:            } else {
                   1070:                /* HFSPlus, Copy the extents from the parallel extents */
                   1071:                extendedFCB = GetParallelFCB (HTOV(hp));
                   1072:                parellextents = extendedFCB->extents;
                   1073:                bcopy ( parellextents, extents, sizeof(HFSPlusExtentRecord));
                   1074:            };
                   1075:        
                   1076:            if (vp->v_type == VLNK) {
                   1077:                ((struct FInfo *)(&nodeData->finderInfo))->fdType = kSymLinkFileType;
                   1078:                ((struct FInfo *)(&nodeData->finderInfo))->fdCreator = kSymLinkCreator;
                   1079:        
                   1080:                        /* Set this up as an alias */
                   1081:                        #if SUPPORTS_MAC_ALIASES
                   1082:                                ((struct FInfo *)(&nodeData->finderInfo))->fdFlags |= kIsAlias;
                   1083:                        #endif
                   1084:                }
                   1085:        }
                   1086:  }
                   1087: 
                   1088: 
                   1089: 
                   1090: void MapFileOffset(struct hfsnode *hp,
                   1091:                    off_t filePosition,
                   1092:                    daddr_t *logBlockNumber,
                   1093:                    long *blockSize,
                   1094:                    long *blockOffset) {
                   1095:     off_t extentOffset = filePosition;
                   1096:     daddr_t precedingBlockCount;
                   1097:     unsigned long logicalBlockSize = 0;
                   1098:     unsigned long spaceRemaining;
                   1099: 
                   1100:     DBG_IO(("MapFileOffset: hp = 0x%08lX, vp = 0x%08lX ('%s'):\n", (u_long)hp, (u_long)HTOV(hp), H_NAME(hp)));
                   1101:     // DBG_IO(("\tfilePosition 0x%08lX", (u_long)filePosition));
                   1102: 
                   1103:     if (filePosition < hp->h_optimizedblocksizelimit) {
                   1104:         int extent;
                   1105: 
                   1106:         precedingBlockCount = 0;
                   1107:         for (extent = 0; extent < LOGBLOCKMAPENTRIES; ++extent) {
                   1108:             if ((hp->h_logicalblocktable[extent].logicalBlockCount > 0) &&
                   1109:                 (extentOffset < hp->h_logicalblocktable[extent].extentLength)) {
                   1110:                 logicalBlockSize = MAXLOGBLOCKSIZE;
                   1111:                 spaceRemaining = hp->h_logicalblocktable[extent].extentLength - ((extentOffset / logicalBlockSize) * logicalBlockSize);
                   1112:                 *blockSize = MIN(logicalBlockSize, spaceRemaining);
                   1113:                 // DBG_IO(("\tUsing entry #%d: preceding blocks = 0x%X, position = 0x%8lX:\n",
                   1114:                 //         extent, precedingBlockCount, (u_long)extentOffset));
                   1115:                 break;
                   1116:             };
                   1117:             precedingBlockCount += hp->h_logicalblocktable[extent].logicalBlockCount;
                   1118:             extentOffset -= hp->h_logicalblocktable[extent].extentLength;
                   1119:         };
                   1120:         DBG_ASSERT(logicalBlockSize > 0);
                   1121:     } else {
                   1122:         // DBG_IO(("\tUsing h_uniformblocksizestart = 0x%X and h_optimizedblocksizelimit = 0x%lX:\n",
                   1123:         //         hp->h_uniformblocksizestart, (u_long)hp->h_optimizedblocksizelimit));
                   1124:         precedingBlockCount = hp->h_uniformblocksizestart;
                   1125:         extentOffset -= hp->h_optimizedblocksizelimit;
                   1126:         logicalBlockSize = hp->h_meta->h_logBlockSize;
                   1127:         *blockSize = logicalBlockSize;
                   1128:     };
                   1129: 
                   1130:     *logBlockNumber =  precedingBlockCount + (extentOffset / logicalBlockSize);
                   1131:     *blockOffset = extentOffset % logicalBlockSize;
                   1132:     DBG_IO(("\tfilePosition 0x%08lX -> logBlockNo = 0x%X, blockSize = 0x%lX, blockOffset = 0x%lX.\n",
                   1133:                  (u_long)filePosition,
                   1134:                  *logBlockNumber,
                   1135:                  *blockSize,
                   1136:                  *blockOffset));
                   1137: }
                   1138: 
                   1139: 
                   1140: long LogicalBlockSize(struct hfsnode *hp, daddr_t logicalBlockNumber) {
                   1141:     if (logicalBlockNumber < hp->h_uniformblocksizestart) {
                   1142:         off_t fragmentOffset = 0;
                   1143:         int extent;
                   1144: 
                   1145:         for (extent = 0; extent < LOGBLOCKMAPENTRIES; ++extent) {
                   1146:             if ((hp->h_logicalblocktable[extent].logicalBlockCount > 0) &&
                   1147:                 (logicalBlockNumber < hp->h_logicalblocktable[extent].logicalBlockCount)) {
                   1148:                 // *filePosition = fragmentOffset + (logicalBlockNumber * MAXLOGBLOCKSIZE);
                   1149:                 return MIN(MAXLOGBLOCKSIZE, hp->h_logicalblocktable[extent].extentLength - (logicalBlockNumber * MAXLOGBLOCKSIZE));
                   1150:             };
                   1151:             logicalBlockNumber -= hp->h_logicalblocktable[extent].logicalBlockCount;
                   1152:             fragmentOffset += hp->h_logicalblocktable[extent].extentLength;
                   1153:         };
                   1154:     } else {
                   1155:         // *filePosition = hp->h_optimizedblocksizelimit + ((logicalBlockNumber - hp->h_uniformblocksizestart) * hp->h_meta->h_logBlockSize);
                   1156:         return hp->h_meta->h_logBlockSize;
                   1157:     };
                   1158: 
                   1159:     DBG_ASSERT(0 /* cannot be reached */);
                   1160:     return 0;
                   1161: };
                   1162: 
                   1163: 
                   1164: void UpdateBlockMappingTableEntry(struct hfsnode *hp, int index, daddr_t firstFragmentBlockNumber, long newFragmentLength) {
                   1165: //  off_t                                      currentFragmentLength;
                   1166: 
                   1167:     /* Compute the number of logical blocks, rounding up to include any small trailing fragments: */
                   1168:     hp->h_logicalblocktable[index].logicalBlockCount = (newFragmentLength + MAXLOGBLOCKSIZE - 1) / MAXLOGBLOCKSIZE;
                   1169: 
                   1170:     DBG_IO(("\tblocktable[%d]: length = 0x%lX, # blocks = 0x%lX.\n",
                   1171:             index,
                   1172:             newFragmentLength,
                   1173:             (u_long)hp->h_logicalblocktable[index].logicalBlockCount));
                   1174: 
                   1175: #if 0
                   1176:     currentFragmentLength = hp->h_logicalblocktable[index].extentLength;
                   1177:     if ((newFragmentLength > currentFragmentLength) && (currentFragmentLength > 0)) {
                   1178:         daddr_t                                        currentLastBlockNumber;
                   1179:         long                                   currentLastBlockSize;
                   1180:         long                                   newLastBlockSize;
                   1181:         struct buf                             *bp;
                   1182:         int                                            retval;
                   1183: 
                   1184:         currentLastBlockNumber = firstFragmentBlockNumber + (currentFragmentLength / MAXLOGBLOCKSIZE);
                   1185:         currentLastBlockSize = currentFragmentLength % MAXLOGBLOCKSIZE;
                   1186:         if (currentLastBlockSize > 0) {
                   1187:             newLastBlockSize = MIN(MAXLOGBLOCKSIZE,
                   1188:                                    newFragmentLength -
                   1189:                                    ((currentLastBlockNumber - firstFragmentBlockNumber) * MAXLOGBLOCKSIZE));
                   1190:             if (newLastBlockSize != currentLastBlockSize) {
                   1191:                 DBG_IO(("\t\t(Adjusting block 0x%lX from 0x%lX to 0x%lX...)\n",
                   1192:                         (unsigned long)currentLastBlockNumber,
                   1193:                         currentLastBlockSize,
                   1194:                         newLastBlockSize));
                   1195:                 retval = bread(HTOV(hp), currentLastBlockNumber, currentLastBlockSize, NOCRED, &bp);
                   1196:                 if (retval == 0) {
                   1197:                     bexpand(bp, newLastBlockSize, NULL, RELEASE_BUFFER);
                   1198:                 } else {
                   1199:                     DBG_IO(("\t\terror (%d.) acquiring block 0x%lX; bp = 0x%08lX\n",
                   1200:                             retval,
                   1201:                             (unsigned long)currentLastBlockNumber,
                   1202:                             (unsigned long)bp));
                   1203:                     if (bp) brelse(bp);
                   1204:                 };
                   1205:             };
                   1206:         };
                   1207:     };
                   1208: #endif
                   1209:     hp->h_logicalblocktable[index].extentLength = newFragmentLength;
                   1210: }
                   1211: 
                   1212: 
                   1213: void UpdateBlockMappingTable(struct hfsnode *hp)
                   1214: {
                   1215:     ExtendedVCB                                *vcb = HTOVCB(hp);
                   1216:     FCB                                                *fcb = HTOFCB(hp);
                   1217:     ExtendedFCB                                *extendedFCB;
                   1218:     Boolean                                    isHFSPlus;
                   1219:     HFSPlusExtentDescriptor *parellextents;
                   1220:     off_t                                      rangeMappedSoFar;
                   1221:     u_long                                     logicalBlocksMappedSoFar;
                   1222:     int                                                i;
                   1223:     off_t                                      newFragmentLength;
                   1224: 
                   1225:     isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
                   1226:     DBG_IO(("UpdateBlockMappingTable: hp = 0x%08lX, vp = 0x%08lX ('%s'):\n", (u_long)hp, (u_long)HTOV(hp), H_NAME(hp)));
                   1227:     if (H_FORKTYPE(hp) != kDirCmplx) {
                   1228:         rangeMappedSoFar = 0;
                   1229:         logicalBlocksMappedSoFar = 0;
                   1230: 
                   1231:         if ( ! isHFSPlus) {
                   1232:             DBG_ASSERT(kHFSExtentDensity <= LOGBLOCKMAPENTRIES);
                   1233:             for (i = 0; i < kHFSExtentDensity; ++i) {
                   1234:                 newFragmentLength = fcb->fcbExtRec[i].blockCount * vcb->blockSize;
                   1235:                 UpdateBlockMappingTableEntry(hp, i, logicalBlocksMappedSoFar, newFragmentLength);
                   1236:                 rangeMappedSoFar += newFragmentLength;
                   1237:                 logicalBlocksMappedSoFar += hp->h_logicalblocktable[i].logicalBlockCount;
                   1238:             }
                   1239:             /* Zero out any remaining entries: */
                   1240:             for (i = kHFSExtentDensity; i < LOGBLOCKMAPENTRIES; ++i) {
                   1241:                 hp->h_logicalblocktable[i].extentLength = 0;
                   1242:             };
                   1243: #if DIAGNOSTIC
                   1244:             if (rangeMappedSoFar < fcb->fcbPLen) DBG_ASSERT(hp->h_logicalblocktable[kHFSExtentDensity-1].extentLength > 0);
                   1245: #endif
                   1246:         } else {
                   1247:             extendedFCB = GetParallelFCB (FCBTOV(fcb));
                   1248:             parellextents = extendedFCB->extents;
                   1249:             for (i = 0; i < kHFSPlusExtentDensity; ++i) {
                   1250:                 newFragmentLength = parellextents[i].blockCount * vcb->blockSize;
                   1251:                 UpdateBlockMappingTableEntry(hp, i, logicalBlocksMappedSoFar, newFragmentLength);
                   1252:                 rangeMappedSoFar += newFragmentLength;
                   1253:                 logicalBlocksMappedSoFar += hp->h_logicalblocktable[i].logicalBlockCount;
                   1254:             }
                   1255:             /* No need to zero out the remaining entries [there are none]: */
                   1256:             DBG_ASSERT(LOGBLOCKMAPENTRIES <= kHFSPlusExtentDensity);
                   1257: #if DIAGNOSTIC
                   1258:             if (rangeMappedSoFar < fcb->fcbPLen) DBG_ASSERT(hp->h_logicalblocktable[kHFSPlusExtentDensity-1].extentLength > 0);
                   1259: #endif
                   1260:         };
                   1261:         
                   1262:         hp->h_optimizedblocksizelimit = rangeMappedSoFar;
                   1263:         hp->h_uniformblocksizestart = logicalBlocksMappedSoFar;
                   1264:         DBG_IO(("\th_optimizedblocksizelimit = 0x%lX, h_uniformblocksizestart = 0x%lX.\n",
                   1265:                 (u_long)hp->h_optimizedblocksizelimit, (u_long)hp->h_uniformblocksizestart));
                   1266: 
                   1267: #if BYPASSBLOCKINGOPTIMIZATION
                   1268:         hp->h_optimizedblocksizelimit = 0;
                   1269:         hp->h_uniformblocksizestart = 0;
                   1270: #endif
                   1271:     };
                   1272: }
                   1273: 
                   1274: void CopyCatalogToHFSNode(struct hfsCatalogInfo *catalogInfo, struct hfsnode *hp)
                   1275: {
                   1276:     FCB                                                *fcb;
                   1277:        ExtendedVCB                             *vcb = HTOVCB(hp);
                   1278:     Boolean                                    isHFSPlus, isDirectory, isResource;
                   1279:     HFSPlusExtentDescriptor    *extents, *parellextents;
                   1280:     ExtendedFCB                                *extendedFCB;
                   1281:     ushort                                     finderFlags;
                   1282:        UInt8                                   forkType;
                   1283: 
                   1284:     DBG_ASSERT (hp != NULL);
                   1285:     DBG_ASSERT (hp->h_valid == HFS_VNODE_MAGIC);
                   1286:     DBG_ASSERT (hp->h_meta != NULL);
                   1287: 
                   1288:     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));
                   1289:     forkType           = H_FORKTYPE(hp);
                   1290:     isResource                 = (forkType == kRsrcFork);
                   1291:     isDirectory                = (catalogInfo->nodeData.nodeType == kCatalogFolderNode);
                   1292:     isHFSPlus          = (vcb->vcbSigWord == kHFSPlusSigWord);
                   1293:     finderFlags        = ((struct FInfo *)(&catalogInfo->nodeData.finderInfo))->fdFlags;
                   1294:     DBG_UTILS(("\t\t forkType:%d, isResource:%d, isDirectory:%d, isHFSPlus:%d\n", forkType, isResource, isDirectory, isHFSPlus));
                   1295: 
                   1296:        /* Copy over the name if NOT set yet */
                   1297:        if (H_NAME(hp) == NULL) {
                   1298:            hp->h_meta->h_namelen = strlen(catalogInfo->spec.name);
                   1299:            if (hp->h_meta->h_namelen <= MAXHFSVNODELEN) {
                   1300:                H_NAME(hp) = hp->h_meta->h_fileName;
                   1301:            }
                   1302:            else {
                   1303:                MALLOC(H_NAME(hp), char *, hp->h_meta->h_namelen+1, M_HFSNODE, M_WAITOK);
                   1304:                hp->h_meta->h_nodeflags |= IN_LONGNAME;
                   1305:            };
                   1306:        bcopy(catalogInfo->spec.name, H_NAME(hp), hp->h_meta->h_namelen+1);
                   1307:         }
                   1308:         else {
                   1309:                 DBG_ASSERT (hp->h_meta->h_namelen == strlen(catalogInfo->spec.name));
                   1310:                 DBG_ASSERT (strcmp(H_NAME(hp), catalogInfo->spec.name) == 0);
                   1311:         };
                   1312: 
                   1313:        /* Copy over the dirid, and hint */
                   1314:     H_FILEID(hp)       = catalogInfo->nodeData.nodeID;
                   1315:     H_DIRID(hp)                = catalogInfo->spec.parID;
                   1316:     H_HINT(hp)                 = catalogInfo->hint;
                   1317: 
                   1318:     if (hp->h_xfcb != NULL) {
                   1319: 
                   1320:         /* Init the fcb */
                   1321:         fcb                    = HTOFCB(hp);
                   1322:         fcb->fcbVPtr   = vcb;
                   1323:         fcb->fcbFlNm   = catalogInfo->nodeData.nodeID;
                   1324:         fcb->fcbFlags  = catalogInfo->nodeData.nodeFlags;
                   1325: 
                   1326:         if (forkType != kDirCmplx) {
                   1327:             fcb->fcbFlags &= kHFSFileLockedMask;               /* Clear resource, dirty bits */
                   1328:             if (fcb->fcbFlags != 0)                                            /* if clear, its not locked, then.. */
                   1329:                 fcb->fcbFlags = fcbFileLockedMask;             /* duplicate the bit for later use */
                   1330: 
                   1331:             fcb->fcbClmpSize = vcb->vcbClpSiz; /*XXX why not use the one in catalogInfo? */
                   1332: 
                   1333:             if (isResource)    
                   1334:                 extents = catalogInfo->nodeData.rsrcExtents;
                   1335:             else
                   1336:                 extents = catalogInfo->nodeData.dataExtents;
                   1337: 
                   1338:             /* Copy the extents to their correct location: */
                   1339:             if ( ! isHFSPlus) {
                   1340:                 int i;
                   1341:                 for (i = 0; i < kHFSExtentDensity; ++i) {
                   1342:                     fcb->fcbExtRec[i].startBlock = (UInt32) (extents[i].startBlock);
                   1343:                     fcb->fcbExtRec[i].blockCount = (UInt32) (extents[i].blockCount);
                   1344:                 }
                   1345:             } else {
                   1346:                 /* HFSPlus, Copy the extents to the parallel extents */
                   1347:                 extendedFCB = GetParallelFCB (FCBTOV(fcb));
                   1348:                 parellextents = extendedFCB->extents;
                   1349:                 bcopy (extents, parellextents, sizeof(HFSPlusExtentRecord));
                   1350:             };
                   1351:             UpdateBlockMappingTable(hp);
                   1352: 
                   1353:             /* the valence field is overloaded to flag files over 2 gig */
                   1354:             /* since we are working with a single fork, isolate it flags <why?> */
                   1355:             /*  secondFlags = catalogInfo->nodeData.valence; */
                   1356: 
                   1357:             if (isResource)    {       
                   1358:                 fcb->fcbEOF = catalogInfo->nodeData.rsrcLogicalSize;
                   1359:                 fcb->fcbPLen = catalogInfo->nodeData.rsrcPhysicalSize;
                   1360:                 fcb->fcbFlags |= fcbResourceMask;
                   1361:             }  else {
                   1362:                 fcb->fcbEOF = catalogInfo->nodeData.dataLogicalSize;
                   1363:                 fcb->fcbPLen = catalogInfo->nodeData.dataPhysicalSize;
                   1364:             };
                   1365:         };
                   1366:        };
                   1367: 
                   1368:     hp->h_meta->h_mtime = to_bsd_time(catalogInfo->nodeData.contentModDate);   /* UNIX-format mod date in seconds */
                   1369:     hp->h_meta->h_crtime = to_bsd_time(catalogInfo->nodeData.createDate);              /* UNIX-format creation date in secs. */
                   1370:     hp->h_meta->h_butime = to_bsd_time(catalogInfo->nodeData.backupDate);              /* UNIX-format backup date in secs. */
                   1371:     if (isHFSPlus) {
                   1372:         hp->h_meta->h_atime = to_bsd_time(catalogInfo->nodeData.accessDate);   /* UNIX-format mod date in seconds */
                   1373:         hp->h_meta->h_ctime = to_bsd_time(catalogInfo->nodeData.attributeModDate);     /* UNIX-format status change date */
                   1374:     }
                   1375:     else {
                   1376:         hp->h_meta->h_atime = to_bsd_time(catalogInfo->nodeData.contentModDate); /* UNIX-format mod date in seconds */
                   1377:         hp->h_meta->h_ctime = to_bsd_time(catalogInfo->nodeData.contentModDate); /* UNIX-format status change date */
                   1378:     }
                   1379: 
                   1380:     /* Now the rest */
                   1381:     if (isHFSPlus && (catalogInfo->nodeData.permissions.permissions & IFMT)) {
                   1382:         hp->h_meta->h_uid = catalogInfo->nodeData.permissions.ownerID;
                   1383:         hp->h_meta->h_gid = catalogInfo->nodeData.permissions.groupID;
                   1384:         /* The 32-bit permissions field is unpacked to yield the two significant bytes of flags and the
                   1385:            mode as follows:
                   1386:                                      +------------------------------------+
                   1387:                         permissions: |    A    |    B   |      mode       |
                   1388:                                      +------------------------------------+
                   1389: 
                   1390:                                                         |
                   1391:                                                         V
                   1392: 
                   1393:                                      +------------------------------------+
                   1394:                hp->h_meta->h_pflags: |XXXXXXXX|    A    |XXXXXXXX|    B   |
                   1395:                                      +------------------------------------+
                   1396: 
                   1397:          */
                   1398:         hp->h_meta->h_pflags = (((catalogInfo->nodeData.permissions.permissions & 0xFF000000) >> 8) |  /* A */
                   1399:                                 ((catalogInfo->nodeData.permissions.permissions & 0x00FF0000) >> 16)); /* B */
                   1400:         hp->h_meta->h_mode = (mode_t)(catalogInfo->nodeData.permissions.permissions & 0x0000FFFF);
                   1401:         hp->h_meta->h_rdev = catalogInfo->nodeData.permissions.specialDevice;
                   1402:     } else {
                   1403:         /*
                   1404:          *     Set the permissions as determined by the mount auguments
                   1405:          *     but keep in account if the file or folder is hfs locked
                   1406:          */    
                   1407:         hp->h_meta->h_nodeflags |= IN_UNSETACCESS;                     
                   1408:         hp->h_meta->h_uid = HTOHFS(hp)->hfs_uid;
                   1409:         hp->h_meta->h_gid = HTOHFS(hp)->hfs_gid;
                   1410:         /* Default access is full read/write/execute: */
                   1411:         hp->h_meta->h_mode = ACCESSPERMS;      /* 0777: rwxrwxrwx */
                   1412:         
                   1413:         /* ... but no more than that permitted by the mount point's: */
                   1414:         if (isDirectory) {
                   1415:             hp->h_meta->h_mode &= HTOHFS(hp)->hfs_dir_mask;
                   1416:                }
                   1417:                else {
                   1418:             hp->h_meta->h_mode &= HTOHFS(hp)->hfs_file_mask;
                   1419:                }
                   1420:         
                   1421:         if(isDirectory)
                   1422:             hp->h_meta->h_mode |= IFDIR;
                   1423:         else if (SUPPORTS_MAC_ALIASES && (finderFlags & kIsAlias))     /* aliases will be symlinks in the future */
                   1424:             hp->h_meta->h_mode |= IFLNK;
                   1425:         else
                   1426:             hp->h_meta->h_mode |= IFREG;
                   1427: 
                   1428:     };
                   1429: 
                   1430:     /* Make sure the IMMUTABLE bits are in sync with the locked flag in the catalog: */
                   1431:     if (!isDirectory) {
                   1432:         if (catalogInfo->nodeData.nodeFlags & kHFSFileLockedMask) {
                   1433:             /* The file's supposed to be locked:
                   1434:                Make sure at least one of the IMMUTABLE bits is set: */
                   1435:             if ((hp->h_meta->h_pflags & (SF_IMMUTABLE | UF_IMMUTABLE)) == 0) {
                   1436:                 hp->h_meta->h_pflags |= UF_IMMUTABLE;                          /* Set the user-changable IMMUTABLE bit */
                   1437:             };
                   1438:         } else {
                   1439:             /* The file's supposed to be unlocked: */
                   1440:             hp->h_meta->h_pflags &= ~(SF_IMMUTABLE | UF_IMMUTABLE);
                   1441:         };
                   1442:     };
                   1443: 
                   1444:        if (isDirectory)
                   1445:        hp->h_size = sizeof (hfsdirentry) * (catalogInfo->nodeData.valence + 2);
                   1446:        else
                   1447:        hp->h_size = catalogInfo->nodeData.rsrcPhysicalSize + catalogInfo->nodeData.dataPhysicalSize;
                   1448:        
                   1449:     /* finish up some vnode stuff */
                   1450:     /* Set the root flag if necesary */
                   1451:        switch (hp->h_meta->h_mode & IFMT) {
                   1452:         case IFDIR:
                   1453:             HTOV(hp)->v_type = VDIR;
                   1454:             if (H_FILEID(hp) == kRootDirID)
                   1455:                 HTOV(hp)->v_flag |= VROOT;
                   1456:             break;
                   1457:         case IFREG:
                   1458:             if (forkType == kDirCmplx)
                   1459:                 HTOV(hp)->v_type = VCPLX;
                   1460:             else
                   1461:                 HTOV(hp)->v_type = VREG;
                   1462:             break;
                   1463:         case IFLNK:
                   1464:             if (forkType == kDirCmplx)
                   1465:                 HTOV(hp)->v_type = VCPLX;
                   1466:             else
                   1467:                HTOV(hp)->v_type = VLNK;
                   1468:             break;
                   1469:         default:
                   1470:             DBG_ASSERT(false);
                   1471:             HTOV(hp)->v_type = VBAD;
                   1472:     };         
                   1473: }
                   1474: 
                   1475: int AttributeBlockSize(struct attrlist *attrlist) {
                   1476:        int size;
                   1477:        attrgroup_t a;
                   1478:        
                   1479: #if ((ATTR_CMN_NAME                    | ATTR_CMN_DEVID                        | ATTR_CMN_FSID                         | ATTR_CMN_OBJTYPE              | \
                   1480:       ATTR_CMN_OBJTAG          | ATTR_CMN_OBJID                        | ATTR_CMN_OBJPERMANENTID       | ATTR_CMN_PAROBJID             | \
                   1481:       ATTR_CMN_SCRIPT          | ATTR_CMN_CRTIME                       | ATTR_CMN_MODTIME                      | ATTR_CMN_CHGTIME              | \
                   1482:       ATTR_CMN_ACCTIME         | ATTR_CMN_BKUPTIME                     | ATTR_CMN_FNDRINFO                     | ATTR_CMN_OWNERID              | \
                   1483:       ATTR_CMN_GRPID           | ATTR_CMN_ACCESSMASK           | ATTR_CMN_NAMEDATTRCOUNT       | ATTR_CMN_NAMEDATTRLIST| \
                   1484:       ATTR_CMN_FLAGS) != ATTR_CMN_VALIDMASK)
                   1485: #error AttributeBlockSize: Missing bits in common mask computation!
                   1486: #endif
                   1487:           DBG_ASSERT((attrlist->commonattr & ~ATTR_CMN_VALIDMASK) == 0);
                   1488: 
                   1489: #if ((ATTR_VOL_FSTYPE          | ATTR_VOL_SIGNATURE            | ATTR_VOL_SIZE                         | ATTR_VOL_SPACEFREE    | \
                   1490:       ATTR_VOL_SPACEAVAIL      | ATTR_VOL_MINALLOCATION        | ATTR_VOL_ALLOCATIONCLUMP      | ATTR_VOL_IOBLOCKSIZE  | \
                   1491:       ATTR_VOL_OBJCOUNT                | ATTR_VOL_FILECOUNT            | ATTR_VOL_DIRCOUNT                     | ATTR_VOL_MAXOBJCOUNT  | \
                   1492:       ATTR_VOL_MOUNTPOINT      | ATTR_VOL_NAME                         | ATTR_VOL_MOUNTFLAGS       | ATTR_VOL_INFO) != ATTR_VOL_VALIDMASK)
                   1493: #error AttributeBlockSize: Missing bits in volume mask computation!
                   1494: #endif
                   1495:           DBG_ASSERT((attrlist->volattr & ~ATTR_VOL_VALIDMASK) == 0);
                   1496: 
                   1497: #if ((ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT) != ATTR_DIR_VALIDMASK)
                   1498: #error AttributeBlockSize: Missing bits in directory mask computation!
                   1499: #endif
                   1500:       DBG_ASSERT((attrlist->dirattr & ~ATTR_DIR_VALIDMASK) == 0);
                   1501: #if ((ATTR_FILE_LINKCOUNT      | ATTR_FILE_TOTALSIZE           | ATTR_FILE_ALLOCSIZE           | ATTR_FILE_IOBLOCKSIZE         | \
                   1502:       ATTR_FILE_CLUMPSIZE      | ATTR_FILE_DEVTYPE                     | ATTR_FILE_FILETYPE            | ATTR_FILE_FORKCOUNT           | \
                   1503:       ATTR_FILE_FORKLIST       | ATTR_FILE_DATALENGTH          | ATTR_FILE_DATAALLOCSIZE       | ATTR_FILE_DATAEXTENTS         | \
                   1504:       ATTR_FILE_RSRCLENGTH     | ATTR_FILE_RSRCALLOCSIZE       | ATTR_FILE_RSRCEXTENTS) != ATTR_FILE_VALIDMASK)
                   1505: #error AttributeBlockSize: Missing bits in file mask computation!
                   1506: #endif
                   1507:           DBG_ASSERT((attrlist->fileattr & ~ATTR_FILE_VALIDMASK) == 0);
                   1508: 
                   1509: #if ((ATTR_FORK_TOTALSIZE | ATTR_FORK_ALLOCSIZE) != ATTR_FORK_VALIDMASK)
                   1510: #error AttributeBlockSize: Missing bits in fork mask computation!
                   1511: #endif
                   1512:       DBG_ASSERT((attrlist->forkattr & ~ATTR_FORK_VALIDMASK) == 0);
                   1513: 
                   1514:        size = 0;
                   1515:        
                   1516:        if ((a = attrlist->commonattr) != 0) {
                   1517:         if (a & ATTR_CMN_NAME) size += sizeof(struct attrreference);
                   1518:                if (a & ATTR_CMN_DEVID) size += sizeof(dev_t);
                   1519:                if (a & ATTR_CMN_FSID) size += sizeof(fsid_t);
                   1520:                if (a & ATTR_CMN_OBJTYPE) size += sizeof(fsobj_type_t);
                   1521:                if (a & ATTR_CMN_OBJTAG) size += sizeof(fsobj_tag_t);
                   1522:                if (a & ATTR_CMN_OBJID) size += sizeof(fsobj_id_t);
                   1523:         if (a & ATTR_CMN_OBJPERMANENTID) size += sizeof(fsobj_id_t);
                   1524:                if (a & ATTR_CMN_PAROBJID) size += sizeof(fsobj_id_t);
                   1525:                if (a & ATTR_CMN_SCRIPT) size += sizeof(text_encoding_t);
                   1526:                if (a & ATTR_CMN_CRTIME) size += sizeof(struct timespec);
                   1527:                if (a & ATTR_CMN_MODTIME) size += sizeof(struct timespec);
                   1528:                if (a & ATTR_CMN_CHGTIME) size += sizeof(struct timespec);
                   1529:                if (a & ATTR_CMN_ACCTIME) size += sizeof(struct timespec);
                   1530:                if (a & ATTR_CMN_BKUPTIME) size += sizeof(struct timespec);
                   1531:                if (a & ATTR_CMN_FNDRINFO) size += 32 * sizeof(UInt8);
                   1532:                if (a & ATTR_CMN_OWNERID) size += sizeof(uid_t);
                   1533:                if (a & ATTR_CMN_GRPID) size += sizeof(gid_t);
                   1534:                if (a & ATTR_CMN_ACCESSMASK) size += sizeof(u_long);
                   1535:                if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(u_long);
                   1536:                if (a & ATTR_CMN_NAMEDATTRLIST) size += sizeof(struct attrreference);
                   1537:                if (a & ATTR_CMN_FLAGS) size += sizeof(u_long);
                   1538:        };
                   1539:        if ((a = attrlist->volattr) != 0) {
                   1540:                if (a & ATTR_VOL_FSTYPE) size += sizeof(u_long);
                   1541:                if (a & ATTR_VOL_SIGNATURE) size += sizeof(u_long);
                   1542:                if (a & ATTR_VOL_SIZE) size += sizeof(off_t);
                   1543:                if (a & ATTR_VOL_SPACEFREE) size += sizeof(off_t);
                   1544:                if (a & ATTR_VOL_SPACEAVAIL) size += sizeof(off_t);
                   1545:                if (a & ATTR_VOL_MINALLOCATION) size += sizeof(off_t);
                   1546:                if (a & ATTR_VOL_ALLOCATIONCLUMP) size += sizeof(off_t);
                   1547:                if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(u_long);
                   1548:                if (a & ATTR_VOL_OBJCOUNT) size += sizeof(u_long);
                   1549:                if (a & ATTR_VOL_FILECOUNT) size += sizeof(u_long);
                   1550:                if (a & ATTR_VOL_DIRCOUNT) size += sizeof(u_long);
                   1551:                if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(u_long);
                   1552:                if (a & ATTR_VOL_MOUNTPOINT) size += sizeof(struct attrreference);
                   1553:         if (a & ATTR_VOL_NAME) size += sizeof(struct attrreference);
                   1554:         if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(u_long);
                   1555:        };
                   1556:        if ((a = attrlist->dirattr) != 0) {
                   1557:                if (a & ATTR_DIR_LINKCOUNT) size += sizeof(u_long);
                   1558:                if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(u_long);
                   1559:        };
                   1560:        if ((a = attrlist->fileattr) != 0) {
                   1561:                if (a & ATTR_FILE_LINKCOUNT) size += sizeof(u_long);
                   1562:                if (a & ATTR_FILE_TOTALSIZE) size += sizeof(off_t);
                   1563:                if (a & ATTR_FILE_ALLOCSIZE) size += sizeof(off_t);
                   1564:                if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(size_t);
                   1565:                if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(off_t);
                   1566:                if (a & ATTR_FILE_DEVTYPE) size += sizeof(u_long);
                   1567:                if (a & ATTR_FILE_FILETYPE) size += sizeof(u_long);
                   1568:                if (a & ATTR_FILE_FORKCOUNT) size += sizeof(u_long);
                   1569:                if (a & ATTR_FILE_FORKLIST) size += sizeof(struct attrreference);
                   1570:                if (a & ATTR_FILE_DATALENGTH) size += sizeof(off_t);
                   1571:                if (a & ATTR_FILE_DATAALLOCSIZE) size += sizeof(off_t);
                   1572:                if (a & ATTR_FILE_DATAEXTENTS) size += sizeof(extentrecord);
                   1573:                if (a & ATTR_FILE_RSRCLENGTH) size += sizeof(off_t);
                   1574:                if (a & ATTR_FILE_RSRCALLOCSIZE) size += sizeof(off_t);
                   1575:                if (a & ATTR_FILE_RSRCEXTENTS) size += sizeof(extentrecord);
                   1576:        };
                   1577:        if ((a = attrlist->forkattr) != 0) {
                   1578:                if (a & ATTR_FORK_TOTALSIZE) size += sizeof(off_t);
                   1579:                if (a & ATTR_FORK_ALLOCSIZE) size += sizeof(off_t);
                   1580:        };
                   1581: 
                   1582:     return size;
                   1583: }
                   1584: 
                   1585: 
                   1586: 
                   1587: void PackVolCommonAttributes(struct attrlist *alist,
                   1588:                                                         struct vnode *root_vp,
                   1589:                                                         struct hfsCatalogInfo *root_catInfo,
                   1590:                                                         void **attrbufptrptr,
                   1591:                                                         void **varbufptrptr) {
                   1592:     void *attrbufptr;
                   1593:     void *varbufptr;
                   1594:     attrgroup_t a;
                   1595:     struct hfsnode *root_hp = VTOH(root_vp);
                   1596:     struct mount *mp = VTOVFS(root_vp);
                   1597:     struct hfsmount *hfsmp = VTOHFS(root_vp);
                   1598:     struct ExtendedVCB *vcb = HFSTOVCB(hfsmp);
                   1599:        u_long attrlength;
                   1600:        
                   1601:        attrbufptr = *attrbufptrptr;
                   1602:        varbufptr = *varbufptrptr;
                   1603: 
                   1604:     if ((a = alist->commonattr) != 0) {
                   1605:         if (a & ATTR_CMN_NAME) {
                   1606:             attrlength = root_hp->h_meta->h_namelen+1;
                   1607:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
                   1608:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1609:             (void) strncpy((unsigned char *)varbufptr, H_NAME(root_hp), attrlength);
                   1610: 
                   1611:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1612:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1613:             ++((struct attrreference *)attrbufptr);
                   1614:         };
                   1615:                if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = hfsmp->hfs_raw_dev;
                   1616:                if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = mp->mnt_stat.f_fsid;
                   1617:                if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = 0;
                   1618:                if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = VT_HFS;
                   1619:                if (a & ATTR_CMN_OBJID) {
                   1620:                        ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
                   1621:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
                   1622:                        ++((fsobj_id_t *)attrbufptr);
                   1623:                };
                   1624:         if (a & ATTR_CMN_OBJPERMANENTID) {
                   1625:             ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
                   1626:             ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
                   1627:             ++((fsobj_id_t *)attrbufptr);
                   1628:         };
                   1629:                if (a & ATTR_CMN_PAROBJID) {
                   1630:             ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
                   1631:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
                   1632:                        ++((fsobj_id_t *)attrbufptr);
                   1633:                };
                   1634:                VCB_LOCK(vcb);
                   1635:         if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = vcb->volumeNameEncodingHint;
                   1636:                /* NOTE: all VCB dates are in local Mac OS time */
                   1637:                if (a & ATTR_CMN_CRTIME) {
                   1638:                        /*
                   1639:                         * HFS Plus stores the volume create date in *local*
                   1640:                         * time in the volume header. So don't use the create
                   1641:                         * date from the vcb. Use the root's crtime instead.
                   1642:                         */
                   1643:                        if (vcb->vcbSigWord == kHFSPlusSigWord) {
                   1644:                                ((struct timespec *)attrbufptr)->tv_sec = root_hp->h_meta->h_crtime;
                   1645:                        } else {
                   1646:                                ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbCrDate);
                   1647:                        }
                   1648:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1649:                        ++((struct timespec *)attrbufptr);
                   1650:                };
                   1651:                if (a & ATTR_CMN_MODTIME) {
                   1652:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbLsMod);
                   1653:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1654:                        ++((struct timespec *)attrbufptr);
                   1655:                };
                   1656:                if (a & ATTR_CMN_CHGTIME) {
                   1657:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbLsMod);
                   1658:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1659:                        ++((struct timespec *)attrbufptr);
                   1660:                };
                   1661:                if (a & ATTR_CMN_ACCTIME) {
                   1662:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbLsMod);
                   1663:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1664:                        ++((struct timespec *)attrbufptr);
                   1665:                };
                   1666:                if (a & ATTR_CMN_BKUPTIME) {
                   1667:                        ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbVolBkUp);
                   1668:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1669:                        ++((struct timespec *)attrbufptr);
                   1670:                };
                   1671:                if (a & ATTR_CMN_FNDRINFO) {
                   1672:             bcopy (&vcb->vcbFndrInfo, attrbufptr, sizeof(vcb->vcbFndrInfo));
                   1673:             attrbufptr += sizeof(vcb->vcbFndrInfo);
                   1674:                };
                   1675:                VCB_UNLOCK(vcb);
                   1676:                if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = root_hp->h_meta->h_uid;
                   1677:                if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = root_hp->h_meta->h_gid;
                   1678:                if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)root_hp->h_meta->h_mode;
                   1679:                if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0;                 /* XXX PPD TBC */
                   1680:                if (a & ATTR_CMN_NAMEDATTRLIST) {
                   1681:                        attrlength = 0;
                   1682:             ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
                   1683:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1684:                        
                   1685:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1686:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1687:             ++((struct attrreference *)attrbufptr);
                   1688:                };
                   1689:                if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = root_hp->h_meta->h_pflags;
                   1690:        };
                   1691:        
                   1692:        *attrbufptrptr = attrbufptr;
                   1693:        *varbufptrptr = varbufptr;
                   1694: }
                   1695: 
                   1696: 
                   1697: 
                   1698: void PackVolAttributeBlock(struct attrlist *alist,
                   1699:                                                   struct vnode *root_vp,
                   1700:                                                   struct hfsCatalogInfo *root_catInfo,
                   1701:                                                   void **attrbufptrptr,
                   1702:                                                   void **varbufptrptr) {
                   1703:     void *attrbufptr;
                   1704:     void *varbufptr;
                   1705:     attrgroup_t a;
                   1706:     struct mount *mp = VTOVFS(root_vp);
                   1707:     struct hfsmount *hfsmp = VTOHFS(root_vp);
                   1708:     struct ExtendedVCB *vcb = HFSTOVCB(hfsmp);
                   1709:        u_long attrlength;
                   1710:        
                   1711:        attrbufptr = *attrbufptrptr;
                   1712:        varbufptr = *varbufptrptr;
                   1713:        
                   1714:        if ((a = alist->volattr) != 0) {
                   1715:                VCB_LOCK(vcb);
                   1716:                if (a & ATTR_VOL_FSTYPE) *((u_long *)attrbufptr)++ = (u_long)mp->mnt_vfc->vfc_typenum;
                   1717:                if (a & ATTR_VOL_SIGNATURE) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbSigWord;
                   1718:         if (a & ATTR_VOL_SIZE) *((off_t *)attrbufptr)++ = (off_t)vcb->totalBlocks * (off_t)vcb->blockSize;
                   1719:         if (a & ATTR_VOL_SPACEFREE) *((off_t *)attrbufptr)++ = (off_t)vcb->freeBlocks * (off_t)vcb->blockSize;
                   1720:         if (a & ATTR_VOL_SPACEAVAIL) *((off_t *)attrbufptr)++ = (off_t)vcb->freeBlocks * (off_t)vcb->blockSize;
                   1721:         if (a & ATTR_VOL_MINALLOCATION) *((off_t *)attrbufptr)++ = (off_t)vcb->blockSize;
                   1722:                if (a & ATTR_VOL_ALLOCATIONCLUMP) *((off_t *)attrbufptr)++ = (off_t)vcb->allocationsClumpSize;
                   1723:         if (a & ATTR_VOL_IOBLOCKSIZE) *((u_long *)attrbufptr)++ = (u_long)hfsmp->hfs_log_block_size;
                   1724:                if (a & ATTR_VOL_OBJCOUNT) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbFilCnt + (u_long)vcb->vcbDirCnt;
                   1725:                if (a & ATTR_VOL_FILECOUNT) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbFilCnt;
                   1726:                if (a & ATTR_VOL_DIRCOUNT) *((u_long *)attrbufptr)++ = (u_long)vcb->vcbDirCnt;
                   1727:                if (a & ATTR_VOL_MAXOBJCOUNT) *((u_long *)attrbufptr)++ = 0xFFFFFFFF;
                   1728:                if (a & ATTR_VOL_MOUNTPOINT) {
                   1729:                        attrlength = strlen(hfsmp->hfs_mountpoint) + 1;
                   1730:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
                   1731:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1732:                        (void) strcpy((unsigned char *)varbufptr, hfsmp->hfs_mountpoint);
                   1733:                        
                   1734:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1735:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1736:             ++((struct attrreference *)attrbufptr);
                   1737:                };
                   1738:         if (a & ATTR_VOL_NAME) {
                   1739:             attrlength = VTOH(root_vp)->h_meta->h_namelen + 1;
                   1740:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
                   1741:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1742:             strncpy((char *)varbufptr, H_NAME(VTOH(root_vp)), attrlength);
                   1743: 
                   1744:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1745:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1746:             ++((struct attrreference *)attrbufptr);
                   1747:         };
                   1748:         if (a & ATTR_VOL_MOUNTFLAGS) *((u_long *)attrbufptr)++ = (u_long)mp->mnt_flag;
                   1749:                VCB_UNLOCK(vcb);
                   1750:        };
                   1751:        
                   1752:        *attrbufptrptr = attrbufptr;
                   1753:        *varbufptrptr = varbufptr;
                   1754: }
                   1755: 
                   1756: 
                   1757: 
                   1758: 
                   1759: void PackVolumeInfo(struct attrlist *alist,
                   1760:                     struct vnode *root_vp,
                   1761:                     struct hfsCatalogInfo *root_catinfo,
                   1762:                     void **attrbufptrptr,
                   1763:                     void **varbufptrptr) {
                   1764: 
                   1765:     PackVolCommonAttributes(alist, root_vp, root_catinfo, attrbufptrptr, varbufptrptr);
                   1766:     PackVolAttributeBlock(alist, root_vp, root_catinfo, attrbufptrptr, varbufptrptr);
                   1767: };
                   1768: 
                   1769: // Pack the common attribute contents of an objects hfsCatalogInfo
                   1770: void PackCommonCatalogInfoAttributeBlock(struct attrlist               *alist,
                   1771:                                                                                struct vnode                    *root_vp,
                   1772:                                                                                struct hfsCatalogInfo   *catalogInfo,
                   1773:                                                                                void                                    **attrbufptrptr,
                   1774:                                                                                void                                    **varbufptrptr )
                   1775: {
                   1776:        struct hfsnode  *hp;
                   1777:        void                    *attrbufptr;
                   1778:        void                    *varbufptr;
                   1779:        attrgroup_t             a;
                   1780:        u_long                  attrlength;
                   1781:        
                   1782:        hp                      = VTOH(root_vp);
                   1783:        attrbufptr      = *attrbufptrptr;
                   1784:        varbufptr       = *varbufptrptr;
                   1785:        
                   1786:        if ((a = alist->commonattr) != 0)
                   1787:        {
                   1788:                if (a & ATTR_CMN_NAME)                                                                          
                   1789:             {
                   1790:             attrlength = strlen(catalogInfo->spec.name) + 1;
                   1791:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
                   1792:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1793:             (void) strncpy((unsigned char *)varbufptr, (unsigned char *) &(catalogInfo->spec.name), attrlength);
                   1794:             // ((char *) varbufptr)[attrlength-1] = 0;                                                                 //      Now it's a C string
                   1795: 
                   1796:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1797:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1798:             ++((struct attrreference *)attrbufptr);
                   1799:             };
                   1800:                if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++                        = hp->h_dev;
                   1801:                if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++                        = VTOVFS(root_vp)->mnt_stat.f_fsid;
                   1802:                if (a & ATTR_CMN_OBJTYPE)
                   1803:                {
                   1804:                        if ( catalogInfo->nodeData.nodeType == kCatalogFolderNode )
                   1805:                                *((fsobj_type_t *)attrbufptr)++ = VDIR;
                   1806:                        else                                                                                                            //XXX could be more robust in object type handling
                   1807:                                *((fsobj_type_t *)attrbufptr)++ = VREG;
                   1808:                }
                   1809:                if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++         = root_vp->v_tag;
                   1810:         if (a & ATTR_CMN_OBJID)
                   1811:         {
                   1812:             ((fsobj_id_t *)attrbufptr)->fid_objno                                      = catalogInfo->nodeData.nodeID; //      H_FILEID(hp);
                   1813:             ((fsobj_id_t *)attrbufptr)->fid_generation                         = 0;
                   1814:             ++((fsobj_id_t *)attrbufptr);
                   1815:         };
                   1816:         if (a & ATTR_CMN_OBJPERMANENTID)
                   1817:         {
                   1818:             ((fsobj_id_t *)attrbufptr)->fid_objno                                      = catalogInfo->nodeData.nodeID; //      H_FILEID(hp);
                   1819:             ((fsobj_id_t *)attrbufptr)->fid_generation                         = 0;
                   1820:             ++((fsobj_id_t *)attrbufptr);
                   1821:         };
                   1822:                if (a & ATTR_CMN_PAROBJID)
                   1823:                {
                   1824:             ((fsobj_id_t *)attrbufptr)->fid_objno                                      = catalogInfo->spec.parID;              //      H_DIRID(hp);
                   1825:                        ((fsobj_id_t *)attrbufptr)->fid_generation                              = 0;
                   1826:                        ++((fsobj_id_t *)attrbufptr);
                   1827:                };
                   1828:         if (a & ATTR_CMN_SCRIPT)
                   1829:          {
                   1830:            if (HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) {
                   1831:                        *((text_encoding_t *)attrbufptr)++ = catalogInfo->nodeData.textEncoding;
                   1832:            } else {
                   1833:                        *((text_encoding_t *)attrbufptr)++ = 0;
                   1834:            }
                   1835:          };
                   1836:                if (a & ATTR_CMN_CRTIME)
                   1837:                {
                   1838:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.createDate);
                   1839:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
                   1840:                        ++((struct timespec *)attrbufptr);
                   1841:                };
                   1842:                if (a & ATTR_CMN_MODTIME)
                   1843:                {
                   1844:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.contentModDate);
                   1845:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
                   1846:                        ++((struct timespec *)attrbufptr);
                   1847:                };
                   1848:                if (a & ATTR_CMN_CHGTIME)
                   1849:                {
                   1850:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.attributeModDate);
                   1851:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
                   1852:                        ++((struct timespec *)attrbufptr);
                   1853:                };
                   1854:                if (a & ATTR_CMN_ACCTIME)
                   1855:                {
                   1856:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.accessDate);
                   1857:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
                   1858:                        ++((struct timespec *)attrbufptr);
                   1859:                };
                   1860:                if (a & ATTR_CMN_BKUPTIME)
                   1861:                {
                   1862:                        ((struct timespec *)attrbufptr)->tv_sec                                 = to_bsd_time(catalogInfo->nodeData.backupDate);
                   1863:                        ((struct timespec *)attrbufptr)->tv_nsec                                = 0;
                   1864:                        ++((struct timespec *)attrbufptr);
                   1865:                };
                   1866:                if (a & ATTR_CMN_FNDRINFO)
                   1867:                {
                   1868:                        bcopy (&catalogInfo->nodeData.finderInfo, attrbufptr, sizeof(catalogInfo->nodeData.finderInfo));
                   1869:                        attrbufptr += sizeof(catalogInfo->nodeData.finderInfo);
                   1870:                        bcopy (&catalogInfo->nodeData.extFinderInfo, attrbufptr, sizeof(catalogInfo->nodeData.extFinderInfo));
                   1871:                        attrbufptr += sizeof(catalogInfo->nodeData.extFinderInfo);
                   1872:                };
                   1873:                if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++                      = catalogInfo->nodeData.permissions.ownerID;
                   1874:                if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++                        = catalogInfo->nodeData.permissions.groupID;
                   1875:                if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++          = (u_long)(mode_t)(catalogInfo->nodeData.permissions.permissions & 0x0000FFFF);
                   1876:                if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++      = 0;                    /* XXX PPD TBC */
                   1877:                if (a & ATTR_CMN_NAMEDATTRLIST)
                   1878:                {
                   1879:                        attrlength = 0;
                   1880:                        ((struct attrreference *)attrbufptr)->attr_dataoffset   = 0;
                   1881:                        ((struct attrreference *)attrbufptr)->attr_length               = attrlength;
                   1882:                        
                   1883:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1884:                        varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1885:                        ++((struct attrreference *)attrbufptr);
                   1886:                };
                   1887:         if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++                      = (u_long)((((catalogInfo->nodeData.permissions.permissions & 0xFFFF0000) >> 8)  & 0x00FF0000) |
                   1888:                                                                                (((catalogInfo->nodeData.permissions.permissions & 0xFFFF0000) >> 24) & 0x000000FF));
                   1889:        };
                   1890:        
                   1891:        *attrbufptrptr  = attrbufptr;
                   1892:        *varbufptrptr   = varbufptr;
                   1893: }
                   1894: 
                   1895: 
                   1896: void PackCommonAttributeBlock(struct attrlist *alist,
                   1897:                                                          struct vnode *vp,
                   1898:                                                          struct hfsCatalogInfo *catInfo,
                   1899:                                                          void **attrbufptrptr,
                   1900:                                                          void **varbufptrptr) {
                   1901:        struct hfsnode *hp;
                   1902:     void *attrbufptr;
                   1903:     void *varbufptr;
                   1904:     attrgroup_t a;
                   1905:        u_long attrlength;
                   1906:        
                   1907:        hp = VTOH(vp);
                   1908:        
                   1909:        attrbufptr = *attrbufptrptr;
                   1910:        varbufptr = *varbufptrptr;
                   1911:        
                   1912:     if ((a = alist->commonattr) != 0) {
                   1913:         if (a & ATTR_CMN_NAME) {
                   1914:             attrlength = hp->h_meta->h_namelen + 1;
                   1915:             ((struct attrreference *)attrbufptr)->attr_dataoffset = varbufptr - attrbufptr;
                   1916:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1917:             (void) strncpy((unsigned char *)varbufptr, H_NAME(hp), attrlength);
                   1918: 
                   1919:             /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1920:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1921:             ++((struct attrreference *)attrbufptr);
                   1922:         };
                   1923:                if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = hp->h_dev;
                   1924:                if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = VTOVFS(vp)->mnt_stat.f_fsid;
                   1925:                if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = vp->v_type;
                   1926:                if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = vp->v_tag;
                   1927:         if (a & ATTR_CMN_OBJID)        {
                   1928:             ((fsobj_id_t *)attrbufptr)->fid_objno = H_FILEID(hp);
                   1929:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
                   1930:                        ++((fsobj_id_t *)attrbufptr);
                   1931:                };
                   1932:         if (a & ATTR_CMN_OBJPERMANENTID)       {
                   1933:             ((fsobj_id_t *)attrbufptr)->fid_objno = H_FILEID(hp);
                   1934:             ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
                   1935:             ++((fsobj_id_t *)attrbufptr);
                   1936:         };
                   1937:                if (a & ATTR_CMN_PAROBJID) {
                   1938:             ((fsobj_id_t *)attrbufptr)->fid_objno = H_DIRID(hp);
                   1939:                        ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
                   1940:                        ++((fsobj_id_t *)attrbufptr);
                   1941:                };
                   1942:         if (a & ATTR_CMN_SCRIPT)
                   1943:          {
                   1944:            if (HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) {
                   1945:                        *((text_encoding_t *)attrbufptr)++ = catInfo->nodeData.textEncoding;
                   1946:            } else {
                   1947:                        *((text_encoding_t *)attrbufptr)++ = 0;
                   1948:            }
                   1949:          };
                   1950:                if (a & ATTR_CMN_CRTIME) {
                   1951:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_crtime;
                   1952:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1953:                        ++((struct timespec *)attrbufptr);
                   1954:                };
                   1955:                if (a & ATTR_CMN_MODTIME) {
                   1956:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_mtime;
                   1957:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1958:                        ++((struct timespec *)attrbufptr);
                   1959:                };
                   1960:                if (a & ATTR_CMN_CHGTIME) {
                   1961:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_ctime;
                   1962:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1963:                        ++((struct timespec *)attrbufptr);
                   1964:                };
                   1965:                if (a & ATTR_CMN_ACCTIME) {
                   1966:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_atime;
                   1967:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1968:                        ++((struct timespec *)attrbufptr);
                   1969:                };
                   1970:                if (a & ATTR_CMN_BKUPTIME) {
                   1971:                        ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_butime;
                   1972:                        ((struct timespec *)attrbufptr)->tv_nsec = 0;
                   1973:                        ++((struct timespec *)attrbufptr);
                   1974:                };
                   1975:                if (a & ATTR_CMN_FNDRINFO) {
                   1976:             bcopy (&catInfo->nodeData.finderInfo, attrbufptr, sizeof(catInfo->nodeData.finderInfo));
                   1977:             attrbufptr += sizeof(catInfo->nodeData.finderInfo);
                   1978:             bcopy (&catInfo->nodeData.extFinderInfo, attrbufptr, sizeof(catInfo->nodeData.extFinderInfo));
                   1979:             attrbufptr += sizeof(catInfo->nodeData.extFinderInfo);
                   1980:                };
                   1981:                if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = hp->h_meta->h_uid;
                   1982:                if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = hp->h_meta->h_gid;
                   1983:                if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)hp->h_meta->h_mode;
                   1984:                if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0;                 /* XXX PPD TBC */
                   1985:                if (a & ATTR_CMN_NAMEDATTRLIST) {
                   1986:                        attrlength = 0;
                   1987:             ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
                   1988:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   1989:                        
                   1990:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   1991:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   1992:             ++((struct attrreference *)attrbufptr);
                   1993:                };
                   1994:                if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = hp->h_meta->h_pflags;
                   1995:        };
                   1996:        
                   1997:        *attrbufptrptr = attrbufptr;
                   1998:        *varbufptrptr = varbufptr;
                   1999: }
                   2000: 
                   2001: 
                   2002: //     Pack the directory attributes given hfsCatalogInfo
                   2003: void PackCatalogInfoDirAttributeBlock( struct attrlist *alist, struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr )
                   2004: {
                   2005:        void            *attrbufptr;
                   2006:        attrgroup_t     a;
                   2007:        
                   2008:        attrbufptr      = *attrbufptrptr;
                   2009:        a                       = alist->dirattr;
                   2010:        
                   2011:        if ( (catInfo->nodeData.nodeType == kCatalogFolderNode) && (a != 0) )
                   2012:        {
                   2013:                /* 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. */
                   2014:                if (a & ATTR_DIR_LINKCOUNT) *((u_long *)attrbufptr)++   = 2;
                   2015:                if (a & ATTR_DIR_ENTRYCOUNT) *((u_long *)attrbufptr)++  = catInfo->nodeData.valence;
                   2016:        };
                   2017:        
                   2018:        *attrbufptrptr = attrbufptr;
                   2019: }
                   2020: 
                   2021: 
                   2022: void PackDirAttributeBlock(struct attrlist *alist,
                   2023:                                                   struct vnode *vp,
                   2024:                                                   struct hfsCatalogInfo *catInfo,
                   2025:                                                   void **attrbufptrptr,
                   2026:                                                   void **varbufptrptr) {
                   2027:     void *attrbufptr;
                   2028: //     void *varbufptr;
                   2029:     attrgroup_t a;
                   2030: //     u_long attrlength;
                   2031:        
                   2032:        attrbufptr = *attrbufptrptr;
                   2033: //     varbufptr = *varbufptrptr;
                   2034:        
                   2035:        a = alist->dirattr;
                   2036:        if ((vp->v_type == VDIR) && (a != 0)) {
                   2037:                /* The 'link count' is faked as 1 (the parent entry and ".").  In reality it would include at least
                   2038:                   an additional link for the ".." in each subdirectory. */
                   2039:                if (a & ATTR_DIR_LINKCOUNT) *((u_long *)attrbufptr)++ = 2;
                   2040:                if (a & ATTR_DIR_ENTRYCOUNT) *((u_long *)attrbufptr)++ = catInfo->nodeData.valence;
                   2041:        };
                   2042:        
                   2043:        *attrbufptrptr = attrbufptr;
                   2044: //     *varbufptrptr = varbufptr;
                   2045: }
                   2046: 
                   2047: 
                   2048: 
                   2049: //     Pack the file attributes from the hfsCatalogInfo for the file.
                   2050: void PackCatalogInfoFileAttributeBlock( struct attrlist *alist, struct hfsCatalogInfo *catInfo, struct vnode *root_vp, void **attrbufptrptr, void **varbufptrptr )
                   2051: {
                   2052:        void                    *attrbufptr;
                   2053:        void                    *varbufptr;
                   2054:        attrgroup_t             a;
                   2055:        u_long                  attrlength;
                   2056:        ExtendedVCB             *vcb                    = VTOVCB(root_vp);
                   2057:        
                   2058:        attrbufptr      = *attrbufptrptr;
                   2059:        varbufptr       = *varbufptrptr;
                   2060:        
                   2061:        a = alist->fileattr;
                   2062:        if ( (catInfo->nodeData.nodeType == kCatalogFileNode) && (a != 0) )
                   2063:        {
                   2064:                if (a & ATTR_FILE_LINKCOUNT) *((u_long *)attrbufptr)++          = 1;            /* There ARE no hard links... */
                   2065:                if (a & ATTR_FILE_TOTALSIZE) *((off_t *)attrbufptr)++           = (off_t)catInfo->nodeData.dataLogicalSize + (off_t)catInfo->nodeData.rsrcLogicalSize;
                   2066:                if (a & ATTR_FILE_ALLOCSIZE) *((off_t *)attrbufptr)++           = (off_t)catInfo->nodeData.dataPhysicalSize + (off_t)catInfo->nodeData.rsrcPhysicalSize;
                   2067:         if (a & ATTR_FILE_IOBLOCKSIZE) *((u_long *)attrbufptr)++       = (u_long)(VTOHFS(root_vp)->hfs_log_block_size);
                   2068:                if (a & ATTR_FILE_CLUMPSIZE) *((u_long *)attrbufptr)++          = vcb->vcbClpSiz;       //XXX Yikes, this is just the vcb clump size
                   2069:                if (a & ATTR_FILE_DEVTYPE) *((u_long *)attrbufptr)++            = (u_long)catInfo->nodeData.permissions.specialDevice;
                   2070:                if (a & ATTR_FILE_FILETYPE) *((u_long *)attrbufptr)++           = 0;                    /* XXX PPD */
                   2071:                if (a & ATTR_FILE_FORKCOUNT) *((u_long *)attrbufptr)++          = 2;                    /* XXX PPD */
                   2072:                if (a & ATTR_FILE_FORKLIST)
                   2073:                {
                   2074:                        attrlength = 0;
                   2075:                        ((struct attrreference *)attrbufptr)->attr_dataoffset   = 0;
                   2076:                        ((struct attrreference *)attrbufptr)->attr_length               = attrlength;
                   2077:                        
                   2078:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   2079:                        varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   2080:                        ++((struct attrreference *)attrbufptr);
                   2081:                };
                   2082:                if (a & ATTR_FILE_DATALENGTH) *((off_t *)attrbufptr)++          = (off_t)catInfo->nodeData.dataLogicalSize;
                   2083:                if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++       = (off_t)catInfo->nodeData.dataPhysicalSize;
                   2084:                if (a & ATTR_FILE_DATAEXTENTS)
                   2085:                {
                   2086:                        bcopy(&catInfo->nodeData.dataExtents, attrbufptr, sizeof(extentrecord));
                   2087:                        attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
                   2088:                };
                   2089:                if (a & ATTR_FILE_RSRCLENGTH) *((off_t *)attrbufptr)++          = (off_t)catInfo->nodeData.rsrcLogicalSize;
                   2090:                if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++       = (off_t)catInfo->nodeData.rsrcPhysicalSize;
                   2091:                if (a & ATTR_FILE_RSRCEXTENTS)
                   2092:                {
                   2093:                        bcopy(&catInfo->nodeData.rsrcExtents, attrbufptr, sizeof(extentrecord));
                   2094:                        attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
                   2095:                };
                   2096:        };
                   2097:        
                   2098:        *attrbufptrptr  = attrbufptr;
                   2099:        *varbufptrptr   = varbufptr;
                   2100: }
                   2101: 
                   2102: 
                   2103: void PackFileAttributeBlock(struct attrlist *alist,
                   2104:                                                        struct vnode *vp,
                   2105:                                                        struct hfsCatalogInfo *catInfo,
                   2106:                                                        void **attrbufptrptr,
                   2107:                                                        void **varbufptrptr) {
                   2108:     struct hfsnode *hp = VTOH(vp);
                   2109:     FCB *fcb = HTOFCB(hp);
                   2110:     ExtendedFCB *extendedFCB;
                   2111:     HFSPlusExtentDescriptor *parellextents;
                   2112:        ExtendedVCB *vcb = HTOVCB(hp);
                   2113:     Boolean isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
                   2114:     void *attrbufptr = *attrbufptrptr;
                   2115:     void *varbufptr = *varbufptrptr;
                   2116:     attrgroup_t a = alist->fileattr;
                   2117:        u_long attrlength;
                   2118:        
                   2119:        if ((vp->v_type == VREG) && (a != 0)) {
                   2120:                if (a & ATTR_FILE_LINKCOUNT) *((u_long *)attrbufptr)++ = 1;             /* There ARE no hard links... */
                   2121:                if (a & ATTR_FILE_TOTALSIZE) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataLogicalSize +
                   2122:                                                                                                                                (off_t)catInfo->nodeData.rsrcLogicalSize;
                   2123:                if (a & ATTR_FILE_ALLOCSIZE) {
                   2124:                        switch (H_FORKTYPE(hp)) {
                   2125:                          case kDataFork:
                   2126:                                *((off_t *)attrbufptr)++ = (off_t)fcb->fcbPLen + (off_t)catInfo->nodeData.rsrcPhysicalSize;
                   2127:                          case kRsrcFork:
                   2128:                                *((off_t *)attrbufptr)++ = (off_t)fcb->fcbPLen + (off_t)catInfo->nodeData.dataPhysicalSize;
                   2129:                          default:
                   2130:                                *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataPhysicalSize +
                   2131:                                                                                   (off_t)catInfo->nodeData.rsrcPhysicalSize;
                   2132:                  };
                   2133:                }; 
                   2134:                if (a & ATTR_FILE_IOBLOCKSIZE) *((u_long *)attrbufptr)++ = hp->h_meta->h_logBlockSize;
                   2135:                if (a & ATTR_FILE_CLUMPSIZE) *((u_long *)attrbufptr)++ = fcb->fcbClmpSize;
                   2136:                if (a & ATTR_FILE_DEVTYPE) *((u_long *)attrbufptr)++ = (u_long)catInfo->nodeData.permissions.specialDevice;
                   2137:                if (a & ATTR_FILE_FILETYPE) *((u_long *)attrbufptr)++ = 0;                      /* XXX PPD */
                   2138:                if (a & ATTR_FILE_FORKCOUNT) *((u_long *)attrbufptr)++ = 2;                     /* XXX PPD */
                   2139:                if (a & ATTR_FILE_FORKLIST) {
                   2140:                        attrlength = 0;
                   2141:             ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
                   2142:             ((struct attrreference *)attrbufptr)->attr_length = attrlength;
                   2143:                        
                   2144:                        /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
                   2145:             varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
                   2146:             ++((struct attrreference *)attrbufptr);
                   2147:                };
                   2148:                if (H_FORKTYPE(hp) == kDataFork) {
                   2149:                        if (a & ATTR_FILE_DATALENGTH)
                   2150: #if    MACH_NBC
                   2151:                 if ((vp->v_type == VREG) && vp->v_vm_info && vp->v_vm_info->mapped &&
                   2152:                     (!vp->v_vm_info->filesize)) {
                   2153:                     *((off_t *)attrbufptr)++ = vp->v_vm_info->vnode_size;
                   2154:                 }
                   2155:                 else
                   2156: #endif /* MACH_NBC */
                   2157:                    *((off_t *)attrbufptr)++ = fcb->fcbEOF;
                   2158:                        if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++ = fcb->fcbPLen;
                   2159:                        if (a & ATTR_FILE_DATAEXTENTS) {
                   2160:                            if ( ! isHFSPlus) {
                   2161:                                /* HFS, Copy the extents from the FCB part */
                   2162:                                int i;
                   2163:                                HFSPlusExtentRecord extents;
                   2164:                                for (i = 0; i < kHFSExtentDensity; ++i) {
                   2165:                                    extents[i].startBlock = (UInt16) (fcb->fcbExtRec[i].startBlock);
                   2166:                                    extents[i].blockCount = (UInt16) (fcb->fcbExtRec[i].blockCount);
                   2167:                                };
                   2168:                                bcopy ( extents, attrbufptr, sizeof(extentrecord));
                   2169:                            } else {
                   2170:                                /* HFSPlus, Copy the extents from the parallel extents */
                   2171:                                extendedFCB = GetParallelFCB (HTOV(hp));
                   2172:                                parellextents = extendedFCB->extents;
                   2173:                                bcopy ( parellextents, attrbufptr, sizeof(extentrecord));
                   2174:                            };
                   2175:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
                   2176:                        };
                   2177:                } else {
                   2178:                        if (a & ATTR_FILE_DATALENGTH) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataLogicalSize;
                   2179:                        if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.dataPhysicalSize;
                   2180:                        if (a & ATTR_FILE_DATAEXTENTS) {
                   2181:                                bcopy(&catInfo->nodeData.dataExtents, attrbufptr, sizeof(extentrecord));
                   2182:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
                   2183:                        };
                   2184:                };
                   2185:                if (H_FORKTYPE(hp) == kRsrcFork) {
                   2186:                        if (a & ATTR_FILE_RSRCLENGTH) 
                   2187: #if    MACH_NBC
                   2188:                 if ((vp->v_type == VREG) && vp->v_vm_info && vp->v_vm_info->mapped &&
                   2189:                     (!vp->v_vm_info->filesize)) {
                   2190:                     *((off_t *)attrbufptr)++ = vp->v_vm_info->vnode_size;
                   2191:                 }
                   2192:                 else
                   2193: #endif /* MACH_NBC */
                   2194:                    *((off_t *)attrbufptr)++ = fcb->fcbEOF;
                   2195:                        if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++ = fcb->fcbPLen;
                   2196:                        if (a & ATTR_FILE_RSRCEXTENTS) {
                   2197:                            if ( ! isHFSPlus) {
                   2198:                                /* HFS, Copy the extents from the FCB part */
                   2199:                                int i;
                   2200:                                HFSPlusExtentRecord extents;
                   2201:                                for (i = 0; i < kHFSExtentDensity; ++i) {
                   2202:                                    extents[i].startBlock = (UInt16) (fcb->fcbExtRec[i].startBlock);
                   2203:                                    extents[i].blockCount = (UInt16) (fcb->fcbExtRec[i].blockCount);
                   2204:                                };
                   2205:                                bcopy ( extents, attrbufptr, sizeof(extentrecord));
                   2206:                            } else {
                   2207:                                /* HFSPlus, Copy the extents from the parallel extents */
                   2208:                                extendedFCB = GetParallelFCB (HTOV(hp));
                   2209:                                parellextents = extendedFCB->extents;
                   2210:                                bcopy ( parellextents, attrbufptr, sizeof(extentrecord));
                   2211:                            };
                   2212:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
                   2213:                        };
                   2214:                } else {
                   2215:                        if (a & ATTR_FILE_RSRCLENGTH) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.rsrcLogicalSize;
                   2216:                        if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++ = (off_t)catInfo->nodeData.rsrcPhysicalSize;
                   2217:                        if (a & ATTR_FILE_RSRCEXTENTS) {
                   2218:                                bcopy(&catInfo->nodeData.rsrcExtents, attrbufptr, sizeof(extentrecord));
                   2219:                                attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
                   2220:                        };
                   2221:                };
                   2222:        };
                   2223:        
                   2224:        *attrbufptrptr = attrbufptr;
                   2225:        *varbufptrptr = varbufptr;
                   2226: }
                   2227: 
                   2228: #if 0
                   2229: void PackForkAttributeBlock(struct attrlist *alist,
                   2230:                                                        struct vnode *vp,
                   2231:                                                        struct hfsCatalogInfo *catInfo,
                   2232:                                                        void **attrbufptrptr,
                   2233:                                                        void **varbufptrptr) {
                   2234:        /* XXX PPD TBC */
                   2235: }
                   2236: #endif
                   2237: 
                   2238: 
                   2239: //     This routine takes catInfo, and alist, as inputs and packs it into an attribute block.
                   2240: void PackCatalogInfoAttributeBlock ( struct attrlist *alist, struct vnode *root_vp, struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr)
                   2241: {
                   2242:        //XXX   Preflight that alist only contains bits with fields in catInfo
                   2243: 
                   2244:        PackCommonCatalogInfoAttributeBlock( alist, root_vp, catInfo, attrbufptrptr, varbufptrptr );
                   2245:        
                   2246:        switch ( catInfo->nodeData.nodeType )
                   2247:        {
                   2248:                case kCatalogFolderNode:
                   2249:                        PackCatalogInfoDirAttributeBlock( alist, catInfo, attrbufptrptr, varbufptrptr );
                   2250:                        break;
                   2251:                
                   2252:                case kCatalogFileNode:
                   2253:                        PackCatalogInfoFileAttributeBlock( alist, catInfo, root_vp, attrbufptrptr, varbufptrptr );
                   2254:                        break;
                   2255:          
                   2256:                default:        /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR not being handled... */
                   2257:                        /* XXX PPD - Panic? */
                   2258:                        break;
                   2259:        }
                   2260: }
                   2261: 
                   2262: 
                   2263: 
                   2264: void PackAttributeBlock(struct attrlist *alist,
                   2265:                                                struct vnode *vp,
                   2266:                                                struct hfsCatalogInfo *catInfo,
                   2267:                                                void **attrbufptrptr,
                   2268:                                                void **varbufptrptr) {
                   2269: 
                   2270: //  DBG_FUNC_NAME("PackAttributeBlock");
                   2271: 
                   2272:        if (alist->volattr != 0) {
                   2273:                DBG_ASSERT((vp->v_flag & VROOT) != 0);
                   2274:                PackVolumeInfo(alist,vp, catInfo, attrbufptrptr, varbufptrptr);
                   2275:        } else {
                   2276:                PackCommonAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2277:                
                   2278:                switch (vp->v_type) {
                   2279:                  case VDIR:
                   2280:                        PackDirAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2281:                        break;
                   2282:                        
                   2283:                  case VREG:
                   2284:           /* case VCPLX: */                    /* XXX PPD TBC */
                   2285:                        PackFileAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2286:                        break;
                   2287:                  
                   2288:        #if 0                                                   /* XXX PPD TBC */
                   2289:                  case VFORK:
                   2290:                        PackForkAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2291:                        break;
                   2292:        #endif
                   2293:                  
                   2294:                  /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
                   2295:                     not being handled...
                   2296:                   */
                   2297:                  default:
                   2298:                        /* XXX PPD - Panic? */
                   2299:                        break;
                   2300:                };
                   2301:        };
                   2302: };
                   2303: 
                   2304: 
                   2305: 
                   2306: void UnpackVolumeAttributeBlock(struct attrlist *alist,
                   2307:                                                                struct vnode *root_vp,
                   2308:                                                                ExtendedVCB *vcb,
                   2309:                                                                void **attrbufptrptr,
                   2310:                                                                void **varbufptrptr) {
                   2311:        void *attrbufptr = *attrbufptrptr;
                   2312:        attrgroup_t a;
                   2313:        text_encoding_t nameEncoding;
                   2314:        
                   2315:     if ((alist->commonattr == 0) && (alist->volattr == 0)) {
                   2316:         return;                /* Get out without dirtying the VCB */
                   2317:     };
                   2318: 
                   2319:     VCB_LOCK(vcb);
                   2320: 
                   2321:        a = alist->commonattr;
                   2322:        
                   2323:        if (a & ATTR_CMN_SCRIPT) {
                   2324:                /* XXX PPD No use for this info right now... */
                   2325:                nameEncoding = *(((text_encoding_t *)attrbufptr)++);
                   2326: #if DIAGNOSTIC
                   2327:                a &= ~ATTR_CMN_SCRIPT;
                   2328: #endif
                   2329:        };
                   2330:        if (a & ATTR_CMN_CRTIME) {
                   2331:                /*
                   2332:                 * HFS Plus stores the volume create date in *local*
                   2333:                 * time in the volume header. So don't set the create
                   2334:                 * date in the vcb. Set the root's crtime instead.
                   2335:                 */
                   2336:                if (vcb->vcbSigWord == kHFSPlusSigWord) {
                   2337:                        VTOH(root_vp)->h_meta->h_crtime =
                   2338:                                        (UInt32)((struct timespec *)attrbufptr)->tv_sec;
                   2339:                } else {
                   2340:                        vcb->vcbCrDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2341:                }
                   2342:                ++((struct timespec *)attrbufptr);
                   2343: #if DIAGNOSTIC
                   2344:                a &= ~ATTR_CMN_CRTIME;
                   2345: #endif
                   2346:        };
                   2347:        if (a & ATTR_CMN_MODTIME) {
                   2348:                vcb->vcbLsMod = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2349:                ++((struct timespec *)attrbufptr);
                   2350: #if DIAGNOSTIC
                   2351:                a &= ~ATTR_CMN_MODTIME;
                   2352: #endif
                   2353:        };
                   2354:        if (a & ATTR_CMN_BKUPTIME) {
                   2355:                vcb->vcbVolBkUp = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2356:                ++((struct timespec *)attrbufptr);
                   2357: #if DIAGNOSTIC
                   2358:                a &= ~ATTR_CMN_BKUPTIME;
                   2359: #endif
                   2360:        };
                   2361:        if (a & ATTR_CMN_FNDRINFO) {
                   2362:                bcopy (attrbufptr, &vcb->vcbFndrInfo, sizeof(vcb->vcbFndrInfo));
                   2363:                attrbufptr += sizeof(vcb->vcbFndrInfo);
                   2364: #if DIAGNOSTIC
                   2365:                a &= ~ATTR_CMN_FNDRINFO;
                   2366: #endif
                   2367:        };
                   2368:        
                   2369:        DBG_ASSERT(a == 0);                             /* All common attributes for volumes must've been handled by now... */
                   2370: 
                   2371:        a = alist->volattr & ~ATTR_VOL_INFO;
                   2372:        if (a & ATTR_VOL_NAME) {
                   2373:         copystr(((char *)attrbufptr) + *((u_long *)attrbufptr), vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
                   2374:         attrbufptr += sizeof(struct attrreference);
                   2375: #if DIAGNOSTIC
                   2376:                a &= ~ATTR_VOL_NAME;
                   2377: #endif
                   2378:        };
                   2379:        
                   2380:        DBG_ASSERT(a == 0);                             /* All common attributes for volumes must've been handled by now... */
                   2381: 
                   2382:     vcb->vcbFlags |= 0xFF00;           // Mark the VCB dirty
                   2383: 
                   2384:     VCB_UNLOCK(vcb);
                   2385: }
                   2386: 
                   2387: 
                   2388: void UnpackCommonAttributeBlock(struct attrlist *alist,
                   2389:                                                                struct vnode *vp,
                   2390:                                                                struct hfsCatalogInfo *catInfo,
                   2391:                                                                void **attrbufptrptr,
                   2392:                                                                void **varbufptrptr) {
                   2393:        struct hfsnode *hp = VTOH(vp);
                   2394:     void *attrbufptr;
                   2395:     attrgroup_t a;
                   2396:        
                   2397:        attrbufptr = *attrbufptrptr;
                   2398: 
                   2399:     DBG_ASSERT(catInfo != NULL);
                   2400:        
                   2401:        a = alist->commonattr;
                   2402:        if (a & ATTR_CMN_SCRIPT) {
                   2403:                /* XXX PPD No use for this info right now... */
                   2404:                ++((text_encoding_t *)attrbufptr);
                   2405: #if DIAGNOSTIC
                   2406:                a &= ~ATTR_CMN_SCRIPT;
                   2407: #endif
                   2408:        };
                   2409:        if (a & ATTR_CMN_CRTIME) {
                   2410:                catInfo->nodeData.createDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2411:                VTOH(vp)->h_meta->h_crtime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
                   2412:                ++((struct timespec *)attrbufptr);
                   2413: #if DIAGNOSTIC
                   2414:                a &= ~ATTR_CMN_CRTIME;
                   2415: #endif
                   2416:        };
                   2417:        if (a & ATTR_CMN_MODTIME) {
                   2418:                catInfo->nodeData.contentModDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2419:                VTOH(vp)->h_meta->h_mtime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
                   2420:                ++((struct timespec *)attrbufptr);
                   2421: #if DIAGNOSTIC
                   2422:                a &= ~ATTR_CMN_MODTIME;
                   2423: #endif
                   2424:        };
                   2425:        if (a & ATTR_CMN_CHGTIME) {
                   2426:                catInfo->nodeData.attributeModDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2427:                VTOH(vp)->h_meta->h_ctime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
                   2428:                ++((struct timespec *)attrbufptr);
                   2429: #if DIAGNOSTIC
                   2430:                a &= ~ATTR_CMN_CHGTIME;
                   2431: #endif
                   2432:        };
                   2433:        if (a & ATTR_CMN_ACCTIME) {
                   2434:                catInfo->nodeData.accessDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2435:                VTOH(vp)->h_meta->h_atime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
                   2436:                ++((struct timespec *)attrbufptr);
                   2437: #if DIAGNOSTIC
                   2438:                a &= ~ATTR_CMN_ACCTIME;
                   2439: #endif
                   2440:        };
                   2441:        if (a & ATTR_CMN_BKUPTIME) {
                   2442:                catInfo->nodeData.backupDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
                   2443:                VTOH(vp)->h_meta->h_butime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
                   2444:                ++((struct timespec *)attrbufptr);
                   2445: #if DIAGNOSTIC
                   2446:                a &= ~ATTR_CMN_BKUPTIME;
                   2447: #endif
                   2448:        };
                   2449:        if (a & ATTR_CMN_FNDRINFO) {
                   2450:                bcopy (attrbufptr, &catInfo->nodeData.finderInfo, sizeof(catInfo->nodeData.finderInfo));
                   2451:                attrbufptr += sizeof(catInfo->nodeData.finderInfo);
                   2452:                bcopy (attrbufptr, &catInfo->nodeData.extFinderInfo, sizeof(catInfo->nodeData.extFinderInfo));
                   2453:                attrbufptr += sizeof(catInfo->nodeData.extFinderInfo);
                   2454: #if DIAGNOSTIC
                   2455:                a &= ~ATTR_CMN_FNDRINFO;
                   2456: #endif
                   2457:        };
                   2458:        if (a & ATTR_CMN_OWNERID) {
                   2459:         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
                   2460:                        u_int32_t uid = (u_int32_t)*((uid_t *)attrbufptr)++;
                   2461:                        if (uid != (uid_t)VNOVAL)
                   2462:                                hp->h_meta->h_uid = uid;        /* catalog will get updated by hfs_chown() */
                   2463:         }
                   2464:                else {
                   2465:             ((uid_t *)attrbufptr)++;
                   2466:                }
                   2467: #if DIAGNOSTIC
                   2468:                a &= ~ATTR_CMN_OWNERID;
                   2469: #endif
                   2470:        };
                   2471:        if (a & ATTR_CMN_GRPID) {
                   2472:         u_int32_t gid = (u_int32_t)*((gid_t *)attrbufptr)++;
                   2473:         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
                   2474:             if (gid != (gid_t)VNOVAL)
                   2475:                 hp->h_meta->h_gid = gid;                                       /* catalog will get updated by hfs_chown() */
                   2476:         };
                   2477: #if DIAGNOSTIC
                   2478:                a &= ~ATTR_CMN_GRPID;
                   2479: #endif
                   2480:        };
                   2481:        if (a & ATTR_CMN_ACCESSMASK) {
                   2482:         u_int16_t mode = (u_int16_t)*((u_long *)attrbufptr)++;
                   2483:         if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
                   2484:             if (mode != (mode_t)VNOVAL) {
                   2485:                 hp->h_meta->h_mode &= ~ALLPERMS;
                   2486:                 hp->h_meta->h_mode |= (mode & ALLPERMS);       /* catalog will get updated by hfs_chmod() */
                   2487:             }
                   2488:         };
                   2489: #if DIAGNOSTIC
                   2490:                a &= ~ATTR_CMN_ACCESSMASK;
                   2491: #endif
                   2492:        };
                   2493:        if (a & ATTR_CMN_FLAGS) {
                   2494:                u_long flags = *((u_long *)attrbufptr)++;
                   2495:         /* Flags are settable only on HFS+ volumes.  A special exception is made for the IMMUTABLE
                   2496:            flags (SF_IMMUTABLE and UF_IMMUTABLE), which can be set on HFS volumes as well: */
                   2497:         if ((VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) ||
                   2498:             ((VTOVCB(vp)->vcbSigWord == kHFSSigWord) && ((flags & ~IMMUTABLE) == 0))) {
                   2499:             if (flags != (u_long)VNOVAL) {
                   2500:                 hp->h_meta->h_pflags = flags;                          /* catalog will get updated by hfs_chflags */
                   2501:             };
                   2502:         };
                   2503: #if DIAGNOSTIC
                   2504:                a &= ~ATTR_CMN_FLAGS;
                   2505: #endif
                   2506:        };
                   2507: 
                   2508: #if DIAGNOSTIC
                   2509:        if (a != 0) {
                   2510:                DEBUG_BREAK_MSG(("UnpackCommonAttributes: unhandled bit: 0x%08X\n", a));
                   2511:        };
                   2512: #endif
                   2513: 
                   2514:        *attrbufptrptr = attrbufptr;
                   2515: //     *varbufptrptr = varbufptr;
                   2516: }
                   2517: 
                   2518: 
                   2519: 
                   2520: #if 0
                   2521: void UnpackDirAttributeBlock(struct attrlist *alist,
                   2522:                                                         struct vnode *vp,
                   2523:                                                         struct hfsCatalogInfo *catInfo,
                   2524:                                                         void **attrbufptrptr,
                   2525:                                                         void **varbufptrptr) {
                   2526:     void *attrbufptr;
                   2527:     void *varbufptr;
                   2528:     attrgroup_t a;
                   2529:        u_long attrlength;
                   2530:        
                   2531:        attrbufptr = *attrbufptrptr;
                   2532:        varbufptr = *varbufptrptr;
                   2533:        
                   2534:        /* XXX PPD TBC */
                   2535:        
                   2536:        *attrbufptrptr = attrbufptr;
                   2537:        *varbufptrptr = varbufptr;
                   2538: }
                   2539: #endif
                   2540: 
                   2541: 
                   2542: 
                   2543: #if 0
                   2544: void UnpackFileAttributeBlock(struct attrlist *alist,
                   2545:                                                          struct vnode *vp,
                   2546:                                                          struct hfsCatalogInfo *catInfo,
                   2547:                                                          void **attrbufptrptr,
                   2548:                                                          void **varbufptrptr) {
                   2549:     void *attrbufptr;
                   2550:     void *varbufptr;
                   2551:     attrgroup_t a;
                   2552:        u_long attrlength;
                   2553:        
                   2554:        attrbufptr = *attrbufptrptr;
                   2555:        varbufptr = *varbufptrptr;
                   2556:        
                   2557:        /* XXX PPD TBC */
                   2558:        
                   2559:        *attrbufptrptr = attrbufptr;
                   2560:        *varbufptrptr = varbufptr;
                   2561: }
                   2562: #endif
                   2563: 
                   2564: 
                   2565: 
                   2566: #if 0
                   2567: void UnpackForkAttributeBlock(struct attrlist *alist,
                   2568:                                                        struct vnode *vp,
                   2569:                                                        struct hfsCatalogInfo *catInfo,
                   2570:                                                        void **attrbufptrptr,
                   2571:                                                        void **varbufptrptr) {
                   2572:     void *attrbufptr;
                   2573:     void *varbufptr;
                   2574:     attrgroup_t a;
                   2575:        u_long attrlength;
                   2576:        
                   2577:        attrbufptr = *attrbufptrptr;
                   2578:        varbufptr = *varbufptrptr;
                   2579:        
                   2580:        /* XXX PPD TBC */
                   2581:        
                   2582:        *attrbufptrptr = attrbufptr;
                   2583:        *varbufptrptr = varbufptr;
                   2584: }
                   2585: #endif
                   2586: 
                   2587: 
                   2588: 
                   2589: void UnpackAttributeBlock(struct attrlist *alist,
                   2590:                                                  struct vnode *vp,
                   2591:                                                  struct hfsCatalogInfo *catInfo,
                   2592:                                                  void **attrbufptrptr,
                   2593:                                                  void **varbufptrptr) {
                   2594: 
                   2595: 
                   2596:        if (alist->volattr != 0) {
                   2597:                UnpackVolumeAttributeBlock(alist, vp, VTOVCB(vp), attrbufptrptr, varbufptrptr);
                   2598:                return;
                   2599:        };
                   2600:        
                   2601:        /* We're dealing with a vnode object here: */
                   2602:        UnpackCommonAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2603:        
                   2604: #if 0
                   2605:        switch (vp->v_type) {
                   2606:          case VDIR:
                   2607:                UnpackDirAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2608:                break;
                   2609: 
                   2610:          case VREG:
                   2611:    /* case VCPLX: */                   /* XXX PPD TBC */
                   2612:                UnpackFileAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2613:                break;
                   2614: 
                   2615:          case VFORK:
                   2616:                UnpackForkAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
                   2617:                break;
                   2618: 
                   2619:          /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
                   2620:             not being handled...
                   2621:           */
                   2622:          default:
                   2623:                /* XXX PPD - Panic? */
                   2624:                break;
                   2625:        };
                   2626: #endif
                   2627: 
                   2628: };
                   2629: 
                   2630: 
                   2631: unsigned long BestBlockSizeFit(unsigned long allocationBlockSize,
                   2632:                                unsigned long blockSizeLimit,
                   2633:                                unsigned long baseMultiple) {
                   2634:     /*
                   2635:        Compute the optimal (largest) block size (no larger than allocationBlockSize) that is less than the
                   2636:        specified limit but still an even multiple of the baseMultiple.
                   2637:      */
                   2638:     int baseBlockCount, blockCount;
                   2639:     unsigned long trialBlockSize;
                   2640: 
                   2641:     if (allocationBlockSize % baseMultiple != 0) {
                   2642:         /*
                   2643:            Whoops: the allocation blocks aren't even multiples of the specified base:
                   2644:            no amount of dividing them into even parts will be a multiple, either then!
                   2645:         */
                   2646:         return 512;            /* Hope for the best */
                   2647:     };
                   2648: 
                   2649:     /* Try the obvious winner first, to prevent 12K allocation blocks, for instance,
                   2650:        from being handled as two 6K logical blocks instead of 3 4K logical blocks.
                   2651:        Even though the former (the result of the loop below) is the larger allocation
                   2652:        block size, the latter is more efficient: */
                   2653:     if (allocationBlockSize % PAGE_SIZE == 0) return PAGE_SIZE;
                   2654: 
                   2655:     /* No clear winner exists: pick the largest even fraction <= MAXBSIZE: */
                   2656:     baseBlockCount = allocationBlockSize / baseMultiple;                               /* Now guaranteed to be an even multiple */
                   2657: 
                   2658:     for (blockCount = baseBlockCount; blockCount > 0; --blockCount) {
                   2659:         trialBlockSize = blockCount * baseMultiple;
                   2660:         if (allocationBlockSize % trialBlockSize == 0) {                               /* An even multiple? */
                   2661:             if ((trialBlockSize <= blockSizeLimit) &&
                   2662:                 (trialBlockSize % baseMultiple == 0)) {
                   2663:                 return trialBlockSize;
                   2664:             };
                   2665:         };
                   2666:     };
                   2667: 
                   2668:     /* Note: we should never get here, since blockCount = 1 should always work,
                   2669:        but this is nice and safe and makes the compiler happy, too ... */
                   2670:     return 512;
                   2671: }
                   2672: 
                   2673: 
                   2674: /*
                   2675:  * Map HFS Common errors (negative) to BSD error codes (positive).
                   2676:  * Positive errors (ie BSD errors) are passed through unchanged.
                   2677:  */
                   2678: short MacToVFSError(OSErr err)
                   2679: {
                   2680:     if (err >= 0) {
                   2681:         if (err > 0) {
                   2682:             DBG_ERR(("MacToVFSError: passing error #%d unchanged...\n", err));
                   2683:         };
                   2684:         return err;
                   2685:     };
                   2686: 
                   2687:     if (err != 0) {
                   2688:         DBG_ERR(("MacToVFSError: mapping error code %d...\n", err));
                   2689:     };
                   2690:     
                   2691:        switch (err) {
                   2692:          case dirFulErr:                                                       /*    -33 */
                   2693:          case dskFulErr:                                                       /*    -34 */
                   2694:          case btNoSpaceAvail:                                          /* -32733 */
                   2695:          case fxOvFlErr:                                                       /* -32750 */
                   2696:                return ENOSPC;                                                  /*    +28 */
                   2697: 
                   2698:          case btBadNode:                                                       /* -32731 */
                   2699:          case ioErr:                                                           /*   -36 */
                   2700:                return EIO;                                                             /*    +5 */
                   2701: 
                   2702:          case badMDBErr:                                                       /*   -60 */
                   2703:          case fnOpnErr:                                                        /*   -38 */
                   2704:                return EBADF;                                                   /*    +9 */
                   2705: 
                   2706:          case mFulErr:                                                         /*   -41 */
                   2707:          case memFullErr:                                                      /*  -108 */
                   2708:                return ENOMEM;                                                  /*   +12 */
                   2709: 
                   2710:          case tmfoErr:                                                         /*   -42 */
                   2711:                /* Consider EMFILE (Too many open files, 24)? */        
                   2712:                return ENFILE;                                                  /*   +23 */
                   2713: 
                   2714:          case nsvErr:                                                          /*   -35 */
                   2715:          case fnfErr:                                                          /*   -43 */
                   2716:          case dirNFErr:                                                        /*  -120 */
                   2717:          case fidNotFound:                                                     /* -1300 */
                   2718:                return ENOENT;                                                  /*    +2 */
                   2719: 
                   2720:          case wPrErr:                                                          /*   -44 */
                   2721:          case vLckdErr:                                                        /*   -46 */
                   2722:          case fsDSIntErr:                                                      /*  -127 */
                   2723:                return EROFS;                                                   /*   +30 */
                   2724: 
                   2725:          case opWrErr:                                                         /*   -49 */
                   2726:          case fLckdErr:                                                        /*   -45 */
                   2727:                return EACCES;                                                  /*   +13 */
                   2728: 
                   2729:          case permErr:                                                         /*   -54 */
                   2730:          case wrPermErr:                                                       /*   -61 */
                   2731:                return EPERM;                                                   /*    +1 */
                   2732: 
                   2733:          case fBsyErr:                                                         /*   -47 */
                   2734:                return EBUSY;                                                   /*   +16 */
                   2735: 
                   2736:          case dupFNErr:                                                        /*    -48 */
                   2737:          case fidExists:                                                       /*  -1301 */
                   2738:          case cmExists:                                                        /* -32718 */
                   2739:          case btExists:                                                        /* -32734 */
                   2740:                return EEXIST;                                                  /*    +17 */
                   2741: 
                   2742:          case rfNumErr:                                                        /*   -51 */
                   2743:                return EBADF;                                                   /*    +9 */
                   2744: 
                   2745:          case notAFileErr:                                                     /* -1302 */
                   2746:                return EISDIR;                                                  /*   +21 */
                   2747: 
                   2748:          case cmNotFound:                                                      /* -32719 */
                   2749:          case btNotFound:                                                      /* -32735 */    
                   2750:                return ENOENT;                                                  /*     28 */
                   2751: 
                   2752:          case cmNotEmpty:                                                      /* -32717 */
                   2753:                return ENOTEMPTY;                                               /*     66 */
                   2754: 
                   2755:          case cmFThdDirErr:                                            /* -32714 */
                   2756:                return EISDIR;                                                  /*     21 */
                   2757: 
                   2758:          case fxRangeErr:                                                      /* -32751 */
                   2759:                return EIO;                                                             /*      5 */
                   2760: 
                   2761:          case bdNamErr:                                                        /*   -37 */
                   2762:                return ENAMETOOLONG;                                    /*    63 */
                   2763: 
                   2764:          case eofErr:                                                          /*   -39 */
                   2765:          case posErr:                                                          /*   -40 */
                   2766:          case paramErr:                                                        /*   -50 */
                   2767:          case badMovErr:                                                       /*  -122 */
                   2768:          case sameFileErr:                                                     /* -1306 */
                   2769:          case badFidErr:                                                       /* -1307 */
                   2770:          case fileBoundsErr:                                           /* -1309 */
                   2771:                return EINVAL;                                                  /*   +22 */
                   2772: 
                   2773:          default:
                   2774:                DBG_UTILS(("Unmapped MacOS error: %d\n", err));
                   2775:                return EIO;                                                             /*   +5 */
                   2776:        }
                   2777: }
                   2778: 
                   2779: 
                   2780: /*
                   2781:  * All of our debugging functions
                   2782:  */
                   2783: 
                   2784: #if DIAGNOSTIC
                   2785: 
                   2786: void debug_vn_status (char* introStr, struct vnode *vn)
                   2787: {
                   2788:     DBG_VOP(("%s:\t",introStr));
                   2789:     if (vn != NULL)
                   2790:       {
                   2791:         if (vn->v_tag != VT_HFS)
                   2792:           {
                   2793:             DBG_VOP(("NON-HFS VNODE Ox%08lX\n", (unsigned long)vn));
                   2794:           }
                   2795:         else if(vn->v_tag==VT_HFS && (vn->v_data==NULL || VTOH((vn))->h_valid != HFS_VNODE_MAGIC))
                   2796:           {
                   2797:             DBG_VOP(("BAD VNODE PRIVATE DATA!!!!\n"));
                   2798:           }
                   2799:         else
                   2800:           {
                   2801:             DBG_VOP(("r: %d & ", vn->v_usecount));
                   2802:             if (lockstatus(&VTOH(vn)->h_lock))
                   2803:               {
                   2804:                 DBG_VOP_CONT(("is L\n"));
                   2805:               }
                   2806:             else
                   2807:               {
                   2808:                 DBG_VOP_CONT(("is U\n"));
                   2809:               }
                   2810:           }
                   2811:       }
                   2812:     else
                   2813:       {
                   2814:         DBG_VOP(("vnode is NULL\n"));
                   2815:       };
                   2816: }
                   2817: 
                   2818: void debug_vn_print (char* introStr, struct vnode *vn)
                   2819: {
                   2820: //  DBG_FUNC_NAME("DBG_VN_PRINT");
                   2821:     DBG_ASSERT (vn != NULL);
                   2822:     DBG_VFS(("%s: ",introStr));
                   2823:     DBG_VFS_CONT(("vnode: 0x%x is a ", (uint)vn));
                   2824:     switch (vn->v_tag)
                   2825:       {
                   2826:         case VT_UFS:
                   2827:             DBG_VFS_CONT(("%s","UFS"));
                   2828:             break;
                   2829:         case VT_HFS:
                   2830:             DBG_VFS_CONT(("%s","HFS"));
                   2831:             break;
                   2832:         default:
                   2833:             DBG_VFS_CONT(("%s","UNKNOWN"));
                   2834:             break;
                   2835:       }
                   2836: 
                   2837:     DBG_VFS_CONT((" vnode\n"));
                   2838:     if (vn->v_tag==VT_HFS)
                   2839:       {
                   2840:         if (vn->v_data==NULL)
                   2841:           {
                   2842:             DBG_VFS(("BAD VNODE PRIVATE DATA!!!!\n"));
                   2843:           }
                   2844:         else
                   2845:           {
                   2846:             DBG_VFS(("     Name: %s Id: %ld ",H_NAME(VTOH(vn)), H_FILEID(VTOH(vn))));
                   2847:           }
                   2848:       }
                   2849:     else
                   2850:         DBG_VFS(("     "));
                   2851: 
                   2852:     DBG_VFS_CONT(("Refcount: %d\n", vn->v_usecount));
                   2853:     if (VOP_ISLOCKED(vn))
                   2854:       {
                   2855:         DBG_VFS(("     The vnode is locked\n"));
                   2856:       }
                   2857:     else
                   2858:       {
                   2859:         DBG_VFS(("     The vnode is not locked\n"));
                   2860:       }
                   2861: }
                   2862: 
                   2863: void debug_rename_test_locks (char*                    introStr,
                   2864:                             struct vnode       *fvp,
                   2865:                             struct vnode       *fdvp,
                   2866:                             struct vnode       *tvp,
                   2867:                             struct vnode       *tdvp,
                   2868:                             int                                fstatus,
                   2869:                             int                                fdstatus,
                   2870:                             int                                tstatus,
                   2871:                             int                                tdstatus
                   2872: )
                   2873: {
                   2874:     DBG_VOP(("\t%s: ", introStr));
                   2875:     if (fvp) {if(lockstatus(&VTOH(fvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
                   2876:     if (fdvp) {if(lockstatus(&VTOH(fdvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
                   2877:     if (tvp) {if(lockstatus(&VTOH(tvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
                   2878:     if (tdvp) {if(lockstatus(&VTOH(tdvp)->h_lock)){DBG_VFS_CONT(("L"));} else {DBG_VFS_CONT(("U"));}} else { DBG_VFS_CONT(("X"));};
                   2879:     DBG_VFS_CONT(("\n"));
                   2880: 
                   2881:     if (fvp) {
                   2882:         if (lockstatus(&VTOH(fvp)->h_lock)) {
                   2883:             if (fstatus==VOPDBG_UNLOCKED) {
                   2884:                 DBG_VOP(("\tfvp should be NOT LOCKED and it is\n"));
                   2885:             }
                   2886:         } else if (fstatus == VOPDBG_LOCKED) {
                   2887:             DBG_VOP(("\tfvp should be LOCKED and it isnt\n"));
                   2888:         }
                   2889:     }
                   2890: 
                   2891:     if (fdvp) {
                   2892:         if (lockstatus(&VTOH(fdvp)->h_lock)) {
                   2893:             if (fdstatus==VOPDBG_UNLOCKED) {
                   2894:                 DBG_VOP(("\tfdvp should be NOT LOCKED and it is\n"));
                   2895:             }
                   2896:         } else if (fdstatus == VOPDBG_LOCKED) {
                   2897:             DBG_VOP(("\tfdvp should be LOCKED and it isnt\n"));
                   2898:         }
                   2899:     }
                   2900: 
                   2901:     if (tvp) {
                   2902:         if (lockstatus(&VTOH(tvp)->h_lock)) {
                   2903:             if (tstatus==VOPDBG_UNLOCKED) {
                   2904:                 DBG_VOP(("\ttvp should be NOT LOCKED and it is\n"));
                   2905:             }
                   2906:         } else if (tstatus == VOPDBG_LOCKED) {
                   2907:             DBG_VOP(("\ttvp should be LOCKED and it isnt\n"));
                   2908:         }
                   2909:     }
                   2910: 
                   2911:     if (tdvp) {
                   2912:         if (lockstatus(&VTOH(tdvp)->h_lock)) {
                   2913:             if (tdstatus==VOPDBG_UNLOCKED) {
                   2914:                 DBG_VOP(("\ttdvp should be NOT LOCKED and it is\n"));
                   2915:             }
                   2916:         } else if (tdstatus == VOPDBG_LOCKED) {
                   2917:             DBG_VOP(("\ttdvp should be LOCKED and it isnt\n"));
                   2918: 
                   2919:         }
                   2920:     }
                   2921: 
                   2922: }
                   2923: #endif /* DIAGNOSTIC */
                   2924: 
                   2925: 
                   2926: #if DIAGNOSTIC
                   2927: void debug_check_buffersizes(struct vnode *vp, struct hfsnode *hp, struct buf *bp) {
                   2928:     DBG_ASSERT(bp->b_validoff == 0);
                   2929:     DBG_ASSERT(bp->b_dirtyoff == 0);
                   2930:     if (bp->b_lblkno < hp->h_uniformblocksizestart) {
                   2931:         DBG_ASSERT((bp->b_bcount == MAXLOGBLOCKSIZE) ||
                   2932:                    (bp->b_bcount == LogicalBlockSize(hp, bp->b_lblkno)) ||
                   2933:                    ((bp->b_bcount % 512 == 0) &&
                   2934:                     (bp->b_validend > 0) &&
                   2935:                     (bp->b_dirtyend >= 0) &&                                                   /* Could be partial block due to file growth */
                   2936:                     (bp->b_bcount < LogicalBlockSize(hp, bp->b_lblkno))));
                   2937:     } else {
                   2938:         DBG_ASSERT((bp->b_bcount == hp->h_meta->h_logBlockSize) ||
                   2939:                    ((bp->b_bcount % 512 == 0) &&
                   2940:                     (bp->b_validend > 0) &&
                   2941:                     (bp->b_dirtyend > 0) &&
                   2942:                     (bp->b_bcount < hp->h_meta->h_logBlockSize)));
                   2943:     };
                   2944: 
                   2945:     if (bp->b_validend == 0) {
                   2946:         DBG_ASSERT(bp->b_dirtyend == 0);
                   2947:     } else {
                   2948:         DBG_ASSERT(bp->b_validend == bp->b_bcount);
                   2949:         DBG_ASSERT(bp->b_dirtyend <= bp->b_bcount);
                   2950:     };
                   2951: 
                   2952:     if ((bp->b_lblkno == 0x21) || (bp->b_lblkno == 0x22)) DBG_ASSERT((hp->h_uniformblocksizestart > 0x21) || (bp->b_bcount != MAXLOGBLOCKSIZE));
                   2953: }
                   2954: 
                   2955: 
                   2956: void debug_check_blocksizes(struct vnode *vp) {
                   2957:     struct hfsnode *hp = VTOH(vp);
                   2958:     struct buf *bp;
                   2959: 
                   2960:     if (vp->v_flag & VSYSTEM) return;
                   2961: 
                   2962:     for (bp = vp->v_cleanblkhd.lh_first; bp != NULL; bp = bp->b_vnbufs.le_next) {
                   2963:         debug_check_buffersizes(vp, hp, bp);
                   2964:     };
                   2965: 
                   2966:     for (bp = vp->v_dirtyblkhd.lh_first; bp != NULL; bp = bp->b_vnbufs.le_next) {
                   2967:         debug_check_buffersizes(vp, hp, bp);
                   2968:     };
                   2969: }
                   2970: 
                   2971: #endif /* DIAGNOSTIC */

unix.superglobalmegacorp.com

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