[newlib-cygwin] Cygwin: improve O_TMPFILE handling

Corinna Vinschen corinna@sourceware.org
Wed Feb 14 11:55:00 GMT 2018


commit 7ae73be14194ccadc9a7557be33c3940ca4667cb
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Feb 14 12:55:24 2018 +0100

    Cygwin: improve O_TMPFILE handling
    Windows does not remove FILE_ATTRIBUTE_TEMPORARY by itself after a
    file has been closed.  It's just some attribute which can be set or
    removed at will, despite its purpose.
    Apparently there are tools out there which use FILE_ATTRIBUTE_TEMPORARY
    accidentally or wrongly, even Microsoft's own tools are affected.  In
    the end, the filesystem is potentially full of files with this attribute
    Implement O_TMPFILE files with FILE_ATTRIBUTE_TEMPORARY and
    FILE_ATTRIBUTE_HIDDEN set.  This combination is pretty unlikely.
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

 winsup/cygwin/fhandler.cc           |  7 +++++--
 winsup/cygwin/fhandler.h            |  2 ++
 winsup/cygwin/fhandler_disk_file.cc | 33 ++++++++++++++++++++++-----------
 3 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 7da1c4e..086be73 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -603,11 +603,14 @@ fhandler_base::open (int flags, mode_t mode)
 	 as with FILE_ATTRIBUTE_TEMPORARY.  The latter speeds up file access,
 	 because the OS tries to keep the file in memory as much as possible.
 	 In conjunction with FILE_DELETE_ON_CLOSE, ideally the OS never has
-	 to write to the disk at all. */
+	 to write to the disk at all.
+	 Note that O_TMPFILE_FILE_ATTRS also sets the DOS HIDDEN attribute
+	 to help telling Cygwin O_TMPFILE files apart from other files
+	 accidentally setting FILE_ATTRIBUTE_TEMPORARY. */
       if (flags & O_TMPFILE)
 	  access |= DELETE;
-	  file_attributes |= FILE_ATTRIBUTE_TEMPORARY;
+	  file_attributes |= O_TMPFILE_FILE_ATTRS;
 	  options |= FILE_DELETE_ON_CLOSE;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index a446e75..9d2b263 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -37,6 +37,8 @@ details. */
    never be used in Cygwin for this function. */
 extern const char *windows_device_names[];
 extern struct __cygwin_perfile *perfile_table;
 #define __fmode (*(user_data->fmode_ptr))
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index f079965..cb6be25 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1243,16 +1243,28 @@ fhandler_disk_file::link (const char *newpath)
 	__seterrno_from_nt_status (status);
       return -1;
-  else if (pc.file_attributes () & FILE_ATTRIBUTE_TEMPORARY)
-    {
-      /* If the original file has been opened with O_TMPFILE the file has
-	 FILE_ATTRIBUTE_TEMPORARY set.  After a successful hardlink the
-	 file is not temporary anymore in the usual sense.  So we remove
-	 FILE_ATTRIBUTE_TEMPORARY here, even if this makes the original file
-	 visible in directory enumeration. */
+  else if ((pc.file_attributes () & O_TMPFILE_FILE_ATTRS)
+    {
+	 FILE_ATTRIBUTE_HIDDEN set.  After a successful hardlink the file is
+	 not temporary anymore in the usual sense.  So we remove these
+	 attributes here, even if this makes the original link (temporarily)
+	 visible in directory enumeration.
+	 Note that we don't create a reopen attribute for the original
+	 link but rather a normal attribute for the just created link.
+	 The reason is a curious behaviour of Windows:  If we remove
+	 the O_TMPFILE attributes on the original link, the new link
+	 will not show up in file system listings, long after the original
+	 link has been closed and removed.  The file and its metadata will
+	 be kept in memory only as long as Windows sees fit.  By opening
+	 the new link, we request the attribute changes on the new link,
+	 so after closing it Windows will have an increased interest to
+	 write back the metadata. */
       status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES,
-			   pc.init_reopen_attr (attr, fh), &io,
+			   newpc.get_object_attr (attr, sec_none_nih), &io,
       if (!NT_SUCCESS (status))
 	debug_printf ("Opening for removing TEMPORARY attrib failed, "
@@ -1263,8 +1275,7 @@ fhandler_disk_file::link (const char *newpath)
 	  fbi.CreationTime.QuadPart = fbi.LastAccessTime.QuadPart
 	  = fbi.LastWriteTime.QuadPart = fbi.ChangeTime.QuadPart = 0LL;
-	  fbi.FileAttributes = (pc.file_attributes ()
+	  fbi.FileAttributes = (pc.file_attributes () & ~O_TMPFILE_FILE_ATTRS)
 	  status = NtSetInformationFile (fh, &io, &fbi, sizeof fbi,
@@ -2213,7 +2224,7 @@ go_ahead:
       /* We don't show O_TMPFILE files in the filesystem.  This is a kludge,
 	 so we may end up removing this snippet again. */
-      if (FileAttributes & FILE_ATTRIBUTE_TEMPORARY)
+      if ((FileAttributes & O_TMPFILE_FILE_ATTRS) == O_TMPFILE_FILE_ATTRS)
 	goto restart;
       RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
       d_mounts (dir)->check_mount (&fname);

More information about the Cygwin-cvs mailing list