diff options
Diffstat (limited to 'winsup')
-rw-r--r-- | winsup/cygwin/fhandler/disk_file.cc | 22 | ||||
-rw-r--r-- | winsup/cygwin/path.cc | 38 |
2 files changed, 48 insertions, 12 deletions
diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc index 19c976a..94f7ef5 100644 --- a/winsup/cygwin/fhandler/disk_file.cc +++ b/winsup/cygwin/fhandler/disk_file.cc @@ -210,13 +210,14 @@ fhandler_base::fstat_by_nfs_ea (struct stat *buf) cyg_ldap cldap; bool ldap_open = false; - if (get_handle ()) + /* NFS stumbles over its own caching. If you write to the file, + a subsequent fstat does not return the actual size of the file, + but the size at the time the handle has been opened. Unless + access through another handle invalidates the caching within the + NFS client. Skip this for Cygwin-created Symlinks playing FIFOs + (this sets the filler1 member to NF3FIFO). */ + if (get_handle () && nfs_attr->filler1 != NF3FIFO) { - /* NFS stumbles over its own caching. If you write to the file, - a subsequent fstat does not return the actual size of the file, - but the size at the time the handle has been opened. Unless - access through another handle invalidates the caching within the - NFS client. */ if (get_access () & GENERIC_WRITE) FlushFileBuffers (get_handle ()); pc.get_finfo (get_handle ()); @@ -357,8 +358,13 @@ fhandler_base::fstat_fs (struct stat *buf) if (get_stat_handle ()) { - if (!nohandle () && (!is_fs_special () || get_flags () & O_PATH)) - res = pc.fs_is_nfs () ? fstat_by_nfs_ea (buf) : fstat_by_handle (buf); + if (!nohandle ()) + { + if (pc.fs_is_nfs ()) + res = fstat_by_nfs_ea (buf); + else if (!is_fs_special () || get_flags () & O_PATH) + res = fstat_by_handle (buf); + } if (res) res = fstat_by_name (buf); return res; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 37e46c0..c631fa8 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -3513,11 +3513,41 @@ restart: } /* If the file is on an NFS share and could be opened with extended - attributes, check if it's a symlink. Only files can be symlinks - (which can be symlinks to directories). */ - else if (fs.is_nfs () && (conv_hdl.nfsattr ()->type & 7) == NF3LNK) + attributes, check if it's a symlink or FIFO. */ + else if (fs.is_nfs ()) { - res = check_nfs_symlink (h); + /* Make sure filler1 is 0, so we can use it safely as a marker. */ + conv_hdl.nfsattr ()->filler1 = 0; + switch (conv_hdl.nfsattr ()->type & 7) + { + case NF3LNK: + res = check_nfs_symlink (h); + /* Enable Cygwin-created FIFOs to be recognized as FIFOs. + We have to overwrite the NFS fattr3 data, otherwise the + info returned by Cygwin's stat will still claim the file + is a symlink. */ + if (res && contents[0] == ':' && contents[1] == '\\' + && parse_device (contents) && major == _major (FH_FIFO)) + { + conv_hdl.nfsattr ()->type = NF3FIFO; + conv_hdl.nfsattr ()->mode = mode; + conv_hdl.nfsattr ()->size = 0; + /* Marker for fhandler_base::fstat_by_nfs_ea not to override + the cached fattr3 data with fresh data from the filesystem, + even if the handle is used for other purposes than stat. */ + conv_hdl.nfsattr ()->filler1 = NF3FIFO; + } + break; + case NF3FIFO: + /* Enable real FIFOs recognized as such. */ + major = _major (FH_FIFO); + minor = _minor (FH_FIFO); + mode = S_IFIFO | (conv_hdl.nfsattr ()->mode & ~S_IFMT); + isdevice = true; + break; + default: + break; + } if (res) break; } |