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 | 29 +++++++++++++++++ configure.ac | 4 +++ dlls/ntdll/unix/file.c | 72 +++++++++++++++++++++++++++++++++++++++++- include/config.h.in | 6 ++++ 4 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/configure b/configure index 3088184aade..0ff9e72c951 100755 --- a/configure +++ b/configure @@ -9105,6 +9105,35 @@ then : fi
+ for ac_header in sys/xattr.h +do : + ac_fn_c_check_header_compile "$LINENO" "sys/xattr.h" "ac_cv_header_sys_xattr_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_xattr_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_XATTR_H 1" >>confdefs.h + HAVE_XATTR=1 + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/xattr.h> +int +main (void) +{ +getxattr("", "", "", 0, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +printf "%s\n" "#define XATTR_ADDITIONAL_OPTIONS 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +done +
DLLFLAGS=""
diff --git a/configure.ac b/configure.ac index 1e733962b75..8264c170b87 100644 --- a/configure.ac +++ b/configure.ac @@ -635,6 +635,10 @@ AC_CHECK_HEADERS([libprocstat.h],,, #include <sys/queue.h> #endif])
+AC_CHECK_HEADERS(sys/xattr.h, [HAVE_XATTR=1] + [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)])])]) + dnl **** Check for working dll ****
AC_SUBST(DLLFLAGS,"") diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 7eb8dbe7ad4..82ecae03c37 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -34,6 +34,7 @@ #include <stdarg.h> #include <string.h> #include <stdlib.h> +#include <stdint.h> #include <stdio.h> #include <limits.h> #include <unistd.h> @@ -98,8 +99,17 @@ #ifdef HAVE_SYS_STATFS_H #include <sys/statfs.h> #endif +#ifdef HAVE_SYS_XATTR_H +#include <sys/xattr.h> +#endif #include <time.h> #include <unistd.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -167,6 +177,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 +368,22 @@ NTSTATUS errno_to_status( int err ) } }
+ +static int xattr_get( const char *path, const char *name, void *value, size_t size ) +{ +#if defined(HAVE_SYS_XATTR_H) +#if defined(XATTR_ADDITIONAL_OPTIONS) + return getxattr( path, name, value, size, 0, 0 ); +#else + return getxattr( path, name, value, size ); +#endif +#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 +1480,38 @@ static inline ULONG get_file_attributes( const struct stat *st ) }
+/* decode the xattr-stored DOS attributes */ +static int parse_samba_dos_attrib_data( char *data, int len ) +{ + size_t string_len = strnlen( data, len ); + + if (len > string_len + 3) + { + uint16_t version; + memcpy( &version, data + string_len + 1, 2 ); + version = ntohs(version); + if ( version != 3 ) + { + static BOOL warn = TRUE; + if (warn) + { + FIXME( "Unsupported Samba DOSATTRIB Extended Attribute version: %u\n", + version ); + warn = FALSE; + } + } + } + + if (string_len > 2 && data[0] == '0' && data[1] == 'x') + { + data[len] = 0; + return strtol( data+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 +1540,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 attr_data[65]; + int attr_len, ret;
*attr = 0; ret = lstat( path, st ); @@ -1505,6 +1567,14 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr ) free( parent_path ); } *attr |= get_file_attributes( st ); + + attr_len = xattr_get( path, SAMBA_XATTR_DOS_ATTRIB, attr_data, sizeof(attr_data)-1 ); + if (attr_len != -1) + *attr |= parse_samba_dos_attrib_data( attr_data, attr_len ); + else if (errno != ENODATA && errno != ENOTSUP) + WARN( "Failed to get extended attribute " SAMBA_XATTR_DOS_ATTRIB " from "%s". errno %d (%s)\n", + path, errno, strerror( errno ) ); + return ret; }
diff --git a/include/config.h.in b/include/config.h.in index de1bf6c61eb..8f0c27bb265 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -679,6 +679,9 @@ /* Define to 1 if you have the <sys/vnode.h> header file. */ #undef HAVE_SYS_VNODE_H
+/* Define to 1 if you have the <sys/xattr.h> header file. */ +#undef HAVE_SYS_XATTR_H + /* Define to 1 if you have the `tcdrain' function. */ #undef HAVE_TCDRAIN
@@ -888,6 +891,9 @@ backward compatibility; new code need not use it. */ #undef STDC_HEADERS
+/* Define if xattr functions take additional arguments (Mac OS X) */ +#undef XATTR_ADDITIONAL_OPTIONS + /* Define to 1 if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING