diff options
Diffstat (limited to 'winsup/cygwin/passwd.cc')
-rw-r--r-- | winsup/cygwin/passwd.cc | 213 |
1 files changed, 127 insertions, 86 deletions
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 88690e379..fb51d5aef 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -19,125 +19,158 @@ details. */ #include "dtable.h" #include "pinfo.h" #include "cygheap.h" -#include "pwdgrp.h" #include "shared_info.h" -/* Read /etc/passwd only once for better performance. This is done - on the first call that needs information from it. */ - -passwd *passwd_buf; -static pwdgrp pr (passwd_buf); - /* Parse /etc/passwd line into passwd structure. */ bool pwdgrp::parse_passwd () { - passwd &res = (*passwd_buf)[curr_lines]; - res.pw_name = next_str (':'); - res.pw_passwd = next_str (':'); - if (!next_num (res.pw_uid)) + pg_pwd &res = passwd ()[curr_lines]; + res.p.pw_name = next_str (':'); + res.p.pw_passwd = next_str (':'); + if (!next_num (res.p.pw_uid)) return false; - if (!next_num (res.pw_gid)) + if (!next_num (res.p.pw_gid)) return false; - res.pw_comment = NULL; - res.pw_gecos = next_str (':'); - res.pw_dir = next_str (':'); - res.pw_shell = next_str (':'); + res.p.pw_comment = NULL; + res.p.pw_gecos = next_str (':'); + res.p.pw_dir = next_str (':'); + res.p.pw_shell = next_str (':'); + res.sid.getfrompw (&res.p); return true; } -/* 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. */ void -pwdgrp::read_passwd () +pwdgrp::init_pwd () +{ + pwdgrp_buf_elem_size = sizeof (pg_pwd); + parse = &pwdgrp::parse_passwd; +} + +pwdgrp * +pwdgrp::prep_tls_pwbuf () { - load (L"\\etc\\passwd"); - - char strbuf[128] = ""; - bool searchentry = true; - struct passwd *pw; - /* must be static */ - static char NO_COPY pretty_ls[] = "????????:*:-1:-1:::"; - - add_line (pretty_ls); - cygsid tu = cygheap->user.sid (); - tu.string (strbuf); - if (!user_shared->cb || myself->uid == ILLEGAL_UID) - searchentry = !internal_getpwsid (tu); - if (searchentry - && (!(pw = internal_getpwnam (cygheap->user.name ())) - || !user_shared->cb - || (myself->uid != ILLEGAL_UID - && myself->uid != pw->pw_uid - && !internal_getpwuid (myself->uid)))) + if (!_my_tls.locals.pwbuf) { - static char linebuf[1024]; // must be static and - // should not be NO_COPY - snprintf (linebuf, sizeof (linebuf), "%s:*:%u:%u:,%s:%s:/bin/sh", - cygheap->user.name (), - (!user_shared->cb || myself->uid == ILLEGAL_UID) - ? UNKNOWN_UID : myself->uid, - !user_shared->cb ? UNKNOWN_GID : myself->gid, - strbuf, getenv ("HOME") ?: ""); - debug_printf ("Completing /etc/passwd: %s", linebuf); - add_line (linebuf); + _my_tls.locals.pwbuf = ccalloc_abort (HEAP_BUF, 1, + sizeof (pwdgrp) + sizeof (pg_pwd)); + pwdgrp *pw = (pwdgrp *) _my_tls.locals.pwbuf; + pw->init_pwd (); + pw->pwdgrp_buf = (void *) (pw + 1); + pw->max_lines = 1; } + pwdgrp *pw = (pwdgrp *) _my_tls.locals.pwbuf; + if (pw->curr_lines) + { + cfree (pw->passwd ()[0].p.pw_name); + pw->curr_lines = 0; + } + return pw; } struct passwd * -internal_getpwsid (cygpsid &sid) +pwdgrp::find_user (cygpsid &sid) +{ + for (ULONG i = 0; i < curr_lines; i++) + if (sid == passwd ()[i].sid) + return &passwd ()[i].p; + return NULL; +} + +struct passwd * +pwdgrp::find_user (const char *name) { - struct passwd *pw; - char *ptr1, *ptr2, *endptr; - char sid_string[128] = {0,','}; + for (ULONG i = 0; i < curr_lines; i++) + /* on Windows NT user names are case-insensitive */ + if (strcasematch (name, passwd ()[i].p.pw_name)) + return &passwd ()[i].p; + return NULL; +} - pr.refresh (false); +struct passwd * +pwdgrp::find_user (uid_t uid) +{ + for (ULONG i = 0; i < curr_lines; i++) + if (uid == passwd ()[i].p.pw_uid) + return &passwd ()[i].p; + return NULL; +} - if (sid.string (sid_string + 2)) +struct passwd * +internal_getpwsid (cygpsid &sid) +{ + struct passwd *ret; + + cygheap->pg.nss_init (); + if (cygheap->pg.nss_pwd_files ()) { - endptr = strchr (sid_string + 2, 0) - 1; - for (int i = 0; i < pr.curr_lines; i++) - { - pw = passwd_buf + i; - if (pw->pw_dir > pw->pw_gecos + 8) - for (ptr1 = endptr, ptr2 = pw->pw_dir - 2; - *ptr1 == *ptr2; ptr2--) - if (!*--ptr1) - return pw; - } + cygheap->pg.pwd_cache.file.check_file (false); + if ((ret = cygheap->pg.pwd_cache.file.find_user (sid))) + return ret; + if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (sid))) + return ret; + } + if (cygheap->pg.nss_pwd_db ()) + { + if ((ret = cygheap->pg.pwd_cache.win.find_user (sid))) + return ret; + return cygheap->pg.pwd_cache.win.add_user_from_windows (sid); } return NULL; } struct passwd * -internal_getpwuid (uid_t uid, bool check) +internal_getpwnam (const char *name) { - pr.refresh (check); + struct passwd *ret; - for (int i = 0; i < pr.curr_lines; i++) - if (uid == passwd_buf[i].pw_uid) - return passwd_buf + i; + cygheap->pg.nss_init (); + if (cygheap->pg.nss_pwd_files ()) + { + cygheap->pg.pwd_cache.file.check_file (false); + if ((ret = cygheap->pg.pwd_cache.file.find_user (name))) + return ret; + if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (name))) + return ret; + } + if (cygheap->pg.nss_pwd_db ()) + { + if ((ret = cygheap->pg.pwd_cache.win.find_user (name))) + return ret; + return cygheap->pg.pwd_cache.win.add_user_from_windows (name); + } return NULL; } struct passwd * -internal_getpwnam (const char *name, bool check) +internal_getpwuid (uid_t uid) { - pr.refresh (check); + struct passwd *ret; - for (int i = 0; i < pr.curr_lines; i++) - /* on Windows NT user names are case-insensitive */ - if (strcasematch (name, passwd_buf[i].pw_name)) - return passwd_buf + i; + cygheap->pg.nss_init (); + if (cygheap->pg.nss_pwd_files ()) + { + cygheap->pg.pwd_cache.file.check_file (false); + if ((ret = cygheap->pg.pwd_cache.file.find_user (uid))) + return ret; + if ((ret = cygheap->pg.pwd_cache.file.add_user_from_file (uid))) + return ret; + } + if (cygheap->pg.nss_pwd_db ()) + { + if ((ret = cygheap->pg.pwd_cache.win.find_user (uid))) + return ret; + return cygheap->pg.pwd_cache.win.add_user_from_windows (uid); + } + else if (uid == ILLEGAL_UID) + return cygheap->pg.pwd_cache.win.add_user_from_windows (uid); return NULL; } - extern "C" struct passwd * getpwuid32 (uid_t uid) { - struct passwd *temppw = internal_getpwuid (uid, true); + struct passwd *temppw = internal_getpwuid (uid); pthread_testcancel (); return temppw; } @@ -160,7 +193,7 @@ getpwuid_r32 (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struc if (!pwd || !buffer) return ERANGE; - struct passwd *temppw = internal_getpwuid (uid, true); + struct passwd *temppw = internal_getpwuid (uid); pthread_testcancel (); if (!temppw) return 0; @@ -198,7 +231,7 @@ getpwuid_r (__uid16_t uid, struct passwd *pwd, char *buffer, size_t bufsize, str extern "C" struct passwd * getpwnam (const char *name) { - struct passwd *temppw = internal_getpwnam (name, true); + struct passwd *temppw = internal_getpwnam (name); pthread_testcancel (); return temppw; } @@ -216,7 +249,7 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s if (!pwd || !buffer || !nam) return ERANGE; - struct passwd *temppw = internal_getpwnam (nam, true); + struct passwd *temppw = internal_getpwnam (nam); pthread_testcancel (); if (!temppw) @@ -245,11 +278,19 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s extern "C" struct passwd * getpwent (void) { - if (_my_tls.locals.pw_pos == 0) - pr.refresh (true); - if (_my_tls.locals.pw_pos < pr.curr_lines) - return passwd_buf + _my_tls.locals.pw_pos++; - + pwdgrp &prf = cygheap->pg.pwd_cache.file; + if (cygheap->pg.nss_pwd_files ()) + { + cygheap->pg.pwd_cache.file.check_file (false); + if (_my_tls.locals.pw_pos < prf.cached_users ()) + return &prf.passwd ()[_my_tls.locals.pw_pos++].p; + } + if ((cygheap->pg.nss_pwd_db ()) && cygheap->pg.nss_db_caching ()) + { + pwdgrp &prw = cygheap->pg.pwd_cache.win; + if (_my_tls.locals.pw_pos - prf.cached_users () < prw.cached_users ()) + return &prw.passwd ()[_my_tls.locals.pw_pos++ - prf.cached_users ()].p; + } return NULL; } |