From fde4eaa105912625b6a78fba79d1fc39ee0fd201 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sun, 6 Jan 2019 14:29:53 +0100 Subject: [PATCH] Cygwin: path_conv: decouple pathconv_flags from path_types There's an unfortunate amalgamation of caller-provided pathconv_arg flags with path_types flags which in turn are mostly mount flags. This leads to a confusion of flag values in sylink_info::pflags and, in turn, in path_conv::path_flags. This patch decouples pathconv_flags from the other flags by making sure that a pathconv_flag is never copied into a variable used for path_types flags. Also, remove PATH_NO_ACCESS_CHECK since it's not necessary. Signed-off-by: Corinna Vinschen --- winsup/cygwin/path.cc | 19 +++++++++++-------- winsup/cygwin/path.h | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index b039801d5..28b966692 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -80,7 +80,8 @@ struct symlink_info char contents[SYMLINK_MAX + 1]; char *ext_here; int extn; - unsigned pflags; + unsigned pflags; /* path flags, i.e. mount flags, special files, ... */ + unsigned pc_flags; /* Relevant flags from caller of path_conv */ DWORD fileattr; int issymlink; bool ext_tacked_on; @@ -735,9 +736,10 @@ path_conv::check (const char *src, unsigned opt, int symlen = 0; - for (unsigned pflags_or = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE); + /* Make sure to check certain flags on last component only. */ + for (unsigned pc_flags = opt & (PC_NO_ACCESS_CHECK | PC_KEEP_HANDLE); ; - pflags_or = 0) + pc_flags = 0) { const suffix_info *suff; char *full_path; @@ -764,7 +766,7 @@ path_conv::check (const char *src, unsigned opt, if (error) return; - sym.pflags |= pflags_or; + sym.pc_flags = pc_flags; if (!dev.exists ()) { @@ -1190,7 +1192,7 @@ path_conv::check (const char *src, unsigned opt, it will be figured out later by anything which cares about this. */ } - /* If the FS has been found to have unrelibale inodes, note + /* If the FS has been found to have unreliable inodes, note that in path_flags. */ if (!fs.hasgood_inode ()) path_flags |= PATH_IHASH; @@ -2721,7 +2723,8 @@ bool symlink_info::set_error (int in_errno) { bool res; - if (!(pflags & PATH_NO_ACCESS_CHECK) || in_errno == ENAMETOOLONG || in_errno == EIO) + if (!(pc_flags & PC_NO_ACCESS_CHECK) + || in_errno == ENAMETOOLONG || in_errno == EIO) { error = in_errno; res = true; @@ -3103,7 +3106,7 @@ restart: The handle has been opened with the FILE_OPEN_REPARSE_POINT flag, so it's a handle to the reparse point, not a handle to the volumes root dir. */ - pflags &= ~PC_KEEP_HANDLE; + pc_flags &= ~PC_KEEP_HANDLE; /* Volume mount point: The filesystem information for the top level directory should be for the volume top level directory, rather than for the reparse point itself. So we fetch the @@ -3202,7 +3205,7 @@ restart: if (h) { - if (pflags & PC_KEEP_HANDLE) + if (pc_flags & PC_KEEP_HANDLE) conv_hdl.set (h); else NtClose (h); diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 981269995..297eaa609 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -39,6 +39,8 @@ struct suffix_info extern suffix_info stat_suffixes[]; +/* DO NOT copy any of these files into the same set of flags as the + below path_types. Ever. */ enum pathconv_arg { PC_SYM_FOLLOW = 0x0001, @@ -76,7 +78,6 @@ enum path_types PATH_DOS = MOUNT_DOS, PATH_IHASH = MOUNT_IHASH, PATH_ALL_EXEC = (PATH_CYGWIN_EXEC | PATH_EXEC), - PATH_NO_ACCESS_CHECK = PC_NO_ACCESS_CHECK, PATH_CTTY = 0x00400000, /* could later be used as ctty */ PATH_OPEN = 0x00800000, /* use open semantics */ /* FIXME? PATH_OPEN collides with