summaryrefslogtreecommitdiffstats
path: root/source/modes/recursivebrowser.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/modes/recursivebrowser.c')
-rw-r--r--source/modes/recursivebrowser.c202
1 files changed, 128 insertions, 74 deletions
diff --git a/source/modes/recursivebrowser.c b/source/modes/recursivebrowser.c
index 7cbd0f96..4a4ce6d5 100644
--- a/source/modes/recursivebrowser.c
+++ b/source/modes/recursivebrowser.c
@@ -178,81 +178,134 @@ static void recursive_browser_mode_init_current_dir(Mode *sw) {
}
static void scan_dir(FileBrowserModePrivateData *pd, GFile *path) {
- char *cdir = g_file_get_path(path);
- DIR *dir = opendir(cdir);
- if (dir) {
- struct dirent *rd = NULL;
- while (pd->end_thread == FALSE && (rd = readdir(dir)) != NULL) {
- if (g_strcmp0(rd->d_name, "..") == 0) {
- continue;
- }
- if (g_strcmp0(rd->d_name, ".") == 0) {
- continue;
- }
- if (pd->filter_regex &&
- g_regex_match(pd->filter_regex, rd->d_name, 0, NULL)) {
- continue;
- }
- switch (rd->d_type) {
- case DT_BLK:
- case DT_CHR:
- case DT_FIFO:
- case DT_UNKNOWN:
- case DT_SOCK:
- default:
- break;
- case DT_REG: {
- FBFile *f = g_malloc0(sizeof(FBFile));
- // Rofi expects utf-8, so lets convert the filename.
- f->path = g_build_filename(cdir, rd->d_name, NULL);
- f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL);
- if (f->name == NULL) {
- f->name = rofi_force_utf8(rd->d_name, -1);
- }
- f->type = (rd->d_type == DT_DIR) ? DIRECTORY : RFILE;
- f->icon_fetch_uid = 0;
- f->icon_fetch_size = 0;
- f->link = FALSE;
-
- g_async_queue_push(pd->async_queue, f);
- if (g_async_queue_length(pd->async_queue) > 10000) {
- write(pd->pipefd2[1], "r", 1);
- }
- break;
- }
- case DT_DIR: {
- char *d = g_build_filename(cdir, rd->d_name, NULL);
- GFile *dirp = g_file_new_for_path(d);
- scan_dir(pd, dirp);
- g_object_unref(dirp);
- g_free(d);
- break;
- }
- case DT_LNK: {
- FBFile *f = g_malloc0(sizeof(FBFile));
- // Rofi expects utf-8, so lets convert the filename.
- f->path = g_build_filename(cdir, rd->d_name, NULL);
- f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL);
- if (f->name == NULL) {
- f->name = rofi_force_utf8(rd->d_name, -1);
- }
- f->icon_fetch_uid = 0;
- f->icon_fetch_size = 0;
- f->link = TRUE;
- // Default to file.
- f->type = RFILE;
- g_async_queue_push(pd->async_queue, f);
- if (g_async_queue_length(pd->async_queue) > 10000) {
- write(pd->pipefd2[1], "r", 1);
- }
- break;
- }
- }
- }
- closedir(dir);
+ GQueue *dirs_to_scan = g_queue_new();
+ g_queue_push_tail(dirs_to_scan, g_object_ref(path));
+ GFile *dir_to_scan = NULL;
+ while ( (dir_to_scan = g_queue_pop_head(dirs_to_scan)) != NULL) {
+ char *cdir = g_file_get_path(dir_to_scan);
+ DIR *dir = opendir(cdir);
+ g_object_unref(dir_to_scan);
+ if (dir) {
+ struct dirent *rd = NULL;
+ while (pd->end_thread == FALSE && (rd = readdir(dir)) != NULL) {
+ if (g_strcmp0(rd->d_name, "..") == 0) {
+ continue;
+ }
+ if (g_strcmp0(rd->d_name, ".") == 0) {
+ continue;
+ }
+ if (pd->filter_regex &&
+ g_regex_match(pd->filter_regex, rd->d_name, 0, NULL)) {
+ continue;
+ }
+ switch (rd->d_type) {
+ case DT_BLK:
+ case DT_CHR:
+ case DT_FIFO:
+ case DT_SOCK:
+ default:
+ break;
+ case DT_REG: {
+ FBFile *f = g_malloc0(sizeof(FBFile));
+ // Rofi expects utf-8, so lets convert the filename.
+ f->path = g_build_filename(cdir, rd->d_name, NULL);
+ f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL);
+ if (f->name == NULL) {
+ f->name = rofi_force_utf8(rd->d_name, -1);
+ }
+ if (f->name == NULL) {
+ f->name = g_strdup("n/a");
+ }
+ f->type = (rd->d_type == DT_DIR) ? DIRECTORY : RFILE;
+ f->icon_fetch_uid = 0;
+ f->icon_fetch_size = 0;
+ f->link = FALSE;
+
+ g_async_queue_push(pd->async_queue, f);
+ if (g_async_queue_length(pd->async_queue) > 10000) {
+ write(pd->pipefd2[1], "r", 1);
+ }
+ break;
+ }
+ case DT_DIR: {
+ char *d = g_build_filename(cdir, rd->d_name, NULL);
+ GFile *dirp = g_file_new_for_path(d);
+ g_queue_push_tail(dirs_to_scan, dirp);
+ g_free(d);
+ break;
+ }
+ case DT_UNKNOWN:
+ case DT_LNK: {
+ FBFile *f = g_malloc0(sizeof(FBFile));
+ // Rofi expects utf-8, so lets convert the filename.
+ f->path = g_build_filename(cdir, rd->d_name, NULL);
+ f->name = g_filename_to_utf8(f->path, -1, NULL, NULL, NULL);
+ if (f->name == NULL) {
+ f->name = rofi_force_utf8(rd->d_name, -1);
+ }
+ if (f->name == NULL) {
+ f->name = g_strdup("n/a");
+ }
+ f->icon_fetch_uid = 0;
+ f->icon_fetch_size = 0;
+ // Default to file.
+ f->type = RFILE;
+ if (rd->d_type == DT_LNK) {
+ f->link = TRUE;
+ } else {
+ f->link = FALSE;
+ }
+ {
+ // If we have link, use a stat to fine out what it is, if we fail, we
+ // mark it as file.
+ // TODO have a 'broken link' mode?
+ // Convert full path to right encoding.
+ // DD: Path should be in file encoding, not utf-8
+ // char *file =
+ // g_filename_from_utf8(pd->array[pd->array_length].path,
+ // -1, NULL, NULL, NULL);
+ // TODO: How to handle loops in links.
+ if (f->path) {
+ GStatBuf statbuf;
+ if (g_stat(f->path, &statbuf) == 0) {
+ if (S_ISDIR(statbuf.st_mode)) {
+ char *new_full_path = g_build_filename(cdir, rd->d_name, NULL);
+ g_free(f->path);
+ g_free(f->name);
+ g_free(f);
+ f = NULL;
+ GFile *dirp = g_file_new_for_path(new_full_path);
+ g_queue_push_tail(dirs_to_scan, dirp);
+ g_free(new_full_path);
+ break;
+ } else if (S_ISREG(statbuf.st_mode)) {
+ f->type = RFILE;
+ }
+
+ } else {
+ g_warning("Failed to stat file: %s, %s", f->path,
+ strerror(errno));
+ }
+
+ // g_free(file);
+ }
+ }
+ if (f != NULL) {
+ g_async_queue_push(pd->async_queue, f);
+ if (g_async_queue_length(pd->async_queue) > 10000) {
+ write(pd->pipefd2[1], "r", 1);
+ }
+ }
+ break;
+ }
+ }
+ }
+ closedir(dir);
+ }
+ g_free(cdir);
}
- g_free(cdir);
+ g_queue_free(dirs_to_scan);
}
static gpointer recursive_browser_input_thread(gpointer userdata) {
FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *)userdata;
@@ -335,7 +388,8 @@ static unsigned int recursive_browser_mode_get_num_entries(const Mode *sw) {
return pd->array_length;
}
-static ModeMode recursive_browser_mode_result(Mode *sw, int mretv, G_GNUC_UNUSED char **input,
+static ModeMode recursive_browser_mode_result(Mode *sw, int mretv,
+ G_GNUC_UNUSED char **input,
unsigned int selected_line) {
ModeMode retv = MODE_EXIT;
FileBrowserModePrivateData *pd =