Implemented improved method for detecting identical files.

This commit is contained in:
LoRd_MuldeR 2022-03-04 20:05:52 +01:00
parent ca16052112
commit c607046831
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
5 changed files with 63 additions and 103 deletions

View File

@ -67,7 +67,7 @@ int encrypt(const char *const passphrase, const CHR *const input_path, const CHR
goto clean_up;
}
const uint64_t file_size = get_file_size(file_in);
const uint64_t file_size = get_size(file_in);
if (file_size == UINT64_MAX)
{
FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr);
@ -252,7 +252,7 @@ int decrypt(const char *const passphrase, const CHR *const input_path, const CHR
goto clean_up;
}
const uint64_t file_size = get_file_size(file_in);
const uint64_t file_size = get_size(file_in);
if (file_size == UINT64_MAX)
{
FPUTS(T("I/O error: Failed to determine size of input file!\n\n"), stderr);

View File

@ -144,11 +144,12 @@ static void sigint_handler(const int sig)
int MAIN(const int argc, CHR *const argv[])
{
int result = EXIT_FAILURE;
const CHR *input_file = NULL, *output_file = NULL;
char *passphrase_buffer = NULL;
init_terminal();
setup_signal_handler(SIGINT, sigint_handler);
int result = EXIT_FAILURE;
CHR *input_file = NULL, *output_file = NULL;
char *passphrase_buffer = NULL;
FPRINTF(stderr, T("SlunkCrypt Utility (%") T(PRIstr) T("-%") T(PRIstr) T("), by LoRd_MuldeR <MuldeR2@GMX.de>\n"), OS_TYPE, CPU_ARCH);
FPRINTF(stderr, T("Using libSlunkCrypt v%u.%u.%u [%") T(PRIstr) T("]\n\n"), SLUNKCRYPT_VERSION_MAJOR, SLUNKCRYPT_VERSION_MINOR, SLUNKCRYPT_VERSION_PATCH, SLUNKCRYPT_BUILD);
@ -219,23 +220,23 @@ int MAIN(const int argc, CHR *const argv[])
}
}
input_file = absolute_path(argv[PW_FROM_ENV ? 2U : 3U]);
if ((!input_file) || (!input_file[0U]))
input_file = argv[PW_FROM_ENV ? 2U : 3U];
if (!input_file[0U])
{
FPUTS(T("Error: Input file path could not be resolved!\n\n"), stderr);
FPUTS(T("Error: The specified input file name must not be empty!\n\n"), stderr);
goto clean_up;
}
output_file = absolute_path(argv[PW_FROM_ENV ? 3U : 4U]);
if ((!output_file) || (!output_file[0U]))
output_file = argv[PW_FROM_ENV ? 3U : 4U];
if (!output_file[0U])
{
FPUTS(T("Error: Output file path could not be resolved!\n\n"), stderr);
FPUTS(T("Error: The specified output file name must not be empty!\n\n"), stderr);
goto clean_up;
}
if (!path_compare(input_file, output_file))
if (same_file(input_file, output_file) > 0)
{
FPUTS(T("Error: Input and output files must not be the same path! (effectively)\n\n"), stderr);
FPUTS(T("Error: The input and output files must not be the same!\n\n"), stderr);
goto clean_up;
}
@ -316,16 +317,6 @@ clean_up:
free(passphrase_buffer);
}
if (input_file)
{
free(input_file);
}
if (output_file)
{
free(output_file);
}
return result;
}

View File

@ -56,9 +56,8 @@ static void trim_end_of_line(char *const buffer)
char *read_passphrase(const CHR *const file_name)
{
char *buffer = NULL;
CHR *passphrase_path = NULL;
FILE *passphrase_file = NULL;
char *buffer = NULL;
if ((!file_name) || (!file_name[0U]))
{
@ -66,20 +65,10 @@ char *read_passphrase(const CHR *const file_name)
goto finish;
}
if (STRICMP(file_name, T("-")))
{
passphrase_path = absolute_path(file_name);
if ((!passphrase_path) || (!passphrase_path[0U]))
{
FPUTS(T("Error: Passphrase input file path could not be resolved!\n\n"), stderr);
goto finish;
}
}
passphrase_file = passphrase_path ? FOPEN(passphrase_path, T("rb")): stdin;
passphrase_file = STRICMP(file_name, T("-")) ? FOPEN(file_name, T("rb")) : stdin;
if (!passphrase_file)
{
FPRINTF(stderr, T("Error: Failed to open passphrase file \"%") T(PRISTR) T("\" for reading!\n\n%") T(PRISTR) T("\n\n"), passphrase_path, STRERROR(errno));
FPRINTF(stderr, T("Error: Failed to open passphrase file \"%") T(PRISTR) T("\" for reading!\n\n%") T(PRISTR) T("\n\n"), file_name, STRERROR(errno));
goto finish;
}
@ -108,11 +97,6 @@ finish:
fclose(passphrase_file);
}
if (passphrase_path)
{
free(passphrase_path);
}
return buffer;
}

View File

@ -27,6 +27,7 @@
# include <io.h>
# include <fcntl.h>
# define STAT_T struct _stati64
# define STAT(X,Y) _wstati64((X),(Y))
# define FSTAT(X,Y) _fstati64((X),(Y))
# define FILENO(X) _fileno((X))
# define S_IFMT _S_IFMT
@ -39,9 +40,11 @@
# include <unistd.h>
# if defined(__USE_LARGEFILE64) && (__USE_LARGEFILE64)
# define STAT_T struct stat64
# define STAT(X,Y) stat64((X),(Y))
# define FSTAT(X,Y) fstat64((X),(Y))
# else
# define STAT_T struct stat
# define STAT(X,Y) stat((X),(Y))
# define FSTAT(X,Y) fstat((X),(Y))
# endif
# define FILENO(X) fileno((X))
@ -111,30 +114,6 @@ void setup_signal_handler(const int signo, signal_handler_t* const handler)
// String functions
// ==========================================================================
char *concat_str(const char *const str, ...)
{
const char *ptr;
char *buffer;
size_t buff_size = 1U;
va_list arg;
va_start(arg, str);
for (ptr = str; ptr != NULL; ptr = va_arg(arg, const char*))
{
buff_size += strlen(ptr);
}
if ((buffer = (char*)calloc(buff_size, sizeof(char))))
{
va_end(arg);
va_start(arg, str);
for (ptr = str; ptr != NULL; ptr = va_arg(arg, const char*))
{
strcat(buffer, ptr);
}
}
va_end(arg);
return buffer;
}
char* CHR_to_utf8(const CHR *const input)
{
#ifdef _WIN32
@ -259,52 +238,59 @@ size_t fread_ui64(uint64_t *const value, FILE *const stream)
// File functions
// ==========================================================================
#define JOIN_PATHS(X,Y) concat_str((X), "/", (Y), NULL)
typedef struct
{
uint64_t dev;
uint64_t ino;
}
file_uid_t;
CHR *absolute_path(const CHR *const path)
static int get_file_unique_id(const CHR *const path, file_uid_t *const file_id)
{
int retval = -1;
#ifdef _WIN32
wchar_t *const result = _wfullpath(NULL, path, 0U);
const HANDLE handle = CreateFileW(path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0U, NULL);
if (handle != INVALID_HANDLE_VALUE)
{
BY_HANDLE_FILE_INFORMATION file_info;
if ((retval = (!GetFileInformationByHandle(handle, &file_info))) == 0)
{
file_id->dev = file_info.dwVolumeSerialNumber;
file_id->ino = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow;
}
CloseHandle(handle);
}
#else
char *result = realpath(path, NULL);
if ((!result) && path[0U] && (path[0U] != '/'))
STAT_T file_info;
if ((retval = STAT(path, &file_info)) == 0)
{
char *const cwd = getcwd(NULL, 0U);
if (cwd)
{
const char *path_off = path;
while ((path_off[0U] == '.') && (path_off[1U] == '/'))
{
path_off += 2U;
while (path_off[0U] == '/') ++path_off;
}
result = JOIN_PATHS(cwd, path_off);
free(cwd);
}
file_id->dev = file_info.st_dev;
file_id->ino = file_info.st_ino;
}
#endif
return result ? result : STRDUP(path);
return retval;
}
int path_compare(const CHR *const path0, const CHR *const path1)
int same_file(const CHR *const path0, const CHR *const path1)
{
#ifdef _WIN32
return _wcsicmp(path0, path1);
#else
return strcmp(path0, path1);
#endif
file_uid_t file_id0, file_id1;
if ((get_file_unique_id(path0, &file_id0) == 0) && (get_file_unique_id(path1, &file_id1) == 0))
{
return (file_id0.dev == file_id1.dev) && (file_id0.ino == file_id1.ino);
}
return -1;
}
uint64_t get_file_size(FILE* const file)
uint64_t get_size(FILE *const file)
{
STAT_T stat;
if (FSTAT(FILENO(file), &stat) == 0)
STAT_T file_info;
if (FSTAT(FILENO(file), &file_info) == 0)
{
const uint16_t file_type = stat.st_mode & S_IFMT;
if ((file_type != S_IFDIR) && (file_type != S_IFIFO))
const unsigned ftype = file_info.st_mode & S_IFMT;
if ((ftype != S_IFDIR) && (ftype != S_IFIFO))
{
const int64_t ssize = stat.st_size;
return (ssize >= 0) ? ((uint64_t)ssize) : 0U;
const int64_t size = file_info.st_size;
return (size >= 0) ? ((uint64_t)size) : 0U;
}
return 0U;
}

View File

@ -24,10 +24,9 @@ size_t fread_ui64(uint64_t *const value, FILE *const stream);
char* CHR_to_utf8(const CHR *const input);
CHR *absolute_path(const CHR *const path);
int path_compare(const CHR *const path0, const CHR *const path1);
int same_file(const CHR*const path0, const CHR*const path1);
uint64_t get_size(FILE *const file);
const CHR *get_file_name(const CHR *path);
uint64_t get_file_size(FILE* const file);
uint64_t round_down(const uint64_t value, const uint64_t base);