Implemented improved method for detecting identical files.
This commit is contained in:
parent
ca16052112
commit
c607046831
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
CHR *absolute_path(const CHR *const path)
|
||||
typedef struct
|
||||
{
|
||||
uint64_t dev;
|
||||
uint64_t ino;
|
||||
}
|
||||
file_uid_t;
|
||||
|
||||
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);
|
||||
#else
|
||||
char *result = realpath(path, NULL);
|
||||
if ((!result) && path[0U] && (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)
|
||||
{
|
||||
char *const cwd = getcwd(NULL, 0U);
|
||||
if (cwd)
|
||||
BY_HANDLE_FILE_INFORMATION file_info;
|
||||
if ((retval = (!GetFileInformationByHandle(handle, &file_info))) == 0)
|
||||
{
|
||||
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.dwVolumeSerialNumber;
|
||||
file_id->ino = (((uint64_t)file_info.nFileIndexHigh) << 32) | file_info.nFileIndexLow;
|
||||
}
|
||||
CloseHandle(handle);
|
||||
}
|
||||
#else
|
||||
STAT_T file_info;
|
||||
if ((retval = STAT(path, &file_info)) == 0)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
uint64_t get_file_size(FILE* const file)
|
||||
{
|
||||
STAT_T stat;
|
||||
if (FSTAT(FILENO(file), &stat) == 0)
|
||||
file_uid_t file_id0, file_id1;
|
||||
if ((get_file_unique_id(path0, &file_id0) == 0) && (get_file_unique_id(path1, &file_id1) == 0))
|
||||
{
|
||||
const uint16_t file_type = stat.st_mode & S_IFMT;
|
||||
if ((file_type != S_IFDIR) && (file_type != S_IFIFO))
|
||||
return (file_id0.dev == file_id1.dev) && (file_id0.ino == file_id1.ino);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t get_size(FILE *const file)
|
||||
{
|
||||
STAT_T file_info;
|
||||
if (FSTAT(FILENO(file), &file_info) == 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user