* fhandler.h (FH_ENC): New enum.

(fhandler_base::get_encoded): New function.
(fhandler_base::set_encoded): Ditto.
* fhandler_disk_file.cc (fhandler_disk_file::opendir): Set encoded flag in
fhandler, as appropriate.
(fhandler_disk_file::readdir): Unmunge filename as appropriate based on new
encoding flag.
* path.cc (normalize_posix_path): Don't punt on files with colons.
(special_char): New function.
(mount_item::fnmunge): Ditto.
(fnunmunge): Ditto.
(special_name): Ditto.
(mount_item::build_win32): Avoid drive considerations when file is encoded.
(mount_info::conv_to_win32_path): Handle encoded filenames.
(mount_info::conv_to_posix_path): Ditto.
(fillout_mntent): Add posix string when directory is encoded.
* path.h (fnunmunge): Declare.
(path_conv::is_encoded): Declare.
This commit is contained in:
Christopher Faylor 2003-07-04 03:07:01 +00:00
parent 8f856553c0
commit 3f21478315
5 changed files with 151 additions and 34 deletions

View File

@ -1,3 +1,25 @@
2003-07-02 Christopher Faylor <cgf@redhat.com>
* fhandler.h (FH_ENC): New enum.
(fhandler_base::get_encoded): New function.
(fhandler_base::set_encoded): Ditto.
* fhandler_disk_file.cc (fhandler_disk_file::opendir): Set encoded flag
in fhandler, as appropriate.
(fhandler_disk_file::readdir): Unmunge filename as appropriate based on
new encoding flag.
* path.cc (normalize_posix_path): Don't punt on files with colons.
(special_char): New function.
(mount_item::fnmunge): Ditto.
(fnunmunge): Ditto.
(special_name): Ditto.
(mount_item::build_win32): Avoid drive considerations when file is
encoded.
(mount_info::conv_to_win32_path): Handle encoded filenames.
(mount_info::conv_to_posix_path): Ditto.
(fillout_mntent): Add posix string when directory is encoded.
* path.h (fnunmunge): Declare.
(path_conv::is_encoded): Declare.
2003-07-03 Christopher Faylor <cgf@redhat.com> 2003-07-03 Christopher Faylor <cgf@redhat.com>
* fhandler_tty.cc (fhandler_tty_slave::open): Conditionalize a little * fhandler_tty.cc (fhandler_tty_slave::open): Conditionalize a little

View File

@ -23,8 +23,7 @@ enum
FH_WBINSET = 0x00010000, /* binary write mode has been explicitly set */ FH_WBINSET = 0x00010000, /* binary write mode has been explicitly set */
FH_APPEND = 0x00020000, /* always append */ FH_APPEND = 0x00020000, /* always append */
FH_ASYNC = 0x00040000, /* async I/O */ FH_ASYNC = 0x00040000, /* async I/O */
FH_SIGCLOSE = 0x00080000, /* signal handler should close fd on interrupt */ FH_ENC = 0x00080000, /* native path is encoded */
FH_SYMLINK = 0x00100000, /* is a symlink */ FH_SYMLINK = 0x00100000, /* is a symlink */
FH_EXECABL = 0x00200000, /* file looked like it would run: FH_EXECABL = 0x00200000, /* file looked like it would run:
* ends in .exe or .bat or begins with #! */ * ends in .exe or .bat or begins with #! */
@ -242,6 +241,9 @@ class fhandler_base
bool get_need_fork_fixup () { return FHISSETF (FFIXUP); } bool get_need_fork_fixup () { return FHISSETF (FFIXUP); }
void set_need_fork_fixup () { FHSETF (FFIXUP); } void set_need_fork_fixup () { FHSETF (FFIXUP); }
bool get_encoded () { return FHISSETF (ENC);}
void set_encoded () { FHSETF (ENC);}
virtual void set_close_on_exec (int val); virtual void set_close_on_exec (int val);
virtual void fixup_before_fork_exec (DWORD) {} virtual void fixup_before_fork_exec (DWORD) {}

View File

@ -607,6 +607,8 @@ fhandler_disk_file::opendir (path_conv& real_name)
res = dir; res = dir;
} }
if (real_name.isencoded ())
set_encoded ();
} }
syscall_printf ("%p = opendir (%s)", res, get_name ()); syscall_printf ("%p = opendir (%s)", res, get_name ());
@ -633,9 +635,7 @@ fhandler_disk_file::readdir (DIR *dir)
} }
} }
else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE) else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
{ return res;
return res;
}
else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf)) else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf))
{ {
DWORD lasterr = GetLastError (); DWORD lasterr = GetLastError ();
@ -650,7 +650,10 @@ fhandler_disk_file::readdir (DIR *dir)
} }
/* We get here if `buf' contains valid data. */ /* We get here if `buf' contains valid data. */
strcpy (dir->__d_dirent->d_name, buf.cFileName); if (get_encoded ())
(void) fnunmunge (dir->__d_dirent->d_name, buf.cFileName);
else
strcpy (dir->__d_dirent->d_name, buf.cFileName);
/* Check for Windows shortcut. If it's a Cygwin or U/WIN /* Check for Windows shortcut. If it's a Cygwin or U/WIN
symlink, drop the .lnk suffix. */ symlink, drop the .lnk suffix. */

View File

@ -203,7 +203,7 @@ normalize_posix_path (const char *src, char *dst)
syscall_printf ("src %s", src); syscall_printf ("src %s", src);
if (isdrive (src) || strpbrk (src, "\\:")) if (isdrive (src))
{ {
int err = normalize_win32_path (src, dst); int err = normalize_win32_path (src, dst);
if (!err && isdrive (dst)) if (!err && isdrive (dst))
@ -499,7 +499,7 @@ path_conv::check (const char *src, unsigned opt,
/* Scan path_copy from right to left looking either for a symlink /* Scan path_copy from right to left looking either for a symlink
or an actual existing file. If an existing file is found, just or an actual existing file. If an existing file is found, just
return. If a symlink is found exit the for loop. return. If a symlink is found, exit the for loop.
Also: be careful to preserve the errno returned from Also: be careful to preserve the errno returned from
symlink.check as the caller may need it. */ symlink.check as the caller may need it. */
/* FIXME: Do we have to worry about multiple \'s here? */ /* FIXME: Do we have to worry about multiple \'s here? */
@ -1390,10 +1390,99 @@ set_flags (unsigned *flags, unsigned val)
} }
} }
char special_chars[] =
"\001" "\002" "\003" "\004" "\005" "\006" "\007" "\010"
"\011" "\012" "\013" "\014" "\015" "\016" "\017" "\020"
"\021" "\022" "\023" "\024" "\025" "\026" "\027" "\030"
"\031" "\032" "\033" "\034" "\035" "\036" "\037"
":" "\\" "*" "?" "%"
"A" "B" "C" "D" "E" "F" "G" "H"
"I" "J" "K" "L" "M" "N" "O" "P"
"Q" "R" "S" "T" "U" "V" "W" "X"
"Y" "Z";
static inline char
special_char (const char *s)
{
char *p = strechr (special_chars, *s);
if (*p == '%' && strlen (p) >= 3)
{
char hex[] = {s[1], s[2], '\0'};
unsigned char c = strtoul (hex, &p, 16);
p = strechr (special_chars, c);
}
return *p;
}
bool
fnunmunge (char *dst, const char *src)
{
bool converted = false;
char c;
while (*src)
if (*src != '%' || !(c = special_char (src)))
*dst++ = *src++;
else
{
converted = true;
*dst++ = c;
src += 3;
}
*dst = *src;
return converted;
}
/* Determines if name is "special". Assumes that name is empty or "absolute" */
static int
special_name (const char *s)
{
if (!*s)
return false;
if (strpbrk (++s, special_chars))
return !strncasematch (s, "%2f", 3);
if (strcasematch (s, "nul")
|| strcasematch (s, "aux")
|| strcasematch (s, "prn"))
return -1;
if (!strncasematch (s, "com", 3)
&& !strncasematch (s, "lpt", 3))
return false;
char *p;
(void) strtol (s, &p, 10);
return -(*p == '\0');
}
void void
mount_item::fnmunge (char *dst, const char *src) mount_item::fnmunge (char *dst, const char *src)
{ {
strcpy (dst, src); int name_type;
if (!(flags & MOUNT_ENC) || !(name_type = special_name (src)))
strcpy (dst, src);
else
{
char *d = dst;
*d++ = *src++;
if (name_type < 0)
{
__small_sprintf (d, "%%%02x", (unsigned char) *src++);
d += 3;
}
while (*src)
if (!special_char (src))
*d++ = *src++;
else
{
__small_sprintf (d, "%%%02x", (unsigned char) *src++);
d += 3;
}
*d = *src;
}
backslashify (dst, dst, 0); backslashify (dst, dst, 0);
} }
@ -1420,7 +1509,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne
const char *p = src + real_posix_pathlen; const char *p = src + real_posix_pathlen;
if (*p == '/') if (*p == '/')
/* nothing */; /* nothing */;
else if ((isdrive (dst) && !dst[2]) || *p) else if ((!(flags & MOUNT_ENC) && isdrive (dst) && !dst[2]) || *p)
dst[n++] = '\\'; dst[n++] = '\\';
fnmunge (dst + n, p); fnmunge (dst + n, p);
} }
@ -1475,22 +1564,6 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
if (dst == NULL) if (dst == NULL)
goto out; /* Sanity check. */ goto out; /* Sanity check. */
/* An MS-DOS spec has either a : or a \. If this is found, short
circuit most of the rest of this function. */
if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path))
{
debug_printf ("%s already win32", src_path);
rc = normalize_win32_path (src_path, dst);
if (rc)
{
debug_printf ("normalize_win32_path failed, rc %d", rc);
return rc;
}
set_flags (flags, (unsigned) set_flags_from_win32_path (dst));
goto out;
}
/* Normalize the path, taking out ../../ stuff, we need to do this /* Normalize the path, taking out ../../ stuff, we need to do this
so that we can move from one mounted directory to another with relative so that we can move from one mounted directory to another with relative
stuff. stuff.
@ -1587,17 +1660,22 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
break; break;
} }
if (i >= nmounts) if (i < nmounts)
{
backslashify (pathbuf, dst, 0); /* just convert */
set_flags (flags, PATH_BINARY);
chroot_ok = !cygheap->root.exists ();
}
else
{ {
mi->build_win32 (dst, pathbuf, flags, chroot_pathlen); mi->build_win32 (dst, pathbuf, flags, chroot_pathlen);
chroot_ok = true; chroot_ok = true;
} }
else
{
if (strpbrk (src_path, ":\\") != NULL || slash_unc_prefix_p (src_path))
rc = normalize_win32_path (src_path, dst);
else
{
backslashify (pathbuf, dst, 0); /* just convert */
set_flags (flags, PATH_BINARY);
}
chroot_ok = !cygheap->root.exists ();
}
if (!isvirtual_dev (devn)) if (!isvirtual_dev (devn))
win32_device_name (src_path, dst, devn, unit); win32_device_name (src_path, dst, devn, unit);
@ -1760,6 +1838,12 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
const char *p = cygheap->root.unchroot (posix_path); const char *p = cygheap->root.unchroot (posix_path);
memmove (posix_path, p, strlen (p) + 1); memmove (posix_path, p, strlen (p) + 1);
} }
if (mi.flags & MOUNT_ENC)
{
char tmpbuf[MAX_PATH + 1];
if (fnunmunge (tmpbuf, posix_path))
strcpy (posix_path, tmpbuf);
}
goto out; goto out;
} }
@ -2420,6 +2504,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
strcat (_reent_winsup ()->mnt_opts, (char *) ",exec"); strcat (_reent_winsup ()->mnt_opts, (char *) ",exec");
else if (flags & MOUNT_NOTEXEC) else if (flags & MOUNT_NOTEXEC)
strcat (_reent_winsup ()->mnt_opts, (char *) ",noexec"); strcat (_reent_winsup ()->mnt_opts, (char *) ",noexec");
if (flags & MOUNT_ENC)
strcat (_reent_winsup ()->mnt_opts, ",posix");
if ((flags & MOUNT_CYGDRIVE)) /* cygdrive */ if ((flags & MOUNT_CYGDRIVE)) /* cygdrive */
strcat (_reent_winsup ()->mnt_opts, (char *) ",noumount"); strcat (_reent_winsup ()->mnt_opts, (char *) ",noumount");
@ -3344,7 +3430,7 @@ chdir (const char *in_dir)
return -1; return -1;
} }
const char *native_dir = path.get_win32 (); const char *native_dir = path;
/* Check to see if path translates to something like C:. /* Check to see if path translates to something like C:.
If it does, append a \ to the native directory specification to If it does, append a \ to the native directory specification to

View File

@ -46,6 +46,7 @@ enum path_types
PATH_EXEC = MOUNT_EXEC, PATH_EXEC = MOUNT_EXEC,
PATH_NOTEXEC = MOUNT_NOTEXEC, PATH_NOTEXEC = MOUNT_NOTEXEC,
PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC, PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC,
PATH_ENC = MOUNT_ENC,
PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC), PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC),
PATH_LNK = 0x01000000, PATH_LNK = 0x01000000,
PATH_TEXT = 0x02000000, PATH_TEXT = 0x02000000,
@ -89,6 +90,7 @@ class path_conv
int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;} int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;}
int hasgood_inode () const {return path_flags & PATH_HASACLS;} // Not strictly correct int hasgood_inode () const {return path_flags & PATH_HASACLS;} // Not strictly correct
int has_buggy_open () const {return path_flags & PATH_HASBUGGYOPEN;} int has_buggy_open () const {return path_flags & PATH_HASBUGGYOPEN;}
bool isencoded () {return path_flags & PATH_ENC;}
int binmode () const int binmode () const
{ {
if (path_flags & PATH_BINARY) if (path_flags & PATH_BINARY)
@ -210,6 +212,8 @@ has_exec_chars (const char *buf, int len)
int pathmatch (const char *path1, const char *path2) __attribute__ ((regparm (2))); int pathmatch (const char *path1, const char *path2) __attribute__ ((regparm (2)));
int pathnmatch (const char *path1, const char *path2, int len) __attribute__ ((regparm (2))); int pathnmatch (const char *path1, const char *path2, int len) __attribute__ ((regparm (2)));
bool fnunmunge (char *, const char *) __attribute__ ((regparm (2)));
int path_prefix_p (const char *path1, const char *path2, int len1) __attribute__ ((regparm (3))); int path_prefix_p (const char *path1, const char *path2, int len1) __attribute__ ((regparm (3)));
/* FIXME: Move to own include file eventually */ /* FIXME: Move to own include file eventually */