* 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:
parent
d4d80d8c65
commit
14ea50290a
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue