From f96ab0203c4119942b9d8ccc27207cc73389b375 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Tue, 19 Aug 2014 22:10:49 -0600
Subject: [PATCH] ntdll: Implement retrieving DOS attributes in
 [fd_]get_file_info().

---
 configure.ac           | 12 +++++++++++
 dlls/ntdll/unix/file.c | 22 ++++++++++++++++++-
 include/wine/port.h    |  9 ++++++++
 libs/port/Makefile.in  |  3 ++-
 libs/port/xattr.c      | 49 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 93 insertions(+), 2 deletions(-)
 create mode 100644 libs/port/xattr.c

diff --git a/configure.ac b/configure.ac
index 4829648c3a5..cff2d4b8288 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,6 +88,7 @@ AC_ARG_WITH(usb,       AS_HELP_STRING([--without-usb],[do not use the libusb lib
 AC_ARG_WITH(v4l2,      AS_HELP_STRING([--without-v4l2],[do not use v4l2 (video capture)]))
 AC_ARG_WITH(vkd3d,     AS_HELP_STRING([--without-vkd3d],[do not use vkd3d (Direct3D 12 support)]))
 AC_ARG_WITH(vulkan,    AS_HELP_STRING([--without-vulkan],[do not use Vulkan]))
+AC_ARG_WITH(xattr,     AS_HELP_STRING([--without-xattr],[do not use xattr (security attributes support)]))
 AC_ARG_WITH(xcomposite,AS_HELP_STRING([--without-xcomposite],[do not use the Xcomposite extension]),
             [if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xcomposite_h=no; fi])
 AC_ARG_WITH(xcursor,   AS_HELP_STRING([--without-xcursor],[do not use the Xcursor extension]),
@@ -697,6 +698,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
 #include <sys/socket.h>
 #endif])
 
+if test "x$with_xattr" != "xno"
+then
+    AC_CHECK_HEADERS(attr/xattr.h, [HAVE_XATTR=1])
+fi
+if test "x$with_xattr" = "xyes"
+then
+    WINE_ERROR_WITH(xattr,[test "x$HAVE_XATTR" = "x"],[xattr ${notice_platform}development files \
+not found. Wine will be built without extended attribute support, which probably isn't what you \
+want. You will need to install ${notice_platform}development packages of libattr at the very least.])
+fi
+
 dnl **** Check for working dll ****
 
 AC_SUBST(DLLFLAGS,"-D_REENTRANT")
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index bf435f109f1..6ac9b18da57 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -1448,6 +1448,22 @@ static BOOL append_entry( struct dir_data *data, const char *long_name,
 }
 
 
+/* 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 )
 {
@@ -1491,7 +1507,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 hexattr[11];
+    int len, ret;
 
     *attr = 0;
     ret = lstat( path, st );
@@ -1517,6 +1534,9 @@ static int get_file_info( const char *path, struct stat *st, ULONG *attr )
         free( parent_path );
     }
     *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 928730a41d7..4670891ae77 100644
--- a/include/wine/port.h
+++ b/include/wine/port.h
@@ -352,6 +352,15 @@ 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 );
+extern int xattr_get( const char *path, const char *name, void *value, size_t size );
+
 #else /* NO_LIBWINE_PORT */
 
 #define __WINE_NOT_PORTABLE(func) func##_is_not_portable func##_is_not_portable
diff --git a/libs/port/Makefile.in b/libs/port/Makefile.in
index 7bc67fa3fee..d1de285d527 100644
--- a/libs/port/Makefile.in
+++ b/libs/port/Makefile.in
@@ -21,4 +21,5 @@ C_SRCS = \
 	strnlen.c \
 	symlink.c \
 	usleep.c \
-	wctype.c
+	wctype.c \
+	xattr.c
diff --git a/libs/port/xattr.c b/libs/port/xattr.c
new file mode 100644
index 00000000000..88e900dac6d
--- /dev/null
+++ b/libs/port/xattr.c
@@ -0,0 +1,49 @@
+/*
+ * 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)
+# include <attr/xattr.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+
+int xattr_fget( int filedes, const char *name, void *value, size_t size )
+{
+#if defined(HAVE_ATTR_XATTR_H)
+    return fgetxattr( filedes, name, value, size );
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
+
+int xattr_get( const char *path, const char *name, void *value, size_t size )
+{
+#if defined(HAVE_ATTR_XATTR_H)
+    return getxattr( path, name, value, size );
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
-- 
2.27.0

