* 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.
* 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.
This commit is contained in:
Christopher Faylor 2003-01-17 05:18:30 +00:00
parent d4d80d8c65
commit 14ea50290a
7 changed files with 258 additions and 190 deletions

View File

@ -1,3 +1,46 @@
2003-01-17 Pierre Humblet <pierre.humblet@ieee.org>
* 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 <cgf@redhat.com>
* 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 <jason@tishler.net>
* mmap.cc (fixup_mmaps_after_fork): Add ERROR_NOACCESS to the list of

View File

@ -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)
{

View File

@ -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))

View File

@ -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;
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)

View File

@ -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);

View File

@ -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,95 +27,36 @@ enum pwdgrp_state {
loaded
};
class pwdgrp_check {
pwdgrp_state state;
FILETIME last_modified;
char file_w32[MAX_PATH];
public:
pwdgrp_check () : state (uninitialized) {}
BOOL isinitializing ()
#define MAX_ETC_FILES 2
class etc
{
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);
}
}
}
return state == initializing;
}
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);
}
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_read {
class pwdgrp
{
pwdgrp_state state;
int pwd_ix;
path_conv pc;
HANDLE fh;
char *buf;
char *lptr, *eptr;
public:
bool open (const char *posix_fname)
{
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)
{
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;
lptr = NULL;
else if (!eptr)
return lptr = NULL;
lptr = NULL;
else
{
lptr = eptr;
eptr = strchr (lptr, '\n');
if (eptr)
@ -124,14 +65,69 @@ public:
*(eptr - 1) = 0;
*eptr++ = '\0';
}
}
return lptr;
}
inline HANDLE get_fhandle () { return fh; }
inline const char *get_fname () { return pc; }
void close ()
public:
pwdgrp () : state (uninitialized) {}
BOOL isinitializing ()
{
if (fh)
CloseHandle (fh);
if (state <= initializing)
state = initializing;
else if (etc::file_changed (pwd_ix - 1))
state = initializing;
return state == initializing;
}
void operator = (pwdgrp_state nstate) { state = nstate; }
BOOL isuninitialized () const { return state == uninitialized; }
bool load (const char *posix_fname, void (* add_line) (char *))
{
if (buf)
free (buf);
buf = lptr = eptr = NULL;
pc.check (posix_fname);
pwd_ix = etc::init (pwd_ix - 1, pc) + 1;
paranoid_printf ("%s", posix_fname);
bool res;
if (pc.error || !pc.exists () || !pc.isdisk () || pc.isdir ())
res = false;
else
{
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;
}
}
state = loaded;
return res;
}
};

View File

@ -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;
}