OSDN Git Service

* cygheap.cc (cygheap_root::cygheap_rot): Remove constructor.
authorcgf <cgf>
Sun, 3 Jun 2001 02:31:16 +0000 (02:31 +0000)
committercgf <cgf>
Sun, 3 Jun 2001 02:31:16 +0000 (02:31 +0000)
(cygheap_root::~cygheap_root): Remove destructor.
(cygheap_root::operator =): Remove.
(cygheap_root::set): New method.
* cygheap.h (cygheap_root): Reflect above changes.  Store root info in
mount-like structure.
(cygheap_root:posix_ok): New method.
(cygheap_root::ischroot_native): Ditto.
(cygheap_root::unchroot): Ditto.
(cygheap_root::exists): Ditto.
(cygheap_root::posix_length): Ditto.
(cygheap_root::posix_path): Ditto.
(cygheap_root::native_length): Ditto.
(cygheap_root::native_path): Ditto.
* dir.cc (opendir): Remove special chroot test.
* path.cc (path_prefix_p): Remove front end.
(normalize_posix_path): Reorganize chroot tests to accomodate new convention of
allowing paths using posix chroot prefix.
(path_conv::check): Pass a "already ran normalize" option to
conv_to_win32_path.  Return if there is an error from this function.
(mount_info::conv_to_win32_path): Add extra argument.  Don't call
normalize_posix_path if caller has already done so.  Substitute chroot setting,
if any, for root translation.  Add chroot checking to final output step.
* shared_info (mount_info): Accomodate additional argument to
conv_to_win32_path.
* syscalls.cc (chroot): Store both normalized posix path and native path in
chroot.

winsup/cygwin/ChangeLog
winsup/cygwin/cygheap.cc
winsup/cygwin/cygheap.h
winsup/cygwin/dir.cc
winsup/cygwin/path.cc
winsup/cygwin/shared_info.h
winsup/cygwin/syscalls.cc

index da4d721..5f29131 100644 (file)
@@ -1,3 +1,34 @@
+Sat Jun  2 14:07:28 2001  Christopher Faylor <cgf@cygnus.com>
+
+       * cygheap.cc (cygheap_root::cygheap_rot): Remove constructor.
+       (cygheap_root::~cygheap_root): Remove destructor.
+       (cygheap_root::operator =): Remove.
+       (cygheap_root::set): New method.
+       * cygheap.h (cygheap_root): Reflect above changes.  Store root info in
+       mount-like structure.
+       (cygheap_root:posix_ok): New method.
+       (cygheap_root::ischroot_native): Ditto.
+       (cygheap_root::unchroot): Ditto.
+       (cygheap_root::exists): Ditto.
+       (cygheap_root::posix_length): Ditto.
+       (cygheap_root::posix_path): Ditto.
+       (cygheap_root::native_length): Ditto.
+       (cygheap_root::native_path): Ditto.
+       * dir.cc (opendir): Remove special chroot test.
+       * path.cc (path_prefix_p): Remove front end.
+       (normalize_posix_path): Reorganize chroot tests to accomodate new
+       convention of allowing paths using posix chroot prefix.
+       (path_conv::check): Pass a "already ran normalize" option to
+       conv_to_win32_path.  Return if there is an error from this function.
+       (mount_info::conv_to_win32_path): Add extra argument.  Don't call
+       normalize_posix_path if caller has already done so.  Substitute chroot
+       setting, if any, for root translation.  Add chroot checking to final
+       output step.
+       * shared_info (mount_info): Accomodate additional argument to
+       conv_to_win32_path.
+       * syscalls.cc (chroot): Store both normalized posix path and native
+       path in chroot.
+
 Fri Jun  1 10:57:19 2001  Christopher Faylor <cgf@cygnus.com>
 
        * path.cc (chdir): Really make sure that isspace gets only an unsigned
index 7cad22b..e22a910 100644 (file)
@@ -290,40 +290,20 @@ cstrdup1 (const char *s)
   return p;
 }
 
-cygheap_root::cygheap_root (cygheap_root &nroot)
-{
-  rootlen = nroot.rootlen;
-  root = nroot.root ? cstrdup (nroot.root) : NULL;
-}
-
-cygheap_root::~cygheap_root ()
-{
-  if (root)
-    cfree (root);
-}
-
-char *
-cygheap_root::operator =(const char *new_root)
+void
+cygheap_root::set (const char *posix, const char *native)
 {
-  if (root)
-    {
-      cfree (root);
-      root = NULL;
-    }
-  rootlen = 0;
-  if (new_root && *new_root)
-    {
-      root = cstrdup (new_root);
-      rootlen = strlen (root);
-      if (rootlen >= 1 && root[rootlen - 1] == '/')
-       root[--rootlen] = '\0';
-      if (!rootlen)
-       {
-         cfree (root);
-         root = NULL;
-       }
-    }
-  return root;
+  if (!m)
+    m = (struct cygheap_root_mount_info *) ccalloc (HEAP_MOUNT, 1, sizeof (*m));
+  strcpy (m->posix_path, posix);
+  m->posix_pathlen = strlen (posix);
+  if (m->posix_pathlen >= 1 && m->posix_path[m->posix_pathlen - 1] == '/')
+    m->posix_path[--m->posix_pathlen] = '\0';
+
+  strcpy (m->native_path, native);
+  m->native_pathlen = strlen (native);
+  if (m->native_pathlen >= 1 && m->native_path[m->native_pathlen - 1] == '\\')
+    m->native_path[--m->native_pathlen] = '\0';
 }
 
 cygheap_user::~cygheap_user ()
index 6a8e562..cc953a7 100644 (file)
@@ -16,6 +16,7 @@ enum cygheap_types
   HEAP_STR,
   HEAP_ARGV,
   HEAP_BUF,
+  HEAP_MOUNT,
   HEAP_1_START,
   HEAP_1_STR,
   HEAP_1_ARGV,
@@ -37,18 +38,51 @@ struct _cmalloc_entry
   char data[0];
 };
 
+struct cygheap_root_mount_info
+{
+  char posix_path[MAX_PATH];
+  unsigned posix_pathlen;
+  char native_path[MAX_PATH];
+  unsigned native_pathlen;
+};
+
 class cygheap_root
 {
   /* Root directory information.
      This is used after a chroot is called. */
-  size_t rootlen;
-  char *root;
+  struct cygheap_root_mount_info *m;
+
 public:
-  cygheap_root (cygheap_root &nroot);
-  ~cygheap_root ();
-  char *operator =(const char *new_root);
-  size_t length () const { return rootlen; }
-  const char *path () const { return root; }
+  bool posix_ok (const char *path)
+  {
+    extern int path_prefix_p (const char *, const char *, int);
+    if (!m)
+      return 1;
+    return path_prefix_p (m->posix_path, path, m->posix_pathlen);
+  }
+  bool ischroot_native (const char *path)
+  {
+    if (!m)
+      return 1;
+    return strncasematch (m->native_path, path, m->native_pathlen)
+            && (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]);
+  }
+  const char *unchroot (const char *path)
+  {
+    if (!m)
+      return path;
+    const char *p = path + m->posix_pathlen;
+    if (!*p)
+      p = "/";
+    return p;
+  }
+  bool exists () {return !!m;}
+  void set (const char *posix, const char *native);
+  size_t posix_length () const { return m->posix_pathlen; }
+  const char *posix_path () const { return m->posix_path; }
+  size_t native_length () const { return m->native_pathlen; }
+  const char *native_path () const { return m->native_path; }
 };
 
 class cygheap_user
index 9e154b0..f55cbe3 100644 (file)
@@ -78,8 +78,7 @@ opendir (const char *dirname)
       goto failed;
     }
 
-  if (stat (cygheap->root.length () ? dirname : real_dirname.get_win32 (),
-           &statbuf) == -1)
+  if (stat (real_dirname, &statbuf) == -1)
     goto failed;
 
   if (!(statbuf.st_mode & S_IFDIR))
@@ -88,7 +87,7 @@ opendir (const char *dirname)
       goto failed;
     }
 
-  len = strlen (real_dirname.get_win32 ());
+  len = strlen (real_dirname);
   if (len > MAX_PATH - 3)
     {
       set_errno (ENAMETOOLONG);
index 21df976..2062991 100644 (file)
@@ -89,7 +89,7 @@ static DWORD available_drives;
 static int normalize_win32_path (const char *src, char *dst);
 static void slashify (const char *src, char *dst, int trailing_slash_p);
 static void backslashify (const char *src, char *dst, int trailing_slash_p);
-static int path_prefix_p_ (const char *path1, const char *path2, int len1);
+static int path_prefix_p (const char *path1, const char *path2, int len1);
 
 struct symlink_info
 {
@@ -108,10 +108,6 @@ struct symlink_info
 
 int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */
 
-#define path_prefix_p(p1, p2, l1) \
-       ((cyg_tolower(*(p1))==cyg_tolower(*(p2))) && \
-       path_prefix_p_(p1, p2, l1))
-
 /* Determine if path prefix matches current cygdrive */
 #define iscygdrive(path) \
   (path_prefix_p (mount_table->cygdrive, (path), mount_table->cygdrive_len))
@@ -121,12 +117,6 @@ int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */
    (isdirsep(path[mount_table->cygdrive_len + 1]) || \
     !path[mount_table->cygdrive_len + 1]))
 
-#define ischrootpath(p) \
-       (cygheap->root.length () && \
-        strncasematch (cygheap->root.path (), p, cygheap->root.length ()) && \
-        (p[cygheap->root.length ()] == '/' \
-         || p[cygheap->root.length ()] == '\0'))
-
 /* Return non-zero if PATH1 is a prefix of PATH2.
    Both are assumed to be of the same path style and / vs \ usage.
    Neither may be "".
@@ -141,8 +131,8 @@ int pcheck_case = PCHECK_RELAXED; /* Determines the case check behaviour. */
    /foo is not a prefix of /foobar
 */
 
-static int
-path_prefix_p_ (const char *path1, const char *path2, int len1)
+int
+path_prefix_p (const char *path1, const char *path2, int len1)
 {
   /* Handle case where PATH1 has trailing '/' and when it doesn't.  */
   if (len1 > 0 && SLASH_P (path1[len1 - 1]))
@@ -182,7 +172,7 @@ pathmatch (const char *path1, const char *path2)
 
 #define isslash(c) ((c) == '/')
 
-static int
+int
 normalize_posix_path (const char *src, char *dst)
 {
   const char *src_start = src;
@@ -211,11 +201,6 @@ normalize_posix_path (const char *src, char *dst)
   /* Two leading /'s?  If so, preserve them.  */
   else if (isslash (src[1]))
     {
-      if (cygheap->root.length ())
-       {
-         debug_printf ("ENOENT = normalize_posix_path (%s)", src);
-         return ENOENT;
-       }
       *dst++ = '/';
       *dst++ = '/';
       src += 2;
@@ -226,12 +211,6 @@ normalize_posix_path (const char *src, char *dst)
          src = src_start + 1;
        }
     }
-  /* Exactly one leading slash. Absolute path. Check for chroot. */
-  else if (cygheap->root.length ())
-    {
-      strcpy (dst, cygheap->root.path ());
-      dst += cygheap->root.length ();
-    }
   else
     *dst = '\0';
 
@@ -264,14 +243,6 @@ normalize_posix_path (const char *src, char *dst)
                }
              else if (src[2] && !isslash (src[2]))
                break;
-             else
-               {
-                 if (!ischrootpath (dst_start) ||
-                     dst - dst_start != (int) cygheap->root.length ())
-                   while (dst > dst_start && !isslash (*--dst))
-                     continue;
-                 src++;
-               }
            }
 
          *dst++ = '/';
@@ -442,7 +413,10 @@ path_conv::check (const char *src, unsigned opt,
 
          /* Convert to native path spec sans symbolic link info. */
          error = mount_table->conv_to_win32_path (path_copy, full_path, devn,
-                                                  unit, &sym.pflags);
+                                                  unit, &sym.pflags, 1);
+
+         if (error)
+           return;
 
          /* devn should not be a device.  If it is, then stop parsing now. */
          if (devn != FH_BAD)
@@ -891,25 +865,9 @@ normalize_win32_path (const char *src, char *dst)
 
   if (beg_src_slash && isdirsep (src[1]))
     {
-      if (cygheap->root.length ())
-       {
-         debug_printf ("ENOENT = normalize_win32_path (%s)", src);
-         return ENOENT;
-       }
       *dst++ = '\\';
       ++src;
     }
-  /* If absolute path, care for chroot. */
-  else if (beg_src_slash  && cygheap->root.length ())
-    {
-      strcpy (dst, cygheap->root.path ());
-      char *c;
-      while ((c = strchr (dst, '/')) != NULL)
-       *c = '\\';
-      dst += cygheap->root.length ();
-      dst_root_start = dst;
-      *dst++ = '\\';
-    }
   else if (strchr (src, ':') == NULL && *src != '/')
     {
       if (!cygheap->cwd.get (dst, 0))
@@ -1127,7 +1085,8 @@ mount_info::init ()
 
 int
 mount_info::conv_to_win32_path (const char *src_path, char *dst,
-                               DWORD &devn, int &unit, unsigned *flags)
+                               DWORD &devn, int &unit, unsigned *flags,
+                               bool no_normalize)
 {
   while (sys_mount_table_counter < cygwin_shared->sys_mount_table_counter)
     {
@@ -1137,6 +1096,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
   int src_path_len = strlen (src_path);
   MALLOC_CHECK;
   unsigned dummy_flags;
+  int chroot_ok = !cygheap->root.exists ();
 
   devn = FH_BAD;
   unit = 0;
@@ -1173,22 +1133,6 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
        }
 
       *flags = set_flags_from_win32_path (dst);
-      if (cygheap->root.length () && dst[0] && dst[1] == ':')
-       {
-         char posix_path[MAX_PATH + 1];
-
-         rc = mount_table->conv_to_posix_path (dst, posix_path, 0);
-         if (rc)
-           {
-             debug_printf ("conv_to_posix_path failed, rc %d", rc);
-             return rc;
-           }
-         if (!ischrootpath (posix_path))
-           {
-             debug_printf ("ischrootpath failed");
-             return ENOENT;
-           }
-       }
       goto out;
     }
 
@@ -1208,20 +1152,26 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
      converting it to a DOS-style path, looking up the appropriate drive
      in the mount table.  */
 
-  rc = normalize_posix_path (src_path, pathbuf);
-
-  if (rc)
+  if (no_normalize)
+    strcpy (pathbuf, src_path);
+  else
     {
-      debug_printf ("%d = conv_to_win32_path (%s)", rc, src_path);
-      *flags = 0;
-      return rc;
+      rc = normalize_posix_path (src_path, pathbuf);
+
+      if (rc)
+       {
+         debug_printf ("%d = conv_to_win32_path (%s)", rc, src_path);
+         *flags = 0;
+         return rc;
+       }
     }
 
   /* See if this is a cygwin "device" */
   if (win32_device_name (pathbuf, dst, devn, unit))
     {
       *flags = MOUNT_BINARY;   /* FIXME: Is this a sensible default for devices? */
-      goto out;
+      rc = 0;
+      goto out_no_chroot_check;
     }
 
   /* Check if the cygdrive prefix was specified.  If so, just strip
@@ -1235,11 +1185,33 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
       goto out;
     }
 
+  int chrooted_path_len;
+  chrooted_path_len = 0;
   /* Check the mount table for prefix matches. */
   for (i = 0; i < nmounts; i++)
     {
+      const char *path;
+      int len;
+
       mi = mount + posix_sorted[i];
-      if (path_prefix_p (mi->posix_path, pathbuf, mi->posix_pathlen))
+      if (!cygheap->root.exists ()
+         || (mi->posix_pathlen == 1 && mi->posix_path[0] == '/'))
+       {
+         path = mi->posix_path;
+         len = mi->posix_pathlen;
+       }
+      else if (cygheap->root.posix_ok (mi->posix_path))
+       {
+         path = cygheap->root.unchroot (mi->posix_path);
+         chrooted_path_len = len = strlen (path);
+       }
+      else
+       {
+         chrooted_path_len = 0;
+         continue;
+       }
+
+      if (path_prefix_p (path, pathbuf, len))
        break;
     }
 
@@ -1250,9 +1222,26 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
     }
   else
     {
-      int n = mi->native_pathlen;
-      memcpy (dst, mi->native_path, n + 1);
-      char *p = pathbuf + mi->posix_pathlen;
+      int n;
+      const char *native_path;
+      int posix_pathlen;
+      if (chroot_ok || chrooted_path_len || mi->posix_pathlen != 1
+         || mi->posix_path[0] != '/')
+       {
+         n = mi->native_pathlen;
+         native_path = mi->native_path;
+         posix_pathlen = chrooted_path_len ?: mi->posix_pathlen;
+         chroot_ok = 1;
+       }
+      else
+       {
+         n = cygheap->root.native_length ();
+         native_path = cygheap->root.native_path ();
+         posix_pathlen = mi->posix_pathlen;
+         chroot_ok = 1;
+       }
+      memcpy (dst, native_path, n + 1);
+      const char *p = pathbuf + posix_pathlen;
       if (*p == '/')
        /* nothing */;
       else if ((isdrive (dst) && !dst[2]) || *p)
@@ -1262,10 +1251,20 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
       *flags = mi->flags;
     }
 
-out:
+ out:
   MALLOC_CHECK;
-  debug_printf ("src_path %s, dst %s, flags %p", src_path, dst, *flags);
-  return 0;
+  if (chroot_ok || cygheap->root.ischroot_native (dst))
+    rc = 0;
+  else
+    {
+      debug_printf ("attempt to access outside of chroot '%s = %s'",
+                   cygheap->root.posix_path (), cygheap->root.native_path ());
+      rc = ENOENT;
+    }
+
+ out_no_chroot_check:
+  debug_printf ("src_path %s, dst %s, flags %p, rc %d", src_path, dst, *flags, rc);
+  return rc;
 }
 
 /* cygdrive_posix_path: Build POSIX path used as the
@@ -1370,6 +1369,9 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
       if (!path_prefix_p (mi.native_path, pathbuf, mi.native_pathlen))
        continue;
 
+      if (cygheap->root.exists () && !cygheap->root.posix_ok (mi.posix_path))
+       continue;
+
       /* SRC_PATH is in the mount table. */
       int nextchar;
       const char *p = pathbuf + mi.native_pathlen;
@@ -1391,9 +1393,31 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
        slashify (p,
                  posix_path + addslash + (mi.posix_pathlen == 1 ? 0 : mi.posix_pathlen),
                  trailing_slash_p);
+
+      if (cygheap->root.exists ())
+       {
+         const char *p = cygheap->root.unchroot (posix_path);
+         memmove (posix_path, p, strlen (p) + 1);
+       }
       goto out;
     }
 
+  if (!cygheap->root.exists ())
+    /* nothing */;
+  else if (cygheap->root.ischroot_native (pathbuf))
+    {
+      const char *p = pathbuf + cygheap->root.native_length ();
+      if (*p)
+       slashify (p, posix_path, trailing_slash_p);
+      else
+       {
+         posix_path[0] = '/';
+         posix_path[1] = '\0';
+       }
+    }
+  else
+    return ENOENT;
+
   /* Not in the database.  This should [theoretically] only happen if either
      the path begins with //, or / isn't mounted, or the path has a drive
      letter not covered by the mount table.  If it's a relative path then the
@@ -3336,11 +3360,9 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
   if (!need_posix)
     tocopy = win32;
   else
-    tocopy = with_chroot && ischrootpath(posix) ?
-            posix + cygheap->root.length () : posix;
+    tocopy = posix;
 
-  debug_printf("cygheap->root: %s, posix: %s",
-              (const char *) cygheap->root.path (), posix);
+  debug_printf("posix %s", posix);
   if (strlen (tocopy) >= ulen)
     {
       set_errno (ERANGE);
index cf61cba..40ddb96 100644 (file)
@@ -77,7 +77,7 @@ class mount_info
 
   unsigned set_flags_from_win32_path (const char *path);
   int conv_to_win32_path (const char *src_path, char *dst, DWORD &devn,
-                         int &unit, unsigned *flags = NULL);
+                         int &unit, unsigned *flags = NULL, bool no_normalize = 0);
   int conv_to_posix_path (const char *src_path, char *posix_path,
                          int keep_rel_p);
   struct mntent *getmntent (int x);
index 0a59e73..f4fcb46 100644 (file)
@@ -38,6 +38,8 @@ details. */
 #include "security.h"
 #include "cygheap.h"
 
+extern int normalize_posix_path (const char *, char *);
+
 SYSTEM_INFO system_info;
 
 /* Close all files and process any queued deletions.
@@ -2195,19 +2197,14 @@ chroot (const char *newroot)
       set_errno (ENOENT);
       goto done;
     }
-  if (! (path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
+  if (!(path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
     {
       set_errno (ENOTDIR);
       goto done;
     }
-  char buf[MAX_PATH + 1];
-  ret = mount_table->conv_to_posix_path (path.get_win32 (), buf, 0);
-  if (ret)
-    {
-      set_errno (ret);
-      goto done;
-    }
-  cygheap->root = buf;
+  char buf[MAX_PATH];
+  normalize_posix_path (newroot, buf);
+  cygheap->root.set (buf, path);
   ret = 0;
 
 done: