1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-15 00:29:49 +02:00

Implement tilde expansion in the same was as 1.4.

This commit is contained in:
Werner Koch 2009-08-26 08:55:57 +00:00
parent f816bdb381
commit 5134fee5b0
5 changed files with 300 additions and 46 deletions

View File

@ -1,3 +1,15 @@
2009-08-26 Werner Koch <wk@g10code.com>
* stringhelp.c [HAVE_PWD_H]: Include pwd.h.
(do_make_filename): New.
(make_filename, make_filename_try): Implement using the new
function.
* t-stringhelp.c (test_make_filename_try): New.
* t-support.c (gcry_strdup): Fix.
* stringhelp.h (make_filename, make_filename_try): Add sentinel
attribute.
2009-08-25 Werner Koch <wk@g10code.com> 2009-08-25 Werner Koch <wk@g10code.com>
* stringhelp.c: Include errno.h. * stringhelp.c: Include errno.h.

View File

@ -24,8 +24,13 @@
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
#include <windows.h> # include <windows.h>
#endif #endif
#include "libjnlib-config.h" #include "libjnlib-config.h"
@ -313,62 +318,159 @@ make_dirname(const char *filepath)
/* Implementation of make_filename and make_filename_try. We need to static char *
use macros here to avoid the use of the sometimes problematic do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
va_copy function which is not available on all systems. */ {
#define MAKE_FILENAME_PART1 \ const char *argv[32];
va_list arg_ptr; \ int argc;
size_t n; \ size_t n;
const char *s; \ int skip = 1;
char *name, *home, *p; \ char *home_buffer = NULL;
\ char *name, *home, *p;
va_start (arg_ptr, first_part); \
n = strlen (first_part) + 1; \ n = strlen (first_part) + 1;
while ( (s = va_arg (arg_ptr, const char *)) ) \ argc = 0;
n += strlen(s) + 1; \ while ( (argv[argc] = va_arg (arg_ptr, const char *)) )
va_end(arg_ptr); \ {
\ n += strlen (argv[argc]) + 1;
home = NULL; \ if (argc >= DIM (argv)-1)
if ( *first_part == '~' && first_part[1] == '/' \ {
&& (home = getenv("HOME")) && *home ) \ if (xmode)
n += strlen (home); BUG ();
errno = EINVAL;
return NULL;
}
argc++;
}
n++;
#define MAKE_FILENAME_PART2 \ home = NULL;
p = (home \ if (*first_part == '~')
? stpcpy (stpcpy (name,home), first_part + 1)\ {
: stpcpy(name, first_part)); \ if (first_part[1] == '/' || !first_part[1])
\ {
va_start (arg_ptr, first_part); \ /* This is the "~/" or "~" case. */
while ( (s = va_arg(arg_ptr, const char *)) ) \ home = getenv("HOME");
p = stpcpy (stpcpy (p,"/"), s); \
va_end(arg_ptr); \
return change_slashes (name);
#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H)
if (!home)
{
struct passwd *pwd;
pwd = getpwuid (getuid());
if (pwd)
{
if (xmode)
home_buffer = home = jnlib_xstrdup (pwd->pw_dir);
else
{
home_buffer = home = jnlib_strdup (pwd->pw_dir);
if (!home)
return NULL;
}
}
}
#endif /* HAVE_GETPWUID && HAVE_PWD_H */
if (home && *home)
n += strlen (home);
}
#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
else
{
/* This is the "~username/" or "~username" case. */
char *user;
struct passwd *pwd;
if (xmode)
user = jnlib_xstrdup (first_part+1);
else
{
user = jnlib_strdup (first_part+1);
if (!user)
return NULL;
}
p = strchr (user, '/');
if (p)
*p = 0;
skip = 1 + strlen (user);
/* Fixme: Use getwpnam_r if available. */
pwd = getpwnam (user);
jnlib_free (user);
if (pwd)
{
if (xmode)
home_buffer = home = jnlib_xstrdup (pwd->pw_dir);
else
{
home_buffer = home = jnlib_strdup (pwd->pw_dir);
if (!home)
return NULL;
}
}
if (home)
n += strlen (home);
else
skip = 1;
}
#endif /*HAVE_GETPWNAM && HAVE_PWD_H*/
}
if (xmode)
name = jnlib_xmalloc (n);
else
{
name = jnlib_malloc (n);
if (!name)
{
jnlib_free (home_buffer);
return NULL;
}
}
if (home)
p = stpcpy (stpcpy (name, home), first_part + skip);
else
p = stpcpy (name, first_part);
jnlib_free (home_buffer);
for (argc=0; argv[argc]; argc++)
p = stpcpy (stpcpy (p, "/"), argv[argc]);
return change_slashes (name);
}
/* Construct a filename from the NULL terminated list of parts. Tilde /* Construct a filename from the NULL terminated list of parts. Tilde
expansion is done here. This function terminates the process on expansion is done for the first argument. This function terminates
memory shortage. */ the process on memory shortage. */
char * char *
make_filename (const char *first_part, ... ) make_filename (const char *first_part, ... )
{ {
MAKE_FILENAME_PART1 va_list arg_ptr;
name = jnlib_xmalloc (n); char *result;
MAKE_FILENAME_PART2
va_start (arg_ptr, first_part);
result = do_make_filename (1, first_part, arg_ptr);
va_end (arg_ptr);
return result;
} }
/* Construct a filename from the NULL terminated list of parts. Tilde /* Construct a filename from the NULL terminated list of parts. Tilde
expansion is done here. This function may return NULL on error. */ expansion is done for the first argument. This function may return
NULL on error. */
char * char *
make_filename_try (const char *first_part, ... ) make_filename_try (const char *first_part, ... )
{ {
MAKE_FILENAME_PART1 va_list arg_ptr;
name = jnlib_malloc (n); char *result;
if (!name)
return NULL; va_start (arg_ptr, first_part);
MAKE_FILENAME_PART2 result = do_make_filename (0, first_part, arg_ptr);
va_end (arg_ptr);
return result;
} }
#undef MAKE_FILENAME_PART1
#undef MAKE_FILENAME_PART2

View File

@ -37,8 +37,8 @@ size_t length_sans_trailing_ws (const unsigned char *line, size_t len);
char *make_basename(const char *filepath, const char *inputpath); char *make_basename(const char *filepath, const char *inputpath);
char *make_dirname(const char *filepath); char *make_dirname(const char *filepath);
char *make_filename( const char *first_part, ... ); char *make_filename( const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0);
char *make_filename_try (const char *first_part, ... ); char *make_filename_try (const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0);
int compare_filenames( const char *a, const char *b ); int compare_filenames( const char *a, const char *b );
int hextobyte (const char *s); int hextobyte (const char *s);

View File

@ -22,12 +22,43 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_PWD_H
# include <pwd.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#include "stringhelp.h" #include "stringhelp.h"
#include "t-support.h" #include "t-support.h"
static char *home_buffer;
const char *
gethome (void)
{
if (!home_buffer)
{
char *home = getenv("HOME");
#if defined(HAVE_GETPWUID) && defined(HAVE_PWD_H)
if(home)
home_buffer = xstrdup (home);
else
{
struct passwd *pwd;
pwd = getpwuid (getuid());
if (pwd)
home_buffer = xstrdup (pwd->pw_dir);
}
#endif
}
return home_buffer;
}
static void static void
test_percent_escape (void) test_percent_escape (void)
@ -261,6 +292,110 @@ test_xstrconcat (void)
} }
static void
test_make_filename_try (void)
{
char *out;
const char *home = gethome ();
size_t homelen = home? strlen (home):0;
out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", NULL);
if (out)
fail (0);
else if (errno != EINVAL)
fail (0);
xfree (out);
out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", NULL);
if (out)
fail (0);
else if (errno != EINVAL)
fail (0);
xfree (out);
out = make_filename_try ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"1", "2", NULL);
if (!out || strcmp (out,
"1/2/3/4/5/6/7/8/9/10/"
"1/2/3/4/5/6/7/8/9/10/"
"1/2/3/4/5/6/7/8/9/10/"
"1/2"))
fail (0);
xfree (out);
out = make_filename_try ("foo", "~/bar", "baz/cde", NULL);
if (!out || strcmp (out, "foo/~/bar/baz/cde"))
fail (1);
xfree (out);
out = make_filename_try ("foo", "~/bar", "baz/cde/", NULL);
if (!out || strcmp (out, "foo/~/bar/baz/cde/"))
fail (1);
xfree (out);
out = make_filename_try ("/foo", "~/bar", "baz/cde/", NULL);
if (!out || strcmp (out, "/foo/~/bar/baz/cde/"))
fail (1);
xfree (out);
out = make_filename_try ("//foo", "~/bar", "baz/cde/", NULL);
if (!out || strcmp (out, "//foo/~/bar/baz/cde/"))
fail (1);
xfree (out);
out = make_filename_try ("", "~/bar", "baz/cde", NULL);
if (!out || strcmp (out, "/~/bar/baz/cde"))
fail (1);
xfree (out);
out = make_filename_try ("~/foo", "bar", NULL);
if (!out)
fail (2);
if (home)
{
if (strlen (out) < homelen + 7)
fail (2);
if (strncmp (out, home, homelen))
fail (2);
if (strcmp (out+homelen, "/foo/bar"))
fail (2);
}
else
{
if (strcmp (out, "~/foo/bar"))
fail (2);
}
xfree (out);
out = make_filename_try ("~", "bar", NULL);
if (!out)
fail (2);
if (home)
{
if (strlen (out) < homelen + 3)
fail (2);
if (strncmp (out, home, homelen))
fail (2);
if (strcmp (out+homelen, "/bar"))
fail (2);
}
else
{
if (strcmp (out, "~/bar"))
fail (2);
}
xfree (out);
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -271,7 +406,9 @@ main (int argc, char **argv)
test_compare_filenames (); test_compare_filenames ();
test_strconcat (); test_strconcat ();
test_xstrconcat (); test_xstrconcat ();
test_make_filename_try ();
xfree (home_buffer);
return 0; return 0;
} }

View File

@ -56,7 +56,10 @@ gcry_xmalloc (size_t n)
char * char *
gcry_strdup (const char *string) gcry_strdup (const char *string)
{ {
return malloc (strlen (string)+1); char *p = malloc (strlen (string)+1);
if (p)
strcpy (p, string);
return p;
} }