package daemon: Fix handling of multiple writable files
When attempting to extract the second writable file from the package, we noticed that the root directory already existed and assumed everything had been already extracted. Now we first extract all files and process them one by one afterwards. Fixes #10131.
This commit is contained in:
@@ -512,12 +512,7 @@ private:
|
|||||||
_AddUser(package, *user);
|
_AddUser(package, *user);
|
||||||
|
|
||||||
// handle global writable files
|
// handle global writable files
|
||||||
const BObjectList<BGlobalWritableFileInfo>& files
|
_AddGlobalWritableFiles(package);
|
||||||
= package->Info().GlobalWritableFileInfos();
|
|
||||||
for (int32 i = 0; const BGlobalWritableFileInfo* file = files.ItemAt(i);
|
|
||||||
i++) {
|
|
||||||
_AddGlobalWritableFile(package, *file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _AddGroup(Package* package, const BString& groupName)
|
void _AddGroup(Package* package, const BString& groupName)
|
||||||
@@ -612,10 +607,19 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _AddGlobalWritableFile(Package* package,
|
void _AddGlobalWritableFiles(Package* package)
|
||||||
const BGlobalWritableFileInfo& file)
|
|
||||||
{
|
{
|
||||||
if (!file.IsIncluded())
|
// get the list of included files
|
||||||
|
const BObjectList<BGlobalWritableFileInfo>& files
|
||||||
|
= package->Info().GlobalWritableFileInfos();
|
||||||
|
BStringList contentPaths;
|
||||||
|
for (int32 i = 0; const BGlobalWritableFileInfo* file = files.ItemAt(i);
|
||||||
|
i++) {
|
||||||
|
if (file->IsIncluded() && !contentPaths.Add(file->Path()))
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentPaths.IsEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Open the root directory of the installation location where we will
|
// Open the root directory of the installation location where we will
|
||||||
@@ -645,9 +649,22 @@ private:
|
|||||||
|
|
||||||
// extract files into a subdir of the writable-files directory
|
// extract files into a subdir of the writable-files directory
|
||||||
BDirectory extractedFilesDirectory;
|
BDirectory extractedFilesDirectory;
|
||||||
_ExtractPackageContent(package, file.Path(),
|
_ExtractPackageContent(package, contentPaths,
|
||||||
fWritableFilesDirectory, extractedFilesDirectory);
|
fWritableFilesDirectory, extractedFilesDirectory);
|
||||||
|
|
||||||
|
for (int32 i = 0; const BGlobalWritableFileInfo* file = files.ItemAt(i);
|
||||||
|
i++) {
|
||||||
|
if (file->IsIncluded()) {
|
||||||
|
_AddGlobalWritableFile(package, *file, rootDirectory,
|
||||||
|
extractedFilesDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _AddGlobalWritableFile(Package* package,
|
||||||
|
const BGlobalWritableFileInfo& file, const BDirectory& rootDirectory,
|
||||||
|
const BDirectory& extractedFilesDirectory)
|
||||||
|
{
|
||||||
// Map the path name to the actual target location. Currently this only
|
// Map the path name to the actual target location. Currently this only
|
||||||
// concerns "settings/", which is mapped to "settings/global/".
|
// concerns "settings/", which is mapped to "settings/global/".
|
||||||
BString targetPath(file.Path());
|
BString targetPath(file.Path());
|
||||||
@@ -662,7 +679,7 @@ private:
|
|||||||
|
|
||||||
// open parent directory of the source entry
|
// open parent directory of the source entry
|
||||||
const char* lastSlash = strrchr(file.Path(), '/');
|
const char* lastSlash = strrchr(file.Path(), '/');
|
||||||
BDirectory* sourceDirectory;
|
const BDirectory* sourceDirectory;
|
||||||
BDirectory stackSourceDirectory;
|
BDirectory stackSourceDirectory;
|
||||||
if (lastSlash != NULL) {
|
if (lastSlash != NULL) {
|
||||||
sourceDirectory = &stackSourceDirectory;
|
sourceDirectory = &stackSourceDirectory;
|
||||||
@@ -671,8 +688,8 @@ private:
|
|||||||
if (sourceParentPath.Length() == 0)
|
if (sourceParentPath.Length() == 0)
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
|
|
||||||
error = stackSourceDirectory.SetTo(&extractedFilesDirectory,
|
status_t error = stackSourceDirectory.SetTo(
|
||||||
sourceParentPath);
|
&extractedFilesDirectory, sourceParentPath);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
throw Exception(error,
|
throw Exception(error,
|
||||||
BString().SetToFormat("failed to open directory \"%s\"",
|
BString().SetToFormat("failed to open directory \"%s\"",
|
||||||
@@ -696,7 +713,7 @@ private:
|
|||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
|
|
||||||
BDirectory targetDirectory;
|
BDirectory targetDirectory;
|
||||||
error = FSUtils::OpenSubDirectory(rootDirectory,
|
status_t error = FSUtils::OpenSubDirectory(rootDirectory,
|
||||||
RelativePath(targetParentPath), true, targetDirectory);
|
RelativePath(targetParentPath), true, targetDirectory);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
throw Exception(error,
|
throw Exception(error,
|
||||||
@@ -718,8 +735,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _AddGlobalWritableFileRecurse(Package* package,
|
void _AddGlobalWritableFileRecurse(Package* package,
|
||||||
BDirectory& sourceDirectory, FSUtils::Path& relativeSourcePath,
|
const BDirectory& sourceDirectory, FSUtils::Path& relativeSourcePath,
|
||||||
BDirectory& targetDirectory, const char* targetName,
|
const BDirectory& targetDirectory, const char* targetName,
|
||||||
BWritableFileUpdateType updateType)
|
BWritableFileUpdateType updateType)
|
||||||
{
|
{
|
||||||
// * If the file doesn't exist, just copy the extracted one.
|
// * If the file doesn't exist, just copy the extracted one.
|
||||||
@@ -1115,8 +1132,9 @@ private:
|
|||||||
return path.IsEmpty() ? fallback : path;
|
return path.IsEmpty() ? fallback : path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ExtractPackageContent(Package* package, const char* contentPath,
|
void _ExtractPackageContent(Package* package,
|
||||||
BDirectory& targetDirectory, BDirectory& _extractedFilesDirectory)
|
const BStringList& contentPaths, BDirectory& targetDirectory,
|
||||||
|
BDirectory& _extractedFilesDirectory)
|
||||||
{
|
{
|
||||||
// check whether the subdirectory already exists
|
// check whether the subdirectory already exists
|
||||||
BString targetName(package->RevisionedNameThrows());
|
BString targetName(package->RevisionedNameThrows());
|
||||||
@@ -1199,14 +1217,19 @@ private:
|
|||||||
NotOwningEntryRef packageRef(fVolume->fPackagesDirectoryRef,
|
NotOwningEntryRef packageRef(fVolume->fPackagesDirectoryRef,
|
||||||
package->FileName());
|
package->FileName());
|
||||||
|
|
||||||
|
int32 contentPathCount = contentPaths.CountStrings();
|
||||||
|
for (int32 i = 0; i < contentPathCount; i++) {
|
||||||
|
const char* contentPath = contentPaths.StringAt(i);
|
||||||
|
|
||||||
error = FSUtils::ExtractPackageContent(FSUtils::Entry(packageRef),
|
error = FSUtils::ExtractPackageContent(FSUtils::Entry(packageRef),
|
||||||
contentPath, FSUtils::Entry(subDirectory));
|
contentPath, FSUtils::Entry(subDirectory));
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
throw Exception(error,
|
throw Exception(error,
|
||||||
BString().SetToFormat("failed to extract \"%s\" from package",
|
BString().SetToFormat(
|
||||||
contentPath),
|
"failed to extract \"%s\" from package", contentPath),
|
||||||
package->FileName());
|
package->FileName());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// tag all entries with the package attribute
|
// tag all entries with the package attribute
|
||||||
error = _TagPackageEntriesRecursively(subDirectory, targetName, true);
|
error = _TagPackageEntriesRecursively(subDirectory, targetName, true);
|
||||||
|
|||||||
Reference in New Issue
Block a user