From b6a65e084dd30e15a301b1d7fcbef91efdb7bc3a Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sun, 19 Mar 2017 11:24:39 +0300 Subject: [PATCH] (file_is_symlink_to_dir): new API. Returns TRUE if file is symbolic link to directory, FALSE otherwise. Signed-off-by: Andrew Borodin --- src/filemanager/dir.c | 15 ++++----------- src/filemanager/file.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/filemanager/file.h | 2 ++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/filemanager/dir.c b/src/filemanager/dir.c index 2188d1983..72433ba35 100644 --- a/src/filemanager/dir.c +++ b/src/filemanager/dir.c @@ -47,6 +47,7 @@ #include "src/setup.h" /* panels_options */ #include "treestore.h" +#include "file.h" /* file_is_symlink_to_dir() */ #include "dir.h" #include "layout.h" /* rotate_dash() */ @@ -150,6 +151,7 @@ handle_dirent (struct dirent *dp, const char *fltr, struct stat *buf1, int *link int *stale_link) { vfs_path_t *vpath; + gboolean stale; if (DIR_IS_DOT (dp->d_name) || DIR_IS_DOTDOT (dp->d_name)) return FALSE; @@ -173,17 +175,8 @@ handle_dirent (struct dirent *dp, const char *fltr, struct stat *buf1, int *link tree_store_mark_checked (dp->d_name); /* A link to a file or a directory? */ - *link_to_dir = 0; - *stale_link = 0; - if (S_ISLNK (buf1->st_mode)) - { - struct stat buf2; - - if (mc_stat (vpath, &buf2) == 0) - *link_to_dir = S_ISDIR (buf2.st_mode) != 0; - else - *stale_link = 1; - } + *link_to_dir = file_is_symlink_to_dir (vpath, buf1, &stale) ? 1 : 0; + *stale_link = stale ? 1 : 0; vfs_path_free (vpath); diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 993f3f6f4..b83658cc0 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -2046,6 +2046,48 @@ end_bg_process (file_op_context_t * ctx, enum OperationMode mode) /*** public functions ****************************************************************************/ /* --------------------------------------------------------------------------------------------- */ +/* Is file symlink to directory or not. + * + * @param path file or directory + * @param st result of mc_lstat(vpath). If NULL, mc_lstat(vpath) is performed here + * @param stale_link TRUE if file is stale link to directory + * + * @return TRUE if file symlink to directory, ELSE otherwise. + */ +gboolean +file_is_symlink_to_dir (const vfs_path_t * vpath, struct stat * st, gboolean * stale_link) +{ + struct stat st2; + gboolean stale = FALSE; + gboolean res = FALSE; + + if (st == NULL) + { + st = &st2; + + if (mc_lstat (vpath, st) != 0) + goto ret; + } + + if (S_ISLNK (st->st_mode)) + { + struct stat st3; + + stale = (mc_stat (vpath, &st3) != 0); + + if (!stale) + res = (S_ISDIR (st3.st_mode) != 0); + } + + ret: + if (stale_link != NULL) + *stale_link = stale; + + return res; +} + +/* --------------------------------------------------------------------------------------------- */ + FileProgressStatus copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const char *src_path, const char *dst_path) diff --git a/src/filemanager/file.h b/src/filemanager/file.h index 0406b8768..a24ea9b35 100644 --- a/src/filemanager/file.h +++ b/src/filemanager/file.h @@ -39,6 +39,8 @@ struct dirsize_status_msg_t /*** declarations of public functions ************************************************************/ +gboolean file_is_symlink_to_dir (const vfs_path_t * path, struct stat *st, gboolean * stale_link); + FileProgressStatus copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx, const char *src_path, const char *dst_path); FileProgressStatus move_dir_dir (file_op_total_context_t * tctx, file_op_context_t * ctx,