|
|
|
@@ -14,9 +14,14 @@
|
|
|
|
|
#include <Message.h>
|
|
|
|
|
#include <Path.h>
|
|
|
|
|
|
|
|
|
|
#include <AutoDeleter.h>
|
|
|
|
|
|
|
|
|
|
#include <package/hpkg/HPKGDefsPrivate.h>
|
|
|
|
|
#include <package/hpkg/PackageDataReader.h>
|
|
|
|
|
#include <package/hpkg/PackageEntry.h>
|
|
|
|
|
#include <package/hpkg/PackageInfoAttributeValue.h>
|
|
|
|
|
#include <package/hpkg/PackageReader.h>
|
|
|
|
|
#include <package/BlockBufferCacheNoLock.h>
|
|
|
|
|
#include <package/ChecksumAccessors.h>
|
|
|
|
|
#include <package/RepositoryInfo.h>
|
|
|
|
|
|
|
|
|
@@ -31,12 +36,230 @@ namespace BPrivate {
|
|
|
|
|
using BPackageKit::BPrivate::GeneralFileChecksumAccessor;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct PackageEntryDataFetcher {
|
|
|
|
|
PackageEntryDataFetcher(BErrorOutput* errorOutput,
|
|
|
|
|
BPackageData& packageData)
|
|
|
|
|
:
|
|
|
|
|
fErrorOutput(errorOutput),
|
|
|
|
|
fBufferCache(B_HPKG_DEFAULT_DATA_CHUNK_SIZE_ZLIB, 2),
|
|
|
|
|
fPackageData(packageData)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status_t ReadIntoString(BDataReader* dataReader, BString& _contents)
|
|
|
|
|
{
|
|
|
|
|
// create a BPackageDataReader
|
|
|
|
|
BPackageDataReader* reader;
|
|
|
|
|
status_t result = BPackageDataReaderFactory(&fBufferCache)
|
|
|
|
|
.CreatePackageDataReader(dataReader, fPackageData, reader);
|
|
|
|
|
if (result != B_OK)
|
|
|
|
|
return result;
|
|
|
|
|
ObjectDeleter<BPackageDataReader> readerDeleter(reader);
|
|
|
|
|
|
|
|
|
|
// copy data into the given string
|
|
|
|
|
int32 bufferSize = fPackageData.UncompressedSize();
|
|
|
|
|
char* buffer = _contents.LockBuffer(bufferSize);
|
|
|
|
|
if (buffer == NULL)
|
|
|
|
|
return B_NO_MEMORY;
|
|
|
|
|
|
|
|
|
|
result = reader->ReadData(0, buffer, bufferSize);
|
|
|
|
|
if (result != B_OK) {
|
|
|
|
|
fErrorOutput->PrintError("Error: Failed to read data: %s\n",
|
|
|
|
|
strerror(result));
|
|
|
|
|
_contents.UnlockBuffer(0);
|
|
|
|
|
} else
|
|
|
|
|
_contents.UnlockBuffer(bufferSize);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
BErrorOutput* fErrorOutput;
|
|
|
|
|
BBlockBufferCacheNoLock fBufferCache;
|
|
|
|
|
BPackageData& fPackageData;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct PackageContentHandler : public BPackageContentHandler {
|
|
|
|
|
PackageContentHandler(BErrorOutput* errorOutput, BPackageInfo* packageInfo,
|
|
|
|
|
int packageFileFD, BRepositoryInfo* repositoryInfo)
|
|
|
|
|
:
|
|
|
|
|
fErrorOutput(errorOutput),
|
|
|
|
|
fPackageInfo(packageInfo),
|
|
|
|
|
fPackageFileReader(packageFileFD),
|
|
|
|
|
fRepositoryInfo(repositoryInfo)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual status_t HandleEntry(BPackageEntry* entry)
|
|
|
|
|
{
|
|
|
|
|
// if license must be approved, read any license files from package such
|
|
|
|
|
// that those can be stored in the repository later
|
|
|
|
|
if ((fPackageInfo->Flags() & B_PACKAGE_FLAG_APPROVE_LICENSE) == 0
|
|
|
|
|
|| entry == NULL)
|
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
|
|
// return if not in ./data/licenses folder
|
|
|
|
|
const BPackageEntry* parent = entry->Parent();
|
|
|
|
|
BString licenseFolderName("licenses");
|
|
|
|
|
if (parent == NULL || licenseFolderName != parent->Name())
|
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
|
|
parent = parent->Parent();
|
|
|
|
|
BString dataFolderName("data");
|
|
|
|
|
if (parent == NULL || dataFolderName != parent->Name())
|
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
|
|
if (parent->Parent() != NULL)
|
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
|
|
// check if license already is in repository
|
|
|
|
|
const BObjectList<BString>& licenseNames
|
|
|
|
|
= fRepositoryInfo->LicenseNames();
|
|
|
|
|
for (int i = 0; i < licenseNames.CountItems(); ++i) {
|
|
|
|
|
if (licenseNames.ItemAt(i)->ICompare(entry->Name()) == 0) {
|
|
|
|
|
// license already exists
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// fetch contents of license file
|
|
|
|
|
BPackageData& packageData = entry->Data();
|
|
|
|
|
PackageEntryDataFetcher dataFetcher(fErrorOutput, packageData);
|
|
|
|
|
|
|
|
|
|
BString licenseText;
|
|
|
|
|
status_t result;
|
|
|
|
|
if (packageData.IsEncodedInline()) {
|
|
|
|
|
BBufferDataReader dataReader(packageData.InlineData(),
|
|
|
|
|
packageData.CompressedSize());
|
|
|
|
|
result = dataFetcher.ReadIntoString(&dataReader, licenseText);
|
|
|
|
|
} else {
|
|
|
|
|
result
|
|
|
|
|
= dataFetcher.ReadIntoString(&fPackageFileReader, licenseText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result != B_OK)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
// add license to repository
|
|
|
|
|
return fRepositoryInfo->AddLicense(entry->Name(), licenseText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
|
|
|
|
|
BPackageEntryAttribute* attribute)
|
|
|
|
|
{
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual status_t HandleEntryDone(BPackageEntry* entry)
|
|
|
|
|
{
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual status_t HandlePackageAttribute(
|
|
|
|
|
const BPackageInfoAttributeValue& value)
|
|
|
|
|
{
|
|
|
|
|
switch (value.attributeID) {
|
|
|
|
|
case B_PACKAGE_INFO_NAME:
|
|
|
|
|
fPackageInfo->SetName(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_SUMMARY:
|
|
|
|
|
fPackageInfo->SetSummary(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_DESCRIPTION:
|
|
|
|
|
fPackageInfo->SetDescription(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_VENDOR:
|
|
|
|
|
fPackageInfo->SetVendor(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_PACKAGER:
|
|
|
|
|
fPackageInfo->SetPackager(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_FLAGS:
|
|
|
|
|
fPackageInfo->SetFlags(value.unsignedInt);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_ARCHITECTURE:
|
|
|
|
|
fPackageInfo->SetArchitecture(
|
|
|
|
|
(BPackageArchitecture)value.unsignedInt);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_VERSION:
|
|
|
|
|
fPackageInfo->SetVersion(value.version);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_COPYRIGHTS:
|
|
|
|
|
fPackageInfo->AddCopyright(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_LICENSES:
|
|
|
|
|
fPackageInfo->AddLicense(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_PROVIDES:
|
|
|
|
|
fPackageInfo->AddProvides(value.resolvable);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_REQUIRES:
|
|
|
|
|
fPackageInfo->AddRequires(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_SUPPLEMENTS:
|
|
|
|
|
fPackageInfo->AddSupplements(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_CONFLICTS:
|
|
|
|
|
fPackageInfo->AddConflicts(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_FRESHENS:
|
|
|
|
|
fPackageInfo->AddFreshens(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_REPLACES:
|
|
|
|
|
fPackageInfo->AddReplaces(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
fErrorOutput->PrintError(
|
|
|
|
|
"Invalid package attribute section: unexpected package "
|
|
|
|
|
"attribute id %d encountered\n", value.attributeID);
|
|
|
|
|
return B_BAD_DATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void HandleErrorOccurred()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
BErrorOutput* fErrorOutput;
|
|
|
|
|
BPackageInfo* fPackageInfo;
|
|
|
|
|
BPackageReader* fPackageReader;
|
|
|
|
|
BFDDataReader fPackageFileReader;
|
|
|
|
|
BRepositoryInfo* fRepositoryInfo;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct RepositoryWriterImpl::PackageNameSet : public std::set<BString> {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RepositoryWriterImpl::RepositoryWriterImpl(BRepositoryWriterListener* listener,
|
|
|
|
|
const BRepositoryInfo* repositoryInfo)
|
|
|
|
|
BRepositoryInfo* repositoryInfo)
|
|
|
|
|
:
|
|
|
|
|
inherited(listener),
|
|
|
|
|
fListener(listener),
|
|
|
|
@@ -96,125 +319,6 @@ RepositoryWriterImpl::Finish()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
RepositoryWriterImpl::HandleEntry(BPackageEntry* entry)
|
|
|
|
|
{
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
RepositoryWriterImpl::HandleEntryAttribute(BPackageEntry* entry,
|
|
|
|
|
BPackageEntryAttribute* attribute)
|
|
|
|
|
{
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
RepositoryWriterImpl::HandleEntryDone(BPackageEntry* entry)
|
|
|
|
|
{
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
RepositoryWriterImpl::HandlePackageAttribute(
|
|
|
|
|
const BPackageInfoAttributeValue& value)
|
|
|
|
|
{
|
|
|
|
|
switch (value.attributeID) {
|
|
|
|
|
case B_PACKAGE_INFO_NAME:
|
|
|
|
|
fPackageInfo.SetName(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_SUMMARY:
|
|
|
|
|
fPackageInfo.SetSummary(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_DESCRIPTION:
|
|
|
|
|
fPackageInfo.SetDescription(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_VENDOR:
|
|
|
|
|
fPackageInfo.SetVendor(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_PACKAGER:
|
|
|
|
|
fPackageInfo.SetPackager(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_FLAGS:
|
|
|
|
|
fPackageInfo.SetFlags(value.unsignedInt);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_ARCHITECTURE:
|
|
|
|
|
fPackageInfo.SetArchitecture(
|
|
|
|
|
(BPackageArchitecture)value.unsignedInt);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_VERSION:
|
|
|
|
|
fPackageInfo.SetVersion(value.version);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_COPYRIGHTS:
|
|
|
|
|
fPackageInfo.AddCopyright(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_LICENSES:
|
|
|
|
|
fPackageInfo.AddLicense(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_PROVIDES:
|
|
|
|
|
fPackageInfo.AddProvides(value.resolvable);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_REQUIRES:
|
|
|
|
|
fPackageInfo.AddRequires(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_SUPPLEMENTS:
|
|
|
|
|
fPackageInfo.AddSupplements(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_CONFLICTS:
|
|
|
|
|
fPackageInfo.AddConflicts(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_FRESHENS:
|
|
|
|
|
fPackageInfo.AddFreshens(value.resolvableExpression);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case B_PACKAGE_INFO_REPLACES:
|
|
|
|
|
fPackageInfo.AddReplaces(value.string);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
fListener->PrintError(
|
|
|
|
|
"Invalid package attribute section: unexpected package "
|
|
|
|
|
"attribute id %d encountered\n", value.attributeID);
|
|
|
|
|
return B_BAD_DATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
RepositoryWriterImpl::HandlePackageAttributesDone()
|
|
|
|
|
{
|
|
|
|
|
status_t result = _RegisterCurrentPackageInfo();
|
|
|
|
|
fPackageInfo.Clear();
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
RepositoryWriterImpl::HandleErrorOccurred()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
|
RepositoryWriterImpl::_Init(const char* fileName)
|
|
|
|
|
{
|
|
|
|
@@ -239,7 +343,8 @@ RepositoryWriterImpl::_Finish()
|
|
|
|
|
sizeof(header) + infoLengthCompressed, packagesLengthCompressed);
|
|
|
|
|
|
|
|
|
|
fListener->OnRepositoryDone(sizeof(header), infoLengthCompressed,
|
|
|
|
|
fPackageCount, packagesLengthCompressed, totalSize);
|
|
|
|
|
fRepositoryInfo->LicenseNames().CountItems(), fPackageCount,
|
|
|
|
|
packagesLengthCompressed, totalSize);
|
|
|
|
|
|
|
|
|
|
// general
|
|
|
|
|
header.magic = B_HOST_TO_BENDIAN_INT32(B_HPKG_REPO_MAGIC);
|
|
|
|
@@ -278,6 +383,13 @@ RepositoryWriterImpl::_AddPackage(const BEntry& packageEntry)
|
|
|
|
|
|
|
|
|
|
fPackageInfo.Clear();
|
|
|
|
|
|
|
|
|
|
// parse package
|
|
|
|
|
PackageContentHandler contentHandler(fListener, &fPackageInfo,
|
|
|
|
|
packageReader.PackageFileFD(), fRepositoryInfo);
|
|
|
|
|
if ((result = packageReader.ParseContent(&contentHandler)) != B_OK)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
// determine package's checksum
|
|
|
|
|
GeneralFileChecksumAccessor checksumAccessor(packageEntry);
|
|
|
|
|
BString checksum;
|
|
|
|
|
if ((result = checksumAccessor.GetChecksum(checksum)) != B_OK) {
|
|
|
|
@@ -286,9 +398,11 @@ RepositoryWriterImpl::_AddPackage(const BEntry& packageEntry)
|
|
|
|
|
}
|
|
|
|
|
fPackageInfo.SetChecksum(checksum);
|
|
|
|
|
|
|
|
|
|
// register package's attributes
|
|
|
|
|
if ((result = _RegisterCurrentPackageInfo()) != B_OK)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return packageReader.ParseContent(this);
|
|
|
|
|
return B_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|