* 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:
Andrew V. Samoilov 2005-01-13 19:37:46 +00:00
parent 33e157631c
commit d332606fd5
4 changed files with 160 additions and 2 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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,

View File

@ -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;
}