+ int len, locLen, maxLength;
+ const char * compName;
+ const char * loc;
+ bool ok;
+
+ maxLength = *length;
+
+ compName = getName( plane );
+ len = strlen( compName );
+ if ((loc = getLocation( plane ))) {
+ locLen = 1 + strlen( loc );
+ } else {
+ locLen = 0;
+ }
+
+ ok = ((len + locLen + 1) < maxLength);
+ if (ok) {
+ strlcpy( path, compName, len + 1 );
+ if (loc) {
+ path += len;
+ len += locLen;
+ *path++ = '@';
+ strlcpy( path, loc, locLen );
+ }
+ *length = len;
+ }
+
+ return ok;
+}
+
+const char *
+IORegistryEntry::matchPathLocation( const char * cmp,
+ const IORegistryPlane * plane )
+{
+ const char * str;
+ const char * result = NULL;
+ u_quad_t num1, num2;
+ char lastPathChar, lastLocationChar;
+
+ str = getLocation( plane );
+ if (str) {
+ lastPathChar = cmp[0];
+ lastLocationChar = str[0];
+ do {
+ if (lastPathChar) {
+ num1 = strtouq( cmp, (char **) &cmp, 16 );
+ lastPathChar = *cmp++;
+ } else {
+ num1 = 0;
+ }
+
+ if (lastLocationChar) {
+ num2 = strtouq( str, (char **) &str, 16 );
+ lastLocationChar = *str++;
+ } else {
+ num2 = 0;
+ }
+
+ if (num1 != num2) {
+ break;
+ }
+
+ if (!lastPathChar && !lastLocationChar) {
+ result = cmp - 1;
+ break;
+ }
+
+ if ((',' != lastPathChar) && (':' != lastPathChar)) {
+ lastPathChar = 0;
+ }
+
+ if (lastPathChar && lastLocationChar && (lastPathChar != lastLocationChar)) {
+ break;
+ }
+ } while (true);
+ }
+
+ return result;
+}
+
+IORegistryEntry *
+IORegistryEntry::getChildFromComponent( const char ** opath,
+ const IORegistryPlane * plane )
+{
+ IORegistryEntry * entry = NULL;
+ OSArray * set;
+ unsigned int index;
+ const char * path;
+ const char * cmp = NULL;
+ char c;
+ size_t len;
+ const char * str;
+
+ set = getChildSetReference( plane );
+ if (set) {
+ path = *opath;
+
+ for (index = 0;
+ (entry = (IORegistryEntry *) set->getObject(index));
+ index++) {
+ cmp = path;
+
+ if (*cmp != '@') {
+ str = entry->getName( plane );
+ len = strlen( str );
+ if (strncmp( str, cmp, len )) {
+ continue;
+ }
+ cmp += len;
+
+ c = *cmp;
+ if ((c == 0) || (c == '/') || (c == ':')) {
+ break;
+ }
+ if (c != '@') {
+ continue;
+ }
+ }
+ cmp++;
+ if ((cmp = entry->matchPathLocation( cmp, plane ))) {
+ break;
+ }
+ }
+ if (entry) {
+ *opath = cmp;
+ }
+ }
+
+ return entry;
+}
+
+const OSSymbol *
+IORegistryEntry::hasAlias( const IORegistryPlane * plane,
+ char * opath, int * length ) const
+{
+ IORegistryEntry * entry;
+ IORegistryEntry * entry2;
+ const OSSymbol * key;
+ const OSSymbol * bestKey = NULL;
+ OSIterator * iter;
+ OSData * data;
+ const char * path = "/aliases";
+
+ entry = IORegistryEntry::fromPath( path, plane );
+ if (entry) {
+ RLOCK;
+ if ((iter = OSCollectionIterator::withCollection(
+ entry->getPropertyTable()))) {
+ while ((key = (OSSymbol *) iter->getNextObject())) {
+ data = (OSData *) entry->getProperty( key );
+ path = (const char *) data->getBytesNoCopy();
+ if ((entry2 = IORegistryEntry::fromPath( path, plane,
+ opath, length ))) {
+ if (this == entry2) {
+ if (!bestKey
+ || (bestKey->getLength() > key->getLength())) {
+ // pick the smallest alias
+ bestKey = key;
+ }
+ }
+ entry2->release();
+ }
+ }
+ iter->release();
+ }
+ entry->release();
+ UNLOCK;
+ }
+ return bestKey;
+}
+
+const char *
+IORegistryEntry::dealiasPath(
+ const char ** opath,
+ const IORegistryPlane * plane )
+{
+ IORegistryEntry * entry;
+ OSData * data;
+ const char * path = *opath;
+ const char * rpath = NULL;
+ const char * end;
+ char c;
+ char temp[kIOMaxPlaneName + 1];
+
+ if (path[0] == '/') {
+ return rpath;
+ }
+
+ // check for alias
+ end = path;
+ while ((c = *end++) && (c != '/') && (c != ':')) {
+ }
+ end--;
+ if ((end - path) < kIOMaxPlaneName) {
+ strlcpy( temp, path, end - path + 1 );
+
+ RLOCK;
+ entry = IORegistryEntry::fromPath( "/aliases", plane );
+ if (entry) {
+ data = (OSData *) entry->getProperty( temp );
+ if (data) {
+ rpath = (const char *) data->getBytesNoCopy();
+ if (rpath) {
+ *opath = end;
+ }
+ }
+ entry->release();
+ }
+ UNLOCK;
+ }
+
+ return rpath;
+}
+
+IORegistryEntry *
+IORegistryEntry::fromPath(
+ const char * path,
+ const IORegistryPlane * plane,
+ char * opath,
+ int * length,
+ IORegistryEntry * fromEntry )
+{
+ IORegistryEntry * where = NULL;
+ IORegistryEntry * aliasEntry = NULL;
+ IORegistryEntry * next;
+ const char * alias;
+ const char * end;
+ int len = 0;
+ int len2;
+ char c;
+ char temp[kIOMaxPlaneName + 1];
+
+ if (NULL == path) {
+ return NULL;
+ }
+
+ if (NULL == plane) {
+ // get plane name
+ end = strchr( path, ':' );
+ if (end && ((end - path) < kIOMaxPlaneName)) {
+ strlcpy( temp, path, end - path + 1 );
+ plane = getPlane( temp );
+ path = end + 1;
+ }
+ }
+ if (NULL == plane) {
+ return NULL;
+ }
+
+ // check for alias
+ end = path;
+ if ((alias = dealiasPath( &end, plane))) {
+ if (length) {
+ len = *length;
+ }
+ aliasEntry = IORegistryEntry::fromPath( alias, plane,
+ opath, &len, fromEntry );
+ where = aliasEntry;
+ if (where) {
+ path = end;
+ } else {
+ len = 0;
+ }
+ }
+
+ RLOCK;