Annotation of XNU/bsd/hfs/hfs_vfsutils.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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