Annotation of kernel/bsd/hfs/hfscommon/Misc/Attributes.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:        File:           Attributes.c
                     27: 
                     28:        Contains:       Extended Attributes Manager
                     29:                                Routines for managing attributes (additional catalog-like data) associated
                     30:                                with files or folders on HFS Plus volumes.
                     31: 
                     32:        Version:        HFS Plus 1.0
                     33: 
                     34:        Copyright:      � 1997-1998 by Apple Computer, Inc., all rights reserved.
                     35: 
                     36:        File Ownership:
                     37: 
                     38:                DRI:                            Mark Day
                     39: 
                     40:                Other Contact:          Greg Parks
                     41: 
                     42:                Technology:                     HFS Plus
                     43: 
                     44:        Writers:
                     45: 
                     46:                (djb)   Don Brady
                     47:                (DSH)   Deric Horn
                     48:                (msd)   Mark Day
                     49: 
                     50:        Change History (most recent first):
                     51:          <Rhap>         4/17/98        djb             Add VCB locking.
                     52:          <Rhap>         3/31/98        djb             Sync up with final HFSVolumes.h header file.
                     53: 
                     54:          <CS13>         11/7/97        msd             Change calls to the wrapper routine CompareUnicodeNames() to use
                     55:                                                                        the underlying routine FastUnicodeCompare() instead.
                     56:          <CS12>        10/17/97        msd             Remove DebugStrs.
                     57:          <CS11>        10/13/97        DSH             Added InitBTreeHeader() fileSize parameter.
                     58:          <CS10>          9/4/97        msd             Remove unneeded/unused routines.
                     59:           <CS9>         8/22/97        djb             Add readFromDisk flag to GetCacheBlock.
                     60:           <CS8>         7/25/97        DSH             Pass kInvalidMRUCacheKey to BTSearchRecord as the heuristicHint.
                     61:           <CS7>         7/24/97        djb             SetEndOfForkProc takes a refNum instead of an FCB.
                     62:           <CS6>         7/18/97        msd             Include LowMemPriv.h.
                     63:           <CS5>         7/16/97        DSH             FilesInternal.i renamed FileMgrInternal.i to avoid name
                     64:                                                                        collision
                     65:           <CS4>          7/8/97        DSH             Loading PrecompiledHeaders from define passed in on C line
                     66:           <CS3>          6/2/97        DSH             On creation make sure we call through the SetEndOfFileProc so
                     67:                                                                        the AlternateVolumeHeader is updated.
                     68:           <CS2>         5/28/97        msd             Change keys to {cnid, flags, creator, selector}. Prototype an
                     69:                                                                        SPI for testing.
                     70:           <CS1>         4/24/97        djb             first checked in
                     71:          <HFS5>         4/10/97        msd             In PropertyDeleteObject, use the global buffer instead of an
                     72:                                                                        automatic variable.
                     73:          <HFS4>          4/8/97        msd             Add AttributesOpenVolume to allocate appropriate buffer space.
                     74:          <HFS3>          4/7/97        msd             Start adding real code. Removed PropertyOpenVolume; that code
                     75:                                                                        now resides in Volumes.c.
                     76:          <HFS2>         3/17/97        DSH             SC needs parameters to the stub functions.
                     77:          <HFS1>          3/5/97        msd             first checked in
                     78: */
                     79: 
                     80: /*
                     81: Public routines:
                     82:        AttributesCloseVolume
                     83:                                Clean up and finalize for a given volume.  Close a property database
                     84:                                file if needed.  In general, clean up after PropertyOpenVolume.
                     85:                                This routine should be called before closing the Catalog and Extents
                     86:                                files on the volume.
                     87: */
                     88: 
                     89: #if ( PRAGMA_LOAD_SUPPORTED )
                     90:         #pragma        load    PrecompiledHeaders
                     91: #else
                     92:        #if TARGET_OS_MAC
                     93:                #include <Types.h>
                     94:                #include <LowMemPriv.h>
                     95:        #else
                     96:                #include "../headers/system/MacOSStubs.h"
                     97:        #endif  /* TARGET_OS_MAC */
                     98: #endif /* PRAGMA_LOAD_SUPPORTED */
                     99: 
                    100: #include "../headers/HFSVolumes.h"
                    101: #include "../headers/FileMgrInternal.h"
                    102: #include "../headers/BTreesInternal.h"
                    103: #include "../headers/HFSBtreesPriv.h"
                    104: #include "../headers/system/HFSUnicodeWrappers.h"
                    105: 
                    106: #if HFSInstrumentation
                    107:         #include "Instrumentation.h"
                    108: #endif
                    109: 
                    110: #define min(x,y)       ((x < y) ? x : y)
                    111: 
                    112: //
                    113: //     Values for flags in AttributesKey.flags
                    114: //
                    115: enum {
                    116:        kAttributeNodeSize              = 4096                  // Size of our Btree node
                    117: };
                    118: 
                    119: 
                    120: #if TARGET_OS_MAC
                    121: OSErr AttributesCloseVolume(ExtendedVCB *              vcb)
                    122: {
                    123:        OSErr   err;
                    124:        
                    125:        err = noErr;
                    126:        
                    127:        if (vcb->vcbSigWord == kHFSPlusSigWord && vcb->attributesRefNum != 0) {
                    128:                err = CloseFile( vcb, vcb->attributesRefNum, LMGetFCBSPtr() );
                    129:                vcb->attributesRefNum = 0;
                    130:        }
                    131:        
                    132:        return err;
                    133: }
                    134: #endif /* TARGET_OS_MAC */
                    135: 
                    136: SInt32 CompareAttributeKeys( const void *inSearchKey, const void *inTrialKey )
                    137: {
                    138:        const AttributeKey *searchKey   = inSearchKey;
                    139:        const AttributeKey *trialKey    = inTrialKey;
                    140:        SInt32                          temp;
                    141:                
                    142:        //
                    143:        //      First, compare the CNID's
                    144:        //
                    145:        if (searchKey->cnid != trialKey->cnid) {
                    146:                return searchKey->cnid < trialKey->cnid ? -1 : 1;
                    147:        }
                    148: 
                    149:        //
                    150:        //      CNID's are equal; compare names
                    151:        //
                    152:        if (searchKey->attributeName.length == 0 || trialKey->attributeName.length == 0)
                    153:                return searchKey->attributeName.length < trialKey->attributeName.length ? -1 : 1;
                    154:        temp = FastUnicodeCompare(&searchKey->attributeName.unicode[0], searchKey->attributeName.length,
                    155:                                                          &trialKey->attributeName.unicode[0], trialKey->attributeName.length);
                    156:        if (temp != 0)
                    157:                return temp;
                    158: 
                    159:        //
                    160:        //      Names are equal; compare startBlock
                    161:        //
                    162:        if (searchKey->startBlock == trialKey->startBlock)
                    163:                return 0;
                    164:        else
                    165:                return searchKey->startBlock < trialKey->startBlock ? -1 : 1;
                    166: }
                    167: 
                    168: 
                    169: #if TARGET_OS_MAC
                    170: static OSErr CreateAndOpenBtree(ExtendedVCB *vcb)
                    171: {
                    172:        OSStatus                err;
                    173:        UInt16                  refnum;                         //      attribute file's refnum
                    174:        Ptr                             fcbHeader;                      //      points to start of FCBs (unused)
                    175:        FCB                             *fcb;                           //      attribute file's FCB
                    176:        ExtendedFCB             *extendedFCB;           //      attribute file's extended FCB
                    177:        UInt32                  clumpSize;
                    178:        UInt32                  mapNodes;
                    179:        LogicalAddress  header;
                    180:        Boolean                 readFromDisk;
                    181:        
                    182:        clumpSize = 32 * vcb->blockSize;                        //�� Need a better value.
                    183: 
                    184:     // Find a free FCB for the attributes file
                    185: #if TARGET_OS_MAC
                    186:        err = FindFileControlBlock(&refnum, &fcbHeader);
                    187: #else  /* TARGET_OS_MAC */
                    188:     err = GetNewFCB(vcb, &refnum );
                    189: #endif /* TARGET_OS_MAC */
                    190: 
                    191:        ReturnIfError(err);
                    192: //     fcb = GetFileControlBlock(refnum);
                    193:        fcb = SetupFCB(vcb, refnum, kHFSAttributesFileID, clumpSize);
                    194: 
                    195:        //      Mark file as empty.
                    196:        fcb->fcbEOF = 0;
                    197:        fcb->fcbPLen = 0;
                    198:        vcb->attributesRefNum = refnum;
                    199:        ClearMemory( (Ptr)fcb->fcbExtRec, sizeof(HFSExtentRecord) );
                    200: /* XXX PPD: Is there any reason this isn't the same for EVERY platform? */
                    201: #if TARGET_OS_MAC
                    202:        extendedFCB = ParallelFCBFromRefnum( refnum );
                    203: #else
                    204:        extendedFCB = GetParallelFCB( refnum );
                    205: #endif
                    206:        ClearMemory( (Ptr)extendedFCB->extents, sizeof(HFSPlusExtentRecord) );
                    207: 
                    208:        //      Allocate some space to the file
                    209:        err = SetEndOfForkProc(refnum, clumpSize, clumpSize);
                    210:        if (err) {
                    211:                ClearMemory(fcb, sizeof(FCB));
                    212:                goto ErrorExit;
                    213:        }
                    214:        fcb->fcbEOF = fcb->fcbPLen;             // grow the file to include the allocated space
                    215:        
                    216:        //      Initialize the b-tree.  Write out the header.
                    217:        err = GetCacheBlock(refnum, 0, kAttributeNodeSize, gbDefault, &header, &readFromDisk);
                    218:        ClearMemory(header, kAttributeNodeSize);
                    219:        InitBTreeHeader(fcb->fcbEOF, clumpSize, kAttributeNodeSize, 0, kAttributeKeyMaximumLength, kBTBigKeysMask, &mapNodes, header);
                    220:        err = ReleaseCacheBlock(header, rbWriteMask);
                    221:        
                    222:        //      Finally, prepare for using the B-tree           
                    223:        err = OpenBTree( refnum, (KeyCompareProcPtr) CompareAttributeKeys );
                    224:        if (err) {
                    225:                ClearMemory(fcb, sizeof(FCB));
                    226:                goto ErrorExit;
                    227:        }
                    228:        
                    229:        //�� Should we update the volume header and alternate volume header?
                    230: 
                    231: ErrorExit:     
                    232:        return err;
                    233: }
                    234: #endif /* #if TARGET_OS_MAC */
                    235: 
                    236: #if TARGET_OS_MAC
                    237: static OSErr PreflightAttributeCall(AttributeParam *pb, FindFileNameGlueRec *fileInfo, Boolean needsWrite)
                    238: {
                    239:        OSErr                           err;
                    240:        ExtendedVCB                     *vcb;
                    241: 
                    242:        //
                    243:        //      See if the file exists.  Get its FileID.
                    244:        //
                    245:        err = FindFileName((ParamBlockRec *) pb, fileInfo);
                    246:        ReturnIfError( err );
                    247:        
                    248:        //
                    249:        //      Make sure the volume is on-line and writable.
                    250:        //
                    251:        vcb = fileInfo->vcb;
                    252:        
                    253:        if (needsWrite) {
                    254:                err = VolumeWritable( vcb );
                    255:                ReturnIfError( err );
                    256:        }
                    257:        
                    258:        err = CheckVolumeOffLine( vcb );
                    259:        ReturnIfError( err );
                    260:        
                    261:        //
                    262:        //      And make sure it is HFS Plus.
                    263:        //
                    264:        if (vcb->vcbSigWord != kHFSPlusSigWord)
                    265:                return wrgVolTypErr;
                    266:        
                    267:        //
                    268:        //��    Make sure there is an attribute file.  Create and open it if needed.
                    269:        //
                    270:        if (vcb->attributesRefNum == 0) {
                    271:                
                    272:                if (needsWrite == false)                //      If we only wanted to read,
                    273:                        return notBTree;                        //      tell caller there is no b-tree
                    274:                //
                    275:                //      Create and open b-tree
                    276:                //
                    277:                err = CreateAndOpenBtree(vcb);
                    278:        }
                    279:        
                    280:        return err;
                    281: }
                    282: #endif /* TARGET_OS_MAC */
                    283: 
                    284: 
                    285: #if TARGET_OS_MAC
                    286: OSErr CreateAttribute(AttributeParam *pb)
                    287: {
                    288:        OSErr                           err;
                    289:        ExtendedVCB                     *vcb;
                    290:        UInt32                          length;
                    291:        UInt32                          numberOfExtents;
                    292:        UInt32                          i,extentsThisRecord;
                    293:        UInt32                          blocksAllocated = 0;
                    294:        UInt32                          hint;
                    295:        AttributeKey            key;
                    296:        FindFileNameGlueRec     fileInfo;
                    297: 
                    298:        err = PreflightAttributeCall(pb, &fileInfo, true);
                    299:        ReturnIfError( err );
                    300:        
                    301:        vcb = fileInfo.vcb;
                    302:        
                    303:        //
                    304:        //      Set up the first key
                    305:        //
                    306:        length = sizeof(UniChar) * (pb->ioAttributeName->length+1);             // length in bytes of Unicode name
                    307: 
                    308:        key.keyLength   = length + offsetof(AttributeKey, attributeName);
                    309:        key.pad                 = 0;
                    310:        key.cnid                = fileInfo.data->nodeID;
                    311:        key.startBlock  = 0;
                    312:        BlockMoveData(pb->ioAttributeName, &key.attributeName, length); // copy attributeName
                    313:        
                    314:        //
                    315:        //      Determine the first record type based on the number of extents
                    316:        //
                    317:        numberOfExtents = pb->filler1;
                    318:        if (numberOfExtents == 0) {
                    319:                AttributeInlineData             record;
                    320:                
                    321:                record.recordType = kAttributeInlineData;
                    322:                record.logicalSize = 0;
                    323:                length = offsetof(AttributeInlineData, userData);
                    324:                err = InsertBTreeRecord(vcb->attributesRefNum, &key, &record, length, &hint);
                    325:        }
                    326:        else {
                    327:                {
                    328:                        AttributeForkData               record;
                    329:                        
                    330:                        //      Set up first record, with ForkData
                    331:                        ClearMemory(&record, sizeof(record));
                    332:                        record.recordType                               = kAttributeForkData;
                    333:                        record.theFork.logicalSize.lo   = numberOfExtents * vcb->blockSize;             // each extent is one block
                    334:                        record.theFork.logicalSize.hi   = 0;
                    335:                        record.theFork.clumpSize                = vcb->attributesClumpSize;
                    336:                        record.theFork.totalBlocks              = numberOfExtents;                                              // one block per extent
                    337:                        extentsThisRecord = min(numberOfExtents, kHFSPlusExtentDensity);
                    338:                        for (i=0; i<extentsThisRecord; i++) {
                    339:                                err = BlockAllocateAny(vcb, 0, vcb->totalBlocks, 1, &record.theFork.extents[i].startBlock,
                    340:                                                                                                                                        &record.theFork.extents[i].blockCount);
                    341:                                ReturnIfError(err);
                    342:                                ++blocksAllocated;
                    343:                        }
                    344:                        err = InsertBTreeRecord(vcb->attributesRefNum, &key, &record, sizeof(record), &hint);
                    345:                        ReturnIfError(err);
                    346:                }
                    347:                
                    348:                {
                    349:                        AttributeExtents                record;
                    350:                        
                    351:                        //      Handle overflow extent records
                    352:                        ClearMemory(&record, sizeof(record));
                    353:                        numberOfExtents -= extentsThisRecord;
                    354:                        record.recordType       = kAttributeExtents;
                    355:                        while (numberOfExtents) {
                    356:                                extentsThisRecord = min(numberOfExtents, kHFSPlusExtentDensity);
                    357:                                key.startBlock += kHFSPlusExtentDensity;
                    358:                                for (i=0; i<extentsThisRecord; i++) {
                    359:                                        err = BlockAllocateAny(vcb, 0, vcb->totalBlocks, 1, &record.extents[i].startBlock,
                    360:                                                                                                                                                &record.extents[i].blockCount);
                    361:                                        ReturnIfError(err);
                    362:                                        ++blocksAllocated;
                    363:                                }
                    364:                                for (; i<kHFSPlusExtentDensity; i++) {
                    365:                                        record.extents[i].startBlock = 0;
                    366:                                        record.extents[i].blockCount = 0;
                    367:                                }
                    368:                                err = InsertBTreeRecord(vcb->attributesRefNum, &key, &record, sizeof(record), &hint);
                    369:                                ReturnIfError(err);
                    370:                                numberOfExtents -= extentsThisRecord;
                    371:                        }
                    372:                }
                    373:        }
                    374:        
                    375:        if (blocksAllocated) {
                    376:                VCB_LOCK(vcb);
                    377:                vcb->freeBlocks -= blocksAllocated;
                    378:                VCB_UNLOCK(vcb);
                    379:                UpdateVCBFreeBlks( vcb );
                    380:                MarkVCBDirty(vcb);
                    381:        }
                    382:        
                    383:        if (err == fsBTDuplicateRecordErr)
                    384:                err = btDupRecErr;
                    385:                        
                    386:        return err;
                    387: }
                    388: #endif /* TARGET_OS_MAC */

unix.superglobalmegacorp.com

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