* implemented checking of licenses, such that it is no longer possible

to create a package that refers to a license that is not a system
  license or contained in the package
* added package-info flags (currently only approve_license and 
  system_package)
* adjusted package-reader/writer and pkgman accordingly

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40393 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe 2011-02-08 19:50:36 +00:00
parent 1b4f0abf9d
commit d77c6cd26a
13 changed files with 207 additions and 51 deletions

View File

@ -0,0 +1,23 @@
/*
* Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _PACKAGE__PACKAGE_FLAGS_H_
#define _PACKAGE__PACKAGE_FLAGS_H_
namespace BPackageKit {
enum {
B_PACKAGE_FLAG_APPROVE_LICENSE = 1ul << 0,
// will trigger display and approval of license before installation
B_PACKAGE_FLAG_SYSTEM_PACKAGE = 1ul << 1,
// marks package as system package (i.e. belonging into /boot/system)
};
} // namespace BPackageKit
#endif // _PACKAGE__PACKAGE_FLAGS_H_

View File

@ -10,6 +10,7 @@
#include <String.h>
#include <package/PackageArchitecture.h>
#include <package/PackageFlags.h>
#include <package/PackageInfoAttributes.h>
#include <package/PackageResolvable.h>
#include <package/PackageResolvableExpression.h>
@ -55,6 +56,8 @@ public:
const BString& Vendor() const;
const BString& Packager() const;
uint32 Flags() const;
BPackageArchitecture Architecture() const;
const BPackageVersion& Version() const;
@ -79,6 +82,8 @@ public:
void SetVendor(const BString& vendor);
void SetPackager(const BString& packager);
void SetFlags(uint32 flags);
void SetArchitecture(
BPackageArchitecture architecture);
@ -128,6 +133,8 @@ private:
BString fVendor;
BString fPackager;
uint32 fFlags;
BPackageArchitecture fArchitecture;
BPackageVersion fVersion;

View File

@ -33,6 +33,7 @@ enum BPackageInfoAttributeIndex {
// contains a patch for
B_PACKAGE_INFO_REPLACES, // list of resolvables that this package
// will replace (upon update)
B_PACKAGE_INFO_FLAGS,
//
B_PACKAGE_INFO_ENUM_COUNT,
};

View File

@ -34,8 +34,7 @@ public:
uint64 uncompressedStringsSize,
uint64 uncompressedMainSize,
uint64 uncompressedTOCSize) = 0;
virtual void OnPackageAttributesSizeInfo(
uint32 stringCount,
virtual void OnPackageAttributesSizeInfo(uint32 stringCount,
uint32 uncompressedSize) = 0;
virtual void OnPackageSizeInfo(uint32 headerSize,
uint64 heapSize, uint64 tocSize,

View File

@ -61,6 +61,8 @@ private:
const char* name, size_t nameLength,
bool isImplicit);
status_t _CheckLicenses();
void _WriteTOC(hpkg_header& header);
int32 _WriteTOCSections(uint64& _attributeTypesSize,
uint64& _stringsSize, uint64& _mainSize);
@ -114,6 +116,8 @@ private:
StringCache fStringCache;
AttributeTypeTable* fAttributeTypes;
BPackageInfo fPackageInfo;
};

View File

@ -129,6 +129,7 @@ enum HPKGPackageAttributeID {
HPKG_PACKAGE_ATTRIBUTE_DESCRIPTION,
HPKG_PACKAGE_ATTRIBUTE_VENDOR,
HPKG_PACKAGE_ATTRIBUTE_PACKAGER,
HPKG_PACKAGE_ATTRIBUTE_FLAGS,
HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE,
HPKG_PACKAGE_ATTRIBUTE_VERSION_MAJOR,
HPKG_PACKAGE_ATTRIBUTE_VERSION_MINOR,

View File

@ -1,5 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
@ -52,7 +53,7 @@ public:
if (fQuiet || !fVerbose)
return;
printf("----- TOC Info -----\n");
printf("----- TOC Info -----------------------------------\n");
printf("attribute types size: %10llu (uncompressed)\n",
uncompressedAttributeTypesSize);
printf("cached strings size: %10llu (uncompressed)\n",
@ -69,9 +70,9 @@ public:
if (fQuiet || !fVerbose)
return;
printf("----- Package Attribute Info -----\n");
printf("string count: %10ld\n", stringCount);
printf("package attributes size: %10ld (uncompressed)\n",
printf("----- Package Attribute Info ---------------------\n");
printf("string count: %10lu\n", stringCount);
printf("package attributes size: %10lu (uncompressed)\n",
uncompressedSize);
}
@ -81,12 +82,12 @@ public:
if (fQuiet)
return;
printf("----- Package Info -----\n");
printf("----- Package Info ----------------\n");
printf("header size: %10lu\n", headerSize);
printf("heap size: %10lld\n", heapSize);
printf("TOC size: %10lld\n", tocSize);
printf("package attributes size: %10ld\n", packageAttributesSize);
printf("total size: %10lld\n", totalSize);
printf("heap size: %10llu\n", heapSize);
printf("TOC size: %10llu\n", tocSize);
printf("package attributes size: %10lu\n", packageAttributesSize);
printf("total size: %10llu\n", totalSize);
}
@ -139,14 +140,11 @@ command_create(int argc, const char* const* argv)
}
}
// The remaining arguments are the package file and the list of files to
// include, i.e. at least two more arguments.
if (optind + 2 > argc)
// The remaining arguments is the package file, i.e. one more argument.
if (optind + 1 != argc)
print_usage_and_exit(true);
const char* packageFileName = argv[optind++];
const char* const* fileNames = argv + optind;
int fileNameCount = argc - optind;
// create package
PackageWriterListener listener(verbose, quiet);
@ -164,32 +162,22 @@ command_create(int argc, const char* const* argv)
}
}
// add files
for (int i = 0; i < fileNameCount; i++) {
if (strcmp(fileNames[i], ".") == 0) {
DIR* dir = opendir(".");
if (dir == NULL) {
listener.PrintError("Error: Failed to opendir '.': %s\n",
strerror(errno));
return 1;
}
while (dirent* entry = readdir(dir)) {
if (strcmp(entry->d_name, ".") == 0
|| strcmp(entry->d_name, "..") == 0)
continue;
result = packageWriter.AddEntry(entry->d_name);
if (result != B_OK)
return 1;
}
closedir(dir);
} else {
result = packageWriter.AddEntry(fileNames[i]);
if (result != B_OK)
return 1;
}
// add all files of current directory
DIR* dir = opendir(".");
if (dir == NULL) {
listener.PrintError("Error: Failed to opendir '.': %s\n",
strerror(errno));
return 1;
}
while (dirent* entry = readdir(dir)) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
result = packageWriter.AddEntry(entry->d_name);
if (result != B_OK)
return 1;
}
closedir(dir);
// write the package
result = packageWriter.Finish();

View File

@ -133,6 +133,16 @@ struct PackageContentListHandler : BPackageContentHandler {
printf("\tpackager: %s\n", value.string);
break;
case B_PACKAGE_INFO_FLAGS:
if (value.unsignedInt == 0)
break;
printf("\tflags:\n");
if ((value.unsignedInt & B_PACKAGE_FLAG_APPROVE_LICENSE) != 0)
printf("\t\tapprove_license\n");
if ((value.unsignedInt & B_PACKAGE_FLAG_SYSTEM_PACKAGE) != 0)
printf("\t\tsystem_package\n");
break;
case B_PACKAGE_INFO_ARCHITECTURE:
printf("\tarchitecure: %s\n",
BPackageInfo::kArchitectureNames[value.unsignedInt]);

View File

@ -1,5 +1,6 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
@ -24,11 +25,10 @@ static const char* kUsage =
"Creates, inspects, or extracts a Haiku package.\n"
"\n"
"Commands:\n"
" create [ <options> ] <package> <file> ...\n"
" Creates package file <package> from a list of files.\n"
" create [ <options> ] <package>\n"
" Creates package file <package> from contents of current directory.\n"
"\n"
" -C <dir> - Change to directory <dir> before interpreting the file\n"
" names <file>.\n"
" -C <dir> - Change to directory <dir> before starting.\n"
"\n"
" dump [ <options> ] <package>\n"
" Dumps the TOC section of package file <package>. For debugging only.\n"

View File

@ -72,6 +72,7 @@ private:
void _RewindTo(const Token& token);
void _ParseStringValue(BString* value);
uint32 _ParseFlags();
void _ParseArchitectureValue(
BPackageArchitecture* value);
void _ParseVersionValue(BPackageVersion* value,
@ -416,6 +417,45 @@ BPackageInfo::Parser::_ParseStringList(BObjectList<BString>* value, bool
}
uint32
BPackageInfo::Parser::_ParseFlags()
{
uint32 flags = 0;
Token openBracket = _NextToken();
if (openBracket.type != TOKEN_OPEN_BRACKET)
throw ParseError("expected start of list ('[')", openBracket.pos);
bool needComma = false;
while (true) {
Token token = _NextToken();
if (token.type == TOKEN_CLOSE_BRACKET)
break;
if (needComma) {
if (token.type != TOKEN_COMMA)
throw ParseError("expected comma", token.pos);
token = _NextToken();
} else
needComma = true;
if (token.type != TOKEN_WORD)
throw ParseError("expected word (a flag)", token.pos);
if (token.text.ICompare("approve_license") == 0)
flags |= B_PACKAGE_FLAG_APPROVE_LICENSE;
else if (token.text.ICompare("system_package") == 0)
flags |= B_PACKAGE_FLAG_SYSTEM_PACKAGE;
else {
throw ParseError("expected 'approve_license' or 'system_package'",
token.pos);
}
}
return flags;
}
void
BPackageInfo::Parser::_ParseResolvableList(
BObjectList<BPackageResolvable>* value)
@ -729,6 +769,16 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
for (int i = 0; i < count; ++i)
packageInfo->AddReplaces(*(replacesList.ItemAt(i)));
seen[B_PACKAGE_INFO_REPLACES] = true;
} else if (t.text.ICompare(names[B_PACKAGE_INFO_FLAGS])
== 0) {
if (seen[B_PACKAGE_INFO_FLAGS]) {
BString error = BString(names[B_PACKAGE_INFO_FLAGS])
<< " already seen!";
throw ParseError(error, t.pos);
}
packageInfo->SetFlags(_ParseFlags());
seen[B_PACKAGE_INFO_FLAGS] = true;
}
}
@ -758,6 +808,7 @@ const char* BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = {
"conflicts",
"freshens",
"replaces",
"flags",
};
@ -771,6 +822,7 @@ BPackageInfo::kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = {
BPackageInfo::BPackageInfo()
:
fFlags(0),
fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
fCopyrightList(5, true),
fLicenseList(5, true),
@ -884,6 +936,13 @@ BPackageInfo::Packager() const
}
uint32
BPackageInfo::Flags() const
{
return fFlags;
}
BPackageArchitecture
BPackageInfo::Architecture() const
{
@ -996,6 +1055,13 @@ BPackageInfo::SetVersion(const BPackageVersion& version)
}
void
BPackageInfo::SetFlags(uint32 flags)
{
fFlags = flags;
}
void
BPackageInfo::SetArchitecture(BPackageArchitecture architecture)
{

View File

@ -1162,6 +1162,11 @@ PackageReaderImpl::_ParsePackageAttributes(AttributeHandlerContext* context)
attributeValue.string);
break;
case HPKG_PACKAGE_ATTRIBUTE_FLAGS:
handlerValue.SetTo(B_PACKAGE_INFO_FLAGS,
(uint32)attributeValue.unsignedInt);
break;
case HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE:
if (attributeValue.unsignedInt
>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {

View File

@ -20,8 +20,11 @@
#include <new>
#include <ByteOrder.h>
#include <Directory.h>
#include <Entry.h>
#include <FindDirectory.h>
#include <fs_attr.h>
#include <Path.h>
#include <AutoDeleter.h>
@ -350,12 +353,11 @@ PackageWriterImpl::AddEntry(const char* fileName)
BPackageWriterListener* listener;
} errorListener(fListener);
BEntry packageInfoEntry(fileName);
BPackageInfo packageInfo;
status_t result = packageInfo.ReadFromConfigFile(packageInfoEntry,
status_t result = fPackageInfo.ReadFromConfigFile(packageInfoEntry,
&errorListener);
if (result != B_OK || (result = packageInfo.InitCheck()) != B_OK)
if (result != B_OK || (result = fPackageInfo.InitCheck()) != B_OK)
return result;
RegisterPackageInfo(PackageAttributes(), packageInfo);
RegisterPackageInfo(PackageAttributes(), fPackageInfo);
}
return _RegisterEntry(fileName);
@ -372,11 +374,16 @@ status_t
PackageWriterImpl::Finish()
{
try {
if (PackageAttributes().IsEmpty()) {
if (fPackageInfo.InitCheck() != B_OK) {
fListener->PrintError("No package-info file found (%s)!\n",
B_HPKG_PACKAGE_INFO_FILE_NAME);
return B_BAD_DATA;
}
status_t result = _CheckLicenses();
if (result != B_OK)
return result;
return _Finish();
} catch (status_t error) {
return error;
@ -418,6 +425,44 @@ PackageWriterImpl::_Init(const char* fileName)
}
status_t
PackageWriterImpl::_CheckLicenses()
{
BPath systemLicensePath;
status_t result
= find_directory(B_SYSTEM_DATA_DIRECTORY, &systemLicensePath);
if (result != B_OK) {
fListener->PrintError("unable to find system data path!\n");
return result;
}
if ((result = systemLicensePath.Append("licenses")) != B_OK) {
fListener->PrintError("unable to append to system data path!\n");
return result;
}
BDirectory systemLicenseDir(systemLicensePath.Path());
BDirectory packageLicenseDir("./data/licenses");
const BObjectList<BString>& licenseList = fPackageInfo.LicenseList();
for (int i = 0; i < licenseList.CountItems(); ++i) {
const BString& licenseName = *licenseList.ItemAt(i);
BEntry license;
if (systemLicenseDir.FindEntry(licenseName.String(), &license) == B_OK)
continue;
// license is not a system license, so it must be contained in package
if (packageLicenseDir.FindEntry(licenseName.String(),
&license) != B_OK) {
fListener->PrintError("License '%s' isn't contained in package!\n",
licenseName.String());
return B_BAD_DATA;
}
}
return B_OK;
}
status_t
PackageWriterImpl::_Finish()
{

View File

@ -391,12 +391,19 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
packager->string = fPackageStringCache.Get(packageInfo.Packager().String());
attributeList.Add(packager);
// flags
PackageAttribute* flags = new PackageAttribute(
HPKG_PACKAGE_ATTRIBUTE_FLAGS, B_HPKG_ATTRIBUTE_TYPE_UINT,
B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT);
flags->unsignedInt = packageInfo.Flags();
attributeList.Add(flags);
// architecture
PackageAttribute* architecture = new PackageAttribute(
HPKG_PACKAGE_ATTRIBUTE_ARCHITECTURE, B_HPKG_ATTRIBUTE_TYPE_UINT,
B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT);
architecture->unsignedInt = packageInfo.Architecture();
attributeList.Add(packager);
attributeList.Add(architecture);
// version
RegisterPackageVersion(attributeList, packageInfo.Version());