summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2011-12-08 00:40:45 +0100
committerDavid Sommerseth <davids@redhat.com>2012-01-10 19:38:35 +0100
commitec302f7061b7ab4dd21bdac77dd115e75b50cbc0 (patch)
treee55a9cccd3446f94f86e505259aad7b890bae0e5
parent8ee5646111625c598efbc82413649b1ab6275877 (diff)
downloadopenvpn-ec302f7061b7ab4dd21bdac77dd115e75b50cbc0.tar.gz
openvpn-ec302f7061b7ab4dd21bdac77dd115e75b50cbc0.tar.xz
openvpn-ec302f7061b7ab4dd21bdac77dd115e75b50cbc0.zip
Move away from openvpn_basename() over to platform provided basename()
This kicks out the openvpn_basename() function from misc.[ch] and puts glibc equivalents into compat.[ch]. This is to provide the same functionality on platforms not having a native basename() function available. In addition this patch adds dirname() which commit 0f2bc0dd92f43c91e depends. Without dirname(), openvpn won't build in Visual Studio. v2: Move all functions from compat.h to compat.c v3: Use glibc versions of basename() and dirname() instead Signed-off-by: David Sommerseth <davids@redhat.com> Acked-by: Alon Bar-Lev <alon.barlev@gmail.com> URL: http://thread.gmane.org/gmane.network.openvpn.devel/5178/focus=5215
-rw-r--r--Makefile.am1
-rw-r--r--compat.c129
-rw-r--r--compat.h42
-rw-r--r--configure.ac2
-rw-r--r--init.c6
-rw-r--r--misc.c23
-rw-r--r--misc.h3
-rw-r--r--options.c1
-rw-r--r--syshead.h2
9 files changed, 182 insertions, 27 deletions
diff --git a/Makefile.am b/Makefile.am
index a47c0c1..ab86cc1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -84,6 +84,7 @@ openvpn_SOURCES = \
circ_list.h \
clinat.c clinat.h \
common.h \
+ compat.h compat.c \
config-win32.h \
crypto.c crypto.h crypto_backend.h \
crypto_openssl.c crypto_openssl.h \
diff --git a/compat.c b/compat.c
new file mode 100644
index 0000000..cb599b0
--- /dev/null
+++ b/compat.c
@@ -0,0 +1,129 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2011 - David Sommerseth <davids@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "syshead.h"
+#include "compat.h"
+#include <string.h>
+
+
+#ifndef HAVE_DIRNAME
+/* Unoptimised version of glibc memrchr().
+ * This is considered fast enough, as only this compat
+ * version of dirname() depends on it.
+ */
+static const char *
+__memrchr(const char *str, int c, size_t n)
+{
+ const char *end = str;
+
+ end += n - 1; /* Go to the end of the string */
+ while (end >= str) {
+ if(c == *end)
+ return end;
+ else
+ end--;
+ }
+ return NULL;
+}
+
+/* Modified version based on glibc-2.14.1 by Ulrich Drepper <drepper@akkadia.org>
+ * This version is extended to handle both / and \ in path names.
+ */
+char *
+dirname (char *path)
+{
+ static const char dot[] = ".";
+ char *last_slash;
+ char separator = '/';
+
+ /* Find last '/'. */
+ last_slash = path != NULL ? strrchr (path, '/') : NULL;
+ /* If NULL, check for \ instead ... might be Windows a path */
+ if (!last_slash) {
+ last_slash = path != NULL ? strrchr (path, '\\') : NULL;
+ separator = last_slash ? '\\' : '/'; /* Change the separator if \ was found */
+ }
+
+ if (last_slash != NULL && last_slash != path && last_slash[1] == '\0') {
+ /* Determine whether all remaining characters are slashes. */
+ char *runp;
+
+ for (runp = last_slash; runp != path; --runp)
+ if (runp[-1] != separator)
+ break;
+
+ /* The '/' is the last character, we have to look further. */
+ if (runp != path)
+ last_slash = (char *) __memrchr (path, separator, runp - path);
+ }
+
+ if (last_slash != NULL) {
+ /* Determine whether all remaining characters are slashes. */
+ char *runp;
+
+ for (runp = last_slash; runp != path; --runp)
+ if (runp[-1] != separator)
+ break;
+
+ /* Terminate the path. */
+ if (runp == path) {
+ /* The last slash is the first character in the string. We have to
+ return "/". As a special case we have to return "//" if there
+ are exactly two slashes at the beginning of the string. See
+ XBD 4.10 Path Name Resolution for more information. */
+ if (last_slash == path + 1)
+ ++last_slash;
+ else
+ last_slash = path + 1;
+ }
+ else
+ last_slash = runp;
+
+ last_slash[0] = '\0';
+ } else
+ /* This assignment is ill-designed but the XPG specs require to
+ return a string containing "." in any case no directory part is
+ found and so a static and constant string is required. */
+ path = (char *) dot;
+
+ return path;
+}
+#endif /* HAVE_DIRNAME */
+
+
+#ifndef HAVE_BASENAME
+/* Modified version based on glibc-2.14.1 by Roland McGrath <roland@gnu.org>
+ * This version is extended to handle both / and \ in path names
+ */
+char *
+basename (const char *filename)
+{
+ char *p = strrchr (filenamem, '/');
+ if (!p) {
+ /* If NULL, check for \ instead ... might be Windows a path */
+ p = strrchr (filename, '\\');
+ }
+ return p ? p + 1 : (char *) filename;
+}
+#endif /* HAVE_BASENAME */
diff --git a/compat.h b/compat.h
new file mode 100644
index 0000000..b380f0b
--- /dev/null
+++ b/compat.h
@@ -0,0 +1,42 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2011 - David Sommerseth <davids@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef COMPAT_H
+#define COMPAT_H
+
+#include "config.h"
+
+#if defined(HAVE_BASENAME) || defined(HAVE_DIRNAME)
+#include <libgen.h>
+#endif
+
+#ifndef HAVE_DIRNAME
+char * dirname(char *str);
+#endif /* HAVE_DIRNAME */
+
+#ifndef HAVE_BASENAME
+char * basename(char *str);
+#endif /* HAVE_BASENAME */
+
+#endif /* COMPAT_H */
diff --git a/configure.ac b/configure.ac
index 7143cc5..d147d38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -521,7 +521,7 @@ AC_CHECK_FUNCS(daemon chroot getpwnam setuid nice system getpid dup dup2 dnl
getpass strerror syslog openlog mlockall getgrnam setgid dnl
setgroups stat flock readv writev time dnl
setsid chdir putenv getpeername unlink dnl
- chsize ftruncate execve getpeereid umask)
+ chsize ftruncate execve getpeereid umask basename dirname)
# Windows use stdcall for winsock so we cannot auto detect these
m4_define([SOCKET_FUNCS], [socket recv recvfrom send sendto listen dnl
diff --git a/init.c b/init.c
index a225c26..00e93c9 100644
--- a/init.c
+++ b/init.c
@@ -879,8 +879,10 @@ init_verb_mute (struct context *c, unsigned int flags)
void
init_options_dev (struct options *options)
{
- if (!options->dev)
- options->dev = openvpn_basename (options->dev_node);
+ if (!options->dev && options->dev_node) {
+ char *dev_node = strdup(options->dev_node); /* POSIX basename() implementaions may modify its arguments */
+ options->dev = basename (dev_node);
+ }
}
bool
diff --git a/misc.c b/misc.c
index b834a3e..bff67a7 100644
--- a/misc.c
+++ b/misc.c
@@ -2145,13 +2145,15 @@ argv_extract_cmd_name (const char *path)
{
if (path)
{
- const char *bn = openvpn_basename (path);
+ char *path_cp = strdup(path); /* POSIX basename() implementaions may modify its arguments */
+ const char *bn = basename (path_cp);
if (bn)
{
char *ret = string_alloc (bn, NULL);
char *dot = strrchr (ret, '.');
if (dot)
*dot = '\0';
+ free(path_cp);
if (ret[0] != '\0')
return ret;
}
@@ -2493,25 +2495,6 @@ argv_test (void)
}
#endif
-const char *
-openvpn_basename (const char *path)
-{
- const char *ret;
- const int dirsep = OS_SPECIFIC_DIRSEP;
-
- if (path)
- {
- ret = strrchr (path, dirsep);
- if (ret && *ret)
- ++ret;
- else
- ret = path;
- if (*ret)
- return ret;
- }
- return NULL;
-}
-
/*
* Remove security-sensitive strings from control message
* so that they will not be output to log file.
diff --git a/misc.h b/misc.h
index b2e6f91..b1badd9 100644
--- a/misc.h
+++ b/misc.h
@@ -381,9 +381,6 @@ extern int script_method; /* GLOBAL */
/* return the next largest power of 2 */
size_t adjust_power_of_2 (size_t u);
-/* return the basename of path */
-const char *openvpn_basename (const char *path);
-
/*
* A printf-like function (that only recognizes a subset of standard printf
* format operators) that prints arguments to an argv list instead
diff --git a/options.c b/options.c
index a186276..67206aa 100644
--- a/options.c
+++ b/options.c
@@ -53,7 +53,6 @@
#include "forward.h"
#include <ctype.h>
#include <unistd.h>
-#include <libgen.h>
#include "memdbg.h"
diff --git a/syshead.h b/syshead.h
index 38de87b..fba6f84 100644
--- a/syshead.h
+++ b/syshead.h
@@ -36,6 +36,8 @@
#include "config.h"
#endif
+#include "compat.h"
+
/* branch prediction hints */
#if defined(__GNUC__)
# define likely(x) __builtin_expect((x),1)