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-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.
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))
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)
{
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");
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 ());
+ {
+ 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);
- HANDLE h = CreateFileW (fstab, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (h == INVALID_HANDLE_VALUE)
+ status = NtOpenFile (&fh, SYNCHRONIZE | FILE_READ_DATA, &attr, &io,
+ FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
+ if (!NT_SUCCESS (status))
{
- debug_printf ("CreateFileW, %E");
+ 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. */
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)
if (got > buf)
from_fstab_line (got, user);
done:
- CloseHandle (h);
+ NtClose (fh);
return true;
}
void
pwdgrp::read_passwd ()
{
- load ("/etc/passwd");
+ load (L"\\etc\\passwd");
char strbuf[128] = "";
bool searchentry = true;
{
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,
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',
'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
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 */;
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);
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;
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;
public:
int curr_lines;
- void load (const char *);
+ void load (const wchar_t *);
inline void refresh (bool check)
{
if (!check && initialized)
#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;
/* 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);
}
}
}
+/* 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 ()
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 */
}
#include "tty.h"
#include "security.h"
#include "mtinfo.h"
+#include "limits.h"
/* Mount table entry */
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
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 ();
#include <unistd.h>
#include <wininet.h>
#include <stdlib.h>
+#include <wchar.h>
#include <lm.h>
#include <iptypes.h>
#include <sys/cygwin.h>
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
+#include "shared_info.h"
#include "registry.h"
#include "child_info.h"
#include "environ.h"
}
void
-pwdgrp::load (const char *posix_fname)
+pwdgrp::load (const wchar_t *rel_path)
{
static const char failed[] = "failed";
static const char succeeded[] = "succeeded";
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,
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
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;
}
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;
}