Recursive folder support
This commit is contained in:
parent
51e2cdc83b
commit
c20b2e98f7
|
@ -2,4 +2,6 @@ output/*
|
||||||
samples/*
|
samples/*
|
||||||
tmp/*
|
tmp/*
|
||||||
build/*
|
build/*
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
|
aclocal.m4
|
||||||
|
configure
|
6
INSTALL
6
INSTALL
|
@ -33,14 +33,16 @@ Cloning from git
|
||||||
==================
|
==================
|
||||||
$ git clone https://github.com/Lymphatus/CaesiumCLT
|
$ git clone https://github.com/Lymphatus/CaesiumCLT
|
||||||
$ cd CaesiumCLT
|
$ cd CaesiumCLT
|
||||||
$ (optional) autoreconf -fiv
|
$ autoreconf -fiv
|
||||||
$ ./configure
|
$ ./configure
|
||||||
$ make
|
$ make
|
||||||
$ sudo make install
|
$ 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
|
$ mkdir build
|
||||||
$ cd build
|
$ cd build
|
||||||
|
Then call:
|
||||||
$ ../configure
|
$ ../configure
|
||||||
$ make
|
$ make
|
||||||
$ sudo make install
|
$ sudo make install
|
|
@ -1,5 +1,5 @@
|
||||||
## Caesium Command Line Tools
|
## 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
|
###### TODO
|
||||||
* Recursive folder support
|
|
||||||
* GIF support?
|
* GIF support?
|
||||||
* Code cleaning
|
* Code cleaning
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
###### CHANGELOG
|
###### 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.
|
* 0.9.1-beta - Initial development stage
|
||||||
* 1.9.9 - Initial development stage
|
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ cclt_compress_parameters initialize_compression_parameters() {
|
||||||
par.lossless = 0;
|
par.lossless = 0;
|
||||||
par.input_files_count = 0;
|
par.input_files_count = 0;
|
||||||
par.recursive = 0;
|
par.recursive = 0;
|
||||||
|
par.input_files = NULL;
|
||||||
|
par.structure = 0;
|
||||||
|
|
||||||
return par;
|
return par;
|
||||||
}
|
}
|
||||||
|
@ -82,11 +84,19 @@ cclt_compress_parameters parse_arguments(int argc, char* argv[]) {
|
||||||
case 'R':
|
case 'R':
|
||||||
parameters.recursive = 1;
|
parameters.recursive = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
parameters.structure = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int i = 0;
|
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*));
|
parameters.input_files = (char**) malloc ((argc - optind) * sizeof (char*));
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
parameters.input_files[i] = (char*) malloc (strlen(argv[optind]) * sizeof(char)); //TODO Necessary??
|
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;
|
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);
|
enum image_type type = detect_image_type(input);
|
||||||
if (type == JPEG && pars->lossless == 0) {
|
if (type == JPEG && pars->lossless == 0) {
|
||||||
cclt_jpeg_compress(output, cclt_jpeg_decompress(input, pars), pars);
|
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) {
|
} else if (type == GIF) {
|
||||||
printf("GIF detected. Not implemented yet.\n");
|
printf("GIF detected. Not implemented yet.\n");
|
||||||
} else {
|
} else {
|
||||||
return;
|
printf("Unknown file type.\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
|
@ -5,6 +5,6 @@
|
||||||
|
|
||||||
cclt_compress_parameters initialize_compression_parameters();
|
cclt_compress_parameters initialize_compression_parameters();
|
||||||
cclt_compress_parameters parse_arguments(int argc, char* argv[]);
|
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
|
#endif
|
54
src/main.c
54
src/main.c
|
@ -21,17 +21,20 @@
|
||||||
-l lossless v
|
-l lossless v
|
||||||
-s scale v
|
-s scale v
|
||||||
-h help v
|
-h help v
|
||||||
-R recursive
|
-R recursive v
|
||||||
|
-S keep folder structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO Use a general fuction to support folder separators
|
//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) {
|
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;
|
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 (mkpath(output_folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
|
||||||
if (errno != EEXIST) {
|
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;
|
off_t i_size, o_size;
|
||||||
int status; //Pointer for stat() call
|
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));
|
char* i_tmp = (char*) malloc (strlen(input_files[i]) * sizeof(char));
|
||||||
|
|
||||||
strcpy(i_tmp, input_files[i]);
|
strcpy(i_tmp, input_files[i]);
|
||||||
strcpy(output_filename, output_folder);
|
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);
|
//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));
|
output_filename = strcat(output_filename, basename(i_tmp));
|
||||||
|
|
||||||
//TODO OVERALL progress update?
|
//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
|
//Check if we ran into a folder
|
||||||
//TODO Check symlinks too
|
//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
|
//Folder found, but we don't need it here
|
||||||
i++;
|
i++;
|
||||||
continue;
|
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
|
//Get input file size
|
||||||
i_size = st_buf.st_size;
|
i_size = st_buf.st_size;
|
||||||
*(i_t_size) += i_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?
|
//TODO Do we want a more verbose output?
|
||||||
fprintf(stdout, "Compressing: %s -> %s\n", input_files[i], output_filename);
|
fprintf(stdout, "Compressing: %s -> %s\n", input_files[i], output_filename);
|
||||||
|
|
||||||
//if (lossless != 0) {
|
int routine = cclt_compress_routine(input_files[i], output_filename, pars);
|
||||||
// cclt_jpeg_optimize(input_files[i], output_filename, exif, input_files[i]);
|
if (routine == -1) {
|
||||||
//} else {
|
i++;
|
||||||
cclt_compress_routine(input_files[i], output_filename, pars);
|
continue;
|
||||||
//}
|
}
|
||||||
|
|
||||||
//Get output stats
|
//Get output stats
|
||||||
status = stat(output_filename, &st_buf);
|
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",
|
fprintf(stdout, "%ld bytes -> %ld bytes [%.2f%%]\n",
|
||||||
(long) i_size, (long) o_size, ((float) o_size - i_size) * 100 / i_size);
|
(long) i_size, (long) o_size, ((float) o_size - i_size) * 100 / i_size);
|
||||||
|
|
||||||
//TODO Perform the required instructions
|
|
||||||
//TODO Provide complete progress support
|
//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++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +168,7 @@ int main (int argc, char *argv[]) {
|
||||||
exit(-13);
|
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);
|
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",
|
fprintf(stdout, "-------------------------------\nCompression completed.\n%ld bytes -> %ld bytes [%.2f%% | %ld bytes]\n",
|
||||||
|
|
128
src/utils.c
128
src/utils.c
|
@ -15,10 +15,8 @@
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
int string_to_int(char* in_string) {
|
int string_to_int(char* in_string) {
|
||||||
long value = 0;
|
long value = 0;
|
||||||
char* endptr;
|
char* endptr;
|
||||||
|
@ -51,9 +49,10 @@ void print_help() {
|
||||||
"\t-e\tkeeps EXIF info during compression\n"
|
"\t-e\tkeeps EXIF info during compression\n"
|
||||||
"\t-o\tcompress to custom folder\n"
|
"\t-o\tcompress to custom folder\n"
|
||||||
"\t-l\tuse lossless optimization\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
|
//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-h\tdisplay this help and exit\n"
|
||||||
"\t-v\toutput version information and exit\n\n");
|
"\t-v\toutput version information and exit\n\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -92,68 +91,65 @@ int mkpath(const char *pathname, mode_t mode) {
|
||||||
return -1;
|
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;
|
int i = 0;
|
||||||
DIR *dp;
|
char** fileList = NULL;
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chdir("..");
|
char absolute_path[PATH_MAX];
|
||||||
closedir(dp);
|
realpath(basedir, absolute_path);
|
||||||
printf("SEG\n");
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printdir(char *dir, int depth)
|
dir = opendir(absolute_path);
|
||||||
{
|
|
||||||
DIR *dp;
|
if (dir != NULL) {
|
||||||
struct dirent *entry;
|
while ((ent = readdir(dir)) != NULL) {
|
||||||
struct stat statbuf;
|
// Do not allow "." or ".."
|
||||||
if((dp = opendir(dir)) == NULL) {
|
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
|
||||||
fprintf(stderr,"cannot open directory: %s\n", dir);
|
continue;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
chdir(dir);
|
//TODO allocate for this entry
|
||||||
while((entry = readdir(dp)) != NULL) {
|
//Basedir + filename + separator
|
||||||
lstat(entry->d_name,&statbuf);
|
entpath = realloc(entpath, (strlen(absolute_path) + strlen(ent->d_name) + 1) * sizeof(char));
|
||||||
if(S_ISDIR(statbuf.st_mode)) {
|
strcpy(entpath, absolute_path);
|
||||||
/* Found a directory, but ignore . and .. */
|
//Append separator
|
||||||
if(strcmp(".",entry->d_name) == 0 ||
|
strcat(entpath, "/");
|
||||||
strcmp("..",entry->d_name) == 0)
|
//Append the name
|
||||||
continue;
|
strcat(entpath, ent->d_name);
|
||||||
printf("%*s%s/\n",depth,"",entry->d_name);
|
|
||||||
/* Recurse at a new indent level */
|
//Gets stats
|
||||||
printdir(entry->d_name,depth+4);
|
stat(entpath, &s);
|
||||||
}
|
|
||||||
else printf("%*s%s\n",depth,"",entry->d_name);
|
if (S_ISDIR(s.st_mode)) {
|
||||||
}
|
// Directory, walk it if recursive is set
|
||||||
chdir("..");
|
if (recur != 0) {
|
||||||
closedir(dp);
|
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) {
|
enum image_type detect_image_type(char* path) {
|
||||||
|
@ -181,8 +177,12 @@ enum image_type detect_image_type(char* path) {
|
||||||
free(type_buffer);
|
free(type_buffer);
|
||||||
return PNG;
|
return PNG;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unsupported file type. Skipping.\n");
|
|
||||||
return UNKN;
|
return UNKN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isDirectory(const char *file_path) {
|
||||||
|
struct stat s;
|
||||||
|
stat(file_path, &s);
|
||||||
|
return S_ISDIR(s.st_mode);
|
||||||
|
}
|
|
@ -5,8 +5,8 @@
|
||||||
#include <turbojpeg.h>
|
#include <turbojpeg.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define APP_VERSION "1.9.9 BETA"
|
#define APP_VERSION "0.9.1-beta"
|
||||||
#define BUILD 20150728
|
#define BUILD 20150921
|
||||||
|
|
||||||
typedef struct cclt_compress_parameters {
|
typedef struct cclt_compress_parameters {
|
||||||
int quality;
|
int quality;
|
||||||
|
@ -22,6 +22,7 @@ typedef struct cclt_compress_parameters {
|
||||||
int input_files_count;
|
int input_files_count;
|
||||||
enum TJSAMP subsample;
|
enum TJSAMP subsample;
|
||||||
int recursive;
|
int recursive;
|
||||||
|
int structure;
|
||||||
} cclt_compress_parameters;
|
} cclt_compress_parameters;
|
||||||
|
|
||||||
enum image_type {
|
enum image_type {
|
||||||
|
@ -36,5 +37,7 @@ void print_help();
|
||||||
void print_progress(int current, int max, char* message);
|
void print_progress(int current, int max, char* message);
|
||||||
int mkpath(const char *pathname, mode_t mode);
|
int mkpath(const char *pathname, mode_t mode);
|
||||||
enum image_type detect_image_type(char* path);
|
enum image_type detect_image_type(char* path);
|
||||||
|
int isDirectory(const char *file_path);
|
||||||
|
char** scan_folder(char* basedir, int* n, int recur);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue