/*! Recursively iterates through the descendents of the given package root node and removes all package nodes from the node tree in post-order, until encountering \a endPackageNode (if non-null). Due to limited kernel stack space we avoid deep recursive function calls and rather use the package node stack implied by the tree. */ void Volume::_RemovePackageContentRootNode(Package* package, PackageNode* rootPackageNode, PackageNode* endPackageNode, bool notify) { PackageNode* packageNode = rootPackageNode; Directory* directory = fRootDirectory; directory->WriteLock(); do { if (packageNode == endPackageNode) break; // recurse into directory if (PackageDirectory* packageDirectory = dynamic_cast<PackageDirectory*>(packageNode)) { if (packageDirectory->FirstChild() != NULL) { if (Directory* childDirectory = dynamic_cast<Directory*>( directory->FindChild(packageNode->Name()))) { directory = childDirectory; packageNode = packageDirectory->FirstChild(); directory->WriteLock(); continue; } } } // continue with the next available (ancestors's) sibling do { PackageDirectory* packageDirectory = packageNode->Parent(); PackageNode* sibling = packageDirectory != NULL ? packageDirectory->NextChild(packageNode) : NULL; // we're done with the node -- remove it _RemovePackageNode(directory, packageNode, directory->FindChild(packageNode->Name()), notify); if (sibling != NULL) { packageNode = sibling; break; } // no more siblings -- go back up the tree packageNode = packageDirectory; directory->WriteUnlock(); directory = directory->Parent(); // the parent is still locked, so this is safe } while (packageNode != NULL/* && packageNode != rootPackageNode*/); } while (packageNode != NULL/* && packageNode != rootPackageNode*/); }
virtual status_t GetNextEntry(void* _cookie, char* nameBuffer, size_t bufferSize) { Cookie* cookie = (Cookie*)_cookie; PackageNode* child = cookie->nextChild; if (child == NULL) return B_ENTRY_NOT_FOUND; cookie->nextChild = fDirectory->NextChild(child); strlcpy(nameBuffer, child->Name(), bufferSize); return B_OK; }
void Volume::_RemovePackageContent(Package* package, PackageNode* endNode, bool notify) { PackageNode* node = package->Nodes().Head(); while (node != NULL) { if (node == endNode) break; PackageNode* nextNode = package->Nodes().GetNext(node); // skip over ".PackageInfo" file, it isn't part of the package content if (strcmp(node->Name(), B_HPKG_PACKAGE_INFO_FILE_NAME) != 0) _RemovePackageContentRootNode(package, node, NULL, notify); node = nextNode; } fPackageFSRoot->RemovePackage(package);; }