diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 65e906e8b..cc9dafe1b 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -479,6 +479,7 @@ LoadDLLfuncEx (SetThreadDescription, KernelBase, 1) LoadDLLfunc (VirtualAlloc2, KernelBase) LoadDLLfunc (NtMapViewOfSectionEx, ntdll) +LoadDLLfuncEx (RtlSetProcessPlaceholderCompatibilityMode, ntdll, 1) LoadDLLfunc (ldap_bind_s, wldap32) LoadDLLfunc (ldap_count_entries, wldap32) diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index fc1eec76a..ea6a18b51 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -809,6 +809,9 @@ dll_crt0_1 (void *) if (dynamically_loaded) sigproc_init (); + /* Call this before accessing any files. */ + RtlSetProcessPlaceholderCompatibilityMode (PHCM_EXPOSE_PLACEHOLDERS); + check_sanity_and_sync (user_data); /* Initialize malloc and then call user_shared_initialize since it relies diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc index d08fe9160..f3592148f 100644 --- a/winsup/cygwin/fhandler/disk_file.cc +++ b/winsup/cygwin/fhandler/disk_file.cc @@ -176,7 +176,9 @@ readdir_check_reparse_point (POBJECT_ATTRIBUTES attr, bool remote) bool ret = false; status = NtOpenFile (&reph, READ_CONTROL, attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT); + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_OPEN_REPARSE_POINT); if (NT_SUCCESS (status)) { PREPARSE_DATA_BUFFER rp = (PREPARSE_DATA_BUFFER) tp.c_get (); @@ -328,6 +330,7 @@ fhandler_base::fstat_by_name (struct stat *buf) status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_NO_RECALL | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); if (!NT_SUCCESS (status)) @@ -616,7 +619,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) opened = NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, pc.get_object_attr (attr, sec_none_nih), &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT)); + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT)); if (!opened) { /* Can't open file. Try again with parent dir. */ @@ -625,7 +629,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) attr.ObjectName = &dirname; opened = NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT)); + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT)); if (!opened) goto out; } @@ -2323,7 +2328,8 @@ readdir_get_ino (const char *path, bool dot_dot) || NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL, pc.get_object_attr (attr, sec_none_nih), &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | (pc.is_known_reparse_point () ? FILE_OPEN_REPARSE_POINT : 0))) ) @@ -2372,8 +2378,9 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err, Mountpoints and unknown or unhandled reparse points will be treated as normal file/directory/unknown. In all cases, returning the INO of the reparse point (not of the target) matches behavior of posix systems. + Unless the file is OFFLINE. *. */ - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) + if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && !isoffline (attr)) { OBJECT_ATTRIBUTES oattr; @@ -2618,7 +2625,8 @@ go_ahead: &nfs_aol_ffei, sizeof nfs_aol_ffei) : NtOpenFile (&hdl, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT); if (NT_SUCCESS (f_status)) { diff --git a/winsup/cygwin/local_includes/ntdll.h b/winsup/cygwin/local_includes/ntdll.h index 9605784e3..7737ae503 100644 --- a/winsup/cygwin/local_includes/ntdll.h +++ b/winsup/cygwin/local_includes/ntdll.h @@ -169,6 +169,13 @@ extern GUID __cygwin_socket_guid; #define FILE_VC_QUOTAS_REBUILDING 0x00000200 #define FILE_VC_VALID_MASK 0x000003ff +#define PHCM_APPLICATION_DEFAULT 0 +#define PHCM_DISGUISE_PLACEHOLDER 1 +#define PHCM_EXPOSE_PLACEHOLDERS 2 +#define PHCM_MAX 2 +#define PHCM_ERROR_INVALID_PARAMETER -1 +#define PHCM_ERROR_NO_TEB -2 + /* IOCTL code to impersonate client of named pipe. */ #define FSCTL_PIPE_DISCONNECT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 1, \ @@ -1639,6 +1646,7 @@ extern "C" BOOLEAN); NTSTATUS RtlSetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR, PSID, BOOLEAN); NTSTATUS RtlSetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR, PSID, BOOLEAN); + CHAR RtlSetProcessPlaceholderCompatibilityMode (CHAR); PUCHAR RtlSubAuthorityCountSid (PSID); PULONG RtlSubAuthoritySid (PSID, ULONG); ULONG RtlUnicodeStringToAnsiSize (PUNICODE_STRING); diff --git a/winsup/cygwin/local_includes/path.h b/winsup/cygwin/local_includes/path.h index d19721e0c..cd0cc8a41 100644 --- a/winsup/cygwin/local_includes/path.h +++ b/winsup/cygwin/local_includes/path.h @@ -23,6 +23,14 @@ has_attribute (DWORD attributes, DWORD attribs_to_test) && (attributes & attribs_to_test); } +extern inline bool +isoffline (DWORD attributes) +{ + return has_attribute (attributes, FILE_ATTRIBUTE_OFFLINE + | FILE_ATTRIBUTE_RECALL_ON_OPEN + | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS); +} + enum executable_states { is_executable, @@ -236,6 +244,12 @@ class path_conv bool exists () const {return fileattr != INVALID_FILE_ATTRIBUTES;} bool has_attribute (DWORD x) const {return exists () && (fileattr & x);} int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);} + bool isoffline () const + { + return has_attribute (FILE_ATTRIBUTE_OFFLINE + | FILE_ATTRIBUTE_RECALL_ON_OPEN + | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS); + } executable_states exec_state () { extern int _check_for_executable; @@ -243,7 +257,7 @@ class path_conv return is_executable; if (mount_flags & MOUNT_NOTEXEC) return not_executable; - if (!_check_for_executable) + if (isoffline () || !_check_for_executable) return dont_care_if_executable; return dont_know_if_executable; } diff --git a/winsup/cygwin/local_includes/winlean.h b/winsup/cygwin/local_includes/winlean.h index 113b2c6b0..947109bde 100644 --- a/winsup/cygwin/local_includes/winlean.h +++ b/winsup/cygwin/local_includes/winlean.h @@ -97,6 +97,13 @@ details. */ #define FILE_SUPPORTS_GHOSTING 0x40000000 #endif +#ifndef FILE_ATTRIBUTE_RECALL_ON_OPEN +#define FILE_ATTRIBUTE_RECALL_ON_OPEN 0x00040000 +#endif +#ifndef FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS +#define FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 0x00400000 +#endif + /* So-called "Microsoft Account" SIDs (S-1-11-...) have a netbios domain name "MicrosoftAccounts". The new "Application Container SIDs" (S-1-15-...) have a netbios domain name "APPLICATION PACKAGE AUTHORITY" diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index b8e5746fd..c0d62e565 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -576,6 +576,7 @@ getfileattr (const char *path, bool caseinsensitive) /* path has to be always ab status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_NO_RECALL | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); if (NT_SUCCESS (status)) @@ -3191,7 +3192,8 @@ restart: } status = NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_REPARSE_POINT + FILE_OPEN_NO_RECALL + | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT); debug_printf ("%y = NtOpenFile (no-EAs %S)", status, &upath); } @@ -3319,6 +3321,7 @@ restart: status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, &dattr, &io, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_NO_RECALL | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); if (!NT_SUCCESS (status)) @@ -3408,7 +3411,11 @@ restart: directory using a relative path, symlink evaluation goes totally awry. We never want a virtual drive evaluated as symlink. */ if (upath.Length <= 14) - goto file_not_symlink; + goto file_not_symlink; + + /* Offline files, even if reparse points, are not symlinks. */ + if (isoffline (fileattr)) + goto file_not_symlink; /* Reparse points are potentially symlinks. This check must be performed before checking the SYSTEM attribute for sysfile @@ -3454,7 +3461,8 @@ restart: status = NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS (status)) res = 0; @@ -3508,7 +3516,8 @@ restart: status = NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS (status))