summaryrefslogtreecommitdiffstats
path: root/misc.c
diff options
context:
space:
mode:
authorHeiko Hund <heiko.hund@sophos.com>2012-02-10 15:13:42 +0100
committerDavid Sommerseth <davids@redhat.com>2012-02-13 17:11:50 +0100
commit71bbbd76c62630c88441237d72fe5b61f0b45b2a (patch)
tree715f8c8183c6e47bb26f0a10c0f6b14f9b9f83a2 /misc.c
parent2ee0dc2bd72ec318fcc227af54e5ca7e1384a6cc (diff)
downloadopenvpn-71bbbd76c62630c88441237d72fe5b61f0b45b2a.tar.gz
openvpn-71bbbd76c62630c88441237d72fe5b61f0b45b2a.tar.xz
openvpn-71bbbd76c62630c88441237d72fe5b61f0b45b2a.zip
handle Windows unicode paths
Openvpn for Windows is not compiled as a Unicode binary and thus cannot handle paths which contain non-ASCII characters using the argv vector. Characters that are not present in the system codepage are simply replaced with a question mark, e.g. if started as 'openvpn --config домой.ovpn' the file '?????.ovpn' is tried to be opened as configuration. The same applies to paths in config files which need to be UTF-8 encoded if they contain non ASCII characters. The option line 'key лев.pem' will lead to openvpn trying to open 'лев.pem' on a system with codepage 1252. This patch makes openvpn read the command line in UCS-2 and convert it to UTF-8 internally. Windows stores names in the filesystem in UCS-2. When using a paths openvpn converts it from UTF-8 to UCS-2 and uses the wide character Windows API function. Signed-off-by: Heiko Hund <heiko.hund@sophos.com> Acked-by: David Sommerseth <davids@redhat.com> Signed-off-by: David Sommerseth <davids@redhat.com>
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c41
1 files changed, 36 insertions, 5 deletions
diff --git a/misc.c b/misc.c
index 1aa1be4..58096fa 100644
--- a/misc.c
+++ b/misc.c
@@ -246,7 +246,7 @@ get_pid_file (const char* filename, struct pid_state *state)
CLEAR (*state);
if (filename)
{
- state->fp = fopen (filename, "w");
+ state->fp = openvpn_fopen (filename, "w");
if (!state->fp)
msg (M_ERR, "Open error on pid file %s", filename);
state->filename = filename;
@@ -356,7 +356,15 @@ int
openvpn_chdir (const char* dir)
{
#ifdef HAVE_CHDIR
+#ifdef TARGET_WIN32
+ int res;
+ struct gc_arena gc = gc_new ();
+ res = _wchdir (wide_string (dir, &gc));
+ gc_free (&gc);
+ return res;
+#else
return chdir (dir);
+#endif
#else
return -1;
#endif
@@ -571,6 +579,7 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
{
#ifdef HAVE_SYSTEM
int ret;
+ struct gc_arena gc;
perf_push (PERF_SCRIPT);
@@ -589,7 +598,13 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
/*
* execute the command
*/
+#ifdef TARGET_WIN32
+ gc = gc_new ();
+ ret = _wsystem (wide_string (command, &gc));
+ gc_free (&gc);
+#else
ret = system (command);
+#endif
/* debugging */
dmsg (D_SCRIPT, "SYSTEM return=%u", ret);
@@ -609,6 +624,19 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
#endif
}
+int
+openvpn_access (const char *path, int mode)
+{
+#ifdef TARGET_WIN32
+ struct gc_arena gc = gc_new ();
+ int ret = _waccess (wide_string (path, &gc), mode);
+ gc_free (&gc);
+ return ret;
+#else
+ return access (path, mode);
+#endif
+}
+
/*
* Run execve() inside a fork(), duping stdout. Designed to replicate the semantics of popen() but
* in a safer way that doesn't require the invocation of a shell or the risks
@@ -1200,7 +1228,7 @@ test_file (const char *filename)
bool ret = false;
if (filename)
{
- FILE *fp = fopen (filename, "r");
+ FILE *fp = openvpn_fopen (filename, "r");
if (fp)
{
fclose (fp);
@@ -1248,7 +1276,7 @@ create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc
/* Atomically create the file. Errors out if the file already
exists. */
- fd = open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
+ fd = openvpn_open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd != -1)
{
close (fd);
@@ -1349,7 +1377,10 @@ bool
delete_file (const char *filename)
{
#if defined(WIN32)
- return (DeleteFile (filename) != 0);
+ struct gc_arena gc = gc_new ();
+ BOOL ret = DeleteFileW (wide_string (filename, &gc));
+ gc_free (&gc);
+ return (ret != 0);
#elif defined(HAVE_UNLINK)
return (unlink (filename) == 0);
#else
@@ -1647,7 +1678,7 @@ get_user_pass_cr (struct user_pass *up,
warn_if_group_others_accessible (auth_file);
- fp = fopen (auth_file, "r");
+ fp = openvpn_fopen (auth_file, "r");
if (!fp)
msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);