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 | 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 +}