Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2001-06-03 06:31:16 +0400
committerChristopher Faylor <me@cgf.cx>2001-06-03 06:31:16 +0400
commit7ceb1cac3a8f2a6822825347d1536f4507680704 (patch)
tree0cb17e09dc70b202a0c5a27fa140a4a897893e55 /winsup/cygwin
parentbb8251474cd5eaf5950a51e6b13dc6d5098ed0aa (diff)
* 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.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog31
-rw-r--r--winsup/cygwin/cygheap.cc46
-rw-r--r--winsup/cygwin/cygheap.h48
-rw-r--r--winsup/cygwin/dir.cc5
-rw-r--r--winsup/cygwin/path.cc192
-rw-r--r--winsup/cygwin/shared_info.h2
-rw-r--r--winsup/cygwin/syscalls.cc15
7 files changed, 201 insertions, 138 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index da4d7216e..5f291312b 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index 7cad22b5e..e22a91060 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -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 ()
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 6a8e56290..cc953a764 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -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
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index 9e154b010..f55cbe31e 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -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);
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 21df976cd..20629913a 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -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);
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index cf61cbab8..40ddb9662 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -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);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 0a59e730b..f4fcb464c 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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: