diff options
author | Werner Koch <[email protected]> | 2020-08-21 19:11:21 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2020-08-21 19:11:21 +0000 |
commit | a68c1975bda47b0698b48761a62e95b371095e9a (patch) | |
tree | bc5220f82e0da76eaa44e3601773e04c4e470bac /src/estream.c | |
parent | argparse: Handle a corner case of wrong ARGC. (diff) | |
download | libgpg-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.c | 125 |
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; |