Annotation of XNU/iokit/Kernel/IORegistryEntry.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved. 
        !            24:  *
        !            25:  * HISTORY
        !            26:  * 12 Nov 98 sdouglas created.
        !            27:  *
        !            28:  */
        !            29: 
        !            30: #include <IOKit/IORegistryEntry.h>
        !            31: #include <libkern/c++/OSContainers.h>
        !            32: #include <IOKit/IOService.h>
        !            33: #include <IOKit/IOKitKeys.h>
        !            34: 
        !            35: #include <IOKit/IOLib.h>
        !            36: 
        !            37: #include <IOKit/assert.h>
        !            38: 
        !            39: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !            40: 
        !            41: #define super OSObject
        !            42: 
        !            43: OSDefineMetaClassAndStructors(IORegistryEntry, OSObject)
        !            44: 
        !            45: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !            46: 
        !            47: static IORegistryEntry * gRegistryRoot;
        !            48: static OSDictionary *   gIORegistryPlanes;
        !            49: 
        !            50: const OSSymbol *       gIONameKey;
        !            51: const OSSymbol *       gIOLocationKey;
        !            52: 
        !            53: enum {
        !            54:     kParentSetIndex    = 0,
        !            55:     kChildSetIndex     = 1,
        !            56:     kNumSetIndex
        !            57: };
        !            58: enum {
        !            59:     kIOMaxPlaneName    = 32
        !            60: };
        !            61: 
        !            62: class IORegistryPlane : public OSObject {
        !            63: 
        !            64:     friend IORegistryEntry;
        !            65: 
        !            66:     OSDeclareAbstractStructors(IORegistryPlane)
        !            67: 
        !            68:     const OSSymbol *   nameKey;
        !            69:     const OSSymbol *   keys[ kNumSetIndex ];
        !            70:     const OSSymbol *   pathNameKey;
        !            71:     const OSSymbol *   pathLocationKey;
        !            72:     int                        reserved[2];
        !            73: 
        !            74: public:
        !            75:     virtual bool serialize(OSSerialize *s) const;
        !            76: };
        !            77: 
        !            78: OSDefineMetaClassAndStructors(IORegistryPlane, OSObject)
        !            79: 
        !            80: 
        !            81: static lock_t *                        gIORegistryLock;
        !            82: static IORecursiveLock *       gPropertiesLock;
        !            83: static SInt32                  gIORegistryGenerationCount;
        !            84: 
        !            85: #define UNLOCK lock_done( gIORegistryLock )
        !            86: #define RLOCK  lock_read( gIORegistryLock )
        !            87: #define WLOCK  lock_write( gIORegistryLock );  \
        !            88:                gIORegistryGenerationCount++
        !            89:                // make atomic
        !            90: 
        !            91: #define PUNLOCK        IORecursiveLockUnlock( gPropertiesLock )
        !            92: #define PLOCK  IORecursiveLockLock( gPropertiesLock )
        !            93: 
        !            94: #define IOREGSPLITTABLES
        !            95: 
        !            96: #ifdef IOREGSPLITTABLES
        !            97: #define registryTable()        fRegistryTable
        !            98: #else
        !            99: #define registryTable()        fPropertyTable
        !           100: #endif
        !           101: 
        !           102: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !           103: 
        !           104: IORegistryEntry * IORegistryEntry::initialize( void )
        !           105: {
        !           106:    bool                        ok;
        !           107: 
        !           108:     if( !gRegistryRoot) {
        !           109: 
        !           110:        gRegistryRoot = new IORegistryEntry;
        !           111:         gIORegistryLock = lock_alloc(true, NULL, NULL);
        !           112:        gPropertiesLock = IORecursiveLockAlloc();
        !           113:        gIORegistryPlanes = OSDictionary::withCapacity( 1 );
        !           114: 
        !           115:        assert( gRegistryRoot && gIORegistryLock && gPropertiesLock
        !           116:                && gIORegistryPlanes );
        !           117:         ok = gRegistryRoot->init();
        !           118: 
        !           119:        gIONameKey = OSSymbol::withCStringNoCopy( "IOName" );
        !           120:        gIOLocationKey = OSSymbol::withCStringNoCopy( "IOLocation" );
        !           121: 
        !           122:        assert( ok && gIONameKey && gIOLocationKey );
        !           123: 
        !           124:        gRegistryRoot->setName( "Root" );
        !           125:         gRegistryRoot->setProperty( kIORegistryPlanesKey, gIORegistryPlanes );
        !           126:     }
        !           127: 
        !           128:     return( gRegistryRoot );
        !           129: }
        !           130: 
        !           131: IORegistryEntry * IORegistryEntry::getRegistryRoot( void )
        !           132: {
        !           133:     return( gRegistryRoot );
        !           134: }
        !           135: 
        !           136: SInt32 IORegistryEntry::getGenerationCount( void )
        !           137: {
        !           138:     return( gIORegistryGenerationCount );
        !           139: }
        !           140: 
        !           141: 
        !           142: const IORegistryPlane * IORegistryEntry::makePlane( const char * name )
        !           143: {
        !           144:     IORegistryPlane *  plane;
        !           145:     const OSSymbol *   nameKey;
        !           146:     const OSSymbol *   parentKey;
        !           147:     const OSSymbol *   childKey;
        !           148:     const OSSymbol *   pathNameKey;
        !           149:     const OSSymbol *   pathLocationKey;
        !           150:     char               key[ kIOMaxPlaneName + 16 ];
        !           151:     char *             end;
        !           152: 
        !           153:     strncpy( key, name, kIOMaxPlaneName );
        !           154:     key[ kIOMaxPlaneName ] = 0;
        !           155:     end = key + strlen( name );
        !           156: 
        !           157:     nameKey = OSSymbol::withCString( key);
        !           158: 
        !           159:     strcpy( end, "ParentLinks" );
        !           160:     parentKey = OSSymbol::withCString( key);
        !           161: 
        !           162:     strcpy( end, "ChildLinks" );
        !           163:     childKey = OSSymbol::withCString( key);
        !           164: 
        !           165:     strcpy( end, "Name" );
        !           166:     pathNameKey = OSSymbol::withCString( key);
        !           167: 
        !           168:     strcpy( end, "Location" );
        !           169:     pathLocationKey = OSSymbol::withCString( key);
        !           170: 
        !           171:     plane = new IORegistryPlane;
        !           172: 
        !           173:     if( plane && plane->init()
        !           174:        && nameKey && parentKey && childKey
        !           175:        && pathNameKey && pathLocationKey ) {
        !           176: 
        !           177:        plane->nameKey = nameKey;
        !           178:        plane->keys[ kParentSetIndex ] = parentKey;
        !           179:        plane->keys[ kChildSetIndex ] = childKey;
        !           180:        plane->pathNameKey = pathNameKey;
        !           181:        plane->pathLocationKey = pathLocationKey;
        !           182: 
        !           183:        WLOCK;
        !           184:         gIORegistryPlanes->setObject( nameKey, plane );
        !           185:        UNLOCK;
        !           186: 
        !           187:     } else {
        !           188: 
        !           189:        if( plane)
        !           190:            plane->release();
        !           191:        if( pathLocationKey)
        !           192:            pathLocationKey->release();
        !           193:        if( pathNameKey)
        !           194:            pathNameKey->release();
        !           195:        if( parentKey)
        !           196:            parentKey->release();
        !           197:        if( childKey)
        !           198:            childKey->release();
        !           199:        if( nameKey)
        !           200:            nameKey->release();
        !           201:        plane = 0;
        !           202:     }
        !           203: 
        !           204:     return( plane);
        !           205: }
        !           206: 
        !           207: const IORegistryPlane * IORegistryEntry::getPlane( const char * name )
        !           208: {
        !           209:     const IORegistryPlane *    plane;
        !           210: 
        !           211:     RLOCK;
        !           212:     plane = (const IORegistryPlane *) gIORegistryPlanes->getObject( name );
        !           213:     UNLOCK;
        !           214: 
        !           215:     return( plane );
        !           216: }
        !           217: 
        !           218: bool IORegistryPlane::serialize(OSSerialize *s) const
        !           219: {
        !           220:     return( nameKey->serialize(s) );
        !           221: }
        !           222: 
        !           223: enum { kIORegCapacityIncrement = 4 };
        !           224: 
        !           225: bool IORegistryEntry::init( OSDictionary * dict = 0 )
        !           226: {
        !           227:     OSString * prop;
        !           228: 
        !           229:     if( !super::init())
        !           230:        return( false);
        !           231: 
        !           232:     if( dict) {
        !           233:        dict->retain();
        !           234:        fPropertyTable = dict;
        !           235: 
        !           236:     } else {
        !           237:         fPropertyTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
        !           238:        if( fPropertyTable)
        !           239:             fPropertyTable->setCapacityIncrement( kIORegCapacityIncrement );
        !           240:     }
        !           241: 
        !           242:     if( !fPropertyTable)
        !           243:         return( false);
        !           244: 
        !           245: #ifdef IOREGSPLITTABLES
        !           246:     fRegistryTable = OSDictionary::withCapacity( kIORegCapacityIncrement );
        !           247:     if( fRegistryTable)
        !           248:         fRegistryTable->setCapacityIncrement( kIORegCapacityIncrement );
        !           249: 
        !           250:     if( (prop = OSDynamicCast( OSString, getProperty( gIONameKey)))) {
        !           251:         OSSymbol * sym = (OSSymbol *)OSSymbol::withString( prop);
        !           252:         // ok for OSSymbol too
        !           253:         setName( sym);
        !           254:         sym->release();
        !           255:     }
        !           256: 
        !           257: #endif /* IOREGSPLITTABLES */
        !           258: 
        !           259:     return( true);
        !           260: }
        !           261: 
        !           262: bool IORegistryEntry::init( IORegistryEntry * old,
        !           263:                                const IORegistryPlane * plane )
        !           264: {
        !           265:     OSArray *          all;
        !           266:     IORegistryEntry *          next;
        !           267:     unsigned int       index;
        !           268: 
        !           269:     if( !super::init())
        !           270:        return( false);
        !           271: 
        !           272:     WLOCK;
        !           273: 
        !           274:     fPropertyTable = old->getPropertyTable();
        !           275:     old->fPropertyTable = 0;
        !           276: #ifdef IOREGSPLITTABLES
        !           277:     fRegistryTable = old->fRegistryTable;
        !           278:     old->fRegistryTable = 0;
        !           279: #endif /* IOREGSPLITTABLES */
        !           280: 
        !           281:     all = getParentSetReference( plane );
        !           282:     if( all) for( index = 0;
        !           283:               (next = (IORegistryEntry *) all->getObject(index));
        !           284:               index++ ) {
        !           285:            next->makeLink( this, kChildSetIndex, plane );
        !           286:             next->breakLink( old, kChildSetIndex, plane );
        !           287:     }
        !           288: 
        !           289:     all = getChildSetReference( plane );
        !           290:     if( all) for( index = 0;
        !           291:               (next = (IORegistryEntry *) all->getObject(index));
        !           292:               index++ ) {
        !           293:            next->makeLink( this, kParentSetIndex, plane );
        !           294:             next->breakLink( old, kParentSetIndex, plane );
        !           295:     }
        !           296: 
        !           297:     UNLOCK;
        !           298: 
        !           299:     return( true );
        !           300: }
        !           301: 
        !           302: void IORegistryEntry::free( void )
        !           303: {
        !           304: 
        !           305: #ifdef DEBUG
        !           306:     OSArray *                  links;
        !           307:     const OSSymbol *           key;
        !           308:     const IORegistryPlane *    plane;
        !           309:     OSCollectionIterator *     iter;
        !           310: 
        !           311:     if( registryTable()) {
        !           312:         iter = OSCollectionIterator::withCollection( gIORegistryPlanes );
        !           313:         if( iter) {
        !           314:             while( (key = (const OSSymbol *) iter->getNextObject())) {
        !           315:                 if( 0 == (plane = (const IORegistryPlane *)
        !           316:                        OSDynamicCast( IORegistryPlane,
        !           317:                                  gIORegistryPlanes->getObject( key ))))
        !           318:                    continue;
        !           319:                 if( (links = getParentSetReference( plane ))
        !           320:                  || (links = getChildSetReference( plane )) ) {
        !           321: 
        !           322:                     IOLog("%s: Still attached in %s at free()\n",
        !           323:                                getName(), plane->nameKey->getCStringNoCopy());
        !           324:                }
        !           325:             }
        !           326:             iter->release();
        !           327:         }
        !           328:     }
        !           329: #endif
        !           330: 
        !           331:     if( getPropertyTable())
        !           332:         getPropertyTable()->release();
        !           333: 
        !           334: #ifdef IOREGSPLITTABLES
        !           335:     if( registryTable())
        !           336:         registryTable()->release();
        !           337: #endif /* IOREGSPLITTABLES */
        !           338: 
        !           339:     super::free();
        !           340: }
        !           341: 
        !           342: void IORegistryEntry::setPropertyTable( OSDictionary * dict )
        !           343: {
        !           344:     if( fPropertyTable)
        !           345:        fPropertyTable->release();
        !           346:     if( dict)
        !           347:        dict->retain();
        !           348:     fPropertyTable = dict;
        !           349: }
        !           350: 
        !           351: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !           352: 
        !           353: /* Wrappers to synchronize property table */
        !           354: 
        !           355: #define wrap1(func,type,constant)                                      \
        !           356: OSObject *                                                             \
        !           357: IORegistryEntry::func ## Property( type * aKey) constant               \
        !           358: {                                                                      \
        !           359:     OSObject * obj;                                                    \
        !           360:                                                                        \
        !           361:     PLOCK;                                     \
        !           362:     obj = getPropertyTable()->func ## Object( aKey );                  \
        !           363:     PUNLOCK;                                   \
        !           364:                                                                        \
        !           365:     return( obj );                                                     \
        !           366: }
        !           367: 
        !           368: #define wrap2(func,type)                                               \
        !           369: OSObject *                                                             \
        !           370: IORegistryEntry::func ## Object( OSObject * anObject, type * aKey)     \
        !           371: {                                                                      \
        !           372:     OSObject * obj;                                                    \
        !           373:                                                                        \
        !           374:     PLOCK;                                     \
        !           375:     obj = getPropertyTable()->func ## Object( anObject, aKey );                \
        !           376:     PUNLOCK;                                   \
        !           377:                                                                        \
        !           378:     return( obj );                                                     \
        !           379: }
        !           380: 
        !           381: #define wrap3(func,type,constant)                                      \
        !           382: void                                                           \
        !           383: IORegistryEntry::func ## Property( type * aKey) constant               \
        !           384: {                                                                      \
        !           385:     PLOCK;                                     \
        !           386:     getPropertyTable()->func ## Object( aKey );                        \
        !           387:     PUNLOCK;                                   \
        !           388: }
        !           389: 
        !           390: bool IORegistryEntry::serializeProperties( OSSerialize * s ) const
        !           391: {
        !           392:     bool ok;
        !           393: 
        !           394: //    setProperty( getRetainCount(), 32, "__retain" );
        !           395: 
        !           396:     PLOCK;
        !           397:     ok = getPropertyTable()->serialize( s );
        !           398:     PUNLOCK;
        !           399: 
        !           400:     return( ok );
        !           401: }
        !           402: 
        !           403: OSDictionary * IORegistryEntry::dictionaryWithProperties( void ) const
        !           404: {
        !           405:     OSDictionary *     dict;
        !           406: 
        !           407:     PLOCK;
        !           408:     dict = OSDictionary::withDictionary( getPropertyTable(),
        !           409:                             getPropertyTable()->getCapacity() );
        !           410:     PUNLOCK;
        !           411: 
        !           412:     return( dict );
        !           413: }
        !           414: 
        !           415: IOReturn IORegistryEntry::setProperties( OSObject * properties )
        !           416: {
        !           417:     return( kIOReturnUnsupported );
        !           418: }
        !           419: 
        !           420: wrap1(get, const OSSymbol, const)  // getProperty() definition
        !           421: wrap1(get, const OSString, const)  // getProperty() definition
        !           422: wrap1(get, const char, const)      // getProperty() definition
        !           423: 
        !           424: wrap3(remove, const OSSymbol,)     // removeProperty() definition
        !           425: wrap3(remove, const OSString,)     // removeProperty() definition
        !           426: wrap3(remove, const char,)         // removeProperty() definition
        !           427: 
        !           428: bool
        !           429: IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject)
        !           430: {
        !           431:     bool ret = false;
        !           432:     PLOCK;
        !           433:     ret = getPropertyTable()->setObject( aKey, anObject );
        !           434:     PUNLOCK;
        !           435:     
        !           436:     return ret;
        !           437: }
        !           438: 
        !           439: bool
        !           440: IORegistryEntry::setProperty( const OSString * aKey, OSObject * anObject)
        !           441: {
        !           442:     bool ret = false;
        !           443:     PLOCK;
        !           444:     ret = getPropertyTable()->setObject( aKey, anObject );
        !           445:     PUNLOCK;
        !           446: 
        !           447:     return ret;
        !           448: }
        !           449: 
        !           450: bool
        !           451: IORegistryEntry::setProperty( const char * aKey,  OSObject * anObject)
        !           452: {
        !           453:     bool ret = false;
        !           454:     PLOCK;
        !           455:     ret = getPropertyTable()->setObject( aKey, anObject );
        !           456:     PUNLOCK;
        !           457:     
        !           458:     return ret;
        !           459: }
        !           460: 
        !           461: bool
        !           462: IORegistryEntry::setProperty(const char * aKey, const char * aString)
        !           463: {
        !           464:     bool ret = false;
        !           465:     OSSymbol * aSymbol = (OSSymbol *) OSSymbol::withCString( aString );
        !           466: 
        !           467:     if( aSymbol) {
        !           468:         PLOCK;
        !           469:         ret = getPropertyTable()->setObject( aKey, aSymbol );
        !           470:         PUNLOCK;
        !           471:         aSymbol->release();
        !           472:     }
        !           473:     return( ret );
        !           474: }
        !           475: 
        !           476: bool
        !           477: IORegistryEntry::setProperty(const char * aKey, bool aBoolean)
        !           478: {
        !           479:     bool ret = false;
        !           480:     OSBoolean * aBooleanObj = OSBoolean::withBoolean( aBoolean );
        !           481: 
        !           482:     if( aBooleanObj) {
        !           483:         PLOCK;
        !           484:         ret = getPropertyTable()->setObject( aKey, aBooleanObj );
        !           485:         PUNLOCK;
        !           486:         aBooleanObj->release();
        !           487:     }
        !           488:     return( ret );
        !           489: }
        !           490: 
        !           491: bool
        !           492: IORegistryEntry::setProperty( const char *       aKey,
        !           493:                               unsigned long long aValue,
        !           494:                               unsigned int       aNumberOfBits)
        !           495: {
        !           496:     bool ret = false;
        !           497:     OSNumber * anOffset = OSNumber::withNumber( aValue, aNumberOfBits );
        !           498: 
        !           499:     if( anOffset) {
        !           500:         PLOCK;
        !           501:         ret = getPropertyTable()->setObject( aKey, anOffset );
        !           502:         PUNLOCK;
        !           503:         anOffset->release();
        !           504:     }
        !           505:     return( ret );
        !           506: }
        !           507: 
        !           508: bool
        !           509: IORegistryEntry::setProperty( const char *      aKey,
        !           510:                               void *           bytes,
        !           511:                               unsigned int      length)
        !           512: {
        !           513:     bool ret = false;
        !           514:     OSData * data = OSData::withBytes( bytes, length );
        !           515: 
        !           516:     if( data) {
        !           517:         PLOCK;
        !           518:         ret = getPropertyTable()->setObject( aKey, data );
        !           519:         PUNLOCK;
        !           520:         data->release();
        !           521:     }
        !           522:     return( ret );
        !           523: }
        !           524: 
        !           525: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !           526: 
        !           527: /* Name, location, paths */
        !           528: 
        !           529: const char * IORegistryEntry::getName( const IORegistryPlane * plane = 0 ) const
        !           530: {
        !           531:     OSSymbol *         sym = 0;
        !           532: 
        !           533:     RLOCK;
        !           534:     if( plane)
        !           535:        sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
        !           536:     if( !sym)
        !           537:        sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
        !           538:     UNLOCK;
        !           539: 
        !           540:     if( sym)
        !           541:        return( sym->getCStringNoCopy());
        !           542:     else
        !           543:         return( (getMetaClass())->getClassName());
        !           544: }
        !           545: 
        !           546: const OSSymbol * IORegistryEntry::copyName(
        !           547:                        const IORegistryPlane * plane = 0 ) const
        !           548: {
        !           549:     OSSymbol *         sym = 0;
        !           550: 
        !           551:     RLOCK;
        !           552:     if( plane)
        !           553:        sym = (OSSymbol *) registryTable()->getObject( plane->pathNameKey );
        !           554:     if( !sym)
        !           555:        sym = (OSSymbol *) registryTable()->getObject( gIONameKey );
        !           556:     if( sym)
        !           557:        sym->retain();
        !           558:     UNLOCK;
        !           559: 
        !           560:     if( sym)
        !           561:        return( sym );
        !           562:     else
        !           563:         return( OSSymbol::withCString((getMetaClass())->getClassName()) );
        !           564: }
        !           565: 
        !           566: const OSSymbol * IORegistryEntry::copyLocation(
        !           567:                        const IORegistryPlane * plane = 0 ) const
        !           568: {
        !           569:     OSSymbol *         sym = 0;
        !           570: 
        !           571:     RLOCK;
        !           572:     if( plane)
        !           573:        sym = (OSSymbol *) registryTable()->getObject( plane->pathLocationKey );
        !           574:     if( !sym)
        !           575:        sym = (OSSymbol *) registryTable()->getObject( gIOLocationKey );
        !           576:     if( sym)
        !           577:        sym->retain();
        !           578:     UNLOCK;
        !           579: 
        !           580:     return( sym );
        !           581: }
        !           582: 
        !           583: const char * IORegistryEntry::getLocation( const IORegistryPlane * plane = 0 ) const
        !           584: {
        !           585:     const OSSymbol *   sym = copyLocation( plane );
        !           586:     const char *       result = 0;
        !           587: 
        !           588:     if( sym) {
        !           589:        result = sym->getCStringNoCopy();
        !           590:        sym->release();
        !           591:     }
        !           592: 
        !           593:     return( result );
        !           594: }
        !           595: 
        !           596: void IORegistryEntry::setName( const OSSymbol * name,
        !           597:                             const IORegistryPlane * plane = 0 )
        !           598: {
        !           599:     const OSSymbol *   key;
        !           600: 
        !           601:     if( name) {
        !           602:         if( plane)
        !           603:             key = plane->pathNameKey;
        !           604:         else
        !           605:             key = gIONameKey;
        !           606: 
        !           607:        WLOCK;
        !           608:         registryTable()->setObject( key, (OSObject *) name);
        !           609:        UNLOCK;
        !           610:     }
        !           611: }
        !           612: 
        !           613: void IORegistryEntry::setName( const char * name,
        !           614:                             const IORegistryPlane * plane = 0 )
        !           615: {
        !           616:     OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( name );
        !           617:     if ( sym ) {
        !           618:         setName( sym, plane );
        !           619:         sym->release();
        !           620:     }
        !           621: }
        !           622: 
        !           623: void IORegistryEntry::setLocation( const OSSymbol * location,
        !           624:                             const IORegistryPlane * plane = 0 )
        !           625: {
        !           626:     const OSSymbol *   key;
        !           627: 
        !           628:     if( location) {
        !           629:         if( plane)
        !           630:             key = plane->pathLocationKey;
        !           631:         else
        !           632:             key = gIOLocationKey;
        !           633: 
        !           634:        WLOCK;
        !           635:         registryTable()->setObject( key, (OSObject *) location);
        !           636:        UNLOCK;
        !           637:     }
        !           638: }
        !           639: 
        !           640: void IORegistryEntry::setLocation( const char * location,
        !           641:                             const IORegistryPlane * plane = 0 )
        !           642: {
        !           643:     OSSymbol * sym = (OSSymbol *)OSSymbol::withCString( location );
        !           644:     if ( sym ) {
        !           645:         setLocation( sym, plane );
        !           646:         sym->release();
        !           647:     }
        !           648: }
        !           649: 
        !           650: bool
        !           651: IORegistryEntry::compareName( OSString * name, OSString ** matched = 0 ) const
        !           652: {
        !           653:     const OSSymbol *   sym = copyName();
        !           654:     bool               isEqual;
        !           655: 
        !           656:     isEqual = sym->isEqualTo( name );
        !           657: 
        !           658:     if( isEqual && matched) {
        !           659:        name->retain();
        !           660:        *matched = name;
        !           661:     }
        !           662: 
        !           663:     if( sym)
        !           664:        sym->release();
        !           665: 
        !           666:     return( isEqual );
        !           667: }
        !           668: 
        !           669: bool
        !           670: IORegistryEntry::compareNames( OSObject * names, OSString ** matched = 0 ) const
        !           671: {
        !           672:     OSString *         string;
        !           673:     OSCollection *     collection;
        !           674:     OSIterator *       iter = 0;
        !           675:     bool               result = false;
        !           676: 
        !           677:     if( (collection = OSDynamicCast( OSCollection, names))) {
        !           678:        iter = OSCollectionIterator::withCollection( collection );
        !           679:        string = 0;
        !           680:     } else
        !           681:        string = OSDynamicCast( OSString, names);
        !           682: 
        !           683:     do {
        !           684:        if( string)
        !           685:             result = compareName( string, matched );
        !           686: 
        !           687:     } while( (false == result)
        !           688:        && iter && (string = OSDynamicCast( OSString, iter->getNextObject())));
        !           689: 
        !           690:     if( iter)
        !           691:        iter->release();
        !           692: 
        !           693:     return( result);
        !           694: }
        !           695: 
        !           696: 
        !           697: bool IORegistryEntry::getPath( char * path, int * length,
        !           698:                                const IORegistryPlane * plane ) const
        !           699: {
        !           700:     OSArray *          stack;
        !           701:     IORegistryEntry *  root;
        !           702:     const IORegistryEntry * entry;
        !           703:     IORegistryEntry *  parent;
        !           704:     const OSSymbol *   alias;
        !           705:     int                        index;
        !           706:     int                        len, maxLength, compLen;
        !           707:     char *             nextComp;
        !           708:     bool               ok;
        !           709: 
        !           710:    if( !path || !length || !plane)
        !           711:        return( false);
        !           712: 
        !           713:     len = 0;
        !           714:     maxLength = *length - 2;
        !           715:     nextComp = path;
        !           716: 
        !           717:     len = plane->nameKey->getLength();
        !           718:     if( len >= maxLength)
        !           719:        return( false);
        !           720:     strcpy( nextComp, plane->nameKey->getCStringNoCopy());
        !           721:     nextComp[ len++ ] = ':';
        !           722:     nextComp += len;
        !           723: 
        !           724:     if( (alias = hasAlias( plane ))) {
        !           725:        len += alias->getLength();
        !           726:        ok = (maxLength > len);
        !           727:        *length = len;
        !           728:        if( ok)
        !           729:            strcpy( nextComp, alias->getCStringNoCopy());
        !           730:        return( ok );
        !           731:     }
        !           732: 
        !           733:     entry = this;
        !           734:     parent = entry->getParentEntry( plane );
        !           735:     if( !parent)
        !           736:        // Error if not attached in plane
        !           737:        return( false);
        !           738: 
        !           739:     stack = OSArray::withCapacity( getDepth( plane ));
        !           740:     if( !stack)
        !           741:        return( false);
        !           742: 
        !           743:     RLOCK;
        !           744: 
        !           745:     root = gRegistryRoot->getChildEntry( plane );
        !           746:     while( parent && (entry != root)) {
        !           747:        // stop below root
        !           748:        stack->setObject( (OSObject *) entry );
        !           749:        entry = parent;
        !           750:        parent = entry->getParentEntry( plane );
        !           751:     }
        !           752: 
        !           753:     index = stack->getCount();
        !           754:     ok = true;
        !           755: 
        !           756:     if( 0 == index) {
        !           757: 
        !           758:         *nextComp++ = '/';
        !           759:         *nextComp = 0;
        !           760:         len++;
        !           761: 
        !           762:     } else while( ok && ((--index) >= 0)) {
        !           763: 
        !           764:         entry = (IORegistryEntry *) stack->getObject((unsigned int) index );
        !           765:         assert( entry );
        !           766: 
        !           767:         compLen = maxLength - len;
        !           768:         ok = entry->getPathComponent( nextComp + 1, &compLen, plane );
        !           769: 
        !           770:         if( ok && compLen) {
        !           771:             compLen++;
        !           772:             *nextComp = '/';
        !           773:             len += compLen;
        !           774:             nextComp += compLen;
        !           775:        }
        !           776:     }
        !           777:     *length = len;
        !           778: 
        !           779:     UNLOCK;
        !           780: 
        !           781:     stack->release();
        !           782: 
        !           783:     return( ok );
        !           784: }
        !           785: 
        !           786: bool IORegistryEntry::getPathComponent( char * path, int * length,
        !           787:                                         const IORegistryPlane * plane ) const
        !           788: {
        !           789:     int                        len, locLen, maxLength;
        !           790:     const char *       compName;
        !           791:     const char *       loc;
        !           792:     bool               ok;
        !           793: 
        !           794:     maxLength = *length;
        !           795: 
        !           796:     compName = getName( plane );
        !           797:     len = strlen( compName );
        !           798:     if( (loc = getLocation( plane )))
        !           799:        locLen = 1 + strlen( loc );
        !           800:     else
        !           801:        locLen = 0;
        !           802: 
        !           803:     ok = ((len + locLen) < maxLength);
        !           804:     if( ok) {
        !           805:         strcpy( path, compName );
        !           806:        if( loc) {
        !           807:             path += len;
        !           808:             len += locLen;
        !           809:             *path++ = '@';
        !           810:             strcpy( path, loc );
        !           811:        }
        !           812:         *length = len;
        !           813:     }
        !           814: 
        !           815:     return( ok );
        !           816: }
        !           817: 
        !           818: const char * IORegistryEntry::matchPathLocation( const char * cmp,
        !           819:                                const IORegistryPlane * plane )
        !           820: {
        !           821:     const char *       str;
        !           822:     const char *       result = 0;
        !           823:     int                        num1, num2;
        !           824:     char               c1, c2;
        !           825: 
        !           826:     str = getLocation( plane );
        !           827:     if( str) {
        !           828:        c2 = str[0];
        !           829:        do {
        !           830:             num1 = strtoul( cmp, (char **) &cmp, 16 );
        !           831:             if( c2) {
        !           832:                 num2 = strtoul( str, (char **) &str, 16 );
        !           833:                 c2 = str[0];
        !           834:            } else
        !           835:                 num2 = 0;
        !           836: 
        !           837:             if( num1 != num2)
        !           838:                 break;
        !           839: 
        !           840:             c1 = *cmp++;
        !           841:             if( ',' != c1) {
        !           842:                 result = cmp - 1;
        !           843:                 break;
        !           844:             }
        !           845: 
        !           846:             if( c2) {
        !           847:                 if( c2 != ',')
        !           848:                     break;
        !           849:                 str++;
        !           850:             }
        !           851: 
        !           852:         } while( true);
        !           853:     }
        !           854: 
        !           855:     return( result );
        !           856: }
        !           857: 
        !           858: IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath,
        !           859:                                const IORegistryPlane * plane )
        !           860: {
        !           861:     IORegistryEntry *  entry = 0;
        !           862:     OSArray *          set;
        !           863:     unsigned int       index;
        !           864:     const char *       path;
        !           865:     const char *       cmp = 0;
        !           866:     size_t             len;
        !           867:     const char *       str;
        !           868: 
        !           869:     set = getChildSetReference( plane );
        !           870:     if( set) {
        !           871: 
        !           872:     path = *opath;
        !           873: 
        !           874:        for( index = 0;
        !           875:              (entry = (IORegistryEntry *) set->getObject(index));
        !           876:              index++ ) {
        !           877: 
        !           878:             cmp = path;
        !           879: 
        !           880:             if( *cmp != '@') {
        !           881:                 str = entry->getName( plane );
        !           882:                 len = strlen( str );
        !           883:                 if( strncmp( str, cmp, len ))
        !           884:                     continue;
        !           885:                 cmp += len;
        !           886:                 if( *cmp != '@' )
        !           887:                 break;
        !           888:             }
        !           889:             cmp++;
        !           890:             if( (cmp = entry->matchPathLocation( cmp, plane )))
        !           891:                 break;
        !           892:         }
        !           893:         if( entry)
        !           894:             *opath = cmp;
        !           895:     }
        !           896: 
        !           897:     return( entry );
        !           898: }
        !           899: 
        !           900: const OSSymbol * IORegistryEntry::hasAlias( const IORegistryPlane * plane,
        !           901:                                char * opath = 0, int * length = 0 ) const
        !           902: {
        !           903:     IORegistryEntry *  entry;
        !           904:     IORegistryEntry *  entry2;
        !           905:     const OSSymbol *   key;
        !           906:     const OSSymbol *   bestKey = 0;
        !           907:     OSIterator *       iter;
        !           908:     OSData *           data;
        !           909:     const char *       path = "/aliases";
        !           910: 
        !           911:     entry = IORegistryEntry::fromPath( path, plane );
        !           912:     if( entry) {
        !           913:         RLOCK;
        !           914:         if( (iter = OSCollectionIterator::withCollection(
        !           915:                                entry->getPropertyTable() ))) {
        !           916: 
        !           917:             while( (key = (OSSymbol *) iter->getNextObject())) {
        !           918: 
        !           919:                 data = (OSData *) entry->getProperty( key );
        !           920:                 path = (const char *) data->getBytesNoCopy();
        !           921:                 if( (entry2 = IORegistryEntry::fromPath( path, plane,
        !           922:                                                opath, length ))) {
        !           923:                     if( this == entry2) {
        !           924:                         if( !bestKey
        !           925:                         || (bestKey->getLength() > key->getLength()))
        !           926:                             // pick the smallest alias
        !           927:                             bestKey = key;
        !           928:                     }
        !           929:                    entry2->release();
        !           930:                }
        !           931:             }
        !           932:             iter->release();
        !           933:         }
        !           934:        entry->release();
        !           935:        UNLOCK;
        !           936:     }
        !           937:     return( bestKey );
        !           938: }
        !           939: 
        !           940: const char * IORegistryEntry::dealiasPath(
        !           941:                        const char **           opath,
        !           942:                        const IORegistryPlane * plane )
        !           943: {
        !           944:     IORegistryEntry *  entry;
        !           945:     OSData *           data;
        !           946:     const char *       path = *opath;
        !           947:     const char *       rpath = 0;
        !           948:     const char *       end;
        !           949:     char               c;
        !           950:     char               temp[ kIOMaxPlaneName + 1 ];
        !           951: 
        !           952:     if( path[0] == '/')
        !           953:        return( rpath );
        !           954: 
        !           955:     // check for alias
        !           956:     end = path;
        !           957:     while( (c = *end++) && (c != '/') && (c != ':'))
        !           958:         {}
        !           959:     end--;
        !           960:     if( (end - path) < kIOMaxPlaneName) {
        !           961:         strncpy( temp, path, end - path );
        !           962:         temp[ end - path ] = 0;
        !           963: 
        !           964:         RLOCK;
        !           965:         entry = IORegistryEntry::fromPath( "/aliases", plane );
        !           966:         if( entry) {
        !           967:             data = (OSData *) entry->getProperty( temp );
        !           968:             if( data ) {
        !           969:                 rpath = (const char *) data->getBytesNoCopy();
        !           970:                 if( rpath)
        !           971:                     *opath = end;
        !           972:             }
        !           973:            entry->release();
        !           974:         }
        !           975:         UNLOCK;
        !           976:     }
        !           977: 
        !           978:     return( rpath );
        !           979: }
        !           980: 
        !           981: IORegistryEntry * IORegistryEntry::fromPath(
        !           982:                         const char *           path,
        !           983:                         const IORegistryPlane * plane = 0,
        !           984:                         char *                 opath = 0,
        !           985:                        int *                   length = 0,
        !           986:                         IORegistryEntry *      fromEntry = 0 )
        !           987: {
        !           988:     IORegistryEntry *  where = 0;
        !           989:     IORegistryEntry *  next;
        !           990:     const char *       alias;
        !           991:     const char *       end;
        !           992:     int                        len = 0;
        !           993:     int                        len2;
        !           994:     char               c;
        !           995:     char               temp[ kIOMaxPlaneName + 1 ];
        !           996: 
        !           997:     if( 0 == path)
        !           998:        return( 0 );
        !           999: 
        !          1000:     if( 0 == plane) {
        !          1001:        // get plane name
        !          1002:         end = strchr( path, ':' );
        !          1003:        if( end && ((end - path) < kIOMaxPlaneName)) {
        !          1004:            strncpy( temp, path, end - path );
        !          1005:            temp[ end - path ] = 0;
        !          1006:             plane = getPlane( temp );
        !          1007:            path = end + 1;
        !          1008:        }
        !          1009:     }
        !          1010:     if( 0 == plane)
        !          1011:        return( 0 );
        !          1012: 
        !          1013:     // check for alias
        !          1014:     end = path;
        !          1015:     if( (alias = dealiasPath( &end, plane))) {
        !          1016:         if( length)
        !          1017:             len = *length;
        !          1018:         where = IORegistryEntry::fromPath( alias, plane,
        !          1019:                                     opath, &len, fromEntry );
        !          1020:         if( where)
        !          1021:             path = end;
        !          1022:         else
        !          1023:             len = 0;
        !          1024:     }
        !          1025: 
        !          1026:     RLOCK;
        !          1027: 
        !          1028:     do {
        !          1029:         if( 0 == where) {
        !          1030:             if( (0 == fromEntry) && (*path++ == '/'))
        !          1031:                 fromEntry = gRegistryRoot->getChildEntry( plane );
        !          1032:             where = fromEntry;
        !          1033:             if( 0 == where)
        !          1034:                 break;
        !          1035:         } else {
        !          1036:             c = *path++;
        !          1037:             if( c != '/') {
        !          1038:                 if( c && (c != ':'))   // check valid terminator
        !          1039:                     where = 0;
        !          1040:                 break;
        !          1041:             }
        !          1042:         }
        !          1043:         next = where->getChildFromComponent( &path, plane );
        !          1044:         if( next)
        !          1045:             where = next;
        !          1046:     } while( next );
        !          1047: 
        !          1048:     if( where) {
        !          1049:        // check residual path
        !          1050:        if( where != fromEntry)
        !          1051:             path--;
        !          1052: 
        !          1053:        if( opath && length) {
        !          1054:             // copy out residual path
        !          1055:            len2 = len + strlen( path );
        !          1056:            if( len2 < *length)
        !          1057:                 strcpy( opath + len, path );
        !          1058:            *length = len2;
        !          1059: 
        !          1060:        } else if( path[0])
        !          1061:            // no residual path => must be no tail for success
        !          1062:             where = 0;
        !          1063:     }
        !          1064: 
        !          1065:     if( where)
        !          1066:        where->retain();
        !          1067: 
        !          1068:     UNLOCK;
        !          1069: 
        !          1070:     return( where );
        !          1071: }
        !          1072: 
        !          1073: IORegistryEntry * IORegistryEntry::childFromPath(
        !          1074:                        const char *            path,
        !          1075:                         const IORegistryPlane * plane = 0,
        !          1076:                         char *                 opath = 0,
        !          1077:                         int *                  len = 0 )
        !          1078: {
        !          1079:     return( IORegistryEntry::fromPath( path, plane, opath, len, this ));
        !          1080: }
        !          1081: 
        !          1082: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !          1083: 
        !          1084: #define IOLinkIterator OSCollectionIterator
        !          1085: 
        !          1086: #undef super
        !          1087: #define super OSObject
        !          1088: 
        !          1089: inline bool IORegistryEntry::arrayMember( OSArray * set,
        !          1090:                                          const IORegistryEntry * member,
        !          1091:                                        unsigned int * index = 0 ) const
        !          1092: {
        !          1093:     int                i;
        !          1094:     OSObject * probeObject;
        !          1095: 
        !          1096:     for( i = 0; (probeObject = set->getObject(i)); i++) {
        !          1097:         if (probeObject == (OSObject *) member) {
        !          1098:            if( index)
        !          1099:                 *index = i;
        !          1100:             return( true );
        !          1101:        }
        !          1102:     }
        !          1103:     return( false );
        !          1104: }
        !          1105: 
        !          1106: bool IORegistryEntry::makeLink( IORegistryEntry * to,
        !          1107:                                 unsigned int relation,
        !          1108:                                 const IORegistryPlane * plane ) const
        !          1109: {
        !          1110:     OSArray *  links;
        !          1111:     bool       result = false;
        !          1112: 
        !          1113:     if( (links = (OSArray *)
        !          1114:                registryTable()->getObject( plane->keys[ relation ] ))) {
        !          1115: 
        !          1116:        result = arrayMember( links, to );
        !          1117:        if( !result)
        !          1118:             result = links->setObject( to );
        !          1119: 
        !          1120:     } else {
        !          1121: 
        !          1122:        links = OSArray::withObjects( (OSObject **) &to, 1, 1 );
        !          1123:        result = (links != 0);
        !          1124:        if( result) {
        !          1125:            result = registryTable()->setObject( plane->keys[ relation ],
        !          1126:                                           links );
        !          1127:             links->release();
        !          1128:        }
        !          1129:     }
        !          1130: 
        !          1131:     return( result);
        !          1132: }
        !          1133: 
        !          1134: void IORegistryEntry::breakLink( IORegistryEntry * to,
        !          1135:                                  unsigned int relation,
        !          1136:                                  const IORegistryPlane * plane ) const
        !          1137: {
        !          1138:     OSArray *          links;
        !          1139:     unsigned int       index;
        !          1140: 
        !          1141:     if( (links = (OSArray *)
        !          1142:                registryTable()->getObject( plane->keys[ relation ]))) {
        !          1143: 
        !          1144:        if( arrayMember( links, to, &index )) {
        !          1145:             links->removeObject( index );
        !          1146:            if( 0 == links->getCount())
        !          1147:                 registryTable()->removeObject( plane->keys[ relation ]);
        !          1148:            }
        !          1149:     }
        !          1150: }
        !          1151: 
        !          1152: 
        !          1153: OSArray * IORegistryEntry::getParentSetReference(
        !          1154:                                const IORegistryPlane * plane ) const
        !          1155: {
        !          1156:     if( plane)
        !          1157:         return( (OSArray *) registryTable()->getObject(
        !          1158:                             plane->keys[ kParentSetIndex ]));
        !          1159:     else
        !          1160:        return( 0 );
        !          1161: }
        !          1162: 
        !          1163: OSIterator * IORegistryEntry::getParentIterator(
        !          1164:                                const IORegistryPlane * plane ) const
        !          1165: {
        !          1166:     OSArray *          links;
        !          1167:     OSIterator *       iter;
        !          1168: 
        !          1169:     if( !plane)
        !          1170:        return( 0 );
        !          1171: 
        !          1172:     RLOCK;
        !          1173:     links = getParentSetReference( plane );
        !          1174:     if( 0 == links)
        !          1175:        links = OSArray::withCapacity( 1 );
        !          1176:     else
        !          1177:        links = OSArray::withArray( links, links->getCount() );
        !          1178:     UNLOCK;
        !          1179: 
        !          1180:     iter = IOLinkIterator::withCollection( links );
        !          1181: 
        !          1182:     if( links)
        !          1183:         links->release();
        !          1184: 
        !          1185:     return( iter );
        !          1186: }
        !          1187: 
        !          1188: IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const
        !          1189: {
        !          1190:     IORegistryEntry *  entry = 0;
        !          1191:     OSArray *          links;
        !          1192: 
        !          1193:     RLOCK;
        !          1194: 
        !          1195:     if( (links = getParentSetReference( plane )))
        !          1196:         entry = (IORegistryEntry *) links->getObject( 0 );
        !          1197: 
        !          1198:     UNLOCK;
        !          1199: 
        !          1200:     return( entry);
        !          1201: }
        !          1202: 
        !          1203: OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const
        !          1204: {
        !          1205:     if( plane)
        !          1206:         return( (OSArray *) registryTable()->getObject(
        !          1207:                             plane->keys[ kChildSetIndex ]));
        !          1208:     else
        !          1209:        return( 0 );
        !          1210: }
        !          1211: 
        !          1212: OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) const
        !          1213: {
        !          1214:     OSArray *          links;
        !          1215:     OSIterator *       iter;
        !          1216: 
        !          1217:     if( !plane)
        !          1218:        return( 0 );
        !          1219: 
        !          1220:     RLOCK;
        !          1221:     links = getChildSetReference( plane );
        !          1222:     if( 0 == links)
        !          1223:         links = OSArray::withCapacity( 1 );
        !          1224:     else
        !          1225:         links = OSArray::withArray( links, links->getCount() );
        !          1226:     UNLOCK;
        !          1227: 
        !          1228:     iter = IOLinkIterator::withCollection( links );
        !          1229: 
        !          1230:     if( links)
        !          1231:         links->release();
        !          1232: 
        !          1233:     return( iter );
        !          1234: }
        !          1235: 
        !          1236: 
        !          1237: IORegistryEntry * IORegistryEntry::getChildEntry(
        !          1238:                                const IORegistryPlane * plane ) const
        !          1239: {
        !          1240:     IORegistryEntry *  entry = 0;
        !          1241:     OSArray *          links;
        !          1242: 
        !          1243:     RLOCK;
        !          1244: 
        !          1245:     if( (links = getChildSetReference( plane )))
        !          1246:        entry = (IORegistryEntry *) links->getObject( 0 );
        !          1247: 
        !          1248:     UNLOCK;
        !          1249: 
        !          1250:     return( entry);
        !          1251: }
        !          1252: 
        !          1253: void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier,
        !          1254:                                        void * context,
        !          1255:                                        const IORegistryPlane * plane ) const
        !          1256: {
        !          1257:     OSArray *          array;
        !          1258:     unsigned int       index;
        !          1259:     IORegistryEntry *  next;
        !          1260: 
        !          1261:     if( !plane)
        !          1262:         return;
        !          1263: 
        !          1264:     RLOCK;
        !          1265:     array = OSArray::withArray( getChildSetReference( plane ));
        !          1266:     UNLOCK;
        !          1267:     if( array) {
        !          1268:         for( index = 0;
        !          1269:              (next = (IORegistryEntry *) array->getObject( index ));
        !          1270:              index++)
        !          1271:             (*applier)(next, context);
        !          1272:         array->release();
        !          1273:     }
        !          1274: }
        !          1275: 
        !          1276: void IORegistryEntry::applyToParents( IORegistryEntryApplierFunction applier,
        !          1277:                                       void * context,
        !          1278:                                       const IORegistryPlane * plane ) const
        !          1279: {
        !          1280:     OSArray *          array;
        !          1281:     unsigned int       index;
        !          1282:     IORegistryEntry *  next;
        !          1283: 
        !          1284:     if( !plane)
        !          1285:         return;
        !          1286: 
        !          1287:     RLOCK;
        !          1288:     array = OSArray::withArray( getParentSetReference( plane ));
        !          1289:     UNLOCK;
        !          1290:     if( array) {
        !          1291:         for( index = 0;
        !          1292:              (next = (IORegistryEntry *) array->getObject( index ));
        !          1293:              index++)
        !          1294:             (*applier)(next, context);
        !          1295:         array->release();
        !          1296:     }
        !          1297: }
        !          1298: 
        !          1299: bool IORegistryEntry::isChild( IORegistryEntry * child,
        !          1300:                                 const IORegistryPlane * plane,
        !          1301:                                bool onlyChild = false ) const
        !          1302: {
        !          1303:     OSArray *  links;
        !          1304:     bool       ret = false;
        !          1305: 
        !          1306:     RLOCK;
        !          1307: 
        !          1308:     if( (links = getChildSetReference( plane ))) {
        !          1309:        if( (!onlyChild) || (1 == links->getCount()))
        !          1310:             ret = arrayMember( links, child );
        !          1311:     }
        !          1312:     if( ret && (links = child->getParentSetReference( plane )))
        !          1313:        ret = arrayMember( links, this );
        !          1314: 
        !          1315:     UNLOCK;
        !          1316: 
        !          1317:     return( ret);
        !          1318: }
        !          1319: 
        !          1320: bool IORegistryEntry::isParent( IORegistryEntry * parent,
        !          1321:                                 const IORegistryPlane * plane,
        !          1322:                                bool onlyParent = false ) const
        !          1323: 
        !          1324: {
        !          1325:     OSArray *  links;
        !          1326:     bool       ret = false;
        !          1327: 
        !          1328:     RLOCK;
        !          1329: 
        !          1330:     if( (links = getParentSetReference( plane ))) {
        !          1331:        if( (!onlyParent) || (1 == links->getCount()))
        !          1332:             ret = arrayMember( links, parent );
        !          1333:     }
        !          1334:     if( ret && (links = parent->getChildSetReference( plane )))
        !          1335:        ret = arrayMember( links, this );
        !          1336: 
        !          1337:     UNLOCK;
        !          1338: 
        !          1339:     return( ret);
        !          1340: }
        !          1341: 
        !          1342: bool IORegistryEntry::inPlane( const IORegistryPlane * plane ) const
        !          1343: {
        !          1344:     bool ret;
        !          1345: 
        !          1346:     RLOCK;
        !          1347: 
        !          1348:     ret = (0 != getParentSetReference( plane ));
        !          1349: 
        !          1350:     UNLOCK;
        !          1351: 
        !          1352:     return( ret );
        !          1353: }
        !          1354: 
        !          1355: bool IORegistryEntry::attachToParent( IORegistryEntry * parent,
        !          1356:                                 const IORegistryPlane * plane )
        !          1357: {
        !          1358:     OSArray *  links;
        !          1359:     bool       ret;
        !          1360:     bool       needParent;
        !          1361: 
        !          1362:     if( this == parent)
        !          1363:        return( false );
        !          1364: 
        !          1365:     WLOCK;
        !          1366: 
        !          1367:     ret = makeLink( parent, kParentSetIndex, plane );
        !          1368: 
        !          1369:     if( (links = parent->getChildSetReference( plane )))
        !          1370:        needParent = (false == arrayMember( links, this ));
        !          1371:     else
        !          1372:        needParent = true;
        !          1373: 
        !          1374: //    ret &= parent->makeLink( this, kChildSetIndex, plane );
        !          1375: 
        !          1376:     UNLOCK;
        !          1377: 
        !          1378:     if( needParent)
        !          1379:         ret &= parent->attachToChild( this, plane );
        !          1380: 
        !          1381:     return( ret );
        !          1382: }
        !          1383: 
        !          1384: bool IORegistryEntry::attachToChild( IORegistryEntry * child,
        !          1385:                                         const IORegistryPlane * plane )
        !          1386: {
        !          1387:     OSArray *  links;
        !          1388:     bool       ret;
        !          1389:     bool       needChild;
        !          1390: 
        !          1391:     if( this == child)
        !          1392:        return( false );
        !          1393: 
        !          1394:     WLOCK;
        !          1395: 
        !          1396:     ret = makeLink( child, kChildSetIndex, plane );
        !          1397: 
        !          1398:     if( (links = child->getParentSetReference( plane )))
        !          1399:        needChild = (false == arrayMember( links, this ));
        !          1400:     else
        !          1401:        needChild = true;
        !          1402: 
        !          1403:     UNLOCK;
        !          1404: 
        !          1405:     if( needChild)
        !          1406:        ret &= child->attachToParent( this, plane );
        !          1407: 
        !          1408:     return( ret );
        !          1409: }
        !          1410: 
        !          1411: void IORegistryEntry::detachFromParent( IORegistryEntry * parent,
        !          1412:                                 const IORegistryPlane * plane )
        !          1413: {
        !          1414:     OSArray *  links;
        !          1415:     bool       needParent;
        !          1416: 
        !          1417:     WLOCK;
        !          1418: 
        !          1419:     parent->retain();
        !          1420: 
        !          1421:     breakLink( parent, kParentSetIndex, plane );
        !          1422: 
        !          1423:     if( (links = parent->getChildSetReference( plane )))
        !          1424:        needParent = arrayMember( links, this );
        !          1425:     else
        !          1426:        needParent = false;
        !          1427: 
        !          1428: //    parent->breakLink( this, kChildSetIndex, plane );
        !          1429: 
        !          1430:     UNLOCK;
        !          1431: 
        !          1432:     if( needParent)
        !          1433:        parent->detachFromChild( this, plane );
        !          1434: 
        !          1435:     parent->release();
        !          1436: }
        !          1437: 
        !          1438: void IORegistryEntry::detachFromChild( IORegistryEntry * child,
        !          1439:                                 const IORegistryPlane * plane )
        !          1440: {
        !          1441:     OSArray *          links;
        !          1442:     bool       needChild;
        !          1443: 
        !          1444:     WLOCK;
        !          1445: 
        !          1446:     child->retain();
        !          1447: 
        !          1448:     breakLink( child, kChildSetIndex, plane );
        !          1449: 
        !          1450:     if( (links = child->getParentSetReference( plane )))
        !          1451:        needChild = arrayMember( links, this );
        !          1452:     else
        !          1453:        needChild = false;
        !          1454: 
        !          1455:     UNLOCK;
        !          1456: 
        !          1457:     if( needChild)
        !          1458:        child->detachFromParent( this, plane );
        !          1459: 
        !          1460:     child->release();
        !          1461: }
        !          1462: 
        !          1463: void IORegistryEntry::detachAbove( const IORegistryPlane * plane )
        !          1464: {
        !          1465:     IORegistryEntry *  parent;
        !          1466: 
        !          1467:     retain();
        !          1468:     while( (parent = getParentEntry( plane )))
        !          1469:        detachFromParent( parent, plane );
        !          1470:     release();
        !          1471: }
        !          1472: 
        !          1473: void IORegistryEntry::detachAll( const IORegistryPlane * plane )
        !          1474: {
        !          1475:     OSOrderedSet *             all;
        !          1476:     IORegistryEntry *          next;
        !          1477:     IORegistryIterator *       regIter;
        !          1478: 
        !          1479:     regIter = IORegistryIterator::iterateOver( this, plane, true );
        !          1480:     if( 0 == regIter)
        !          1481:        return;
        !          1482:     all = regIter->iterateAll();
        !          1483:     regIter->release();
        !          1484: 
        !          1485:     detachAbove( plane );
        !          1486:     if( all) {
        !          1487:        while( (next = (IORegistryEntry *) all->getLastObject())) {
        !          1488: 
        !          1489:             next->retain();
        !          1490:             all->removeObject(next);
        !          1491: 
        !          1492:             next->detachAbove( plane );
        !          1493:             next->release();
        !          1494:         }
        !          1495:         all->release();
        !          1496:     }
        !          1497: }
        !          1498: 
        !          1499: unsigned int IORegistryEntry::getDepth( const IORegistryPlane * plane ) const
        !          1500: {
        !          1501:     unsigned int               depth = 1;
        !          1502:     OSArray *                  parents;
        !          1503:     unsigned int               oneDepth, maxParentDepth, count;
        !          1504:     IORegistryEntry *          one;
        !          1505:     const IORegistryEntry *    next;
        !          1506:     unsigned int               index;
        !          1507: 
        !          1508:     RLOCK;
        !          1509: 
        !          1510:     next = this;
        !          1511:     while( (parents = next->getParentSetReference( plane ))) {
        !          1512: 
        !          1513:        count = parents->getCount();
        !          1514:        if( 0 == count)
        !          1515:            break;
        !          1516:        if( 1 == count) {
        !          1517:             depth++;
        !          1518:             next = (IORegistryEntry *) parents->getObject( 0 );
        !          1519:        } else {
        !          1520:            // painful
        !          1521:            maxParentDepth = 0;
        !          1522:            for( index = 0;
        !          1523:                 (one = (IORegistryEntry *) parents->getObject( index ));
        !          1524:                 index++ ) {
        !          1525:                 oneDepth = one->getDepth( plane );
        !          1526:                 if( oneDepth > maxParentDepth)
        !          1527:                     maxParentDepth = oneDepth;
        !          1528:             }
        !          1529:             depth += maxParentDepth;
        !          1530:            break;
        !          1531:        }
        !          1532:     }
        !          1533: 
        !          1534:     UNLOCK;
        !          1535: 
        !          1536:     return( depth);
        !          1537: }
        !          1538: 
        !          1539: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !          1540: 
        !          1541: #undef super
        !          1542: #define super OSIterator
        !          1543: 
        !          1544: OSDefineMetaClassAndStructors(IORegistryIterator, OSIterator)
        !          1545: 
        !          1546: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
        !          1547: 
        !          1548: IORegistryIterator *
        !          1549: IORegistryIterator::iterateOver( IORegistryEntry * root,
        !          1550:                                  const IORegistryPlane * plane,
        !          1551:                                  IOOptionBits options = 0 )
        !          1552: {
        !          1553:     IORegistryIterator *       create;
        !          1554: 
        !          1555:     if( 0 == root)
        !          1556:        return( 0);
        !          1557:     if( 0 == plane)
        !          1558:        return( 0);
        !          1559: 
        !          1560:     create = new IORegistryIterator;
        !          1561:     if( create) {
        !          1562:         if( create->init()) {
        !          1563: 
        !          1564:             root->retain();
        !          1565:             create->root = root;
        !          1566:             create->where = &create->start;
        !          1567:             create->start.current = root;
        !          1568:             create->plane = plane;
        !          1569:             create->options = options;
        !          1570: 
        !          1571:        } else {
        !          1572:            create->release();
        !          1573:            create = 0;
        !          1574:        }
        !          1575:     }
        !          1576:     return( create);
        !          1577: }
        !          1578: 
        !          1579: IORegistryIterator *
        !          1580: IORegistryIterator::iterateOver( const IORegistryPlane * plane,
        !          1581:                                 IOOptionBits options = 0 )
        !          1582: {
        !          1583:     return( iterateOver( gRegistryRoot, plane, options ));
        !          1584: }
        !          1585: 
        !          1586: bool IORegistryIterator::isValid( void )
        !          1587: {
        !          1588:     bool               ok;
        !          1589:     IORegCursor *      next;
        !          1590: 
        !          1591:     ok = true;
        !          1592:     next = where;
        !          1593: 
        !          1594:     RLOCK;
        !          1595:     while( ok && next) {
        !          1596:        if( where->iter)
        !          1597:             ok = where->iter->isValid();
        !          1598:        next = next->next;
        !          1599:     }
        !          1600:     UNLOCK;
        !          1601: 
        !          1602:     return( ok);
        !          1603: }
        !          1604: 
        !          1605: void IORegistryIterator::enterEntry( const IORegistryPlane * enterPlane )
        !          1606: {
        !          1607:     IORegCursor *      prev;
        !          1608: 
        !          1609:     prev = where;
        !          1610:     where = (IORegCursor *) IOMalloc( sizeof( IORegCursor));
        !          1611:     assert( where);
        !          1612: 
        !          1613:     if( where) {
        !          1614:         where->iter = 0;
        !          1615:         where->next = prev;
        !          1616:         where->current = prev->current;
        !          1617:         plane = enterPlane;
        !          1618:     }
        !          1619: }
        !          1620: 
        !          1621: void IORegistryIterator::enterEntry( void )
        !          1622: {
        !          1623:     enterEntry( plane );
        !          1624: }
        !          1625: 
        !          1626: bool IORegistryIterator::exitEntry( void )
        !          1627: {
        !          1628:     IORegCursor *      gone;
        !          1629: 
        !          1630:     if( where->iter) {
        !          1631:        where->iter->release();
        !          1632:        where->iter = 0;
        !          1633:         if( where->current)// && (where != &start))
        !          1634:             where->current->release();
        !          1635:     }
        !          1636: 
        !          1637:     if( where != &start) {
        !          1638:        gone = where;
        !          1639:         where = gone->next;
        !          1640:         IOFree( gone, sizeof( IORegCursor));
        !          1641:        return( true);
        !          1642: 
        !          1643:     } else
        !          1644:         return( false);
        !          1645: }
        !          1646: 
        !          1647: void IORegistryIterator::reset( void )
        !          1648: {
        !          1649:     while( exitEntry())
        !          1650:        {}
        !          1651: 
        !          1652:     if( done) {
        !          1653:        done->release();
        !          1654:        done = 0;
        !          1655:     }
        !          1656: 
        !          1657:     where->current = root;
        !          1658: }
        !          1659: 
        !          1660: void IORegistryIterator::free( void )
        !          1661: {
        !          1662:     reset();
        !          1663: 
        !          1664:     if( root)
        !          1665:         root->release();
        !          1666: 
        !          1667:     super::free();
        !          1668: }
        !          1669: 
        !          1670: 
        !          1671: IORegistryEntry * IORegistryIterator::getNextObjectFlat( void )
        !          1672: {
        !          1673:     IORegistryEntry *  next = 0;
        !          1674:     OSArray *          links = 0;
        !          1675: 
        !          1676:     RLOCK;
        !          1677: 
        !          1678:     if( (0 == where->iter)) {
        !          1679:        // just entered - create new iter
        !          1680:        if( isValid()
        !          1681:         &&  where->current
        !          1682:         &&  (links = ( (options & kIORegistryIterateParents) ?
        !          1683:                         where->current->getParentSetReference( plane ) :
        !          1684:                         where->current->getChildSetReference( plane ) )) )
        !          1685: 
        !          1686:             where->iter = OSCollectionIterator::withCollection( links );
        !          1687: 
        !          1688:     } else
        !          1689:        // next sibling - release current
        !          1690:         if( where->current)
        !          1691:             where->current->release();
        !          1692: 
        !          1693:     if( where->iter)
        !          1694:         next = (IORegistryEntry *) where->iter->getNextObject();
        !          1695: 
        !          1696:     if( next)
        !          1697:        next->retain();
        !          1698: 
        !          1699:     where->current = next;
        !          1700: 
        !          1701:     UNLOCK;
        !          1702: 
        !          1703:     return( next);
        !          1704: }
        !          1705: 
        !          1706: IORegistryEntry * IORegistryIterator::getNextObjectRecursive( void )
        !          1707: {
        !          1708:     IORegistryEntry *  next;
        !          1709: 
        !          1710:     do
        !          1711:         next = getNextObjectFlat();
        !          1712:     while( (0 == next) && exitEntry());
        !          1713: 
        !          1714:     if( next) {
        !          1715:        if( 0 == done)
        !          1716:             done = OSOrderedSet::withCapacity( 10 );
        !          1717:        if( done->setObject((OSObject *) next)) {
        !          1718:                    // done set didn't contain this one, so recurse
        !          1719:             enterEntry();
        !          1720:        }
        !          1721:     }
        !          1722:     return( next);
        !          1723: }
        !          1724: 
        !          1725: IORegistryEntry * IORegistryIterator::getNextObject( void )
        !          1726: {
        !          1727:     if( options & kIORegistryIterateRecursively)
        !          1728:        return( getNextObjectRecursive());
        !          1729:     else
        !          1730:        return( getNextObjectFlat());
        !          1731: }
        !          1732: 
        !          1733: IORegistryEntry * IORegistryIterator::getCurrentEntry( void )
        !          1734: {
        !          1735:     if( isValid())
        !          1736:        return( where->current);
        !          1737:     else
        !          1738:        return( 0);
        !          1739: }
        !          1740: 
        !          1741: OSOrderedSet * IORegistryIterator::iterateAll( void )
        !          1742: {
        !          1743:     reset();
        !          1744:     while( getNextObjectRecursive())
        !          1745:         {}
        !          1746:     if( done)
        !          1747:         done->retain();
        !          1748:     return( done);
        !          1749: }
        !          1750: 
        !          1751: 

unix.superglobalmegacorp.com

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