From 86e52e3c33843f67a7972181ccbf33b48a40e557 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 20 Oct 2020 14:08:35 +0200 Subject: [PATCH] Replace most calls to open by a new wrapper. * common/sysutils.c (any8bitchar) [W32]: New. (gnupg_open): New. Replace most calls to open by this. * common/iobuf.c (any8bitchar) [W32]: New. (direct_open) [W32]: Use CreateFileW if needed. -- This is yet another step for full Unicode support on Windows. GnuPG-bug-id: 5098 (cherry picked from commit 4dcef0e17836e8725c31a3b76f2bf7144345c808) --- common/iobuf.c | 45 +++++++++++++++++++++++++++++--------------- common/sysutils.c | 36 +++++++++++++++++++++++++++++++++++ common/sysutils.h | 1 + dirmngr/crlcache.c | 4 ++-- g10/gpg.c | 6 +++--- g10/tdbio.c | 6 +++--- sm/gpgsm.c | 2 +- tools/gpgconf-comp.c | 5 +++-- 8 files changed, 79 insertions(+), 26 deletions(-) diff --git a/common/iobuf.c b/common/iobuf.c index b20761ba1..4fd8cf57d 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -193,6 +193,19 @@ fd_cache_strcmp (const char *a, const char *b) #endif } + +#ifdef HAVE_W32_SYSTEM +static int +any8bitchar (const char *string) +{ + if (string) + for ( ; *string; string++) + if ((*string & 0x80)) + return 1; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + /* * Invalidate (i.e. close) a cached iobuf */ @@ -294,21 +307,23 @@ direct_open (const char *fname, const char *mode, int mode700) sm = FILE_SHARE_READ; } -#ifdef HAVE_W32CE_SYSTEM - { - wchar_t *wfname = utf8_to_wchar (fname); - if (wfname) - { - hfile = CreateFile (wfname, da, sm, NULL, cd, - FILE_ATTRIBUTE_NORMAL, NULL); - xfree (wfname); - } - else - hfile = INVALID_HANDLE_VALUE; - } -#else - hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL); -#endif + /* We use the Unicode version of the function only if needed to + * avoid an extra conversion step. */ + if (any8bitchar (fname)) + { + wchar_t *wfname = utf8_to_wchar (fname); + if (wfname) + { + hfile = CreateFileW (wfname, da, sm, NULL, cd, + FILE_ATTRIBUTE_NORMAL, NULL); + xfree (wfname); + } + else + hfile = INVALID_HANDLE_VALUE; + } + else + hfile = CreateFileA (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL); + return hfile; #else /*!HAVE_W32_SYSTEM*/ diff --git a/common/sysutils.c b/common/sysutils.c index 7b2f70311..e06be057f 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -171,6 +171,18 @@ enable_core_dumps (void) #endif } +#ifdef HAVE_W32_SYSTEM +static int +any8bitchar (const char *string) +{ + if (string) + for ( ; *string; string++) + if ((*string & 0x80)) + return 1; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + /* Allow the use of special "-&nnn" style file names. */ void @@ -1095,6 +1107,30 @@ gnupg_access (const char *name, int mode) #endif } +/* A wrapper around open to handle Unicode file names under Windows. */ +int +gnupg_open (const char *name, int flags, unsigned int mode) +{ +#ifdef HAVE_W32_SYSTEM + if (any8bitchar (name)) + { + wchar_t *wname; + int ret; + + wname = utf8_to_wchar (name); + if (!wname) + return -1; + ret = _wopen (wname, flags, mode); + xfree (wname); + return ret; + } + else + return open (name, flags, mode); +#else + return open (name, flags, mode); +#endif +} + #ifdef HAVE_W32CE_SYSTEM diff --git a/common/sysutils.h b/common/sysutils.h index 1970f0a26..aabd15f8b 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -73,6 +73,7 @@ int gnupg_setenv (const char *name, const char *value, int overwrite); int gnupg_unsetenv (const char *name); char *gnupg_getcwd (void); gpg_err_code_t gnupg_access (const char *name, int mode); +int gnupg_open (const char *name, int flags, unsigned int mode); char *gnupg_get_socket_name (int fd); int gnupg_fd_valid (int fd); diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c index cd35335ce..e8d5e0332 100644 --- a/dirmngr/crlcache.c +++ b/dirmngr/crlcache.c @@ -1142,7 +1142,7 @@ lock_db_file (crl_cache_t cache, crl_cache_entry_t entry) xfree (fname); return NULL; } - fd = open (fname, O_RDONLY | O_BINARY); + fd = gnupg_open (fname, O_RDONLY | O_BINARY, 0); if (fd == -1) { log_error (_("error opening cache file '%s': %s\n"), @@ -2226,7 +2226,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader) } } - fd_cdb = open (fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); + fd_cdb = gnupg_open (fname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd_cdb == -1) { err = gpg_error_from_errno (errno); diff --git a/g10/gpg.c b/g10/gpg.c index e6be86a3e..96c79b953 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1334,10 +1334,10 @@ open_info_file (const char *fname, int for_write, int binary) do { if (for_write) - fd = open (fname, O_CREAT | O_TRUNC | O_WRONLY | binary, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + fd = gnupg_open (fname, O_CREAT | O_TRUNC | O_WRONLY | binary, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); else - fd = open (fname, O_RDONLY | binary); + fd = gnupg_open (fname, O_RDONLY | binary, 0); } while (fd == -1 && errno == EINTR); /* } */ diff --git a/g10/tdbio.c b/g10/tdbio.c index 947dbb36d..b91a843ff 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -753,7 +753,7 @@ tdbio_set_dbname (ctrl_t ctrl, const char *new_dbname, log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno)); es_fclose (fp); - db_fd = open (db_name, O_RDWR | MY_O_BINARY); + db_fd = gnupg_open (db_name, O_RDWR | MY_O_BINARY, 0); if (db_fd == -1) log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno)); @@ -813,7 +813,7 @@ open_db () (int)prevrc, (int)GetLastError ()); } #else /*!HAVE_W32CE_SYSTEM*/ - db_fd = open (db_name, O_RDWR | MY_O_BINARY ); + db_fd = gnupg_open (db_name, O_RDWR | MY_O_BINARY, 0); if (db_fd == -1 && (errno == EACCES #ifdef EROFS || errno == EROFS @@ -821,7 +821,7 @@ open_db () ) ) { /* Take care of read-only trustdbs. */ - db_fd = open (db_name, O_RDONLY | MY_O_BINARY ); + db_fd = gnupg_open (db_name, O_RDONLY | MY_O_BINARY, 0); if (db_fd != -1 && !opt.quiet) log_info (_("Note: trustdb not writable\n")); } diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 492f63eab..eca266c8e 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -2213,7 +2213,7 @@ open_read (const char *filename) fd = check_special_filename (filename, 0, 0); if (fd != -1) return fd; - fd = open (filename, O_RDONLY | O_BINARY); + fd = gnupg_open (filename, O_RDONLY | O_BINARY, 0); if (fd == -1) { log_error (_("can't open '%s': %s\n"), filename, strerror (errno)); diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index ce21081f9..5903cf407 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -3016,8 +3016,9 @@ change_options_program (gc_component_t component, gc_backend_t backend, *dest_filenamep = dest_filename; *orig_filenamep = orig_filename; - /* Use open() so that we can use O_EXCL. */ - fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644); + /* Use open() so that we can use O_EXCL. + * FIXME: gpgrt has an x flag for quite some time now - use that. */ + fd = gnupg_open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644); if (fd < 0) return -1; src_file = gpgrt_fdopen (fd, "w");