diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index acf923735..3f1a04fd0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,29 @@ +2003-01-21 Christopher Faylor + + * grp.cc: Call gr.refresh() rather than doing isunitialized tests + throughout. + (gr): Use constructor (sigh). + (pwdgrp::parse_group): Rename from parse_grp. + (pwdgrp::read_group): Rename from read_etc_group. Just call gr.load + with a single argument. + * passwd.cc: Call pr.refresh() rather than doing isunitialized tests + throughout. + (pr): Use constructor (sigh). + (pwdgrp::parse_passwd): Rename from "parse_pwd". + (pwdgrp::read_passwd): Rename from read_etc_passwd. Just call pr.load + with a single argument. + * pwdgrp.h (pwdgrp_state): Eliminate. + (pwdgrp): Reflect above renamings. + (pwdgrp::etc_ix): Rename from pwd_ix. + (pwdgrp::read): New element. + (pwdgrp::lock): New element. + (pwdgrp::refresh): New function. + (pwdgrp::load): Eliminate variations which take buffer arguments. + (pwdgrp::pwdgrp): New constructors. Initialize mutex here. + * uinfo.cc (pwdgrp::load): Accommodate pwd_ix -> etc_ix renaming. + (pwdgrp::load): Set initialized state to true rather than setting state + to loaded. + 2003-01-21 Christopher Faylor * include/cygwin/version.h: Bump DLL minor number. diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index dc1330429..529fdbe26 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -29,19 +29,19 @@ details. */ /* Position in the group cache */ #define grp_pos _reent_winsup ()->_grp_pos -static pwdgrp gr; static __group32 *group_buf; +static pwdgrp gr (group_buf); static char * NO_COPY null_ptr; bool -pwdgrp::parse_grp (char *line) +pwdgrp::parse_group (char *line) { char *dp = strchr (line, ':'); if (!dp) return false; -# define grp (* group_buf)[curr_lines] +# define grp (*group_buf)[curr_lines] *dp++ = '\0'; grp.gr_name = line; @@ -83,68 +83,43 @@ pwdgrp::parse_grp (char *line) # undef grp } -class group_lock -{ - bool armed; - static NO_COPY pthread_mutex_t mutex; -public: - group_lock (bool doit) - { - if (armed = doit) - pthread_mutex_lock (&mutex); - } - ~group_lock () - { - if (armed) - pthread_mutex_unlock (&mutex); - } -}; - -pthread_mutex_t NO_COPY group_lock::mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; - /* Cygwin internal */ /* Read in /etc/group and save contents in the group cache */ /* This sets group_in_memory_p to 1 so functions in this file can tell that /etc/group has been read in */ -static void -read_etc_group () +void +pwdgrp::read_group () { - group_lock here (cygwin_finished_initializing); + for (int i = 0; i < gr.curr_lines; i++) + if ((*group_buf)[i].gr_mem != &null_ptr) + free ((*group_buf)[i].gr_mem); - /* if we got blocked by the mutex, then etc_group may have been processed */ - if (gr.isinitializing ()) + if (!gr.load ("/etc/group")) + debug_printf ("gr.load failed"); + + /* Complete /etc/group in memory if needed */ + if (!internal_getgrgid (myself->gid)) { - for (int i = 0; i < gr.curr_lines; i++) - if ((group_buf + i)->gr_mem != &null_ptr) - free ((group_buf + i)->gr_mem); + static char linebuf [200]; + char group_name [UNLEN + 1] = "mkgroup"; + char strbuf[128] = ""; - if (!gr.load ("/etc/group", group_buf)) - debug_printf ("gr.load failed"); - - /* Complete /etc/group in memory if needed */ - if (!internal_getgrgid (myself->gid)) - { - static char linebuf [200]; - char group_name [UNLEN + 1] = "mkgroup"; - char strbuf[128] = ""; - - if (wincap.has_security ()) - { - struct __group32 *gr; - - cygheap->user.groups.pgsid.string (strbuf); - if ((gr = internal_getgrsid (cygheap->user.groups.pgsid))) - strlcpy (group_name, gr->gr_name, sizeof (group_name)); - } - snprintf (linebuf, sizeof (linebuf), "%s:%s:%lu:%s", - group_name, strbuf, myself->gid, cygheap->user.name ()); - debug_printf ("Completing /etc/group: %s", linebuf); - gr.add_line (linebuf); - } - static char NO_COPY pretty_ls[] = "????????::-1:"; if (wincap.has_security ()) - gr.add_line (pretty_ls); + { + struct __group32 *gr; + + cygheap->user.groups.pgsid.string (strbuf); + if ((gr = internal_getgrsid (cygheap->user.groups.pgsid))) + strlcpy (group_name, gr->gr_name, sizeof (group_name)); + } + snprintf (linebuf, sizeof (linebuf), "%s:%s:%lu:%s", + group_name, strbuf, myself->gid, cygheap->user.name ()); + debug_printf ("Completing /etc/group: %s", linebuf); + gr.add_line (linebuf); } + static char NO_COPY pretty_ls[] = "????????::-1:"; + if (wincap.has_security ()) + gr.add_line (pretty_ls); return; } @@ -153,8 +128,7 @@ internal_getgrsid (cygsid &sid) { char sid_string[128]; - if (gr.isuninitialized ()) - read_etc_group (); + gr.refresh (); if (sid.string (sid_string)) for (int i = 0; i < gr.curr_lines; i++) @@ -166,8 +140,7 @@ internal_getgrsid (cygsid &sid) struct __group32 * internal_getgrgid (__gid32_t gid, bool check) { - if (gr.isuninitialized () || (check && gr.isinitializing ())) - read_etc_group (); + gr.refresh (check); for (int i = 0; i < gr.curr_lines; i++) if (group_buf[i].gr_gid == gid) @@ -178,8 +151,7 @@ internal_getgrgid (__gid32_t gid, bool check) struct __group32 * internal_getgrnam (const char *name, bool check) { - if (gr.isuninitialized () || (check && gr.isinitializing ())) - read_etc_group (); + gr.refresh (check); for (int i = 0; i < gr.curr_lines; i++) if (strcasematch (group_buf[i].gr_name, name)) @@ -242,8 +214,7 @@ endgrent () extern "C" struct __group32 * getgrent32 () { - if (gr.isinitializing ()) - read_etc_group (); + gr.refresh (); if (grp_pos < gr.curr_lines) return group_buf + grp_pos++; @@ -269,8 +240,7 @@ setgrent () struct __group32 * internal_getgrent (int pos) { - if (gr.isuninitialized ()) - read_etc_group (); + gr.refresh (); if (pos < gr.curr_lines) return group_buf + pos; diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 91cbfa62f..81ba9edab 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -26,8 +26,9 @@ details. */ /* Read /etc/passwd only once for better performance. This is done on the first call that needs information from it. */ -static pwdgrp pr; passwd *passwd_buf; +/* FIXME: This really should use a constructor, but they are slow */ +static pwdgrp pr (passwd_buf); /* Position in the passwd cache */ #define pw_pos _reent_winsup ()->_pw_pos @@ -63,7 +64,7 @@ grab_int (char **p) /* Parse /etc/passwd line into passwd structure. */ bool -pwdgrp::parse_pwd (char *buf) +pwdgrp::parse_passwd (char *buf) { # define res (*passwd_buf)[curr_lines] /* Allocate enough room for the passwd struct and all the strings @@ -83,75 +84,45 @@ pwdgrp::parse_pwd (char *buf) # undef res } -class passwd_lock -{ - bool armed; - static NO_COPY pthread_mutex_t mutex; - public: - passwd_lock (bool doit) - { - if (doit) - pthread_mutex_lock (&mutex); - armed = doit; - } - ~passwd_lock () - { - if (armed) - pthread_mutex_unlock (&mutex); - } -}; - -pthread_mutex_t NO_COPY passwd_lock::mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; - /* Read in /etc/passwd and save contents in the password cache. This sets pr to loaded or emulated so functions in this file can tell that /etc/passwd has been read in or will be emulated. */ -static void -read_etc_passwd () +void +pwdgrp::read_passwd () { - /* 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 - * at most be called once from each thread, after that the pr - * test will succeed */ - passwd_lock here (cygwin_finished_initializing); + if (!load ("/etc/passwd")) + debug_printf ("load failed"); - /* if we got blocked by the mutex, then etc_passwd may have been processed */ - if (pr.isinitializing ()) + char strbuf[128] = ""; + bool searchentry = true; + struct passwd *pw; + + if (wincap.has_security ()) { - if (!pr.load ("/etc/passwd", passwd_buf)) - debug_printf ("pr.load failed"); - - char strbuf[128] = ""; - bool searchentry = true; - struct passwd *pw; - - if (wincap.has_security ()) - { - static char NO_COPY pretty_ls[] = "????????:*:-1:-1:"; - pr.add_line (pretty_ls); - cygsid tu = cygheap->user.sid (); - tu.string (strbuf); - if (myself->uid == ILLEGAL_UID) - searchentry = !internal_getpwsid (tu); - } - else if (myself->uid == ILLEGAL_UID) - searchentry = !internal_getpwuid (DEFAULT_UID); - if (searchentry && - (!(pw = internal_getpwnam (cygheap->user.name ())) || - (myself->uid != ILLEGAL_UID && - myself->uid != (__uid32_t) pw->pw_uid && - !internal_getpwuid (myself->uid)))) - { - char linebuf[1024]; - (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_NT : myself->uid, - myself->gid, - strbuf, getenv ("HOME") ?: ""); - debug_printf ("Completing /etc/passwd: %s", linebuf); - pr.add_line (linebuf); - } + static char NO_COPY pretty_ls[] = "????????:*:-1:-1:"; + pr.add_line (pretty_ls); + cygsid tu = cygheap->user.sid (); + tu.string (strbuf); + if (myself->uid == ILLEGAL_UID) + searchentry = !internal_getpwsid (tu); + } + else if (myself->uid == ILLEGAL_UID) + searchentry = !internal_getpwuid (DEFAULT_UID); + if (searchentry && + (!(pw = internal_getpwnam (cygheap->user.name ())) || + (myself->uid != ILLEGAL_UID && + myself->uid != (__uid32_t) pw->pw_uid && + !internal_getpwuid (myself->uid)))) + { + char linebuf[1024]; + (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_NT : myself->uid, + myself->gid, + strbuf, getenv ("HOME") ?: ""); + debug_printf ("Completing /etc/passwd: %s", linebuf); + pr.add_line (linebuf); } return; } @@ -163,8 +134,7 @@ internal_getpwsid (cygsid &sid) char *ptr1, *ptr2, *endptr; char sid_string[128] = {0,','}; - if (pr.isuninitialized ()) - read_etc_passwd (); + pr.refresh (); if (sid.string (sid_string + 2)) { @@ -182,8 +152,7 @@ internal_getpwsid (cygsid &sid) struct passwd * internal_getpwuid (__uid32_t uid, bool check) { - if (pr.isuninitialized () || (check && pr.isinitializing ())) - read_etc_passwd (); + pr.refresh (check); for (int i = 0; i < pr.curr_lines; i++) if (uid == (__uid32_t) passwd_buf[i].pw_uid) @@ -194,8 +163,7 @@ internal_getpwuid (__uid32_t uid, bool check) struct passwd * internal_getpwnam (const char *name, bool check) { - if (pr.isuninitialized () || (check && pr.isinitializing ())) - read_etc_passwd (); + pr.refresh (check); for (int i = 0; i < pr.curr_lines; i++) /* on Windows NT user names are case-insensitive */ @@ -316,8 +284,7 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s extern "C" struct passwd * getpwent (void) { - if (pr.isinitializing ()) - read_etc_passwd (); + pr.refresh (); if (pw_pos < pr.curr_lines) return passwd_buf + pw_pos++; @@ -355,8 +322,7 @@ getpass (const char * prompt) char *pass=_reent_winsup ()->_pass; struct termios ti, newti; - if (pr.isinitializing ()) - read_etc_passwd (); + pr.refresh (); cygheap_fdget fhstdin (0); diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h index 566c40137..eb0a974d1 100644 --- a/winsup/cygwin/pwdgrp.h +++ b/winsup/cygwin/pwdgrp.h @@ -21,59 +21,61 @@ extern struct __group32 *internal_getgrnam (const char *, bool = FALSE); extern struct __group32 *internal_getgrent (int); int internal_getgroups (int, __gid32_t *, cygsid * = NULL); -enum pwdgrp_state { - uninitialized = 0, - initializing, - loaded -}; - class pwdgrp { - pwdgrp_state state; - int pwd_ix; - path_conv pc; - char *buf; - int max_lines; + unsigned pwdgrp_buf_elem_size; union { passwd **passwd_buf; __group32 **group_buf; void **pwdgrp_buf; }; - unsigned pwdgrp_buf_elem_size; + void (pwdgrp::*read) (); bool (pwdgrp::*parse) (char *); + int etc_ix; + path_conv pc; + char *buf; + int max_lines; + bool initialized; + CRITICAL_SECTION lock; char *gets (char*&); - bool parse_pwd (char *); - bool parse_grp (char *); public: int curr_lines; + bool parse_passwd (char *); + bool parse_group (char *); + void read_passwd (); + void read_group (); + void add_line (char *); - bool isinitializing () + void refresh (bool check = true) { - if (state <= initializing) - state = initializing; - else if (etc::file_changed (pwd_ix)) - state = initializing; - return state == initializing; + if (initialized && check && etc::file_changed (etc_ix)) + initialized = false; + if (!initialized) + { + EnterCriticalSection (&lock); + if (!initialized) + (this->*read) (); + LeaveCriticalSection (&lock); + } } - bool isuninitialized () const { return state == uninitialized; } bool load (const char *); - bool load (const char *posix_fname, passwd *&buf) - { - passwd_buf = &buf; - pwdgrp_buf_elem_size = sizeof (*buf); - parse = &pwdgrp::parse_pwd; - return load (posix_fname); - } - bool load (const char *posix_fname, __group32 *&buf) - { - group_buf = &buf; - pwdgrp_buf_elem_size = sizeof (*buf); - parse = &pwdgrp::parse_grp; - return load (posix_fname); - } + pwdgrp (passwd *&pbuf) : + pwdgrp_buf_elem_size (sizeof (*pbuf)), passwd_buf (&pbuf) + { + read = &pwdgrp::read_passwd; + parse = &pwdgrp::parse_passwd; + InitializeCriticalSection (&lock); + } + pwdgrp (__group32 *&gbuf) : + pwdgrp_buf_elem_size (sizeof (*gbuf)), group_buf (&gbuf) + { + read = &pwdgrp::read_group; + parse = &pwdgrp::parse_group; + InitializeCriticalSection (&lock); + } }; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 2e10b47ed..0c154ea69 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -429,7 +429,7 @@ pwdgrp::load (const char *posix_fname) buf = NULL; pc.check (posix_fname); - pwd_ix = etc::init (pwd_ix, pc); + etc_ix = etc::init (etc_ix, pc); paranoid_printf ("%s", posix_fname); @@ -470,6 +470,6 @@ pwdgrp::load (const char *posix_fname) } } - state = loaded; + initialized = true; return res; }