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

Corinna Vinschen cygwin-patches@cygwin.com
Sat Aug 4 12:59:00 GMT 2001


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.

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.

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.



More information about the Cygwin-patches mailing list