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