mirror of
https://github.com/MidnightCommander/mc
synced 2025-02-02 00:16:04 +03:00
* subshell.c (do_subshell_chdir): Use mc_realpath() to fix tcsh's
problem with symlink. * utilunix.c: Add function mc_realpath(). Is the BSD version of realpath(3). * util.h: Add mc_realpath() declaration.
This commit is contained in:
parent
33e157631c
commit
d332606fd5
@ -1,3 +1,11 @@
|
||||
2005-01-14 Pavel Shirshov <me@pavelsh.pp.ru>
|
||||
|
||||
* subshell.c (do_subshell_chdir): Use mc_realpath() to fix tcsh's
|
||||
problem with symlink.
|
||||
* utilunix.c: Add function mc_realpath(). Is the BSD version of
|
||||
realpath(3).
|
||||
* util.h: Add mc_realpath() declaration.
|
||||
|
||||
2004-12-13 Andrew V. Samoilov <sav@bcs.zp.ua>
|
||||
|
||||
* find.c (find_parameters): Use translated string.
|
||||
|
@ -753,6 +753,8 @@ subshell_name_quote (const char *s)
|
||||
void
|
||||
do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
|
||||
{
|
||||
int bPathNotEq;
|
||||
|
||||
if (!
|
||||
(subshell_state == INACTIVE
|
||||
&& strcmp (subshell_cwd, current_panel->cwd))) {
|
||||
@ -787,8 +789,20 @@ do_subshell_chdir (const char *directory, int do_update, int reset_prompt)
|
||||
subshell_state = RUNNING_COMMAND;
|
||||
feed_subshell (QUIETLY, FALSE);
|
||||
|
||||
if (subshell_alive && strcmp (subshell_cwd, current_panel->cwd)
|
||||
&& strcmp (current_panel->cwd, ".")) {
|
||||
if (subshell_type == TCSH) {
|
||||
char rp_subshell_cwd[PATH_MAX];
|
||||
char rp_current_panel_cwd[PATH_MAX];
|
||||
|
||||
if (mc_realpath(subshell_cwd, rp_subshell_cwd) == NULL)
|
||||
strlcpy(rp_subshell_cwd, subshell_cwd, PATH_MAX);
|
||||
|
||||
if (mc_realpath(current_panel->cwd, rp_current_panel_cwd) == NULL)
|
||||
strlcpy(rp_current_panel_cwd, current_panel->cwd, PATH_MAX);
|
||||
|
||||
bPathNotEq = strcmp (rp_subshell_cwd, rp_current_panel_cwd);
|
||||
} else bPathNotEq = strcmp (subshell_cwd, current_panel->cwd);
|
||||
|
||||
if (subshell_alive && bPathNotEq && strcmp (current_panel->cwd, ".")) {
|
||||
char *cwd = strip_password (g_strdup (current_panel->cwd), 1);
|
||||
fprintf (stderr, _("Warning: Cannot change to %s.\n"),
|
||||
cwd);
|
||||
|
18
src/util.h
18
src/util.h
@ -148,6 +148,24 @@ void rotate_dash (void);
|
||||
const char *mc_tmpdir (void);
|
||||
int mc_mkstemps(char **pname, const char *prefix, const char *suffix);
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#ifdef _POSIX_VERSION
|
||||
#define PATH_MAX _POSIX_PATH_MAX
|
||||
#else
|
||||
#ifdef MAXPATHLEN
|
||||
#define PATH_MAX MAXPATHLEN
|
||||
#else
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef MAXSYMLINKS
|
||||
#define MAXSYMLINKS 32
|
||||
#endif
|
||||
|
||||
char *mc_realpath(const char *path, char resolved_path[]);
|
||||
|
||||
enum {
|
||||
COMPRESSION_NONE,
|
||||
COMPRESSION_GZIP,
|
||||
|
118
src/utilunix.c
118
src/utilunix.c
@ -4,6 +4,9 @@
|
||||
Miguel de Icaza, Janne Kukonlehto, Dugan Porter,
|
||||
Jakub Jelinek, Mauricio Plaza.
|
||||
|
||||
The mc_realpath routine is mostly from uClibc package, written
|
||||
by Rick Sladkey <jrs@world.std.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
@ -27,6 +30,7 @@
|
||||
#include <signal.h> /* struct sigaction */
|
||||
#include <limits.h> /* INT_MAX */
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h> /* for MAXPATHLEN */
|
||||
#include <stdarg.h>
|
||||
#include <errno.h> /* errno */
|
||||
#include <string.h>
|
||||
@ -673,3 +677,117 @@ putenv (char *string)
|
||||
}
|
||||
#endif /* !HAVE_PUTENV */
|
||||
|
||||
char *
|
||||
mc_realpath (const char *path, char resolved_path[])
|
||||
{
|
||||
char copy_path[PATH_MAX];
|
||||
char link_path[PATH_MAX];
|
||||
char got_path[PATH_MAX];
|
||||
char *new_path = got_path;
|
||||
char *max_path;
|
||||
int readlinks = 0;
|
||||
int n;
|
||||
|
||||
/* Make a copy of the source path since we may need to modify it. */
|
||||
if (strlen (path) >= PATH_MAX - 2) {
|
||||
errno = ENAMETOOLONG;
|
||||
return NULL;
|
||||
}
|
||||
strcpy (copy_path, path);
|
||||
path = copy_path;
|
||||
max_path = copy_path + PATH_MAX - 2;
|
||||
/* If it's a relative pathname use getwd for starters. */
|
||||
if (*path != '/') {
|
||||
/* Ohoo... */
|
||||
#ifdef HAVE_GETCWD
|
||||
getcwd (new_path, PATH_MAX - 1);
|
||||
#else
|
||||
getwd (new_path);
|
||||
#endif
|
||||
new_path += strlen (new_path);
|
||||
if (new_path[-1] != '/')
|
||||
*new_path++ = '/';
|
||||
} else {
|
||||
*new_path++ = '/';
|
||||
path++;
|
||||
}
|
||||
/* Expand each slash-separated pathname component. */
|
||||
while (*path != '\0') {
|
||||
/* Ignore stray "/". */
|
||||
if (*path == '/') {
|
||||
path++;
|
||||
continue;
|
||||
}
|
||||
if (*path == '.') {
|
||||
/* Ignore ".". */
|
||||
if (path[1] == '\0' || path[1] == '/') {
|
||||
path++;
|
||||
continue;
|
||||
}
|
||||
if (path[1] == '.') {
|
||||
if (path[2] == '\0' || path[2] == '/') {
|
||||
path += 2;
|
||||
/* Ignore ".." at root. */
|
||||
if (new_path == got_path + 1)
|
||||
continue;
|
||||
/* Handle ".." by backing up. */
|
||||
while ((--new_path)[-1] != '/');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Safely copy the next pathname component. */
|
||||
while (*path != '\0' && *path != '/') {
|
||||
if (path > max_path) {
|
||||
errno = ENAMETOOLONG;
|
||||
return NULL;
|
||||
}
|
||||
*new_path++ = *path++;
|
||||
}
|
||||
#ifdef S_IFLNK
|
||||
/* Protect against infinite loops. */
|
||||
if (readlinks++ > MAXSYMLINKS) {
|
||||
errno = ELOOP;
|
||||
return NULL;
|
||||
}
|
||||
/* See if latest pathname component is a symlink. */
|
||||
*new_path = '\0';
|
||||
n = readlink (got_path, link_path, PATH_MAX - 1);
|
||||
if (n < 0) {
|
||||
/* EINVAL means the file exists but isn't a symlink. */
|
||||
if (errno != EINVAL) {
|
||||
/* Make sure it's null terminated. */
|
||||
*new_path = '\0';
|
||||
strcpy (resolved_path, got_path);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* Note: readlink doesn't add the null byte. */
|
||||
link_path[n] = '\0';
|
||||
if (*link_path == '/')
|
||||
/* Start over for an absolute symlink. */
|
||||
new_path = got_path;
|
||||
else
|
||||
/* Otherwise back up over this component. */
|
||||
while (*(--new_path) != '/');
|
||||
/* Safe sex check. */
|
||||
if (strlen (path) + n >= PATH_MAX - 2) {
|
||||
errno = ENAMETOOLONG;
|
||||
return NULL;
|
||||
}
|
||||
/* Insert symlink contents into path. */
|
||||
strcat (link_path, path);
|
||||
strcpy (copy_path, link_path);
|
||||
path = copy_path;
|
||||
}
|
||||
#endif /* S_IFLNK */
|
||||
*new_path++ = '/';
|
||||
}
|
||||
/* Delete trailing slash but don't whomp a lone slash. */
|
||||
if (new_path != got_path + 1 && new_path[-1] == '/')
|
||||
new_path--;
|
||||
/* Make sure it's null terminated. */
|
||||
*new_path = '\0';
|
||||
strcpy (resolved_path, got_path);
|
||||
return resolved_path;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user