err2errno.c 4.9 KB
Newer Older
1
/*****************************************************************************\
S
Shengliang Guan 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14
*                                                                             *
*   Filename	    err2errno.c						      *
*									      *
*   Description:    Convert a WIN32 error to a Unix errno		      *
*                                                                             *
*   Notes:	                                                              *
*		    							      *
*   History:								      *
*    2014-02-17 JFL Created this module.				      *
*    2016-10-05 JFL Fixed compatibility with Visual Studio 2003 and older.    *
*                   Removed a few useless special cases, and added EZERO case.*
*                   Make sure the global errno is _not_ changed by this funct.*
*                                                                             *
15
*         Copyright 2016 Hewlett Packard Enterprise Development LP          *
S
Shengliang Guan 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
\*****************************************************************************/

/* Microsoft C libraries include files */
#include <errno.h>
#include <stdio.h>
/* MsvcLibX library extensions */
#include "debugm.h"


#ifdef _WIN32

#include <windows.h>

/*---------------------------------------------------------------------------*\
*                                                                             *
|   Function:	    Win32ErrorToErrno					      |
|									      |
|   Description:    Convert a Win32 system error code to a Posix errno        |
|									      |
|   Parameters:     DWORD dwError		The Win32 error code          |
|									      |
|   Returns:	    The corresponding Posix errno			      |
|									      |
|   Notes:	    There's no 1-to-1 correspondance between Windows and      |
|		    Posix errors. This routine attempts to convert codes for  |
|		    the most likely errors for MsvcLibX.		      |
|		    Please add those you encounter, that end up in the	      |
|		    default category, and incorrectly return EIO by default.  |
|		    							      |
|		    Does not change errno. (Contrary to _dosmaperr, etc)      |
|		    You must set errno thereafter if desired.		      |
|		    							      |
|   History:								      |
|    2014-02-05 JFL Created this routine                                      |
|    2014-03-05 JFL Added the default call to _get_errno_from_oserr().        |
|    2015-12-07 JFL Use the new error conversion routine name in the UCRT.    |
*									      *
\*---------------------------------------------------------------------------*/

#if defined(_UCRT) /* Visual Studio 14 and later */
#define _get_errno_from_oserr __acrt_errno_from_os_error /* The name changed in the UCRT */
#endif

#if (_MSC_VER < 1400) /* Anything older than Visual Studio 8 (= VS 2003 and older) */
#pragma message("Defining our own _get_errno_from_oserr()")
extern void __cdecl _dosmaperr(unsigned long);
int _get_errno_from_oserr(unsigned long dwErr) {
  _dosmaperr(dwErr); /* Sets errno from WIN32 error */
  return errno;
}
#else
#pragma message("Using the default " MSVCLIBX_STRINGIZE(_get_errno_from_oserr) "()")
/* Equivalent function in MSVC library. Does not know about symlink errors. */
extern int __cdecl _get_errno_from_oserr(unsigned long oserrno);
#endif

int Win32ErrorToErrno() {
  DWORD dwError = GetLastError();

  DEBUG_CODE({
    LPVOID lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
		  NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		  (LPTSTR)&lpMsgBuf, 0, NULL);
    DEBUG_PRINTF(("// Win32 error %d (0x%X): %s", dwError, dwError, lpMsgBuf ? lpMsgBuf : "Unknown\n"));
    LocalFree( lpMsgBuf );
  });

  switch (dwError) {
    case ERROR_SUCCESS:
      return 0;
    case ERROR_PRIVILEGE_NOT_HELD: /* Not running with the SE_CREATE_SYMBOLIC_LINK_NAME privilege */
    case ERROR_REPARSE_ATTRIBUTE_CONFLICT:
      return EACCES;
    case ERROR_INSUFFICIENT_BUFFER:
      return E2BIG;
    case ERROR_FILE_EXISTS:
    case ERROR_ALREADY_EXISTS:
      return EEXIST;
    case ERROR_WRITE_PROTECT:
      return EROFS;
    case ERROR_HANDLE_DISK_FULL:
      return ENOSPC;
    case ERROR_NOT_A_REPARSE_POINT:
    case ERROR_REPARSE_TAG_MISMATCH:
    case ERROR_INVALID_FLAGS:
    case ERROR_INVALID_PARAMETER:
      return EINVAL;
    case ERROR_INVALID_REPARSE_DATA:
    case ERROR_REPARSE_TAG_INVALID:
      return EBADF; /* Not supposed to happen in Posix OSs, but may happen when experimenting with junction() IOCTLs. */
    case ERROR_NO_UNICODE_TRANSLATION:
      return EILSEQ;
    default: {
      int errno0, errno1;
      errno0 = errno; /* Preserve the initial errno */
      errno1 = _get_errno_from_oserr(dwError); /* Let MSVC library decide. May change errno. */
      errno = errno0; /* Restore the initial errno */
      return errno1;
    }
  }
}

#endif /* _WIN32 */