threads / patch / 18340

patch, 2 partsMinGW: a helper function that translates Win32 API error codes

Subject: [PATCH 1/2] MinGW: a helper function that translates Win32 API error codes

## tl;dr

4 messages between Mar 17, 2009 and Mar 17, 2009. Diffs are folded; open one to read it.

replies: 3people: 2as markdown or json

Johannes Sixt· Mar 17, 2009, 07:39 UTC · lore
From: Petr Kodl <petrkodl@gmail.com>
Date: Sat, 24 Jan 2009 15:04:39 +0100

This function translates many possible Win32 error codes to suitable errno numbers. We will use it in our wrapper functions that need to call into Win32.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
  Dscho,
  I've split this off from the Petr's hard-link patch and moved the function
  to the top or mingw.c because we should reuse it in our other wrappers
  to convert error codes.
  -- Hannes
  compat/mingw.c |  113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1 files changed, 113 insertions(+), 0 deletions(-)
Show changes to compat/mingw.c +113 −0
diff --git a/compat/mingw.c b/compat/mingw.c
index 27bcf3f..f66ad56 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -4,6 +4,119 @@

  unsigned int _CRT_fmode = _O_BINARY;

+static int err_win_to_posix(DWORD winerr)
+{
+	int error = ENOSYS;
+	switch(winerr) {
+	case ERROR_ACCESS_DENIED: error = EACCES; break;
+	case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
+	case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
+	case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
+	case ERROR_ALREADY_EXISTS: error = EEXIST; break;
+	case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
+	case ERROR_BAD_COMMAND: error = EIO; break;
+	case ERROR_BAD_DEVICE: error = ENODEV; break;
+	case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
+	case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
+	case ERROR_BAD_FORMAT: error = ENOEXEC; break;
+	case ERROR_BAD_LENGTH: error = EINVAL; break;
+	case ERROR_BAD_PATHNAME: error = ENOENT; break;
+	case ERROR_BAD_PIPE: error = EPIPE; break;
+	case ERROR_BAD_UNIT: error = ENODEV; break;
+	case ERROR_BAD_USERNAME: error = EINVAL; break;
+	case ERROR_BROKEN_PIPE: error = EPIPE; break;
+	case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
+	case ERROR_BUSY: error = EBUSY; break;
+	case ERROR_BUSY_DRIVE: error = EBUSY; break;
+	case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
+	case ERROR_CANNOT_MAKE: error = EACCES; break;
+	case ERROR_CANTOPEN: error = EIO; break;
+	case ERROR_CANTREAD: error = EIO; break;
+	case ERROR_CANTWRITE: error = EIO; break;
+	case ERROR_CRC: error = EIO; break;
+	case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
+	case ERROR_DEVICE_IN_USE: error = EBUSY; break;
+	case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
+	case ERROR_DIRECTORY: error = EINVAL; break;
+	case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
+	case ERROR_DISK_CHANGE: error = EIO; break;
+	case ERROR_DISK_FULL: error = ENOSPC; break;
+	case ERROR_DRIVE_LOCKED: error = EBUSY; break;
+	case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
+	case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
+	case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
+	case ERROR_FILE_EXISTS: error = EEXIST; break;
+	case ERROR_FILE_INVALID: error = ENODEV; break;
+	case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
+	case ERROR_GEN_FAILURE: error = EIO; break;
+	case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
+	case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
+	case ERROR_INVALID_ACCESS: error = EACCES; break;
+	case ERROR_INVALID_ADDRESS: error = EFAULT; break;
+	case ERROR_INVALID_BLOCK: error = EFAULT; break;
+	case ERROR_INVALID_DATA: error = EINVAL; break;
+	case ERROR_INVALID_DRIVE: error = ENODEV; break;
+	case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
+	case ERROR_INVALID_FLAGS: error = EINVAL; break;
+	case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
+	case ERROR_INVALID_HANDLE: error = EBADF; break;
+	case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
+	case ERROR_INVALID_NAME: error = EINVAL; break;
+	case ERROR_INVALID_OWNER: error = EINVAL; break;
+	case ERROR_INVALID_PARAMETER: error = EINVAL; break;
+	case ERROR_INVALID_PASSWORD: error = EPERM; break;
+	case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
+	case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
+	case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
+	case ERROR_INVALID_WORKSTATION: error = EACCES; break;
+	case ERROR_IO_DEVICE: error = EIO; break;
+	case ERROR_IO_INCOMPLETE: error = EINTR; break;
+	case ERROR_LOCKED: error = EBUSY; break;
+	case ERROR_LOCK_VIOLATION: error = EACCES; break;
+	case ERROR_LOGON_FAILURE: error = EACCES; break;
+	case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
+	case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
+	case ERROR_MORE_DATA: error = EPIPE; break;
+	case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
+	case ERROR_NOACCESS: error = EFAULT; break;
+	case ERROR_NONE_MAPPED: error = EINVAL; break;
+	case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
+	case ERROR_NOT_READY: error = EAGAIN; break;
+	case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
+	case ERROR_NO_DATA: error = EPIPE; break;
+	case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
+	case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
+	case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
+	case ERROR_OPEN_FAILED: error = EIO; break;
+	case ERROR_OPEN_FILES: error = EBUSY; break;
+	case ERROR_OPERATION_ABORTED: error = EINTR; break;
+	case ERROR_OUTOFMEMORY: error = ENOMEM; break;
+	case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
+	case ERROR_PATH_BUSY: error = EBUSY; break;
+	case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
+	case ERROR_PIPE_BUSY: error = EBUSY; break;
+	case ERROR_PIPE_CONNECTED: error = EPIPE; break;
+	case ERROR_PIPE_LISTENING: error = EPIPE; break;
+	case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
+	case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
+	case ERROR_READ_FAULT: error = EIO; break;
+	case ERROR_SEEK: error = EIO; break;
+	case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
+	case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
+	case ERROR_SHARING_VIOLATION: error = EACCES; break;
+	case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
+	case ERROR_SWAPERROR: error = ENOENT; break;
+	case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
+	case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
+	case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
+	case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
+	case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
+	case ERROR_WRITE_FAULT: error = EIO; break;
+	case ERROR_WRITE_PROTECT: error = EROFS; break;
+	}
+	return error;
+}
+
  #undef open
  int mingw_open (const char *filename, int oflags, ...)
  {
-- 
1.6.2.rc2.971.g14d5
Johannes Sixt· Mar 17, 2009, 07:46 UTC · re: Johannes Sixt · lore

[PATCH 2/2] MinGW: a hardlink implementation

From: Petr Kodl <petrkodl@gmail.com>
Date: Sat, 24 Jan 2009 15:04:39 +0100
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
  This is the meat of Petr's original patch with the fixup that was
  discussed in the msysgit mailing list (WINAPI was added in the
  typedef).
  -- Hannes
  compat/mingw.c |   21 +++++++++++++++++++++
  compat/mingw.h |    3 +--
  2 files changed, 22 insertions(+), 2 deletions(-)
Show changes to 2 files +22 −2

compat/mingw.c, compat/mingw.h

diff --git a/compat/mingw.c b/compat/mingw.c
index f66ad56..171fa85 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1118,3 +1118,24 @@ void mingw_open_html(const char *unixpath)
  	printf("Launching default browser to display HTML ...\n");
  	ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
  }
+
+int link(const char *oldpath, const char *newpath)
+{
+	typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
+	static T create_hard_link = NULL;
+	if (!create_hard_link) {
+		create_hard_link = (T) GetProcAddress(
+			GetModuleHandle("kernel32.dll"), "CreateHardLinkA");
+		if (!create_hard_link)
+			create_hard_link = (T)-1;
+	}
+	if (create_hard_link == (T)-1) {
+		errno = ENOSYS;
+		return -1;
+	}
+	if (!create_hard_link(newpath, oldpath, NULL)) {
+		errno = err_win_to_posix(GetLastError());
+		return -1;
+	}
+	return 0;
+}
diff --git a/compat/mingw.h b/compat/mingw.h
index f5da647..762eb14 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -67,8 +67,6 @@ static inline int readlink(const char *path, char *buf, size_t bufsiz)
  { errno = ENOSYS; return -1; }
  static inline int symlink(const char *oldpath, const char *newpath)
  { errno = ENOSYS; return -1; }
-static inline int link(const char *oldpath, const char *newpath)
-{ errno = ENOSYS; return -1; }
  static inline int fchmod(int fildes, mode_t mode)
  { errno = ENOSYS; return -1; }
  static inline int fork(void)
@@ -134,6 +132,7 @@ int getpagesize(void);	/* defined in MinGW's libgcc.a */
  struct passwd *getpwuid(int uid);
  int setitimer(int type, struct itimerval *in, struct itimerval *out);
  int sigaction(int sig, struct sigaction *in, struct sigaction *out);
+int link(const char *oldpath, const char *newpath);

  /*
   * replacements of existing functions
-- 
1.6.2.rc2.971.g14d5
Johannes Schindelin· Mar 17, 2009, 10:12 UTC · re: Johannes Sixt · lore

Re: [PATCH 2/2] MinGW: a hardlink implementation

Hi,
On Tue, 17 Mar 2009, Johannes Sixt wrote:
Show 9 quoted lines
> From: Petr Kodl <petrkodl@gmail.com>
> Date: Sat, 24 Jan 2009 15:04:39 +0100
> 
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
> ---
>  This is the meat of Petr's original patch with the fixup that was 
>  discussed in the msysgit mailing list (WINAPI was added in the 
>  typedef).

To save everybody searching why WINAPI is needed: in the error case (e.g. when you try to hard link from a different device), the stack was corrupted, leading to a rather nasty segmentation fault (which has a different name on Windows, just as everything else: access violation):

	http://code.google.com/p/msysgit/issues/detail?id=204

Ciao, Dscho

Johannes Schindelin· Mar 17, 2009, 10:10 UTC · re: Johannes Sixt · lore

Re: [PATCH 1/2] MinGW: a helper function that translates Win32 API error codes

Hi,
On Tue, 17 Mar 2009, Johannes Sixt wrote:
Show 15 quoted lines
> From: Petr Kodl <petrkodl@gmail.com>
> Date: Sat, 24 Jan 2009 15:04:39 +0100
> 
> This function translates many possible Win32 error codes to suitable
> errno numbers.  We will use it in our wrapper functions that need to call
> into Win32.
> 
> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
> ---
>  Dscho,
> 
>  I've split this [error code translation from Win32 to POSIX] off from 
>  the Petr's hard-link patch and moved the function to the top or mingw.c 
>  because we should reuse it in our other wrappers to convert error 
>  codes.
I fully agree.

Ciao, Dscho

← back to recent threads