From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/file.c | 85 ++++---------------------------------- dlls/ucrtbase/tests/file.c | 4 ++ 2 files changed, 11 insertions(+), 78 deletions(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index 737548afd31..ee52c37552a 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -65,6 +65,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); #undef _stat64i32 #undef _wstat64i32 #undef _wstat64 +int __cdecl _wstat64(const wchar_t*, struct _stat64*);
/* for stat mode, permissions apply to all,owner and group */ #define ALL_S_IREAD (_S_IREAD | (_S_IREAD >> 3) | (_S_IREAD >> 6)) @@ -284,11 +285,6 @@ static int MSVCRT_umask = 0; static LONG tmpnam_unique; static LONG tmpnam_s_unique;
-static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e'; -static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't'; -static const unsigned int CMD = 'c' << 16 | 'm' << 8 | 'd'; -static const unsigned int COM = 'c' << 16 | 'o' << 8 | 'm'; - #define TOUL(x) (ULONGLONG)(x) static const ULONGLONG WCEXE = TOUL('e') << 32 | TOUL('x') << 16 | TOUL('e'); static const ULONGLONG WCBAT = TOUL('b') << 32 | TOUL('a') << 16 | TOUL('t'); @@ -3191,80 +3187,13 @@ int CDECL _setmode(int fd,int mode) */ int CDECL _stat64(const char* path, struct _stat64 * buf) { - DWORD dw; - WIN32_FILE_ATTRIBUTE_DATA hfi; - unsigned short mode = ALL_S_IREAD; - int plen; - - TRACE(":file (%s) buf(%p)\n", path, buf); - - plen = strlen(path); - while (plen && path[plen-1]==' ') - plen--; - - if (plen==2 && path[1]==':') - { - *_errno() = ENOENT; - return -1; - } - -#if _MSVCR_VER<140 - if (plen>=2 && path[plen-2]!=':' && (path[plen-1]=='\' || path[plen-1]=='/')) - { - *_errno() = ENOENT; - return -1; - } -#endif - - if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi)) - { - TRACE("failed (%ld)\n", GetLastError()); - *_errno() = ENOENT; - return -1; - } - - memset(buf,0,sizeof(struct _stat64)); - - /* FIXME: rdev isn't drive num, despite what the docs say-what is it? - Bon 011120: This FIXME seems incorrect - Also a letter as first char isn't enough to be classified - as a drive letter - */ - if (isalpha(*path)&& (*(path+1)==':')) - buf->st_dev = buf->st_rdev = _toupper_l(*path, NULL) - 'A'; /* drive num */ - else - buf->st_dev = buf->st_rdev = _getdrive() - 1; - - /* Dir, or regular file? */ - if (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - mode |= (_S_IFDIR | ALL_S_IEXEC); - else - { - mode |= _S_IFREG; - /* executable? */ - if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */ - { - unsigned int ext = _tolower_l(path[plen-1], NULL) | - (_tolower_l(path[plen-2], NULL) << 8) | - (_tolower_l(path[plen-3], NULL) << 16); - if (ext == EXE || ext == BAT || ext == CMD || ext == COM) - mode |= ALL_S_IEXEC; - } - } - - if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) - mode |= ALL_S_IWRITE; + wchar_t *pathW = NULL; + int ret;
- buf->st_mode = mode; - buf->st_nlink = 1; - buf->st_size = ((__int64)hfi.nFileSizeHigh << 32) + hfi.nFileSizeLow; - RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastAccessTime, &dw); - buf->st_atime = dw; - RtlTimeToSecondsSince1970((LARGE_INTEGER *)&hfi.ftLastWriteTime, &dw); - buf->st_mtime = buf->st_ctime = dw; - TRACE("%d %d %#I64x %I64d %I64d %I64d\n", buf->st_mode, buf->st_nlink, - buf->st_size, buf->st_atime, buf->st_mtime, buf->st_ctime); - return 0; + if (path && !(pathW = wstrdupa_utf8(path))) return -1; + ret = _wstat64(pathW, buf); + free(pathW); + return ret; }
/********************************************************************* diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index cdf90e797ae..5615ea8c128 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -239,6 +239,7 @@ static void test_utf8(void) const WCHAR dirW[] = L"dir\x0119\x015b\x0107";
char file2[32], buf[256], *p; + struct _stat64 stat; FILE *f; int ret;
@@ -287,6 +288,9 @@ static void test_utf8(void) ret = access(file, 0); ok(!ret, "access returned %d, error %d\n", ret, errno);
+ ret = _stat64(file, &stat); + ok(!ret, "_stat64 returned %d, error %d\n", ret, errno); + ret = _chmod(file, _S_IREAD | _S_IWRITE); ok(!ret, "_chmod returned %d, error %d\n", ret, errno);