* 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>
* 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_APPEND = 0x00020000, /* always append */
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_EXECABL = 0x00200000, /* file looked like it would run:
* ends in .exe or .bat or begins with #! */
@ -242,6 +241,9 @@ class fhandler_base
bool get_need_fork_fixup () { return FHISSETF (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 fixup_before_fork_exec (DWORD) {}

View File

@ -607,6 +607,8 @@ fhandler_disk_file::opendir (path_conv& real_name)
res = dir;
}
if (real_name.isencoded ())
set_encoded ();
}
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)
{
return res;
}
else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf))
{
DWORD lasterr = GetLastError ();
@ -650,6 +650,9 @@ fhandler_disk_file::readdir (DIR *dir)
}
/* We get here if `buf' contains valid data. */
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

View File

@ -203,7 +203,7 @@ normalize_posix_path (const char *src, char *dst)
syscall_printf ("src %s", src);
if (isdrive (src) || strpbrk (src, "\\:"))
if (isdrive (src))
{
int err = normalize_win32_path (src, 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
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
symlink.check as the caller may need it. */
/* 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
mount_item::fnmunge (char *dst, const char *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);
}
@ -1420,7 +1509,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne
const char *p = src + real_posix_pathlen;
if (*p == '/')
/* nothing */;
else if ((isdrive (dst) && !dst[2]) || *p)
else if ((!(flags & MOUNT_ENC) && isdrive (dst) && !dst[2]) || *p)
dst[n++] = '\\';
fnmunge (dst + n, p);
}
@ -1475,22 +1564,6 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
if (dst == NULL)
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
so that we can move from one mounted directory to another with relative
stuff.
@ -1587,17 +1660,22 @@ mount_info::conv_to_win32_path (const char *src_path, char *dst,
break;
}
if (i >= nmounts)
{
backslashify (pathbuf, dst, 0); /* just convert */
set_flags (flags, PATH_BINARY);
chroot_ok = !cygheap->root.exists ();
}
else
if (i < nmounts)
{
mi->build_win32 (dst, pathbuf, flags, chroot_pathlen);
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))
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);
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;
}
@ -2420,6 +2504,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
strcat (_reent_winsup ()->mnt_opts, (char *) ",exec");
else if (flags & MOUNT_NOTEXEC)
strcat (_reent_winsup ()->mnt_opts, (char *) ",noexec");
if (flags & MOUNT_ENC)
strcat (_reent_winsup ()->mnt_opts, ",posix");
if ((flags & MOUNT_CYGDRIVE)) /* cygdrive */
strcat (_reent_winsup ()->mnt_opts, (char *) ",noumount");
@ -3344,7 +3430,7 @@ chdir (const char *in_dir)
return -1;
}
const char *native_dir = path.get_win32 ();
const char *native_dir = path;
/* Check to see if path translates to something like C:.
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_NOTEXEC = MOUNT_NOTEXEC,
PATH_CYGWIN_EXEC = MOUNT_CYGWIN_EXEC,
PATH_ENC = MOUNT_ENC,
PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC),
PATH_LNK = 0x01000000,
PATH_TEXT = 0x02000000,
@ -89,6 +90,7 @@ class path_conv
int has_symlinks () const {return path_flags & PATH_HAS_SYMLINKS;}
int hasgood_inode () const {return path_flags & PATH_HASACLS;} // Not strictly correct
int has_buggy_open () const {return path_flags & PATH_HASBUGGYOPEN;}
bool isencoded () {return path_flags & PATH_ENC;}
int binmode () const
{
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 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)));
/* FIXME: Move to own include file eventually */