Serenity Operating System
at master 92 lines 3.3 kB view raw
1/* 2 * Copyright (c) 2021, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibCore/ArgsParser.h> 8#include <LibCore/File.h> 9#include <LibCore/System.h> 10#include <LibCrypto/Checksum/Adler32.h> 11#include <LibCrypto/Checksum/CRC32.h> 12#include <LibMain/Main.h> 13#include <string.h> 14 15ErrorOr<int> serenity_main(Main::Arguments arguments) 16{ 17 Vector<DeprecatedString> paths; 18 StringView opt_algorithm; 19 20 Core::ArgsParser args_parser; 21 args_parser.add_option(opt_algorithm, "Checksum algorithm (default 'crc32', use 'list' to list available algorithms)", "algorithm", '\0', nullptr); 22 args_parser.add_positional_argument(paths, "File", "file", Core::ArgsParser::Required::No); 23 args_parser.parse(arguments); 24 25 auto algorithm = opt_algorithm.is_empty() ? "crc32" : DeprecatedString(opt_algorithm).to_lowercase(); 26 27 auto available_algorithms = Vector<DeprecatedString> { "crc32", "adler32" }; 28 29 if (algorithm == "list") { 30 outln("Available algorithms:"); 31 for (auto& available_algorithm : available_algorithms) { 32 outln(available_algorithm); 33 } 34 exit(0); 35 } 36 37 if (!available_algorithms.contains_slow(algorithm)) { 38 warnln("{}: Unknown checksum algorithm: {}", arguments.strings[0], algorithm); 39 exit(1); 40 } 41 42 if (paths.is_empty()) 43 paths.append("-"); 44 45 bool fail = false; 46 Array<u8, PAGE_SIZE> buffer; 47 48 for (auto& path : paths) { 49 auto file_or_error = Core::File::open_file_or_standard_stream(path, Core::File::OpenMode::Read); 50 auto filepath = (path == "-") ? "/dev/stdin" : path; 51 if (file_or_error.is_error()) { 52 warnln("{}: {}: {}", arguments.strings[0], filepath, file_or_error.error()); 53 fail = true; 54 continue; 55 } 56 auto file = file_or_error.release_value(); 57 size_t file_size = 0; 58 59 if (algorithm == "crc32") { 60 Crypto::Checksum::CRC32 crc32; 61 while (!file->is_eof()) { 62 auto data_or_error = file->read_some(buffer); 63 if (data_or_error.is_error()) { 64 warnln("{}: Failed to read {}: {}", arguments.strings[0], filepath, data_or_error.error()); 65 fail = true; 66 continue; 67 } 68 file_size += data_or_error.value().size(); 69 crc32.update(data_or_error.value()); 70 } 71 outln("{:08x} {} {}", crc32.digest(), file_size, path); 72 } else if (algorithm == "adler32") { 73 Crypto::Checksum::Adler32 adler32; 74 while (!file->is_eof()) { 75 auto data_or_error = file->read_some(buffer); 76 if (data_or_error.is_error()) { 77 warnln("{}: Failed to read {}: {}", arguments.strings[0], filepath, data_or_error.error()); 78 fail = true; 79 continue; 80 } 81 file_size += data_or_error.value().size(); 82 adler32.update(data_or_error.value()); 83 } 84 outln("{:08x} {} {}", adler32.digest(), file_size, path); 85 } else { 86 warnln("{}: Unknown checksum algorithm: {}", arguments.strings[0], algorithm); 87 exit(1); 88 } 89 } 90 91 return fail; 92}