From fa50ee854d5e6d59e99144b26498067e2773c468 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 14 Jul 2014 00:46:20 +0200 Subject: [PATCH] package: Add checksum command --- src/bin/package/Jamfile | 1 + src/bin/package/command_checksum.cpp | 162 +++++++++++++++++++++++++++ src/bin/package/package.cpp | 13 +++ src/bin/package/package.h | 1 + src/tools/package/Jamfile | 1 + 5 files changed, 178 insertions(+) create mode 100644 src/bin/package/command_checksum.cpp diff --git a/src/bin/package/Jamfile b/src/bin/package/Jamfile index bc4acc6326..a5454fa168 100644 --- a/src/bin/package/Jamfile +++ b/src/bin/package/Jamfile @@ -4,6 +4,7 @@ UsePrivateHeaders kernel shared storage support ; BinCommand package : command_add.cpp + command_checksum.cpp command_create.cpp command_dump.cpp command_extract.cpp diff --git a/src/bin/package/command_checksum.cpp b/src/bin/package/command_checksum.cpp new file mode 100644 index 0000000000..02ff7c4fe0 --- /dev/null +++ b/src/bin/package/command_checksum.cpp @@ -0,0 +1,162 @@ +/* + * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include "package.h" +#include "PackageWriterListener.h" + + +using BPackageKit::BHPKG::BPackageWriter; +using BPackageKit::BHPKG::BPackageWriterListener; +using BPackageKit::BHPKG::BPackageWriterParameters; + + +struct ChecksumIO : BDataIO { + ChecksumIO() + { + fChecksummer.Init(); + } + + virtual ssize_t Write(const void* buffer, size_t size) + { + if (size > 0) + fChecksummer.Update(buffer, size); + return (ssize_t)size; + } + + BString Digest() + { + const uint8* digest = fChecksummer.Digest(); + BString hex; + size_t length = fChecksummer.DigestLength(); + char* buffer = hex.LockBuffer(length * 2); + if (buffer == NULL) + { + throw std::bad_alloc(); + } + + for (size_t i = 0; i < length; i++) + snprintf(buffer + 2 * i, 3, "%02x", digest[i]); + + hex.UnlockBuffer(); + return hex; + } + +private: + SHA256 fChecksummer; +}; + + +static BPositionIO* +create_stdio(bool isInput) +{ + BFdIO* dataIO = new BFdIO(isInput ? 0 : 1, false); + return new BDataPositionIOWrapper(dataIO); +} + + +int +command_checksum(int argc, const char* const* argv) +{ + bool quiet = false; + bool verbose = false; + + while (true) { + static struct option sLongOptions[] = { + { "help", no_argument, 0, 'h' }, + { "quiet", no_argument, 0, 'q' }, + { "verbose", no_argument, 0, 'v' }, + { 0, 0, 0, 0 } + }; + + opterr = 0; // don't print errors + int c = getopt_long(argc, (char**)argv, "+hqv", + sLongOptions, NULL); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage_and_exit(false); + break; + + case 'q': + quiet = true; + break; + + case 'v': + verbose = true; + break; + + default: + print_usage_and_exit(true); + break; + } + } + + // The optional remaining argument is the package file. + if (argc - optind > 1) + print_usage_and_exit(true); + + const char* packageFileName = optind < argc ? argv[optind++] : NULL; + + // open the input package + status_t error = B_OK; + BPositionIO* inputFile; + if (packageFileName == NULL || strcmp(packageFileName, "-") == 0) { + inputFile = create_stdio(true); + } else { + BFile* inputFileFile = new BFile; + error = inputFileFile->SetTo(packageFileName, O_RDONLY); + if (error != B_OK) { + fprintf(stderr, "Error: Failed to open input file \"%s\": %s\n", + packageFileName, strerror(error)); + return 1; + } + inputFile = inputFileFile; + } + + // write the output package to a BDataIO that computes the checksum + BPackageWriterParameters writerParameters; + writerParameters.SetCompressionLevel(0); + writerParameters.SetCompression( + BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE); + + PackageWriterListener listener(verbose, quiet); + BPackageWriter packageWriter(&listener); + ChecksumIO outputFile; + error = packageWriter.Init(new BDataPositionIOWrapper(&outputFile), true, + &writerParameters); + if (error != B_OK) + return 1; + + error = packageWriter.Recompress(inputFile); + if (error != B_OK) + return 1; + + printf("%s\n", outputFile.Digest().String()); + + return 0; +} diff --git a/src/bin/package/package.cpp b/src/bin/package/package.cpp index 5d8c90d34d..d47b8bca7b 100644 --- a/src/bin/package/package.cpp +++ b/src/bin/package/package.cpp @@ -41,6 +41,16 @@ static const char* kUsage = " -q - Be quiet (don't show any output except for errors).\n" " -v - Be verbose (show more info about created package).\n" "\n" + " checksum [ ] [ ]\n" + " Computes the checksum of package file . If is " + "omitted\n" + " or \"-\", the file is read from stdin. This is only supported, if the " + "package\n" + " is uncompressed.\n" + "\n" + " -q - Be quiet (don't show any output except for errors).\n" + " -v - Be verbose (show more info about created package).\n" + "\n" " create [ ] \n" " Creates package file from contents of current directory.\n" "\n" @@ -134,6 +144,9 @@ main(int argc, const char* const* argv) if (strcmp(command, "add") == 0) return command_add(argc - 1, argv + 1); + if (strcmp(command, "checksum") == 0) + return command_checksum(argc - 1, argv + 1); + if (strcmp(command, "create") == 0) return command_create(argc - 1, argv + 1); diff --git a/src/bin/package/package.h b/src/bin/package/package.h index f15268bc09..93350cd583 100644 --- a/src/bin/package/package.h +++ b/src/bin/package/package.h @@ -9,6 +9,7 @@ void print_usage_and_exit(bool error); int command_add(int argc, const char* const* argv); +int command_checksum(int argc, const char* const* argv); int command_create(int argc, const char* const* argv); int command_dump(int argc, const char* const* argv); int command_extract(int argc, const char* const* argv); diff --git a/src/tools/package/Jamfile b/src/tools/package/Jamfile index 5764329f1f..23d4d0940d 100644 --- a/src/tools/package/Jamfile +++ b/src/tools/package/Jamfile @@ -8,6 +8,7 @@ USES_BE_API on package = true ; BuildPlatformMain package : command_add.cpp + command_checksum.cpp command_create.cpp command_dump.cpp command_extract.cpp