From 3ec22997a208b8260c2a0e7a61888d7c0db4e4fd Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 15 Apr 2019 17:17:01 +0300 Subject: [PATCH] Fix MS-Windows build broken by make-fingerprint changes * lib-src/make-fingerprint.c (fseeko) [WNDOWSNT]: Define to fseeko64 for non-MinGW64 MinGW. * lib-src/ntlib.c (stat): Fix calculation of file size. (fstat): New function, a subset of src/w32.c:fstat. This is needed because make-fingerprint.c now calls 'fstat', and the MS version will fail to produce reliable results because nt/inc/sys/stat.h redefines 'struct stat'. --- lib-src/make-fingerprint.c | 5 ++ lib-src/ntlib.c | 100 +++++++++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/lib-src/make-fingerprint.c b/lib-src/make-fingerprint.c index dc21fc2aa9a..535e5751320 100644 --- a/lib-src/make-fingerprint.c +++ b/lib-src/make-fingerprint.c @@ -50,6 +50,11 @@ along with GNU Emacs. If not, see . */ is really just insurance. */ #undef fopen #include + +#ifndef MINGW_W64 +# undef fseeko +# define fseeko fseeko64 +#endif #endif /* WINDOWSNT */ int diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index dbafc47da28..d992f54a0fa 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -290,8 +290,8 @@ is_exec (const char * name) /* FIXME? This is in configure.ac now - is this still needed? */ #define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\') -/* We need this because nt/inc/sys/stat.h defines struct stat that is - incompatible with the MS run-time libraries. */ +/* We need stat/fsfat below because nt/inc/sys/stat.h defines struct + stat that is incompatible with the MS run-time libraries. */ int stat (const char * path, struct stat * buf) { @@ -377,7 +377,9 @@ stat (const char * path, struct stat * buf) buf->st_dev = _getdrive (); buf->st_rdev = buf->st_dev; - buf->st_size = wfd.nFileSizeLow; + buf->st_size = wfd.nFileSizeHigh; + buf->st_size <<= 32; + buf->st_size += wfd.nFileSizeLow; /* Convert timestamps to Unix format. */ buf->st_mtime = convert_time (wfd.ftLastWriteTime); @@ -408,6 +410,98 @@ lstat (const char * path, struct stat * buf) return stat (path, buf); } +int +fstat (int desc, struct stat * buf) +{ + HANDLE fh = (HANDLE) _get_osfhandle (desc); + BY_HANDLE_FILE_INFORMATION info; + unsigned __int64 fake_inode; + int permission; + + if (!init) + { + /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ + SYSTEMTIME st; + + st.wYear = 1970; + st.wMonth = 1; + st.wDay = 1; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + SystemTimeToFileTime (&st, &utc_base_ft); + utc_base = (long double) utc_base_ft.dwHighDateTime + * 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime; + init = 1; + } + + switch (GetFileType (fh) & ~FILE_TYPE_REMOTE) + { + case FILE_TYPE_DISK: + buf->st_mode = S_IFREG; + if (!GetFileInformationByHandle (fh, &info)) + { + errno = EACCES; + return -1; + } + break; + case FILE_TYPE_PIPE: + buf->st_mode = S_IFIFO; + goto non_disk; + case FILE_TYPE_CHAR: + case FILE_TYPE_UNKNOWN: + default: + buf->st_mode = S_IFCHR; + non_disk: + memset (&info, 0, sizeof (info)); + info.dwFileAttributes = 0; + info.ftCreationTime = utc_base_ft; + info.ftLastAccessTime = utc_base_ft; + info.ftLastWriteTime = utc_base_ft; + } + + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + buf->st_mode = S_IFDIR; + + buf->st_nlink = info.nNumberOfLinks; + /* Might as well use file index to fake inode values, but this + is not guaranteed to be unique unless we keep a handle open + all the time. */ + fake_inode = info.nFileIndexHigh; + fake_inode <<= 32; + fake_inode += info.nFileIndexLow; + buf->st_ino = fake_inode; + + buf->st_dev = info.dwVolumeSerialNumber; + buf->st_rdev = info.dwVolumeSerialNumber; + + buf->st_size = info.nFileSizeHigh; + buf->st_size <<= 32; + buf->st_size += info.nFileSizeLow; + + /* Convert timestamps to Unix format. */ + buf->st_mtime = convert_time (info.ftLastWriteTime); + buf->st_atime = convert_time (info.ftLastAccessTime); + if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; + buf->st_ctime = convert_time (info.ftCreationTime); + if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; + + /* determine rwx permissions */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + permission = S_IREAD; + else + permission = S_IREAD | S_IWRITE; + + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + permission |= S_IEXEC; + + buf->st_mode |= permission | (permission >> 3) | (permission >> 6); + + return 0; +} + /* On Windows, you cannot rename into an existing file. */ int sys_rename (const char *from, const char *to) -- 2.39.2