char *complete_filename(const char *start_prefix) { /* This might be NULL if the current directory has been unlinked, or it is not readable. in that case, we end up moving to the completion directory. */ char * const cur_dir_name = ne_getcwd(CUR_DIR_MAX_SIZE); char * const dir_name = str_dup(start_prefix); if (dir_name) { char * const p = (char *)file_part(dir_name); *p = 0; if (p != dir_name && chdir(tilde_expand(dir_name)) == -1) { free(dir_name); return NULL; } } start_prefix = file_part(start_prefix); bool is_dir, unique = true; char *cur_prefix = NULL; DIR * const d = opendir(CURDIR); if (d) { for(struct dirent * de; !stop && (de = readdir(d)); ) { if (is_prefix(start_prefix, de->d_name)) if (cur_prefix) { cur_prefix[max_prefix(cur_prefix, de->d_name)] = 0; unique = false; } else { cur_prefix = str_dup(de->d_name); is_dir = is_directory(de->d_name); } } closedir(d); } char * result = NULL; if (cur_prefix) { result = malloc(strlen(dir_name) + strlen(cur_prefix) + 2); strcat(strcat(strcpy(result, dir_name), cur_prefix), unique && is_dir ? "/" : ""); } if (cur_dir_name != NULL) { chdir(cur_dir_name); free(cur_dir_name); } free(dir_name); free(cur_prefix); return result; }
char *request_files(const char * const filename, bool use_prefix) { char * const cur_dir_name = ne_getcwd(CUR_DIR_MAX_SIZE); if (!cur_dir_name) return NULL; char * const dir_name = str_dup(filename); if (dir_name) { int result = 0; char * const p = (char *)file_part(dir_name); if (p != dir_name) { *p = 0; result = chdir(tilde_expand(dir_name)); } free(dir_name); if (result == -1) return NULL; } req_list rl; bool next_dir; char *result = NULL; do { next_dir = false; if (req_list_init(&rl, filenamecmp, true, false, '/') != OK) break; DIR * const d = opendir(CURDIR); if (d) { stop = false; for(struct dirent * de; !stop && (de = readdir(d)); ) { const bool is_dir = is_directory(de->d_name); if (use_prefix && !is_prefix(file_part(filename), de->d_name)) continue; if (!req_list_add(&rl, de->d_name, is_dir)) break; } req_list_finalize(&rl); if (rl.cur_entries) { /* qsort(rl.entries, rl.cur_entries, sizeof(char *), filenamecmpp); */ const int t = request_strings(&rl, 0); if (t != ERROR) { char * const p = rl.entries[t >= 0 ? t : -t - 2]; if (p[strlen(p) - 1] == '/' && t >= 0) { p[strlen(p) - 1] = 0; if (chdir(p)) alert(); else use_prefix = false; next_dir = true; } else { result = ne_getcwd(CUR_DIR_MAX_SIZE + strlen(p) + 2); if (strcmp(result, "/")) strcat(result, "/"); strcat(result, p); if (t < 0) { memmove(result + 1, result, strlen(result) + 1); result[0] = 0; } } } } closedir(d); } else alert(); req_list_free(&rl); } while(next_dir); chdir(cur_dir_name); free(cur_dir_name); return result; }
char *request_files(const char * const filename, int use_prefix) { int i, num_entries, name_len, max_name_len, total_len, next_dir, is_dir, entries_alloc_size = DEF_ENTRIES_ALLOC_SIZE, names_alloc_size = DEF_NAMES_ALLOC_SIZE; char *dir_name, **entries = NULL, *names = NULL, *cur_dir_name, *result = NULL, *p; DIR *d; struct dirent *de; if (!(cur_dir_name = ne_getcwd(CUR_DIR_MAX_SIZE))) return NULL; if (dir_name = str_dup(filename)) { i = 0; if ((p = (char *)file_part(dir_name)) != dir_name) { *p = 0; i = chdir(tilde_expand(dir_name)); } free(dir_name); if (i == -1) return NULL; } if (entries = malloc(sizeof(char *) * entries_alloc_size)) { if (names = malloc(sizeof(char) * names_alloc_size)) { do { next_dir = FALSE; if (d = opendir(CURDIR)) { num_entries = max_name_len = total_len = 0; stop = FALSE; while(!stop && (de = readdir(d))) { is_dir = is_directory(de->d_name); if (use_prefix && !is_prefix(file_part(filename), de->d_name)) continue; name_len = strlen(de->d_name) + is_dir + 1; if (name_len > max_name_len) max_name_len = name_len; if (total_len + name_len > names_alloc_size) { char *t; t = realloc(names, sizeof(char) * (names_alloc_size = names_alloc_size * 2 + name_len)); if (!t) break; names = t; /* Now adjust the entries to point to the newly reallocated strings */ entries[0] = names; for (i = 1; i < num_entries; i++) entries[i] = entries[i - 1] + strlen(entries[i - 1]) + 1; } if (num_entries >= entries_alloc_size) { char **t; t = realloc(entries, sizeof(char *) * (entries_alloc_size *= 2)); if (!t) break; entries = t; } strcpy(entries[num_entries] = names + total_len, de->d_name); if (is_dir) strcpy(names + total_len + name_len - 2, "/"); total_len += name_len; num_entries++; } if (num_entries) { qsort(entries, num_entries, sizeof(char *), filenamecmpp); if ((i = request_strings((const char * const *)entries, num_entries, 0, max_name_len, '/')) != ERROR) { p = entries[i >= 0 ? i : -i - 2]; if (p[strlen(p) - 1] == '/' && i >= 0) { p[strlen(p) - 1] = 0; if (chdir(p)) alert(); else use_prefix = FALSE; next_dir = TRUE; } else { result = ne_getcwd(CUR_DIR_MAX_SIZE + strlen(p) + 2); if (strcmp(result, "/")) strcat(result, "/"); strcat(result, p); if (i < 0) { memmove(result + 1, result, strlen(result) + 1); result[0] = 0; } } } } closedir(d); } else alert(); } while(next_dir); free(names); } free(entries); } chdir(cur_dir_name); free(cur_dir_name); return result; }