/* Resolve link target and either navigate inside directory link points to or * navigate to directory where target is located pointing cursor on * it (the follow_dirs flag controls behaviour). */ static void follow_link(FileView *view, int follow_dirs) { char *dir, *file; char full_path[PATH_MAX]; char linkto[PATH_MAX + NAME_MAX]; dir_entry_t *const entry = &curr_view->dir_entry[curr_view->list_pos]; get_full_path_of(entry, sizeof(full_path), full_path); if(get_link_target_abs(full_path, entry->origin, linkto, sizeof(linkto)) != 0) { show_error_msg("Error", "Can't read link."); return; } if(!path_exists(linkto, DEREF)) { show_error_msg("Broken Link", "Can't access link destination. It might be broken."); return; } chosp(linkto); if(is_dir(linkto) && !follow_dirs) { dir = strdup(entry->name); file = NULL; } else { dir = strdup(linkto); remove_last_path_component(dir); file = get_last_path_component(linkto); } if(dir[0] != '\0') { navigate_to(view, dir); } if(file != NULL) { const int pos = find_file_pos_in_list(view, file); if(pos >= 0) { flist_set_pos(view, pos); } } free(dir); }
SymLinkType get_symlink_type(const char path[]) { char cwd[PATH_MAX]; char linkto[PATH_MAX + NAME_MAX]; int saved_errno; char *filename_copy; char *p; if(get_cwd(cwd, sizeof(cwd)) == NULL) { /* getcwd() failed, just use "." rather than fail. */ strcpy(cwd, "."); } /* Use readlink() (in get_link_target_abs) before realpath() to check for * target at slow file system. realpath() doesn't fit in this case as it * resolves chains of symbolic links and we want to try only the first one. */ if(get_link_target_abs(path, cwd, linkto, sizeof(linkto)) != 0) { LOG_SERROR_MSG(errno, "Can't readlink \"%s\"", path); log_cwd(); return SLT_UNKNOWN; } if(refers_to_slower_fs(path, linkto)) { return SLT_SLOW; } filename_copy = strdup(path); chosp(filename_copy); p = os_realpath(filename_copy, linkto); saved_errno = errno; free(filename_copy); if(p == linkto) { return is_dir(linkto) ? SLT_DIR : SLT_UNKNOWN; } LOG_SERROR_MSG(saved_errno, "Can't realpath \"%s\"", path); log_cwd(); return SLT_UNKNOWN; }
void quick_view_file(FileView *view) { char path[PATH_MAX]; const dir_entry_t *entry; if(curr_stats.load_stage < 2) { return; } if(vle_mode_is(VIEW_MODE)) { return; } if(curr_stats.number_of_windows == 1) { return; } if(draw_abandoned_view_mode()) { return; } ui_view_erase(other_view); entry = &view->dir_entry[view->list_pos]; get_full_path_of(entry, sizeof(path), path); switch(view->dir_entry[view->list_pos].type) { case FT_CHAR_DEV: mvwaddstr(other_view->win, LINE, COL, "File is a Character Device"); break; case FT_BLOCK_DEV: mvwaddstr(other_view->win, LINE, COL, "File is a Block Device"); break; #ifndef _WIN32 case FT_SOCK: mvwaddstr(other_view->win, LINE, COL, "File is a Socket"); break; #endif case FT_FIFO: mvwaddstr(other_view->win, LINE, COL, "File is a Named Pipe"); break; case FT_LINK: if(get_link_target_abs(path, entry->origin, path, sizeof(path)) != 0) { mvwaddstr(other_view->win, LINE, COL, "Cannot resolve Link"); break; } if(!ends_with_slash(path) && is_dir(path)) { strncat(path, "/", sizeof(path) - strlen(path) - 1); } /* break intensionally omitted */ case FT_UNK: default: { const char *viewer; FILE *fp; char *const typed_fname = get_typed_fname(path); viewer = ft_get_viewer(typed_fname); free(typed_fname); if(viewer == NULL && is_dir(path)) { mvwaddstr(other_view->win, LINE, COL, "File is a Directory"); break; } if(is_null_or_empty(viewer)) { fp = os_fopen(path, "rb"); } else { fp = use_info_prog(viewer); } if(fp == NULL) { mvwaddstr(other_view->win, LINE, COL, "Cannot open file"); break; } ui_view_clear(other_view); wattrset(other_view->win, 0); view_file(fp, cfg.wrap_quick_view); fclose(fp); break; } } refresh_view_win(other_view); ui_view_title_update(other_view); }
void quick_view_file(FileView *view) { char buf[PATH_MAX]; if(curr_stats.load_stage < 2) return; if(get_mode() == VIEW_MODE) return; if(curr_stats.number_of_windows == 1) return; werase(other_view->win); werase(other_view->title); mvwaddstr(other_view->title, 0, 0, "File: "); wprint(other_view->title, view->dir_entry[view->list_pos].name); snprintf(buf, sizeof(buf), "%s/%s", view->curr_dir, view->dir_entry[view->list_pos].name); switch(view->dir_entry[view->list_pos].type) { case CHARACTER_DEVICE: mvwaddstr(other_view->win, LINE, COL, "File is a Character Device"); break; case BLOCK_DEVICE: mvwaddstr(other_view->win, LINE, COL, "File is a Block Device"); break; #ifndef _WIN32 case SOCKET: mvwaddstr(other_view->win, LINE, COL, "File is a Socket"); break; #endif case FIFO: mvwaddstr(other_view->win, LINE, COL, "File is a Named Pipe"); break; case LINK: if(get_link_target_abs(buf, view->curr_dir, buf, sizeof(buf)) != 0) { mvwaddstr(other_view->win, LINE, COL, "Cannot resolve Link"); break; } if(!ends_with_slash(buf) && is_dir(buf)) { strncat(buf, "/", sizeof(buf) - strlen(buf) - 1); } /* break intensionally omitted */ case UNKNOWN: default: { const char *viewer; FILE *fp; viewer = get_viewer_for_file(buf); if(viewer == NULL && is_dir(buf)) { mvwaddstr(other_view->win, LINE, COL, "File is a Directory"); break; } if(is_null_or_empty(viewer)) fp = fopen(buf, "r"); else fp = use_info_prog(viewer); if(fp == NULL) { mvwaddstr(other_view->win, LINE, COL, "Cannot open file"); break; } colmgr_reset(); wattrset(other_view->win, 0); view_file(fp, cfg.wrap_quick_view); fclose(fp); } break; } refresh_view_win(other_view); wrefresh(other_view->title); }