* shared.cc (user_shared_initialize): Fetch potentially changed Cygwin

username from /etc/passwd before loading mount table.
	(shared_info::init_installation_root): New function fetching Cygwin's
	installation root dir and storing as native NT path in global shared
	memory.
	(shared_info::initialize): Call init_installation_root exactly once at
	first startup.
	* shared_info.h (SHARED_INFO_CB): Accommodate change to shared_info.
	(CURR_SHARED_MAGIC): Ditto.
	(class shared_info): Add installation_root member.
	(shared_info::init_installation_root): Declare.

	* grp.cc (pwdgrp::read_group): Call pwdgrp::load with native WCHAR path.
	* passwd.cc (pwdgrp::read_passwd): Ditto.  Avoid recursion.
	(etc::init): Take POBJECT_ATTRIBUTES instead of path_conv.
	* path.h (etc::init): Change prototype accordingly.
	* pwdgrp.h (class pwdgrp): Store path as UNICODE_STRING/PWCHAR instead
	of as path_conv.
	(pwdgrp::load): Accommodate prototype.
	* uinfo.cc (pwdgrp::load): Change argument type from char to wchar_t.
	Create native NT path here instead of calling path_conv.

	* mount.cc (find_root_from_cygwin_dll): Drop in favor of global
	initializaion in shared_info.
	(mount_info::init): Fetch native NT root dir from cygwin_shared.
	(mount_info::from_fstab): Expect native NT path and use native NT
	functions to access file.  Convert username part in user fstab path
	according to special char transformation rules.
	* path.cc (tfx_chars): Convert slash to backslash.
	(transform_chars): Implement for path given as PWCHAR.
	(transform_chars): PUNICODE_STRING version calls PWCHAR version.
	Remove useless commented code.
This commit is contained in:
Corinna Vinschen 2008-07-24 18:25:52 +00:00
parent 410c1d122d
commit 520fcc9747
10 changed files with 170 additions and 90 deletions

View File

@ -1,3 +1,38 @@
2008-07-24 Corinna Vinschen <corinna@vinschen.de>
* shared.cc (user_shared_initialize): Fetch potentially changed Cygwin
username from /etc/passwd before loading mount table.
(shared_info::init_installation_root): New function fetching Cygwin's
installation root dir and storing as native NT path in global shared
memory.
(shared_info::initialize): Call init_installation_root exactly once at
first startup.
* shared_info.h (SHARED_INFO_CB): Accommodate change to shared_info.
(CURR_SHARED_MAGIC): Ditto.
(class shared_info): Add installation_root member.
(shared_info::init_installation_root): Declare.
* grp.cc (pwdgrp::read_group): Call pwdgrp::load with native WCHAR path.
* passwd.cc (pwdgrp::read_passwd): Ditto. Avoid recursion.
(etc::init): Take POBJECT_ATTRIBUTES instead of path_conv.
* path.h (etc::init): Change prototype accordingly.
* pwdgrp.h (class pwdgrp): Store path as UNICODE_STRING/PWCHAR instead
of as path_conv.
(pwdgrp::load): Accommodate prototype.
* uinfo.cc (pwdgrp::load): Change argument type from char to wchar_t.
Create native NT path here instead of calling path_conv.
* mount.cc (find_root_from_cygwin_dll): Drop in favor of global
initializaion in shared_info.
(mount_info::init): Fetch native NT root dir from cygwin_shared.
(mount_info::from_fstab): Expect native NT path and use native NT
functions to access file. Convert username part in user fstab path
according to special char transformation rules.
* path.cc (tfx_chars): Convert slash to backslash.
(transform_chars): Implement for path given as PWCHAR.
(transform_chars): PUNICODE_STRING version calls PWCHAR version.
Remove useless commented code.
2008-07-22 Corinna Vinschen <corinna@vinschen.de>
* spawn.cc (spawn_guts): Fix previous patch for UNC paths.

View File

@ -72,7 +72,7 @@ pwdgrp::read_group ()
if ((*group_buf)[i].gr_mem != &null_ptr)
free ((*group_buf)[i].gr_mem);
load ("/etc/group");
load (L"\\etc\\group");
/* Complete /etc/group in memory if needed */
if (!internal_getgrgid (myself->gid))

View File

@ -72,32 +72,6 @@ win32_device_name (const char *src_path, char *win32_path, device& dev)
return true;
}
/* Use absolute path of cygwin1.dll to derive a "root".
Return false if GetModuleFileNameW fails or path is "funny".
Otherwise return true. */
static inline PWCHAR
find_root_from_cygwin_dll (WCHAR *path)
{
if (!GetModuleFileNameW (cygwin_hmodule, path, NT_MAX_PATH))
{
debug_printf ("GetModuleFileNameW(%p, %p, %u), %E", cygwin_hmodule, path, NT_MAX_PATH);
return NULL;
}
PWCHAR w = wcsrchr (path, L'\\');
if (w)
{
*w = L'\0';
w = wcsrchr (path, L'\\');
}
if (!w)
{
debug_printf ("Invalid DLL path");
return NULL;
}
*w = L'\0';
return w;
}
inline void
mount_info::create_root_entry (const PWCHAR root)
{
@ -121,14 +95,13 @@ mount_info::init ()
nmounts = 0;
PWCHAR pathend;
WCHAR path[NT_MAX_PATH];
if ((pathend = find_root_from_cygwin_dll (path)))
{
create_root_entry (path);
pathend = wcpcpy (pathend, L"\\etc\\fstab");
if (from_fstab (false, path, pathend) /* The single | is correct! */
| from_fstab (true, path, pathend))
return;
}
pathend = wcpcpy (path, cygwin_shared->installation_root);
create_root_entry (path);
pathend = wcpcpy (pathend, L"\\etc\\fstab");
if (from_fstab (false, path, pathend) /* The single | is correct! */
| from_fstab (true, path, pathend))
return;
/* FIXME: Remove warning message before releasing 1.7.0. */
small_printf ("Huh? No /etc/fstab file? Using default root and cygdrive prefix...\n");
@ -737,27 +710,45 @@ mount_info::from_fstab_line (char *line, bool user)
bool
mount_info::from_fstab (bool user, WCHAR fstab[], PWCHAR fstab_end)
{
UNICODE_STRING upath;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
HANDLE fh;
if (user)
sys_mbstowcs (wcpcpy (fstab_end, L".d\\"),
NT_MAX_PATH - (fstab_end - fstab),
cygheap->user.name ());
debug_printf ("Try to read mounts from %W", fstab);
HANDLE h = CreateFileW (fstab, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
debug_printf ("CreateFileW, %E");
extern void transform_chars (PWCHAR, PWCHAR);
PWCHAR username;
sys_mbstowcs (username = wcpcpy (fstab_end, L".d\\"),
NT_MAX_PATH - (fstab_end - fstab),
cygheap->user.name ());
/* Make sure special chars in the username are converted according to
the rules. */
transform_chars (username, username + wcslen (username) - 1);
}
RtlInitUnicodeString (&upath, fstab);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
debug_printf ("Try to read mounts from %W", fstab);
status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io,
FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS (status))
{
system_printf ("NtOpenFile(%S) failed, %p", &upath, status);
return false;
}
char buf[NT_MAX_PATH];
char *got = buf;
DWORD len = 0;
unsigned line = 1;
/* Using buffer size - 2 leaves space to append two \0. */
while (ReadFile (h, got, (sizeof (buf) - 2) - (got - buf), &len, NULL))
while (NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, got,
(sizeof (buf) - 2) - (got - buf), NULL, NULL)))
{
char *end;
len = io.Information;
/* Set end marker. */
got[len] = got[len + 1] = '\0';
/* Set len to the absolute len of bytes in buf. */
@ -783,8 +774,10 @@ retry:
if (!got_nl)
{
system_printf ("%W: Line %d too long, skipping...", fstab, line);
while (ReadFile (h, buf, (sizeof (buf) - 2), &len, NULL))
while (NT_SUCCESS (NtReadFile (fh, NULL, NULL, NULL, &io, buf,
(sizeof (buf) - 2), NULL, NULL)))
{
len = io.Information;
buf[len] = buf[len + 1] = '\0';
got = strchr (buf, '\n');
if (got)
@ -809,7 +802,7 @@ retry:
if (got > buf)
from_fstab_line (got, user);
done:
CloseHandle (h);
NtClose (fh);
return true;
}

View File

@ -51,7 +51,7 @@ pwdgrp::parse_passwd ()
void
pwdgrp::read_passwd ()
{
load ("/etc/passwd");
load (L"\\etc\\passwd");
char strbuf[128] = "";
bool searchentry = true;
@ -72,7 +72,6 @@ pwdgrp::read_passwd ()
{
static char linebuf[1024]; // must be static and
// should not be NO_COPY
cygheap->user.ontherange (CH_HOME, NULL);
snprintf (linebuf, sizeof (linebuf), "%s:*:%lu:%lu:,%s:%s:/bin/sh",
cygheap->user.name (),
myself->uid == ILLEGAL_UID ? UNKNOWN_UID : myself->uid,

View File

@ -574,7 +574,7 @@ WCHAR tfx_chars[] NO_COPY = {
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
32, '!', 0xf000 | '"', '#', '$', '%', '&', 39,
'(', ')', 0xf000 | '*', '+', ',', '-', '.', '/',
'(', ')', 0xf000 | '*', '+', ',', '-', '.', '\\',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 0xf000 | ':', ';', 0xf000 | '<', '=', 0xf000 | '>', 0xf000 | '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
@ -587,22 +587,20 @@ WCHAR tfx_chars[] NO_COPY = {
'x', 'y', 'z', '{', 0xf000 | '|', '}', '~', 127
};
static void
void
transform_chars (PWCHAR path, PWCHAR path_end)
{
for (; path <= path_end; ++path)
if (*path < 128)
*path = tfx_chars[*path];
}
static inline
void
transform_chars (PUNICODE_STRING upath, USHORT start_idx)
{
register PWCHAR buf = upath->Buffer;
register PWCHAR end = buf + upath->Length / sizeof (WCHAR) - 1;
for (buf += start_idx; buf <= end; ++buf)
if (*buf < 128)
*buf = tfx_chars[*buf];
#if 0
/* Win32 can't handle trailing dots and spaces. Transform the last of them
to the private use area, too, to create a valid Win32 filename. */
if (*end == L'\\')
--end;
if (*end == L'.' || *end == L' ')
*end |= 0xf000;
#endif
transform_chars (upath->Buffer + start_idx,
upath->Buffer + upath->Length / sizeof (WCHAR) - 1);
}
PUNICODE_STRING
@ -3391,7 +3389,7 @@ OBJECT_ATTRIBUTES etc::fn[MAX_ETC_FILES + 1];
LARGE_INTEGER etc::last_modified[MAX_ETC_FILES + 1];
int
etc::init (int n, path_conv &pc)
etc::init (int n, POBJECT_ATTRIBUTES attr)
{
if (n > 0)
/* ok */;
@ -3400,7 +3398,7 @@ etc::init (int n, path_conv &pc)
else
api_fatal ("internal error");
pc.get_object_attr (fn[n], sec_none_nih);
fn[n] = *attr;
change_possible[n] = false;
test_file_change (n);
paranoid_printf ("fn[%d] %S, curr_ix %d", n, fn[n].ObjectName, curr_ix);

View File

@ -350,7 +350,7 @@ class etc
static OBJECT_ATTRIBUTES fn[MAX_ETC_FILES + 1];
static LARGE_INTEGER last_modified[MAX_ETC_FILES + 1];
static bool dir_changed (int);
static int init (int, path_conv &pc);
static int init (int, POBJECT_ATTRIBUTES);
static bool file_changed (int);
static bool test_file_change (int);
friend class pwdgrp;

View File

@ -35,7 +35,8 @@ class pwdgrp
void (pwdgrp::*read) ();
bool (pwdgrp::*parse) ();
int etc_ix;
path_conv pc;
UNICODE_STRING upath;
PWCHAR path;
char *buf, *lptr;
int max_lines;
bool initialized;
@ -67,7 +68,7 @@ class pwdgrp
public:
int curr_lines;
void load (const char *);
void load (const wchar_t *);
inline void refresh (bool check)
{
if (!check && initialized)

View File

@ -22,8 +22,10 @@ details. */
#include "shared_info_magic.h"
#include "registry.h"
#include "cygwin_version.h"
#include "pwdgrp.h"
#include "ntdll.h"
#include <alloca.h>
#include <wchar.h>
shared_info NO_COPY *cygwin_shared;
user_info NO_COPY *user_shared;
@ -225,7 +227,12 @@ user_shared_initialize (bool reinit)
/* Initialize the Cygwin per-user shared, if necessary */
if (!sversion)
{
debug_printf ("initializing user shared");
cygpsid sid (cygheap->user.sid ());
struct passwd *pw = internal_getpwsid (sid);
/* Correct the user name with what's defined in /etc/passwd before
loading the user fstab file. */
if (pw)
cygheap->user.set_name (pw->pw_name);
user_shared->mountinfo.init (); /* Initialize the mount table. */
user_shared->cb = sizeof (*user_shared);
}
@ -240,6 +247,46 @@ user_shared_initialize (bool reinit)
}
}
/* Use absolute path of cygwin1.dll to derive the Win32 dir which
is our installation root. Note that we can't handle Cygwin installation
root dirs of more than 4K path length. I assume that's ok... */
void
shared_info::init_installation_root ()
{
if (!GetModuleFileNameW (cygwin_hmodule, installation_root, PATH_MAX))
api_fatal ("Can't initialize Cygwin installation root dir.\n"
"GetModuleFileNameW(%p, %p, %u), %E",
cygwin_hmodule, installation_root, PATH_MAX);
PWCHAR p = installation_root;
if (wcsncmp (p, L"\\\\?\\", 4)) /* No long path prefix. */
{
if (!wcsncasecmp (p, L"\\\\", 2)) /* UNC */
{
p = wcpcpy (p, L"\\??\\UN");
GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6);
*p = L'C';
}
else
{
p = wcpcpy (p, L"\\??\\");
GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4);
}
}
installation_root[1] = L'?';
PWCHAR w = wcsrchr (installation_root, L'\\');
if (w)
{
*w = L'\0';
w = wcsrchr (installation_root, L'\\');
}
if (!w)
api_fatal ("Can't initialize Cygwin installation root dir.\n"
"Invalid DLL path");
*w = L'\0';
}
/* Initialize obcaseinsensitive. Default to case insensitive on pre-XP. */
void
shared_info::init_obcaseinsensitive ()
@ -279,10 +326,10 @@ shared_info::initialize ()
if (!sversion)
{
init_installation_root ();/* Initialize installation root dir. */
init_obcaseinsensitive ();/* Initialize obcaseinsensitive. */
tty.init (); /* Initialize tty table. */
mt.initialize (); /* Initialize shared tape information. */
init_obcaseinsensitive ();/* Initialize obcaseinsensitive. */
cb = sizeof (*this); /* Do last, after all shared memory initialization */
}

View File

@ -11,6 +11,7 @@ details. */
#include "tty.h"
#include "security.h"
#include "mtinfo.h"
#include "limits.h"
/* Mount table entry */
@ -117,9 +118,9 @@ public:
cygwin_version.api_minor)
#define SHARED_VERSION_MAGIC CYGWIN_VERSION_MAGIC (SHARED_MAGIC, SHARED_VERSION)
#define SHARED_INFO_CB 31136
#define SHARED_INFO_CB 39328
#define CURR_SHARED_MAGIC 0x18da899eU
#define CURR_SHARED_MAGIC 0x22f9ff0bU
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@ -135,10 +136,12 @@ class shared_info
DWORD sys_mount_table_counter;
tty_list tty;
LONG last_used_bindresvport;
WCHAR installation_root[PATH_MAX];
DWORD obcaseinsensitive;
mtinfo mt;
void initialize ();
void init_installation_root ();
void init_obcaseinsensitive ();
unsigned heap_chunk_size ();
unsigned heap_slop_size ();

View File

@ -13,6 +13,7 @@ details. */
#include <unistd.h>
#include <wininet.h>
#include <stdlib.h>
#include <wchar.h>
#include <lm.h>
#include <iptypes.h>
#include <sys/cygwin.h>
@ -22,6 +23,7 @@ details. */
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
#include "shared_info.h"
#include "registry.h"
#include "child_info.h"
#include "environ.h"
@ -508,7 +510,7 @@ pwdgrp::add_line (char *eptr)
}
void
pwdgrp::load (const char *posix_fname)
pwdgrp::load (const wchar_t *rel_path)
{
static const char failed[] = "failed";
static const char succeeded[] = "succeeded";
@ -526,23 +528,26 @@ pwdgrp::load (const char *posix_fname)
buf = NULL;
curr_lines = 0;
pc.check (posix_fname);
etc_ix = etc::init (etc_ix, pc);
paranoid_printf ("%s", posix_fname);
if (pc.error || !pc.exists () || pc.isdir ())
if (!path &&
!(path = (PWCHAR) malloc ((wcslen (cygwin_shared->installation_root)
+ wcslen (rel_path) + 1) * sizeof (WCHAR))))
{
paranoid_printf ("strange path_conv problem");
paranoid_printf ("malloc (%W) failed", rel_path);
goto out;
}
status = NtOpenFile (&fh, FILE_READ_DATA,
pc.get_object_attr (attr, sec_none_nih), &io,
wcpcpy (wcpcpy (path, cygwin_shared->installation_root), rel_path);
RtlInitUnicodeString (&upath, path);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
etc_ix = etc::init (etc_ix, &attr);
paranoid_printf ("%S", &upath);
status = NtOpenFile (&fh, FILE_READ_DATA, &attr, &io,
FILE_SHARE_VALID_FLAGS, 0);
if (!NT_SUCCESS (status))
{
paranoid_printf ("NtOpenFile(%S) failed, status %p",
pc.get_nt_native_path (), status);
paranoid_printf ("NtOpenFile(%S) failed, status %p", &upath, status);
goto out;
}
status = NtQueryInformationFile (fh, &io, &fsi, sizeof fsi,
@ -550,7 +555,7 @@ pwdgrp::load (const char *posix_fname)
if (!NT_SUCCESS (status))
{
paranoid_printf ("NtQueryInformationFile(%S) failed, status %p",
pc.get_nt_native_path (), status);
&upath, status);
goto out;
}
/* FIXME: Should we test for HighPart set? If so, the
@ -567,8 +572,7 @@ pwdgrp::load (const char *posix_fname)
fsi.EndOfFile.LowPart, &off, NULL);
if (!NT_SUCCESS (status))
{
paranoid_printf ("NtReadFile(%S) failed, status %p",
pc.get_nt_native_path (), status);
paranoid_printf ("NtReadFile(%S) failed, status %p", &upath, status);
free (buf);
goto out;
}
@ -576,12 +580,12 @@ pwdgrp::load (const char *posix_fname)
char *eptr = buf;
while ((eptr = add_line (eptr)))
continue;
debug_printf ("%s curr_lines %d", posix_fname, curr_lines);
debug_printf ("%W curr_lines %d", rel_path, curr_lines);
res = succeeded;
out:
if (fh)
NtClose (fh);
debug_printf ("%s load %s", posix_fname, res);
debug_printf ("%W load %s", rel_path, res);
initialized = true;
}