Added add_backing
This commit is contained in:
140
src/utils.c
140
src/utils.c
@@ -10,7 +10,7 @@
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
char ERROR_BUFFER[ERROR_BUFFER_SIZE];
|
||||
|
||||
@@ -412,6 +412,62 @@ result_t write_file(const char* path, const char* str) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result_t copy_file(const char* src, const char* dst) {
|
||||
// Open the source file
|
||||
errno = 0;
|
||||
int src_fd = open(src, O_RDONLY);
|
||||
if (src_fd < 0)
|
||||
return failure("Failed to open the source file '%s' (%s).", src, strerror(errno));
|
||||
|
||||
// Open the destination file
|
||||
errno = 0;
|
||||
int dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (dst_fd < 0) {
|
||||
close(src_fd);
|
||||
return failure("Failed to open the destination file '%s' (%s).", dst, strerror(errno));
|
||||
}
|
||||
|
||||
// Copy the source file to the destination file
|
||||
char buffer[4096];
|
||||
ssize_t count;
|
||||
|
||||
while (1) {
|
||||
// Read from the source file
|
||||
errno = 0;
|
||||
count = read(src_fd, buffer, sizeof(buffer));
|
||||
if (count < 0) {
|
||||
close(src_fd);
|
||||
close(dst_fd);
|
||||
return failure("Failed to read from the source file '%s' (%s).", src, strerror(errno));
|
||||
}
|
||||
|
||||
// If the end of the file is reached, stop copying
|
||||
if (count == 0)
|
||||
break;
|
||||
|
||||
// Write to the destination file
|
||||
while (count > 0) {
|
||||
errno = 0;
|
||||
ssize_t written = write(dst_fd, buffer, count);
|
||||
if (written < 0) {
|
||||
close(src_fd);
|
||||
close(dst_fd);
|
||||
return failure("Failed to write to the destination file '%s' (%s).", dst, strerror(errno));
|
||||
}
|
||||
|
||||
count -= written;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the source file
|
||||
close(src_fd);
|
||||
|
||||
// Close the destination file
|
||||
close(dst_fd);
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
result_t list_files(char*** _files, const char* path, bool (*filter)(const char*)) {
|
||||
// Initialize the output parameters
|
||||
*_files = NULL;
|
||||
@@ -493,3 +549,85 @@ result_t list_files(char*** _files, const char* path, bool (*filter)(const char*
|
||||
*_files = files;
|
||||
return success();
|
||||
}
|
||||
|
||||
result_t md5sum(char** _md5, const char* path) {
|
||||
// Initialize the output parameters
|
||||
*_md5 = NULL;
|
||||
|
||||
// Open the file
|
||||
errno = 0;
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return failure("Failed to open the file '%s' (%s).", path, strerror(errno));
|
||||
|
||||
// Initialize the MD5 context
|
||||
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
|
||||
if (mdctx == NULL) {
|
||||
close(fd);
|
||||
return failure("Failed to initialize the MD5 context.");
|
||||
}
|
||||
|
||||
if (EVP_DigestInit_ex(mdctx, EVP_md5(), NULL) != 1) {
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
close(fd);
|
||||
return failure("Failed to initialize the MD5 context.");
|
||||
}
|
||||
|
||||
// Read the file and update the MD5 context
|
||||
char buffer[4096];
|
||||
ssize_t count;
|
||||
|
||||
while (1) {
|
||||
// Read from the file
|
||||
errno = 0;
|
||||
count = read(fd, buffer, sizeof(buffer));
|
||||
if (count < 0) {
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
close(fd);
|
||||
return failure("Failed to read from the file '%s' (%s).", path, strerror(errno));
|
||||
}
|
||||
|
||||
// If the end of the file is reached, stop updating the MD5 context
|
||||
if (count == 0)
|
||||
break;
|
||||
|
||||
// Update the MD5 context
|
||||
if (EVP_DigestUpdate(mdctx, buffer, count) != 1) {
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
close(fd);
|
||||
return failure("Failed to update the MD5 context.");
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the MD5 context
|
||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len;
|
||||
|
||||
if (EVP_DigestFinal_ex(mdctx, md_value, &md_len) != 1) {
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
close(fd);
|
||||
return failure("Failed to finalize the MD5 context.");
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
// Close the file
|
||||
close(fd);
|
||||
|
||||
// Format the MD5 checksum
|
||||
errno = 0;
|
||||
char* md5 = malloc(2 * md_len + 1); // +1 for the null terminator
|
||||
if (md5 == NULL)
|
||||
return failure("Failed to allocate memory for the MD5 checksum (%s).", strerror(errno));
|
||||
|
||||
for (unsigned int i = 0; i < md_len; i++)
|
||||
if (snprintf(md5 + 2 * i, 3, "%02x", md_value[i]) != 2) {
|
||||
free(md5);
|
||||
return failure("Failed to format the MD5 checksum.");
|
||||
}
|
||||
md5[2 * md_len] = '\0';
|
||||
|
||||
// Return the MD5 checksum
|
||||
*_md5 = md5;
|
||||
return success();
|
||||
}
|
Reference in New Issue
Block a user