From: "Erich E. Hoover" erich.e.hoover@gmail.com
Co-authored-by: Joel Holdsworth joel@airwebreathe.org.uk Signed-off-by: Joel Holdsworth joel@airwebreathe.org.uk --- dlls/ntdll/unix/file.c | 97 +++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 4d58a251e66..8709b4eb7ea 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -363,6 +363,36 @@ NTSTATUS errno_to_status( int err ) }
+static int xattr_fremove( int filedes, const char *name ) +{ +#if defined(HAVE_SYS_XATTR_H) +#if defined(XATTR_ADDITIONAL_OPTIONS) + return fremovexattr( filedes, name, 0 ); +#else + return fremovexattr( filedes, name ); +#endif +#else + errno = ENOSYS; + return -1; +#endif +} + + +static int xattr_fset( int filedes, const char *name, const void *value, size_t size ) +{ +#if defined(HAVE_SYS_XATTR_H) +#if defined(XATTR_ADDITIONAL_OPTIONS) + return fsetxattr( filedes, name, value, size, 0, 0 ); +#else + return fsetxattr( filedes, name, value, size, 0 ); +#endif +#else + errno = ENOSYS; + return -1; +#endif +} + + static int xattr_get( const char *path, const char *name, void *value, size_t size ) { #if defined(HAVE_SYS_XATTR_H) @@ -1532,6 +1562,52 @@ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULON }
+static int fd_set_dos_attrib( int fd, ULONG attr ) +{ + /* we only store the HIDDEN and SYSTEM attributes */ + attr &= XATTR_ATTRIBS_MASK; + if (attr != 0) + { + /* encode the attribures in Samba 3 ASCII format. Samba 4 has extended + * this format with more features, but retains compatibility with the + * earlier format. */ + char data[11]; + int len = sprintf( data, "0x%x", attr ); + return xattr_fset( fd, SAMBA_XATTR_DOS_ATTRIB, data, len ); + } + else + return xattr_fremove( fd, SAMBA_XATTR_DOS_ATTRIB ); +} + + +/* set the stat info and file attributes for a file (by file descriptor) */ +NTSTATUS fd_set_file_info( int fd, ULONG attr ) +{ + struct stat st; + + if (fstat( fd, &st ) == -1) return errno_to_status( errno ); + if (attr & FILE_ATTRIBUTE_READONLY) + { + if (S_ISDIR( st.st_mode)) + WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n"); + else + st.st_mode &= ~0222; /* clear write permission bits */ + } + else + { + /* add write permission only where we already have read permission */ + st.st_mode |= (0600 | ((st.st_mode & 044) >> 1)) & (~start_umask); + } + if (fchmod( fd, st.st_mode ) == -1) return errno_to_status( errno ); + + if (fd_set_dos_attrib( fd, attr ) == -1 && errno != ENOTSUP) + WARN( "Failed to set extended attribute " SAMBA_XATTR_DOS_ATTRIB ". errno %d (%s)\n", + errno, strerror( errno ) ); + + return STATUS_SUCCESS; +} + + /* get the stat info and file attributes for a file (by name) */ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) { @@ -4429,7 +4505,6 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, case FileBasicInformation: if (len >= sizeof(FILE_BASIC_INFORMATION)) { - struct stat st; const FILE_BASIC_INFORMATION *info = ptr; LARGE_INTEGER mtime, atime;
@@ -4443,25 +4518,7 @@ NTSTATUS WINAPI NtSetInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, status = set_file_times( fd, &mtime, &atime );
if (status == STATUS_SUCCESS && info->FileAttributes) - { - if (fstat( fd, &st ) == -1) status = errno_to_status( errno ); - else - { - if (info->FileAttributes & FILE_ATTRIBUTE_READONLY) - { - if (S_ISDIR( st.st_mode)) - WARN("FILE_ATTRIBUTE_READONLY ignored for directory.\n"); - else - st.st_mode &= ~0222; /* clear write permission bits */ - } - else - { - /* add write permission only where we already have read permission */ - st.st_mode |= (0600 | ((st.st_mode & 044) >> 1)) & (~start_umask); - } - if (fchmod( fd, st.st_mode ) == -1) status = errno_to_status( errno ); - } - } + status = fd_set_file_info( fd, info->FileAttributes );
if (needs_close) close( fd ); }