[PATCH V2 4/7] ntdll: Implement storing DOS attributes in NtCreateFile.

Vijay Kiran Kamuju infyquest at gmail.com
Sat Apr 27 21:20:01 CDT 2019


From: "Erich E. Hoover" <erich.e.hoover at gmail.com>

v2: merge macos support

From: Erich E. Hoover <erich.e.hoover at gmail.com>
Signed-off-by: Vijay Kiran Kamuju <infyquest at gmail.com>
---
 dlls/ntdll/file.c            | 76 +++++++++++++++++++++++-------------
 dlls/ntdll/tests/directory.c | 24 ++++++------
 include/wine/port.h          |  2 +
 libs/port/xattr.c            | 24 ++++++++++++
 4 files changed, 86 insertions(+), 40 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 852b2462fe..122f2fd42e 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -224,6 +224,21 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr )
     return ret;
 }
 
+NTSTATUS set_file_info( const char *path, ULONG attr )
+{
+    char hexattr[11];
+    int len;
+
+    /* Note: unix mode already set when called this way */
+    attr &= ~FILE_ATTRIBUTE_NORMAL; /* do not store everything, but keep everything Samba can use */
+    len = sprintf( hexattr, "0x%x", attr );
+    if (attr != 0)
+        xattr_set( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, len );
+    else
+        xattr_remove( path, SAMBA_XATTR_DOS_ATTRIB );
+    return STATUS_SUCCESS;
+}
+
 /**************************************************************************
  *                 FILE_CreateFile                    (internal)
  * Open a file.
@@ -235,6 +250,10 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
                                  ULONG attributes, ULONG sharing, ULONG disposition,
                                  ULONG options, PVOID ea_buffer, ULONG ea_length )
 {
+    static UNICODE_STRING empty_string;
+    OBJECT_ATTRIBUTES unix_attr;
+    data_size_t len;
+    struct object_attributes *objattr;
     ANSI_STRING unix_name;
     BOOL created = FALSE;
 
@@ -278,37 +297,34 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
         io->u.Status = STATUS_SUCCESS;
     }
 
-    if (io->u.Status == STATUS_SUCCESS)
+    if (io->u.Status != STATUS_SUCCESS)
     {
-        static UNICODE_STRING empty_string;
-        OBJECT_ATTRIBUTES unix_attr = *attr;
-        data_size_t len;
-        struct object_attributes *objattr;
-
-        unix_attr.ObjectName = &empty_string;  /* we send the unix name instead */
-        if ((io->u.Status = alloc_object_attributes( &unix_attr, &objattr, &len )))
-        {
-            RtlFreeAnsiString( &unix_name );
-            return io->u.Status;
-        }
+        WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
+        return io->u.Status;
+    }
 
-        SERVER_START_REQ( create_file )
-        {
-            req->access     = access;
-            req->sharing    = sharing;
-            req->create     = disposition;
-            req->options    = options;
-            req->attrs      = attributes;
-            wine_server_add_data( req, objattr, len );
-            wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
-            io->u.Status = wine_server_call( req );
-            *handle = wine_server_ptr_handle( reply->handle );
-        }
-        SERVER_END_REQ;
-        RtlFreeHeap( GetProcessHeap(), 0, objattr );
+    unix_attr = *attr;
+    unix_attr.ObjectName = &empty_string;  /* we send the unix name instead */
+    if ((io->u.Status = alloc_object_attributes( &unix_attr, &objattr, &len )))
+    {
         RtlFreeAnsiString( &unix_name );
+        return io->u.Status;
     }
-    else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), io->u.Status );
+
+    SERVER_START_REQ( create_file )
+    {
+        req->access     = access;
+        req->sharing    = sharing;
+        req->create     = disposition;
+        req->options    = options;
+        req->attrs      = attributes;
+        wine_server_add_data( req, objattr, len );
+        wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
+        io->u.Status = wine_server_call( req );
+        *handle = wine_server_ptr_handle( reply->handle );
+    }
+    SERVER_END_REQ;
+    RtlFreeHeap( GetProcessHeap(), 0, objattr );
 
     if (io->u.Status == STATUS_SUCCESS)
     {
@@ -330,6 +346,11 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
             io->Information = FILE_OVERWRITTEN;
             break;
         }
+        if (io->Information == FILE_CREATED)
+        {
+            /* set any DOS extended attributes */
+            set_file_info( unix_name.Buffer, attributes );
+        }
     }
     else if (io->u.Status == STATUS_TOO_MANY_OPENED_FILES)
     {
@@ -337,6 +358,7 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
         if (!once++) ERR_(winediag)( "Too many open files, ulimit -n probably needs to be increased\n" );
     }
 
+    RtlFreeAnsiString( &unix_name );
     return io->u.Status;
 }
 
diff --git a/dlls/ntdll/tests/directory.c b/dlls/ntdll/tests/directory.c
index 1109f7f3a4..eaef08cdc4 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,7 @@ 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 (%x), got %x (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 (%x), got %x (is your linux new enough?)\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/include/wine/port.h b/include/wine/port.h
index 1c9fe93745..68deef426d 100644
--- a/include/wine/port.h
+++ b/include/wine/port.h
@@ -345,6 +345,8 @@ 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 );
+extern int xattr_remove( const char *path, const char *name );
+extern int xattr_set( 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 1366e72f3d..60fb88d57a 100644
--- a/libs/port/xattr.c
+++ b/libs/port/xattr.c
@@ -78,3 +78,27 @@ int xattr_get( const char *path, const char *name, void *value, size_t size )
     return -1;
 #endif
 }
+
+int xattr_remove( const char *path, const char *name )
+{
+#if defined(XATTR_ADDITIONAL_OPTIONS)
+    return removexattr( path, name, 0 );
+#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
+    return removexattr( path, name );
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
+
+int xattr_set( const char *path, const char *name, void *value, size_t size )
+{
+#if defined(XATTR_ADDITIONAL_OPTIONS)
+    return setxattr( path, name, value, size, 0, 0 );
+#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
+    return setxattr( path, name, value, size, 0 );
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
-- 
2.21.0




More information about the wine-devel mailing list