diff --git a/.gitignore b/.gitignore index 00aafef..4c2e4f0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ output/* samples/* tmp/* build/* -autom4te.cache \ No newline at end of file +autom4te.cache +aclocal.m4 +configure \ No newline at end of file diff --git a/INSTALL b/INSTALL index cc65a79..3106ecf 100644 --- a/INSTALL +++ b/INSTALL @@ -33,14 +33,16 @@ Cloning from git ================== $ git clone https://github.com/Lymphatus/CaesiumCLT $ cd CaesiumCLT - $ (optional) autoreconf -fiv + $ autoreconf -fiv $ ./configure $ make $ sudo make install -You can build out of the source tree in a separate folder. For example: +You can build out of the source tree in a separate folder. Add this steps before +invoking configure: $ mkdir build $ cd build +Then call: $ ../configure $ make $ sudo make install \ No newline at end of file diff --git a/README.md b/README.md index 6eeff27..9150b93 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## Caesium Command Line Tools -##### CCLT - v 1.9.9 BETA (build 20150911) - Copyright © Matteo Paonessa, 2015. All Rights Reserved. +##### CCLT - v0.9.1-beta (build 20150921) - Copyright © Matteo Paonessa, 2015. All Rights Reserved. ---------- @@ -23,15 +23,13 @@ See INSTALL for more details. ---------- ###### TODO -* Recursive folder support * GIF support? * Code cleaning ---------- ###### CHANGELOG -Note that CCLT started along with Caesium 2.0.0 so it uses its versioning system. 2.0.0 has to be considered the initial release. -* 1.9.9 - Initial development stage +* 0.9.1-beta - Initial development stage ---------- diff --git a/src/compresshelper.c b/src/compresshelper.c index 82d9912..7f24585 100644 --- a/src/compresshelper.c +++ b/src/compresshelper.c @@ -27,6 +27,8 @@ cclt_compress_parameters initialize_compression_parameters() { par.lossless = 0; par.input_files_count = 0; par.recursive = 0; + par.input_files = NULL; + par.structure = 0; return par; } @@ -82,11 +84,19 @@ cclt_compress_parameters parse_arguments(int argc, char* argv[]) { case 'R': parameters.recursive = 1; break; + case 'S': + parameters.structure = 1; + break; default: abort(); } } else { int i = 0; + if (isDirectory(argv[optind])) { + //TODO Works but I'd like to pass the list and return the number of files instead + parameters.input_files = scan_folder(argv[optind], ¶meters.input_files_count, parameters.recursive); + return parameters; + } parameters.input_files = (char**) malloc ((argc - optind) * sizeof (char*)); while (optind < argc) { parameters.input_files[i] = (char*) malloc (strlen(argv[optind]) * sizeof(char)); //TODO Necessary?? @@ -101,7 +111,7 @@ cclt_compress_parameters parse_arguments(int argc, char* argv[]) { return parameters; } -void cclt_compress_routine(char* input, char* output, cclt_compress_parameters* pars) { +int cclt_compress_routine(char* input, char* output, cclt_compress_parameters* pars) { enum image_type type = detect_image_type(input); if (type == JPEG && pars->lossless == 0) { cclt_jpeg_compress(output, cclt_jpeg_decompress(input, pars), pars); @@ -113,6 +123,8 @@ void cclt_compress_routine(char* input, char* output, cclt_compress_parameters* } else if (type == GIF) { printf("GIF detected. Not implemented yet.\n"); } else { - return; + printf("Unknown file type.\n"); + return -1; } + return 0; } \ No newline at end of file diff --git a/src/compresshelper.h b/src/compresshelper.h index 67afe52..1966b10 100644 --- a/src/compresshelper.h +++ b/src/compresshelper.h @@ -5,6 +5,6 @@ cclt_compress_parameters initialize_compression_parameters(); cclt_compress_parameters parse_arguments(int argc, char* argv[]); -void cclt_compress_routine(char* input, char* output, cclt_compress_parameters* pars); +int cclt_compress_routine(char* input, char* output, cclt_compress_parameters* pars); //Returns -1 if the file type is unknown #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 54d8fdc..78ab60d 100755 --- a/src/main.c +++ b/src/main.c @@ -21,17 +21,20 @@ -l lossless v -s scale v -h help v --R recursive +-R recursive v +-S keep folder structure */ //TODO Use a general fuction to support folder separators +//TODO If inputs a folder AND files, send an error +//TODO If the output is INSIDE the folder we are passing as input, ignore it or we're gonna go in a infinite loop void cclt_start(char** input_files, int n, char* output_folder, cclt_compress_parameters* pars, off_t* i_t_size, off_t* o_t_size) { struct stat st_buf; - int i = 0, recursive = pars->recursive; + int i = 0; if (mkpath(output_folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) { if (errno != EEXIST) { @@ -43,9 +46,9 @@ void cclt_start(char** input_files, int n, char* output_folder, cclt_compress_pa off_t i_size, o_size; int status; //Pointer for stat() call - char* output_filename = (char*) malloc ((strlen(output_folder) + 2) * sizeof(char)); + char* output_filename = (char*) malloc ((strlen(output_folder) + 1) * sizeof(char)); char* i_tmp = (char*) malloc (strlen(input_files[i]) * sizeof(char)); - + strcpy(i_tmp, input_files[i]); strcpy(output_filename, output_folder); @@ -56,7 +59,7 @@ void cclt_start(char** input_files, int n, char* output_folder, cclt_compress_pa //fprintf(stderr, "%s - %lu\n", output_filename, strlen(output_filename) + strlen(get_filename_with_extension(i_tmp)) + 1); - output_filename = realloc(output_filename, (strlen(output_filename) + strlen(basename(i_tmp)) + 1) * sizeof(char)); + output_filename = realloc(output_filename, (strlen(output_filename) + strlen(basename(i_tmp))) * sizeof(char)); output_filename = strcat(output_filename, basename(i_tmp)); //TODO OVERALL progress update? @@ -71,33 +74,12 @@ void cclt_start(char** input_files, int n, char* output_folder, cclt_compress_pa //Check if we ran into a folder //TODO Check symlinks too - if (S_ISDIR (st_buf.st_mode) && recursive == 0) { + if (isDirectory(input_files[i])) { //Folder found, but we don't need it here i++; continue; - } else if (S_ISDIR (st_buf.st_mode) && recursive != 0) { - //Folder found, we need to get into it - - - /* - 1. Scan the entire folder input_files[i] - 2. Get a new array containing all the files and folders - 3. Set the output folder to be one step deeper - 3. Call cclt_start(new_list, new folder, same, same, same) - */ - - //TODO malloc? - //char** new_files = (char**) malloc(256 * sizeof(char*)); - //new_files = scan_folder(input_files[i], 0); - //cclt_start(new_files, output_folder, pars, i_t_size, o_t_size); - //i++; - //TODO Remove this after this funcion is fully completed - //free(new_files); - continue; } - - //Get input file size i_size = st_buf.st_size; *(i_t_size) += i_size; @@ -105,11 +87,11 @@ void cclt_start(char** input_files, int n, char* output_folder, cclt_compress_pa //TODO Do we want a more verbose output? fprintf(stdout, "Compressing: %s -> %s\n", input_files[i], output_filename); - //if (lossless != 0) { - // cclt_jpeg_optimize(input_files[i], output_filename, exif, input_files[i]); - //} else { - cclt_compress_routine(input_files[i], output_filename, pars); - //} + int routine = cclt_compress_routine(input_files[i], output_filename, pars); + if (routine == -1) { + i++; + continue; + } //Get output stats status = stat(output_filename, &st_buf); @@ -124,14 +106,7 @@ void cclt_start(char** input_files, int n, char* output_folder, cclt_compress_pa fprintf(stdout, "%ld bytes -> %ld bytes [%.2f%%]\n", (long) i_size, (long) o_size, ((float) o_size - i_size) * 100 / i_size); - //TODO Perform the required instructions //TODO Provide complete progress support - //INPUT: pars.input_files[i] | OUTPUT: output_filename - - //Free allocated memory - //TODO Causing segfaults - //free(output_filename); - //free(i_tmp); i++; } @@ -193,6 +168,7 @@ int main (int argc, char *argv[]) { exit(-13); } + //We need the file list right here cclt_start(pars.input_files, pars.input_files_count, pars.output_folder, &pars, &i_t_size, &o_t_size); fprintf(stdout, "-------------------------------\nCompression completed.\n%ld bytes -> %ld bytes [%.2f%% | %ld bytes]\n", diff --git a/src/utils.c b/src/utils.c index b53b460..dbf8921 100644 --- a/src/utils.c +++ b/src/utils.c @@ -15,10 +15,8 @@ #include #endif - #include "utils.h" - int string_to_int(char* in_string) { long value = 0; char* endptr; @@ -51,9 +49,10 @@ void print_help() { "\t-e\tkeeps EXIF info during compression\n" "\t-o\tcompress to custom folder\n" "\t-l\tuse lossless optimization\n" - "\t-s\tscale to value, expressed as percentage (e.g. 20%%)\n" + "\t-s\tscale to value, expressed as percentage (e.g. 20%%) [Only 1/2^n allowed]\n" //TODO Remove this warning - "\t-R\tif input is a folder, scan subfolders too [NOT IMPLEMENTED YET]\n" + "\t-R\tif input is a folder, scan subfolders too\n" + "\t-S\tkeep the folder structure [Not active yet]\n" "\t-h\tdisplay this help and exit\n" "\t-v\toutput version information and exit\n\n"); exit(0); @@ -92,68 +91,65 @@ int mkpath(const char *pathname, mode_t mode) { return -1; } -char** scan_folder(char* dir, int depth) { +char** scan_folder(char* basedir, int* n, int recur) { + DIR *dir; + struct dirent *ent; + char* entpath = NULL; + struct stat s; + int indexes = 0; int i = 0; - DIR *dp; - struct dirent *entry; - struct stat statbuf; - char** files = (char**) malloc(sizeof(char*)); - if ((dp = opendir(dir)) == NULL) { - fprintf(stderr, "Cannot open %s. Aborting.\n", dir); - exit(-14); - } - chdir(dir); - while ((entry = readdir(dp)) != NULL) { - lstat(entry->d_name, &statbuf); - if (S_ISDIR(statbuf.st_mode)) { - if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) { - continue; - } - files = (char**) realloc(files, sizeof(files) + sizeof(char*)); - printf("QUI\n"); - files[i] = entry->d_name; - i++; - scan_folder(entry->d_name, depth+4); - } - else { - files = (char**) realloc(files, sizeof(files) + sizeof(char*)); - printf("QUI\n"); - files[i] = entry->d_name; - i++; - } - } + char** fileList = NULL; - chdir(".."); - closedir(dp); - printf("SEG\n"); - return files; -} + char absolute_path[PATH_MAX]; + realpath(basedir, absolute_path); -void printdir(char *dir, int depth) -{ - DIR *dp; - struct dirent *entry; - struct stat statbuf; - if((dp = opendir(dir)) == NULL) { - fprintf(stderr,"cannot open directory: %s\n", dir); - return; - } - chdir(dir); - while((entry = readdir(dp)) != NULL) { - lstat(entry->d_name,&statbuf); - if(S_ISDIR(statbuf.st_mode)) { - /* Found a directory, but ignore . and .. */ - if(strcmp(".",entry->d_name) == 0 || - strcmp("..",entry->d_name) == 0) - continue; - printf("%*s%s/\n",depth,"",entry->d_name); - /* Recurse at a new indent level */ - printdir(entry->d_name,depth+4); - } - else printf("%*s%s\n",depth,"",entry->d_name); - } - chdir(".."); - closedir(dp); + dir = opendir(absolute_path); + + if (dir != NULL) { + while ((ent = readdir(dir)) != NULL) { + // Do not allow "." or ".." + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { + continue; + } + + //TODO allocate for this entry + //Basedir + filename + separator + entpath = realloc(entpath, (strlen(absolute_path) + strlen(ent->d_name) + 1) * sizeof(char)); + strcpy(entpath, absolute_path); + //Append separator + strcat(entpath, "/"); + //Append the name + strcat(entpath, ent->d_name); + + //Gets stats + stat(entpath, &s); + + if (S_ISDIR(s.st_mode)) { + // Directory, walk it if recursive is set + if (recur != 0) { + fileList = scan_folder(entpath, n, recur); + } + } else { + //File, add to the list + //New entry in the array + + indexes++; + //Alloc new room for the array + fileList = realloc(fileList, indexes * sizeof(char*)); + fileList[i] = (char*) malloc(strlen(entpath) * sizeof(char)); + //Copy the file path in the array + fileList[i] = strcpy(fileList[i], entpath); + i++; + } + } + closedir(dir); + } else { + fprintf(stderr, "Failed to open folder. Aborting.\n"); + exit(-19); + } + free(entpath); + *n = i; + return fileList; } enum image_type detect_image_type(char* path) { @@ -181,8 +177,12 @@ enum image_type detect_image_type(char* path) { free(type_buffer); return PNG; } else { - fprintf(stderr, "Unsupported file type. Skipping.\n"); return UNKN; } } +int isDirectory(const char *file_path) { + struct stat s; + stat(file_path, &s); + return S_ISDIR(s.st_mode); +} \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index 65a9600..65f90c5 100644 --- a/src/utils.h +++ b/src/utils.h @@ -5,8 +5,8 @@ #include #include -#define APP_VERSION "1.9.9 BETA" -#define BUILD 20150728 +#define APP_VERSION "0.9.1-beta" +#define BUILD 20150921 typedef struct cclt_compress_parameters { int quality; @@ -22,6 +22,7 @@ typedef struct cclt_compress_parameters { int input_files_count; enum TJSAMP subsample; int recursive; + int structure; } cclt_compress_parameters; enum image_type { @@ -36,5 +37,7 @@ void print_help(); void print_progress(int current, int max, char* message); int mkpath(const char *pathname, mode_t mode); enum image_type detect_image_type(char* path); +int isDirectory(const char *file_path); +char** scan_folder(char* basedir, int* n, int recur); #endif