Index: cygheap.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/cygheap.h,v retrieving revision 1.56 diff -u -p -r1.56 cygheap.h --- cygheap.h 22 Oct 2002 16:18:55 -0000 1.56 +++ cygheap.h 16 Jan 2003 06:47:32 -0000 @@ -216,15 +216,12 @@ struct init_cygheap mode_t umask; HANDLE shared_h; HANDLE console_h; - HANDLE etc_changed_h; char *cygwin_regname; cwdstuff cwd; dtable fdtab; #ifdef DEBUGGING cygheap_debug debug; #endif - - bool etc_changed (); }; #define CYGHEAPSIZE (sizeof (init_cygheap) + (16000 * sizeof (fhandler_union)) + (4 * 65536)) Index: cygheap.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/cygheap.cc,v retrieving revision 1.75 diff -u -p -r1.75 cygheap.cc --- cygheap.cc 15 Jan 2003 17:27:20 -0000 1.75 +++ cygheap.cc 16 Jan 2003 06:47:38 -0000 @@ -380,39 +380,6 @@ 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) { Index: pwdgrp.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/pwdgrp.h,v retrieving revision 1.8 diff -u -p -r1.8 pwdgrp.h --- pwdgrp.h 10 Dec 2002 12:43:49 -0000 1.8 +++ pwdgrp.h 16 Jan 2003 06:47:44 -0000 @@ -19,74 +19,101 @@ extern struct __group32 *internal_getgrs extern struct __group32 *internal_getgrgid (__gid32_t gid, BOOL = FALSE); extern struct __group32 *internal_getgrnam (const char *, BOOL = FALSE); extern struct __group32 *internal_getgrent (int); -int internal_getgroups (int, __gid32_t *); +int internal_getgroups (int, __gid32_t *, cygsid * = NULL); + +enum etc_changed_bits +{ + ETC_PASSWD = 1, + ETC_GROUP= 2 +}; + +struct etc_change +{ + HANDLE etc_changed_h; + int etc_changed_flags; + void etc_watch (); + bool etc_changed (etc_changed_bits); +}; enum pwdgrp_state { uninitialized = 0, initializing, - loaded + stable }; -class pwdgrp_check { - pwdgrp_state state; - FILETIME last_modified; - char file_w32[MAX_PATH]; +class pwdgrp_file { + path_conv pc; + pwdgrp_state *stateptr; /* state itself is NO_COPY */ + const char *posix_fname; + etc_changed_bits me; + HANDLE fh; + FILETIME last_modified; + char *buf; + char *lptr, *eptr; + static struct etc_change NO_COPY etc; public: - pwdgrp_check () : state (uninitialized) {} - BOOL isinitializing () + pwdgrp_file (const char *fname, pwdgrp_state * statep, etc_changed_bits who) + { + posix_fname = fname; + stateptr = statep; + me = who; + } + bool setpc () { - if (state <= initializing) - state = initializing; - else if (cygheap->etc_changed ()) + if (!pc.exists ()) { - if (!file_w32[0]) - state = initializing; - else + pc.check (posix_fname); + if (pc.error || !pc.exists () || !pc.isdisk () || pc.isdir ()) { - HANDLE h; - WIN32_FIND_DATA data; - - if ((h = FindFirstFile (file_w32, &data)) != INVALID_HANDLE_VALUE) - { - if (CompareFileTime (&data.ftLastWriteTime, &last_modified) > 0) - state = initializing; - FindClose (h); - } + pc.check (""); + return false; } } - return state == initializing; + return true; } - void operator = (pwdgrp_state nstate) + bool iamchanged () { - state = nstate; + HANDLE h; + WIN32_FIND_DATA data; + bool ret = false; + + if ((h = FindFirstFile (pc, &data)) != INVALID_HANDLE_VALUE) + { + ret = (CompareFileTime (&data.ftLastWriteTime, &last_modified) > 0); + FindClose (h); + } + return ret; + } + BOOL isuninitialized () + { + if (*stateptr != uninitialized) + return false; + /* start watching /etc */ + etc.etc_watch (); + /* buf isn't null when forked with file loaded */ + if (setpc () && buf && !iamchanged ()) + { + *stateptr = stable; + return false; + } + return true; } - BOOL isuninitialized () const { return state == uninitialized; } - void set_last_modified (HANDLE fh, const char *name) + BOOL isinitializing () { - if (!file_w32[0]) - strcpy (file_w32, name); - GetFileTime (fh, NULL, NULL, &last_modified); + if (*stateptr <= initializing) + return true; + else if (!etc.etc_changed (me) || !setpc () || !iamchanged ()) + return false; + *stateptr = initializing; + return true; } -}; - -class pwdgrp_read { - path_conv pc; - HANDLE fh; - char *buf; - char *lptr, *eptr; - -public: - bool open (const char *posix_fname) + bool read () { if (buf) free (buf); buf = lptr = eptr = NULL; - pc.check (posix_fname); - if (pc.error || !pc.exists () || !pc.isdisk () || pc.isdir ()) - return false; - fh = CreateFile (pc, GENERIC_READ, wincap.shared (), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (fh != INVALID_HANDLE_VALUE) @@ -98,14 +125,16 @@ public: if (buf) free (buf); buf = NULL; - CloseHandle (fh); - fh = NULL; - return false; } - buf[read_bytes] = '\0'; - return true; + else + { + buf[read_bytes] = '\0'; + GetFileTime (fh, NULL, NULL, &last_modified); + } + CloseHandle (fh); } - return false; + *stateptr = stable; + return (buf != NULL); } char *gets () { @@ -125,13 +154,5 @@ public: *eptr++ = '\0'; } return lptr; - } - inline HANDLE get_fhandle () { return fh; } - inline const char *get_fname () { return pc; } - void close () - { - if (fh) - CloseHandle (fh); - fh = NULL; } }; Index: passwd.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/passwd.cc,v retrieving revision 1.57 diff -u -p -r1.57 passwd.cc --- passwd.cc 10 Jan 2003 12:32:46 -0000 1.57 +++ passwd.cc 16 Jan 2003 06:47:49 -0000 @@ -23,14 +23,53 @@ details. */ #include #include "pwdgrp.h" +/* Per process data */ +struct etc_change NO_COPY pwdgrp_file::etc; +static pwdgrp_state NO_COPY state; + +void +etc_change::etc_watch () +{ + 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); + } +} +bool +etc_change::etc_changed (etc_changed_bits who) +{ + bool res = 0; + + if (etc_changed_h != INVALID_HANDLE_VALUE) + { + if (etc_changed_flags & who) + { + etc_changed_flags &= ~who; + res = 1; + } + else if (WaitForSingleObject (etc_changed_h, 0) == WAIT_OBJECT_0) + { + (void) FindNextChangeNotification (etc_changed_h); + etc_changed_flags |= ~who; + res = 1; + } + } + return res; +} + + /* Read /etc/passwd only once for better performance. This is done on the first call that needs information from it. */ static struct passwd *passwd_buf; /* passwd contents in memory */ static int curr_lines; static int max_lines; - -static pwdgrp_check passwd_state; +static pwdgrp_file pwd_file ("/etc/passwd", &state, ETC_PASSWD); /* Position in the passwd cache */ @@ -40,7 +79,7 @@ static pwdgrp_check passwd_state; static int pw_pos = 0; #endif -/* Remove a : teminated string from the buffer, and increment the pointer */ +/* Remove a : terminated string from the buffer, and increment the pointer */ static char * grab_string (char **p) { @@ -65,7 +104,7 @@ grab_int (char **p) { char *src = *p; unsigned int val = strtoul (src, p, 10); - *p = (*p == src || **p != ':') ? almost_null : *p + 1; + *p = (*p == src || **p != ':') ? (char *) "" : *p + 1; return val; } @@ -127,7 +166,6 @@ pthread_mutex_t NO_COPY passwd_lock::mut static void read_etc_passwd () { - static pwdgrp_read pr; /* A mutex is ok for speed here - pthreads will use critical sections not * mutexes for non-shared mutexes in the future. Also, this function will @@ -136,34 +174,31 @@ read_etc_passwd () passwd_lock here (cygwin_finished_initializing); /* if we got blocked by the mutex, then etc_passwd may have been processed */ - if (passwd_state.isinitializing ()) + if (pwd_file.isinitializing ()) { curr_lines = 0; - if (pr.open ("/etc/passwd")) + if (pwd_file.read ()) { char *line; - while ((line = pr.gets ()) != NULL) + while ((line = pwd_file.gets ()) != NULL) add_pwd_line (line); - passwd_state.set_last_modified (pr.get_fhandle (), pr.get_fname ()); - pr.close (); debug_printf ("Read /etc/passwd, %d lines", curr_lines); } - passwd_state = loaded; static char linebuf[1024]; char strbuf[128] = ""; BOOL searchentry = TRUE; - __uid32_t default_uid = DEFAULT_UID; struct passwd *pw; if (wincap.has_security ()) { + static char pretty_ls[] = "????????:*:-1:-1:"; + add_pwd_line (pretty_ls); cygsid tu = cygheap->user.sid (); tu.string (strbuf); - if (myself->uid == ILLEGAL_UID - && (searchentry = !internal_getpwsid (tu))) - default_uid = DEFAULT_UID_NT; + if (myself->uid == ILLEGAL_UID) + searchentry = !internal_getpwsid (tu); } else if (myself->uid == ILLEGAL_UID) searchentry = !internal_getpwuid (DEFAULT_UID); @@ -173,11 +208,12 @@ read_etc_passwd () myself->uid != (__uid32_t) pw->pw_uid && !internal_getpwuid (myself->uid)))) { + (void) cygheap->user.ontherange (CH_HOME, NULL); snprintf (linebuf, sizeof (linebuf), "%s:*:%lu:%lu:,%s:%s:/bin/sh", cygheap->user.name (), - myself->uid == ILLEGAL_UID ? default_uid : myself->uid, + myself->uid == ILLEGAL_UID ? DEFAULT_UID_NT : myself->uid, myself->gid, - strbuf, getenv ("HOME") ?: "/"); + strbuf, getenv ("HOME") ?: ""); debug_printf ("Completing /etc/passwd: %s", linebuf); add_pwd_line (linebuf); } @@ -192,7 +228,7 @@ internal_getpwsid (cygsid &sid) char *ptr1, *ptr2, *endptr; char sid_string[128] = {0,','}; - if (passwd_state.isuninitialized ()) + if (pwd_file.isuninitialized ()) read_etc_passwd (); if (sid.string (sid_string + 2)) @@ -211,8 +247,8 @@ internal_getpwsid (cygsid &sid) struct passwd * internal_getpwuid (__uid32_t uid, BOOL check) { - if (passwd_state.isuninitialized () - || (check && passwd_state.isinitializing ())) + if (pwd_file.isuninitialized () + || (check && pwd_file.isinitializing ())) read_etc_passwd (); for (int i = 0; i < curr_lines; i++) @@ -224,8 +260,8 @@ internal_getpwuid (__uid32_t uid, BOOL c struct passwd * internal_getpwnam (const char *name, BOOL check) { - if (passwd_state.isuninitialized () - || (check && passwd_state.isinitializing ())) + if (pwd_file.isuninitialized () + || (check && pwd_file.isinitializing ())) read_etc_passwd (); for (int i = 0; i < curr_lines; i++) @@ -347,7 +383,7 @@ getpwnam_r (const char *nam, struct pass extern "C" struct passwd * getpwent (void) { - if (passwd_state.isinitializing ()) + if (pwd_file.isinitializing ()) read_etc_passwd (); if (pw_pos < curr_lines) @@ -390,7 +426,7 @@ getpass (const char * prompt) #endif struct termios ti, newti; - if (passwd_state.isinitializing ()) + if (pwd_file.isinitializing ()) read_etc_passwd (); cygheap_fdget fhstdin (0); Index: grp.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/grp.cc,v retrieving revision 1.61 diff -u -p -r1.61 grp.cc --- grp.cc 10 Dec 2002 12:43:49 -0000 1.61 +++ grp.cc 16 Jan 2003 06:47:57 -0000 @@ -29,9 +29,13 @@ details. */ /* Read /etc/group only once for better performance. This is done on the first call that needs information from it. */ +/* Per process data */ +static pwdgrp_state NO_COPY state; + static struct __group32 *group_buf; /* group contents in memory */ static int curr_lines; static int max_lines; +static pwdgrp_file grp_file ("/etc/group", &state, ETC_GROUP); /* Position in the group cache */ #ifdef _MT_SAFE @@ -40,7 +44,6 @@ static int max_lines; static int grp_pos = 0; #endif -static pwdgrp_check group_state; static char * NO_COPY null_ptr = NULL; static int @@ -129,35 +132,29 @@ pthread_mutex_t NO_COPY group_lock::mute static void read_etc_group () { - static pwdgrp_read gr; - group_lock here (cygwin_finished_initializing); /* if we got blocked by the mutex, then etc_group may have been processed */ - if (group_state.isinitializing ()) + if (grp_file.isinitializing ()) { for (int i = 0; i < curr_lines; i++) if ((group_buf + i)->gr_mem != &null_ptr) free ((group_buf + i)->gr_mem); curr_lines = 0; - if (gr.open ("/etc/group")) + if (grp_file.read ()) { char *line; - while ((line = gr.gets ()) != NULL) + while ((line = grp_file.gets ()) != NULL) add_grp_line (line); - group_state.set_last_modified (gr.get_fhandle (), gr.get_fname ()); - gr.close (); debug_printf ("Read /etc/group, %d lines", curr_lines); } - group_state = loaded; - /* Complete /etc/group in memory if needed */ if (!internal_getgrgid (myself->gid)) { static char linebuf [200]; - char group_name [UNLEN + 1] = "unknown"; + char group_name [UNLEN + 1] = "mkgroup"; char strbuf[128] = ""; if (wincap.has_security ()) @@ -173,6 +170,9 @@ read_etc_group () debug_printf ("Completing /etc/group: %s", linebuf); add_grp_line (linebuf); } + static char pretty_ls[] = "????????::-1:"; + if (wincap.has_security ()) + add_grp_line (pretty_ls); } return; } @@ -182,7 +182,7 @@ internal_getgrsid (cygsid &sid) { char sid_string[128]; - if (group_state.isuninitialized ()) + if (grp_file.isuninitialized ()) read_etc_group (); if (sid.string (sid_string)) @@ -195,27 +195,21 @@ internal_getgrsid (cygsid &sid) struct __group32 * internal_getgrgid (__gid32_t gid, BOOL check) { - struct __group32 * default_grp = NULL; - - if (group_state.isuninitialized () - || (check && group_state.isinitializing ())) + if (grp_file.isuninitialized () + || (check && grp_file.isinitializing ())) read_etc_group (); for (int i = 0; i < curr_lines; i++) - { - if (group_buf[i].gr_gid == myself->gid) - default_grp = group_buf + i; - if (group_buf[i].gr_gid == gid) - return group_buf + i; - } - return allow_ntsec || gid != ILLEGAL_GID ? NULL : default_grp; + if (group_buf[i].gr_gid == gid) + return group_buf + i; + return NULL; } struct __group32 * internal_getgrnam (const char *name, BOOL check) { - if (group_state.isuninitialized () - || (check && group_state.isinitializing ())) + if (grp_file.isuninitialized () + || (check && grp_file.isinitializing ())) read_etc_group (); for (int i = 0; i < curr_lines; i++) @@ -280,7 +274,7 @@ endgrent () extern "C" struct __group32 * getgrent32 () { - if (group_state.isinitializing ()) + if (grp_file.isinitializing ()) read_etc_group (); if (grp_pos < curr_lines) @@ -307,7 +301,7 @@ setgrent () struct __group32 * internal_getgrent (int pos) { - if (group_state.isuninitialized ()) + if (grp_file.isuninitialized ()) read_etc_group (); if (pos < curr_lines) @@ -316,7 +310,7 @@ internal_getgrent (int pos) } int -internal_getgroups (int gidsetsize, __gid32_t *grouplist) +internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygsid * srchsid) { HANDLE hToken = NULL; DWORD size; @@ -345,6 +339,13 @@ internal_getgroups (int gidsetsize, __gi { cygsid sid; + if (srchsid) + { + for (DWORD pg = 0; pg < groups->GroupCount; ++pg) + if (*srchsid == groups->Groups[pg].Sid) + return 1; + return 0; + } for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx) if (sid.getfromgr (gr)) for (DWORD pg = 0; pg < groups->GroupCount; ++pg)