You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Added patch to implement DOS hidden/system file attributes.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
From 7922ba3b2a5414d30053821394962afed4e5b13c Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Tue, 19 Aug 2014 20:31:00 -0600
|
||||
Subject: ntdll: Unify retrieving the attributes of a file.
|
||||
|
||||
---
|
||||
dlls/ntdll/file.c | 25 +++++++++++++++++--------
|
||||
1 file changed, 17 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 92d9829..78c375a 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -1774,6 +1774,21 @@ static inline void get_file_times( const struct stat *st, LARGE_INTEGER *mtime,
|
||||
#endif
|
||||
}
|
||||
|
||||
+/* fetch the attributes of a file */
|
||||
+static inline ULONG get_file_attributes( const struct stat *st )
|
||||
+{
|
||||
+ ULONG attr;
|
||||
+
|
||||
+ if (S_ISDIR(st->st_mode))
|
||||
+ attr = FILE_ATTRIBUTE_DIRECTORY;
|
||||
+ else
|
||||
+ attr = FILE_ATTRIBUTE_ARCHIVE;
|
||||
+ if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||
+ attr |= FILE_ATTRIBUTE_READONLY;
|
||||
+ return attr;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* fill in the file information that depends on the stat info */
|
||||
NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class )
|
||||
{
|
||||
@@ -1785,10 +1800,7 @@ NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLAS
|
||||
|
||||
get_file_times( st, &info->LastWriteTime, &info->ChangeTime,
|
||||
&info->LastAccessTime, &info->CreationTime );
|
||||
- if (S_ISDIR(st->st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||
- else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
- if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||
- info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
||||
+ info->FileAttributes = get_file_attributes( st );
|
||||
}
|
||||
break;
|
||||
case FileStandardInformation:
|
||||
@@ -1842,16 +1854,13 @@ NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLAS
|
||||
{
|
||||
info->AllocationSize.QuadPart = 0;
|
||||
info->EndOfFile.QuadPart = 0;
|
||||
- info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->AllocationSize.QuadPart = (ULONGLONG)st->st_blocks * 512;
|
||||
info->EndOfFile.QuadPart = st->st_size;
|
||||
- info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
- if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||
- info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
|
||||
+ info->FileAttributes = get_file_attributes( st );
|
||||
}
|
||||
break;
|
||||
case FileIdFullDirectoryInformation:
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,408 @@
|
||||
From 07b0e6fe66d8ac19d7584f52a066d2957d858144 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: ntdll: Implement retrieving DOS attributes in
|
||||
NtQueryInformationFile.
|
||||
|
||||
---
|
||||
configure.ac | 12 +++++++
|
||||
dlls/ntdll/directory.c | 3 +-
|
||||
dlls/ntdll/file.c | 80 ++++++++++++++++++++++++++++++++++++-----------
|
||||
dlls/ntdll/ntdll_misc.h | 2 +-
|
||||
include/wine/port.h | 11 +++++++
|
||||
libs/port/Makefile.in | 3 +-
|
||||
libs/port/xattr.c | 61 ++++++++++++++++++++++++++++++++++++
|
||||
7 files changed, 150 insertions(+), 22 deletions(-)
|
||||
create mode 100644 libs/port/xattr.c
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 7de7a87..b77c12f 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -75,6 +75,7 @@ AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthrea
|
||||
AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)]))
|
||||
AC_ARG_WITH(tiff, AS_HELP_STRING([--without-tiff],[do not use TIFF]))
|
||||
AC_ARG_WITH(v4l, AS_HELP_STRING([--without-v4l],[do not use v4l1 (v4l support)]))
|
||||
+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]),
|
||||
@@ -667,6 +668,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
|
||||
#include <sys/socket.h>
|
||||
#endif])
|
||||
|
||||
+if test "x$with_xattr" != "xno"
|
||||
+then
|
||||
+ AC_CHECK_HEADERS(attr/xattr.h sys/xattr.h sys/extattr.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 libacl at the very least.])
|
||||
+fi
|
||||
+
|
||||
dnl **** Check for working dll ****
|
||||
|
||||
AC_SUBST(dlldir,"\${libdir}/wine")
|
||||
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
|
||||
index a2796b2..678aef5 100644
|
||||
--- a/dlls/ntdll/directory.c
|
||||
+++ b/dlls/ntdll/directory.c
|
||||
@@ -1381,6 +1381,7 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
WCHAR *filename;
|
||||
UNICODE_STRING str;
|
||||
ULONG attributes = 0;
|
||||
+ ULONG xattr = 0;
|
||||
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
long_len = ntdll_umbstowcs( 0, long_name, strlen(long_name), long_nameW, MAX_DIR_ENTRY_LEN );
|
||||
@@ -1440,7 +1441,7 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
info = (union file_directory_info *)((char *)info_ptr + io->Information);
|
||||
if (st.st_dev != curdir.dev) st.st_ino = 0; /* ignore inode if on a different device */
|
||||
/* all the structures start with a FileDirectoryInformation layout */
|
||||
- fill_stat_info( &st, info, class );
|
||||
+ fill_file_info( xattr, &st, info, class );
|
||||
info->dir.NextEntryOffset = total_len;
|
||||
info->dir.FileIndex = 0; /* NTFS always has 0 here, so let's not bother with it */
|
||||
info->dir.FileAttributes |= attributes;
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 78c375a..c8176dd 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -103,6 +103,41 @@ mode_t FILE_umask = 0;
|
||||
|
||||
static const WCHAR ntfsW[] = {'N','T','F','S'};
|
||||
|
||||
+/* Match the conventions as Samba 3 for storing DOS file attributes;
|
||||
+ * see {get,set}_ea_dos_attribute() in http://gitweb.samba.org/?p=samba.git;a=blob;f=source3/smbd/dosmode.c
|
||||
+ * In particular, encode FILE_ATTRIBUTE_* as the string 0x followed by one or two hexadecimal digits.
|
||||
+ * Differences from Samba 3:
|
||||
+ * Wine currently only stores hidden and system in xattrs;
|
||||
+ * Samba 3 also seems to store the readonly and directory bits.
|
||||
+ * Samba 4 additionally supports NT security descriptors with a different xattr
|
||||
+ */
|
||||
+#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)
|
||||
+
|
||||
+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;
|
||||
+}
|
||||
+
|
||||
+int fd_get_file_info( int fd, struct stat *st, ULONG *xattr )
|
||||
+{
|
||||
+ int len, ret = fstat( fd, st );
|
||||
+ char hexattr[10];
|
||||
+
|
||||
+ *xattr = 0;
|
||||
+ if (ret == -1) return ret;
|
||||
+ len = xattr_fget( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 );
|
||||
+ if (len == -1) return ret;
|
||||
+ *xattr |= get_file_xattr( hexattr, len );
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**************************************************************************
|
||||
* FILE_CreateFile (internal)
|
||||
* Open a file.
|
||||
@@ -1775,7 +1810,7 @@ static inline void get_file_times( const struct stat *st, LARGE_INTEGER *mtime,
|
||||
}
|
||||
|
||||
/* fetch the attributes of a file */
|
||||
-static inline ULONG get_file_attributes( const struct stat *st )
|
||||
+static inline ULONG get_file_attributes( const ULONG xattr, const struct stat *st )
|
||||
{
|
||||
ULONG attr;
|
||||
|
||||
@@ -1783,6 +1818,10 @@ static inline ULONG get_file_attributes( const struct stat *st )
|
||||
attr = FILE_ATTRIBUTE_DIRECTORY;
|
||||
else
|
||||
attr = FILE_ATTRIBUTE_ARCHIVE;
|
||||
+
|
||||
+ /* if any extended attributes exist then add them to the traditional attributes */
|
||||
+ attr |= xattr;
|
||||
+
|
||||
if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||
attr |= FILE_ATTRIBUTE_READONLY;
|
||||
return attr;
|
||||
@@ -1790,7 +1829,7 @@ static inline ULONG get_file_attributes( const struct stat *st )
|
||||
|
||||
|
||||
/* fill in the file information that depends on the stat info */
|
||||
-NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class )
|
||||
+NTSTATUS fill_file_info( const ULONG xattr, const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class )
|
||||
{
|
||||
switch (class)
|
||||
{
|
||||
@@ -1800,7 +1839,7 @@ NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLAS
|
||||
|
||||
get_file_times( st, &info->LastWriteTime, &info->ChangeTime,
|
||||
&info->LastAccessTime, &info->CreationTime );
|
||||
- info->FileAttributes = get_file_attributes( st );
|
||||
+ info->FileAttributes = get_file_attributes( xattr, st );
|
||||
}
|
||||
break;
|
||||
case FileStandardInformation:
|
||||
@@ -1836,9 +1875,9 @@ NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLAS
|
||||
case FileAllInformation:
|
||||
{
|
||||
FILE_ALL_INFORMATION *info = ptr;
|
||||
- fill_stat_info( st, &info->BasicInformation, FileBasicInformation );
|
||||
- fill_stat_info( st, &info->StandardInformation, FileStandardInformation );
|
||||
- fill_stat_info( st, &info->InternalInformation, FileInternalInformation );
|
||||
+ fill_file_info( xattr, st, &info->BasicInformation, FileBasicInformation );
|
||||
+ fill_file_info( xattr, st, &info->StandardInformation, FileStandardInformation );
|
||||
+ fill_file_info( xattr, st, &info->InternalInformation, FileInternalInformation );
|
||||
}
|
||||
break;
|
||||
/* all directory structures start with the FileDirectoryInformation layout */
|
||||
@@ -1860,21 +1899,21 @@ NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLAS
|
||||
info->AllocationSize.QuadPart = (ULONGLONG)st->st_blocks * 512;
|
||||
info->EndOfFile.QuadPart = st->st_size;
|
||||
}
|
||||
- info->FileAttributes = get_file_attributes( st );
|
||||
+ info->FileAttributes = get_file_attributes( xattr, st );
|
||||
}
|
||||
break;
|
||||
case FileIdFullDirectoryInformation:
|
||||
{
|
||||
FILE_ID_FULL_DIRECTORY_INFORMATION *info = ptr;
|
||||
info->FileId.QuadPart = st->st_ino;
|
||||
- fill_stat_info( st, info, FileDirectoryInformation );
|
||||
+ fill_file_info( xattr, st, info, FileDirectoryInformation );
|
||||
}
|
||||
break;
|
||||
case FileIdBothDirectoryInformation:
|
||||
{
|
||||
FILE_ID_BOTH_DIRECTORY_INFORMATION *info = ptr;
|
||||
info->FileId.QuadPart = st->st_ino;
|
||||
- fill_stat_info( st, info, FileDirectoryInformation );
|
||||
+ fill_file_info( xattr, st, info, FileDirectoryInformation );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2026,6 +2065,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
|
||||
struct stat st;
|
||||
int fd, needs_close = FALSE;
|
||||
+ ULONG xattr;
|
||||
|
||||
TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", hFile, io, ptr, len, class);
|
||||
|
||||
@@ -2050,12 +2090,12 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
switch (class)
|
||||
{
|
||||
case FileBasicInformation:
|
||||
- if (fstat( fd, &st ) == -1)
|
||||
+ if (fd_get_file_info( fd, &st, &xattr ) == -1)
|
||||
io->u.Status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
io->u.Status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
- fill_stat_info( &st, ptr, class );
|
||||
+ fill_file_info( xattr, &st, ptr, class );
|
||||
break;
|
||||
case FileStandardInformation:
|
||||
{
|
||||
@@ -2064,7 +2104,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else
|
||||
{
|
||||
- fill_stat_info( &st, info, class );
|
||||
+ fill_file_info( xattr, &st, info, class );
|
||||
info->DeletePending = FALSE; /* FIXME */
|
||||
}
|
||||
}
|
||||
@@ -2079,7 +2119,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
break;
|
||||
case FileInternalInformation:
|
||||
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
- else fill_stat_info( &st, ptr, class );
|
||||
+ else fill_file_info( xattr, &st, ptr, class );
|
||||
break;
|
||||
case FileEaInformation:
|
||||
{
|
||||
@@ -2089,21 +2129,21 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
|
||||
break;
|
||||
case FileEndOfFileInformation:
|
||||
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
- else fill_stat_info( &st, ptr, class );
|
||||
+ else fill_file_info( xattr, &st, ptr, class );
|
||||
break;
|
||||
case FileAllInformation:
|
||||
{
|
||||
FILE_ALL_INFORMATION *info = ptr;
|
||||
ANSI_STRING unix_name;
|
||||
|
||||
- if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
+ if (fd_get_file_info( fd, &st, &xattr ) == -1) io->u.Status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
io->u.Status = STATUS_INVALID_INFO_CLASS;
|
||||
else if (!(io->u.Status = server_get_unix_name( hFile, &unix_name )))
|
||||
{
|
||||
LONG name_len = len - FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName);
|
||||
|
||||
- fill_stat_info( &st, info, FileAllInformation );
|
||||
+ fill_file_info( xattr, &st, info, FileAllInformation );
|
||||
info->StandardInformation.DeletePending = FALSE; /* FIXME */
|
||||
info->EaInformation.EaSize = 0;
|
||||
info->AccessInformation.AccessFlags = 0; /* FIXME */
|
||||
@@ -2455,6 +2495,7 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
struct stat st;
|
||||
+ ULONG xattr = 0;
|
||||
|
||||
if (stat( unix_name.Buffer, &st ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
@@ -2465,8 +2506,8 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||
FILE_BASIC_INFORMATION basic;
|
||||
FILE_STANDARD_INFORMATION std;
|
||||
|
||||
- fill_stat_info( &st, &basic, FileBasicInformation );
|
||||
- fill_stat_info( &st, &std, FileStandardInformation );
|
||||
+ fill_file_info( xattr, &st, &basic, FileBasicInformation );
|
||||
+ fill_file_info( xattr, &st, &std, FileStandardInformation );
|
||||
|
||||
info->CreationTime = basic.CreationTime;
|
||||
info->LastAccessTime = basic.LastAccessTime;
|
||||
@@ -2497,6 +2538,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
||||
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
struct stat st;
|
||||
+ ULONG xattr = 0;
|
||||
|
||||
if (stat( unix_name.Buffer, &st ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
@@ -2504,7 +2546,7 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
else
|
||||
{
|
||||
- status = fill_stat_info( &st, info, FileBasicInformation );
|
||||
+ status = fill_file_info( xattr, &st, info, FileBasicInformation );
|
||||
if (DIR_is_hidden_file( attr->ObjectName ))
|
||||
info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index 4370084..ec96427 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -148,7 +148,7 @@ extern NTSTATUS COMM_FlushBuffersFile( int fd ) DECLSPEC_HIDDEN;
|
||||
/* file I/O */
|
||||
struct stat;
|
||||
extern NTSTATUS FILE_GetNtStatus(void) DECLSPEC_HIDDEN;
|
||||
-extern NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class ) DECLSPEC_HIDDEN;
|
||||
+extern NTSTATUS fill_file_info( ULONG xattr, const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
|
||||
extern void DIR_init_windows_dir( const WCHAR *windir, const WCHAR *sysdir ) DECLSPEC_HIDDEN;
|
||||
extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name ) DECLSPEC_HIDDEN;
|
||||
diff --git a/include/wine/port.h b/include/wine/port.h
|
||||
index 3548a44..715a9e2 100644
|
||||
--- a/include/wine/port.h
|
||||
+++ b/include/wine/port.h
|
||||
@@ -363,6 +363,17 @@ extern int mkstemps(char *template, int suffix_len);
|
||||
extern int _spawnvp(int mode, const char *cmdname, const char * const argv[]);
|
||||
#endif
|
||||
|
||||
+/* Extended attribute functions */
|
||||
+
|
||||
+#ifndef XATTR_USER_PREFIX
|
||||
+#define XATTR_USER_PREFIX "user."
|
||||
+#endif
|
||||
+#ifndef XATTR_USER_PREFIX_LEN
|
||||
+#define XATTR_USER_PREFIX_LEN (sizeof(XATTR_USER_PREFIX) - 1)
|
||||
+#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 65f1714..67efbc7 100644
|
||||
--- a/libs/port/Makefile.in
|
||||
+++ b/libs/port/Makefile.in
|
||||
@@ -23,4 +23,5 @@ C_SRCS = \
|
||||
strerror.c \
|
||||
strncasecmp.c \
|
||||
symlink.c \
|
||||
- usleep.c
|
||||
+ usleep.c \
|
||||
+ xattr.c
|
||||
diff --git a/libs/port/xattr.c b/libs/port/xattr.c
|
||||
new file mode 100644
|
||||
index 0000000..8b64867
|
||||
--- /dev/null
|
||||
+++ b/libs/port/xattr.c
|
||||
@@ -0,0 +1,61 @@
|
||||
+/*
|
||||
+ * 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"
|
||||
+
|
||||
+#ifdef HAVE_SYS_XATTR_H
|
||||
+# include <sys/xattr.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_ATTR_XATTR_H
|
||||
+# include <attr/xattr.h>
|
||||
+#endif
|
||||
+#ifdef HAVE_SYS_EXTATTR_H
|
||||
+# include <sys/extattr.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <ctype.h>
|
||||
+#include <errno.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;
|
||||
+}
|
||||
+
|
||||
+int xattr_fget( int filedes, const char *name, void *value, size_t size )
|
||||
+{
|
||||
+ if (!xattr_valid_namespace( name )) return -1;
|
||||
+#if defined(HAVE_ATTR_XATTR_H)
|
||||
+ return fgetxattr( filedes, name, value, size );
|
||||
+#elif defined(HAVE_SYS_XATTR_H)
|
||||
+ return fgetxattr( filedes, name, value, size, 0, 0 );
|
||||
+#elif defined(HAVE_SYS_EXTATTR_H)
|
||||
+ return extattr_get_fd( filedes, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN],
|
||||
+ value, size );
|
||||
+#else
|
||||
+ errno = ENOTSUP;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,106 @@
|
||||
From aca454765b4a1cd8b7a50761fb0bd9f82043b895 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 20 Aug 2014 16:04:34 -0600
|
||||
Subject: ntdll: Implement retrieving DOS attributes in
|
||||
NtQuery[Full]AttributesFile.
|
||||
|
||||
---
|
||||
dlls/ntdll/file.c | 28 ++++++++++++++++++++++++----
|
||||
include/wine/port.h | 1 +
|
||||
libs/port/xattr.c | 16 ++++++++++++++++
|
||||
3 files changed, 41 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index c8176dd..8b2f398 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -138,6 +138,26 @@ int fd_get_file_info( int fd, struct stat *st, ULONG *xattr )
|
||||
return ret;
|
||||
}
|
||||
|
||||
+int get_file_info( const char *path, struct stat *st, ULONG *xattr )
|
||||
+{
|
||||
+ char hexattr[10];
|
||||
+ int len, ret;
|
||||
+
|
||||
+ *xattr = 0;
|
||||
+ ret = lstat( path, st );
|
||||
+ if (ret == -1) return ret;
|
||||
+ if (S_ISLNK( st->st_mode ))
|
||||
+ {
|
||||
+ ret = stat( path, st );
|
||||
+ if (ret == -1) return ret;
|
||||
+ if (S_ISDIR( st->st_mode )) *xattr |= FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
+ }
|
||||
+ len = xattr_get( path, SAMBA_XATTR_DOS_ATTRIB, hexattr, sizeof(hexattr)-1 );
|
||||
+ if (len == -1) return ret;
|
||||
+ *xattr |= get_file_xattr( hexattr, len );
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/**************************************************************************
|
||||
* FILE_CreateFile (internal)
|
||||
* Open a file.
|
||||
@@ -2495,9 +2515,9 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
|
||||
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
struct stat st;
|
||||
- ULONG xattr = 0;
|
||||
+ ULONG xattr;
|
||||
|
||||
- if (stat( unix_name.Buffer, &st ) == -1)
|
||||
+ if (get_file_info( unix_name.Buffer, &st, &xattr ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
@@ -2538,9 +2558,9 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
||||
if (!(status = nt_to_unix_file_name_attr( attr, &unix_name, FILE_OPEN )))
|
||||
{
|
||||
struct stat st;
|
||||
- ULONG xattr = 0;
|
||||
+ ULONG xattr;
|
||||
|
||||
- if (stat( unix_name.Buffer, &st ) == -1)
|
||||
+ if (get_file_info( unix_name.Buffer, &st, &xattr ) == -1)
|
||||
status = FILE_GetNtStatus();
|
||||
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||
status = STATUS_INVALID_INFO_CLASS;
|
||||
diff --git a/include/wine/port.h b/include/wine/port.h
|
||||
index 715a9e2..7d8ea1a 100644
|
||||
--- a/include/wine/port.h
|
||||
+++ b/include/wine/port.h
|
||||
@@ -373,6 +373,7 @@ extern int _spawnvp(int mode, const char *cmdname, const char * const argv[]);
|
||||
#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 8b64867..0d77ce3 100644
|
||||
--- a/libs/port/xattr.c
|
||||
+++ b/libs/port/xattr.c
|
||||
@@ -59,3 +59,19 @@ 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 (!xattr_valid_namespace( name )) return -1;
|
||||
+#if defined(HAVE_ATTR_XATTR_H)
|
||||
+ return getxattr( path, name, value, size );
|
||||
+#elif defined(HAVE_SYS_XATTR_H)
|
||||
+ return getxattr( path, name, value, size, 0, 0 );
|
||||
+#elif defined(HAVE_SYS_EXTATTR_H)
|
||||
+ return extattr_get_file( path, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN],
|
||||
+ value, size );
|
||||
+#else
|
||||
+ errno = ENOTSUP;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,52 @@
|
||||
From 2e97bfb51b37d8b3bd85a486b706bb1608ebd132 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 20 Aug 2014 16:05:38 -0600
|
||||
Subject: ntdll: Implement retrieving DOS attributes in NtQueryDirectoryFile.
|
||||
|
||||
---
|
||||
dlls/ntdll/directory.c | 9 ++-------
|
||||
dlls/ntdll/ntdll_misc.h | 1 +
|
||||
2 files changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
|
||||
index 678aef5..9fb4b87 100644
|
||||
--- a/dlls/ntdll/directory.c
|
||||
+++ b/dlls/ntdll/directory.c
|
||||
@@ -1381,7 +1381,7 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
WCHAR *filename;
|
||||
UNICODE_STRING str;
|
||||
ULONG attributes = 0;
|
||||
- ULONG xattr = 0;
|
||||
+ ULONG xattr;
|
||||
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
long_len = ntdll_umbstowcs( 0, long_name, strlen(long_name), long_nameW, MAX_DIR_ENTRY_LEN );
|
||||
@@ -1418,12 +1418,7 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
if (!match_filename( &str, mask )) return NULL;
|
||||
}
|
||||
|
||||
- if (lstat( long_name, &st ) == -1) return NULL;
|
||||
- if (S_ISLNK( st.st_mode ))
|
||||
- {
|
||||
- if (stat( long_name, &st ) == -1) return NULL;
|
||||
- if (S_ISDIR( st.st_mode )) attributes |= FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
- }
|
||||
+ if (get_file_info( long_name, &st, &xattr ) == -1) return NULL;
|
||||
if (is_ignored_file( &st ))
|
||||
{
|
||||
TRACE( "ignoring file %s\n", long_name );
|
||||
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||
index ec96427..226bc85 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -148,6 +148,7 @@ extern NTSTATUS COMM_FlushBuffersFile( int fd ) DECLSPEC_HIDDEN;
|
||||
/* file I/O */
|
||||
struct stat;
|
||||
extern NTSTATUS FILE_GetNtStatus(void) DECLSPEC_HIDDEN;
|
||||
+extern int get_file_info( const char *path, struct stat *st, ULONG *xattr ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS fill_file_info( ULONG xattr, const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
|
||||
extern void DIR_init_windows_dir( const WCHAR *windir, const WCHAR *sysdir ) DECLSPEC_HIDDEN;
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,185 @@
|
||||
From 1313cd2f5b09593702acd6d71187afdd50ccea4d Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 20 Aug 2014 00:08:52 -0600
|
||||
Subject: ntdll: Implement storing DOS attributes in NtSetInformationFile.
|
||||
|
||||
---
|
||||
dlls/ntdll/file.c | 50 ++++++++++++++++++++++++++++-------------------
|
||||
dlls/ntdll/tests/file.c | 8 ++++----
|
||||
include/wine/port.h | 2 ++
|
||||
libs/port/xattr.c | 31 +++++++++++++++++++++++++++++
|
||||
4 files changed, 67 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 8b2f398..1294888 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -138,6 +138,35 @@ int fd_get_file_info( int fd, struct stat *st, ULONG *xattr )
|
||||
return ret;
|
||||
}
|
||||
|
||||
+NTSTATUS fd_set_file_info( int fd, ULONG attr )
|
||||
+{
|
||||
+ char hexattr[10];
|
||||
+ struct stat st;
|
||||
+ int len;
|
||||
+
|
||||
+ 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 */
|
||||
+ len = sprintf( hexattr, "0x%x", attr );
|
||||
+ if (attr != 0)
|
||||
+ xattr_fset( fd, SAMBA_XATTR_DOS_ATTRIB, hexattr, len );
|
||||
+ else
|
||||
+ xattr_fremove( fd, SAMBA_XATTR_DOS_ATTRIB );
|
||||
+ return STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
int get_file_info( const char *path, struct stat *st, ULONG *xattr )
|
||||
{
|
||||
char hexattr[10];
|
||||
@@ -2324,7 +2353,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 )))
|
||||
@@ -2334,25 +2362,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 d70ed6b..7a8e5d4 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -1234,7 +1234,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));
|
||||
@@ -1247,7 +1247,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));
|
||||
@@ -1304,7 +1304,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));
|
||||
@@ -1317,7 +1317,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 7d8ea1a..af052da 100644
|
||||
--- a/include/wine/port.h
|
||||
+++ b/include/wine/port.h
|
||||
@@ -373,6 +373,8 @@ extern int _spawnvp(int mode, const char *cmdname, const char * const argv[]);
|
||||
#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 0d77ce3..2668cf9 100644
|
||||
--- a/libs/port/xattr.c
|
||||
+++ b/libs/port/xattr.c
|
||||
@@ -60,6 +60,37 @@ int xattr_fget( int filedes, const char *name, void *value, size_t size )
|
||||
#endif
|
||||
}
|
||||
|
||||
+int xattr_fremove( int filedes, const char *name )
|
||||
+{
|
||||
+ if (!xattr_valid_namespace( name )) return -1;
|
||||
+#if defined(HAVE_ATTR_XATTR_H)
|
||||
+ return fremovexattr( filedes, name );
|
||||
+#elif defined(HAVE_SYS_XATTR_H)
|
||||
+ return fremovexattr( filedes, name, 0 );
|
||||
+#elif defined(HAVE_SYS_EXTATTR_H)
|
||||
+ return extattr_delete_fd( filedes, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN] );
|
||||
+#else
|
||||
+ errno = ENOTSUP;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+int xattr_fset( int filedes, const char *name, void *value, size_t size )
|
||||
+{
|
||||
+ if (!xattr_valid_namespace( name )) return -1;
|
||||
+#if defined(HAVE_ATTR_XATTR_H)
|
||||
+ return fsetxattr( filedes, name, value, size, 0 );
|
||||
+#elif defined(HAVE_SYS_XATTR_H)
|
||||
+ return fsetxattr( filedes, name, value, size, 0, 0 );
|
||||
+#elif defined(HAVE_SYS_EXTATTR_H)
|
||||
+ return extattr_set_fd( filedes, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN],
|
||||
+ value, size );
|
||||
+#else
|
||||
+ errno = ENOTSUP;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
int xattr_get( const char *path, const char *name, void *value, size_t size )
|
||||
{
|
||||
if (!xattr_valid_namespace( name )) return -1;
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,237 @@
|
||||
From f9c827c6a03c5741aebdcada20d512c9ceb44284 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 20 Aug 2014 15:28:00 -0600
|
||||
Subject: ntdll: Implement storing DOS attributes in NtCreateFile.
|
||||
|
||||
---
|
||||
dlls/ntdll/file.c | 80 ++++++++++++++++++++++++++----------------
|
||||
dlls/ntdll/tests/directory.c | 22 +++++-------
|
||||
include/wine/port.h | 2 ++
|
||||
libs/port/xattr.c | 31 ++++++++++++++++
|
||||
4 files changed, 91 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 1294888..6c278eb 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -187,6 +187,21 @@ int get_file_info( const char *path, struct stat *st, ULONG *xattr )
|
||||
return ret;
|
||||
}
|
||||
|
||||
+NTSTATUS set_file_info( const char *path, ULONG attr )
|
||||
+{
|
||||
+ char hexattr[10];
|
||||
+ 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.
|
||||
@@ -198,6 +213,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;
|
||||
|
||||
@@ -240,40 +257,37 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
|
||||
created = TRUE;
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
}
|
||||
-
|
||||
- if (io->u.Status == STATUS_SUCCESS)
|
||||
+ else 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)
|
||||
{
|
||||
@@ -295,6 +309,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)
|
||||
{
|
||||
@@ -302,6 +321,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 af052da..f989731 100644
|
||||
--- a/include/wine/port.h
|
||||
+++ b/include/wine/port.h
|
||||
@@ -376,6 +376,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 2668cf9..3093ecf 100644
|
||||
--- a/libs/port/xattr.c
|
||||
+++ b/libs/port/xattr.c
|
||||
@@ -106,3 +106,34 @@ 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 (!xattr_valid_namespace( name )) return -1;
|
||||
+#if defined(HAVE_ATTR_XATTR_H)
|
||||
+ return removexattr( path, name );
|
||||
+#elif defined(HAVE_SYS_XATTR_H)
|
||||
+ return removexattr( path, name, 0 );
|
||||
+#elif defined(HAVE_SYS_EXTATTR_H)
|
||||
+ return extattr_delete_file( path, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN] );
|
||||
+#else
|
||||
+ errno = ENOTSUP;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+int xattr_set( const char *path, const char *name, void *value, size_t size )
|
||||
+{
|
||||
+ if (!xattr_valid_namespace( name )) return -1;
|
||||
+#if defined(HAVE_ATTR_XATTR_H)
|
||||
+ return setxattr( path, name, value, size, 0 );
|
||||
+#elif defined(HAVE_SYS_XATTR_H)
|
||||
+ return setxattr( path, name, value, size, 0, 0 );
|
||||
+#elif defined(HAVE_SYS_EXTATTR_H)
|
||||
+ return extattr_set_file( path, EXTATTR_NAMESPACE_USER, &name[XATTR_USER_PREFIX_LEN],
|
||||
+ value, size );
|
||||
+#else
|
||||
+ errno = ENOTSUP;
|
||||
+ return -1;
|
||||
+#endif
|
||||
+}
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,115 @@
|
||||
From 398cf0a70a0d313bf84c4ff8335f49ca68e1ee84 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Wed, 20 Aug 2014 11:26:48 -0600
|
||||
Subject: ntdll: Perform the Unix-style hidden file check within the unified
|
||||
file info grabbing routine.
|
||||
|
||||
---
|
||||
dlls/ntdll/directory.c | 15 +++++----------
|
||||
dlls/ntdll/file.c | 8 ++------
|
||||
dlls/ntdll/ntdll_misc.h | 2 +-
|
||||
3 files changed, 8 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
|
||||
index 9fb4b87..726af4d 100644
|
||||
--- a/dlls/ntdll/directory.c
|
||||
+++ b/dlls/ntdll/directory.c
|
||||
@@ -1198,17 +1198,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;
|
||||
@@ -1380,7 +1380,6 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
WCHAR short_nameW[12];
|
||||
WCHAR *filename;
|
||||
UNICODE_STRING str;
|
||||
- ULONG attributes = 0;
|
||||
ULONG xattr;
|
||||
|
||||
io->u.Status = STATUS_SUCCESS;
|
||||
@@ -1424,9 +1423,6 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
TRACE( "ignoring file %s\n", long_name );
|
||||
return NULL;
|
||||
}
|
||||
- if (!show_dot_files && long_name[0] == '.' && long_name[1] && (long_name[1] != '.' || long_name[2]))
|
||||
- attributes |= FILE_ATTRIBUTE_HIDDEN;
|
||||
-
|
||||
total_len = dir_info_size( class, long_len );
|
||||
if (io->Information + total_len > max_length)
|
||||
{
|
||||
@@ -1439,7 +1435,6 @@ static union file_directory_info *append_entry( void *info_ptr, IO_STATUS_BLOCK
|
||||
fill_file_info( xattr, &st, info, class );
|
||||
info->dir.NextEntryOffset = total_len;
|
||||
info->dir.FileIndex = 0; /* NTFS always has 0 here, so let's not bother with it */
|
||||
- info->dir.FileAttributes |= attributes;
|
||||
|
||||
switch (class)
|
||||
{
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 6c278eb..91f96ee 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -173,6 +173,8 @@ int get_file_info( const char *path, struct stat *st, ULONG *xattr )
|
||||
int len, ret;
|
||||
|
||||
*xattr = 0;
|
||||
+ if (DIR_is_hidden_file( path ))
|
||||
+ *xattr |= FILE_ATTRIBUTE_HIDDEN;
|
||||
ret = lstat( path, st );
|
||||
if (ret == -1) return ret;
|
||||
if (S_ISLNK( st->st_mode ))
|
||||
@@ -2566,8 +2568,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 );
|
||||
}
|
||||
@@ -2595,11 +2595,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( xattr, &st, 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 226bc85..be07d59 100644
|
||||
--- a/dlls/ntdll/ntdll_misc.h
|
||||
+++ b/dlls/ntdll/ntdll_misc.h
|
||||
@@ -152,7 +152,7 @@ extern int get_file_info( const char *path, struct stat *st, ULONG *xattr ) DECL
|
||||
extern NTSTATUS fill_file_info( ULONG xattr, const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
|
||||
extern void DIR_init_windows_dir( const WCHAR *windir, const WCHAR *sysdir ) 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;
|
||||
--
|
||||
1.7.9.5
|
||||
|
4
patches/ntdll-DOS_Attributes/definition
Normal file
4
patches/ntdll-DOS_Attributes/definition
Normal file
@@ -0,0 +1,4 @@
|
||||
Author: Erich E. Hoover
|
||||
Subject: Implement DOS hidden/system file attributes
|
||||
Revision: 1
|
||||
Fixes: [9158] Support for DOS hidden/system file attributes
|
Reference in New Issue
Block a user