From d77c6cd26a5cf3863ba4258a063d7d8645abf1e3 Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Tue, 8 Feb 2011 19:50:36 +0000 Subject: [PATCH] * 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 --- headers/os/package/PackageFlags.h | 23 +++++++ headers/os/package/PackageInfo.h | 7 ++ headers/os/package/PackageInfoAttributes.h | 1 + headers/os/package/hpkg/PackageWriter.h | 3 +- .../private/package/hpkg/PackageWriterImpl.h | 4 ++ headers/private/package/hpkg/haiku_package.h | 1 + src/bin/package/command_create.cpp | 66 ++++++++----------- src/bin/package/command_list.cpp | 10 +++ src/bin/package/package.cpp | 8 +-- src/kits/package/PackageInfo.cpp | 66 +++++++++++++++++++ src/kits/package/hpkg/PackageReaderImpl.cpp | 5 ++ src/kits/package/hpkg/PackageWriterImpl.cpp | 55 ++++++++++++++-- src/kits/package/hpkg/WriterImplBase.cpp | 9 ++- 13 files changed, 207 insertions(+), 51 deletions(-) create mode 100644 headers/os/package/PackageFlags.h diff --git a/headers/os/package/PackageFlags.h b/headers/os/package/PackageFlags.h new file mode 100644 index 0000000000..9c3720dfb3 --- /dev/null +++ b/headers/os/package/PackageFlags.h @@ -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_ diff --git a/headers/os/package/PackageInfo.h b/headers/os/package/PackageInfo.h index b8be176324..67fa376acd 100644 --- a/headers/os/package/PackageInfo.h +++ b/headers/os/package/PackageInfo.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -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; diff --git a/headers/os/package/PackageInfoAttributes.h b/headers/os/package/PackageInfoAttributes.h index 7e1818df49..3128414ecd 100644 --- a/headers/os/package/PackageInfoAttributes.h +++ b/headers/os/package/PackageInfoAttributes.h @@ -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, }; diff --git a/headers/os/package/hpkg/PackageWriter.h b/headers/os/package/hpkg/PackageWriter.h index 22e60d8d24..51eb7d103d 100644 --- a/headers/os/package/hpkg/PackageWriter.h +++ b/headers/os/package/hpkg/PackageWriter.h @@ -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, diff --git a/headers/private/package/hpkg/PackageWriterImpl.h b/headers/private/package/hpkg/PackageWriterImpl.h index fe251536aa..525d87881f 100644 --- a/headers/private/package/hpkg/PackageWriterImpl.h +++ b/headers/private/package/hpkg/PackageWriterImpl.h @@ -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; }; diff --git a/headers/private/package/hpkg/haiku_package.h b/headers/private/package/hpkg/haiku_package.h index 5479b8ffa3..92eb37e663 100644 --- a/headers/private/package/hpkg/haiku_package.h +++ b/headers/private/package/hpkg/haiku_package.h @@ -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, diff --git a/src/bin/package/command_create.cpp b/src/bin/package/command_create.cpp index f37ebf9351..1d1d4deb97 100644 --- a/src/bin/package/command_create.cpp +++ b/src/bin/package/command_create.cpp @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2011, Oliver Tappe * 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(); diff --git a/src/bin/package/command_list.cpp b/src/bin/package/command_list.cpp index 5e00208564..ac6a081503 100644 --- a/src/bin/package/command_list.cpp +++ b/src/bin/package/command_list.cpp @@ -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]); diff --git a/src/bin/package/package.cpp b/src/bin/package/package.cpp index c8e9602d38..ce3fe5e3f0 100644 --- a/src/bin/package/package.cpp +++ b/src/bin/package/package.cpp @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2011, Oliver Tappe * 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 [ ] ...\n" - " Creates package file from a list of files.\n" + " create [ ] \n" + " Creates package file from contents of current directory.\n" "\n" - " -C - Change to directory before interpreting the file\n" - " names .\n" + " -C - Change to directory before starting.\n" "\n" " dump [ ] \n" " Dumps the TOC section of package file . For debugging only.\n" diff --git a/src/kits/package/PackageInfo.cpp b/src/kits/package/PackageInfo.cpp index 9ac6a5a35b..a4236c3c4b 100644 --- a/src/kits/package/PackageInfo.cpp +++ b/src/kits/package/PackageInfo.cpp @@ -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* 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* 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) { diff --git a/src/kits/package/hpkg/PackageReaderImpl.cpp b/src/kits/package/hpkg/PackageReaderImpl.cpp index c16bb0c1f3..54bcfaa0a3 100644 --- a/src/kits/package/hpkg/PackageReaderImpl.cpp +++ b/src/kits/package/hpkg/PackageReaderImpl.cpp @@ -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) { diff --git a/src/kits/package/hpkg/PackageWriterImpl.cpp b/src/kits/package/hpkg/PackageWriterImpl.cpp index 2f4520f8f5..c09d43c822 100644 --- a/src/kits/package/hpkg/PackageWriterImpl.cpp +++ b/src/kits/package/hpkg/PackageWriterImpl.cpp @@ -20,8 +20,11 @@ #include #include +#include #include +#include #include +#include #include @@ -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& 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() { diff --git a/src/kits/package/hpkg/WriterImplBase.cpp b/src/kits/package/hpkg/WriterImplBase.cpp index 30854563b8..b1e6bf4a2a 100644 --- a/src/kits/package/hpkg/WriterImplBase.cpp +++ b/src/kits/package/hpkg/WriterImplBase.cpp @@ -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());