OSDN Git Service

* shared.cc (user_shared_initialize): Fetch potentially changed Cygwin
authorcorinna <corinna>
Thu, 24 Jul 2008 18:25:47 +0000 (18:25 +0000)
committercorinna <corinna>
Thu, 24 Jul 2008 18:25:47 +0000 (18:25 +0000)
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.

winsup/cygwin/ChangeLog
winsup/cygwin/grp.cc
winsup/cygwin/mount.cc
winsup/cygwin/passwd.cc
winsup/cygwin/path.cc
winsup/cygwin/path.h
winsup/cygwin/pwdgrp.h
winsup/cygwin/shared.cc
winsup/cygwin/shared_info.h
winsup/cygwin/uinfo.cc

index 8d84953..4c844be 100644 (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.
index f38888e..a007ae6 100644 (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))
index 7febd90..4ef1f0f 100644 (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 ());
+    {
+      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. */
@@ -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;
 }
 
index 14d0cee..1773de5 100644 (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,
index d550203..ae10549 100644 (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);
index 32c46a5..a9f0cc3 100644 (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;
index 94631c5..7db722c 100644 (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)
index 8f25379..fca79e4 100644 (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 */
     }
 
index 3b00362..684a84a 100644 (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 ();
index cc8beeb..9d7a5ce 100644 (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;
 }