Przeglądaj źródła

mingw: Use GetFileSize to get file size

_wstat family does not work with symbolic links.  They always returns
size 0.  To workaround this, we now use GetFileSize to get file size.
To do that, we need to first obtain file HANDLE, which is a bit
tedious because of the messy interface of CreateFileW, but we have no
way to get around it.
Tatsuhiro Tsujikawa 10 lat temu
rodzic
commit
432675e512
1 zmienionych plików z 35 dodań i 1 usunięć
  1. 35 1
      src/File.cc

+ 35 - 1
src/File.cc

@@ -103,12 +103,46 @@ bool File::remove() {
   }
 }
 
-int64_t File::size() {
+#ifdef __MINGW32__
+namespace {
+HANDLE openFile(const std::string& filename)
+{
+  DWORD desiredAccess = GENERIC_READ;
+  DWORD sharedMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+  DWORD creationDisp = OPEN_EXISTING;
+  return CreateFileW(utf8ToWChar(filename).c_str(), desiredAccess, sharedMode,
+                     /* lpSecurityAttributes */ nullptr, creationDisp,
+                     FILE_ATTRIBUTE_NORMAL, /* hTemplateFile */ nullptr);
+}
+} // namespace
+#endif // __MINGW32__
+
+int64_t File::size()
+{
+#ifdef __MINGW32__
+  // _wstat cannot be used for symlink.  It always returns 0.  Quoted
+  // from https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx:
+  //
+  //   _wstat does not work with Windows Vista symbolic links. In
+  //   these cases, _wstat will always report a file size of 0. _stat
+  //   does work correctly with symbolic links.
+  auto hn = openFile(name_);
+  if (hn == INVALID_HANDLE_VALUE) {
+    return 0;
+  }
+  LARGE_INTEGER fileSize;
+  if (!GetFileSizeEx(hn, &fileSize)) {
+    return 0;
+  }
+  CloseHandle(hn);
+  return fileSize.QuadPart;
+#else  // !__MINGW32__
   a2_struct_stat fstat;
   if(fillStat(fstat) < 0) {
     return 0;
   }
   return fstat.st_size;
+#endif // !__MINGW32__
 }
 
 bool File::mkdirs() {