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