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 --- configure.ac | 8 ++++++++ dlls/ntdll/file.c | 22 +++++++++++++++++++++- include/wine/port.h | 8 ++++++++ libs/port/Makefile.in | 3 ++- libs/port/xattr.c | 44 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 libs/port/xattr.c
diff --git a/configure.ac b/configure.ac index d1502bacf7..5782df2a3f 100644 --- a/configure.ac +++ b/configure.ac @@ -702,6 +702,14 @@ AC_CHECK_HEADERS([libprocstat.h],,, #include <sys/socket.h> #endif])
+AC_CHECK_HEADERS([attr/xattr.h sys/xattr.h]) +if test "$ac_cv_header_sys_xattr_h" = "yes" +then + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/xattr.h>]], [[getxattr("", "", "", 0, 0, 0);]])] + [AC_DEFINE(XATTR_ADDITIONAL_OPTIONS, 1, + [Define if xattr functions take additional arguments (Mac OS X)])]) +fi + dnl **** Check for working dll ****
AC_SUBST(DLLFLAGS,"-D_REENTRANT") diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 3dafdcfb44..d62126df6e 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -122,6 +122,22 @@ mode_t FILE_umask = 0;
static const WCHAR ntfsW[] = {'N','T','F','S'};
+/* Match the Samba conventions for storing DOS file attributes */ +#define SAMBA_XATTR_DOS_ATTRIB XATTR_USER_PREFIX "DOSATTRIB" +/* We are only interested in some attributes, the others have corresponding Unix attributes */ +#define XATTR_ATTRIBS_MASK (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM) + +/* decode the xattr-stored DOS attributes */ +static inline 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; +} + /* fetch the attributes of a file */ static inline ULONG get_file_attributes( const struct stat *st ) { @@ -139,12 +155,16 @@ static inline ULONG get_file_attributes( const struct stat *st ) /* get the stat info and file attributes for a file (by file descriptor) */ int fd_get_file_info( int fd, struct stat *st, ULONG *attr ) { - int ret; + char hexattr[11]; + int len, ret;
*attr = 0; ret = fstat( fd, st ); if (ret == -1) return ret; *attr |= get_file_attributes( st ); + len = xattr_fget( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 ); + if (len == -1) return ret; + *attr |= get_file_xattr( hexattr, len ); return ret; }
diff --git a/include/wine/port.h b/include/wine/port.h index d23e2b033f..2be2afe421 100644 --- a/include/wine/port.h +++ b/include/wine/port.h @@ -335,6 +335,14 @@ int usleep (unsigned int useconds);
extern int mkstemps(char *template, int suffix_len);
+/* Extended attribute functions */ + +#ifndef XATTR_USER_PREFIX +# define XATTR_USER_PREFIX "user." +#endif + +extern int xattr_fget( int filedes, const char *name, void *value, size_t size ); + /* Interlocked functions */
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) diff --git a/libs/port/Makefile.in b/libs/port/Makefile.in index a2e96d1500..dcc1ea1769 100644 --- a/libs/port/Makefile.in +++ b/libs/port/Makefile.in @@ -108,4 +108,5 @@ C_SRCS = \ usleep.c \ utf8.c \ wctomb.c \ - wctype.c + wctype.c \ + xattr.c diff --git a/libs/port/xattr.c b/libs/port/xattr.c new file mode 100644 index 0000000000..1c06b89a86 --- /dev/null +++ b/libs/port/xattr.c @@ -0,0 +1,44 @@ +/* + * extended attributes functions + * + * Copyright 2014 Erich E. Hoover + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#if defined(HAVE_ATTR_XATTR_H) +# undef XATTR_ADDITIONAL_OPTIONS +# include <attr/xattr.h> +#elif defined(HAVE_SYS_XATTR_H) +# include <sys/xattr.h> +#endif + +#include <ctype.h> +#include <errno.h> + +int xattr_fget( int filedes, const char *name, void *value, size_t size ) +{ +#if defined(XATTR_ADDITIONAL_OPTIONS) + return fgetxattr( filedes, name, value, size, 0, 0 ); +#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) + return fgetxattr( filedes, name, value, size ); +#else + errno = ENOSYS; + return -1; +#endif +}
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 | 6 +++++- include/wine/port.h | 1 + libs/port/xattr.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index d62126df6e..02fd7a940b 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -171,7 +171,8 @@ int fd_get_file_info( int fd, struct stat *st, ULONG *attr ) /* get the stat info and file attributes for a file (by name) */ int get_file_info( const char *path, struct stat *st, ULONG *attr ) { - int ret; + char hexattr[11]; + int len, ret;
*attr = 0; ret = lstat( path, st ); @@ -184,6 +185,9 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr ) if (S_ISDIR( st->st_mode )) *attr |= FILE_ATTRIBUTE_REPARSE_POINT; } *attr |= get_file_attributes( st ); + len = xattr_get( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 ); + if (len == -1) return ret; + *attr |= get_file_xattr( hexattr, len ); return ret; }
diff --git a/include/wine/port.h b/include/wine/port.h index 2be2afe421..15b7b3f666 100644 --- a/include/wine/port.h +++ b/include/wine/port.h @@ -342,6 +342,7 @@ 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_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 1c06b89a86..38f978cfb2 100644 --- a/libs/port/xattr.c +++ b/libs/port/xattr.c @@ -42,3 +42,15 @@ int xattr_fget( int filedes, const char *name, void *value, size_t size ) return -1; #endif } + +int xattr_get( const char *path, const char *name, void *value, size_t size ) +{ +#if defined(XATTR_ADDITIONAL_OPTIONS) + return getxattr( path, name, value, size, 0, 0 ); +#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) + return getxattr( path, name, value, size ); +#else + errno = ENOSYS; + return -1; +#endif +}
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)
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 +}
From: "Erich E. Hoover" erich.e.hoover@gmail.com
From: Erich E. Hoover erich.e.hoover@gmail.com Signed-off-by: Vijay Kiran Kamuju infyquest@gmail.com --- configure.ac | 2 +- libs/port/xattr.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac index 5782df2a3f..f76ed54218 100644 --- a/configure.ac +++ b/configure.ac @@ -702,7 +702,7 @@ AC_CHECK_HEADERS([libprocstat.h],,, #include <sys/socket.h> #endif])
-AC_CHECK_HEADERS([attr/xattr.h sys/xattr.h]) +AC_CHECK_HEADERS([attr/xattr.h sys/extattr.h sys/xattr.h]) if test "$ac_cv_header_sys_xattr_h" = "yes" then AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/xattr.h>]], [[getxattr("", "", "", 0, 0, 0);]])] diff --git a/libs/port/xattr.c b/libs/port/xattr.c index 60fb88d57a..35cf297d0b 100644 --- a/libs/port/xattr.c +++ b/libs/port/xattr.c @@ -24,6 +24,9 @@ #if defined(HAVE_ATTR_XATTR_H) # undef XATTR_ADDITIONAL_OPTIONS # include <attr/xattr.h> +#elif defined(HAVE_SYS_EXTATTR_H) +# undef XATTR_ADDITIONAL_OPTIONS +# include <sys/extattr.h> #elif defined(HAVE_SYS_XATTR_H) # include <sys/xattr.h> #endif @@ -31,12 +34,32 @@ #include <ctype.h> #include <errno.h>
+#ifndef XATTR_USER_PREFIX_LEN +# define XATTR_USER_PREFIX_LEN (sizeof(XATTR_USER_PREFIX) - 1) +#endif + +#ifdef HAVE_SYS_EXTATTR_H +static inline int xattr_valid_namespace( const char *name ) +{ + if (strncmp( XATTR_USER_PREFIX, name, XATTR_USER_PREFIX_LEN ) != 0) + { + errno = EPERM; + return 0; + } + return 1; +} +#endif + int xattr_fget( int filedes, const char *name, void *value, size_t size ) { #if defined(XATTR_ADDITIONAL_OPTIONS) return fgetxattr( filedes, name, value, size, 0, 0 ); #elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) return fgetxattr( filedes, name, value, size ); +#elif defined(HAVE_SYS_EXTATTR_H) + if (!xattr_valid_namespace( name )) return -1; + return extattr_get_fd( filedes, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN], + value, size ); #else errno = ENOSYS; return -1; @@ -49,6 +72,9 @@ int xattr_fremove( int filedes, const char *name ) return fremovexattr( filedes, name, 0 ); #elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) return fremovexattr( filedes, name ); +#elif defined(HAVE_SYS_EXTATTR_H) + if (!xattr_valid_namespace( name )) return -1; + return extattr_delete_fd( filedes, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN] ); #else errno = ENOSYS; return -1; @@ -61,6 +87,10 @@ int xattr_fset( int filedes, const char *name, void *value, size_t size ) 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 ); +#elif defined(HAVE_SYS_EXTATTR_H) + if (!xattr_valid_namespace( name )) return -1; + return extattr_set_fd( filedes, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN], + value, size ); #else errno = ENOSYS; return -1; @@ -73,6 +103,10 @@ int xattr_get( const char *path, const char *name, void *value, size_t size ) return getxattr( path, name, value, size, 0, 0 ); #elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) return getxattr( path, name, value, size ); +#elif defined(HAVE_SYS_EXTATTR_H) + if (!xattr_valid_namespace( name )) return -1; + return extattr_get_file( path, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN], + value, size ); #else errno = ENOSYS; return -1; @@ -85,6 +119,9 @@ int xattr_remove( const char *path, const char *name ) return removexattr( path, name, 0 ); #elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) return removexattr( path, name ); +#elif defined(HAVE_SYS_EXTATTR_H) + if (!xattr_valid_namespace( name )) return -1; + return extattr_delete_file( path, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN] ); #else errno = ENOSYS; return -1; @@ -97,6 +134,10 @@ int xattr_set( const char *path, const char *name, void *value, size_t size ) 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 ); +#elif defined(HAVE_SYS_EXTATTR_H) + if (!xattr_valid_namespace( name )) return -1; + return extattr_set_file( path, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN], + value, size ); #else errno = ENOSYS; return -1;
From: "Erich E. Hoover" erich.e.hoover@gmail.com
From: Erich E. Hoover erich.e.hoover@gmail.com Signed-off-by: Vijay Kiran Kamuju infyquest@gmail.com --- dlls/ntdll/directory.c | 15 +++++---------- dlls/ntdll/file.c | 10 ++++------ dlls/ntdll/ntdll_misc.h | 2 +- 3 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index c8534704c4..56737b8784 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -1267,17 +1267,17 @@ static DWORD WINAPI init_options( RTL_RUN_ONCE *once, void *param, void **contex * * Check if the specified file should be hidden based on its name and the show dot files option. */ -BOOL DIR_is_hidden_file( const UNICODE_STRING *name ) +BOOL DIR_is_hidden_file( const char *name ) { - WCHAR *p, *end; + char *p, *end;
RtlRunOnceExecuteOnce( &init_once, init_options, NULL, NULL );
if (show_dot_files) return FALSE;
- end = p = name->Buffer + name->Length/sizeof(WCHAR); - while (p > name->Buffer && IS_SEPARATOR(p[-1])) p--; - while (p > name->Buffer && !IS_SEPARATOR(p[-1])) p--; + end = p = (char *)name + strlen(name); + while (p > name && IS_SEPARATOR(p[-1])) p--; + while (p > name && !IS_SEPARATOR(p[-1])) p--; if (p == end || *p != '.') return FALSE; /* make sure it isn't '.' or '..' */ if (p + 1 == end) return FALSE; @@ -1526,11 +1526,6 @@ static NTSTATUS get_dir_data_entry( struct dir_data *dir_data, void *info_ptr, I if (class != FileNamesInformation) { if (st.st_dev != dir_data->id.dev) st.st_ino = 0; /* ignore inode if on a different device */ - - if (!show_dot_files && names->long_name[0] == '.' && names->long_name[1] && - (names->long_name[1] != '.' || names->long_name[2])) - attributes |= FILE_ATTRIBUTE_HIDDEN; - fill_file_info( &st, attributes, info, class ); }
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 122f2fd42e..3fefcf0981 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -218,6 +218,10 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr ) if (S_ISDIR( st->st_mode )) *attr |= FILE_ATTRIBUTE_REPARSE_POINT; } *attr |= get_file_attributes( st ); + /* convert Unix-style hidden files to a DOS hidden file attribute */ + if (DIR_is_hidden_file( path )) + *attr |= FILE_ATTRIBUTE_HIDDEN; + /* retrieve any stored DOS attributes */ len = xattr_get( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 ); if (len == -1) return ret; *attr |= get_file_xattr( hexattr, len ); @@ -2925,8 +2929,6 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr, info->AllocationSize = std.AllocationSize; info->EndOfFile = std.EndOfFile; info->FileAttributes = basic.FileAttributes; - if (DIR_is_hidden_file( attr->ObjectName )) - info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; } RtlFreeAnsiString( &unix_name ); } @@ -2954,11 +2956,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) status = STATUS_INVALID_INFO_CLASS; else - { status = fill_file_info( &st, attributes, info, FileBasicInformation ); - if (DIR_is_hidden_file( attr->ObjectName )) - info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; - } RtlFreeAnsiString( &unix_name ); } else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), status ); diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 6a609123fb..7c9c6cc601 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -158,7 +158,7 @@ extern NTSTATUS fill_file_info( const struct stat *st, ULONG attr, void *ptr, FILE_INFORMATION_CLASS class ) DECLSPEC_HIDDEN; extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN; extern void init_directories(void) DECLSPEC_HIDDEN; -extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name ) DECLSPEC_HIDDEN; +extern BOOL DIR_is_hidden_file( const char *name ) DECLSPEC_HIDDEN; extern NTSTATUS DIR_unmount_device( HANDLE handle ) DECLSPEC_HIDDEN; extern NTSTATUS DIR_get_unix_cwd( char **cwd ) DECLSPEC_HIDDEN; extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ) DECLSPEC_HIDDEN;
From: Sebastian Lackner sebastian@fds-team.de
From: Sebastian Lackner sebastian@fds-team.de Signed-off-by: Vijay Kiran Kamuju infyquest@gmail.com --- dlls/ntdll/file.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 3fefcf0981..f7b4bacd84 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -218,12 +218,15 @@ int get_file_info( const char *path, struct stat *st, ULONG *attr ) if (S_ISDIR( st->st_mode )) *attr |= FILE_ATTRIBUTE_REPARSE_POINT; } *attr |= get_file_attributes( st ); - /* convert Unix-style hidden files to a DOS hidden file attribute */ - if (DIR_is_hidden_file( path )) - *attr |= FILE_ATTRIBUTE_HIDDEN; /* retrieve any stored DOS attributes */ len = xattr_get( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 ); - if (len == -1) return ret; + if (len == -1) + { + /* convert Unix-style hidden files to a DOS hidden file attribute */ + if (DIR_is_hidden_file( path )) + *attr |= FILE_ATTRIBUTE_HIDDEN; + return ret; + } *attr |= get_file_xattr( hexattr, len ); return ret; } @@ -236,7 +239,7 @@ NTSTATUS set_file_info( const char *path, ULONG attr ) /* 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) + if (attr != 0 || DIR_is_hidden_file( path )) xattr_set( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, len ); else xattr_remove( path, SAMBA_XATTR_DOS_ATTRIB );