From: "Erich E. Hoover" Subject: [PATCH 4/4] ntdll: Implement storing DOS attributes in NtCreateFile (try 2). Message-Id: Date: Thu, 18 Dec 2014 17:15:17 -0700 This patch implements storing DOS attributes from the Samba format "user.DOSATTRIB" extended attribute using setxattr and removexattr. The patch complements part 3 (fsetxattr and fremovexattr), allowing the use of pathnames instead of file descriptors. From ac9076b71ddda6d430fe80fcfe62a47c2dcc9dc9 Mon Sep 17 00:00:00 2001 From: "Erich E. Hoover" Date: Wed, 20 Aug 2014 15:28:00 -0600 Subject: ntdll: Implement storing DOS attributes in NtCreateFile. --- dlls/ntdll/file.c | 79 ++++++++++++++++++++++++++++---------------- dlls/ntdll/tests/directory.c | 22 +++++------- include/wine/port.h | 2 ++ libs/port/xattr.c | 20 +++++++++++ 4 files changed, 80 insertions(+), 43 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 521ab64..b4187d4 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -205,6 +205,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. @@ -216,6 +231,8 @@ 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 ) { + struct object_attributes objattr; + struct security_descriptor *sd; ANSI_STRING unix_name; BOOL created = FALSE; @@ -259,39 +276,37 @@ 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) { - struct security_descriptor *sd; - struct object_attributes objattr; - - objattr.rootdir = wine_server_obj_handle( attr->RootDirectory ); - objattr.name_len = 0; - io->u.Status = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len ); - if (io->u.Status != STATUS_SUCCESS) - { - 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->attributes = attr->Attributes; - req->sharing = sharing; - req->create = disposition; - req->options = options; - req->attrs = attributes; - wine_server_add_data( req, &objattr, sizeof(objattr) ); - if (objattr.sd_len) wine_server_add_data( req, sd, objattr.sd_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; - NTDLL_free_struct_sd( sd ); + objattr.rootdir = wine_server_obj_handle( attr->RootDirectory ); + objattr.name_len = 0; + io->u.Status = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len ); + if (io->u.Status != STATUS_SUCCESS) + { 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->attributes = attr->Attributes; + req->sharing = sharing; + req->create = disposition; + req->options = options; + req->attrs = attributes; + wine_server_add_data( req, &objattr, sizeof(objattr) ); + if (objattr.sd_len) wine_server_add_data( req, sd, objattr.sd_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; + NTDLL_free_struct_sd( sd ); if (io->u.Status == STATUS_SUCCESS) { @@ -313,6 +328,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) { @@ -320,6 +340,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 f190ff4..68b5406 100644 --- a/dlls/ntdll/tests/directory.c +++ b/dlls/ntdll/tests/directory.c @@ -51,7 +51,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 */ const char *name; /* filename to use */ @@ -60,13 +59,13 @@ static struct testfile_s { int nfound; /* How many were found (expect 1) */ WCHAR nameW[20]; /* unicode version of name (filled in later) */ } testfiles[] = { - { 0, 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" }, - { 1, 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" }, - { 1, 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" }, - { 0, 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" }, - { 0, 0, FILE_ATTRIBUTE_DIRECTORY, ".", NULL, ". directory" }, - { 0, 0, FILE_ATTRIBUTE_DIRECTORY, "..", NULL, ".. directory" }, - { 0, 0, 0, NULL } + { 0, FILE_ATTRIBUTE_NORMAL, "n.tmp", NULL, "normal" }, + { 0, FILE_ATTRIBUTE_HIDDEN, "h.tmp", NULL, "hidden" }, + { 0, FILE_ATTRIBUTE_SYSTEM, "s.tmp", NULL, "system" }, + { 0, FILE_ATTRIBUTE_DIRECTORY, "d.tmp", NULL, "directory" }, + { 0, FILE_ATTRIBUTE_DIRECTORY, ".", NULL, ". directory" }, + { 0, FILE_ATTRIBUTE_DIRECTORY, "..", NULL, ".. directory" }, + { 0, 0, NULL } }; static const int max_test_dir_size = 20; /* size of above plus some for .. etc */ @@ -147,12 +146,7 @@ static void tally_test_file(FILE_BOTH_DIRECTORY_INFORMATION *dir_info) if (namelen != len || memcmp(nameW, testfiles[i].nameW, len*sizeof(WCHAR))) continue; if (!testfiles[i].attr_done) { - if (testfiles[i].todo) { - todo_wine - ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", testfiles[i].name, testfiles[i].description, testfiles[i].attr, attrib); - } else { - ok (attrib == (testfiles[i].attr & attribmask), "file %s: expected %s (%x), got %x (is your linux new enough?)\n", 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", 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 cc572f3..9e2b8165 100644 --- a/include/wine/port.h +++ b/include/wine/port.h @@ -373,6 +373,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 6918c99..683e7a6 100644 --- a/libs/port/xattr.c +++ b/libs/port/xattr.c @@ -67,3 +67,23 @@ 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(HAVE_ATTR_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(HAVE_ATTR_XATTR_H) + return setxattr( path, name, value, size, 0 ); +#else + errno = ENOSYS; + return -1; +#endif +} -- 1.9.1