This patch set is based upon [patches from Wine Staging](https://github.com/wine-staging/wine-staging/tree/master/patches/ntdll-DOS_A...) by Erich E. Hoover (@ehoover), and implements support for the `SYSTEM`, `HIDDEN` and `READONLY` DOS file attributes. These can implemented in various ways depending upon the capabilities of the operating system and the file system. However, this initial patch-set focusses on just one method: Samba-formatted Extended File Attributes.
Modern filesystems generally support Extended File Attributes - auxiliary blobs of binary data that can be attached to a file. Samba uses the `user.DOSATTRIB` attribute to store DOS attribute information in the form of a hexadecimal value, and this patch-set implements a compatible mechanism.
Support for additional storage methods to increase operating system and filesystem compatibility is planned for later patch submissions.
This effort is part of a larger project I have been working on to get Msys2 and Cygwin working properly on Wine. The absence of DOS fule attribute support prevents one of the modes that Cygwin and Msys2 can use to emulate symbolic links from working correctly, which causes the Cygwin installer to fail: https://bugs.winehq.org/show_bug.cgi?id=9158
-- v3: ntdll: Implement storing DOS attributes in NtCreateFile.
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 --- configure | 11 +++++++++++ configure.ac | 2 ++ dlls/ntdll/unix/file.c | 38 +++++++++++++++++++++++++++++++++++++- include/config.h.in | 3 +++ 4 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/configure b/configure index 3088184aade..a8bb25a13e6 100755 --- a/configure +++ b/configure @@ -9105,6 +9105,17 @@ then : fi
+ for ac_header in attr/xattr.h +do : + ac_fn_c_check_header_compile "$LINENO" "attr/xattr.h" "ac_cv_header_attr_xattr_h" "$ac_includes_default" +if test "x$ac_cv_header_attr_xattr_h" = xyes +then : + printf "%s\n" "#define HAVE_ATTR_XATTR_H 1" >>confdefs.h + HAVE_XATTR=1 +fi + +done +
DLLFLAGS=""
diff --git a/configure.ac b/configure.ac index 1e733962b75..fd59bd6948d 100644 --- a/configure.ac +++ b/configure.ac @@ -635,6 +635,8 @@ AC_CHECK_HEADERS([libprocstat.h],,, #include <sys/queue.h> #endif])
+AC_CHECK_HEADERS(attr/xattr.h, [HAVE_XATTR=1]) + dnl **** Check for working dll ****
AC_SUBST(DLLFLAGS,"") diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 7eb8dbe7ad4..12d83bd9d0c 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -98,6 +98,9 @@ #ifdef HAVE_SYS_STATFS_H #include <sys/statfs.h> #endif +#ifdef HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#endif #include <time.h> #include <unistd.h>
@@ -167,6 +170,9 @@ typedef struct
#define MAX_IGNORED_FILES 4
+#define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB" +#define XATTR_ATTRIBS_MASK (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM) + struct file_identity { dev_t dev; @@ -355,6 +361,18 @@ NTSTATUS errno_to_status( int err ) } }
+ +static int xattr_get( const char *path, const char *name, void *value, size_t size ) +{ +#if defined(HAVE_ATTR_XATTR_H) + return getxattr( path, name, value, size ); +#else + errno = ENOSYS; + return -1; +#endif +} + + /* get space from the current directory data buffer, allocating a new one if necessary */ static void *get_dir_data_space( struct dir_data *data, unsigned int size ) { @@ -1451,6 +1469,18 @@ static inline ULONG get_file_attributes( const struct stat *st ) }
+/* decode the xattr-stored DOS attributes */ +static int get_file_xattr( char *hexattr, int attrlen ) +{ + if (attrlen > 2 && hexattr[0] == '0' && hexattr[1] == 'x') + { + hexattr[attrlen] = 0; + return strtol( hexattr+2, NULL, 16 ) & XATTR_ATTRIBS_MASK; + } + return 0; +} + + static BOOL fd_is_mount_point( int fd, const struct stat *st ) { struct stat parent; @@ -1479,7 +1509,8 @@ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULON static int get_file_info( const char *path, struct stat *st, ULONG *attr ) { char *parent_path; - int ret; + char hexattr[11]; + int len, ret;
*attr = 0; ret = lstat( path, st ); @@ -1505,6 +1536,11 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) free( parent_path ); } *attr |= get_file_attributes( st ); + + len = xattr_get( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 ); + if (len != -1) + *attr |= get_file_xattr( hexattr, len ); + return ret; }
diff --git a/include/config.h.in b/include/config.h.in index de1bf6c61eb..25f09636b3a 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -25,6 +25,9 @@ /* Define to 1 if you have the <asm/user.h> header file. */ #undef HAVE_ASM_USER_H
+/* Define to 1 if you have the <attr/xattr.h> header file. */ +#undef HAVE_ATTR_XATTR_H + /* Define to 1 if you have the <capi20.h> header file. */ #undef HAVE_CAPI20_H
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 | 103 +++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 12d83bd9d0c..9b6b16c3b40 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -362,6 +362,28 @@ NTSTATUS errno_to_status( int err ) }
+static int xattr_fremove( int filedes, const char *name ) +{ +#if defined(HAVE_ATTR_XATTR_H) + return fremovexattr( filedes, name ); +#else + errno = ENOSYS; + return -1; +#endif +} + + +static int xattr_fset( int filedes, const char *name, void *value, size_t size ) +{ +#if defined(HAVE_ATTR_XATTR_H) + return fsetxattr( filedes, name, value, size, 0 ); +#else + errno = ENOSYS; + return -1; +#endif +} + + static int xattr_get( const char *path, const char *name, void *value, size_t size ) { #if defined(HAVE_ATTR_XATTR_H) @@ -1505,6 +1527,66 @@ 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 ) +{ + /* do not store everything, but keep everything Samba can use */ + attr &= ~FILE_ATTRIBUTE_NORMAL; + if (attr != 0) + { + char hexattr[11]; + int len = sprintf( hexattr, "0x%x", attr ); + int ret; + struct stat st; + + ret = xattr_fset( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, len ); + if (ret == 0) return 0; + if (errno != EACCES) return ret; + + /* if we don't have access, try temporarily modifying permissions. */ + if (fstat( fd, &st ) != 0 || + st.st_uid != getuid() || + fchmod( fd, st.st_mode | S_IRUSR ) != 0) + { + errno = EACCES; + return -1; + } + + ret = xattr_fset( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, len ); + if (ret != 0) return ret; + + return fchmod( fd, st.st_mode ); + } + 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 ); + + fd_set_dos_attrib( fd, attr ); + + 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 ) { @@ -4399,7 +4481,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;
@@ -4413,25 +4494,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 ); }
From: Joel Holdsworth joel@airwebreathe.org.uk
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=9158 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=15679 Co-authored-by: Erich E. Hoover erich.e.hoover@gmail.com Signed-off-by: Joel Holdsworth joel@airwebreathe.org.uk --- dlls/ntdll/tests/file.c | 8 ++++---- dlls/ntdll/unix/file.c | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index dd0061b13d8..d49d4d5c26f 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -1392,7 +1392,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 %lx not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes ); + ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fbi.FileAttributes );
/* Then HIDDEN */ memset(&fbi, 0, sizeof(fbi)); @@ -1405,7 +1405,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 %lx not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes ); + ok ( (fbi.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\n", fbi.FileAttributes );
/* Check NORMAL last of all (to make sure we can clear attributes) */ memset(&fbi, 0, sizeof(fbi)); @@ -1462,7 +1462,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 %lx not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes ); + ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_SYSTEM, "attribute %lx not FILE_ATTRIBUTE_SYSTEM\n", fai_buf.fai.BasicInformation.FileAttributes );
/* Then HIDDEN */ memset(&fai_buf.fai.BasicInformation, 0, sizeof(fai_buf.fai.BasicInformation)); @@ -1475,7 +1475,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 %lx not FILE_ATTRIBUTE_HIDDEN\n", fai_buf.fai.BasicInformation.FileAttributes ); + ok ( (fai_buf.fai.BasicInformation.FileAttributes & attrib_mask) == FILE_ATTRIBUTE_HIDDEN, "attribute %lx not FILE_ATTRIBUTE_HIDDEN\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/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 9b6b16c3b40..3e2d33278b1 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -395,6 +395,17 @@ static int xattr_get( const char *path, const char *name, void *value, size_t si }
+static int xattr_fget( int filedes, const char *name, void *value, size_t size ) +{ +#if defined(HAVE_ATTR_XATTR_H) + return fgetxattr( filedes, name, value, size ); +#else + errno = ENOSYS; + return -1; +#endif +} + + /* get space from the current directory data buffer, allocating a new one if necessary */ static void *get_dir_data_space( struct dir_data *data, unsigned int size ) { @@ -1514,7 +1525,8 @@ static BOOL fd_is_mount_point( int fd, const struct stat *st ) /* get the stat info and file attributes for a file (by file descriptor) */ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULONG *attr ) { - int ret; + char hexattr[11]; + int len, ret;
*attr = 0; ret = fstat( fd, st ); @@ -1523,6 +1535,11 @@ static int fd_get_file_info( int fd, unsigned int options, struct stat *st, ULON /* consider mount points to be reparse points (IO_REPARSE_TAG_MOUNT_POINT) */ if ((options & FILE_OPEN_REPARSE_POINT) && fd_is_mount_point( fd, st )) *attr |= FILE_ATTRIBUTE_REPARSE_POINT; + + len = xattr_fget( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 ); + if (len != -1) + *attr |= get_file_xattr( hexattr, len ); + return ret; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=124421
Your paranoid android.
=== debian11 (32 bit report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit ar:MA report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit de report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit fr report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit he:IL report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit hi:IN report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit ja:JP report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit zh:CN report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit WoW report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (64 bit WoW report) ===
ntdll: file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
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/tests/directory.c | 25 ++++++++++++------------- dlls/ntdll/unix/file.c | 11 +++++++++++ 2 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c index 2a5fedb4659..a5ea7900f8d 100644 --- a/dlls/ntdll/tests/directory.c +++ b/dlls/ntdll/tests/directory.c @@ -55,7 +55,6 @@ static NTSTATUS (WINAPI *pRtlWow64EnableFsRedirectionEx)( ULONG disable, ULONG *
/* The attribute sets to test */ static struct testfile_s { - BOOL todo; /* set if it doesn't work on wine yet */ BOOL attr_done; /* set if attributes were tested for this file already */ const DWORD attr; /* desired attribute */ WCHAR name[20]; /* filename to use */ @@ -63,16 +62,16 @@ static struct testfile_s { const char *description; /* for error messages */ int nfound; /* How many were found (expect 1) */ } testfiles[] = { - { 0, 0, FILE_ATTRIBUTE_NORMAL, {'l','o','n','g','f','i','l','e','n','a','m','e','.','t','m','p'}, "normal" }, - { 0, 0, FILE_ATTRIBUTE_NORMAL, {'n','.','t','m','p',}, "normal" }, - { 1, 0, FILE_ATTRIBUTE_HIDDEN, {'h','.','t','m','p',}, "hidden" }, - { 1, 0, FILE_ATTRIBUTE_SYSTEM, {'s','.','t','m','p',}, "system" }, - { 0, 0, FILE_ATTRIBUTE_DIRECTORY, {'d','.','t','m','p',}, "directory" }, - { 0, 0, FILE_ATTRIBUTE_NORMAL, {0xe9,'a','.','t','m','p'}, "normal" }, - { 0, 0, FILE_ATTRIBUTE_NORMAL, {0xc9,'b','.','t','m','p'}, "normal" }, - { 0, 0, FILE_ATTRIBUTE_NORMAL, {'e','a','.','t','m','p'}, "normal" }, - { 0, 0, FILE_ATTRIBUTE_DIRECTORY, {'.'}, ". directory" }, - { 0, 0, FILE_ATTRIBUTE_DIRECTORY, {'.','.'}, ".. directory" } + { 0, FILE_ATTRIBUTE_NORMAL, {'l','o','n','g','f','i','l','e','n','a','m','e','.','t','m','p'}, "normal" }, + { 0, FILE_ATTRIBUTE_NORMAL, {'n','.','t','m','p',}, "normal" }, + { 0, FILE_ATTRIBUTE_HIDDEN, {'h','.','t','m','p',}, "hidden" }, + { 0, FILE_ATTRIBUTE_SYSTEM, {'s','.','t','m','p',}, "system" }, + { 0, FILE_ATTRIBUTE_DIRECTORY, {'d','.','t','m','p',}, "directory" }, + { 0, FILE_ATTRIBUTE_NORMAL, {0xe9,'a','.','t','m','p'}, "normal" }, + { 0, FILE_ATTRIBUTE_NORMAL, {0xc9,'b','.','t','m','p'}, "normal" }, + { 0, FILE_ATTRIBUTE_NORMAL, {'e','a','.','t','m','p'}, "normal" }, + { 0, FILE_ATTRIBUTE_DIRECTORY, {'.'}, ". directory" }, + { 0, FILE_ATTRIBUTE_DIRECTORY, {'.','.'}, ".. directory" } }; static const int test_dir_count = ARRAY_SIZE(testfiles); static const int max_test_dir_size = ARRAY_SIZE(testfiles) + 5; /* size of above plus some for .. etc */ @@ -162,8 +161,8 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info) if (namelen != len || memcmp(nameW, testfiles[i].name, len*sizeof(WCHAR))) continue; if (!testfiles[i].attr_done) { - todo_wine_if (testfiles[i].todo) - ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%lx), got %lx (is your linux new enough?)\n", wine_dbgstr_w(testfiles[i].name), testfiles[i].description, testfiles[i].attr, attrib); + ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%lx), got %lx\n", + wine_dbgstr_w(testfiles[i].name), testfiles[i].description, testfiles[i].attr, attrib); testfiles[i].attr_done = TRUE; } testfiles[i].nfound++; diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 3e2d33278b1..77feb250d1e 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -3985,6 +3985,17 @@ NTSTATUS WINAPI NtCreateFile( HANDLE *handle, ACCESS_MASK access, OBJECT_ATTRIBU io->Information = FILE_OVERWRITTEN; break; } + + if (io->Information == FILE_CREATED) + { + int fd, needs_close; + + /* set any DOS extended attributes */ + if (!(status = server_get_unix_fd( *handle, 0, &fd, &needs_close, NULL, NULL ))) { + fd_set_dos_attrib( fd, attributes ); + if (needs_close) close( fd ); + } + } } else if (status == STATUS_TOO_MANY_OPENED_FILES) {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=124422
Your paranoid android.
=== debian11 (32 bit report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0 file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit ar:MA report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0
=== debian11 (32 bit de report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0
=== debian11 (32 bit fr report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0
=== debian11 (32 bit he:IL report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0
=== debian11 (32 bit hi:IN report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0
=== debian11 (32 bit ja:JP report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0
=== debian11 (32 bit zh:CN report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0 file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (32 bit WoW report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0 file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
=== debian11 (64 bit WoW report) ===
ntdll: directory.c:164: Test failed: file L"h.tmp": expected (null) (2), got 0 directory.c:164: Test failed: file L"s.tmp": expected (null) (4), got 0 file.c:1395: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1408: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN file.c:1465: Test failed: attribute 20 not FILE_ATTRIBUTE_SYSTEM file.c:1478: Test failed: attribute 20 not FILE_ATTRIBUTE_HIDDEN
Your probably need someone to add that to the testbot image.
I contacted Francois Gouget to inquire about it.
On a separate note, the last patch (ntdll: Implement storing DOS attributes in NtCreateFile.) appears to unnecessarily change `open_unix_file`. That's probably my bad in the original version.
Ok now fixed.
Wait, why do these patches require libattr? As far as I can tell we're not actually using it. We could just as easily include sys/xattr.h instead.
That's probably the only way I could get the header 8-ish years ago, but it could be I just included the wrong one at the time.
(I also can't tell what libattr does, since there's almost no documentation attached to the project.)
It's just a compatibility library for using extended attributes on various systems.