diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 179985f59..050342f3d 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,23 @@ +Sun Sep 9 18:36:00 2001 Corinna Vinschen + Christopher Faylor + + * cygheap.cc (init_cygheap::etc_changed): New method to signal + a change in /etc. + * cygheap.h (struct init_cygheap): Add member `etc_changed_h' + and method `etc_changed'. + * grp.cc (enum grp_state): Eliminate. + (class grp_check): Ditto. + (group_state): Define as `class pwdgrp_check'. + (parse_grp): Remeber path and modification time of /etc/group file. + * passwd.cc (enum_pwd_state): Eliminate. + (class pwd_check): Ditto. + (passwd_state): Define as `class pwdgrp_check'. + (read_etc_passwd): Remember path and modification time of /etc/passwd + file. + * pwdgrp.h: New file. + (enum pwdgrp_state): Substitutes `pwd_state' and `grp_state'. + (class pwdgrp_check): Substitutes `pwd_check' and `grp_check'. + Sun Sep 9 14:31:00 2001 Corinna Vinschen * include/cygwin/version.h: Bump API minor version to 45 according diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 53a66cfac..be52f0446 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -16,6 +16,7 @@ #include "security.h" #include "fhandler.h" #include "dtable.h" +#include "path.h" #include "cygheap.h" #include "child_info.h" #include "heap.h" @@ -345,6 +346,39 @@ cstrdup1 (const char *s) return p; } +bool +init_cygheap::etc_changed () +{ + bool res = 0; + + if (!etc_changed_h) + { + path_conv pwd ("/etc"); + etc_changed_h = FindFirstChangeNotification (pwd, FALSE, + FILE_NOTIFY_CHANGE_LAST_WRITE); + if (etc_changed_h == INVALID_HANDLE_VALUE) + system_printf ("Can't open /etc for checking, %E", (char *) pwd, + etc_changed_h); + else if (!DuplicateHandle (hMainProc, etc_changed_h, hMainProc, + &etc_changed_h, 0, TRUE, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) + { + system_printf ("Can't inherit /etc handle, %E", (char *) pwd, + etc_changed_h); + etc_changed_h = INVALID_HANDLE_VALUE; + } + } + + if (etc_changed_h != INVALID_HANDLE_VALUE + && WaitForSingleObject (etc_changed_h, 0) == WAIT_OBJECT_0) + { + (void) FindNextChangeNotification (etc_changed_h); + res = 1; + } + + return res; +} + void cygheap_root::set (const char *posix, const char *native) { diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 1a90a94b6..8d34e671a 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -161,8 +161,11 @@ struct init_cygheap mode_t umask; HANDLE shared_h; HANDLE console_h; + HANDLE etc_changed_h; cwdstuff cwd; dtable fdtab; + + bool etc_changed (); }; #define CYGHEAPSIZE (sizeof (init_cygheap) + (4000 * sizeof (fhandler_union)) + (2 * 65536)) diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index b70db13f8..3cac0fc1d 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -26,6 +26,7 @@ details. */ #include "path.h" #include "cygheap.h" #include "cygerrno.h" +#include "pwdgrp.h" /* Read /etc/group only once for better performance. This is done on the first call that needs information from it. */ @@ -42,57 +43,7 @@ static int max_lines; static int grp_pos = 0; #endif -/* Set to loaded when /etc/passwd has been read in by read_etc_passwd (). - Set to emulated if passwd is emulated. */ -/* Functions in this file need to check the value of passwd_state - and read in the password file if it isn't set. */ -enum grp_state { - uninitialized = 0, - initializing, - emulated, - loaded -}; -class grp_check { - grp_state state; - FILETIME last_modified; - char grp_w32[MAX_PATH]; - -public: - grp_check () : state (uninitialized) - { - last_modified.dwLowDateTime = last_modified.dwHighDateTime = 0; - grp_w32[0] = '\0'; - } - operator grp_state () - { - HANDLE h; - WIN32_FIND_DATA data; - - if (!grp_w32[0]) /* First call. */ - { - path_conv g ("/etc/group", PC_SYM_FOLLOW | PC_FULL); - if (!g.error) - strcpy (grp_w32, g.get_win32 ()); - } - - if ((h = FindFirstFile (grp_w32, &data)) != INVALID_HANDLE_VALUE) - { - if (CompareFileTime (&data.ftLastWriteTime, &last_modified) > 0) - { - state = uninitialized; - last_modified = data.ftLastWriteTime; - } - FindClose (h); - } - return state; - } - void operator = (grp_state nstate) - { - state = nstate; - } -}; - -static grp_check group_state; +static pwdgrp_check group_state; static int parse_grp (struct group &grp, const char *line) @@ -215,6 +166,7 @@ read_etc_group () add_grp_line (linebuf); } + group_state.set_last_modified (f); fclose (f); group_state = loaded; } diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index a43869676..f6943cda8 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -1,6 +1,6 @@ /* passwd.cc: getpwnam () and friends - Copyright 1996, 1997, 1998 Cygnus Solutions. + Copyright 1996, 1997, 1998, 2001 Cygnus Solutions. This file is part of Cygwin. @@ -23,6 +23,7 @@ details. */ #include "pinfo.h" #include "cygheap.h" #include +#include "pwdgrp.h" /* Read /etc/passwd only once for better performance. This is done on the first call that needs information from it. */ @@ -31,57 +32,7 @@ static struct passwd *passwd_buf; /* passwd contents in memory */ static int curr_lines; static int max_lines; -/* Set to loaded when /etc/passwd has been read in by read_etc_passwd (). - Set to emulated if passwd is emulated. */ -/* Functions in this file need to check the value of passwd_state - and read in the password file if it isn't set. */ -enum pwd_state { - uninitialized = 0, - initializing, - emulated, - loaded -}; -class pwd_check { - pwd_state state; - FILETIME last_modified; - char pwd_w32[MAX_PATH]; - -public: - pwd_check () : state (uninitialized) - { - last_modified.dwLowDateTime = last_modified.dwHighDateTime = 0; - pwd_w32[0] = '\0'; - } - operator pwd_state () - { - HANDLE h; - WIN32_FIND_DATA data; - - if (!pwd_w32[0]) /* First call. */ - { - path_conv p ("/etc/passwd", PC_SYM_FOLLOW | PC_FULL); - if (!p.error) - strcpy (pwd_w32, p.get_win32 ()); - } - - if ((h = FindFirstFile (pwd_w32, &data)) != INVALID_HANDLE_VALUE) - { - if (CompareFileTime (&data.ftLastWriteTime, &last_modified) > 0) - { - state = uninitialized; - last_modified = data.ftLastWriteTime; - } - FindClose (h); - } - return state; - } - void operator = (pwd_state nstate) - { - state = nstate; - } -}; - -static pwd_check passwd_state; +static pwdgrp_check passwd_state; /* Position in the passwd cache */ @@ -200,6 +151,7 @@ read_etc_passwd () add_pwd_line (linebuf); } + passwd_state.set_last_modified (f); fclose (f); passwd_state = loaded; } diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h new file mode 100644 index 000000000..bc27c7bb8 --- /dev/null +++ b/winsup/cygwin/pwdgrp.h @@ -0,0 +1,57 @@ +/* pwdgrp.h + + Copyright 2001 Red Hat inc. + + Stuff common to pwd and grp handling. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +enum pwdgrp_state { + uninitialized = 0, + initializing, + emulated, + loaded +}; + +class pwdgrp_check { + pwdgrp_state state; + FILETIME last_modified; + char file_w32[MAX_PATH]; + +public: + pwdgrp_check () : state (uninitialized) {} + operator pwdgrp_state () + { + if (state != uninitialized && file_w32[0] && cygheap->etc_changed ()) + { + HANDLE h; + WIN32_FIND_DATA data; + + if ((h = FindFirstFile (file_w32, &data)) != INVALID_HANDLE_VALUE) + { + if (CompareFileTime (&data.ftLastWriteTime, &last_modified) > 0) + state = uninitialized; + FindClose (h); + } + } + return state; + } + void operator = (pwdgrp_state nstate) + { + state = nstate; + } + void set_last_modified (FILE *f) + { + if (!file_w32[0]) + strcpy (file_w32, cygheap->fdtab[fileno (f)]->get_win32_name ()); + + BY_HANDLE_FILE_INFORMATION inf; + if (GetFileInformationByHandle (cygheap->fdtab[fileno (f)]->get_handle (), + &inf)) + last_modified = inf.ftLastWriteTime; + } +}; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 657aa883e..0e1e9fcc4 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -214,6 +214,9 @@ extern "C" int __small_vsprintf (char *dst, const char *fmt, va_list ap) /*__att extern "C" void __malloc_lock (struct _reent *); extern "C" void __malloc_unlock (struct _reent *); +extern "C" void __malloc_lock (struct _reent *); +extern "C" void __malloc_unlock (struct _reent *); + /**************************** Exports ******************************/ extern "C" {