From 4af0415e73e8d7af1fd0213decf48e511308d2ba Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Sat, 3 Jun 2017 12:21:50 +0200 Subject: [PATCH 1/6] Initial --- CMakeLists.txt | 4 +- src/error.c | 4 +- src/helper.c | 11 ++- src/optparse.c | 12 ++-- src/utils.c | 177 ++++++++++++++++++++++++------------------------- 5 files changed, 106 insertions(+), 102 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9bddd6..e613397 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ project(caesiumclt) # The version number. set(VERSION_MAJOR 0) -set(VERSION_MINOR 10) -set(VERSION_PATCH 2) +set(VERSION_MINOR 11) +set(VERSION_PATCH 0) configure_file( "src/config.h.in" diff --git a/src/error.c b/src/error.c index cc1b898..e2e6b21 100644 --- a/src/error.c +++ b/src/error.c @@ -39,9 +39,9 @@ const char *get_error_message(int code) case 9: return "Input files provided. Cannot mix them with a folder."; case 10: - return "-R is useless on files."; + return "-R has no effects on files."; case 11: - return "-S is useless without -R."; + return "-S has no effect without -R."; case 12: return "Cannot set output folder inside the input one"; diff --git a/src/helper.c b/src/helper.c index 4f73aaa..26912e9 100644 --- a/src/helper.c +++ b/src/helper.c @@ -18,6 +18,7 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) struct optparse_long longopts[] = { {"quality", 'q', OPTPARSE_REQUIRED}, {"exif", 'e', OPTPARSE_NONE}, + {"progressive", 'p', OPTPARSE_NONE}, {"output", 'o', OPTPARSE_REQUIRED}, {"recursive", 'R', OPTPARSE_NONE}, {"keep-structure", 'S', OPTPARSE_NONE}, @@ -37,6 +38,8 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) break; case 'e': options->jpeg.exif_copy = true; + case 'p': + options->jpeg.progressive = false; break; case 'o': if (opts.optarg[strlen(opts.optarg) - 1] == '/' || opts.optarg[strlen(opts.optarg) - 1] == '\\') { @@ -76,7 +79,7 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) while ((arg = optparse_arg(&opts))) { if (folders_flag) { display_error(WARNING, 8); - continue; + break; } //Check if it's a directory and add its content if (is_directory(arg)) { @@ -155,9 +158,11 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) size_t index = strspn(options->input_folder, options->input_files[i]) + 1; size_t size = strlen(options->input_files[i]) - index - strlen(filename); char output_full_folder[strlen(options->output_folder) + size + 1]; - snprintf(output_full_folder, strlen(options->output_folder) + size + 1, "%s%s", options->output_folder, &options->input_files[i][index]); + snprintf(output_full_folder, strlen(options->output_folder) + size + 1, "%s%s", options->output_folder, + &options->input_files[i][index]); output_full_path = malloc((strlen(output_full_folder) + strlen(filename) + 1) * sizeof(char)); - snprintf(output_full_path, strlen(output_full_folder) + strlen(filename) + 1, "%s%s", output_full_folder, filename); + snprintf(output_full_path, strlen(output_full_folder) + strlen(filename) + 1, "%s%s", output_full_folder, + filename); mkpath(output_full_folder); } diff --git a/src/optparse.c b/src/optparse.c index 9804d99..78ecb8e 100644 --- a/src/optparse.c +++ b/src/optparse.c @@ -99,11 +99,6 @@ int optparse(struct optparse *options, const char *optstring) int type = argtype(optstring, option[0]); char *next = options->argv[options->optind + 1]; switch (type) { - case -1: { - options->optind++; - char str[2] = {option[0]}; - return opterror(options, MSG_INVALID, str); - } case OPTPARSE_NONE: if (option[1]) { options->subopt++; @@ -134,8 +129,13 @@ int optparse(struct optparse *options, const char *optstring) else options->optarg = 0; return option[0]; + default: + case -1: { + options->optind++; + char str[2] = {option[0]}; + return opterror(options, MSG_INVALID, str); + } } - return 0; } char *optparse_arg(struct optparse *options) diff --git a/src/utils.c b/src/utils.c index 9913ef0..654d51c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -19,6 +19,7 @@ void print_help() "Options:\n" "\t-q, --quality\t\tset output file quality between [0-100], 0 for optimization\n" "\t-e, --exif\t\tkeeps EXIF info during compression\n" + "\t-p, --progressive\t\toutputs a progressive JPEG\n" "\t-o, --output\t\toutput folder\n" "\t-R, --recursive\t\tif input is a folder, scan subfolders too\n" "\t-S, --keep-structure\tkeep the folder structure, use with -R\n" @@ -30,18 +31,18 @@ void print_help() bool is_directory(const char *path) { #ifdef _WIN32 - tinydir_dir dir; + tinydir_dir dir; - return tinydir_open(&dir, path) != -1; + return tinydir_open(&dir, path) != -1; #else - tinydir_file file; + tinydir_file file; - if (tinydir_file_open(&file, path) == -1) { - display_error(ERROR, 6); - } + if (tinydir_file_open(&file, path) == -1) { + display_error(ERROR, 6); + } - return (bool) file.is_dir; + return (bool) file.is_dir; #endif } @@ -62,10 +63,10 @@ int scan_folder(const char *directory, cclt_options *options, bool recursive) } else { options->input_files = realloc(options->input_files, (options->files_count + 1) * sizeof(char *)); options->input_files[options->files_count] = malloc((strlen(file.path) + 1) * sizeof(char)); - snprintf(options->input_files[options->files_count], - strlen(file.path) + 1, "%s", file.path); + snprintf(options->input_files[options->files_count], + strlen(file.path) + 1, "%s", file.path); #ifdef _WIN32 - options->input_files[options->files_count] = str_replace(options->input_files[options->files_count], "/", "\\"); + options->input_files[options->files_count] = str_replace(options->input_files[options->files_count], "/", "\\"); #endif options->files_count++; n++; @@ -107,13 +108,11 @@ char *get_filename(char *full_path) //Get just the filename tofree = strdup(full_path); - //TODO change to strncpy - strcpy(tofree, full_path); - //TODO Windows? + snprintf(tofree, strlen(full_path) + 1, "%s", full_path); #ifdef _WIN32 - while ((token = strsep(&tofree, "\\")) != NULL) { + while ((token = strsep(&tofree, "\\")) != NULL) { #else - while ((token = strsep(&tofree, "/")) != NULL) { + while ((token = strsep(&tofree, "/")) != NULL) { #endif if (tofree == NULL) { break; @@ -127,15 +126,15 @@ char *get_filename(char *full_path) off_t get_file_size(const char *path) { - FILE *f = fopen(path, "rb"); - if (f == NULL) { - display_error(ERROR, 7); - } - fseek(f, 0, SEEK_END); - unsigned long len = (unsigned long)ftell(f); - fclose(f); + FILE *f = fopen(path, "rb"); + if (f == NULL) { + display_error(ERROR, 7); + } + fseek(f, 0, SEEK_END); + off_t len = ftell(f); + fclose(f); - return len; + return len; } char *get_human_size(off_t size) @@ -160,86 +159,86 @@ char *get_human_size(off_t size) #ifdef _WIN32 char *str_replace(char *orig, char *rep, char *with) { - char *result; // the return string - char *ins; // the next insert point - char *tmp; // varies - int len_rep; // length of rep (the string to remove) - int len_with; // length of with (the string to replace rep with) - int len_front; // distance between rep and end of last rep - int count; // number of replacements + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements - if (!orig || !rep) - return NULL; - len_rep = strlen(rep); - if (len_rep == 0) - return NULL; - if (!with) - with = ""; - len_with = strlen(with); + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; + if (!with) + with = ""; + len_with = strlen(with); - ins = orig; - for (count = 0; tmp = strstr(ins, rep); ++count) { - ins = tmp + len_rep; - } + ins = orig; + for (count = 0; tmp = strstr(ins, rep); ++count) { + ins = tmp + len_rep; + } - tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); - if (!result) - return NULL; + if (!result) + return NULL; - while (count--) { - ins = strstr(orig, rep); - len_front = ins - orig; - tmp = strncpy(tmp, orig, len_front) + len_front; - tmp = strcpy(tmp, with) + len_with; - orig += len_front + len_rep; - } - strcpy(tmp, orig); - return result; + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; + } + strcpy(tmp, orig); + return result; } char *strsep (char **stringp, const char *delim) { - char *begin, *end; + char *begin, *end; - begin = *stringp; - if (begin == NULL) - return NULL; + begin = *stringp; + if (begin == NULL) + return NULL; - /* A frequent case is when the delimiter string contains only one - character. Here we don't need to call the expensive `strpbrk' - function and instead work using `strchr'. */ - if (delim[0] == '\0' || delim[1] == '\0') - { - char ch = delim[0]; + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if (delim[0] == '\0' || delim[1] == '\0') + { + char ch = delim[0]; - if (ch == '\0') - end = NULL; - else - { - if (*begin == ch) - end = begin; - else if (*begin == '\0') - end = NULL; - else - end = strchr (begin + 1, ch); - } - } - else - /* Find the end of the token. */ - end = strpbrk (begin, delim); + if (ch == '\0') + end = NULL; + else + { + if (*begin == ch) + end = begin; + else if (*begin == '\0') + end = NULL; + else + end = strchr (begin + 1, ch); + } + } + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); - if (end) - { - /* Terminate the token and set *STRINGP past NUL character. */ - *end++ = '\0'; - *stringp = end; - } - else - /* No more delimiters; this is the last token. */ - *stringp = NULL; + if (end) + { + /* Terminate the token and set *STRINGP past NUL character. */ + *end++ = '\0'; + *stringp = end; + } + else + /* No more delimiters; this is the last token. */ + *stringp = NULL; - return begin; + return begin; } #endif From 77ad35ef509941a5e07c9625f6fe64709ef2f73b Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Mon, 5 Jun 2017 09:28:10 +0200 Subject: [PATCH 2/6] Working on filter --- README.md | 4 ++-- src/helper.c | 40 ++++++++++++++++++++++++++++++++++++---- src/helper.h | 1 + src/main.c | 2 +- src/utils.c | 38 +++++++++++++++++++++++++++++++++++++- src/utils.h | 6 ++++++ 6 files changed, 83 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 314cb3f..b4057b2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## Caesium CommandLineTools -##### caesium-clt - v0.10.2-beta (build 20170318) - Copyright © Matteo Paonessa, 2017. All Rights Reserved. +##### caesium-clt - v0.11.0-beta (build 20170604) - Copyright © Matteo Paonessa, 2017. All Rights Reserved. [![Build Status](https://travis-ci.org/Lymphatus/caesium-clt.svg?branch=master)](https://travis-ci.org/Lymphatus/caesium-clt) ---------- @@ -13,7 +13,7 @@ ---------- ###### TESTED PLATFORMS -* Mac OS X Sierra (v10.12.3) +* Mac OS X Sierra (v10.12.5) * Ubuntu 16.04 * Windows 10 diff --git a/src/helper.c b/src/helper.c index 26912e9..84acc8d 100644 --- a/src/helper.c +++ b/src/helper.c @@ -18,10 +18,10 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) struct optparse_long longopts[] = { {"quality", 'q', OPTPARSE_REQUIRED}, {"exif", 'e', OPTPARSE_NONE}, - {"progressive", 'p', OPTPARSE_NONE}, {"output", 'o', OPTPARSE_REQUIRED}, {"recursive", 'R', OPTPARSE_NONE}, {"keep-structure", 'S', OPTPARSE_NONE}, + {"filter", 'f', OPTPARSE_REQUIRED}, {"version", 'v', OPTPARSE_NONE}, {"help", 'h', OPTPARSE_NONE}, {0} @@ -60,6 +60,9 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) case 'S': parameters.keep_structure = true; break; + case 'f': + parameters.filters = get_filters(opts.optarg); + break; case 'v': fprintf(stdout, "%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); exit(EXIT_SUCCESS); @@ -85,7 +88,16 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) if (is_directory(arg)) { if (!files_flag) { folders_flag = true; - parameters.input_folder = strdup(arg); + if (arg[strlen(arg) - 1] == '/' || arg[strlen(arg) - 1] == '\\') { + parameters.input_folder = strdup(arg); + } else { + parameters.input_folder = malloc((strlen(arg) + 2) * sizeof(char)); +#ifdef _WIN32 + snprintf(parameters.input_folder, (strlen(arg) + 2), "%s\\", arg); +#else + snprintf(parameters.input_folder, (strlen(arg) + 2), "%s/", arg); +#endif + } int count = 0; count = scan_folder(arg, ¶meters, parameters.recursive); if (count == 0) { @@ -105,8 +117,10 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) } //Check if the output folder is a subfolder of the input to avoid infinite loops + //However, if the folders are the same, we can let it go as it will overwrite the files if (folders_flag) { - if (strstr(parameters.output_folder, parameters.input_folder) != NULL) { + if (strstr(parameters.output_folder, parameters.input_folder) != NULL + && strcmp(parameters.output_folder, parameters.input_folder) != 0) { display_error(ERROR, 12); } } @@ -141,7 +155,9 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) for (int i = 0; i < options->files_count; i++) { char *filename = get_filename(options->input_files[i]); - char *output_full_path; + char *output_full_path = NULL; + char *original_output_full_path = NULL; + bool overwriting = false; //If we don't need to keep the structure, we put all the files in one folder by just the filename if (!options->keep_structure) { output_full_path = malloc((strlen(filename) + strlen(options->output_folder) + 1) * sizeof(char)); @@ -158,11 +174,13 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) size_t index = strspn(options->input_folder, options->input_files[i]) + 1; size_t size = strlen(options->input_files[i]) - index - strlen(filename); char output_full_folder[strlen(options->output_folder) + size + 1]; + snprintf(output_full_folder, strlen(options->output_folder) + size + 1, "%s%s", options->output_folder, &options->input_files[i][index]); output_full_path = malloc((strlen(output_full_folder) + strlen(filename) + 1) * sizeof(char)); snprintf(output_full_path, strlen(output_full_folder) + strlen(filename) + 1, "%s%s", output_full_folder, filename); + mkpath(output_full_folder); } @@ -172,6 +190,14 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) filename, output_full_path); + //If the file already exist, create a temporary file + if (file_exists(output_full_path)) { + original_output_full_path = strdup(output_full_path); + output_full_path = realloc(output_full_path, (strlen(output_full_path) + 4) * sizeof(char)); + snprintf(output_full_path, (strlen(original_output_full_path) + 4), "%s.cs", original_output_full_path); + overwriting = true; + } + input_file_size = get_file_size(options->input_files[i]); options->input_total_size += input_file_size; if (cs_compress(options->input_files[i], output_full_path, parameters)) { @@ -190,6 +216,12 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) options->input_total_size -= get_file_size(options->input_files[i]); } + //Rename if we were overwriting + if (overwriting) { + rename(output_full_path, original_output_full_path); + } + + free(original_output_full_path); free(output_full_path); } diff --git a/src/helper.h b/src/helper.h index 28accbe..5707dfc 100644 --- a/src/helper.h +++ b/src/helper.h @@ -13,6 +13,7 @@ typedef struct cclt_options int files_count; off_t input_total_size; off_t output_total_size; + char **filters; } cclt_options; cclt_options parse_arguments(char *argv[], cs_image_pars *options); diff --git a/src/main.c b/src/main.c index 3dd7df1..3185016 100755 --- a/src/main.c +++ b/src/main.c @@ -7,7 +7,7 @@ int main(int argc, char *argv[]) { - //Exit if no arguments + //Exit if less than 2 arguments if (argc < 2) { print_help(); exit(EXIT_FAILURE); diff --git a/src/utils.c b/src/utils.c index 654d51c..0601f83 100644 --- a/src/utils.c +++ b/src/utils.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "utils.h" #include "tinydir.h" #include "error.h" @@ -23,6 +24,7 @@ void print_help() "\t-o, --output\t\toutput folder\n" "\t-R, --recursive\t\tif input is a folder, scan subfolders too\n" "\t-S, --keep-structure\tkeep the folder structure, use with -R\n" + "\t-f, --filter\t\tfilter by image format (eg. jpg or png)\n" "\t-h, --help\t\tdisplay this help and exit\n" "\t-v, --version\t\toutput version information and exit\n\n"); exit(EXIT_SUCCESS); @@ -108,7 +110,6 @@ char *get_filename(char *full_path) //Get just the filename tofree = strdup(full_path); - snprintf(tofree, strlen(full_path) + 1, "%s", full_path); #ifdef _WIN32 while ((token = strsep(&tofree, "\\")) != NULL) { #else @@ -157,6 +158,41 @@ char *get_human_size(off_t size) return final; } +bool file_exists(const char* file_path) +{ + struct stat buffer; + return (stat(file_path, &buffer) == 0); +} + +char **get_filters(const char *command_line_filter) +{ + char** result = NULL; + char* token = NULL; + char* toFree = strdup(command_line_filter); + int i = 0; + + while ((token = strsep(&toFree, ",")) != NULL) { + result = realloc(result, (i + 1) * sizeof(char*)); + result[i] = strdup(token); + i++; + } + + for (int j = 0; j < i; j++) { + printf(result[j]); + } + + free(toFree); + free(token); + + return result; +} + +char *strtolower(char *string) +{ + for ( ; *string; ++string) *string = (char) tolower(*string); + return string; +} + #ifdef _WIN32 char *str_replace(char *orig, char *rep, char *with) { char *result; // the return string diff --git a/src/utils.h b/src/utils.h index 9942b8d..dbee235 100644 --- a/src/utils.h +++ b/src/utils.h @@ -21,6 +21,12 @@ char* get_human_size(off_t size); int mkpath(const char *pathname); +bool file_exists(const char* file_path); + +char** get_filters(const char* command_line_filter); + +char* strtolower(char* string); + #ifdef _WIN32 char *str_replace(char *orig, char *rep, char *with); char *strsep(char **stringp, const char *delim); From a0cd63209892ba4b151146f7a3bb2595552a3366 Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Fri, 10 Nov 2017 01:58:34 +0100 Subject: [PATCH 3/6] Path resolving fixings Still a bug with '~' operator --- README.md | 4 +- src/helper.c | 113 +++++++++++++++++++++++++++++++-------------------- src/helper.h | 13 ++++-- src/main.c | 4 +- src/utils.c | 34 ++-------------- src/utils.h | 4 -- 6 files changed, 86 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index b4057b2..0f8592a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## Caesium CommandLineTools -##### caesium-clt - v0.11.0-beta (build 20170604) - Copyright © Matteo Paonessa, 2017. All Rights Reserved. +##### caesium-clt - v0.11.0-beta (build 20171109) - Copyright © Matteo Paonessa, 2017. All Rights Reserved. [![Build Status](https://travis-ci.org/Lymphatus/caesium-clt.svg?branch=master)](https://travis-ci.org/Lymphatus/caesium-clt) ---------- @@ -13,7 +13,7 @@ ---------- ###### TESTED PLATFORMS -* Mac OS X Sierra (v10.12.5) +* Mac OS X Sierra (v10.13.0) * Ubuntu 16.04 * Windows 10 diff --git a/src/helper.c b/src/helper.c index 84acc8d..d81d10a 100644 --- a/src/helper.c +++ b/src/helper.c @@ -1,6 +1,15 @@ #include #include #include + +#ifdef _WIN32 +#include +#include +#define getcwd _getcwd +#else +#include +#endif + #include "helper.h" #include "optparse.h" #include "utils.h" @@ -11,7 +20,7 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) { struct optparse opts; //Initialize application options - cclt_options parameters = {NULL, NULL, false, false, 0, 0, 0}; + cclt_options parameters = {NULL, "", "", false, false, 0, 0, 0, false}; //Parse command line args optparse_init(&opts, argv); @@ -21,13 +30,13 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) {"output", 'o', OPTPARSE_REQUIRED}, {"recursive", 'R', OPTPARSE_NONE}, {"keep-structure", 'S', OPTPARSE_NONE}, - {"filter", 'f', OPTPARSE_REQUIRED}, + {"dry-run", 'd', OPTPARSE_NONE}, {"version", 'v', OPTPARSE_NONE}, {"help", 'h', OPTPARSE_NONE}, {0} }; - int option; + int option; while ((option = optparse_long(&opts, longopts, NULL)) != -1) { switch (option) { case 'q': @@ -42,17 +51,22 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) options->jpeg.progressive = false; break; case 'o': - if (opts.optarg[strlen(opts.optarg) - 1] == '/' || opts.optarg[strlen(opts.optarg) - 1] == '\\') { - parameters.output_folder = malloc((strlen(opts.optarg) + 1) * sizeof(char)); - snprintf(parameters.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg); - } else { - parameters.output_folder = malloc((strlen(opts.optarg) + 2) * sizeof(char)); -#ifdef _WIN32 - snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s\\", opts.optarg); -#else - snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s/", opts.optarg); -#endif + realpath(opts.optarg, parameters.output_folder); + //TODO Resolve ~ + if (opts.optarg[0] == '~') { + snprintf(parameters.output_folder, strlen(parameters.output_folder), "%s", parameters.output_folder); } +// if (opts.optarg[strlen(opts.optarg) - 1] == '/' || opts.optarg[strlen(opts.optarg) - 1] == '\\') { +// snprintf(parameters.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg); +// } else { +//#ifdef _WIN32 +// snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s\\", opts.optarg); +//#else +// snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s/", opts.optarg); +//#endif +// } + + //Prepend the current directory if necessary break; case 'R': parameters.recursive = true; @@ -60,8 +74,8 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) case 'S': parameters.keep_structure = true; break; - case 'f': - parameters.filters = get_filters(opts.optarg); + case 'd': + parameters.dry_run = true; break; case 'v': fprintf(stdout, "%d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); @@ -79,27 +93,35 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) //Remaining arguments char *arg; bool files_flag = false, folders_flag = false; + char resolved_path[MAX_PATH_SIZE]; while ((arg = optparse_arg(&opts))) { if (folders_flag) { display_error(WARNING, 8); break; } + //Check if it's a directory and add its content - if (is_directory(arg)) { + realpath(arg, resolved_path); + //TODO Resolve ~ + if (arg[0] == '~') { + snprintf(resolved_path, strlen(resolved_path), "%s", resolved_path); + } + if (is_directory(resolved_path)) { if (!files_flag) { folders_flag = true; - if (arg[strlen(arg) - 1] == '/' || arg[strlen(arg) - 1] == '\\') { - parameters.input_folder = strdup(arg); - } else { - parameters.input_folder = malloc((strlen(arg) + 2) * sizeof(char)); -#ifdef _WIN32 - snprintf(parameters.input_folder, (strlen(arg) + 2), "%s\\", arg); -#else - snprintf(parameters.input_folder, (strlen(arg) + 2), "%s/", arg); -#endif - } + snprintf(parameters.input_folder, strlen(resolved_path) + 1, "%s", resolved_path); +// if (arg[strlen(arg) - 1] == '/' || arg[strlen(arg) - 1] == '\\') { +// parameters.input_folder = strdup(arg); +// } else { +// parameters.input_folder = malloc((strlen(arg) + 2) * sizeof(char)); +//#ifdef _WIN32 +// snprintf(parameters.input_folder, (strlen(arg) + 2), "%s\\", arg); +//#else +// snprintf(parameters.input_folder, (strlen(arg) + 2), "%s/", arg); +//#endif +// } int count = 0; - count = scan_folder(arg, ¶meters, parameters.recursive); + count = scan_folder(resolved_path, ¶meters, parameters.recursive); if (count == 0) { display_error(WARNING, 3); } @@ -108,7 +130,6 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) } } else { files_flag = true; - parameters.input_folder = NULL; parameters.input_files = realloc(parameters.input_files, (parameters.files_count + 1) * sizeof(char *)); parameters.input_files[parameters.files_count] = malloc((strlen(arg) + 1) * sizeof(char)); snprintf(parameters.input_files[parameters.files_count], strlen(arg) + 1, "%s", arg); @@ -171,12 +192,12 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) * A piece of cake <3 */ - size_t index = strspn(options->input_folder, options->input_files[i]) + 1; + size_t index = strspn(options->input_folder, options->input_files[i]); size_t size = strlen(options->input_files[i]) - index - strlen(filename); char output_full_folder[strlen(options->output_folder) + size + 1]; - snprintf(output_full_folder, strlen(options->output_folder) + size + 1, "%s%s", options->output_folder, - &options->input_files[i][index]); + snprintf(output_full_folder, strlen(options->output_folder) + size + 1, "%s%s", + options->output_folder, &options->input_files[i][index]); output_full_path = malloc((strlen(output_full_folder) + strlen(filename) + 1) * sizeof(char)); snprintf(output_full_path, strlen(output_full_folder) + strlen(filename) + 1, "%s%s", output_full_folder, filename); @@ -200,24 +221,28 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) input_file_size = get_file_size(options->input_files[i]); options->input_total_size += input_file_size; - if (cs_compress(options->input_files[i], output_full_path, parameters)) { - compressed_files++; - output_file_size = get_file_size(output_full_path); - options->output_total_size += output_file_size; - char *human_input_size = get_human_size(input_file_size); - char *human_output_size = get_human_size(output_file_size); + //Prevent compression if running in dry mode + if (!options->dry_run) { + if (cs_compress(options->input_files[i], output_full_path, parameters)) { + compressed_files++; + output_file_size = get_file_size(output_full_path); + options->output_total_size += output_file_size; - fprintf(stdout, "%s -> %s [%.2f%%]\n", - human_input_size, - human_output_size, - ((float) output_file_size - input_file_size) * 100 / input_file_size); - } else { - options->input_total_size -= get_file_size(options->input_files[i]); + char *human_input_size = get_human_size(input_file_size); + char *human_output_size = get_human_size(output_file_size); + + fprintf(stdout, "%s -> %s [%.2f%%]\n", + human_input_size, + human_output_size, + ((float) output_file_size - input_file_size) * 100 / input_file_size); + } else { + options->input_total_size -= get_file_size(options->input_files[i]); + } } //Rename if we were overwriting - if (overwriting) { + if (overwriting && !options->dry_run) { rename(output_full_path, original_output_full_path); } diff --git a/src/helper.h b/src/helper.h index 5707dfc..23baa21 100644 --- a/src/helper.h +++ b/src/helper.h @@ -3,17 +3,24 @@ #include +#ifdef _WIN32 +#define MAX_PATH_SIZE _MAX_PATH +#else +#include +#define MAX_PATH_SIZE PATH_MAX +#endif + typedef struct cclt_options { char **input_files; - char *input_folder; - char *output_folder; + char input_folder[MAX_PATH_SIZE]; + char output_folder[MAX_PATH_SIZE]; bool recursive; bool keep_structure; int files_count; off_t input_total_size; off_t output_total_size; - char **filters; + bool dry_run; } cclt_options; cclt_options parse_arguments(char *argv[], cs_image_pars *options); diff --git a/src/main.c b/src/main.c index 3185016..f25c067 100755 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,8 @@ #include #include "utils.h" +#include + int main(int argc, char *argv[]) { @@ -28,9 +30,7 @@ int main(int argc, char *argv[]) start_compression(&options, &compress_options); //Cleanup the two memory allocated objects - free(options.output_folder); free(options.input_files); - free(options.input_folder); //Get the difference diff = clock() - start; diff --git a/src/utils.c b/src/utils.c index 0601f83..4980e03 100644 --- a/src/utils.c +++ b/src/utils.c @@ -5,6 +5,7 @@ #include #include #include + #include "utils.h" #include "tinydir.h" #include "error.h" @@ -24,7 +25,7 @@ void print_help() "\t-o, --output\t\toutput folder\n" "\t-R, --recursive\t\tif input is a folder, scan subfolders too\n" "\t-S, --keep-structure\tkeep the folder structure, use with -R\n" - "\t-f, --filter\t\tfilter by image format (eg. jpg or png)\n" + "\t-d, --dry-run\t\tdo not really compress files but just show output paths\n" "\t-h, --help\t\tdisplay this help and exit\n" "\t-v, --version\t\toutput version information and exit\n\n"); exit(EXIT_SUCCESS); @@ -158,41 +159,12 @@ char *get_human_size(off_t size) return final; } -bool file_exists(const char* file_path) +bool file_exists(const char *file_path) { struct stat buffer; return (stat(file_path, &buffer) == 0); } -char **get_filters(const char *command_line_filter) -{ - char** result = NULL; - char* token = NULL; - char* toFree = strdup(command_line_filter); - int i = 0; - - while ((token = strsep(&toFree, ",")) != NULL) { - result = realloc(result, (i + 1) * sizeof(char*)); - result[i] = strdup(token); - i++; - } - - for (int j = 0; j < i; j++) { - printf(result[j]); - } - - free(toFree); - free(token); - - return result; -} - -char *strtolower(char *string) -{ - for ( ; *string; ++string) *string = (char) tolower(*string); - return string; -} - #ifdef _WIN32 char *str_replace(char *orig, char *rep, char *with) { char *result; // the return string diff --git a/src/utils.h b/src/utils.h index dbee235..87de3c6 100644 --- a/src/utils.h +++ b/src/utils.h @@ -23,10 +23,6 @@ int mkpath(const char *pathname); bool file_exists(const char* file_path); -char** get_filters(const char* command_line_filter); - -char* strtolower(char* string); - #ifdef _WIN32 char *str_replace(char *orig, char *rep, char *with); char *strsep(char **stringp, const char *delim); From a0f1a34f1428812dc9acc4cad43ebd93478c2cc0 Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Sun, 12 Nov 2017 12:29:10 +0100 Subject: [PATCH 4/6] Fixing paths --- .gitignore | 161 ++++++++++++++++++- .idea/.name | 1 + .idea/caesium-clt.iml | 2 + .idea/inspectionProfiles/Project_Default.xml | 125 ++++++++++++++ .idea/misc.xml | 12 ++ .idea/modules.xml | 8 + .idea/scopes/Inspection.xml | 3 + .idea/vcs.xml | 6 + src/helper.c | 60 +++---- src/main.c | 4 +- src/utils.c | 6 +- 11 files changed, 347 insertions(+), 41 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/caesium-clt.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/scopes/Inspection.xml create mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index f567c79..8ef00d0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,163 @@ Thumbs.db .Spotlight-V100 .Trashes -.idea +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake cmake-build-* -build \ No newline at end of file + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### macOS template +# General +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.TemporaryItems +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk +### Linux template +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Windows template +# Windows thumbnail cache files +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk +### C template +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf \ No newline at end of file diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..572ef0b --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +caesiumclt \ No newline at end of file diff --git a/.idea/caesium-clt.iml b/.idea/caesium-clt.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/caesium-clt.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..ecc50f5 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,125 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..81967a4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..96d27b3 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/scopes/Inspection.xml b/.idea/scopes/Inspection.xml new file mode 100644 index 0000000..7eb5c79 --- /dev/null +++ b/.idea/scopes/Inspection.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/helper.c b/src/helper.c index d81d10a..61c37e0 100644 --- a/src/helper.c +++ b/src/helper.c @@ -7,7 +7,7 @@ #include #define getcwd _getcwd #else -#include + #endif #include "helper.h" @@ -40,33 +40,27 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) while ((option = optparse_long(&opts, longopts, NULL)) != -1) { switch (option) { case 'q': - options->jpeg.quality = atoi(opts.optarg); + options->jpeg.quality = (int)strtol(opts.optarg, (char **)NULL, 10);; if (options->jpeg.quality < 0 || options->jpeg.quality > 100) { display_error(ERROR, 1); } break; case 'e': options->jpeg.exif_copy = true; - case 'p': - options->jpeg.progressive = false; - break; case 'o': - realpath(opts.optarg, parameters.output_folder); - //TODO Resolve ~ if (opts.optarg[0] == '~') { - snprintf(parameters.output_folder, strlen(parameters.output_folder), "%s", parameters.output_folder); + if (opts.optarg[strlen(opts.optarg) - 1] == '/' || opts.optarg[strlen(opts.optarg) - 1] == '\\') { + snprintf(parameters.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg); + } else { +#ifdef _WIN32 + snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s\\", opts.optarg); +#else + snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s/", opts.optarg); +#endif + } + } else { + realpath(opts.optarg, parameters.output_folder); } -// if (opts.optarg[strlen(opts.optarg) - 1] == '/' || opts.optarg[strlen(opts.optarg) - 1] == '\\') { -// snprintf(parameters.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg); -// } else { -//#ifdef _WIN32 -// snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s\\", opts.optarg); -//#else -// snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s/", opts.optarg); -//#endif -// } - - //Prepend the current directory if necessary break; case 'R': parameters.recursive = true; @@ -89,7 +83,6 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) display_error(ERROR, 2); } } - //Remaining arguments char *arg; bool files_flag = false, folders_flag = false; @@ -101,25 +94,23 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) } //Check if it's a directory and add its content - realpath(arg, resolved_path); - //TODO Resolve ~ if (arg[0] == '~') { - snprintf(resolved_path, strlen(resolved_path), "%s", resolved_path); + if (arg[strlen(arg) - 1] == '/' || arg[strlen(arg) - 1] == '\\') { + snprintf(resolved_path, strlen(arg), "%s", arg); + } else { +#ifdef _WIN32 + snprintf(resolved_path, strlen(arg) + 1, "%s\\", arg); +#else + snprintf(resolved_path, strlen(arg) + 1, "%s/", arg); +#endif + } + } else { + realpath(arg, resolved_path); } if (is_directory(resolved_path)) { if (!files_flag) { folders_flag = true; snprintf(parameters.input_folder, strlen(resolved_path) + 1, "%s", resolved_path); -// if (arg[strlen(arg) - 1] == '/' || arg[strlen(arg) - 1] == '\\') { -// parameters.input_folder = strdup(arg); -// } else { -// parameters.input_folder = malloc((strlen(arg) + 2) * sizeof(char)); -//#ifdef _WIN32 -// snprintf(parameters.input_folder, (strlen(arg) + 2), "%s\\", arg); -//#else -// snprintf(parameters.input_folder, (strlen(arg) + 2), "%s/", arg); -//#endif -// } int count = 0; count = scan_folder(resolved_path, ¶meters, parameters.recursive); if (count == 0) { @@ -199,7 +190,8 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) snprintf(output_full_folder, strlen(options->output_folder) + size + 1, "%s%s", options->output_folder, &options->input_files[i][index]); output_full_path = malloc((strlen(output_full_folder) + strlen(filename) + 1) * sizeof(char)); - snprintf(output_full_path, strlen(output_full_folder) + strlen(filename) + 1, "%s%s", output_full_folder, + snprintf(output_full_path, strlen(output_full_folder) + strlen(filename) + 1, "%s%s", + output_full_folder, filename); mkpath(output_full_folder); diff --git a/src/main.c b/src/main.c index f25c067..d4e47e8 100755 --- a/src/main.c +++ b/src/main.c @@ -4,8 +4,6 @@ #include #include "utils.h" -#include - int main(int argc, char *argv[]) { @@ -29,7 +27,7 @@ int main(int argc, char *argv[]) start_compression(&options, &compress_options); - //Cleanup the two memory allocated objects + //Cleanup the memory allocated objects free(options.input_files); //Get the difference diff --git a/src/utils.c b/src/utils.c index 4980e03..5afb0fe 100644 --- a/src/utils.c +++ b/src/utils.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "utils.h" #include "tinydir.h" @@ -21,7 +20,6 @@ void print_help() "Options:\n" "\t-q, --quality\t\tset output file quality between [0-100], 0 for optimization\n" "\t-e, --exif\t\tkeeps EXIF info during compression\n" - "\t-p, --progressive\t\toutputs a progressive JPEG\n" "\t-o, --output\t\toutput folder\n" "\t-R, --recursive\t\tif input is a folder, scan subfolders too\n" "\t-S, --keep-structure\tkeep the folder structure, use with -R\n" @@ -141,6 +139,10 @@ off_t get_file_size(const char *path) char *get_human_size(off_t size) { + if (size == 0) { + return "0.00 B"; + } + //We should not get more than TB images char *unit[5] = {"B", "KB", "MB", "GB", "TB"}; //Index of the array containing the correct unit From 67d1d3e85300b00b568a400278f7a87c3fc5e72c Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Sun, 12 Nov 2017 13:21:44 +0100 Subject: [PATCH 5/6] Not getting file size does not make the program exit --- src/helper.c | 31 +++++++++++++++---------------- src/utils.c | 3 ++- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/helper.c b/src/helper.c index 61c37e0..e7fdad5 100644 --- a/src/helper.c +++ b/src/helper.c @@ -1,15 +1,9 @@ #include #include #include - #ifdef _WIN32 #include -#include -#define getcwd _getcwd -#else - #endif - #include "helper.h" #include "optparse.h" #include "utils.h" @@ -49,18 +43,17 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) options->jpeg.exif_copy = true; case 'o': if (opts.optarg[0] == '~') { - if (opts.optarg[strlen(opts.optarg) - 1] == '/' || opts.optarg[strlen(opts.optarg) - 1] == '\\') { - snprintf(parameters.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg); - } else { -#ifdef _WIN32 - snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s\\", opts.optarg); -#else - snprintf(parameters.output_folder, strlen(opts.optarg) + 2, "%s/", opts.optarg); -#endif - } + snprintf(parameters.output_folder, strlen(opts.optarg) + 1, "%s", opts.optarg); } else { realpath(opts.optarg, parameters.output_folder); } + if (parameters.output_folder[strlen(opts.optarg) - 1] != '/' && parameters.output_folder[strlen(opts.optarg) - 1] != '\\') { +#ifdef _WIN32 + snprintf(parameters.output_folder, strlen(parameters.output_folder) + 2, "%s\\", parameters.output_folder); +#else + snprintf(parameters.output_folder, strlen(parameters.output_folder) + 2, "%s/", parameters.output_folder); +#endif + } break; case 'R': parameters.recursive = true; @@ -170,6 +163,7 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) char *output_full_path = NULL; char *original_output_full_path = NULL; bool overwriting = false; + off_t file_size = 0; //If we don't need to keep the structure, we put all the files in one folder by just the filename if (!options->keep_structure) { output_full_path = malloc((strlen(filename) + strlen(options->output_folder) + 1) * sizeof(char)); @@ -211,7 +205,12 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) overwriting = true; } - input_file_size = get_file_size(options->input_files[i]); + file_size = get_file_size(options->input_files[i]); + if (file_size == 0) { + //We could not open the file + continue; + } + input_file_size = file_size; options->input_total_size += input_file_size; //Prevent compression if running in dry mode diff --git a/src/utils.c b/src/utils.c index 5afb0fe..7914c4b 100644 --- a/src/utils.c +++ b/src/utils.c @@ -128,7 +128,8 @@ off_t get_file_size(const char *path) { FILE *f = fopen(path, "rb"); if (f == NULL) { - display_error(ERROR, 7); + display_error(WARNING, 7); + return 0; } fseek(f, 0, SEEK_END); off_t len = ftell(f); From e1a6c862a2c826251079381d9a165a2d35926716 Mon Sep 17 00:00:00 2001 From: Matteo Paonessa Date: Fri, 29 Dec 2017 23:18:20 +0100 Subject: [PATCH 6/6] / bugfix --- .idea/codeStyles/Project.xml | 29 +++++++++++++++++++++++++++++ README.md | 3 ++- src/helper.c | 26 +++++++++++++++++++++----- 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 .idea/codeStyles/Project.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 0f8592a..60ba669 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ---------- ###### TESTED PLATFORMS -* Mac OS X Sierra (v10.13.0) +* Mac OS X High Sierra (v10.13.1) * Ubuntu 16.04 * Windows 10 @@ -60,6 +60,7 @@ $ caesiumclt -q 0 -RS -o ~/output/ ~/Pictures ---------- ###### CHANGELOG +* 0.11.0-beta - Fixing paths issues and dry-run option * 0.10.2-beta - Bugfixes & full Windows support * 0.10.1-beta - All features are available * 0.10.0-beta - Switched to cmake build system and libcaesium diff --git a/src/helper.c b/src/helper.c index e7fdad5..e98ef82 100644 --- a/src/helper.c +++ b/src/helper.c @@ -1,9 +1,11 @@ #include #include #include + #ifdef _WIN32 #include #endif + #include "helper.h" #include "optparse.h" #include "utils.h" @@ -34,7 +36,7 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) while ((option = optparse_long(&opts, longopts, NULL)) != -1) { switch (option) { case 'q': - options->jpeg.quality = (int)strtol(opts.optarg, (char **)NULL, 10);; + options->jpeg.quality = (int) strtol(opts.optarg, (char **) NULL, 10);; if (options->jpeg.quality < 0 || options->jpeg.quality > 100) { display_error(ERROR, 1); } @@ -47,11 +49,13 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) } else { realpath(opts.optarg, parameters.output_folder); } - if (parameters.output_folder[strlen(opts.optarg) - 1] != '/' && parameters.output_folder[strlen(opts.optarg) - 1] != '\\') { + if (parameters.output_folder[strlen(opts.optarg) - 1] != '/' && + parameters.output_folder[strlen(opts.optarg) - 1] != '\\') { #ifdef _WIN32 snprintf(parameters.output_folder, strlen(parameters.output_folder) + 2, "%s\\", parameters.output_folder); #else - snprintf(parameters.output_folder, strlen(parameters.output_folder) + 2, "%s/", parameters.output_folder); + snprintf(parameters.output_folder, strlen(parameters.output_folder) + 2, "%s/", + parameters.output_folder); #endif } break; @@ -103,6 +107,16 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) if (is_directory(resolved_path)) { if (!files_flag) { folders_flag = true; + + if (resolved_path[strlen(resolved_path) - 1] != '/' && resolved_path[strlen(resolved_path) - 1] != '\\') { +#ifdef _WIN32 + resolved_path[strlen(resolved_path)] = '\\'; +#else + resolved_path[strlen(resolved_path)] = '/'; +#endif + resolved_path[strlen(resolved_path)] = '\0'; + } + snprintf(parameters.input_folder, strlen(resolved_path) + 1, "%s", resolved_path); int count = 0; count = scan_folder(resolved_path, ¶meters, parameters.recursive); @@ -122,10 +136,12 @@ cclt_options parse_arguments(char **argv, cs_image_pars *options) } //Check if the output folder is a subfolder of the input to avoid infinite loops + //but just if the -R option is set //However, if the folders are the same, we can let it go as it will overwrite the files if (folders_flag) { if (strstr(parameters.output_folder, parameters.input_folder) != NULL - && strcmp(parameters.output_folder, parameters.input_folder) != 0) { + && strcmp(parameters.output_folder, parameters.input_folder) != 0 + && parameters.recursive) { display_error(ERROR, 12); } } @@ -171,7 +187,7 @@ int start_compression(cclt_options *options, cs_image_pars *parameters) options->output_folder, filename); } else { /* - * Otherwise, we nee to compute the whole directory structure + * Otherwise, we need to compute the whole directory structure * We are sure we have a folder only as input, so that's the root * Just compute the subfolders without the filename, make them and append the filename * A piece of cake <3