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:
Patrick Winnertz 2009-02-10 13:54:23 +01:00
parent f237a14635
commit 7d0fa9afce
2 changed files with 188 additions and 1 deletions

View File

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

View File

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