diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e9c3a2077..3868a2f4c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,46 @@ +2003-01-17 Pierre Humblet + + * grp.cc (read_etc_group): On NT, add a line for gid = -1. Change name + "unknown" to "mkgroup". + (internal_getgrgid): Do not return default in nontsec case. + (internal_getgroups): Add argument srchsid and look for it in groups if + not NULL. + * passwd.cc (read_etc_passwd): On NT, add a line for uid = -1. Use + same default uid for Win95 and NT. Call cygheap_user::ontherange to + initialize HOME. + + +2003-01-16 Christopher Faylor + + * cygheap.cc (init_cygheap::etc_changed): Move to uinfo.cc. + * cygheap.h (init_cygheap::etc_changed_h): Remove. + (init_cygheap::etc_changed): Ditto. + * grp.cc (group_state): Remove. Use gr instead throughout. + (gr): Define as class pwdgrp. + (read_etc_group): Remove gr definition. Remove calls to + set_last_modified and close. Pass add_grp to gr.load to load file. + * passwd.cc (passwd_state): Remove. Use pr instead, throughout. + (pr): Define as class pwdgrp. + (read_etc_passwd): Remove pr definition. Remove calls to + set_last_modified and close. Pass add_pwd_line to pr.load to load + file. + * pwdgrp.h (etc): New helper class for pwdgrp. + (pwdgrp): Combine pwdgrp_check and pwdgrp_read into one class. Remove + file_w32 and last_modified fields. + (pwdgrp::set_last_modified): Remove. + (pwdgrp::isinitializing): Remove FindFirstFile stuff. Move to + etc::file_changed. + (pwdgrp::load): Rename from 'open'. Call etc::init to initialize etc + scanning. Close file handle after reading buffer into memory. Parse + buffer by calling second argument. + (pwdgrp::gets): Reorganize slightly to rely on eptr starting at + beginning of buffer. Free buffer when memory exhausted. + (pwdgrp::close): Remove. + * uinfo.cc (etc::dir_changed): New function. + (etc::init): Ditto. + (etc::file_changed): Ditto. + (etc::set_last_modified): Ditto. + 2003-01-16 Jason Tishler * mmap.cc (fixup_mmaps_after_fork): Add ERROR_NOACCESS to the list of diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index d0843e7ac..cdef3e490 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -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) { diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 703c1d1dc..bfa7a9308 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -1,6 +1,6 @@ /* cygheap.h: Cygwin heap manager. - Copyright 2000, 2001, 2002 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003 Red Hat, Inc. This file is part of Cygwin. @@ -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)) diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 51ccd066c..9ce2787d0 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -40,8 +40,8 @@ static int max_lines; static int grp_pos = 0; #endif -static pwdgrp_check group_state; -static char * NO_COPY null_ptr = NULL; +static pwdgrp gr; +static char * NO_COPY null_ptr; static int parse_grp (struct __group32 &grp, char *line) @@ -129,35 +129,24 @@ pthread_mutex_t NO_COPY group_lock::mutex = (pthread_mutex_t) PTHREAD_MUTEX_INIT 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 (gr.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")) - { - char *line; - while ((line = gr.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; + if (!gr.load ("/etc/group", add_grp_line)) + 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] = "unknown"; + char group_name [UNLEN + 1] = "mkgroup"; char strbuf[128] = ""; if (wincap.has_security ()) @@ -173,6 +162,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 +174,7 @@ internal_getgrsid (cygsid &sid) { char sid_string[128]; - if (group_state.isuninitialized ()) + if (gr.isuninitialized ()) read_etc_group (); if (sid.string (sid_string)) @@ -195,27 +187,19 @@ 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 (gr.isuninitialized () || (check && gr.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 (gr.isuninitialized () || (check && gr.isinitializing ())) read_etc_group (); for (int i = 0; i < curr_lines; i++) @@ -280,7 +264,7 @@ endgrent () extern "C" struct __group32 * getgrent32 () { - if (group_state.isinitializing ()) + if (gr.isinitializing ()) read_etc_group (); if (grp_pos < curr_lines) @@ -307,7 +291,7 @@ setgrent () struct __group32 * internal_getgrent (int pos) { - if (group_state.isuninitialized ()) + if (gr.isuninitialized ()) read_etc_group (); if (pos < curr_lines) @@ -316,7 +300,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 +329,13 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist) { 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) diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 2aca84c5d..d87864f52 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -30,8 +30,7 @@ static struct passwd *passwd_buf; /* passwd contents in memory */ static int curr_lines; static int max_lines; -static pwdgrp_check passwd_state; - +static pwdgrp pr; /* Position in the passwd cache */ #ifdef _MT_SAFE @@ -40,7 +39,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) { @@ -122,48 +121,37 @@ class passwd_lock 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 passwd_state to loaded or emulated so functions in this file can + 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 () { - 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 - * at most be called once from each thread, after that the passwd_state + * at most be called once from each thread, after that the pr * test will succeed */ 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 (pr.isinitializing ()) { curr_lines = 0; - if (pr.open ("/etc/passwd")) - { - char *line; - while ((line = pr.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; + if (!pr.load ("/etc/passwd", add_pwd_line)) + debug_printf ("pr.load failed"); 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 +161,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 +181,7 @@ internal_getpwsid (cygsid &sid) char *ptr1, *ptr2, *endptr; char sid_string[128] = {0,','}; - if (passwd_state.isuninitialized ()) + if (pr.isuninitialized ()) read_etc_passwd (); if (sid.string (sid_string + 2)) @@ -211,8 +200,8 @@ internal_getpwsid (cygsid &sid) struct passwd * internal_getpwuid (__uid32_t uid, BOOL check) { - if (passwd_state.isuninitialized () - || (check && passwd_state.isinitializing ())) + if (pr.isuninitialized () + || (check && pr.isinitializing ())) read_etc_passwd (); for (int i = 0; i < curr_lines; i++) @@ -224,8 +213,8 @@ internal_getpwuid (__uid32_t uid, BOOL check) struct passwd * internal_getpwnam (const char *name, BOOL check) { - if (passwd_state.isuninitialized () - || (check && passwd_state.isinitializing ())) + if (pr.isuninitialized () + || (check && pr.isinitializing ())) read_etc_passwd (); for (int i = 0; i < curr_lines; i++) @@ -347,7 +336,7 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s extern "C" struct passwd * getpwent (void) { - if (passwd_state.isinitializing ()) + if (pr.isinitializing ()) read_etc_passwd (); if (pw_pos < curr_lines) @@ -390,7 +379,7 @@ getpass (const char * prompt) #endif struct termios ti, newti; - if (passwd_state.isinitializing ()) + if (pr.isinitializing ()) read_etc_passwd (); cygheap_fdget fhstdin (0); diff --git a/winsup/cygwin/pwdgrp.h b/winsup/cygwin/pwdgrp.h index 6be1b32f7..c0466b446 100644 --- a/winsup/cygwin/pwdgrp.h +++ b/winsup/cygwin/pwdgrp.h @@ -19,7 +19,7 @@ extern struct __group32 *internal_getgrsid (cygsid &); 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 pwdgrp_state { uninitialized = 0, @@ -27,111 +27,107 @@ enum pwdgrp_state { loaded }; -class pwdgrp_check { - pwdgrp_state state; - FILETIME last_modified; - char file_w32[MAX_PATH]; +#define MAX_ETC_FILES 2 +class etc +{ + static int curr_ix; + static bool sawchange[MAX_ETC_FILES]; + static const char *fn[MAX_ETC_FILES]; + static FILETIME last_modified[MAX_ETC_FILES]; + static bool dir_changed (int); + static int init (int, const char *); + static bool file_changed (int); + static void set_last_modified (int, FILETIME&); + friend class pwdgrp; +}; + +class pwdgrp +{ + pwdgrp_state state; + int pwd_ix; + path_conv pc; + char *buf; + char *lptr, *eptr; + + char *gets () + { + if (!buf) + lptr = NULL; + else if (!eptr) + lptr = NULL; + else + { + lptr = eptr; + eptr = strchr (lptr, '\n'); + if (eptr) + { + if (eptr > lptr && *(eptr - 1) == '\r') + *(eptr - 1) = 0; + *eptr++ = '\0'; + } + } + return lptr; + } public: - pwdgrp_check () : state (uninitialized) {} + pwdgrp () : state (uninitialized) {} BOOL isinitializing () { if (state <= initializing) state = initializing; - else if (cygheap->etc_changed ()) - { - if (!file_w32[0]) - state = initializing; - else - { - 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); - } - } - } + else if (etc::file_changed (pwd_ix - 1)) + state = initializing; return state == initializing; } - void operator = (pwdgrp_state nstate) - { - state = nstate; - } + void operator = (pwdgrp_state nstate) { state = nstate; } BOOL isuninitialized () const { return state == uninitialized; } - void set_last_modified (HANDLE fh, const char *name) - { - if (!file_w32[0]) - strcpy (file_w32, name); - GetFileTime (fh, NULL, NULL, &last_modified); - } -}; -class pwdgrp_read { - path_conv pc; - HANDLE fh; - char *buf; - char *lptr, *eptr; - -public: - bool open (const char *posix_fname) + bool load (const char *posix_fname, void (* add_line) (char *)) { if (buf) free (buf); buf = lptr = eptr = NULL; pc.check (posix_fname); - if (pc.error || !pc.exists () || !pc.isdisk () || pc.isdir ()) - return false; + pwd_ix = etc::init (pwd_ix - 1, pc) + 1; - fh = CreateFile (pc, GENERIC_READ, wincap.shared (), NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); - if (fh != INVALID_HANDLE_VALUE) - { - DWORD size = GetFileSize (fh, NULL), read_bytes; - buf = (char *) malloc (size + 1); - if (!ReadFile (fh, buf, size, &read_bytes, NULL)) - { - if (buf) - free (buf); - buf = NULL; - CloseHandle (fh); - fh = NULL; - return false; - } - buf[read_bytes] = '\0'; - return true; - } - return false; - } - char *gets () - { - if (!buf) - return NULL; - if (!lptr) - lptr = buf; - else if (!eptr) - return lptr = NULL; + paranoid_printf ("%s", posix_fname); + + bool res; + if (pc.error || !pc.exists () || !pc.isdisk () || pc.isdir ()) + res = false; else - lptr = eptr; - eptr = strchr (lptr, '\n'); - if (eptr) { - if (eptr > lptr && *(eptr - 1) == '\r') - *(eptr - 1) = 0; - *eptr++ = '\0'; + HANDLE fh = CreateFile (pc, GENERIC_READ, wincap.shared (), NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (fh == INVALID_HANDLE_VALUE) + res = false; + else + { + DWORD size = GetFileSize (fh, NULL), read_bytes; + buf = (char *) malloc (size + 1); + if (!ReadFile (fh, buf, size, &read_bytes, NULL)) + { + if (buf) + free (buf); + buf = NULL; + fh = NULL; + return false; + } + buf[read_bytes] = '\0'; + eptr = buf; + CloseHandle (fh); + FILETIME ft; + if (GetFileTime (fh, NULL, NULL, &ft)) + etc::set_last_modified (pwd_ix - 1, ft); + char *line; + while ((line = gets()) != NULL) + add_line (line); + res = true; + } } - return lptr; - } - inline HANDLE get_fhandle () { return fh; } - inline const char *get_fname () { return pc; } - void close () - { - if (fh) - CloseHandle (fh); - fh = NULL; + + state = loaded; + return res; } }; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index a2a46a03f..5eb76b100 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -389,3 +389,88 @@ cygheap_user::env_name (const char *name, size_t namelen) (void) domain (); return pwinname; } + +int NO_COPY etc::curr_ix = -1; +bool NO_COPY etc::sawchange[MAX_ETC_FILES]; +const NO_COPY char *etc::fn[MAX_ETC_FILES]; +FILETIME NO_COPY etc::last_modified[MAX_ETC_FILES]; + +int +etc::init (int n, const char *etc_fn) +{ + if (n >= 0) + /* ok */; + else if (++curr_ix < MAX_ETC_FILES) + n = curr_ix; + else + api_fatal ("internal error"); + + fn[n] = etc_fn; + sawchange[n] = false; + paranoid_printf ("curr_ix %d, n %d", curr_ix, n); + return curr_ix; +} + +bool +etc::dir_changed (int n) +{ + bool res = sawchange[n]; + + if (!res) + { + static HANDLE NO_COPY changed_h; + if (!changed_h) + { + path_conv pwd ("/etc"); + changed_h = FindFirstChangeNotification (pwd, FALSE, + FILE_NOTIFY_CHANGE_LAST_WRITE); + if (changed_h == INVALID_HANDLE_VALUE) + system_printf ("Can't open /etc for checking, %E", (char *) pwd, + changed_h); + } + + if (changed_h == INVALID_HANDLE_VALUE) + res = true; + else if (WaitForSingleObject (changed_h, 0) == WAIT_OBJECT_0) + { + (void) FindNextChangeNotification (changed_h); + memset (sawchange, true, sizeof sawchange); + res = true; + } + } + + paranoid_printf ("%s res %d", fn[n], res); + return res; +} + +bool +etc::file_changed (int n) +{ + bool res = false; + if (!fn[n]) + res = true; + else if (dir_changed (n)) + { + HANDLE h; + WIN32_FIND_DATA data; + + if ((h = FindFirstFile (fn[n], &data)) == INVALID_HANDLE_VALUE) + res = true; + else + { + FindClose (h); + if (CompareFileTime (&data.ftLastWriteTime, last_modified + n) > 0) + res = true; + } + } + sawchange[n] = false; + paranoid_printf ("%s res %d", fn[n], res); + return res; +} + +void +etc::set_last_modified (int n, FILETIME& ft) +{ + last_modified[n] = ft; + sawchange[n] = false; +}