From: Takashi Sawanaka Date: Sun, 2 Jul 2017 08:46:22 +0000 (+0900) Subject: Add the alternative functions of _fstat() and _wstat() for the bug https://connect... X-Git-Tag: 2.16.4+-jp-10~418 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d3c41ce67c0036ffb8dfd92f925ecccd32590fa4;p=winmerge-jp%2Fwinmerge-jp.git Add the alternative functions of _fstat() and _wstat() for the bug https://connect.microsoft.com/VisualStudio/feedback/details/1600505/stat-not-working-on-windows-xp-using-v14-xp-platform-toolset-vs2015 --- diff --git a/Src/DiffFileData.cpp b/Src/DiffFileData.cpp index b1c44b770..4f2bb9cb5 100644 --- a/Src/DiffFileData.cpp +++ b/Src/DiffFileData.cpp @@ -92,7 +92,7 @@ bool DiffFileData::DoOpenFiles() // Get file stats (diffutils uses these) #ifdef _WIN32 - if (_fstat(m_inf[i].desc, &m_inf[i].stat) != 0) + if (myfstat(m_inf[i].desc, &m_inf[i].stat) != 0) #else if (fstat(m_inf[i].desc, &m_inf[i].stat) != 0) #endif diff --git a/Src/DiffWrapper.cpp b/Src/DiffWrapper.cpp index ea0938258..60a5fbf9a 100644 --- a/Src/DiffWrapper.cpp +++ b/Src/DiffWrapper.cpp @@ -1543,8 +1543,8 @@ void CDiffWrapper::WritePatchFile(struct change * script, file_data * inf) // If not, then we can't help it, and hence assert that this won't happen. if (!m_bPathsAreTemp) { - _tstat(m_files[0].c_str(), &inf_patch[0].stat); - _tstat(m_files[1].c_str(), &inf_patch[1].stat); + mywstat(m_files[0].c_str(), &inf_patch[0].stat); + mywstat(m_files[1].c_str(), &inf_patch[1].stat); } else { diff --git a/Src/Merge.vcxproj b/Src/Merge.vcxproj index f35c8c524..59e041221 100644 --- a/Src/Merge.vcxproj +++ b/Src/Merge.vcxproj @@ -883,6 +883,9 @@ NotUsing + + NotUsing + NotUsing diff --git a/Src/Merge.vcxproj.filters b/Src/Merge.vcxproj.filters index 5cf17884e..323b41c2b 100644 --- a/Src/Merge.vcxproj.filters +++ b/Src/Merge.vcxproj.filters @@ -223,37 +223,37 @@ Source Files - + DiffEngine - + DiffEngine - + DiffEngine DiffEngine - + DiffEngine DiffEngine - + DiffEngine - + DiffEngine - + DiffEngine - + DiffEngine - + DiffEngine @@ -751,6 +751,9 @@ MFCGui\Source Files + + DiffEngine + diff --git a/Src/Merge.vs2015.vcxproj b/Src/Merge.vs2015.vcxproj index 7565f8390..bc14974c1 100644 --- a/Src/Merge.vs2015.vcxproj +++ b/Src/Merge.vs2015.vcxproj @@ -674,6 +674,7 @@ NotUsing + NotUsing @@ -684,6 +685,7 @@ NotUsing + NotUsing @@ -732,6 +734,9 @@ NotUsing + + NotUsing + NotUsing @@ -939,6 +944,7 @@ + diff --git a/Src/diffutils/src/diff.h b/Src/diffutils/src/diff.h index 9ae8e8231..405e2fd06 100644 --- a/Src/diffutils/src/diff.h +++ b/Src/diffutils/src/diff.h @@ -231,7 +231,7 @@ struct file_data { int desc; /* File descriptor */ char const *name; /* File name */ #ifdef _WIN32 - struct _stat stat; /* File status from fstat() */ + struct _stat64 stat; /* File status from fstat() */ #else struct stat stat; /* File status from fstat() */ #endif @@ -375,6 +375,12 @@ int FileIsBinary(int fd); /* version.c */ extern char const version_string[]; +#ifdef _WIN32 +/* mystat.cpp */ +int myfstat(int fd, struct _stat64 *buf); +int mywstat(const wchar_t *filename, struct _stat64 *buf); +#endif + #ifdef __cplusplus #undef HUGE } diff --git a/Src/diffutils/src/mystat.cpp b/Src/diffutils/src/mystat.cpp new file mode 100644 index 000000000..0e89507d1 --- /dev/null +++ b/Src/diffutils/src/mystat.cpp @@ -0,0 +1,90 @@ +// my own _fstat() and _wstat() implementation for the bug https://connect.microsoft.com/VisualStudio/feedback/details/1600505/stat-not-working-on-windows-xp-using-v14-xp-platform-toolset-vs2015 +#include +#include +#include +#include +#include + +inline time_t filetime_to_time_t(const FILETIME& ft) +{ + return ((static_cast(ft.dwHighDateTime) << 32) + ft.dwLowDateTime) / 10000000ULL - 11644473600ULL; +} + +template +inline void set_statbuf(const FileInfo& hfi, struct _stat64& buf) +{ + buf.st_size = (static_cast(hfi.nFileSizeHigh) << 32) | hfi.nFileSizeLow; + buf.st_atime = filetime_to_time_t(hfi.ftLastAccessTime); + buf.st_mtime = filetime_to_time_t(hfi.ftLastWriteTime); + buf.st_ctime = filetime_to_time_t(hfi.ftCreationTime); + buf.st_mode = + ((hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG) | + ((hfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) ? + (_S_IREAD | ( _S_IREAD >> 3) | ( _S_IREAD >> 6)) : + ((_S_IREAD | _S_IWRITE) | ((_S_IREAD | _S_IWRITE) >> 3) | ((_S_IREAD | _S_IWRITE) >> 6))); +} + +extern "C" int myfstat(int fd, struct _stat64 *buf) +{ + if (!buf) + { + errno = EINVAL; + return -1; + } + HANDLE hFile = reinterpret_cast(_get_osfhandle(fd)); + if (hFile == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return -1; + } + memset(buf, 0, sizeof(*buf)); + switch (GetFileType(hFile) & ~FILE_TYPE_REMOTE) + { + case FILE_TYPE_CHAR: + buf->st_mode = _S_IFCHR; + return 0; + case FILE_TYPE_PIPE: + buf->st_mode = _S_IFIFO; + DWORD nBufferSize; + if (PeekNamedPipe(hFile, NULL, 0, NULL, &nBufferSize, NULL)) + buf->st_size = nBufferSize; + return 0; + case FILE_TYPE_DISK: + BY_HANDLE_FILE_INFORMATION hfi; + if (!GetFileInformationByHandle(hFile, &hfi)) + { + errno = EBADF; + return -1; + } + set_statbuf(hfi, *buf); + return 0; + default: + errno = EBADF; + return -1; + } +} + +extern "C" int mywstat(const wchar_t *filename, struct _stat64 *buf) +{ + if (!buf) + { + errno = EINVAL; + return -1; + } + if (wcspbrk(filename, L"*?")) + { + errno = ENOENT; + return -1; + } + WIN32_FIND_DATAW ffd; + HANDLE hFindFile = FindFirstFileW(filename, &ffd); + if (hFindFile == INVALID_HANDLE_VALUE) + { + errno = ENOENT; + return -1; + } + FindClose(hFindFile); + memset(buf, 0, sizeof(*buf)); + set_statbuf(ffd, *buf); + return 0; +} diff --git a/Testing/GoogleTest/UnitTests/UnitTests.vcxproj b/Testing/GoogleTest/UnitTests/UnitTests.vcxproj index a371f8d10..6dfa024a4 100644 --- a/Testing/GoogleTest/UnitTests/UnitTests.vcxproj +++ b/Testing/GoogleTest/UnitTests/UnitTests.vcxproj @@ -191,6 +191,7 @@ + @@ -211,6 +212,7 @@ NotUsing + diff --git a/Testing/GoogleTest/UnitTests/UnitTests.vcxproj.filters b/Testing/GoogleTest/UnitTests/UnitTests.vcxproj.filters new file mode 100644 index 000000000..11e5de2c8 --- /dev/null +++ b/Testing/GoogleTest/UnitTests/UnitTests.vcxproj.filters @@ -0,0 +1,372 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx + + + {4b87ff85-2ba4-475b-823e-af42e45a3098} + + + {20eb57d2-cf08-44a2-b9e0-c7f267013211} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Tests + + + Source Files + + + gtest + + + Source Files + + + Tests + + + Source Files + + + Tests + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Tests + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj b/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj index 4e5841704..b5ae582d6 100644 --- a/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj +++ b/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj @@ -192,6 +192,7 @@ + @@ -212,6 +213,7 @@ NotUsing + diff --git a/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj.filters b/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj.filters index fca369ab7..11e5de2c8 100644 --- a/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj.filters +++ b/Testing/GoogleTest/UnitTests/UnitTests.vs2015.vcxproj.filters @@ -240,6 +240,12 @@ Source Files + + Source Files + + + Tests + diff --git a/Testing/GoogleTest/diffutils/mystat_test.cpp b/Testing/GoogleTest/diffutils/mystat_test.cpp new file mode 100644 index 000000000..a3472daa5 --- /dev/null +++ b/Testing/GoogleTest/diffutils/mystat_test.cpp @@ -0,0 +1,63 @@ +#include +#include +#include "Environment.h" +#include "paths.h" +#include "diff.h" +#include + +TEST(diffutils, stat) +{ + struct _stat64 buf, buf2, buf3, buf4, buf5; + String filename = paths::ConcatPath(env::GetProgPath(), _T("../TestData/_tmp_test.txt")); + String filename2 = paths::ConcatPath(env::GetProgPath(), _T("../TestData/LeftAndRight.WinMerge")); + int fd; + EXPECT_EQ(0, _tsopen_s(&fd, filename.c_str(), _O_RDWR | _O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE)); + _write(fd, "0123456789", 10); + time_t t = time(&t); + + EXPECT_EQ(0, myfstat(fd, &buf)); + EXPECT_EQ(buf.st_size, 10); + EXPECT_EQ(t, buf.st_mtime); + EXPECT_NE(0, buf.st_mode & _S_IFREG); + EXPECT_NE(0, buf.st_mode & _S_IREAD); + EXPECT_NE(0, buf.st_mode & _S_IWRITE); + _close(fd); + + mywstat(filename.c_str(), &buf2); + EXPECT_EQ(buf2.st_size, 10); + EXPECT_EQ(t, buf2.st_mtime); + EXPECT_NE(0, buf2.st_mode & _S_IFREG); + EXPECT_NE(0, buf2.st_mode & _S_IREAD); + EXPECT_NE(0, buf2.st_mode & _S_IWRITE); + _tremove(filename.c_str()); + + int fds[2]; + char data[256]; + EXPECT_EQ(0, _pipe(fds, 256, O_BINARY)); + _write(fds[1], "0123456789", 10); + EXPECT_EQ(0, myfstat(fds[0], &buf3)); + EXPECT_EQ(10, buf3.st_size); + EXPECT_NE(0, buf3.st_mode & _S_IFIFO); + _read(fds[0], data, sizeof(data)); + _close(fds[0]); + _close(fds[1]); + + _tsopen_s(&fd, _T("CON"), _O_TEXT, _SH_DENYNO, _S_IWRITE); + EXPECT_EQ(0, myfstat(fd, &buf4)); + EXPECT_NE(0, buf4.st_mode & _S_IFCHR); + _close(fd); + + _tsopen_s(&fd, _T("NUL"), _O_TEXT, _SH_DENYNO, _S_IWRITE); + EXPECT_EQ(0, myfstat(fd, &buf5)); + EXPECT_NE(0, buf5.st_mode & _S_IFCHR); + _close(fd); + + //EXPECT_EQ(-1, myfstat(999, &buf)); + EXPECT_EQ(-1, myfstat(1, NULL)); + EXPECT_EQ(-1, mywstat(L"aaaa", NULL)); + EXPECT_EQ(-1, mywstat(L"aaaa", &buf2)); + EXPECT_EQ(-1, mywstat(filename2.c_str(), NULL)); + + EXPECT_EQ(0, mywstat(L"CON", &buf2)); + +}