Hi all, this patch semi-implements msvcrt._stati64 (call down to MSVCRT__stat), needed by Winamp3. Now Winamp3 is about as usable with builtin msvcrt as with native msvcrt. (read: not usable, since it crashes when adding mp3s) - semi-implement msvcrt._stati64 - correct function definitions in header file - group stat functions together Index: dlls/msvcrt/file.c =================================================================== RCS file: /home/wine/wine/dlls/msvcrt/file.c,v retrieving revision 1.40 diff -u -r1.40 file.c --- dlls/msvcrt/file.c 25 Oct 2002 03:12:01 -0000 1.40 +++ dlls/msvcrt/file.c 9 Nov 2002 16:23:13 -0000 @@ -708,6 +708,156 @@ } /********************************************************************* + * _stat (MSVCRT.@) + */ +int MSVCRT__stat(const char* path, struct _stat * buf) +{ + DWORD dw; + WIN32_FILE_ATTRIBUTE_DATA hfi; + unsigned short mode = MSVCRT_S_IREAD; + int plen; + + TRACE(":file (%s) buf(%p)\n",path,buf); + + if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi)) + { + TRACE("failed (%ld)\n",GetLastError()); + MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); + return -1; + } + + memset(buf,0,sizeof(struct _stat)); + + /* FIXME: rdev isnt 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 classify + as drive letter + */ + if (isalpha(*path)&& (*(path+1)==':')) + buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */ + else + buf->st_dev = buf->st_rdev = _getdrive() - 1; + + plen = strlen(path); + + /* Dir, or regular file? */ + if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || + (path[plen-1] == '\\')) + mode |= (_S_IFDIR | MSVCRT_S_IEXEC); + else + { + mode |= _S_IFREG; + /* executable? */ + if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */ + { + unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) | + (tolower(path[plen-3]) << 16); + if (ext == EXE || ext == BAT || ext == CMD || ext == COM) + mode |= MSVCRT_S_IEXEC; + } + } + + if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + mode |= MSVCRT_S_IWRITE; + + buf->st_mode = mode; + buf->st_nlink = 1; + buf->st_size = 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("\n%d %d %d %ld %ld %ld\n", buf->st_mode,buf->st_nlink,buf->st_size, + buf->st_atime,buf->st_mtime, buf->st_ctime); + return 0; +} + +/********************************************************************* + * _wstat (MSVCRT.@) + */ +int _wstat(const WCHAR* path, struct _stat * buf) +{ + DWORD dw; + WIN32_FILE_ATTRIBUTE_DATA hfi; + unsigned short mode = MSVCRT_S_IREAD; + int plen; + + TRACE(":file (%s) buf(%p)\n",debugstr_w(path),buf); + + if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi)) + { + TRACE("failed (%ld)\n",GetLastError()); + MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); + return -1; + } + + memset(buf,0,sizeof(struct _stat)); + + /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */ + if (MSVCRT_iswalpha(*path)) + buf->st_dev = buf->st_rdev = toupperW(*path - (WCHAR)L'A'); /* drive num */ + else + buf->st_dev = buf->st_rdev = _getdrive() - 1; + + plen = strlenW(path); + + /* Dir, or regular file? */ + if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || + (path[plen-1] == (WCHAR)L'\\')) + mode |= (_S_IFDIR | MSVCRT_S_IEXEC); + else + { + mode |= _S_IFREG; + /* executable? */ + if (plen > 6 && path[plen-4] == (WCHAR)L'.') /* shortest exe: "\x.exe" */ + { + ULONGLONG ext = tolowerW(path[plen-1]) | (tolowerW(path[plen-2]) << 16) | + ((ULONGLONG)tolowerW(path[plen-3]) << 32); + if (ext == WCEXE || ext == WCBAT || ext == WCCMD || ext == WCCOM) + mode |= MSVCRT_S_IEXEC; + } + } + + if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + mode |= MSVCRT_S_IWRITE; + + buf->st_mode = mode; + buf->st_nlink = 1; + buf->st_size = 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("\n%d %d %d %ld %ld %ld\n", buf->st_mode,buf->st_nlink,buf->st_size, + buf->st_atime,buf->st_mtime, buf->st_ctime); + return 0; +} + +__int64 _stati64(const char *path, struct _stati64 *buffer) +{ + struct _stat tmpstat; + __int64 tmpres; + + FIXME("(%s, %p): semi-stub !\n", path, buffer); + + tmpres = MSVCRT__stat(path, &tmpstat); + + buffer->st_dev = tmpstat.st_dev; + buffer->st_ino = tmpstat.st_ino; + buffer->st_mode = tmpstat.st_mode; + buffer->st_nlink = tmpstat.st_nlink; + buffer->st_uid = tmpstat.st_uid; + buffer->st_gid = tmpstat.st_gid; + buffer->st_rdev = tmpstat.st_rdev; + buffer->st_size = tmpstat.st_size; + buffer->st_atime = tmpstat.st_atime; + buffer->st_mtime = tmpstat.st_mtime; + buffer->st_ctime = tmpstat.st_ctime; + + return tmpres; +} + +/********************************************************************* * _futime (MSVCRT.@) */ int _futime(int fd, struct _utimbuf *t) @@ -1131,132 +1281,6 @@ { if (mode & _O_TEXT) FIXME("fd (%d) mode (%d) TEXT not implemented\n",fd,mode); - return 0; -} - -/********************************************************************* - * _stat (MSVCRT.@) - */ -int MSVCRT__stat(const char* path, struct _stat * buf) -{ - DWORD dw; - WIN32_FILE_ATTRIBUTE_DATA hfi; - unsigned short mode = MSVCRT_S_IREAD; - int plen; - - TRACE(":file (%s) buf(%p)\n",path,buf); - - if (!GetFileAttributesExA(path, GetFileExInfoStandard, &hfi)) - { - TRACE("failed (%ld)\n",GetLastError()); - MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); - return -1; - } - - memset(buf,0,sizeof(struct _stat)); - - /* FIXME: rdev isnt 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 classify - as drive letter - */ - if (isalpha(*path)&& (*(path+1)==':')) - buf->st_dev = buf->st_rdev = toupper(*path) - 'A'; /* drive num */ - else - buf->st_dev = buf->st_rdev = _getdrive() - 1; - - plen = strlen(path); - - /* Dir, or regular file? */ - if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || - (path[plen-1] == '\\')) - mode |= (_S_IFDIR | MSVCRT_S_IEXEC); - else - { - mode |= _S_IFREG; - /* executable? */ - if (plen > 6 && path[plen-4] == '.') /* shortest exe: "\x.exe" */ - { - unsigned int ext = tolower(path[plen-1]) | (tolower(path[plen-2]) << 8) | - (tolower(path[plen-3]) << 16); - if (ext == EXE || ext == BAT || ext == CMD || ext == COM) - mode |= MSVCRT_S_IEXEC; - } - } - - if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) - mode |= MSVCRT_S_IWRITE; - - buf->st_mode = mode; - buf->st_nlink = 1; - buf->st_size = 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("\n%d %d %d %ld %ld %ld\n", buf->st_mode,buf->st_nlink,buf->st_size, - buf->st_atime,buf->st_mtime, buf->st_ctime); - return 0; -} - -/********************************************************************* - * _wstat (MSVCRT.@) - */ -int _wstat(const WCHAR* path, struct _stat * buf) -{ - DWORD dw; - WIN32_FILE_ATTRIBUTE_DATA hfi; - unsigned short mode = MSVCRT_S_IREAD; - int plen; - - TRACE(":file (%s) buf(%p)\n",debugstr_w(path),buf); - - if (!GetFileAttributesExW(path, GetFileExInfoStandard, &hfi)) - { - TRACE("failed (%ld)\n",GetLastError()); - MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); - return -1; - } - - memset(buf,0,sizeof(struct _stat)); - - /* FIXME: rdev isn't drive num, despite what the docs says-what is it? */ - if (MSVCRT_iswalpha(*path)) - buf->st_dev = buf->st_rdev = toupperW(*path - (WCHAR)L'A'); /* drive num */ - else - buf->st_dev = buf->st_rdev = _getdrive() - 1; - - plen = strlenW(path); - - /* Dir, or regular file? */ - if ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || - (path[plen-1] == (WCHAR)L'\\')) - mode |= (_S_IFDIR | MSVCRT_S_IEXEC); - else - { - mode |= _S_IFREG; - /* executable? */ - if (plen > 6 && path[plen-4] == (WCHAR)L'.') /* shortest exe: "\x.exe" */ - { - ULONGLONG ext = tolowerW(path[plen-1]) | (tolowerW(path[plen-2]) << 16) | - ((ULONGLONG)tolowerW(path[plen-3]) << 32); - if (ext == WCEXE || ext == WCBAT || ext == WCCMD || ext == WCCOM) - mode |= MSVCRT_S_IEXEC; - } - } - - if (!(hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) - mode |= MSVCRT_S_IWRITE; - - buf->st_mode = mode; - buf->st_nlink = 1; - buf->st_size = 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("\n%d %d %d %ld %ld %ld\n", buf->st_mode,buf->st_nlink,buf->st_size, - buf->st_atime,buf->st_mtime, buf->st_ctime); return 0; } Index: include/msvcrt/sys/stat.h =================================================================== RCS file: /home/wine/wine/include/msvcrt/sys/stat.h,v retrieving revision 1.5 diff -u -r1.5 stat.h --- include/msvcrt/sys/stat.h 31 Jul 2002 20:04:20 -0000 1.5 +++ include/msvcrt/sys/stat.h 9 Nov 2002 16:23:13 -0000 @@ -61,11 +61,11 @@ int MSVCRT(_fstat)(int,struct _stat*); int MSVCRT(_stat)(const char*,struct _stat*); -int _fstati64(int,struct _stati64*); -int _stati64(const char*,struct _stati64*); +__int64 _fstati64(int,struct _stati64*); +__int64 _stati64(const char*,struct _stati64*); int _wstat(const WCHAR*,struct _stat*); -int _wstati64(const WCHAR*,struct _stati64*); +__int64 _wstati64(const WCHAR*,struct _stati64*); #ifdef __cplusplus } -- Andreas Mohr Stauferstr. 6, D-71272 Renningen, Germany Tel. +49 7159 800604 http://mohr.de.tt