diff options
Diffstat (limited to 'trashsys_small_paths.cc')
-rw-r--r-- | trashsys_small_paths.cc | 1256 |
1 files changed, 0 insertions, 1256 deletions
diff --git a/trashsys_small_paths.cc b/trashsys_small_paths.cc deleted file mode 100644 index 19d7be7..0000000 --- a/trashsys_small_paths.cc +++ /dev/null @@ -1,1256 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include <ftw.h> -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <unistd.h> -#include <time.h> -#include <fcntl.h> -#include <errno.h> -#include <pwd.h> -#include <string.h> -#include <libgen.h> -#include <dirent.h> -#include <stdarg.h> -#include <limits.h> -#include <sys/stat.h> -#include <iostream> -#include <string> -#include <vector> -#define PATH_MAX 4096 -#define USAGE "tsr [-vt] [-y][-n][-f][-a][-l][-L][-c][-C][-h][-R id] [FILE(s)]\n" -#define LONG_USAGE "tsr [options] filename(s)\n"\ - "\n"\ - "OPTIONS:\n"\ - " -t /tmp mode. tsr will use /tmp instead of the user's $HOME.\n"\ - " -y Answer 'yes' when pressing return on all [Y / N] prompts.\n"\ - " -n Answer 'no' when pressing return on all [Y / N] prompts.\n"\ - " -f Force answer 'yes' on all [Y / N] prompts. Prompt will not show.\n"\ - " -l List all trashed files.\n"\ - " -L List all trashed files with more details.\n"\ - " -c Clear all trashed files that are older than the configured time limit.\n"\ - " -C Clear all trashed files regardless of age. Will prompt with a [Y / N] prompt.\n"\ - " -h Display this help message.\n"\ - " -R id path(optional) Restore a file by ID. Use -l or -L to find the ID associated with the file.\n"\ - " -v Verbose mode, not recommended unless you are a developer.\n"\ - " -i Check for inconsistencies in the logs and trashed files (maybe implement)\n"\ - "\n" -#define MODE_NORMAL -1 -#define MODE_YES 0 -#define MODE_NO 1 -#define MODE_FORCE 2 -#define ENVVAR_HOME "HOME" -#define NOFILE 3 -#define FUNCTION_FAILURE -1 -#define FUNCTION_SUCCESS 0 -#define REM_SZ(remsz, final) (remsz - strlen(final)) -#define USAGE_OUT(stream) (fprintf(stream, "%s", USAGE)) -#define USAGE_OUT_L(stream) (fprintf(stream, "%s", LONG_USAGE)) - -bool v_cvm_fprintf = false; -int choice_mode = MODE_NORMAL; -char *g_argv = NULL; - -struct trashsys_log_info { - int64_t ts_log_id; - char ts_log_filename[FILENAME_MAX]; - size_t ts_log_filesize; - time_t ts_log_trashtime; - char ts_log_originalpath[PATH_MAX]; - bool ts_log_tmp; - bool ts_is_dir; -}; - -struct list_file_content { - char ID[PATH_MAX]; - char filename[PATH_MAX]; - char trashed_filename[PATH_MAX]; - char filesize[PATH_MAX]; - char time[PATH_MAX]; - char originalpath[PATH_MAX]; - char tmp[PATH_MAX]; - char is_dir[PATH_MAX]; - struct list_file_content *next; -}; - -struct dynamic_paths { - char old_trashfile_path[PATH_MAX]; - char new_trashfile_path[PATH_MAX]; - char new_trashfile_filename[FILENAME_MAX]; - char new_logfile_path_incl_name[PATH_MAX]; -}; - -struct initial_path_info { // Initial useful strings to create before we do anything. Super useful when programming. - char ts_path_user_home[PATH_MAX]; - char ts_path_trashsys[PATH_MAX]; - char ts_path_log[PATH_MAX]; - char ts_path_trashed[PATH_MAX]; - char ts_path_user_home_withslash[PATH_MAX]; - char ts_path_trashsys_withslash[PATH_MAX]; - char ts_path_log_withslash[PATH_MAX]; - char ts_path_trashed_withslash[PATH_MAX]; -}; - -int handle_ynf (const bool y_used, const bool n_used, const bool f_used) { - - int choice_mode_ynf = MODE_NORMAL; - if (n_used == true) { choice_mode_ynf = MODE_NO; } - if (y_used == true) { choice_mode_ynf = MODE_YES; } - if (f_used == true) { choice_mode_ynf = MODE_FORCE; } - - return choice_mode_ynf; -} - -int choice (const int mode) { - - char choice; - char modechoice; - do { - if (mode == MODE_NORMAL) { fputs("[Y / N] ? ", stdout); } - if (mode == MODE_YES) { fputs("[Y / n] ? ", stdout); } - if (mode == MODE_NO) { fputs("[y / N] ? ", stdout); } - if (mode == MODE_FORCE) { return 0; } - - choice = getchar(); - if (choice == '\n' && mode == MODE_YES) { modechoice = 'Y'; choice = modechoice; goto modeskip;} - if (choice == '\n' && mode == MODE_NO) { modechoice = 'N'; choice = modechoice; goto modeskip;} - if (choice == '\n' && mode == MODE_NORMAL) { continue; } - - while ('\n' != getchar()); - - } while ( (choice != 'Y') && (choice != 'y') && (choice != 'N') && (choice != 'n') ); - - modeskip: - if ((choice == 'Y') || (choice == 'y')) { - return 0; - } - - if ((choice == 'N') || (choice == 'n')) { - return 1; - } - - return FUNCTION_FAILURE; // Should never happen -} - -int get_line (const char *filename, long focus, char **line, size_t *start) { // taken from 7Editor and modified slightly - - FILE *file; - file = fopen(filename,"r"); // Open file - if (file == NULL) { // Check if you can open file - fprintf(stderr, "Cannot open file get_line.\n"); - return FUNCTION_FAILURE; - } - - if (focus == 1) { - int c1_count = 0; - while (1) { - char c = fgetc(file); - if (c == '\n') { - c1_count++; - break; - } else if (c == EOF) { - break; - } else { - c1_count++; - } - } // checks how many characters are in the first line - - char c1buf[c1_count+1]; - fseek(file, 0, SEEK_SET); - int i = 0; - for (; i < c1_count ; i++) { - c1buf[i] = fgetc(file); - } - - c1buf[i] = '\0'; - *line = (char *)malloc(strlen(c1buf) + 1); - if (*line != NULL) { - strcpy(*line, c1buf); // Return line 1 - } - - *start = 0; // Is start the start of where line - } else { - focus--; - size_t line_count = 0; // Counter starting at 0 - size_t save_i = 0; - for (size_t i = 0; ; i++) { - char c = fgetc(file); - if (feof(file)) { // If end of file is encountered then break - break; - } - - if (c == '\n') { - line_count++; - if (line_count == (size_t)focus) { - save_i = i; - break; - } - } - } - - fseek(file, save_i+1, SEEK_SET); - int c2_count = 0; - while (1) { - char c = fgetc(file); - if (c == '\n') { - c2_count++; - break; - } else if (c == EOF) { - break; - } else { - c2_count++; - } - } - - fseek(file, save_i+1, SEEK_SET); - char c2buf[c2_count+1]; - int i = 0; - for (; i < c2_count ; i++) { - c2buf[i] = fgetc(file); - } - - c2buf[i] = '\0'; - *line = (char *)malloc(strlen(c2buf) + 1); - if (*line != NULL) { - strcpy(*line, c2buf); - } - - *start = save_i+1; // not sure but i think it saves the start position of the line - } - - fclose(file); - return FUNCTION_SUCCESS; -} - -int cvm_fprintf (const bool ONOROFF, FILE *stream, const char *format, ...) { - - if (ONOROFF == false) { - return FUNCTION_SUCCESS; - } - - va_list args; - va_start(args, format); - int result = vfprintf(stream, format, args); - va_end(args); - return result; -} - -char *concat_str (char *final, const ssize_t rem_size, const char *from) { - // IF you use this function PLEASE know this: - // rem_size is the amount of characters left in final - // rem_size should NOT include \0 in the size - // So if you were to have 5 remaining characters then 5 is what you put as the argument - // from is calculated and then we add +1 to account for the \0 character. - if (final == NULL || from == NULL) { - return NULL; - } - - ssize_t from_len = strlen(from); - if (from_len+1 > rem_size) { - return NULL; - } - - strcat(final, from); - return final; -} - -int fill_ipi (const bool t_used, struct initial_path_info *ipi) { // Function for filling out initial_path_info so it can be used later - - const char *ts_toplevel = "/.trashsys"; - const char *ts_log = "/log"; - const char *ts_trashed = "/trashed"; - const char *ts_toplevel_withslash = "/.trashsys/"; - const char *ts_log_withslash = "/log/"; - const char *ts_trashed_withslash = "/trashed/"; - char *homepath; - const char *ts_tmp = "/tmp"; - const char *ts_tmp_toplevel = "/tmp/.trashsys"; - const char *ts_tmp_log = "/tmp/.trashsys/log"; - const char *ts_tmp_trashed = "/tmp/.trashsys/trashed"; - const char *ts_tmp_withslash = "/tmp/"; - const char *ts_tmp_toplevel_withslash = "/tmp/.trashsys/"; - const char *ts_tmp_log_withslash = "/tmp/.trashsys/log/"; - const char *ts_tmp_trashed_withslash = "/tmp/.trashsys/trashed/"; - ipi->ts_path_user_home[0] = '\0'; - ipi->ts_path_trashsys[0] = '\0'; - ipi->ts_path_log[0] = '\0'; - ipi->ts_path_trashed[0] = '\0'; - ipi->ts_path_user_home_withslash[0] = '\0'; - ipi->ts_path_trashsys_withslash[0] = '\0'; - ipi->ts_path_log_withslash[0] = '\0'; - ipi->ts_path_trashed_withslash[0] = '\0'; - - if (t_used == false) { - homepath = getenv(ENVVAR_HOME); // Get the home path of the current user - if (homepath == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi(): getenv failed"); - return FUNCTION_FAILURE; - } - - // /home/john - // /home/john/ - if(concat_str(ipi->ts_path_user_home, PATH_MAX, homepath) == NULL - || concat_str(ipi->ts_path_user_home_withslash, PATH_MAX, homepath) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - if(concat_str(ipi->ts_path_user_home_withslash, REM_SZ(PATH_MAX, ipi->ts_path_user_home_withslash), "/") == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - // /home/john/.trashsys - // /home/john/.trashsys/ - if(concat_str(ipi->ts_path_trashsys, PATH_MAX, homepath) == NULL - || concat_str(ipi->ts_path_trashsys_withslash, PATH_MAX, homepath) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - if(concat_str(ipi->ts_path_trashsys, REM_SZ(PATH_MAX, ipi->ts_path_trashsys), ts_toplevel) == NULL - || concat_str(ipi->ts_path_trashsys_withslash, REM_SZ(PATH_MAX, ipi->ts_path_trashsys_withslash), ts_toplevel_withslash) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - // /home/john/.trashsys/log - // /home/john/.trashsys/log/ - if(concat_str(ipi->ts_path_log, PATH_MAX, ipi->ts_path_trashsys) == NULL - || concat_str(ipi->ts_path_log_withslash, PATH_MAX, ipi->ts_path_trashsys) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - if(concat_str(ipi->ts_path_log, REM_SZ(PATH_MAX, ipi->ts_path_log), ts_log) == NULL - || concat_str(ipi->ts_path_log_withslash, REM_SZ(PATH_MAX, ipi->ts_path_log_withslash), ts_log_withslash) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - // /home/john/.trashsys/trashed - // /home/john/.trashsys/trashed/ - if(concat_str(ipi->ts_path_trashed, PATH_MAX, ipi->ts_path_trashsys) == NULL - || concat_str(ipi->ts_path_trashed_withslash, PATH_MAX, ipi->ts_path_trashsys) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - if(concat_str(ipi->ts_path_trashed, REM_SZ(PATH_MAX, ipi->ts_path_trashed), ts_trashed) == NULL - || concat_str(ipi->ts_path_trashed_withslash, REM_SZ(PATH_MAX, ipi->ts_path_trashed_withslash), ts_trashed_withslash) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - - } else if (t_used == true) { // If -t flag is specified we fill ipi with /tmp paths instead - if(concat_str(ipi->ts_path_user_home, PATH_MAX, ts_tmp) == NULL || - concat_str(ipi->ts_path_trashsys, PATH_MAX, ts_tmp_toplevel) == NULL || - concat_str(ipi->ts_path_log, PATH_MAX, ts_tmp_log) == NULL || - concat_str(ipi->ts_path_trashed, PATH_MAX, ts_tmp_trashed) == NULL || - concat_str(ipi->ts_path_user_home_withslash, PATH_MAX, ts_tmp_withslash) == NULL || - concat_str(ipi->ts_path_trashsys_withslash, PATH_MAX, ts_tmp_toplevel_withslash) == NULL || - concat_str(ipi->ts_path_log_withslash, PATH_MAX, ts_tmp_log_withslash) == NULL || - concat_str(ipi->ts_path_trashed_withslash, PATH_MAX, ts_tmp_trashed_withslash) == NULL - ) { - cvm_fprintf(v_cvm_fprintf, stdout, "fill_ipi: path is too long\n"); - return FUNCTION_FAILURE; - } - } - - cvm_fprintf(v_cvm_fprintf, stdout, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n" - , ipi->ts_path_user_home - , ipi->ts_path_trashsys - , ipi->ts_path_log - , ipi->ts_path_trashed - , ipi->ts_path_user_home_withslash - , ipi->ts_path_trashsys_withslash - , ipi->ts_path_log_withslash - , ipi->ts_path_trashed_withslash - ); - return FUNCTION_SUCCESS; -} - -int check_create_ts_dirs(const struct initial_path_info *ipi) { // 1. Check if trashsys toplevel exists 2. Check if log exists 3. Check if trashed exists - - int mkd; - mkd = mkdir(ipi->ts_path_trashsys, 0755); - if (mkd < 0) { - if (errno == EEXIST) { cvm_fprintf(v_cvm_fprintf, stdout, ".trashsys exists\n"); } else { return FUNCTION_FAILURE; } - } else { cvm_fprintf(v_cvm_fprintf, stdout, "%s was created\n", ipi->ts_path_trashsys); } - - mkd = mkdir(ipi->ts_path_log, 0755); - if (mkd < 0) { - if (errno == EEXIST) { cvm_fprintf(v_cvm_fprintf, stdout, "log exists\n"); } else { return FUNCTION_FAILURE; } - } else { cvm_fprintf(v_cvm_fprintf, stdout, "%s was created\n", ipi->ts_path_log); } - - mkd = mkdir(ipi->ts_path_trashed, 0755); - if (mkd < 0) { - if (errno == EEXIST) { cvm_fprintf(v_cvm_fprintf, stdout, "trashed exists\n"); } else { return FUNCTION_FAILURE; } - } else { cvm_fprintf(v_cvm_fprintf, stdout, "%s was created\n", ipi->ts_path_trashed); } - - return FUNCTION_SUCCESS; -} - -int64_t find_highest_id (const struct initial_path_info *ipi) { - // We need to check whether a file is a directory or just a file. - int64_t id = 0; - struct dirent *ddd = NULL; - DIR *dir = opendir(ipi->ts_path_log); - if (dir == NULL) { - return FUNCTION_FAILURE; - } - - while ((ddd = readdir(dir)) != NULL) { - char stat_fullpath[PATH_MAX]; - stat_fullpath[0] = '\0'; - if(concat_str(stat_fullpath, PATH_MAX, ipi->ts_path_log_withslash) == NULL) { - fprintf(stderr, "Path is too long\n"); // rare case but at least its handled - closedir(dir); - return FUNCTION_FAILURE; - } - - if(concat_str(stat_fullpath, REM_SZ(PATH_MAX, stat_fullpath), ddd->d_name) == NULL) { - fprintf(stderr, "Path is too long\n"); // rare case but at least its handled - closedir(dir); - return FUNCTION_FAILURE; - } - - struct stat d_or_f; - stat(stat_fullpath, &d_or_f); - if(S_ISREG(d_or_f.st_mode)) { // check if given file is actually a file - cvm_fprintf(v_cvm_fprintf, stdout, "is regular file: %s\nstat_fullpath: %s\n", ddd->d_name, stat_fullpath); - char *endptr = NULL; - int64_t strtoll_ID = strtoull(ddd->d_name, &endptr, 10); - if(ddd->d_name == endptr) { - cvm_fprintf(v_cvm_fprintf, stdout, "d_name == endptr | d_name: %p | endptr: %p | d_name string: %s\n", ddd->d_name, endptr, ddd->d_name); - continue; - } - - if(*endptr != ':') { - cvm_fprintf(v_cvm_fprintf, stdout, "':' not found for file: %s\n", ddd->d_name); - continue; - } - - if(strtoll_ID > id) { // If id is bigger then update it - id = strtoll_ID; - cvm_fprintf(v_cvm_fprintf, stdout, "found higher ID: %d\n", id); - } - } - } - closedir(dir); - return id; -} - -int tli_fill_info (struct trashsys_log_info *tli, char* filename, const bool log_tmp, struct initial_path_info *ipi) { - // This function will be the main function that gathers and fills out info that will be in the log file for a file a user wants to trash - char *rp = NULL; - time_t curtime; - rp = realpath(filename, NULL); // get full entire path of the file - if (rp == NULL) { - return NOFILE; - } - - tli->ts_log_originalpath[0] = '\0'; - tli->ts_log_filename[0] = '\0'; - if(concat_str(tli->ts_log_originalpath, PATH_MAX, rp) == NULL) { - free(rp); - return FUNCTION_FAILURE; - } - - free(rp); - rp = NULL; - if(concat_str(tli->ts_log_filename, FILENAME_MAX, basename(filename)) == NULL) { - return FUNCTION_FAILURE; - } - - tli->ts_log_tmp = log_tmp; // tmp or not? - curtime = time(NULL); - if (curtime == -1) { - return FUNCTION_FAILURE; - } - - tli->ts_log_trashtime = curtime; - struct stat s; - rp = realpath(filename, NULL); - stat(rp, &s); - free(rp); - if(S_ISDIR(s.st_mode)) { - tli->ts_is_dir = true; - tli->ts_log_filesize = 0; - // Code to recursively check size within directories - } else { - FILE *file = fopen(filename, "r"); // We get the filesize in bytes /*Perhaps we need to check if its a dir/file here?*/ - if(file == NULL) { - return NOFILE; - } - fseek(file, 0, SEEK_END); - long filesize = ftell(file); - fclose(file); - tli->ts_log_filesize = (size_t)filesize; - } - - int64_t ID = find_highest_id(ipi); - if (ID == FUNCTION_FAILURE) { - return FUNCTION_FAILURE; - } - - tli->ts_log_id = ID + 1; // +1 because if we are making a new file we need to give it one above highest ID. - return FUNCTION_SUCCESS; -} - -int fill_dynamic_paths (struct initial_path_info *ipi, struct trashsys_log_info *tli, struct dynamic_paths *dp) { - - dp->old_trashfile_path[0] = '\0'; - dp->new_trashfile_path[0] = '\0'; - dp->new_logfile_path_incl_name[0] = '\0'; - dp->new_trashfile_filename[0] = '\0'; - // /path/to/my/file.txt - if(concat_str(dp->old_trashfile_path, PATH_MAX, tli->ts_log_originalpath) == NULL) { return FUNCTION_FAILURE; } - - // filename ID eg. '35:' - char idstr[23]; - snprintf(idstr, 23, "%ld:", tli->ts_log_id); - - // /home/john/.trashsys/trashed/35:file.txt - if(concat_str(dp->new_trashfile_path, PATH_MAX, ipi->ts_path_trashed_withslash) == NULL) { return FUNCTION_FAILURE; } - if(concat_str(dp->new_trashfile_path, REM_SZ(PATH_MAX, dp->new_trashfile_path), idstr) == NULL) { return FUNCTION_FAILURE; } - if(concat_str(dp->new_trashfile_path, REM_SZ(PATH_MAX, dp->new_trashfile_path), tli->ts_log_filename) == NULL) { return FUNCTION_FAILURE; } - - // /home/john/.trashsys/log/35:file.txt.log - if(concat_str(dp->new_logfile_path_incl_name, PATH_MAX, ipi->ts_path_log_withslash) == NULL) { return FUNCTION_FAILURE; } - if(concat_str(dp->new_logfile_path_incl_name, REM_SZ(PATH_MAX, dp->new_logfile_path_incl_name), idstr) == NULL) { return FUNCTION_FAILURE; } - if(concat_str(dp->new_logfile_path_incl_name, REM_SZ(PATH_MAX, dp->new_logfile_path_incl_name), tli->ts_log_filename) == NULL) { return FUNCTION_FAILURE; } - if(concat_str(dp->new_logfile_path_incl_name, REM_SZ(PATH_MAX, dp->new_logfile_path_incl_name), ".log") == NULL) { return FUNCTION_FAILURE; } - - // 35:file.txt - if(concat_str(dp->new_trashfile_filename, PATH_MAX, basename(dp->new_trashfile_path)) == NULL) { return FUNCTION_FAILURE; } - - cvm_fprintf(v_cvm_fprintf, stdout, "%s\n%s\n%s\n%s\n" - , dp->old_trashfile_path - , dp->new_trashfile_path - , dp->new_trashfile_filename - , dp->new_logfile_path_incl_name - ); - - return FUNCTION_SUCCESS; -} - -int write_log_file (struct dynamic_paths *dp, struct trashsys_log_info *tli, const bool t_used_aka_tmp) { - - if (t_used_aka_tmp == true) { - cvm_fprintf(v_cvm_fprintf, stdout, "tmp"); - } - - cvm_fprintf(v_cvm_fprintf, stdout, "logfile path: %s\n", dp->new_logfile_path_incl_name); - FILE *file = fopen(dp->new_logfile_path_incl_name, "w"); - if(file == NULL) { - printf("%s\n", strerror(errno)); - return FUNCTION_FAILURE; - } - - /*this fprintf is what WRITES in to the logfile*/ - fprintf(file, "%ld\n%s\n%s\n%ld\n%ld\n%s\n%d\n%d\n" - , tli->ts_log_id - , tli->ts_log_filename - , dp->new_trashfile_filename - , tli->ts_log_filesize - , tli->ts_log_trashtime - , tli->ts_log_originalpath - , tli->ts_log_tmp - , tli->ts_is_dir - ); - - fclose(file); - return FUNCTION_SUCCESS; -} - -char *rawtime_to_readable (time_t rawtime) { - - struct tm *tmp = NULL; - char *pretty_time = (char*)malloc(sizeof(char) * 512); - tmp = localtime(&rawtime); - if(strftime(pretty_time, 512, "%F", tmp) == 0) { - free(pretty_time); - return NULL; - } - - return pretty_time; -} - -std::string bytes_to_readable_str (size_t bytes, char *str, size_t str_len) { - - char tmp_str[str_len]; - double f_bytes = (double)bytes; - int count = 0; - std::vector<std::string> BKMG = {"B", "KiB", "MiB", "GiB"}; - while (f_bytes >= 1024) { - f_bytes = f_bytes / 1024; - count++; - } - - snprintf(tmp_str, str_len, "%0.1f", f_bytes); - if(concat_str(str, str_len, tmp_str) == NULL) { - return NULL; - } - - return BKMG[count]; -} - -int lfc_formatted (struct list_file_content *lfc, const bool L_used) { - - time_t rawtime; - size_t filesize_bytes; - char *endptr = NULL; - char *endptr2 = NULL; - char *pretty_time = NULL; - std::string sdir = "directory"; - std::string sfile = "file"; - const char *dir = sdir.c_str(); - const char *file = sfile.c_str(); - const char *type = NULL; - rawtime = (time_t)strtoll(lfc->time, &endptr, 10); - if (errno == ERANGE || lfc->time == endptr) { - fprintf(stdout, "strtoll fail\n"); - return FUNCTION_FAILURE; - } - - filesize_bytes = (size_t)strtoul(lfc->filesize, &endptr2, 10); - if (errno == ERANGE || lfc->filesize == endptr) { - fprintf(stdout, "strtoul fail\n"); - return FUNCTION_FAILURE; - } - - pretty_time = rawtime_to_readable(rawtime); - if(pretty_time == NULL){ - fprintf(stdout, "Cannot convert time to readable\n"); - return FUNCTION_FAILURE; - } - - if(lfc->is_dir[0] == '0') { - type = file; - } else if(lfc->is_dir[0] == '1') { - type = dir; - } - - std::string fff; - size_t str_len = 1024; - char readable_mib_str[str_len]; - readable_mib_str[0] = '\0'; - fff = bytes_to_readable_str(filesize_bytes, readable_mib_str, str_len); - const char *fffcstr = fff.c_str(); - if (L_used == true) { - fprintf(stdout, "ID: %s %s %s %s %s B Trashed at: %s (unixtime: %s) originalpath: %s %s\n" - , lfc->ID - , lfc->filename - , readable_mib_str - , fffcstr - , lfc->filesize - , pretty_time - , lfc->time - , lfc->originalpath - , type - ); - free(pretty_time); - return FUNCTION_SUCCESS; - } - - fprintf(stdout, "ID: %s %s %s %s Trashed at: %s %s\n" - , lfc->ID - , lfc->filename - , readable_mib_str - , fffcstr - , pretty_time - , type - ); - free(pretty_time); - return FUNCTION_SUCCESS; -} - -void free_lfc (struct list_file_content *lfc) { - - struct list_file_content *save = NULL; - while (lfc != NULL) { - save = lfc; - lfc = lfc->next; - free(save); - } -} - -struct list_file_content *fill_lfc (struct initial_path_info *ipi) { - - struct dirent *ddd = NULL; - DIR *dir = opendir(ipi->ts_path_log); - if (dir == NULL) { - return NULL; - } - - struct list_file_content *lfc = (list_file_content*)malloc(sizeof(struct list_file_content)); // first node - lfc->next = NULL; - struct list_file_content *lfc_head = lfc; - bool first = true; - while ((ddd = readdir(dir)) != NULL) { - char stat_fullpath[PATH_MAX]; - stat_fullpath[0] = '\0'; - if(concat_str(stat_fullpath, PATH_MAX, ipi->ts_path_log_withslash) == NULL) { - fprintf(stderr, "Path is too long\n"); // rare case but at least its handle - free_lfc(lfc_head); - closedir(dir); - return NULL; - } - - if(concat_str(stat_fullpath, REM_SZ(PATH_MAX, stat_fullpath), ddd->d_name) == NULL) { - fprintf(stderr, "Path is too long\n"); // rare case but at least its handled - free_lfc(lfc_head); - closedir(dir); - return NULL; - } - - struct stat d_or_f; - stat(stat_fullpath, &d_or_f); - if(S_ISREG(d_or_f.st_mode)) { // check if given file is actually a file - if(first == false) { - lfc->next = (list_file_content*)malloc(sizeof(struct list_file_content)); // Create next node - lfc = lfc->next; // Point lfc to the newly created node - lfc->next = NULL; // Set next to NULL so in case there is a failure, free_lfc wont get a segfault - } else { - first = false; - } - - cvm_fprintf(v_cvm_fprintf, stdout, "is regular file: %s\nstat_fullpath: %s\n", ddd->d_name, stat_fullpath); - FILE *file = fopen(stat_fullpath, "r"); - if (file == NULL) { - free_lfc(lfc_head); - closedir(dir); - return NULL; - } - - char *lfc_a[8] = {NULL}; - lfc->ID[0] = '\0'; - lfc->filename[0] = '\0'; - lfc->trashed_filename[0] = '\0'; - lfc->filesize[0] = '\0'; - lfc->time[0] = '\0'; - lfc->originalpath[0] = '\0'; - lfc->tmp[0] = '\0'; - lfc->is_dir[0] = '\0'; - lfc_a[0] = lfc->ID; - lfc_a[1] = lfc->filename; - lfc_a[2] = lfc->trashed_filename; - lfc_a[3] = lfc->filesize; - lfc_a[4] = lfc->time; - lfc_a[5] = lfc->originalpath; - lfc_a[6] = lfc->tmp; - lfc_a[7] = lfc->is_dir; - int i = 0; - int linenum = 1; - for ( ; i < 8 ; i++, linenum++) { - char *line = NULL; - size_t start; - if(get_line(stat_fullpath, linenum, &line, &start) == FUNCTION_FAILURE) { - free_lfc(lfc_head); - closedir(dir); - return NULL; - } - - if(concat_str(lfc_a[i], PATH_MAX, line) == NULL) { - free_lfc(lfc_head); - free(line); - closedir(dir); - return NULL; - } - - for(int si = 0 ;; si++) { - if(lfc_a[i][si] == '\n') { - lfc_a[i][si] = '\0'; - break; - } - } - free(line); - } - fclose(file); - } - } - if(first == true) { - free_lfc(lfc_head); - closedir(dir); - return NULL; - } - - lfc = NULL; - closedir(dir); - return lfc_head; -} - -int remove_nftw (const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - - (void) sb; - (void) typeflag; - (void) ftwbuf; - int rmn = remove(fpath); - if (rmn) { - fprintf(stderr, "fail\n"); - } - - return rmn; -} - -int clear_all_files (char *paths, bool *errors) { - - struct dirent *ddd = NULL; - DIR *dir = opendir(paths); - if (dir == NULL) { - return FUNCTION_FAILURE; - } - - char all[PATH_MAX] = {0}; - if(concat_str(all, PATH_MAX, paths) == NULL) { - closedir(dir); - return FUNCTION_FAILURE; - } - - int paths_len = strlen(paths); - while ((ddd = readdir(dir)) != NULL) { - - if (strncmp(".", ddd->d_name, 2) == 0 || strncmp("..", ddd->d_name, 3) == 0) { - continue; - } - - all[paths_len] = '\0'; - if(concat_str(all, REM_SZ(PATH_MAX, all), ddd->d_name) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths too long\n"); - closedir(dir); - return FUNCTION_FAILURE; - } - - int rm; - struct stat s; - stat(all, &s); - if(S_ISDIR(s.st_mode)) { - cvm_fprintf(v_cvm_fprintf, stdout, "clear_old_files: dir\n"); - rm = nftw(all, remove_nftw, 128, FTW_DEPTH | FTW_PHYS); - if(rm == -1) { - *errors = true; - fprintf(stderr, "%s: failed to remove: %s\n", g_argv, ddd->d_name); - continue; - } - cvm_fprintf(v_cvm_fprintf, stdout, "removed %s\n", ddd->d_name); - continue; - } - - rm = remove(all); - if(rm == -1) { - *errors = true; - fprintf(stderr, "%s: failed to remove: %s\n", g_argv, ddd->d_name); - continue; - } - - cvm_fprintf(v_cvm_fprintf, stdout, "removed %s\n", ddd->d_name); - } - - closedir(dir); - return FUNCTION_SUCCESS; -} - -int compare_unixtime (time_t deleted_time, int difference_in_days) { - - time_t diff_converted; - time_t current_time; - time_t final; - diff_converted = (time_t)difference_in_days * 86400; - current_time = time(NULL); - if(current_time == -1) { - return FUNCTION_FAILURE; - } - - final = current_time - deleted_time; - if(final < diff_converted) { - cvm_fprintf(v_cvm_fprintf, stdout, "final is not older than diff_converted\n"); - return FUNCTION_FAILURE; - } - - cvm_fprintf(v_cvm_fprintf, stdout, "final is older than diff_converted\n"); - return FUNCTION_SUCCESS; -} - -int clear_old_files (int file_age_in_days, struct initial_path_info *ipi) { - - struct list_file_content *lfc = fill_lfc(ipi); - struct list_file_content *walk = NULL; - int i = 1; - if(lfc == NULL) { return EXIT_SUCCESS; } - for(walk = lfc ; walk != NULL ; walk = walk->next, i++) { - char *endptr = NULL; - time_t deleted_time = (time_t)strtoll(walk->time, &endptr, 10); - if (errno == ERANGE || lfc->time == endptr) { - cvm_fprintf(v_cvm_fprintf, stdout, "strtoll fail\n"); - return FUNCTION_FAILURE; - } - - if(compare_unixtime(deleted_time, file_age_in_days) == FUNCTION_FAILURE) { - continue; - } - - char cur_log_path[PATH_MAX]; - char cur_trashed_path[PATH_MAX]; - cur_log_path[0] = '\0'; - cur_trashed_path[0] = '\0'; - if(concat_str(cur_log_path, PATH_MAX, ipi->ts_path_log_withslash) == NULL - || concat_str(cur_trashed_path, PATH_MAX, ipi->ts_path_trashed_withslash) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths are too long. Continuing to next file.\n"); - continue; - } - - if(concat_str(cur_log_path, REM_SZ(PATH_MAX, cur_log_path), walk->trashed_filename) == NULL - || concat_str(cur_trashed_path, REM_SZ(PATH_MAX, cur_trashed_path), walk->trashed_filename) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths are too long. Continuing to next file.\n"); - continue; - } - - if(concat_str(cur_log_path, REM_SZ(PATH_MAX, cur_log_path), ".log") == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths are too long. Continuing to next file.\n"); - continue; - } - - int rm1; - int rm2; - struct stat s; - stat(cur_trashed_path, &s); - if(S_ISDIR(s.st_mode)) { - cvm_fprintf(v_cvm_fprintf, stdout, "clear_old_files: dir\n"); - rm1 = remove(cur_log_path); - rm2 = nftw(cur_trashed_path, remove_nftw, 64, FTW_DEPTH | FTW_PHYS); - } else { - rm1 = remove(cur_log_path); - rm2 = remove(cur_trashed_path); - } - - if(rm1 == -1 || rm2 == -1) { - if(rm1 == -1) {fprintf(stderr, "%s failed to remove: %s\n", g_argv, cur_log_path);} - if(rm2 == -1) {fprintf(stderr, "%s failed to remove: %s\n", g_argv, cur_trashed_path);} - continue; - } - - cvm_fprintf(v_cvm_fprintf, stdout, "removed %s\n", cur_log_path); - cvm_fprintf(v_cvm_fprintf, stdout, "removed %s\n", cur_trashed_path); - } - - free_lfc(lfc); - return EXIT_SUCCESS; -} - -int restore_file (unsigned long long ID, struct initial_path_info *ipi) { - - unsigned long long logfile_ID; - struct list_file_content *lfc = fill_lfc(ipi); - struct list_file_content *walk = NULL; - int i = 1; - if(lfc == NULL) { return EXIT_SUCCESS; } - for(walk = lfc ; walk != NULL ; walk = walk->next, i++) { - char *endptr = NULL; - logfile_ID = 0; - logfile_ID = strtoll(walk->ID, &endptr, 10); - if(errno == ERANGE) { - cvm_fprintf(v_cvm_fprintf, stdout, "ID out of range.\n"); - continue; - } - if(lfc->ID == endptr) { - cvm_fprintf(v_cvm_fprintf, stdout, "invalid ID.\n"); - continue; - } - - if(logfile_ID != ID) { - cvm_fprintf(v_cvm_fprintf, stdout, "logfile_ID != ID.\n"); - continue; - } - - char cur_log_full[PATH_MAX]; // /home/john/.trashsys/log/1:myfile.txt.log - char cur_trashed_full[PATH_MAX]; // /home/john/.trashsys/trashed/1:myfile.txt - cur_log_full[0] = '\0'; - cur_trashed_full[0] = '\0'; - if(concat_str(cur_log_full, PATH_MAX, ipi->ts_path_log_withslash) == NULL - || concat_str(cur_trashed_full, PATH_MAX, ipi->ts_path_trashed_withslash) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths are too long. Continuing to next file.\n"); - return FUNCTION_FAILURE; - } - - if(concat_str(cur_log_full, REM_SZ(PATH_MAX, cur_log_full), walk->trashed_filename) == NULL - || concat_str(cur_trashed_full, REM_SZ(PATH_MAX, cur_trashed_full), walk->trashed_filename) == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths are too long. Continuing to next file.\n"); - return FUNCTION_FAILURE; - } - - if(concat_str(cur_log_full, REM_SZ(PATH_MAX, cur_log_full), ".log") == NULL) { - cvm_fprintf(v_cvm_fprintf, stdout, "Paths are too long. Continuing to next file.\n"); - return FUNCTION_FAILURE; - } - - int rnm = rename(cur_trashed_full, walk->originalpath); - int rm = remove(cur_log_full); - if(rm == -1 || rnm == -1) { - cvm_fprintf(v_cvm_fprintf, stdout, "%Failed to restore file.\nrnm: %d\nrm: %d\n", rnm, rm); - free_lfc(lfc); - return FUNCTION_FAILURE; - } - - fprintf(stdout, "Restored to: %s\n", walk->originalpath); - } - - free_lfc(lfc); - return FUNCTION_SUCCESS; -} - -int main (int argc, char *argv[]) { - - if (argc == 1) { - USAGE_OUT(stderr); - return EXIT_FAILURE; - } - - g_argv = argv[0]; - int R_mut = 0; - int C_mut = 0; - int c_mut = 0; - int L_mut = 0; - int l_mut = 0; - int y_mut = 0; - int n_mut = 0; - int f_mut = 0; - int h_mut = 0; - bool y_used = false; - bool n_used = false; - bool v_used = false; - bool f_used = false; - bool t_used = false; - bool l_used = false; - bool L_used = false; - bool c_used = false; - bool C_used = false; - bool R_used = false; - bool h_used = false; - int opt; - unsigned long long optarg_converted; - bool R_failed = false; - while ((opt = getopt(argc, argv, "ynvfatlLcCR:h")) != -1) { - switch (opt) { - case 'y': - - y_mut = 1; - y_used = true; // YES on enter - - break; - case 'n': - - n_mut = 1; - n_used = true; // NO on enter - - break; - case 'v': - - v_used = true; // Verbose debug mode - - break; - case 'f': - - f_mut = 1; - f_used = true; // choice will not ask, it will just say yes by default thus basically "forcing" it - - break; - case 't': - - t_used = true; - - break; - case 'l': - - l_mut = 1; - l_used = true; - - break; - case 'L': - - L_mut = 1; - L_used = true; - - break; - case 'c': - - c_mut = 1; - c_used = true; - - break; - case 'C': - - C_mut = 1; - C_used = true; - - break; - case 'R': { - - R_mut = 1; - R_used = true; - char *endptr = NULL; - optarg_converted = strtoull(optarg, &endptr, 10); - if(endptr == optarg) { // not valid at all - R_failed = true; - } - - if(errno == ERANGE || optarg[0] == '-') { - fprintf(stderr, "%s: ID is out of range.\n", argv[0]); - R_failed = true; - } - - if(endptr[0] != '\0' || optarg[0] == '+' || optarg[0] == '0') { // if it starts valid but ends in anything but a \0 - R_failed = true; // we know that if it ends in a \0 its valid (i hope) - } - } - break; - case 'h': - - h_mut = 1; - h_used = true; - - break; - } - } - - if((R_mut + C_mut + c_mut + L_mut + l_mut + h_mut) > 1) { - USAGE_OUT(stderr); - return EXIT_FAILURE; - } - - if((y_mut + n_mut + f_mut + h_mut) > 1) { - USAGE_OUT(stderr); - return EXIT_FAILURE; - } - - if(optind == argc && (l_used || L_used || C_used || c_used || h_used || R_used) == false) { - USAGE_OUT(stderr); - return EXIT_FAILURE; - } - - if(R_failed == true) { - USAGE_OUT(stderr); - return EXIT_FAILURE; - } - - if(h_used == true) { - USAGE_OUT_L(stderr); - return EXIT_SUCCESS; - } - - if(v_used == true) { v_cvm_fprintf = true; } // Verbose mode - cvm_fprintf(v_cvm_fprintf, stdout, "options RCcLltafvny: %d%d%d%d%d%d%d%d%d%d\n", - R_used, C_used, c_used, - L_used, l_used, t_used, - f_used, v_used, n_used, - y_used - ); - choice_mode = handle_ynf(y_used, n_used, f_used); - struct initial_path_info ipi_m; - int cctd; - if(fill_ipi(t_used, &ipi_m) == FUNCTION_FAILURE) { - fprintf(stderr, "%s: error getting paths, exiting...\n", g_argv); - return EXIT_FAILURE; - } - - cctd = check_create_ts_dirs(&ipi_m); // check for or create directories - if(cctd == FUNCTION_FAILURE) { - fprintf(stderr, "%s: error creating trashsys directories, exiting...\n", g_argv); - return EXIT_FAILURE; - } - - if(R_used == true) { - if(optind != argc) { - USAGE_OUT(stderr); - return EXIT_FAILURE; - } - - if(restore_file(optarg_converted, &ipi_m) == FUNCTION_FAILURE) { - fprintf(stderr, "%s: failed to restore file."/* Please run %s -i to check for inconsistencies."*/, g_argv/*, g_argv*/); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - - if(c_used == true) { - if(clear_old_files(30, &ipi_m)) { - fprintf(stderr, "%s: There was an error clearing old files.", g_argv); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; - } - - if(C_used == true) { - if(choice(choice_mode) == 1) { - return EXIT_SUCCESS; - } - bool errors1 = false; - bool errors2 = false; - if(clear_all_files(ipi_m.ts_path_trashed_withslash, &errors1) == FUNCTION_FAILURE || errors1 == true) { - fprintf(stderr, "%s: There was an error clearing files. Please run %s -i to check for inconsistencies.", g_argv, g_argv); - } - - if(clear_all_files(ipi_m.ts_path_log_withslash, &errors2) == FUNCTION_FAILURE || errors2 == true) { - fprintf(stderr, "%s: There was an error clearing log files. Please run %s -i to check for inconsistencies", g_argv, g_argv); - } - - return EXIT_SUCCESS; - } - - if(l_used == true || L_used == true) { - struct list_file_content *lfc = fill_lfc(&ipi_m); - struct list_file_content *walk = NULL; - int i = 1; - if(lfc == NULL) { return EXIT_SUCCESS; } - for(walk = lfc ; walk != NULL ; walk = walk->next, i++) { - lfc_formatted(walk, L_used); - } - - free_lfc(lfc); - return EXIT_SUCCESS; - } - - int index; - for (index = optind ; index < argc ; index++) { - struct trashsys_log_info tli_m; - struct dynamic_paths dp; - int tli_fi_r = tli_fill_info(&tli_m , argv[index], false, &ipi_m); - if(tli_fi_r == NOFILE) { - fprintf(stderr, "%s: error '%s': No such file or directory\n", basename(argv[0]), basename(argv[index])); - continue; - - } else if(tli_fi_r == FUNCTION_FAILURE) { - fprintf(stderr, "%s: cannot process paths\n", basename(argv[0])); - continue; - } - - if(fill_dynamic_paths(&ipi_m, &tli_m, &dp) == -1) { - fprintf(stderr, "%s: cannot process paths\n", basename(argv[0])); - continue; - } - - if(write_log_file(&dp, &tli_m, t_used) == -1) { - fprintf(stderr, "%s: cannot create logfile\n", basename(argv[0])); - continue; - } - - if(rename(dp.old_trashfile_path, dp.new_trashfile_path) == -1) { - continue; - } - - cvm_fprintf(v_cvm_fprintf, stdout, "ID: %ld\nfull original path: %s\noriginal filename: %s\ntime: %ld\ntmp: %d\nsize: %ld\nnew trashed filename: %s\n" - , tli_m.ts_log_id - , tli_m.ts_log_originalpath - , tli_m.ts_log_filename - , tli_m.ts_log_trashtime - , tli_m.ts_log_tmp - , tli_m.ts_log_filesize - , dp.new_trashfile_filename - ); - } - - return EXIT_SUCCESS; -} |