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 set. 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>
This commit is contained in:
parent
1188d308bf
commit
7ae73be141
|
@ -603,11 +603,14 @@ fhandler_base::open (int flags, mode_t mode)
|
||||||
as with FILE_ATTRIBUTE_TEMPORARY. The latter speeds up file access,
|
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.
|
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
|
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)
|
if (flags & O_TMPFILE)
|
||||||
{
|
{
|
||||||
access |= DELETE;
|
access |= DELETE;
|
||||||
file_attributes |= FILE_ATTRIBUTE_TEMPORARY;
|
file_attributes |= O_TMPFILE_FILE_ATTRS;
|
||||||
options |= FILE_DELETE_ON_CLOSE;
|
options |= FILE_DELETE_ON_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ details. */
|
||||||
never be used in Cygwin for this function. */
|
never be used in Cygwin for this function. */
|
||||||
#define PIPE_ADD_PID FILE_FLAG_FIRST_PIPE_INSTANCE
|
#define PIPE_ADD_PID FILE_FLAG_FIRST_PIPE_INSTANCE
|
||||||
|
|
||||||
|
#define O_TMPFILE_FILE_ATTRS (FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_HIDDEN)
|
||||||
|
|
||||||
extern const char *windows_device_names[];
|
extern const char *windows_device_names[];
|
||||||
extern struct __cygwin_perfile *perfile_table;
|
extern struct __cygwin_perfile *perfile_table;
|
||||||
#define __fmode (*(user_data->fmode_ptr))
|
#define __fmode (*(user_data->fmode_ptr))
|
||||||
|
|
|
@ -1243,16 +1243,28 @@ fhandler_disk_file::link (const char *newpath)
|
||||||
__seterrno_from_nt_status (status);
|
__seterrno_from_nt_status (status);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (pc.file_attributes () & FILE_ATTRIBUTE_TEMPORARY)
|
else if ((pc.file_attributes () & O_TMPFILE_FILE_ATTRS)
|
||||||
|
== O_TMPFILE_FILE_ATTRS)
|
||||||
{
|
{
|
||||||
/* If the original file has been opened with O_TMPFILE the file has
|
/* An O_TMPFILE file has FILE_ATTRIBUTE_TEMPORARY and
|
||||||
FILE_ATTRIBUTE_TEMPORARY set. After a successful hardlink the
|
FILE_ATTRIBUTE_HIDDEN set. After a successful hardlink the file is
|
||||||
file is not temporary anymore in the usual sense. So we remove
|
not temporary anymore in the usual sense. So we remove these
|
||||||
FILE_ATTRIBUTE_TEMPORARY here, even if this makes the original file
|
attributes here, even if this makes the original link (temporarily)
|
||||||
visible in directory enumeration. */
|
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. */
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES,
|
status = NtOpenFile (&fh, FILE_WRITE_ATTRIBUTES,
|
||||||
pc.init_reopen_attr (attr, fh), &io,
|
newpc.get_object_attr (attr, sec_none_nih), &io,
|
||||||
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
|
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
debug_printf ("Opening for removing TEMPORARY attrib failed, "
|
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.CreationTime.QuadPart = fbi.LastAccessTime.QuadPart
|
||||||
= fbi.LastWriteTime.QuadPart = fbi.ChangeTime.QuadPart = 0LL;
|
= fbi.LastWriteTime.QuadPart = fbi.ChangeTime.QuadPart = 0LL;
|
||||||
fbi.FileAttributes = (pc.file_attributes ()
|
fbi.FileAttributes = (pc.file_attributes () & ~O_TMPFILE_FILE_ATTRS)
|
||||||
& ~FILE_ATTRIBUTE_TEMPORARY)
|
|
||||||
?: FILE_ATTRIBUTE_NORMAL;
|
?: FILE_ATTRIBUTE_NORMAL;
|
||||||
status = NtSetInformationFile (fh, &io, &fbi, sizeof fbi,
|
status = NtSetInformationFile (fh, &io, &fbi, sizeof fbi,
|
||||||
FileBasicInformation);
|
FileBasicInformation);
|
||||||
|
@ -2213,7 +2224,7 @@ go_ahead:
|
||||||
}
|
}
|
||||||
/* We don't show O_TMPFILE files in the filesystem. This is a kludge,
|
/* We don't show O_TMPFILE files in the filesystem. This is a kludge,
|
||||||
so we may end up removing this snippet again. */
|
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;
|
goto restart;
|
||||||
RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
|
RtlInitCountedUnicodeString (&fname, FileName, FileNameLength);
|
||||||
d_mounts (dir)->check_mount (&fname);
|
d_mounts (dir)->check_mount (&fname);
|
||||||
|
|
Loading…
Reference in New Issue