[PATCH]: Check modification time on /etc/passwd and /etc/group

Christopher Faylor cgf@redhat.com
Sat Aug 4 14:21:00 GMT 2001


On Sat, Aug 04, 2001 at 09:59:35PM +0200, Corinna Vinschen wrote:
>On Fri, Aug 03, 2001 at 11:39:03PM +1000, Robert Collins wrote:
>> Have you tried touch /etc/passwd? 
>> What I mean is that the following code cycle seems inevitable to me :
>> 
>> read_etc_password
>> \->check_state
>>    \->stat()
>>       \->check acls
>>          \->(couple of steps here from memory)
>>             \->read_etc_password
>>                \->check_state
>> 
>> and so on. There was a similar loop with fopen() whcih we discussed when
>> we introduced getpwuid_r.
>
>I haven't found such a problem. I had no endless loop. However, I have
>a redefined solution which doesn't use stat(). Instead it converts
>the /etc/passwd and /etc/group paths to win32 paths and accesses them
>directly using FileFirstFind() which should be way faster.

This is probably ok but there is a potential gotcha if the user changes
a mount or makes a symbolic link to /etc/passwd or something.

>If we additionally change the read_etc_passwd() and read_etc_group()
>code so that direct win32 calls are used for reading the files, we could
>perhaps speed up Cygwin again a few percent.

I think we'd get much more savings by moving /etc/passwd info into either
the cygwin heap or shared memory so that /etc/passwd wasn't read by
each exec'ed process.  Then the file would only be read when it was
needed.

Actually, it's possible that /etc/passwd isn't read by an exec'ed process
now unless it needs to look up a uid other than it's own.  I don't know
for sure.

cgf
>The ChangeLog is the same as in my first mail.
>
>Corinna
>
>Index: grp.cc
>===================================================================
>RCS file: /cvs/src/src/winsup/cygwin/grp.cc,v
>retrieving revision 1.26
>diff -u -p -r1.26 grp.cc
>--- grp.cc	2001/07/26 19:22:24	1.26
>+++ grp.cc	2001/08/04 19:57:07
>@@ -23,6 +23,7 @@ details. */
> #include "security.h"
> #include "fhandler.h"
> #include "dtable.h"
>+#include "path.h"
> #include "cygheap.h"
> #include "cygerrno.h"
> 
>@@ -51,8 +52,48 @@ enum grp_state {
>   emulated,
>   loaded
> };
>-static grp_state group_state = uninitialized;
>+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 int
> parse_grp (struct group &grp, const char *line)
> {
>@@ -153,6 +194,7 @@ read_etc_group ()
>   if (group_state != initializing)
>     {
>       group_state = initializing;
>+      curr_lines = 0;
> 
>       FILE *f = fopen (etc_group, "rt");
> 
>Index: passwd.cc
>===================================================================
>RCS file: /cvs/src/src/winsup/cygwin/passwd.cc,v
>retrieving revision 1.27
>diff -u -p -r1.27 passwd.cc
>--- passwd.cc	2001/07/26 19:22:24	1.27
>+++ passwd.cc	2001/08/04 19:57:07
>@@ -17,6 +17,7 @@ details. */
> #include "security.h"
> #include "fhandler.h"
> #include "dtable.h"
>+#include "path.h"
> #include "sync.h"
> #include "sigproc.h"
> #include "pinfo.h"
>@@ -40,8 +41,49 @@ enum pwd_state {
>   emulated,
>   loaded
> };
>-static pwd_state passwd_state = uninitialized;
>+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;
>+
>+
> /* Position in the passwd cache */
> #ifdef _MT_SAFE
> #define pw_pos  _reent_winsup ()->_pw_pos
>@@ -140,6 +182,7 @@ read_etc_passwd ()
>     if (passwd_state != initializing)
>       {
> 	passwd_state = initializing;
>+	curr_lines = 0;
> 
> 	FILE *f = fopen ("/etc/passwd", "rt");
> 
>
>-- 
>Corinna Vinschen                  Please, send mails regarding Cygwin to
>Cygwin Developer                                mailto:cygwin@cygwin.com
>Red Hat, Inc.

-- 
cgf@cygnus.com                        Red Hat, Inc.
http://sources.redhat.com/            http://www.redhat.com/



More information about the Cygwin-patches mailing list