Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'windows/utils/open_for_write_would_lose_data.c')
-rw-r--r--windows/utils/open_for_write_would_lose_data.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/windows/utils/open_for_write_would_lose_data.c b/windows/utils/open_for_write_would_lose_data.c
new file mode 100644
index 00000000..2aef5c5a
--- /dev/null
+++ b/windows/utils/open_for_write_would_lose_data.c
@@ -0,0 +1,76 @@
+/*
+ * Implementation of open_for_write_would_lose_data for Windows.
+ */
+
+#include "putty.h"
+
+/*
+ * This is slightly fiddly because we want to be backwards-compatible
+ * with systems too old to have GetFileAttributesEx. The next best
+ * thing is FindFirstFile, which will return a different data
+ * structure, but one that also contains the fields we want. (But it
+ * will behave more unhelpfully - for this application - in the
+ * presence of wildcards, so we'd prefer to use GFAE if we can.)
+ */
+
+static inline bool open_for_write_would_lose_data_impl(
+ DWORD dwFileAttributes, DWORD nFileSizeHigh, DWORD nFileSizeLow)
+{
+ if (dwFileAttributes & (FILE_ATTRIBUTE_DEVICE|FILE_ATTRIBUTE_DIRECTORY)) {
+ /*
+ * File is something other than an ordinary disk file, so
+ * opening it for writing will not cause truncation. (It may
+ * not _succeed_ either, but that's not our problem here!)
+ */
+ return false;
+ }
+ if (nFileSizeHigh == 0 && nFileSizeLow == 0) {
+ /*
+ * File is zero-length (or may be a named pipe, which
+ * dwFileAttributes can't tell apart from a regular file), so
+ * opening it for writing won't truncate any data away because
+ * there's nothing to truncate anyway.
+ */
+ return false;
+ }
+ return true;
+}
+
+bool open_for_write_would_lose_data(const Filename *fn)
+{
+ static HMODULE kernel32_module;
+ DECL_WINDOWS_FUNCTION(static, BOOL, GetFileAttributesExA,
+ (LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID));
+
+ if (!kernel32_module) {
+ kernel32_module = load_system32_dll("kernel32.dll");
+ GET_WINDOWS_FUNCTION(kernel32_module, GetFileAttributesExA);
+ }
+
+ if (p_GetFileAttributesExA) {
+ WIN32_FILE_ATTRIBUTE_DATA attrs;
+ if (!p_GetFileAttributesExA(fn->path, GetFileExInfoStandard, &attrs)) {
+ /*
+ * Generally, if we don't identify a specific reason why we
+ * should return true from this function, we return false, and
+ * let the subsequent attempt to open the file for real give a
+ * more useful error message.
+ */
+ return false;
+ }
+ return open_for_write_would_lose_data_impl(
+ attrs.dwFileAttributes, attrs.nFileSizeHigh, attrs.nFileSizeLow);
+ } else {
+ WIN32_FIND_DATA fd;
+ HANDLE h = FindFirstFile(fn->path, &fd);
+ if (h == INVALID_HANDLE_VALUE) {
+ /*
+ * As above, if we can't find the file at all, return false.
+ */
+ return false;
+ }
+ CloseHandle(h);
+ return open_for_write_would_lose_data_impl(
+ fd.dwFileAttributes, fd.nFileSizeHigh, fd.nFileSizeLow);
+ }
+}