Пример #1
0
/*!	This method recursively iterates through the descendents of the given
	package root node and adds all package nodes to the node tree in
	pre-order.
	Due to limited kernel stack space we avoid deep recursive function calls
	and rather use the package node stack implied by the tree.
*/
status_t
Volume::_AddPackageContentRootNode(Package* package,
	PackageNode* rootPackageNode, bool notify)
{
	PackageNode* packageNode = rootPackageNode;
	Directory* directory = fRootDirectory;
	directory->WriteLock();

	do {
		Node* node;
		status_t error = _AddPackageNode(directory, packageNode, notify, node);
			// returns B_OK with a NULL node, when skipping the node
		if (error != B_OK) {
			// unlock all directories
			while (directory != NULL) {
				directory->WriteUnlock();
				directory = directory->Parent();
			}

			// remove the added package nodes
			_RemovePackageContentRootNode(package, rootPackageNode, packageNode,
				notify);
			RETURN_ERROR(error);
		}

		// recurse into directory, unless we're supposed to skip the node
		if (node != NULL) {
			if (PackageDirectory* packageDirectory
					= dynamic_cast<PackageDirectory*>(packageNode)) {
				if (packageDirectory->FirstChild() != NULL) {
					directory = dynamic_cast<Directory*>(node);
					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;

			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);
	} while (packageNode != NULL);

	return B_OK;
}
Пример #2
0
	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;
	}
Пример #3
0
/*!	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*/);
}
Пример #4
0
	virtual void RemoveEntry(const char* path)
	{
		const char* componentEnd = strchr(path, '/');
		if (componentEnd == NULL)
			componentEnd = path + strlen(path);

		PackageNode* child = _LookupChild(path, componentEnd - path);
		if (child == NULL)
			return;

		if (*componentEnd == '\0') {
			// last path component -- delete the child
			fEntries.Remove(child);
			delete child;
		} else {
			// must be a directory component -- continue resolving the path
			child->RemoveEntry(componentEnd + 1);
		}
	}
Пример #5
0
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);;
}
Пример #6
0
	virtual status_t HandleEntryAttribute(BPackageEntry* entry,
		BPackageEntryAttribute* attribute)
	{
		if (fErrorOccurred)
			return B_OK;

		PackageNode* node = (PackageNode*)entry->UserToken();

		PackageNodeAttribute* nodeAttribute = new(std::nothrow)
			PackageNodeAttribute(attribute->Type(), attribute->Data());
		if (nodeAttribute == NULL)
			RETURN_ERROR(B_NO_MEMORY)

		status_t error = nodeAttribute->Init(attribute->Name());
		if (error != B_OK) {
			delete nodeAttribute;
			RETURN_ERROR(error);
		}

		node->AddAttribute(nodeAttribute);

		return B_OK;
	}
Пример #7
0
	virtual status_t HandleEntry(BPackageEntry* entry)
	{
		if (fErrorOccurred)
			return B_OK;

		PackageDirectory* parentDir = NULL;
		if (entry->Parent() != NULL) {
			parentDir = dynamic_cast<PackageDirectory*>(
				(PackageNode*)entry->Parent()->UserToken());
			if (parentDir == NULL)
				RETURN_ERROR(B_BAD_DATA);
		}

		status_t error;

		// get the file mode -- filter out write permissions
		mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH);

		// create the package node
		PackageNode* node;
		if (S_ISREG(mode)) {
			// file
			node = new(std::nothrow) PackageFile(fPackage, mode, entry->Data());
		} else if (S_ISLNK(mode)) {
			// symlink
			PackageSymlink* symlink = new(std::nothrow) PackageSymlink(
				fPackage, mode);
			if (symlink == NULL)
				RETURN_ERROR(B_NO_MEMORY);

			error = symlink->SetSymlinkPath(entry->SymlinkPath());
			if (error != B_OK) {
				delete symlink;
				return error;
			}

			node = symlink;
		} else if (S_ISDIR(mode)) {
			// directory
			node = new(std::nothrow) PackageDirectory(fPackage, mode);
		} else
			RETURN_ERROR(B_BAD_DATA);

		if (node == NULL)
			RETURN_ERROR(B_NO_MEMORY);
		BReference<PackageNode> nodeReference(node, true);

		error = node->Init(parentDir, entry->Name());
		if (error != B_OK)
			RETURN_ERROR(error);

		node->SetModifiedTime(entry->ModifiedTime());

		// add it to the parent directory
		if (parentDir != NULL)
			parentDir->AddChild(node);
		else
			fPackage->AddNode(node);

		entry->SetUserToken(node);

		return B_OK;
	}
Пример #8
0
	virtual status_t HandleEntry(BPackageEntry* entry)
	{
		if (fErrorOccurred
			|| (fLastSettingsEntry != NULL
				&& fLastSettingsEntry->IsBlackListed())) {
			return B_OK;
		}

		PackageDirectory* parentDir = NULL;
		if (const BPackageEntry* parentEntry = entry->Parent()) {
			if (!S_ISDIR(parentEntry->Mode()))
				RETURN_ERROR(B_BAD_DATA);

			parentDir = static_cast<PackageDirectory*>(
				(PackageNode*)parentEntry->UserToken());
		}

		if (fSettingsItem != NULL
			&& (parentDir == NULL
				|| entry->Parent() == fLastSettingsEntryEntry)) {
			PackageSettingsItem::Entry* settingsEntry
				= fSettingsItem->FindEntry(fLastSettingsEntry, entry->Name());
			if (settingsEntry != NULL) {
				fLastSettingsEntry = settingsEntry;
				fLastSettingsEntryEntry = entry;
				if (fLastSettingsEntry->IsBlackListed())
					return B_OK;
			}
		}

		if (parentDir == NULL)
			parentDir = fVolume->RootDirectory();

		status_t error;

		// get the file mode -- filter out write permissions
		mode_t mode = entry->Mode() & ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH);

		// create the package node
		PackageNode* node;
		if (S_ISREG(mode)) {
			// file
			node = new(std::nothrow) PackageFile(fVolume, mode, entry->Data());
		} else if (S_ISLNK(mode)) {
			// symlink
			PackageSymlink* symlink = new(std::nothrow) PackageSymlink(
				fVolume, mode);
			if (symlink == NULL)
				RETURN_ERROR(B_NO_MEMORY);

			error = symlink->SetSymlinkPath(entry->SymlinkPath());
			if (error != B_OK) {
				delete symlink;
				return error;
			}

			node = symlink;
		} else if (S_ISDIR(mode)) {
			// directory
			node = new(std::nothrow) PackageDirectory(fVolume, mode);
		} else
			RETURN_ERROR(B_BAD_DATA);

		if (node == NULL)
			RETURN_ERROR(B_NO_MEMORY);

		error = node->Init(parentDir, entry->Name(), fVolume->NextNodeID());
		if (error != B_OK) {
			delete node;
			RETURN_ERROR(error);
		}

		node->SetModifiedTime(entry->ModifiedTime());

		// add it to the parent directory
		parentDir->AddChild(node);

		entry->SetUserToken(node);

		return B_OK;
	}