From 1b61bf152b3972c6afd3f938d7654c7738b1c2bc Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 21 Aug 2007 12:37:40 +0000 Subject: [PATCH] * ntdll.h (NtNotifyChangeDirectoryFile): Declare. (NtQueryAttributesFile): Move to maintain alphabetical order of declarations. Add comment to note that timestamp information returned by NtQueryAttributesFile is unreliable. * path.h (etc::changed_h): Move here. (etc::fn): Change type to OBJECT_ATTRIBUTES. (etc::last_modified): Change type to LARGE_INTEGER. (etc::init): Take PUNICODE_STRING as second argument. * path.cc: Accomodate above changes. (etc::test_file_change): Use NT native functions. (etc::dir_changed): Ditto. * uinfo.cc (pwdgrp::load): Call etc::init with NT native path. --- winsup/cygwin/ChangeLog | 15 +++++++ winsup/cygwin/ntdll.h | 10 ++++- winsup/cygwin/path.cc | 86 ++++++++++++++++++++++++++++++----------- winsup/cygwin/path.h | 7 ++-- winsup/cygwin/uinfo.cc | 2 +- 5 files changed, 91 insertions(+), 29 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index cb80c589c..7ed188da2 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2007-08-21 Corinna Vinschen + + * ntdll.h (NtNotifyChangeDirectoryFile): Declare. + (NtQueryAttributesFile): Move to maintain alphabetical order of + declarations. Add comment to note that timestamp information returned + by NtQueryAttributesFile is unreliable. + * path.h (etc::changed_h): Move here. + (etc::fn): Change type to OBJECT_ATTRIBUTES. + (etc::last_modified): Change type to LARGE_INTEGER. + (etc::init): Take PUNICODE_STRING as second argument. + * path.cc: Accomodate above changes. + (etc::test_file_change): Use NT native functions. + (etc::dir_changed): Ditto. + * uinfo.cc (pwdgrp::load): Call etc::init with NT native path. + 2007-08-21 Corinna Vinschen * fhandler_disk_file.cc: Change debugging output througout to print diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index ff9f95506..f5c079767 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -779,11 +779,19 @@ extern "C" NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG, PLARGE_INTEGER, PULONG, SECTION_INHERIT, ULONG, ULONG); + NTSTATUS NTAPI NtNotifyChangeDirectoryFile (HANDLE, HANDLE, PIO_APC_ROUTINE, + PVOID, PIO_STATUS_BLOCK, + PFILE_NOTIFY_INFORMATION, ULONG, + ULONG, BOOLEAN); NTSTATUS NTAPI NtOpenDirectoryObject (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG); NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES); + /* WARNING! Don't rely on the timestamp information returned by + NtQueryAttributesFile. Only the DOS file attribute info is reliable. */ + NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES, + PFILE_BASIC_INFORMATION); NTSTATUS NTAPI NtQueryDirectoryFile(HANDLE, HANDLE, PVOID, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS, BOOLEAN, @@ -792,8 +800,6 @@ extern "C" BOOLEAN, PULONG, PULONG); NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN); - NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES, - PFILE_BASIC_INFORMATION); NTSTATUS NTAPI NtQueryFullAttributesFile (POBJECT_ATTRIBUTES, PFILE_NETWORK_OPEN_INFORMATION); NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID, diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index e3377a069..8dcccc847 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -4456,11 +4456,11 @@ out: int etc::curr_ix = 0; /* Note that the first elements of the below arrays are unused */ bool etc::change_possible[MAX_ETC_FILES + 1]; -const char *etc::fn[MAX_ETC_FILES + 1]; -FILETIME etc::last_modified[MAX_ETC_FILES + 1]; +OBJECT_ATTRIBUTES etc::fn[MAX_ETC_FILES + 1]; +LARGE_INTEGER etc::last_modified[MAX_ETC_FILES + 1]; int -etc::init (int n, const char *etc_fn) +etc::init (int n, PUNICODE_STRING etc_fn) { if (n > 0) /* ok */; @@ -4469,35 +4469,36 @@ etc::init (int n, const char *etc_fn) else api_fatal ("internal error"); - fn[n] = etc_fn; + InitializeObjectAttributes (&fn[n], etc_fn, OBJ_CASE_INSENSITIVE, NULL, NULL); change_possible[n] = false; test_file_change (n); - paranoid_printf ("fn[%d] %s, curr_ix %d", n, fn[n], curr_ix); + paranoid_printf ("fn[%d] %S, curr_ix %d", n, fn[n].ObjectName, curr_ix); return n; } bool etc::test_file_change (int n) { - HANDLE h; - WIN32_FIND_DATA data; + NTSTATUS status; + FILE_NETWORK_OPEN_INFORMATION fnoi; bool res; - if ((h = FindFirstFile (fn[n], &data)) == INVALID_HANDLE_VALUE) + status = NtQueryFullAttributesFile (&fn[n], &fnoi); + if (!NT_SUCCESS (status)) { res = true; memset (last_modified + n, 0, sizeof (last_modified[n])); - debug_printf ("FindFirstFile failed, %E"); + debug_printf ("NtQueryFullAttributesFile (%S) failed, %p", + fn[n].ObjectName, status); } else { - FindClose (h); - res = CompareFileTime (&data.ftLastWriteTime, last_modified + n) > 0; - last_modified[n] = data.ftLastWriteTime; - debug_printf ("FindFirstFile succeeded"); + res = CompareFileTime ((FILETIME *) &fnoi.LastWriteTime, + (FILETIME *) last_modified + n) > 0; + last_modified[n].QuadPart = fnoi.LastWriteTime.QuadPart; } - paranoid_printf ("fn[%d] %s res %d", n, fn[n], res); + paranoid_printf ("fn[%d] %S res %d", n, fn[n].ObjectName, res); return res; } @@ -4507,17 +4508,42 @@ etc::dir_changed (int n) if (!change_possible[n]) { static HANDLE changed_h NO_COPY; + NTSTATUS status; + IO_STATUS_BLOCK io; if (!changed_h) { - path_conv pwd ("/etc"); - changed_h = FindFirstChangeNotification (pwd.get_win32 (), FALSE, - FILE_NOTIFY_CHANGE_LAST_WRITE - | FILE_NOTIFY_CHANGE_FILE_NAME); + OBJECT_ATTRIBUTES attr; + + path_conv dir ("/etc"); + status = NtOpenFile (&changed_h, SYNCHRONIZE | FILE_LIST_DIRECTORY, + dir.get_object_attr (attr, sec_none_nih), &io, + FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE); + if (!NT_SUCCESS (status)) + { +#ifdef DEBUGGING + system_printf ("NtOpenFile (%S) failed, %p", + dir.get_nt_native_path (), status); +#endif + changed_h = INVALID_HANDLE_VALUE; + } + else + { + status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL, + NULL, &io, NULL, 0, + FILE_NOTIFY_CHANGE_LAST_WRITE + | FILE_NOTIFY_CHANGE_FILE_NAME, + FALSE); + if (!NT_SUCCESS (status)) + { #ifdef DEBUGGING - if (changed_h == INVALID_HANDLE_VALUE) - system_printf ("Can't open %s for checking, %E", (char *) pwd); + system_printf ("NtNotifyChangeDirectoryFile (1) failed, %p", + status); #endif + NtClose (changed_h); + changed_h = INVALID_HANDLE_VALUE; + } + } memset (change_possible, true, sizeof (change_possible)); } @@ -4525,12 +4551,26 @@ etc::dir_changed (int n) change_possible[n] = true; else if (WaitForSingleObject (changed_h, 0) == WAIT_OBJECT_0) { - FindNextChangeNotification (changed_h); + status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL, + NULL, &io, NULL, 0, + FILE_NOTIFY_CHANGE_LAST_WRITE + | FILE_NOTIFY_CHANGE_FILE_NAME, + FALSE); + if (!NT_SUCCESS (status)) + { +#ifdef DEBUGGING + system_printf ("NtNotifyChangeDirectoryFile (2) failed, %p", + status); +#endif + NtClose (changed_h); + changed_h = INVALID_HANDLE_VALUE; + } memset (change_possible, true, sizeof change_possible); } } - paranoid_printf ("fn[%d] %s change_possible %d", n, fn[n], change_possible[n]); + paranoid_printf ("fn[%d] %S change_possible %d", + n, fn[n].ObjectName, change_possible[n]); return change_possible[n]; } @@ -4541,7 +4581,7 @@ etc::file_changed (int n) if (dir_changed (n) && test_file_change (n)) res = true; change_possible[n] = false; /* Change is no longer possible */ - paranoid_printf ("fn[%d] %s res %d", n, fn[n], res); + paranoid_printf ("fn[%d] %S res %d", n, fn[n].ObjectName, res); return res; } diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index b258ac9b6..5bf9717e3 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -336,11 +336,12 @@ class etc { friend class dtable; static int curr_ix; + static HANDLE changed_h; static bool change_possible[MAX_ETC_FILES + 1]; - static const char *fn[MAX_ETC_FILES + 1]; - static FILETIME last_modified[MAX_ETC_FILES + 1]; + static OBJECT_ATTRIBUTES fn[MAX_ETC_FILES + 1]; + static LARGE_INTEGER last_modified[MAX_ETC_FILES + 1]; static bool dir_changed (int); - static int init (int, const char *); + static int init (int, PUNICODE_STRING); static bool file_changed (int); static bool test_file_change (int); friend class pwdgrp; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 4ebe7245c..210b1d1f7 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -518,7 +518,7 @@ pwdgrp::load (const char *posix_fname) curr_lines = 0; pc.check (posix_fname); - etc_ix = etc::init (etc_ix, pc.get_win32 ()); + etc_ix = etc::init (etc_ix, pc.get_nt_native_path ()); paranoid_printf ("%s", posix_fname); -- 2.43.5