Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / bin / package / command_checksum.cpp
blob02ff7c4fe0d2a0171655b89a0cc0bf60d8d83457
1 /*
2 * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <getopt.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
15 #include <new>
17 #include <File.h>
18 #include <String.h>
20 #include <package/hpkg/HPKGDefs.h>
21 #include <package/hpkg/PackageWriter.h>
23 #include <DataPositionIOWrapper.h>
24 #include <FdIO.h>
25 #include <SHA256.h>
27 #include "package.h"
28 #include "PackageWriterListener.h"
31 using BPackageKit::BHPKG::BPackageWriter;
32 using BPackageKit::BHPKG::BPackageWriterListener;
33 using BPackageKit::BHPKG::BPackageWriterParameters;
36 struct ChecksumIO : BDataIO {
37 ChecksumIO()
39 fChecksummer.Init();
42 virtual ssize_t Write(const void* buffer, size_t size)
44 if (size > 0)
45 fChecksummer.Update(buffer, size);
46 return (ssize_t)size;
49 BString Digest()
51 const uint8* digest = fChecksummer.Digest();
52 BString hex;
53 size_t length = fChecksummer.DigestLength();
54 char* buffer = hex.LockBuffer(length * 2);
55 if (buffer == NULL)
57 throw std::bad_alloc();
60 for (size_t i = 0; i < length; i++)
61 snprintf(buffer + 2 * i, 3, "%02x", digest[i]);
63 hex.UnlockBuffer();
64 return hex;
67 private:
68 SHA256 fChecksummer;
72 static BPositionIO*
73 create_stdio(bool isInput)
75 BFdIO* dataIO = new BFdIO(isInput ? 0 : 1, false);
76 return new BDataPositionIOWrapper(dataIO);
80 int
81 command_checksum(int argc, const char* const* argv)
83 bool quiet = false;
84 bool verbose = false;
86 while (true) {
87 static struct option sLongOptions[] = {
88 { "help", no_argument, 0, 'h' },
89 { "quiet", no_argument, 0, 'q' },
90 { "verbose", no_argument, 0, 'v' },
91 { 0, 0, 0, 0 }
94 opterr = 0; // don't print errors
95 int c = getopt_long(argc, (char**)argv, "+hqv",
96 sLongOptions, NULL);
97 if (c == -1)
98 break;
100 switch (c) {
101 case 'h':
102 print_usage_and_exit(false);
103 break;
105 case 'q':
106 quiet = true;
107 break;
109 case 'v':
110 verbose = true;
111 break;
113 default:
114 print_usage_and_exit(true);
115 break;
119 // The optional remaining argument is the package file.
120 if (argc - optind > 1)
121 print_usage_and_exit(true);
123 const char* packageFileName = optind < argc ? argv[optind++] : NULL;
125 // open the input package
126 status_t error = B_OK;
127 BPositionIO* inputFile;
128 if (packageFileName == NULL || strcmp(packageFileName, "-") == 0) {
129 inputFile = create_stdio(true);
130 } else {
131 BFile* inputFileFile = new BFile;
132 error = inputFileFile->SetTo(packageFileName, O_RDONLY);
133 if (error != B_OK) {
134 fprintf(stderr, "Error: Failed to open input file \"%s\": %s\n",
135 packageFileName, strerror(error));
136 return 1;
138 inputFile = inputFileFile;
141 // write the output package to a BDataIO that computes the checksum
142 BPackageWriterParameters writerParameters;
143 writerParameters.SetCompressionLevel(0);
144 writerParameters.SetCompression(
145 BPackageKit::BHPKG::B_HPKG_COMPRESSION_NONE);
147 PackageWriterListener listener(verbose, quiet);
148 BPackageWriter packageWriter(&listener);
149 ChecksumIO outputFile;
150 error = packageWriter.Init(new BDataPositionIOWrapper(&outputFile), true,
151 &writerParameters);
152 if (error != B_OK)
153 return 1;
155 error = packageWriter.Recompress(inputFile);
156 if (error != B_OK)
157 return 1;
159 printf("%s\n", outputFile.Digest().String());
161 return 0;