Cygwin: path_conv: decouple path_types from mount types
- Remove another unfortunate amalgamation: Mount flags (MOUNT_xxx) are converted to path_types (PATH_xxx) and mixed with non-mount path_types flags in the same storage, leading to a tangled, pell-mell usage of mount flags and path flags in path_conv and symlink_info. - There's also the case of PC_NONULLEMPTY. It's used in exactly one place with a path_conv constructor only used in this single place, just to override the automatic PC_NULLEMPTY addition when calling the other path_conv constructors. Crazily, PC_NONULLEMPTY is a define, no path_types flag, despite its name. - It doesn't help that the binary flag exists as mount and path flag, while the text flag only exists as path flag. This leads to mount code using path flags to set text/binary. Very confusing is the fact that a text mount/path flag is not actually required; the mount code sets the text flag on non binary mounts anyway, so there are only two states. However, to puzzle people a bit more, path_conv::binary wrongly implies there's a third, non-binary/non-text state. Clean up this mess: - Store path flags separately from mount flags in path_conv and symlink_info classes and change all checks and testing inline methods accordingly. - Make PC_NONULLEMPTY a simple path_types flag and drop the redundant path_check constructor. - Clean up the definition of pathconv_arg, path_types, and mount flags. Use _BIT expression, newly define in cygwin/bits.h. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
@@ -80,8 +80,9 @@ struct symlink_info
|
||||
char contents[SYMLINK_MAX + 1];
|
||||
char *ext_here;
|
||||
int extn;
|
||||
unsigned pflags; /* path flags, i.e. mount flags, special files, ... */
|
||||
unsigned pc_flags; /* Relevant flags from caller of path_conv */
|
||||
unsigned path_flags;
|
||||
unsigned mount_flags;
|
||||
unsigned pc_flags; /* Relevant pathconv_arg flags from path_conv caller */
|
||||
DWORD fileattr;
|
||||
int issymlink;
|
||||
bool ext_tacked_on;
|
||||
@@ -671,6 +672,7 @@ path_conv::check (const char *src, unsigned opt,
|
||||
__try
|
||||
{
|
||||
int loop = 0;
|
||||
mount_flags = 0;
|
||||
path_flags = 0;
|
||||
suffix = NULL;
|
||||
fileattr = INVALID_FILE_ATTRIBUTES;
|
||||
@@ -761,7 +763,7 @@ 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,
|
||||
dev, &sym.pflags);
|
||||
dev, &sym.mount_flags);
|
||||
|
||||
if (error)
|
||||
return;
|
||||
@@ -782,7 +784,7 @@ path_conv::check (const char *src, unsigned opt,
|
||||
else
|
||||
{
|
||||
fileattr = getfileattr (THIS_path,
|
||||
sym.pflags & MOUNT_NOPOSIX);
|
||||
sym.mount_flags & MOUNT_NOPOSIX);
|
||||
dev = FH_FS;
|
||||
}
|
||||
goto out;
|
||||
@@ -897,14 +899,15 @@ path_conv::check (const char *src, unsigned opt,
|
||||
goto virtual_component_retry;
|
||||
}
|
||||
if (component == 0 || dev != FH_NETDRIVE)
|
||||
path_flags |= PATH_RO;
|
||||
mount_flags |= MOUNT_RO;
|
||||
goto out;
|
||||
}
|
||||
/* devn should not be a device. If it is, then stop parsing. */
|
||||
else if (dev != FH_FS)
|
||||
{
|
||||
fileattr = 0;
|
||||
path_flags = sym.pflags;
|
||||
mount_flags = sym.mount_flags;
|
||||
path_flags = sym.path_flags;
|
||||
if (component)
|
||||
{
|
||||
error = ENOTDIR;
|
||||
@@ -928,7 +931,7 @@ path_conv::check (const char *src, unsigned opt,
|
||||
calling sym.check, otherwise the path is potentially treated
|
||||
casesensitive. */
|
||||
if (is_msdos)
|
||||
sym.pflags |= PATH_NOPOSIX | PATH_NOACL;
|
||||
sym.mount_flags |= MOUNT_NOPOSIX | MOUNT_NOACL;
|
||||
|
||||
is_fs_via_procsys:
|
||||
|
||||
@@ -950,7 +953,7 @@ path_conv::check (const char *src, unsigned opt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sym.pflags & PATH_SOCKET)
|
||||
if (sym.path_flags & PATH_SOCKET)
|
||||
{
|
||||
if (component)
|
||||
{
|
||||
@@ -959,12 +962,13 @@ path_conv::check (const char *src, unsigned opt,
|
||||
}
|
||||
fileattr = sym.fileattr;
|
||||
#ifdef __WITH_AF_UNIX
|
||||
dev.parse ((sym.pflags & PATH_REP) ? FH_UNIX : FH_LOCAL);
|
||||
dev.parse ((sym.path_flags & PATH_REP) ? FH_UNIX : FH_LOCAL);
|
||||
#else
|
||||
dev.parse (FH_LOCAL);
|
||||
#endif /* __WITH_AF_UNIX */
|
||||
dev.setfs (1);
|
||||
path_flags = sym.pflags;
|
||||
mount_flags = sym.mount_flags;
|
||||
path_flags = sym.path_flags;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -973,7 +977,8 @@ path_conv::check (const char *src, unsigned opt,
|
||||
/* Make sure that /dev always exists. */
|
||||
fileattr = isdev_dev (dev) ? FILE_ATTRIBUTE_DIRECTORY
|
||||
: sym.fileattr;
|
||||
path_flags = sym.pflags;
|
||||
mount_flags = sym.mount_flags;
|
||||
path_flags = sym.path_flags;
|
||||
}
|
||||
else if (isdev_dev (dev))
|
||||
{
|
||||
@@ -1184,23 +1189,23 @@ path_conv::check (const char *src, unsigned opt,
|
||||
debug_printf ("this->path(%s), has_acls(%d)",
|
||||
path, fs.has_acls ());
|
||||
/* CV: We could use this->has_acls() but I want to make sure that
|
||||
we don't forget that the PATH_NOACL flag must be taken into
|
||||
we don't forget that the MOUNT_NOACL flag must be taken into
|
||||
account here. */
|
||||
if (!(path_flags & PATH_NOACL) && fs.has_acls ())
|
||||
if (!(mount_flags & MOUNT_NOACL) && fs.has_acls ())
|
||||
set_exec (0); /* We really don't know if this is executable or
|
||||
not here but set it to not executable since
|
||||
it will be figured out later by anything
|
||||
which cares about this. */
|
||||
}
|
||||
/* If the FS has been found to have unreliable inodes, note
|
||||
that in path_flags. */
|
||||
that in mount_flags. */
|
||||
if (!fs.hasgood_inode ())
|
||||
path_flags |= PATH_IHASH;
|
||||
mount_flags |= MOUNT_IHASH;
|
||||
/* If the OS is caseinsensitive or the FS is caseinsensitive,
|
||||
don't handle path casesensitive. */
|
||||
if (cygwin_shared->obcaseinsensitive || fs.caseinsensitive ())
|
||||
path_flags |= PATH_NOPOSIX;
|
||||
caseinsensitive = (path_flags & PATH_NOPOSIX)
|
||||
mount_flags |= MOUNT_NOPOSIX;
|
||||
caseinsensitive = (mount_flags & MOUNT_NOPOSIX)
|
||||
? OBJ_CASE_INSENSITIVE : 0;
|
||||
if (exec_state () != dont_know_if_executable)
|
||||
/* ok */;
|
||||
@@ -2272,7 +2277,7 @@ symlink_info::check_shortcut (HANDLE h)
|
||||
}
|
||||
}
|
||||
if (res) /* It's a symlink. */
|
||||
pflags |= PATH_SYMLINK | PATH_LNK;
|
||||
path_flags |= PATH_SYMLINK | PATH_LNK;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2302,24 +2307,24 @@ symlink_info::check_sysfile (HANDLE h)
|
||||
&& memcmp (cookie_buf, SYMLINK_COOKIE, sizeof (cookie_buf)) == 0)
|
||||
{
|
||||
/* It's a symlink. */
|
||||
pflags |= PATH_SYMLINK;
|
||||
path_flags |= PATH_SYMLINK;
|
||||
}
|
||||
else if (io.Information == sizeof (cookie_buf)
|
||||
&& memcmp (cookie_buf, SOCKET_COOKIE, sizeof (cookie_buf)) == 0)
|
||||
pflags |= PATH_SOCKET;
|
||||
path_flags |= PATH_SOCKET;
|
||||
else if (io.Information >= sizeof (INTERIX_SYMLINK_COOKIE)
|
||||
&& memcmp (cookie_buf, INTERIX_SYMLINK_COOKIE,
|
||||
sizeof (INTERIX_SYMLINK_COOKIE) - 1) == 0)
|
||||
{
|
||||
/* It's an Interix symlink. */
|
||||
pflags |= PATH_SYMLINK;
|
||||
path_flags |= PATH_SYMLINK;
|
||||
interix_symlink = true;
|
||||
/* Interix symlink cookies are shorter than Cygwin symlink cookies, so
|
||||
in case of an Interix symlink cooky we have read too far into the
|
||||
file. Set file pointer back to the position right after the cookie. */
|
||||
off.QuadPart = sizeof (INTERIX_SYMLINK_COOKIE) - 1;
|
||||
}
|
||||
if (pflags & PATH_SYMLINK)
|
||||
if (path_flags & PATH_SYMLINK)
|
||||
{
|
||||
status = NtReadFile (h, NULL, NULL, NULL, &io, srcbuf,
|
||||
NT_MAX_PATH, &off, NULL);
|
||||
@@ -2487,7 +2492,7 @@ symlink_info::check_reparse_point (HANDLE h, bool remote)
|
||||
return ret;
|
||||
}
|
||||
/* ret is > 0, so it's a known reparse point, path in symbuf. */
|
||||
pflags |= ret;
|
||||
path_flags |= ret;
|
||||
if (ret & PATH_SYMLINK)
|
||||
sys_wcstombs (srcbuf, SYMLINK_MAX + 7, symbuf.Buffer,
|
||||
symbuf.Length / sizeof (WCHAR));
|
||||
@@ -2523,7 +2528,7 @@ symlink_info::check_nfs_symlink (HANDLE h)
|
||||
(pffei->EaName + pffei->EaNameLength + 1);
|
||||
res = sys_wcstombs (contents, SYMLINK_MAX + 1,
|
||||
spath, pffei->EaValueLength);
|
||||
pflags |= PATH_SYMLINK;
|
||||
path_flags |= PATH_SYMLINK;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -2803,7 +2808,8 @@ symlink_info::check (char *path, const suffix_info *suffixes, fs_info &fs,
|
||||
suffix_scan suffix;
|
||||
|
||||
const ULONG ci_flag = cygwin_shared->obcaseinsensitive
|
||||
|| (pflags & PATH_NOPOSIX) ? OBJ_CASE_INSENSITIVE : 0;
|
||||
|| (mount_flags & MOUNT_NOPOSIX)
|
||||
? OBJ_CASE_INSENSITIVE : 0;
|
||||
/* TODO: Temporarily do all char->UNICODE conversion here. This should
|
||||
already be slightly faster than using Ascii functions. */
|
||||
tmp_pathbuf tp;
|
||||
@@ -2823,7 +2829,8 @@ restart:
|
||||
major = 0;
|
||||
minor = 0;
|
||||
mode = 0;
|
||||
pflags &= ~(PATH_SYMLINK | PATH_LNK | PATH_REP);
|
||||
// mount_flags is an incoming value set in path_conv */
|
||||
path_flags = 0;
|
||||
|
||||
PVOID eabuf = &nfs_aol_ffei;
|
||||
ULONG easize = sizeof nfs_aol_ffei;
|
||||
@@ -2842,7 +2849,7 @@ restart:
|
||||
while (suffix.next ())
|
||||
{
|
||||
error = 0;
|
||||
get_nt_native_path (suffix.path, upath, pflags & PATH_DOS);
|
||||
get_nt_native_path (suffix.path, upath, mount_flags & MOUNT_DOS);
|
||||
if (h)
|
||||
{
|
||||
NtClose (h);
|
||||
@@ -2895,7 +2902,7 @@ restart:
|
||||
slow down normal operation. This extra check only kicks in if
|
||||
we encountered a STATUS_OBJECT_NAME_NOT_FOUND *and* we didn't
|
||||
already attach a suffix. */
|
||||
if (!restarted && !*ext_here && !(pflags & PATH_DOS))
|
||||
if (!restarted && !*ext_here && !(mount_flags & MOUNT_DOS))
|
||||
{
|
||||
/* Check for trailing dot or space or leading space in
|
||||
last component. */
|
||||
@@ -2917,7 +2924,7 @@ restart:
|
||||
/* If so, try again. Since we now know the FS, the
|
||||
filenames will be tweaked to follow DOS rules via the
|
||||
third parameter in the call to get_nt_native_path. */
|
||||
pflags |= PATH_DOS;
|
||||
mount_flags |= MOUNT_DOS;
|
||||
restarted = true;
|
||||
goto restart;
|
||||
}
|
||||
@@ -3211,8 +3218,8 @@ restart:
|
||||
NtClose (h);
|
||||
}
|
||||
|
||||
syscall_printf ("%d = symlink.check(%s, %p) (%y)",
|
||||
res, suffix.path, contents, pflags);
|
||||
syscall_printf ("%d = symlink.check(%s, %p) (mount_flags %y, path_flags %y)",
|
||||
res, suffix.path, contents, mount_flags, path_flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3222,7 +3229,8 @@ int
|
||||
symlink_info::set (char *path)
|
||||
{
|
||||
strcpy (contents, path);
|
||||
pflags = PATH_SYMLINK;
|
||||
mount_flags = 0;
|
||||
path_flags = PATH_SYMLINK;
|
||||
fileattr = FILE_ATTRIBUTE_NORMAL;
|
||||
error = 0;
|
||||
issymlink = true;
|
||||
@@ -3373,9 +3381,9 @@ chdir (const char *in_dir)
|
||||
|
||||
syscall_printf ("dir '%s'", in_dir);
|
||||
|
||||
/* Convert path. First argument ensures that we don't check for
|
||||
/* Convert path. PC_NONULLEMPTY ensures that we don't check for
|
||||
NULL/empty/invalid again. */
|
||||
path_conv path (PC_NONULLEMPTY, in_dir, PC_SYM_FOLLOW | PC_POSIX);
|
||||
path_conv path (in_dir, PC_SYM_FOLLOW | PC_POSIX | PC_NONULLEMPTY);
|
||||
if (path.error)
|
||||
{
|
||||
set_errno (path.error);
|
||||
|
Reference in New Issue
Block a user