From: "Erich E. Hoover" erich.e.hoover@gmail.com
v2: merge macos support
From: Erich E. Hoover erich.e.hoover@gmail.com Signed-off-by: Vijay Kiran Kamuju infyquest@gmail.com --- dlls/ntdll/file.c | 54 ++++++++++++++++++++++++++--------------- dlls/ntdll/tests/file.c | 8 +++--- include/wine/port.h | 2 ++ libs/port/xattr.c | 24 ++++++++++++++++++ 4 files changed, 64 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 02fd7a940b..852b2462fe 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -168,6 +168,39 @@ int fd_get_file_info( int fd, struct stat *st, ULONG *attr ) return ret; }
+/* set the stat info and file attributes for a file (by file descriptor) */ +NTSTATUS fd_set_file_info( int fd, ULONG attr ) +{ + char hexattr[11]; + struct stat st; + + if (fstat( fd, &st ) == -1) return FILE_GetNtStatus(); + 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)) & (~FILE_umask); + } + if (fchmod( fd, st.st_mode ) == -1) return FILE_GetNtStatus(); + attr &= ~FILE_ATTRIBUTE_NORMAL; /* do not store everything, but keep everything Samba can use */ + if (attr != 0) + { + int len; + + len = sprintf( hexattr, "0x%x", attr ); + xattr_fset( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, len ); + } + else + xattr_fremove( fd, SAMBA_XATTR_DOS_ATTRIB ); + return STATUS_SUCCESS; +} + /* get the stat info and file attributes for a file (by name) */ int get_file_info( const char *path, struct stat *st, ULONG *attr ) { @@ -2544,7 +2577,6 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, case FileBasicInformation: if (len >= sizeof(FILE_BASIC_INFORMATION)) { - struct stat st; const FILE_BASIC_INFORMATION *info = ptr;
if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) @@ -2554,25 +2586,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, io->u.Status = set_file_times( fd, &info->LastWriteTime, &info->LastAccessTime );
if (io->u.Status == STATUS_SUCCESS && info->FileAttributes) - { - if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus(); - 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)) & (~FILE_umask); - } - if (fchmod( fd, st.st_mode ) == -1) io->u.Status = FILE_GetNtStatus(); - } - } + io->u.Status = fd_set_file_info( fd, info->FileAttributes );
if (needs_close) close( fd ); } diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 8e54dbb541..fc20615550 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -1340,7 +1340,7 @@ static void test_file_basic_information(void) memset(&fbi, 0, sizeof(fbi)); res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation); ok ( res == STATUS_SUCCESS, "can't get attributes\n"); - todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes ); + ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fbi.FileAttributes );
/* Then HIDDEN */ memset(&fbi, 0, sizeof(fbi)); @@ -1353,7 +1353,7 @@ static void test_file_basic_information(void) memset(&fbi, 0, sizeof(fbi)); res = pNtQueryInformationFile(h, &io, &fbi, sizeof fbi, FileBasicInformation); ok ( res == STATUS_SUCCESS, "can't get attributes\n"); - todo_wine ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes ); + ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fbi.FileAttributes );
/* Check NORMAL last of all (to make sure we can clear attributes) */ memset(&fbi, 0, sizeof(fbi)); @@ -1410,7 +1410,7 @@ static void test_file_all_information(void) memset(&fai_buf.fai, 0, sizeof(fai_buf.fai)); res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation); ok ( res == STATUS_SUCCESS, "can't get attributes, res %x\n", res); - todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes ); + ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %x not FILE_ATTRIBUTE_SYSTEM (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
/* Then HIDDEN */ memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation)); @@ -1423,7 +1423,7 @@ static void test_file_all_information(void) memset(&fai_buf.fai, 0, sizeof(fai_buf.fai)); res = pNtQueryInformationFile(h, &io, &fai_buf.fai, sizeof fai_buf, FileAllInformation); ok ( res == STATUS_SUCCESS, "can't get attributes\n"); - todo_wine ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN\n", fai_buf.fai.BasicInformation.FileAttributes ); + ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %x not FILE_ATTRIBUTE_HIDDEN (ok in old linux without xattr)\n", fai_buf.fai.BasicInformation.FileAttributes );
/* Check NORMAL last of all (to make sure we can clear attributes) */ memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation)); diff --git a/include/wine/port.h b/include/wine/port.h index 15b7b3f666..1c9fe93745 100644 --- a/include/wine/port.h +++ b/include/wine/port.h @@ -342,6 +342,8 @@ extern int mkstemps(char *template, int suffix_len); #endif
extern int xattr_fget( int filedes, const char *name, void *value, size_t size ); +extern int xattr_fremove( int filedes, const char *name ); +extern int xattr_fset( int filedes, const char *name, void *value, size_t size ); extern int xattr_get( const char *path, const char *name, void *value, size_t size );
/* Interlocked functions */ diff --git a/libs/port/xattr.c b/libs/port/xattr.c index 38f978cfb2..1366e72f3d 100644 --- a/libs/port/xattr.c +++ b/libs/port/xattr.c @@ -43,6 +43,30 @@ int xattr_fget( int filedes, const char *name, void *value, size_t size ) #endif }
+int xattr_fremove( int filedes, const char *name ) +{ +#if defined(XATTR_ADDITIONAL_OPTIONS) + return fremovexattr( filedes, name, 0 ); +#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) + return fremovexattr( filedes, name ); +#else + errno = ENOSYS; + return -1; +#endif +} + +int xattr_fset( int filedes, const char *name, void *value, size_t size ) +{ +#if defined(XATTR_ADDITIONAL_OPTIONS) + return fsetxattr( filedes, name, value, size, 0, 0 ); +#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) + return fsetxattr( filedes, name, value, size, 0 ); +#else + errno = ENOSYS; + return -1; +#endif +} + int xattr_get( const char *path, const char *name, void *value, size_t size ) { #if defined(XATTR_ADDITIONAL_OPTIONS)