#include <winioctl.h>
static int normalize_win32_path (const char *cwd, const char *src, char *dst);
-static char *getcwd_inner (char *buf, size_t ulen, int posix_p);
+static char *getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot);
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 unsigned long cwd_hash;
#endif
+#define ischrootpath(path) \
+ (myself->rootlen && \
+ strncasematch (myself->root, path, myself->rootlen) && \
+ (path[myself->rootlen] == '/' || path[myself->rootlen] == '\0'))
+
static int
path_prefix_p_ (const char *path1, const char *path2, int len1)
{
/* Two leading /'s? If so, preserve them. */
else if (isslash (src[1]))
{
+ if (myself->rootlen)
+ {
+ debug_printf ("ENOENT = normalize_posix_path (%s)", src);
+ return ENOENT;
+ }
*dst++ = '/';
*dst++ = '/';
src += 2;
src = src_start + 1;
}
}
+ /* Exactly one leading slash. Absolute path. Check for chroot. */
+ else if (myself->rootlen)
+ {
+ strcpy (dst, myself->root);
+ dst += myself->rootlen;
+ }
while (*src)
{
{
if (src[2] && !isslash (src[2]))
break;
- while (dst > dst_start && !isslash (*--dst))
- continue;
+ if (!ischrootpath (dst_start) ||
+ dst - dst_start != (int) myself->rootlen)
+ while (dst > dst_start && !isslash (*--dst))
+ continue;
src++;
}
}
The result is 0 for success, or an errno error value.
FIXME: A lot of this should be mergeable with the POSIX critter. */
-
static int
normalize_win32_path (const char *cwd, const char *src, char *dst)
{
const char *src_start = src;
char *dst_start = dst;
+ char *dst_root_start = dst;
if (!SLASH_P (src[0]) && strchr (src, ':') == NULL)
{
/* Two leading \'s? If so, preserve them. */
else if (SLASH_P (src[0]) && SLASH_P (src[1]))
{
+ if (myself->rootlen)
+ {
+ debug_printf ("ENOENT = normalize_win32_path (%s)", src);
+ return ENOENT;
+ }
*dst++ = '\\';
++src;
}
+ /* If absolute path, care for chroot. */
+ else if (SLASH_P (src[0]) && !SLASH_P (src[1]) && myself->rootlen)
+ {
+ strcpy (dst, myself->root);
+ char *c;
+ while ((c = strchr (dst, '/')) != NULL)
+ *c = '\\';
+ dst += myself->rootlen;
+ dst_root_start = dst;
+ *dst++ = '\\';
+ }
while (*src)
{
&& (SLASH_P (src[2]) || src[2] == 0))
{
/* Back up over /, but not if it's the first one. */
- if (dst > dst_start + 1)
+ if (dst > dst_root_start + 1)
dst--;
/* Now back up to the next /. */
- while (dst > dst_start + 1 && dst[-1] != '\\' && dst[-2] != ':')
+ while (dst > dst_root_start + 1 && dst[-1] != '\\' && dst[-2] != ':')
dst--;
src += 2;
if (SLASH_P (*src))
char pathbuf[MAX_PATH];
char cwd[MAX_PATH];
- getcwd_inner (cwd, MAX_PATH, TRUE); /* FIXME: check rc */
+ getcwd_inner (cwd, MAX_PATH, TRUE, 0); /* FIXME: check rc */
/* Determine where the destination should be placed. */
if (full_win32_path != NULL)
}
isrelpath = !isabspath (src_path);
*flags = set_flags_from_win32_path (dst);
+ if (myself->rootlen && dst[0] && dst[1] == ':')
+ {
+ char posix_path[MAX_PATH + 1];
+
+ rc = cygwin_shared->mount.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 fillin;
}
/* No need to fetch cwd if path is absolute. */
if (relative_path_p)
- getcwd_inner (cwd, MAX_PATH, 0); /* FIXME: check rc */
+ getcwd_inner (cwd, MAX_PATH, 0, 0); /* FIXME: check rc */
else
strcpy (cwd, "/"); /* some innocuous value */
/* getcwd */
char *
-getcwd_inner (char *buf, size_t ulen, int posix_p)
+getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
{
char *resbuf = NULL;
size_t len = ulen;
}
else if (cwd_posix != NULL)
{
+ debug_printf("myself->root: %s, cwd_posix: %s", myself->root, cwd_posix);
if (strlen (cwd_posix) >= len)
set_errno (ERANGE);
+ else if (with_chroot && ischrootpath(cwd_posix))
+ {
+ strcpy (buf, cwd_posix + myself->rootlen);
+ if (!buf[0])
+ strcpy (buf, "/");
+ resbuf = buf;
+ }
else
{
strcpy (buf, cwd_posix);
size_t tlen = strlen (temp);
+ if (with_chroot && ischrootpath (temp))
+ tlen -= myself->rootlen;
+
cwd_posix = (char *) realloc (
cwd_posix, tlen + 1);
if (cwd_posix != NULL)
- strcpy (cwd_posix, temp);
+ if (with_chroot && ischrootpath (temp))
+ {
+ strcpy (cwd_posix, temp + myself->rootlen);
+ if (!buf[0])
+ strcpy (buf, "/");
+ }
+ else
+ strcpy (cwd_posix, temp);
if (tlen >= ulen)
{
if (buf == NULL || ulen == 0)
{
buf = (char *) alloca (MAX_PATH);
- res = getcwd_inner (buf, MAX_PATH, 1);
+ res = getcwd_inner (buf, MAX_PATH, 1, 1);
res = strdup (buf);
}
else
{
- res = getcwd_inner (buf, ulen, 1);
+ res = getcwd_inner (buf, ulen, 1, 1);
}
return res;
char pathbuf[MAX_PATH];
(void) normalize_posix_path (cwd_posix, dir, pathbuf);
+ /* Look for trailing path component consisting entirely of dots. This
+ is needed only in case of chdir since Windows simply ignores count
+ of dots > 2 here instead of returning an error code. Counts of dots
+ <= 2 are already eliminated by normalize_posix_path. */
+ char *last_slash = strrchr (pathbuf, '/');
+ if (last_slash && strspn (last_slash + 1, ".") == strlen (last_slash + 1))
+ *last_slash = '\0';
free (cwd_posix);
cwd_posix = strdup (pathbuf);
}