mirror of https://github.com/dnomd343/md5sum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
1.9 KiB
80 lines
1.9 KiB
#include "md5.h"
|
|
#include <iostream>
|
|
#include <optional>
|
|
|
|
using md5::MD5;
|
|
|
|
#if not __linux__
|
|
std::optional<std::string> hash_file(const std::string_view &file_name) {
|
|
auto *fp = std::fopen(file_name.data(), "rb");
|
|
if (!fp) {
|
|
std::perror("File open failed");
|
|
return std::nullopt;
|
|
}
|
|
|
|
MD5 md5;
|
|
size_t len;
|
|
char buffer[BUFSIZ];
|
|
while ((len = std::fread(buffer, sizeof(char), BUFSIZ, fp)) > 0) {
|
|
md5.Update(buffer, len);
|
|
}
|
|
if (std::ferror(fp)) {
|
|
std::perror("File read failed");
|
|
std::fclose(fp);
|
|
return std::nullopt;
|
|
}
|
|
std::fclose(fp);
|
|
return md5.Final().Digest();
|
|
}
|
|
|
|
#else
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
|
|
std::optional<std::string> hash_file(const std::string_view &file_name) {
|
|
auto fd = open(file_name.data(), O_RDONLY);
|
|
if (fd < 0) {
|
|
std::perror("File open failed");
|
|
return std::nullopt;
|
|
}
|
|
|
|
struct stat st {};
|
|
fstat(fd, &st);
|
|
auto file_size = st.st_size;
|
|
|
|
auto ptr = mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
close(fd);
|
|
if (ptr == MAP_FAILED) {
|
|
std::perror("File mapping failed");
|
|
return std::nullopt;
|
|
}
|
|
auto result = MD5::Hash(ptr, file_size);
|
|
if (munmap(ptr, file_size)) {
|
|
std::perror("File unmapping failed");
|
|
}
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
constexpr auto NO_ERROR = 0;
|
|
constexpr auto ARG_ERROR = 1;
|
|
constexpr auto FILE_ERROR = 2;
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc == 1) {
|
|
std::cout << "Usage: " << argv[0] << " [FILE]" << std::endl;
|
|
return NO_ERROR;
|
|
} else if (argc != 2) {
|
|
std::cout << "Invalid MD5 arguments" << std::endl;
|
|
return ARG_ERROR;
|
|
}
|
|
|
|
if (auto result = hash_file(argv[1]); result.has_value()) {
|
|
std::cout << result.value() << std::endl;
|
|
return NO_ERROR;
|
|
}
|
|
return FILE_ERROR;
|
|
}
|
|
|