diff --git a/Changelog b/Changelog index 553ab76..f60842b 100644 --- a/Changelog +++ b/Changelog @@ -6,6 +6,7 @@ * fixed a small memleak when leaving ncursesfm while a search was active * some print_info() related fixes * fixed a bug in shasum call from within main() +* fixed another long standing bug in extractor. It now works perfectly fine 12 / 18 / 2015 * fixed a small bug in ask_user diff --git a/README.md b/README.md index 3eb065d..b2486cf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ncursesFM Ncurses File Manager for linux. -It aims to be as user friendly and lightweight as possible, while being good looking (my own tastes), simple and easy to use. +It aims to be as user friendly and lightweight as possible, while being good looking (my own tastes) and simple. Being simple doesn't imply being useless; indeed it is a full featured fm. It can be built with a very small set of dependencies, as i tried to make as many deps as possible optional (compile time or runtime). diff --git a/src/archiver.c b/src/archiver.c index afc2560..6f95e5c 100644 --- a/src/archiver.c +++ b/src/archiver.c @@ -2,7 +2,7 @@ static void archiver_func(void); static int recursive_archive(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf); -static void extractor_thread(struct archive *a); +static void extractor_thread(struct archive *a, const char *current_dir); static struct archive *archive; @@ -69,12 +69,17 @@ static int recursive_archive(const char *path, const struct stat *sb, int typefl int try_extractor(void) { struct archive *a; + char current_dir[PATH_MAX + 1]; a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_all(a); if ((a) && (archive_read_open_filename(a, thread_h->filename, BUFF_SIZE) == ARCHIVE_OK)) { - extractor_thread(a); + strcpy(current_dir, thread_h->filename); + char *tmp = strrchr(current_dir, '/'); + int len = strlen(current_dir) - strlen(tmp); + current_dir[len] = '\0'; + extractor_thread(a, current_dir); return 0; } archive_read_free(a); @@ -87,37 +92,30 @@ int try_extractor(void) { * While there are headers inside the archive being read, it goes on copying data from * the read archive to the disk. */ -static void extractor_thread(struct archive *a) { +static void extractor_thread(struct archive *a, const char *current_dir) { struct archive *ext; struct archive_entry *entry; - int len, num = 0; + int len, num; int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS; - char buff[BUFF_SIZE], current_dir[PATH_MAX + 1], fullpathname[PATH_MAX + 1]; - char *tmp; + char buff[BUFF_SIZE], fullpathname[PATH_MAX + 1]; char name[PATH_MAX + 1], tmp_name[PATH_MAX + 1]; - strcpy(current_dir, thread_h->filename); - tmp = strrchr(current_dir, '/'); - len = strlen(current_dir) - strlen(tmp); - current_dir[len] = '\0'; ext = archive_write_disk_new(); archive_write_disk_set_options(ext, flags); archive_write_disk_set_standard_lookup(ext); while (archive_read_next_header(a, &entry) != ARCHIVE_EOF) { strcpy(name, archive_entry_pathname(entry)); - /* only perform overwrite check if on the first entry, or if num != 1 */ - if ((len == strlen(current_dir)) || (num != 1)) { - /* avoid overwriting a file/dir in path if it has the same name of a file being extracted there */ + num = 0; + /* avoid overwriting a file/dir in path if it has the same name of a file being extracted there */ + if (strchr(name, '/')) { strcpy(tmp_name, strchr(name, '/')); - len = strlen(name) - strlen(tmp_name); - if (num == 0) { - while (access(name, F_OK) != -1) { - num++; - sprintf(name + len, "%d%s", num, tmp_name); - } - } else { - sprintf(name + len, "%d%s", num, tmp_name); - } + } else { + tmp_name[0] = '\0'; + } + len = strlen(name) - strlen(tmp_name); + while (access(name, F_OK) != -1) { + num++; + sprintf(name + len, "%d%s", num, tmp_name); } sprintf(fullpathname, "%s/%s", current_dir, name); archive_entry_set_pathname(entry, fullpathname); diff --git a/src/inhibit.c b/src/inhibit.c index fe18bf1..c3eb09d 100644 --- a/src/inhibit.c +++ b/src/inhibit.c @@ -2,6 +2,11 @@ #include "../inc/inhibit.h" + +/* + * Thanks elogind project for some hints to improve my old implementation. + * https://github.com/andywingo/elogind/blob/master/src/login/inhibit.c + */ int inhibit_suspend(const char *str) { sd_bus *bus; sd_bus_message *reply = NULL; diff --git a/src/search.c b/src/search.c index b5fba0e..4df043e 100644 --- a/src/search.c +++ b/src/search.c @@ -10,17 +10,17 @@ void search(void) { ask_user(search_insert_name, sv.searched_string, 20, 0); if (strlen(sv.searched_string) < 5) { print_info(searched_string_minimum, ERR_LINE); - return; - } - sv.found_cont = 0; - sv.search_archive = 0; - ask_user(search_archives, &c, 1, 'n'); - if (c == 'y') { - sv.search_archive = 1; + } else { + sv.found_cont = 0; + sv.search_archive = 0; + ask_user(search_archives, &c, 1, 'n'); + if (c == 'y') { + sv.search_archive = 1; + } + sv.searching = 1; + print_info("", SEARCH_LINE); + pthread_create(&search_th, NULL, search_thread, NULL); } - sv.searching = 1; - print_info("", SEARCH_LINE); - pthread_create(&search_th, NULL, search_thread, NULL); } static int recursive_search(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { @@ -48,34 +48,33 @@ static int recursive_search(const char *path, const struct stat *sb, int typefla return quit ? 1 : ret; } +/* + * For each entry in the archive, it checks "entry + len" pointer against searched string. + * Len is always the offset of the current dir inside archive, eg: foo.tgz/bar/x, + * while checking x, len will be strlen("bar/") + */ static int search_inside_archive(const char *path) { - char str[PATH_MAX + 1], *ptr; - struct archive *a = archive_read_new(); + char *ptr; + int len = 0, ret = 0, string_length; struct archive_entry *entry; - int len, ret = 0; - + struct archive *a = archive_read_new(); + archive_read_support_filter_all(a); archive_read_support_format_all(a); + string_length = strlen(sv.searched_string); if ((a) && (archive_read_open_filename(a, path, BUFF_SIZE) == ARCHIVE_OK)) { - while ((!quit) && (archive_read_next_header(a, &entry) == ARCHIVE_OK)) { - strcpy(str, archive_entry_pathname(entry)); - len = strlen(str); - if (str[len - 1] == '/') { // check if we're on a dir - str[len - 1] = '\0'; - } - ptr = str; - if (strrchr(str, '/')) { - ptr = strrchr(str, '/') + 1; - } - len = strlen(sv.searched_string); - if (strncmp(ptr, sv.searched_string, len) == 0) { + while ((!quit) && (!ret) && (archive_read_next_header(a, &entry) == ARCHIVE_OK)) { + if (strncmp(archive_entry_pathname(entry) + len, sv.searched_string, string_length) == 0) { sprintf(sv.found_searched[sv.found_cont], "%s/%s", path, archive_entry_pathname(entry)); sv.found_cont++; if (sv.found_cont == MAX_NUMBER_OF_FOUND) { ret = 1; - break; } } + ptr = strrchr(archive_entry_pathname(entry), '/'); + if ((ptr) && (strlen(ptr) == 1)) { + len = strlen(archive_entry_pathname(entry)); + } } } archive_read_free(a);