open_for_write_would_lose_data.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*
  2. * Implementation of open_for_write_would_lose_data for Windows.
  3. */
  4. #include "putty.h"
  5. /*
  6. * This is slightly fiddly because we want to be backwards-compatible
  7. * with systems too old to have GetFileAttributesEx. The next best
  8. * thing is FindFirstFile, which will return a different data
  9. * structure, but one that also contains the fields we want. (But it
  10. * will behave more unhelpfully - for this application - in the
  11. * presence of wildcards, so we'd prefer to use GFAE if we can.)
  12. */
  13. static inline bool open_for_write_would_lose_data_impl(
  14. DWORD dwFileAttributes, DWORD nFileSizeHigh, DWORD nFileSizeLow)
  15. {
  16. if (dwFileAttributes & (FILE_ATTRIBUTE_DEVICE|FILE_ATTRIBUTE_DIRECTORY)) {
  17. /*
  18. * File is something other than an ordinary disk file, so
  19. * opening it for writing will not cause truncation. (It may
  20. * not _succeed_ either, but that's not our problem here!)
  21. */
  22. return false;
  23. }
  24. if (nFileSizeHigh == 0 && nFileSizeLow == 0) {
  25. /*
  26. * File is zero-length (or may be a named pipe, which
  27. * dwFileAttributes can't tell apart from a regular file), so
  28. * opening it for writing won't truncate any data away because
  29. * there's nothing to truncate anyway.
  30. */
  31. return false;
  32. }
  33. return true;
  34. }
  35. bool open_for_write_would_lose_data(const Filename *fn)
  36. {
  37. static HMODULE kernel32_module;
  38. DECL_WINDOWS_FUNCTION(static, BOOL, GetFileAttributesExW,
  39. (LPCWSTR, GET_FILEEX_INFO_LEVELS, LPVOID));
  40. if (!kernel32_module) {
  41. kernel32_module = load_system32_dll("kernel32.dll");
  42. GET_WINDOWS_FUNCTION(kernel32_module, GetFileAttributesExW);
  43. }
  44. if (p_GetFileAttributesExW) {
  45. WIN32_FILE_ATTRIBUTE_DATA attrs;
  46. if (!p_GetFileAttributesExW(fn->wpath, GetFileExInfoStandard, &attrs)) {
  47. /*
  48. * Generally, if we don't identify a specific reason why we
  49. * should return true from this function, we return false, and
  50. * let the subsequent attempt to open the file for real give a
  51. * more useful error message.
  52. */
  53. return false;
  54. }
  55. return open_for_write_would_lose_data_impl(
  56. attrs.dwFileAttributes, attrs.nFileSizeHigh, attrs.nFileSizeLow);
  57. } else {
  58. WIN32_FIND_DATAW fd;
  59. HANDLE h = FindFirstFileW(fn->wpath, &fd);
  60. if (h == INVALID_HANDLE_VALUE) {
  61. /*
  62. * As above, if we can't find the file at all, return false.
  63. */
  64. return false;
  65. }
  66. CloseHandle(h);
  67. return open_for_write_would_lose_data_impl(
  68. fd.dwFileAttributes, fd.nFileSizeHigh, fd.nFileSizeLow);
  69. }
  70. }