summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler.cc')
-rw-r--r--winsup/cygwin/fhandler.cc37
1 files changed, 36 insertions, 1 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index e38a58226..4d4d0d83d 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -28,6 +28,7 @@ details. */
#include "ntdll.h"
#include "cygtls.h"
#include "sigproc.h"
+#include "nfs.h"
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
@@ -469,6 +470,8 @@ fhandler_base::open (int flags, mode_t mode)
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
NTSTATUS status;
+ PFILE_FULL_EA_INFORMATION p = NULL;
+ ULONG plen = 0;
syscall_printf ("(%S, %p)", pc.get_nt_native_path (), flags);
@@ -522,6 +525,18 @@ fhandler_base::open (int flags, mode_t mode)
break;
}
+ if (query_open () && pc.fs_is_nfs ())
+ {
+ /* Make sure we can read EAs of files on an NFS share. Also make
+ sure that we're going to act on the file itself, even if it'a
+ a symlink. */
+ access |= FILE_READ_EA;
+ if (query_open () >= query_write_control)
+ access |= FILE_WRITE_EA;
+ plen = sizeof nfs_aol_ffei;
+ p = (PFILE_FULL_EA_INFORMATION) &nfs_aol_ffei;
+ }
+
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
{
if (flags & O_CREAT)
@@ -578,13 +593,33 @@ fhandler_base::open (int flags, mode_t mode)
set_security_attribute (mode, &sa, sd);
attr.SecurityDescriptor = sa.lpSecurityDescriptor;
}
+ else if (pc.fs_is_nfs ())
+ {
+ /* When creating a file on an NFS share, we have to set the
+ file mode by writing a NFS fattr3 structure with the
+ correct mode bits set. */
+ access |= FILE_WRITE_EA;
+ plen = sizeof (FILE_FULL_EA_INFORMATION) + sizeof (NFS_V3_ATTR)
+ + sizeof (fattr3);
+ p = (PFILE_FULL_EA_INFORMATION) alloca (plen);
+ p->NextEntryOffset = 0;
+ p->Flags = 0;
+ p->EaNameLength = sizeof (NFS_V3_ATTR) - 1;
+ p->EaValueLength = sizeof (fattr3);
+ strcpy (p->EaName, NFS_V3_ATTR);
+ fattr3 *nfs_attr = (fattr3 *) (p->EaName
+ + p->EaNameLength + 1);
+ memset (nfs_attr, 0, sizeof (fattr3));
+ nfs_attr->type = NF3REG;
+ nfs_attr->mode = mode;
+ }
/* The file attributes are needed for later use in, e.g. fchmod. */
pc.file_attributes (file_attributes);
}
}
status = NtCreateFile (&x, access, &attr, &io, NULL, file_attributes, shared,
- create_disposition, create_options, NULL, 0);
+ create_disposition, create_options, p, plen);
if (!NT_SUCCESS (status))
{
/* Trying to create a directory should return EISDIR, not ENOENT. */