aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-04-15 14:40:48 +0000
committerWerner Koch <[email protected]>2014-04-22 13:58:33 +0000
commit71a54313adf7b57b7b27bb9ad07b142a34306260 (patch)
tree5c37da59f48b7c740f0ade7e85c0f22ac089d5a0
parentcommon: Add function gnupg_getcwd. (diff)
downloadgnupg-71a54313adf7b57b7b27bb9ad07b142a34306260.tar.gz
gnupg-71a54313adf7b57b7b27bb9ad07b142a34306260.zip
common: Add functions make_absfilename and make_absfilename_try.
* common/stringhelp.c (do_make_filename): Add modes 2 and 3. (make_absfilename): New. (make_absfilename_try): New.
Diffstat (limited to '')
-rw-r--r--common/stringhelp.c100
-rw-r--r--common/stringhelp.h3
-rw-r--r--common/t-stringhelp.c73
3 files changed, 174 insertions, 2 deletions
diff --git a/common/stringhelp.c b/common/stringhelp.c
index 7cbf82ccc..4d7c3a63b 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -1,6 +1,7 @@
/* stringhelp.c - standard string helper functions
* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007,
* 2008, 2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2014 Werner Koch
*
* This file is part of JNLIB, which is a subsystem of GnuPG.
*
@@ -49,9 +50,9 @@
#include "libjnlib-config.h"
#include "utf8conv.h"
+#include "sysutils.h"
#include "stringhelp.h"
-
#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
/* Sometimes we want to avoid mixing slashes and backslashes on W32
@@ -395,6 +396,12 @@ get_pwdir (int xmode, const char *name)
return result;
}
+
+/* xmode 0 := Return NULL on error
+ 1 := Terminate on error
+ 2 := Make sure that name is absolute; return NULL on error
+ 3 := Make sure that name is absolute; terminate on error
+ */
static char *
do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
{
@@ -404,6 +411,10 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
int skip = 1;
char *home_buffer = NULL;
char *name, *home, *p;
+ int want_abs;
+
+ want_abs = !!(xmode & 2);
+ xmode &= 1;
n = strlen (first_part) + 1;
argc = 0;
@@ -478,10 +489,65 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr)
p = stpcpy (name, first_part);
jnlib_free (home_buffer);
-
for (argc=0; argv[argc]; argc++)
p = stpcpy (stpcpy (p, "/"), argv[argc]);
+ if (want_abs)
+ {
+#ifdef HAVE_DRIVE_LETTERS
+ p = strchr (name, ':');
+ if (!p)
+ p = name;
+#else
+ p = name;
+#endif
+ if (*p != '/'
+#ifdef HAVE_DRIVE_LETTERS
+ && *p != '\\'
+#endif
+ )
+ {
+ home = gnupg_getcwd ();
+ if (!home)
+ {
+ if (xmode)
+ {
+ fprintf (stderr, "\nfatal: getcwd failed: %s\n",
+ strerror (errno));
+ exit(2);
+ }
+ jnlib_free (name);
+ return NULL;
+ }
+ n = strlen (home) + 1 + strlen (name) + 1;
+ if (xmode)
+ home_buffer = jnlib_xmalloc (n);
+ else
+ {
+ home_buffer = jnlib_malloc (n);
+ if (!home_buffer)
+ {
+ jnlib_free (name);
+ return NULL;
+ }
+ }
+ if (p == name)
+ p = home_buffer;
+ else /* Windows case. */
+ {
+ memcpy (home_buffer, p, p - name + 1);
+ p = home_buffer + (p - name + 1);
+ }
+ strcpy (stpcpy (stpcpy (p, home), "/"), name);
+ jnlib_free (name);
+ name = home_buffer;
+ /* Let's do a simple compression to catch the most common
+ case of using "." for gpg's --homedir option. */
+ n = strlen (name);
+ if (n > 2 && name[n-2] == '/' && name[n-1] == '.')
+ name[n-2] = 0;
+ }
+ }
return change_slashes (name);
}
@@ -515,6 +581,36 @@ make_filename_try (const char *first_part, ... )
return result;
}
+/* Construct an absolute filename from the NULL terminated list of
+ parts. Tilde expansion is done for the first argument. This
+ function terminates the process on memory shortage. */
+char *
+make_absfilename (const char *first_part, ... )
+{
+ va_list arg_ptr;
+ char *result;
+
+ va_start (arg_ptr, first_part);
+ result = do_make_filename (3, first_part, arg_ptr);
+ va_end (arg_ptr);
+ return result;
+}
+
+/* Construct an absolute filename from the NULL terminated list of
+ parts. Tilde expansion is done for the first argument. This
+ function may return NULL on error. */
+char *
+make_absfilename_try (const char *first_part, ... )
+{
+ va_list arg_ptr;
+ char *result;
+
+ va_start (arg_ptr, first_part);
+ result = do_make_filename (2, first_part, arg_ptr);
+ va_end (arg_ptr);
+ return result;
+}
+
/* Compare whether the filenames are identical. This is a
diff --git a/common/stringhelp.h b/common/stringhelp.h
index 21bb20d5a..1ad380e79 100644
--- a/common/stringhelp.h
+++ b/common/stringhelp.h
@@ -53,6 +53,9 @@ char *make_basename(const char *filepath, const char *inputpath);
char *make_dirname(const char *filepath);
char *make_filename( const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0);
char *make_filename_try (const char *first_part, ... ) GNUPG_GCC_A_SENTINEL(0);
+char *make_absfilename (const char *first_part, ...) GNUPG_GCC_A_SENTINEL(0);
+char *make_absfilename_try (const char *first_part,
+ ...) GNUPG_GCC_A_SENTINEL(0);
int compare_filenames( const char *a, const char *b );
int hextobyte (const char *s);
diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c
index 990a8004a..dcd5a453f 100644
--- a/common/t-stringhelp.c
+++ b/common/t-stringhelp.c
@@ -71,6 +71,34 @@ gethome (void)
}
+static char *
+mygetcwd (void)
+{
+ char *buffer;
+ size_t size = 100;
+
+ for (;;)
+ {
+ buffer = xmalloc (size+1);
+#ifdef HAVE_W32CE_SYSTEM
+ strcpy (buffer, "/"); /* Always "/". */
+ return buffer;
+#else
+ if (getcwd (buffer, size) == buffer)
+ return buffer;
+ xfree (buffer);
+ if (errno != ERANGE)
+ {
+ fprintf (stderr,"error getting current cwd: %s\n",
+ strerror (errno));
+ exit (2);
+ }
+ size *= 2;
+#endif
+ }
+}
+
+
static void
test_percent_escape (void)
{
@@ -407,6 +435,50 @@ test_make_filename_try (void)
}
+static void
+test_make_absfilename_try (void)
+{
+ char *out;
+ char *cwd = mygetcwd ();
+ size_t cwdlen = strlen (cwd);
+
+ out = make_absfilename_try ("foo", "bar", NULL);
+ if (!out)
+ fail (0);
+ if (strlen (out) < cwdlen + 7)
+ fail (0);
+ if (strncmp (out, cwd, cwdlen))
+ fail (0);
+ if (strcmp (out+cwdlen, "/foo/bar"))
+ fail (0);
+ xfree (out);
+
+ out = make_absfilename_try ("./foo", NULL);
+ if (!out)
+ fail (1);
+ if (strlen (out) < cwdlen + 5)
+ fail (1);
+ if (strncmp (out, cwd, cwdlen))
+ fail (1);
+ if (strcmp (out+cwdlen, "/./foo"))
+ fail (1);
+ xfree (out);
+
+ out = make_absfilename_try (".", NULL);
+ if (!out)
+ fail (2);
+ if (strlen (out) < cwdlen)
+ fail (2);
+ if (strncmp (out, cwd, cwdlen))
+ fail (2);
+ if (strcmp (out+cwdlen, ""))
+ fail (2);
+ xfree (out);
+
+ xfree (cwd);
+}
+
+
int
main (int argc, char **argv)
{
@@ -418,6 +490,7 @@ main (int argc, char **argv)
test_strconcat ();
test_xstrconcat ();
test_make_filename_try ();
+ test_make_absfilename_try ();
xfree (home_buffer);
return 0;