@@ -32,15 +32,68 @@ int fsetpos_64(FILE* stream, int64_t pos)
3232
3333HRESULT HRESULTFromErrno ()
3434{
35- // stdio functions preserve last error in simple cases.
36- // It's sufficient for logging only.
37- HRESULT hr = HRESULT_FROM_WIN32 (::GetLastError ());
35+ // maps the common I/O errors
36+ // based on FILEGetLastErrorFromErrno
3837
39- if (SUCCEEDED (hr) && errno != 0 )
38+ // stdio functions aren't guaranteed to preserve GetLastError.
39+ // errno should be used as source of truth.
40+
41+ DWORD win32Err;
42+
43+ switch (errno)
4044 {
41- // Fallback when last error was cleared unexpectedly.
42- return E_FAIL;
45+ case 0 :
46+ win32Err = ERROR_SUCCESS;
47+ break ;
48+ case ENAMETOOLONG:
49+ win32Err = ERROR_FILENAME_EXCED_RANGE;
50+ break ;
51+ case ENOTDIR:
52+ win32Err = ERROR_PATH_NOT_FOUND;
53+ break ;
54+ case ENOENT:
55+ win32Err = ERROR_FILE_NOT_FOUND;
56+ break ;
57+ case EACCES:
58+ case EPERM:
59+ case EROFS:
60+ case EISDIR:
61+ win32Err = ERROR_ACCESS_DENIED;
62+ break ;
63+ case EEXIST:
64+ win32Err = ERROR_ALREADY_EXISTS;
65+ break ;
66+ case ENOTEMPTY:
67+ win32Err = ERROR_DIR_NOT_EMPTY;
68+ break ;
69+ case EBADF:
70+ win32Err = ERROR_INVALID_HANDLE;
71+ break ;
72+ case ENOMEM:
73+ win32Err = ERROR_NOT_ENOUGH_MEMORY;
74+ break ;
75+ case EBUSY:
76+ win32Err = ERROR_BUSY;
77+ break ;
78+ case ENOSPC:
79+ case EDQUOT:
80+ win32Err = ERROR_DISK_FULL;
81+ break ;
82+ case ELOOP:
83+ win32Err = ERROR_BAD_PATHNAME;
84+ break ;
85+ case EIO:
86+ win32Err = ERROR_WRITE_FAULT;
87+ break ;
88+ case EMFILE:
89+ win32Err = ERROR_TOO_MANY_OPEN_FILES;
90+ break ;
91+ case ERANGE:
92+ win32Err = ERROR_BAD_PATHNAME;
93+ break ;
94+ default :
95+ win32Err = ERROR_GEN_FAILURE;
4396 }
4497
45- return hr ;
98+ return HRESULT_FROM_WIN32 (win32Err) ;
4699}
0 commit comments