]> git.eshelyaron.com Git - emacs.git/commitdiff
Don't follow symlinks in w32notify file watches
authorEli Zaretskii <eliz@gnu.org>
Wed, 7 Sep 2022 12:18:54 +0000 (15:18 +0300)
committerEli Zaretskii <eliz@gnu.org>
Wed, 7 Sep 2022 12:18:54 +0000 (15:18 +0300)
* src/w32notify.c (add_watch): On filesystems that support
symlinks, don't follow symlinks.  (Bug#57536)
* src/w32.c (symlinks_supported): New function.
* src/w32.h (symlinks_supported): Add prototype.

src/w32.c
src/w32.h
src/w32notify.c

index 44c279602cfe0bb1e8a9ecd2d97c19903e9f60f7..9c7d536adade8c15bdb587402698328d9a902482 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -6480,6 +6480,17 @@ chase_symlinks (const char *file)
   return target;
 }
 
+/* Return non-zero if FILE's filesystem supports symlinks.  */
+bool
+symlinks_supported (const char *file)
+{
+  if (is_windows_9x () != TRUE
+      && get_volume_info (file, NULL)
+      && (volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+    return true;
+  return false;
+}
+
 \f
 /* Posix ACL emulation.  */
 
index dc91c595c433468a73a5ae2fff58afa108984b83..b914aa9bafa24fbd8d45f4489d914927bf50ac21 100644 (file)
--- a/src/w32.h
+++ b/src/w32.h
@@ -228,6 +228,8 @@ extern int sys_link (const char *, const char *);
 extern int openat (int, const char *, int, int);
 extern int fchmodat (int, char const *, mode_t, int);
 extern int lchmod (char const *, mode_t);
+extern bool symlinks_supported (const char *);
+
 
 /* Return total and free memory info.  */
 extern int w32_memory_info (unsigned long long *, unsigned long long *,
index 72e634f77c75e2d137937419ecd9d8dff3c2629f..6b5fce9f927d5bad840507c3202b5333054e801e 100644 (file)
@@ -367,6 +367,12 @@ add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags)
   if (!file)
     return NULL;
 
+  /* Do not follow symlinks, so that the caller could watch symlink
+     files.  */
+  DWORD crflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
+  if (symlinks_supported (parent_dir))
+    crflags |= FILE_FLAG_OPEN_REPARSE_POINT;
+
   if (w32_unicode_filenames)
     {
       wchar_t dir_w[MAX_PATH], file_w[MAX_PATH];
@@ -383,8 +389,7 @@ add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags)
                             processes from deleting files inside
                             parent_dir.  */
                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                         NULL, OPEN_EXISTING,
-                         FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+                         NULL, OPEN_EXISTING, crflags,
                          NULL);
     }
   else
@@ -400,8 +405,7 @@ add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags)
       hdir = CreateFileA (dir_a,
                          FILE_LIST_DIRECTORY,
                          FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
-                         NULL, OPEN_EXISTING,
-                         FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+                         NULL, OPEN_EXISTING, crflags,
                          NULL);
     }
   if (hdir == INVALID_HANDLE_VALUE)