aboutsummaryrefslogtreecommitdiffstats
path: root/src/estream.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-08-21 19:11:21 +0000
committerWerner Koch <[email protected]>2020-08-21 19:11:21 +0000
commita68c1975bda47b0698b48761a62e95b371095e9a (patch)
treebc5220f82e0da76eaa44e3601773e04c4e470bac /src/estream.c
parentargparse: Handle a corner case of wrong ARGC. (diff)
downloadlibgpg-error-a68c1975bda47b0698b48761a62e95b371095e9a.tar.gz
libgpg-error-a68c1975bda47b0698b48761a62e95b371095e9a.zip
core,w32: Add UTF-8 support to gpgrt_fopen, gpgrt_mkdir and gpgrt_chdir.
* src/protos.h: New. * src/Makefile.am (libgpg_error_la_SOURCES): Add file. * src/gpgrt-int.h: Include protos.h. * src/sysutils.c (_gpgrt_mkdir) [W32]: Make UTF-8 aware. (_gpgrt_chdir) [W32]: Ditto. * src/w32-gettext.c: Include protos.h. (utf8_to_wchar): Allow for strings. (_gpgrt_utf8_to_wchar): New. (_gpgrt_free_wchar): New. * src/estream.c (map_w32_to_errno): Add more error codes. (_gpgrt_w32_set_errno): New. (any8bitchar) [W32]: New helper. (func_file_create) [W32]: Convert file name and use _wopen. -- GnuPG-bug-id: 4083 Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'src/estream.c')
-rw-r--r--src/estream.c125
1 files changed, 122 insertions, 3 deletions
diff --git a/src/estream.c b/src/estream.c
index 06ebdaa..0d37c1a 100644
--- a/src/estream.c
+++ b/src/estream.c
@@ -238,7 +238,8 @@ mem_free (void *p)
/*
* A Windows helper function to map a W32 API error code to a standard
- * system error code.
+ * system error code. That actually belong into sysutils but to allow
+ * standalone use of estream we keep it here.
*/
#ifdef HAVE_W32_SYSTEM
static int
@@ -256,11 +257,19 @@ map_w32_to_errno (DWORD w32_err)
return ENOENT;
case ERROR_ACCESS_DENIED:
- return EPERM;
+ return EPERM; /* ReactOS uses EACCES ("Permission denied") and
+ * is likely right because they used an
+ * undocumented function to associate the error
+ * codes. However we have always used EPERM
+ * ("Operation not permitted", e.g. function is
+ * required to be called by root) and we better
+ * stick to that to avoid surprising bugs. */
case ERROR_INVALID_HANDLE:
+ return EBADF;
+
case ERROR_INVALID_BLOCK:
- return EINVAL;
+ return ENOMEM;
case ERROR_NOT_ENOUGH_MEMORY:
return ENOMEM;
@@ -268,10 +277,90 @@ map_w32_to_errno (DWORD w32_err)
case ERROR_NO_DATA:
return EPIPE;
+ case ERROR_ALREADY_EXISTS:
+ return EEXIST;
+
+ /* This mapping has been taken from reactOS. */
+ case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
+ case ERROR_ARENA_TRASHED: return ENOMEM;
+ case ERROR_BAD_ENVIRONMENT: return E2BIG;
+ case ERROR_BAD_FORMAT: return ENOEXEC;
+ case ERROR_INVALID_DRIVE: return ENOENT;
+ case ERROR_CURRENT_DIRECTORY: return EACCES;
+ case ERROR_NOT_SAME_DEVICE: return EXDEV;
+ case ERROR_NO_MORE_FILES: return ENOENT;
+ case ERROR_WRITE_PROTECT: return EACCES;
+ case ERROR_BAD_UNIT: return EACCES;
+ case ERROR_NOT_READY: return EACCES;
+ case ERROR_BAD_COMMAND: return EACCES;
+ case ERROR_CRC: return EACCES;
+ case ERROR_BAD_LENGTH: return EACCES;
+ case ERROR_SEEK: return EACCES;
+ case ERROR_NOT_DOS_DISK: return EACCES;
+ case ERROR_SECTOR_NOT_FOUND: return EACCES;
+ case ERROR_OUT_OF_PAPER: return EACCES;
+ case ERROR_WRITE_FAULT: return EACCES;
+ case ERROR_READ_FAULT: return EACCES;
+ case ERROR_GEN_FAILURE: return EACCES;
+ case ERROR_SHARING_VIOLATION: return EACCES;
+ case ERROR_LOCK_VIOLATION: return EACCES;
+ case ERROR_WRONG_DISK: return EACCES;
+ case ERROR_SHARING_BUFFER_EXCEEDED: return EACCES;
+ case ERROR_BAD_NETPATH: return ENOENT;
+ case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
+ case ERROR_BAD_NET_NAME: return ENOENT;
+ case ERROR_FILE_EXISTS: return EEXIST;
+ case ERROR_CANNOT_MAKE: return EACCES;
+ case ERROR_FAIL_I24: return EACCES;
+ case ERROR_NO_PROC_SLOTS: return EAGAIN;
+ case ERROR_DRIVE_LOCKED: return EACCES;
+ case ERROR_BROKEN_PIPE: return EPIPE;
+ case ERROR_DISK_FULL: return ENOSPC;
+ case ERROR_INVALID_TARGET_HANDLE: return EBADF;
+ case ERROR_WAIT_NO_CHILDREN: return ECHILD;
+ case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
+ case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
+ case ERROR_SEEK_ON_DEVICE: return EACCES;
+ case ERROR_DIR_NOT_EMPTY: return ENOTEMPTY;
+ case ERROR_NOT_LOCKED: return EACCES;
+ case ERROR_BAD_PATHNAME: return ENOENT;
+ case ERROR_MAX_THRDS_REACHED: return EAGAIN;
+ case ERROR_LOCK_FAILED: return EACCES;
+ case ERROR_INVALID_STARTING_CODESEG: return ENOEXEC;
+ case ERROR_INVALID_STACKSEG: return ENOEXEC;
+ case ERROR_INVALID_MODULETYPE: return ENOEXEC;
+ case ERROR_INVALID_EXE_SIGNATURE: return ENOEXEC;
+ case ERROR_EXE_MARKED_INVALID: return ENOEXEC;
+ case ERROR_BAD_EXE_FORMAT: return ENOEXEC;
+ case ERROR_ITERATED_DATA_EXCEEDS_64k: return ENOEXEC;
+ case ERROR_INVALID_MINALLOCSIZE: return ENOEXEC;
+ case ERROR_DYNLINK_FROM_INVALID_RING: return ENOEXEC;
+ case ERROR_IOPL_NOT_ENABLED: return ENOEXEC;
+ case ERROR_INVALID_SEGDPL: return ENOEXEC;
+ case ERROR_AUTODATASEG_EXCEEDS_64k: return ENOEXEC;
+ case ERROR_RING2SEG_MUST_BE_MOVABLE: return ENOEXEC;
+ case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: return ENOEXEC;
+ case ERROR_INFLOOP_IN_RELOC_CHAIN: return ENOEXEC;
+ case ERROR_FILENAME_EXCED_RANGE: return ENOENT;
+ case ERROR_NESTING_NOT_ALLOWED: return EAGAIN;
+ case ERROR_NOT_ENOUGH_QUOTA: return ENOMEM;
+
default:
return EIO;
}
}
+
+/* Wrapper to be used by other modules to set ERRNO from the Windows
+ * error. EC may be -1 to get the last error. */
+void
+_gpgrt_w32_set_errno (int ec)
+{
+ if (ec == -1)
+ ec = GetLastError ();
+ _set_errno (map_w32_to_errno (ec));
+}
+
+
#endif /*HAVE_W32_SYSTEM*/
/*
@@ -1578,6 +1667,18 @@ static struct cookie_io_functions_s estream_functions_fp =
* operations ares handled by file descriptor based I/O.
*/
+#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*/
+
/* Create function for objects identified by a file name. */
static int
func_file_create (void **cookie, int *filedes,
@@ -1596,7 +1697,25 @@ func_file_create (void **cookie, int *filedes,
goto out;
}
+#ifdef HAVE_W32_SYSTEM
+ if (any8bitchar (path))
+ {
+ wchar_t *wpath;
+
+ wpath = _gpgrt_utf8_to_wchar (path);
+ if (!wpath)
+ fd = -1;
+ else
+ {
+ fd = _wopen (wpath, modeflags, cmode);
+ _gpgrt_free_wchar (wpath);
+ }
+ }
+ else /* Avoid unnecessary conversion. */
+ fd = open (path, modeflags, cmode);
+#else
fd = open (path, modeflags, cmode);
+#endif
if (fd == -1)
{
err = -1;