mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
fixed canonicalize_pathname() breakage: fixed str_move() function (memmove semantics) again
and add shell_(un)escape again
This patch reintroduces fix firstly appeared in (and recently broken by mhl revert)
> commit e48cb7c89f
> Author: Sergei Trofimovich <st@anti-virus.by>
> Date: Fri Jan 30 09:31:28 2009 +0200
>
> mhl: added mhl_strmove() function (memmove semantics)
...
> Snippet of man strcpy:
> DESCRIPTION
> The strcpy() function copies the string pointed to by src, including the terminating
> null byte ('\0'), to the buffer pointed to by dest. ___The strings may not overlap___,
> and the destination string dest must be large enough to receive the copy.
> We used strcpy to move data chunk in memory: "./foo" -> "foo", etc.
>
> This patch introduces mhl_strmove and fixed canonicalize_pathname.
Conflicts:
src/util.h
Signed-off-by: Patrick Winnertz <winnie@debian.org>
This commit is contained in:
parent
f237a14635
commit
7d0fa9afce
154
src/util.c
154
src/util.c
@ -1531,3 +1531,157 @@ Q_ (const char *s)
|
|||||||
sep = strchr(result, '|');
|
sep = strchr(result, '|');
|
||||||
return (sep != NULL) ? sep + 1 : result;
|
return (sep != NULL) ? sep + 1 : result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define shell_escape_toesc(x) \
|
||||||
|
(((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \
|
||||||
|
((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \
|
||||||
|
((x)=='{')||((x)=='}')||((x)=='[')||((x)==']')||((x)=='`')|| \
|
||||||
|
((x)=='?')||((x)=='|')||((x)=='<')||((x)=='>')||((x)==';')|| \
|
||||||
|
((x)=='*')||((x)=='\\')||((x)=='"'))
|
||||||
|
|
||||||
|
#define shell_escape_nottoesc(x) \
|
||||||
|
(((x)!=0) && (!shell_escape_toesc((x))))
|
||||||
|
/** To be compatible with the general posix command lines we have to escape
|
||||||
|
strings for the command line
|
||||||
|
|
||||||
|
\params in
|
||||||
|
string for escaping
|
||||||
|
|
||||||
|
\returns
|
||||||
|
return escaped string (which needs to be freed later)
|
||||||
|
*/
|
||||||
|
char*
|
||||||
|
shell_escape(const char* src)
|
||||||
|
{
|
||||||
|
GString *str;
|
||||||
|
char *result = NULL;
|
||||||
|
|
||||||
|
if ((src==NULL)||(!(*src)))
|
||||||
|
return strdup("");
|
||||||
|
|
||||||
|
str = g_string_new("");
|
||||||
|
|
||||||
|
/* look for the first char to escape */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
/* copy over all chars not to escape */
|
||||||
|
while ((c=(*src)) && shell_escape_nottoesc(c))
|
||||||
|
{
|
||||||
|
g_string_append_c(str,c);
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at this point we either have an \0 or an char to escape */
|
||||||
|
if (!c) {
|
||||||
|
result = str->str;
|
||||||
|
g_string_free(str,FALSE);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append_c(str,'\\');
|
||||||
|
g_string_append_c(str,c);
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unescape paths or other strings for e.g the internal cd
|
||||||
|
shell-unescape within a given buffer (writing to it!)
|
||||||
|
|
||||||
|
\params src
|
||||||
|
string for unescaping
|
||||||
|
|
||||||
|
\returns
|
||||||
|
return unescaped string (which needs to be freed)
|
||||||
|
*/
|
||||||
|
char*
|
||||||
|
shell_unescape(const char* text)
|
||||||
|
{
|
||||||
|
GString *str;
|
||||||
|
char *result = NULL;
|
||||||
|
|
||||||
|
if (!text)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* look for the first \ - that's quick skipover if there's nothing to escape */
|
||||||
|
const char* readptr = text;
|
||||||
|
while ((*readptr) && ((*readptr)!='\\')) readptr++;
|
||||||
|
if (!(*readptr)) {
|
||||||
|
result = g_strdup(text);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
str = g_string_new_len(text, readptr - text);
|
||||||
|
|
||||||
|
/* if we're here, we're standing on the first '\' */
|
||||||
|
char c;
|
||||||
|
while ((c = *readptr))
|
||||||
|
{
|
||||||
|
if (c=='\\')
|
||||||
|
{
|
||||||
|
readptr++;
|
||||||
|
switch ((c = *readptr))
|
||||||
|
{
|
||||||
|
case '\0': /* end of string! malformed escape string */
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
case 'n': g_string_append_c(str,'\n'); break;
|
||||||
|
case 'r': g_string_append_c(str,'\r'); break;
|
||||||
|
case 't': g_string_append_c(str,'\t'); break;
|
||||||
|
|
||||||
|
case ' ':
|
||||||
|
case '\\':
|
||||||
|
case '#':
|
||||||
|
case '$':
|
||||||
|
case '%':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '!':
|
||||||
|
case '*':
|
||||||
|
case '?':
|
||||||
|
case '~':
|
||||||
|
case '`':
|
||||||
|
case '"':
|
||||||
|
case ';':
|
||||||
|
default:
|
||||||
|
g_string_append_c(str,c); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* got a normal character */
|
||||||
|
{
|
||||||
|
g_string_append_c(str,c);
|
||||||
|
}
|
||||||
|
readptr++;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
|
||||||
|
result = str->str;
|
||||||
|
g_string_free(str,FALSE);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if char in pointer contain escape'd chars
|
||||||
|
|
||||||
|
\params in
|
||||||
|
string for checking
|
||||||
|
|
||||||
|
\returns
|
||||||
|
return TRUE if string contain escaped chars
|
||||||
|
otherwise return FALSE
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
shell_is_char_escaped ( const char *in )
|
||||||
|
{
|
||||||
|
if (in == NULL || !*in || in[0] != '\\')
|
||||||
|
return FALSE;
|
||||||
|
if (shell_escape_toesc(in[1]))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
35
src/util.h
35
src/util.h
@ -1,7 +1,9 @@
|
|||||||
#ifndef MC_UTIL_H
|
#ifndef MC_UTIL_H
|
||||||
#define MC_UTIL_H
|
#define MC_UTIL_H96fc77bc3ee1f2ae2ae7c0a14d3bf08975b4cb66
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* Returns its argument as a "modifiable" string. This function is
|
/* Returns its argument as a "modifiable" string. This function is
|
||||||
* intended to pass strings to legacy libraries that don't know yet
|
* intended to pass strings to legacy libraries that don't know yet
|
||||||
@ -256,4 +258,35 @@ extern int ascii_alpha_to_cntrl (int ch);
|
|||||||
#undef Q_
|
#undef Q_
|
||||||
const char *Q_ (const char *s);
|
const char *Q_ (const char *s);
|
||||||
|
|
||||||
|
|
||||||
|
gboolean shell_is_char_escaped ( const char * );
|
||||||
|
char *shell_unescape( const char * );
|
||||||
|
char *shell_escape( const char * );
|
||||||
|
|
||||||
|
#define str_dup_range(s_start, s_bound) (g_strndup(s_start, s_bound - s_start))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* strcpy is unsafe on overlapping memory areas, so define memmove-alike
|
||||||
|
* string function.
|
||||||
|
* Have sense only when:
|
||||||
|
* * dest <= src
|
||||||
|
* AND
|
||||||
|
* * dest and str are pointers to one object (as Roland Illig pointed).
|
||||||
|
*
|
||||||
|
* We can't use str*cpy funs here:
|
||||||
|
* http://kerneltrap.org/mailarchive/openbsd-misc/2008/5/27/1951294
|
||||||
|
*/
|
||||||
|
static inline char * str_move(char * dest, const char * src)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
assert (dest<=src);
|
||||||
|
|
||||||
|
n = strlen (src) + 1; /* + '\0' */
|
||||||
|
|
||||||
|
return memmove (dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MC_PTR_FREE(ptr) do { g_free(ptr); (ptr) = NULL; } while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user