Skip to content

Commit

Permalink
Merge branch 'symlink-and-exec-fixes'
Browse files Browse the repository at this point in the history
Resolve symbolic links for mime-type matchers.

Try to preserve symbolic links in current path when starting vifm by
checking value of $PWD.

Fixed some resources (like output pipe for --choose-files and
--choose-dir) being inherited by child processes.

Thanks to Vigi.
  • Loading branch information
xaizek committed Nov 16, 2018
2 parents 29bbf12 + 3810226 commit f712733
Show file tree
Hide file tree
Showing 18 changed files with 135 additions and 37 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
@@ -1,5 +1,10 @@
0.10 to current

Resolve symbolic links for mime-type matchers. Thanks to Vigi.

Try to preserve symbolic links in current path when starting vifm by
checking value of $PWD. Thanks to Vigi.

Fixed `:tabnew ..` not working due to use of uninitialized data.

Fixed access to uninitialized memory on clearing view after graphical
Expand All @@ -8,6 +13,9 @@
Fixed possible crashes after certain patterns of using view mode and
closing tabs.

Fixed some resources (like output pipe for --choose-files and
--choose-dir) being inherited by child processes. Thanks to Vigi.

0.10-beta to 0.10 (2018-11-11)

Display list of files in removal confirmation dialog. Thanks to ovk.
Expand Down
1 change: 1 addition & 0 deletions THANKS
Expand Up @@ -172,6 +172,7 @@ Tomek K. (TomiCode)
tYGjQCsvVI
Tyler Spivey
Valery Ushakov (nbuwe)
Vigi
Vlad Glagolev (Stealth)
Von Welch
vzel
Expand Down
2 changes: 2 additions & 0 deletions src/background.c
Expand Up @@ -637,6 +637,7 @@ bg_run_and_capture(char cmd[], int user_sh, FILE **out, FILE **err)
}

sh = user_sh ? get_execv_path(cfg.shell) : "/bin/sh";
prepare_for_exec();
execvp(sh, make_execv_array(sh, cmd));
_Exit(127);
}
Expand Down Expand Up @@ -826,6 +827,7 @@ bg_run_external(const char cmd[], int skip_errors)

setpgid(0, 0);

prepare_for_exec();
execve(get_execv_path(cfg.shell), make_execv_array(cfg.shell, command),
environ);
_Exit(127);
Expand Down
35 changes: 19 additions & 16 deletions src/int/file_magic.c
Expand Up @@ -54,28 +54,31 @@ static void parse_app_dir(const char directory[], const char mime_type[],
assoc_records_t
get_magic_handlers(const char file[])
{
char real_path[PATH_MAX + 1];
char *const symlink_base = strdup(file);
return get_handlers(get_mimetype(file, 1));
}

if(!is_root_dir(symlink_base))
{
remove_last_path_component(symlink_base);
}
const char *
get_mimetype(const char file[], int resolve_symlinks)
{
static char mimetype[128];

if(get_link_target_abs(file, symlink_base, real_path, sizeof(real_path)) != 0)
char target[PATH_MAX + 1];
if(resolve_symlinks)
{
copy_str(real_path, sizeof(real_path), file);
}
char *const symlink_base = strdup(file);

free(symlink_base);
if(!is_root_dir(symlink_base))
{
remove_last_path_component(symlink_base);
}

return get_handlers(get_mimetype(real_path));
}
if(get_link_target_abs(file, symlink_base, target, sizeof(target)) == 0)
{
file = target;
}

const char *
get_mimetype(const char file[])
{
static char mimetype[128];
free(symlink_base);
}

if(get_gtk_mimetype(file, mimetype, sizeof(mimetype)) == -1)
{
Expand Down
7 changes: 4 additions & 3 deletions src/int/file_magic.h
Expand Up @@ -21,9 +21,10 @@

#include "../filetype.h"

/* Retrieves mime type of the file specified by its path. Returns pointer to a
* statically allocated buffer. */
const char * get_mimetype(const char file[]);
/* Retrieves mime type of the file specified by its path. The resolve_symlinks
* argument controls whether mime-type of the link should be that of its target.
* Returns pointer to a statically allocated buffer. */
const char * get_mimetype(const char file[], int resolve_symlinks);

/* Retrieves system-wide desktop file associations. Caller shouldn't free
* anything. */
Expand Down
1 change: 1 addition & 0 deletions src/int/fuse.c
Expand Up @@ -629,6 +629,7 @@ run_fuse_command(char cmd[], const cancellation_t *cancellation, int *cancelled)

(void)set_sigchld(0);

prepare_for_exec();
(void)execve(get_execv_path(cfg.shell), make_execv_array(cfg.shell, cmd),
environ);
_Exit(127);
Expand Down
2 changes: 1 addition & 1 deletion src/modes/file_info.c
Expand Up @@ -361,7 +361,7 @@ show_mime_type(view_t *view, int curr_y)
const char *mimetype = NULL;

get_current_full_path(view, sizeof(full_path), full_path);
mimetype = get_mimetype(full_path);
mimetype = get_mimetype(full_path, 0);

mvwaddstr(menu_win, curr_y, 2, "Mime Type: ");

Expand Down
2 changes: 1 addition & 1 deletion src/utils/matcher.c
Expand Up @@ -351,7 +351,7 @@ matcher_matches(const matcher_t *matcher, const char path[])

if(matcher->type == MT_MIME)
{
path = get_mimetype(path);
path = get_mimetype(path, 1);
if(path == NULL)
{
return matcher->negated;
Expand Down
26 changes: 25 additions & 1 deletion src/utils/utils_nix.c
Expand Up @@ -45,7 +45,7 @@
#include <signal.h> /* SIG* SIG_* sigset_t kill() sigaddset() sigemptyset()
sigfillset() signal() sigprocmask() */
#include <stddef.h> /* NULL size_t */
#include <stdio.h> /* FILE stderr fdopen() fprintf() snprintf() */
#include <stdio.h> /* FILE stderr fclose() fdopen() fprintf() snprintf() */
#include <stdlib.h> /* atoi() free() */
#include <string.h> /* strchr() strdup() strerror() strlen() strncmp() */

Expand All @@ -54,6 +54,7 @@
#include "../compat/mntent.h" /* mntent setmntent() getmntent() endmntent() */
#include "../compat/os.h"
#include "../compat/reallocarray.h"
#include "../ui/tabs.h"
#include "../ui/ui.h"
#include "../running.h"
#include "../status.h"
Expand Down Expand Up @@ -136,6 +137,7 @@ run_in_shell_no_cls(char command[])
signal(SIGINT, SIG_DFL);
(void)set_sigchld(0);

prepare_for_exec();
execve(get_execv_path(cfg.shell), make_execv_array(cfg.shell, command),
environ);
_Exit(127);
Expand Down Expand Up @@ -274,10 +276,32 @@ run_from_fork(int pipe[2], int err_only, int preserve_stdin, char cmd[])
(void)close(null_fd);
}

prepare_for_exec();
execvp(get_execv_path(cfg.shell), make_execv_array(cfg.shell, cmd));
_Exit(127);
}

void
prepare_for_exec(void)
{
if(curr_stats.original_stdout != NULL)
{
(void)fclose(curr_stats.original_stdout);
}

/* More generic cleanup functions aren't called here to do not waste time on
* freeing resources which will be replaced by exec(). */
tab_info_t tab_info;
int i;
for(i = 0; tabs_get(curr_view, i, &tab_info); ++i)
{
view_t *view = tab_info.view;
fswatch_free(view->watch);
fswatch_free(view->left_column.watch);
fswatch_free(view->right_column.watch);
}
}

char *
get_execv_path(char shell[])
{
Expand Down
5 changes: 5 additions & 0 deletions src/utils/utils_nix.h
Expand Up @@ -45,6 +45,11 @@ int get_proc_exit_status(pid_t pid);
void _gnuc_noreturn run_from_fork(int pipe[2], int err_only, int preserve_stdin,
char cmd[]);

/* Frees some resources before exec(), which shouldn't be inherited and remain
* allocated in child process or it might make those resources appear busy
* (e.g., pipe not being closed, directory being still in use). */
void prepare_for_exec(void);

/* Extracts name of the shell to be used with execv*() function. Returns
* pointer to statically allocated buffer. */
char * get_execv_path(char shell[]);
Expand Down
30 changes: 26 additions & 4 deletions src/vifm.c
Expand Up @@ -62,6 +62,7 @@
#include "ui/statusbar.h"
#include "ui/tabs.h"
#include "ui/ui.h"
#include "utils/env.h"
#include "utils/fs.h"
#include "utils/log.h"
#include "utils/macros.h"
Expand Down Expand Up @@ -96,6 +97,7 @@
#include "undo.h"

static int vifm_main(int argc, char *argv[]);
static int get_start_cwd(char buf[], size_t buf_len);
static int undo_perform_func(OPS op, void *data, const char src[],
const char dst[]);
static void parse_received_arguments(char *args[]);
Expand Down Expand Up @@ -155,18 +157,16 @@ vifm_main(int argc, char *argv[])

static const int quit = 0;

char dir[PATH_MAX + 1];
char **files = NULL;
int nfiles = 0;
int lwin_cv, rwin_cv;

if(get_cwd(dir, sizeof(dir)) == NULL)
char dir[PATH_MAX + 1];
if(get_start_cwd(dir, sizeof(dir)) != 0)
{
perror("getcwd");
return -1;
}

(void)vifm_chdir(dir);
args_parse(&vifm_args, argc, argv, dir);
args_process(&vifm_args, 1);

Expand Down Expand Up @@ -347,6 +347,28 @@ vifm_main(int argc, char *argv[])
return 0;
}

/* Loads original working directory of the process attempting to avoid resolving
* symbolic links in the path. Returns zero on success, otherwise non-zero is
* returned. */
static int
get_start_cwd(char buf[], size_t buf_len)
{
if(get_cwd(buf, buf_len) == NULL)
{
perror("getcwd");
return -1;
}

/* If $PWD points to the same location as CWD, use its value to preserve
* symbolic links in the path. */
const char *pwd = env_get("PWD");
if(pwd != NULL && paths_are_same(pwd, buf))
{
copy_str(buf, buf_len, pwd);
}
return 0;
}

/* perform_operation() interface adaptor for the undo unit. */
static int
undo_perform_func(OPS op, void *data, const char src[], const char dst[])
Expand Down
2 changes: 1 addition & 1 deletion tests/filetype/filetype.c
Expand Up @@ -157,7 +157,7 @@ TEST(pattern_list, IF(has_mime_type_detection))
char cmd[1024];

snprintf(cmd, sizeof(cmd), "<%s>{binary-data}",
get_mimetype(TEST_DATA_PATH "/read/binary-data"));
get_mimetype(TEST_DATA_PATH "/read/binary-data", 0));
set_programs(cmd, "prog", 0, 0);

assert_string_equal("prog",
Expand Down
2 changes: 1 addition & 1 deletion tests/filetype/test.c
Expand Up @@ -31,7 +31,7 @@ set_viewers(const char pattern[], const char viewers[])
int
has_mime_type_detection(void)
{
return get_mimetype(TEST_DATA_PATH "/read/dos-line-endings") != NULL;
return get_mimetype(TEST_DATA_PATH "/read/dos-line-endings", 0) != NULL;
}

/* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
Expand Down
2 changes: 1 addition & 1 deletion tests/filetype/viewers.c
Expand Up @@ -98,7 +98,7 @@ TEST(pattern_list, IF(has_mime_type_detection))
char cmd[1024];

snprintf(cmd, sizeof(cmd), "<%s>{binary-data}",
get_mimetype(TEST_DATA_PATH "/read/binary-data"));
get_mimetype(TEST_DATA_PATH "/read/binary-data", 0));
set_viewers(cmd, "prog1");

ft_init(&prog1_available);
Expand Down
6 changes: 3 additions & 3 deletions tests/misc/commands_filetype.c
Expand Up @@ -77,11 +77,11 @@ TEST(pattern_anding_and_orring, IF(has_mime_type_detection))

snprintf(cmd, sizeof(cmd),
"filetype {two-lines}<text/plain>,<%s>{binary-data} app",
get_mimetype(TEST_DATA_PATH "/read/binary-data"));
get_mimetype(TEST_DATA_PATH "/read/binary-data", 0));
assert_success(exec_commands(cmd, &lwin, CIT_COMMAND));
snprintf(cmd, sizeof(cmd),
"fileviewer {two-lines}<text/plain>,<%s>{binary-data} viewer",
get_mimetype(TEST_DATA_PATH "/read/binary-data"));
get_mimetype(TEST_DATA_PATH "/read/binary-data", 0));
assert_success(exec_commands(cmd, &lwin, CIT_COMMAND));

ft = ft_get_all_programs(TEST_DATA_PATH "/read/two-lines");
Expand Down Expand Up @@ -137,7 +137,7 @@ prog_exists(const char name[])
static int
has_mime_type_detection(void)
{
return get_mimetype(TEST_DATA_PATH "/read/dos-line-endings") != NULL;
return get_mimetype(TEST_DATA_PATH "/read/dos-line-endings", 0) != NULL;
}

/* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
Expand Down
6 changes: 3 additions & 3 deletions tests/misc/file_magic.c
Expand Up @@ -49,7 +49,7 @@ TEST(relatively_large_file_name_does_not_crash,
SANDBOX_PATH "/B", path, sizeof(path)));

assert_success(chdir(SANDBOX_PATH "/B"));
assert_non_null(get_mimetype(get_last_path_component(path)));
assert_non_null(get_mimetype(get_last_path_component(path), 0));

restore_cwd(saved_cwd);

Expand All @@ -66,7 +66,7 @@ check_empty_file(const char fname[])
if(f != NULL)
{
fclose(f);
assert_non_null(get_mimetype(fname));
assert_non_null(get_mimetype(fname, 0));
assert_success(unlink(fname));
}
}
Expand All @@ -80,7 +80,7 @@ has_mime_type_detection_and_symlinks(void)
static int
has_mime_type_detection(void)
{
return get_mimetype(TEST_DATA_PATH "/read/dos-line-endings") != NULL;
return get_mimetype(TEST_DATA_PATH "/read/dos-line-endings", 0) != NULL;
}

/* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
Expand Down
2 changes: 1 addition & 1 deletion tests/stic/stic.h
Expand Up @@ -12,7 +12,7 @@

/* Global data. */

#define STIC_VERSION "0.5.2"
#define STIC_VERSION "0.6"
#define STIC_PROJECT_HOME "https://github.com/xaizek/stic"
#define STIC_PRINT_BUFFER_SIZE 100000

Expand Down

0 comments on commit f712733

Please sign in to comment.