mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-21 00:07:36 +08:00
* autoload.cc (NtQueryEaFile): Define.
(NtSetEaFile): Define. * fhandler.cc (fhandler_base::open): Use appropriate open flags in query case when allow_ntea is set. * ntdll.h (struct _FILE_GET_EA_INFORMATION): Define. (struct _FILE_FULL_EA_INFORMATION): Define. (NtQueryEaFile): Declare. (NtSetEaFile): Declare. * ntea.cc (read_ea): Rename from NTReadEA and rewrite using NtQueryEaFile. (write_ea): Rename from NTWriteEA and rewrite using NtSetEaFile. * path.cc (get_symlink_ea): Make static. Add handle parameter to accomodate new read_ea call. (set_symlink_ea): Make static. Add handle parameter to accomodate new write_ea call. (symlink_worker): Call set_symlink_ea while file is still open. (symlink_info::check): Call get_symlink_ea after file has been opened. * security.cc (get_file_attribute): Accomodate new read_ea call. (set_file_attribute): Accomodate new write_ea call. * security.h (read_ea): Change declaration accordingly. (write_ea): Ditto.
This commit is contained in:
parent
e60e8d3b0e
commit
4635b6ebd8
@ -1,3 +1,27 @@
|
|||||||
|
2006-07-03 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* autoload.cc (NtQueryEaFile): Define.
|
||||||
|
(NtSetEaFile): Define.
|
||||||
|
* fhandler.cc (fhandler_base::open): Use appropriate open flags
|
||||||
|
in query case when allow_ntea is set.
|
||||||
|
* ntdll.h (struct _FILE_GET_EA_INFORMATION): Define.
|
||||||
|
(struct _FILE_FULL_EA_INFORMATION): Define.
|
||||||
|
(NtQueryEaFile): Declare.
|
||||||
|
(NtSetEaFile): Declare.
|
||||||
|
* ntea.cc (read_ea): Rename from NTReadEA and rewrite using
|
||||||
|
NtQueryEaFile.
|
||||||
|
(write_ea): Rename from NTWriteEA and rewrite using NtSetEaFile.
|
||||||
|
* path.cc (get_symlink_ea): Make static. Add handle parameter to
|
||||||
|
accomodate new read_ea call.
|
||||||
|
(set_symlink_ea): Make static. Add handle parameter to accomodate new
|
||||||
|
write_ea call.
|
||||||
|
(symlink_worker): Call set_symlink_ea while file is still open.
|
||||||
|
(symlink_info::check): Call get_symlink_ea after file has been opened.
|
||||||
|
* security.cc (get_file_attribute): Accomodate new read_ea call.
|
||||||
|
(set_file_attribute): Accomodate new write_ea call.
|
||||||
|
* security.h (read_ea): Change declaration accordingly.
|
||||||
|
(write_ea): Ditto.
|
||||||
|
|
||||||
2006-07-03 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
|
2006-07-03 Kazuhiro Fujieda <fujieda@jaist.ac.jp>
|
||||||
|
|
||||||
* fhandler.h (class dev_console): Add `metabit' indicating the
|
* fhandler.h (class dev_console): Add `metabit' indicating the
|
||||||
|
@ -392,6 +392,7 @@ LoadDLLfuncNt (NtOpenFile, 24, ntdll)
|
|||||||
LoadDLLfuncNt (NtOpenSection, 12, ntdll)
|
LoadDLLfuncNt (NtOpenSection, 12, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryDirectoryObject, 28, ntdll)
|
LoadDLLfuncNt (NtQueryDirectoryObject, 28, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryDirectoryFile, 44, ntdll)
|
LoadDLLfuncNt (NtQueryDirectoryFile, 44, ntdll)
|
||||||
|
LoadDLLfuncNt (NtQueryEaFile, 36, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryInformationFile, 20, ntdll)
|
LoadDLLfuncNt (NtQueryInformationFile, 20, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryInformationProcess, 20, ntdll)
|
LoadDLLfuncNt (NtQueryInformationProcess, 20, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryObject, 20, ntdll)
|
LoadDLLfuncNt (NtQueryObject, 20, ntdll)
|
||||||
@ -399,6 +400,7 @@ LoadDLLfuncNt (NtQuerySystemInformation, 16, ntdll)
|
|||||||
LoadDLLfuncNt (NtQuerySecurityObject, 20, ntdll)
|
LoadDLLfuncNt (NtQuerySecurityObject, 20, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryVirtualMemory, 24, ntdll)
|
LoadDLLfuncNt (NtQueryVirtualMemory, 24, ntdll)
|
||||||
LoadDLLfuncNt (NtQueryVolumeInformationFile, 20, ntdll)
|
LoadDLLfuncNt (NtQueryVolumeInformationFile, 20, ntdll)
|
||||||
|
LoadDLLfuncNt (NtSetEaFile, 16, ntdll)
|
||||||
LoadDLLfuncNt (NtSetSecurityObject, 12, ntdll)
|
LoadDLLfuncNt (NtSetSecurityObject, 12, ntdll)
|
||||||
LoadDLLfuncNt (NtUnlockVirtualMemory, 16, ntdll)
|
LoadDLLfuncNt (NtUnlockVirtualMemory, 16, ntdll)
|
||||||
LoadDLLfuncNt (NtUnmapViewOfSection, 8, ntdll)
|
LoadDLLfuncNt (NtUnmapViewOfSection, 8, ntdll)
|
||||||
|
@ -590,11 +590,13 @@ fhandler_base::open (int flags, mode_t mode)
|
|||||||
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
|
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
|
||||||
break;
|
break;
|
||||||
case query_stat_control:
|
case query_stat_control:
|
||||||
access = READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_DATA;
|
access = READ_CONTROL | FILE_READ_ATTRIBUTES
|
||||||
|
| (allow_ntea ? FILE_READ_EA : 0);
|
||||||
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
|
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
|
||||||
break;
|
break;
|
||||||
case query_write_control:
|
case query_write_control:
|
||||||
access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
|
access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES
|
||||||
|
| (allow_ntea ? FILE_WRITE_EA : 0);
|
||||||
create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
|
create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
|
||||||
break;
|
break;
|
||||||
case query_write_attributes:
|
case query_write_attributes:
|
||||||
|
@ -581,6 +581,23 @@ typedef struct _DIRECTORY_BASIC_INFORMATION
|
|||||||
UNICODE_STRING ObjectTypeName;
|
UNICODE_STRING ObjectTypeName;
|
||||||
} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
|
} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct _FILE_GET_EA_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
UCHAR EaNameLength;
|
||||||
|
CHAR EaName[1];
|
||||||
|
} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _FILE_FULL_EA_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
UCHAR Flags;
|
||||||
|
UCHAR EaNameLength;
|
||||||
|
USHORT EaValueLength;
|
||||||
|
CHAR EaName[1];
|
||||||
|
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
|
||||||
|
|
||||||
/* Function declarations for ntdll.dll. These don't appear in any
|
/* Function declarations for ntdll.dll. These don't appear in any
|
||||||
standard Win32 header. */
|
standard Win32 header. */
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -611,6 +628,8 @@ extern "C"
|
|||||||
PUNICODE_STRING, BOOLEAN);
|
PUNICODE_STRING, BOOLEAN);
|
||||||
NTSTATUS NTAPI NtQueryDirectoryObject (HANDLE, PVOID, ULONG, BOOLEAN,
|
NTSTATUS NTAPI NtQueryDirectoryObject (HANDLE, PVOID, ULONG, BOOLEAN,
|
||||||
BOOLEAN, PULONG, PULONG);
|
BOOLEAN, PULONG, PULONG);
|
||||||
|
NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
||||||
|
BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
|
||||||
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
|
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
|
||||||
ULONG, FILE_INFORMATION_CLASS);
|
ULONG, FILE_INFORMATION_CLASS);
|
||||||
NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS,
|
NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS,
|
||||||
@ -626,6 +645,7 @@ extern "C"
|
|||||||
NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *,
|
NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *,
|
||||||
VOID *, ULONG,
|
VOID *, ULONG,
|
||||||
FS_INFORMATION_CLASS);
|
FS_INFORMATION_CLASS);
|
||||||
|
NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG);
|
||||||
NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
|
NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
|
||||||
PSECURITY_DESCRIPTOR);
|
PSECURITY_DESCRIPTOR);
|
||||||
NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
|
NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* ntea.cc: code for manipulating NTEA information
|
/* ntea.cc: code for manipulating NTEA information
|
||||||
|
|
||||||
Copyright 1997, 1998, 2000, 2001 Red Hat, Inc.
|
Copyright 1997, 1998, 2000, 2001, 2006 Red Hat, Inc.
|
||||||
|
|
||||||
Written by Sergey S. Okhapkin (sos@prospect.com.ru)
|
Written by Sergey S. Okhapkin (sos@prospect.com.ru)
|
||||||
|
|
||||||
@ -11,315 +11,162 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|||||||
details. */
|
details. */
|
||||||
|
|
||||||
#include "winsup.h"
|
#include "winsup.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <ntdef.h>
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
|
#include "ntdll.h"
|
||||||
|
|
||||||
/* Default to not using NTEA information */
|
/* Default to not using NTEA information */
|
||||||
bool allow_ntea;
|
bool allow_ntea;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
From Windows NT DDK:
|
* read_ea - read file's Extended Attribute.
|
||||||
|
|
||||||
FILE_FULL_EA_INFORMATION provides extended attribute information.
|
|
||||||
This structure is used primarily by network drivers.
|
|
||||||
|
|
||||||
Members
|
|
||||||
|
|
||||||
NextEntryOffset
|
|
||||||
The offset of the next FILE_FULL_EA_INFORMATION-type entry. This member is
|
|
||||||
zero if no other entries follow this one.
|
|
||||||
|
|
||||||
Flags
|
|
||||||
Can be zero or can be set with FILE_NEED_EA, indicating that the file to which
|
|
||||||
the EA belongs cannot be interpreted without understanding the associated
|
|
||||||
extended attributes.
|
|
||||||
|
|
||||||
EaNameLength
|
|
||||||
The length in bytes of the EaName array. This value does not include a
|
|
||||||
zero-terminator to EaName.
|
|
||||||
|
|
||||||
EaValueLength
|
|
||||||
The length in bytes of each EA value in the array.
|
|
||||||
|
|
||||||
EaName
|
|
||||||
An array of characters naming the EA for this entry.
|
|
||||||
|
|
||||||
Comments
|
|
||||||
This structure is longword-aligned. If a set of FILE_FULL_EA_INFORMATION
|
|
||||||
entries is buffered, NextEntryOffset value in each entry, except the last,
|
|
||||||
falls on a longword boundary.
|
|
||||||
The value(s) associated with each entry follows the EaName array. That is, an
|
|
||||||
EA's values are located at EaName + (EaNameLength + 1).
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _FILE_FULL_EA_INFORMATION {
|
|
||||||
ULONG NextEntryOffset;
|
|
||||||
UCHAR Flags;
|
|
||||||
UCHAR EaNameLength;
|
|
||||||
USHORT EaValueLength;
|
|
||||||
CHAR EaName[1];
|
|
||||||
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
|
|
||||||
|
|
||||||
/* Functions prototypes */
|
|
||||||
|
|
||||||
int NTReadEA (const char *file, const char *attrname, char *buf, int len);
|
|
||||||
static PFILE_FULL_EA_INFORMATION NTReadEARaw (HANDLE file, int *len);
|
|
||||||
BOOL NTWriteEA(const char *file, const char *attrname, char *buf, int len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NTReadEA - read file's Extended Attribute.
|
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* file - pointer to filename
|
* file - pointer to filename
|
||||||
* attrname- pointer to EA name (case insensitivy. EAs are sored in upper
|
* attrname- pointer to EA name (case insensitiv)
|
||||||
* case).
|
|
||||||
* attrbuf - pointer to buffer to store EA's value.
|
* attrbuf - pointer to buffer to store EA's value.
|
||||||
* len - length of attrbuf.
|
* len - length of attrbuf.
|
||||||
* Return value:
|
* Return value:
|
||||||
* 0 - if file or attribute "attrname" not found.
|
* 0 - if file or attribute "attrname" not found.
|
||||||
* N - number of bytes stored in attrbuf if succes.
|
* N - number of bytes stored in attrbuf if success.
|
||||||
* -1 - attrbuf too small for EA value.
|
* -1 - attrbuf too small for EA value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int __stdcall
|
int __stdcall
|
||||||
NTReadEA (const char *file, const char *attrname, char *attrbuf, int len)
|
read_ea (HANDLE hdl, const char *file, const char *attrname, char *attrbuf,
|
||||||
|
int len)
|
||||||
{
|
{
|
||||||
HANDLE hFileSource;
|
IO_STATUS_BLOCK io;
|
||||||
int eafound = 0;
|
|
||||||
PFILE_FULL_EA_INFORMATION ea, sea;
|
|
||||||
int easize = 0;
|
|
||||||
|
|
||||||
hFileSource = CreateFile (file, FILE_READ_EA,
|
/* Prepare buffer which receives the result. */
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
ULONG flen = sizeof (FILE_FULL_EA_INFORMATION) + strlen (attrname)
|
||||||
&sec_none_nih, // sa
|
+ len + 1;
|
||||||
OPEN_EXISTING,
|
PFILE_FULL_EA_INFORMATION fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
|
||||||
FILE_FLAG_BACKUP_SEMANTICS,
|
/* Prepare buffer specifying the EA to search for. */
|
||||||
NULL);
|
ULONG glen = sizeof (FILE_GET_EA_INFORMATION) + strlen (attrname);
|
||||||
|
PFILE_GET_EA_INFORMATION gea = (PFILE_GET_EA_INFORMATION) alloca (glen);
|
||||||
|
gea->NextEntryOffset = 0;
|
||||||
|
gea->EaNameLength = strlen (attrname);
|
||||||
|
strcpy (gea->EaName, attrname);
|
||||||
|
|
||||||
if (hFileSource == INVALID_HANDLE_VALUE)
|
/* If no incoming hdl is given, the loop only runs once, trying to
|
||||||
return 0;
|
open the file and to query the EA. If an incoming hdl is given,
|
||||||
|
the loop runs twice, first trying to query with the given hdl.
|
||||||
/* Read in raw array of EAs */
|
If this fails it tries to open the file and to query with that
|
||||||
ea = sea = NTReadEARaw (hFileSource, &easize);
|
handle again. */
|
||||||
|
HANDLE h = hdl;
|
||||||
/* Search for requested attribute */
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
while (sea)
|
int ret = 0;
|
||||||
{
|
while (true)
|
||||||
if (strcasematch (ea->EaName, attrname)) /* EA found */
|
|
||||||
{
|
|
||||||
if (ea->EaValueLength > len)
|
|
||||||
{
|
|
||||||
eafound = -1; /* buffer too small */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy (attrbuf, ea->EaName + (ea->EaNameLength + 1),
|
|
||||||
ea->EaValueLength);
|
|
||||||
eafound = ea->EaValueLength;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((ea->NextEntryOffset == 0) || ((int) ea->NextEntryOffset > easize))
|
|
||||||
break;
|
|
||||||
ea = (PFILE_FULL_EA_INFORMATION) ((char *) ea + ea->NextEntryOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sea)
|
|
||||||
free (sea);
|
|
||||||
CloseHandle (hFileSource);
|
|
||||||
|
|
||||||
return eafound;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NTReadEARaw - internal routine to read EAs array to malloced buffer. The
|
|
||||||
* caller should free this buffer after usage.
|
|
||||||
* Parameters:
|
|
||||||
* hFileSource - handle to file. This handle should have FILE_READ_EA
|
|
||||||
* rights.
|
|
||||||
* len - pointer to int variable where length of buffer will
|
|
||||||
* be stored.
|
|
||||||
* Return value:
|
|
||||||
* pointer to buffer with file's EAs, or NULL if any error occured.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static PFILE_FULL_EA_INFORMATION
|
|
||||||
NTReadEARaw (HANDLE hFileSource, int *len)
|
|
||||||
{
|
|
||||||
WIN32_STREAM_ID StreamId;
|
|
||||||
DWORD dwBytesWritten;
|
|
||||||
LPVOID lpContext;
|
|
||||||
DWORD StreamSize;
|
|
||||||
PFILE_FULL_EA_INFORMATION eafound = NULL;
|
|
||||||
|
|
||||||
lpContext = NULL;
|
|
||||||
StreamSize = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**);
|
|
||||||
|
|
||||||
/* Read the WIN32_STREAM_ID in */
|
|
||||||
|
|
||||||
while (BackupRead (hFileSource, (LPBYTE) &StreamId, StreamSize,
|
|
||||||
&dwBytesWritten,
|
|
||||||
FALSE, // don't abort yet
|
|
||||||
FALSE, // don't process security
|
|
||||||
&lpContext))
|
|
||||||
{
|
{
|
||||||
DWORD sl,sh;
|
if (!hdl && (h = CreateFile (file, FILE_READ_EA,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
if (dwBytesWritten == 0) /* No more Stream IDs */
|
&sec_none_nih, OPEN_EXISTING,
|
||||||
break;
|
FILE_FLAG_BACKUP_SEMANTICS, NULL))
|
||||||
/* skip StreamName */
|
== INVALID_HANDLE_VALUE)
|
||||||
if (StreamId.dwStreamNameSize)
|
|
||||||
{
|
{
|
||||||
unsigned char *buf;
|
debug_printf ("Opening %s for querying EA %s failed, %E",
|
||||||
buf = (unsigned char *) malloc (StreamId.dwStreamNameSize);
|
file, attrname);
|
||||||
|
goto out;
|
||||||
if (buf == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!BackupRead (hFileSource, buf, // buffer to read
|
|
||||||
StreamId.dwStreamNameSize, // num bytes to read
|
|
||||||
&dwBytesWritten,
|
|
||||||
FALSE, // don't abort yet
|
|
||||||
FALSE, // don't process security
|
|
||||||
&lpContext)) // Stream name read error
|
|
||||||
{
|
|
||||||
free (buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free (buf);
|
|
||||||
}
|
}
|
||||||
|
status = NtQueryEaFile (h, &io, fea, flen, FALSE, gea, glen, NULL, TRUE);
|
||||||
/* Is it EA stream? */
|
if (NT_SUCCESS (status) || !hdl)
|
||||||
if (StreamId.dwStreamId == BACKUP_EA_DATA)
|
break;
|
||||||
{
|
debug_printf ("1. chance, %x = NtQueryEaFile (%s, %s), Win32 error %d",
|
||||||
unsigned char *buf;
|
status, file, attrname, RtlNtStatusToDosError (status));
|
||||||
buf = (unsigned char *) malloc (StreamId.Size.LowPart);
|
hdl = NULL;
|
||||||
|
}
|
||||||
if (buf == NULL)
|
if (!hdl)
|
||||||
break;
|
CloseHandle (h);
|
||||||
if (!BackupRead (hFileSource, buf, // buffer to read
|
if (!NT_SUCCESS (status))
|
||||||
StreamId.Size.LowPart, // num bytes to write
|
{
|
||||||
&dwBytesWritten,
|
ret = -1;
|
||||||
FALSE, // don't abort yet
|
debug_printf ("%x = NtQueryEaFile (%s, %s), Win32 error %d",
|
||||||
FALSE, // don't process security
|
status, file, attrname, RtlNtStatusToDosError (status));
|
||||||
&lpContext))
|
}
|
||||||
{
|
if (!fea->EaValueLength)
|
||||||
free (buf); /* EA read error */
|
ret = 0;
|
||||||
break;
|
else
|
||||||
}
|
{
|
||||||
eafound = (PFILE_FULL_EA_INFORMATION) buf;
|
memcpy (attrbuf, fea->EaName + fea->EaNameLength + 1,
|
||||||
*len = StreamId.Size.LowPart;
|
fea->EaValueLength);
|
||||||
break;
|
ret = fea->EaValueLength;
|
||||||
}
|
|
||||||
/* Skip current stream */
|
|
||||||
if (!BackupSeek (hFileSource,
|
|
||||||
StreamId.Size.LowPart,
|
|
||||||
StreamId.Size.HighPart,
|
|
||||||
&sl,
|
|
||||||
&sh,
|
|
||||||
&lpContext))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free context */
|
out:
|
||||||
BackupRead (
|
debug_printf ("%d = read_ea (%x, %s, %s, %x, %d)", ret, hdl, file, attrname,
|
||||||
hFileSource,
|
attrbuf, len);
|
||||||
NULL, // buffer to write
|
return ret;
|
||||||
0, // number of bytes to write
|
|
||||||
&dwBytesWritten,
|
|
||||||
TRUE, // abort
|
|
||||||
FALSE, // don't process security
|
|
||||||
&lpContext);
|
|
||||||
|
|
||||||
return eafound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NTWriteEA - write file's Extended Attribute.
|
* write_ea - write file's Extended Attribute.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* file - pointer to filename
|
* file - pointer to filename
|
||||||
* attrname- pointer to EA name (case insensitivy. EAs are sored in upper
|
* attrname- pointer to EA name (case insensitiv)
|
||||||
* case).
|
* attrbuf - pointer to buffer with EA value.
|
||||||
* buf - pointer to buffer with EA value.
|
* len - length of attrbuf.
|
||||||
* len - length of buf.
|
|
||||||
* Return value:
|
* Return value:
|
||||||
* true if success, false otherwice.
|
* true if success, false otherwice.
|
||||||
* Note: if len=0 given EA will be deleted.
|
* Note: if len=0 given EA will be deleted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL __stdcall
|
BOOL __stdcall
|
||||||
NTWriteEA (const char *file, const char *attrname, const char *buf, int len)
|
write_ea (HANDLE hdl, const char *file, const char *attrname,
|
||||||
|
const char *attrbuf, int len)
|
||||||
{
|
{
|
||||||
HANDLE hFileSource;
|
IO_STATUS_BLOCK io;
|
||||||
WIN32_STREAM_ID StreamId;
|
|
||||||
DWORD dwBytesWritten;
|
|
||||||
LPVOID lpContext;
|
|
||||||
DWORD StreamSize, easize;
|
|
||||||
bool bSuccess = false;
|
|
||||||
PFILE_FULL_EA_INFORMATION ea;
|
|
||||||
|
|
||||||
hFileSource = CreateFile (file, FILE_WRITE_EA,
|
/* Prepare buffer specifying the EA to write back. */
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
ULONG flen = sizeof (FILE_FULL_EA_INFORMATION) + strlen (attrname)
|
||||||
&sec_none_nih, // sa
|
+ len + 1;
|
||||||
OPEN_EXISTING,
|
PFILE_FULL_EA_INFORMATION fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
|
||||||
FILE_FLAG_BACKUP_SEMANTICS,
|
fea->NextEntryOffset = 0;
|
||||||
NULL);
|
fea->Flags = 0;
|
||||||
|
fea->EaNameLength = strlen (attrname);
|
||||||
|
fea->EaValueLength = len;
|
||||||
|
strcpy (fea->EaName, attrname);
|
||||||
|
memcpy (fea->EaName + fea->EaNameLength + 1, attrbuf, len);
|
||||||
|
|
||||||
if (hFileSource == INVALID_HANDLE_VALUE)
|
/* If no incoming hdl is given, the loop only runs once, trying to
|
||||||
return FALSE;
|
open the file and to set the EA. If an incoming hdl is given,
|
||||||
|
the loop runs twice, first trying to set the EA with the given hdl.
|
||||||
|
If this fails it tries to open the file and to set the EA with that
|
||||||
|
handle again. */
|
||||||
|
HANDLE h = hdl;
|
||||||
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
|
bool ret = false;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!hdl && (h = CreateFile (file, FILE_READ_EA,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
&sec_none_nih, OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS, NULL))
|
||||||
|
== INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
debug_printf ("Opening %s for setting EA %s failed, %E",
|
||||||
|
file, attrname);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
status = NtSetEaFile (h, &io, fea, flen);
|
||||||
|
if (NT_SUCCESS (status) || !hdl)
|
||||||
|
break;
|
||||||
|
debug_printf ("1. chance, %x = NtQueryEaFile (%s, %s), Win32 error %d",
|
||||||
|
status, file, attrname, RtlNtStatusToDosError (status));
|
||||||
|
hdl = NULL;
|
||||||
|
}
|
||||||
|
if (!hdl)
|
||||||
|
CloseHandle (h);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("%x = NtQueryEaFile (%s, %s), Win32 error %d",
|
||||||
|
status, file, attrname, RtlNtStatusToDosError (status));
|
||||||
|
else
|
||||||
|
ret = true;
|
||||||
|
|
||||||
lpContext = NULL;
|
out:
|
||||||
StreamSize = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**);
|
debug_printf ("%d = write_ea (%x, %s, %s, %x, %d)", ret, hdl, file, attrname,
|
||||||
|
attrbuf, len);
|
||||||
/* FILE_FULL_EA_INFORMATION structure is longword-aligned */
|
return ret;
|
||||||
easize = sizeof (*ea) - sizeof (WCHAR**) + strlen (attrname) + 1 + len
|
|
||||||
+ (sizeof (DWORD) - 1);
|
|
||||||
easize &= ~(sizeof (DWORD) - 1);
|
|
||||||
|
|
||||||
if ((ea = (PFILE_FULL_EA_INFORMATION) malloc (easize)) == NULL)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
memset (ea, 0, easize);
|
|
||||||
ea->EaNameLength = strlen (attrname);
|
|
||||||
ea->EaValueLength = len;
|
|
||||||
strcpy (ea->EaName, attrname);
|
|
||||||
memcpy (ea->EaName + (ea->EaNameLength + 1), buf, len);
|
|
||||||
|
|
||||||
StreamId.dwStreamId = BACKUP_EA_DATA;
|
|
||||||
StreamId.dwStreamAttributes = 0;
|
|
||||||
StreamId.Size.HighPart = 0;
|
|
||||||
StreamId.Size.LowPart = easize;
|
|
||||||
StreamId.dwStreamNameSize = 0;
|
|
||||||
|
|
||||||
if (!BackupWrite (hFileSource, (LPBYTE) &StreamId, StreamSize,
|
|
||||||
&dwBytesWritten,
|
|
||||||
FALSE, // don't abort yet
|
|
||||||
FALSE, // don't process security
|
|
||||||
&lpContext))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (!BackupWrite (hFileSource, (LPBYTE) ea, easize,
|
|
||||||
&dwBytesWritten,
|
|
||||||
FALSE, // don't abort yet
|
|
||||||
FALSE, // don't process security
|
|
||||||
&lpContext))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
bSuccess = true;
|
|
||||||
/* free context */
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
BackupRead (hFileSource,
|
|
||||||
NULL, // buffer to write
|
|
||||||
0, // number of bytes to write
|
|
||||||
&dwBytesWritten,
|
|
||||||
TRUE, // abort
|
|
||||||
FALSE, // don't process security
|
|
||||||
&lpContext);
|
|
||||||
|
|
||||||
CloseHandle (hFileSource);
|
|
||||||
if (ea)
|
|
||||||
free (ea);
|
|
||||||
|
|
||||||
return bSuccess;
|
|
||||||
}
|
}
|
||||||
|
@ -2694,20 +2694,20 @@ endmntent (FILE *)
|
|||||||
/********************** Symbolic Link Support **************************/
|
/********************** Symbolic Link Support **************************/
|
||||||
|
|
||||||
/* Read symlink from Extended Attribute */
|
/* Read symlink from Extended Attribute */
|
||||||
int
|
static int
|
||||||
get_symlink_ea (const char* frompath, char* buf, int buf_size)
|
get_symlink_ea (HANDLE hdl, const char* frompath, char* buf, int buf_size)
|
||||||
{
|
{
|
||||||
int res = NTReadEA (frompath, SYMLINK_EA_NAME, buf, buf_size);
|
int res = read_ea (hdl, frompath, SYMLINK_EA_NAME, buf, buf_size);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
debug_printf ("Cannot read symlink from EA");
|
debug_printf ("Cannot read symlink from EA");
|
||||||
return (res - 1);
|
return (res - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save symlink to Extended Attribute */
|
/* Save symlink to Extended Attribute */
|
||||||
bool
|
static bool
|
||||||
set_symlink_ea (const char* frompath, const char* topath)
|
set_symlink_ea (HANDLE hdl, const char* frompath, const char* topath)
|
||||||
{
|
{
|
||||||
if (!NTWriteEA (frompath, SYMLINK_EA_NAME, topath, strlen (topath) + 1))
|
if (!write_ea (hdl, frompath, SYMLINK_EA_NAME, topath, strlen (topath) + 1))
|
||||||
{
|
{
|
||||||
debug_printf ("Cannot save symlink in EA");
|
debug_printf ("Cannot save symlink in EA");
|
||||||
return false;
|
return false;
|
||||||
@ -2926,6 +2926,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
|
|||||||
}
|
}
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
if (!isdevice && win32_path.fs_has_ea ())
|
||||||
|
set_symlink_ea (h, win32_path, oldpath);
|
||||||
CloseHandle (h);
|
CloseHandle (h);
|
||||||
if (!allow_ntsec && allow_ntea)
|
if (!allow_ntsec && allow_ntea)
|
||||||
set_file_attribute (false, NULL, win32_path.get_win32 (),
|
set_file_attribute (false, NULL, win32_path.get_win32 (),
|
||||||
@ -2940,8 +2942,6 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
|
|||||||
#endif
|
#endif
|
||||||
SetFileAttributes (win32_path, attr);
|
SetFileAttributes (win32_path, attr);
|
||||||
|
|
||||||
if (!isdevice && win32_path.fs_has_ea ())
|
|
||||||
set_symlink_ea (win32_path, oldpath);
|
|
||||||
res = 0;
|
res = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3340,16 +3340,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
if (!sym_check)
|
if (!sym_check)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
if (sym_check > 0 && opt & PC_CHECK_EA &&
|
|
||||||
(res = get_symlink_ea (suffix.path, contents, sizeof (contents))) > 0)
|
|
||||||
{
|
|
||||||
pflags = PATH_SYMLINK | pflags_or;
|
|
||||||
if (sym_check == 1)
|
|
||||||
pflags |= PATH_LNK;
|
|
||||||
debug_printf ("Got symlink from EA: %s", contents);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open the file. */
|
/* Open the file. */
|
||||||
|
|
||||||
h = CreateFile (suffix.path, GENERIC_READ, FILE_SHARE_READ,
|
h = CreateFile (suffix.path, GENERIC_READ, FILE_SHARE_READ,
|
||||||
@ -3358,8 +3348,17 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
|||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
goto file_not_symlink;
|
goto file_not_symlink;
|
||||||
|
|
||||||
/* FIXME: if symlink isn't present in EA, but EAs are supported,
|
if (sym_check > 0 && opt & PC_CHECK_EA
|
||||||
should we write it there? */
|
&& (res = get_symlink_ea (h, suffix.path, contents,
|
||||||
|
sizeof (contents))) > 0)
|
||||||
|
{
|
||||||
|
pflags = PATH_SYMLINK | pflags_or;
|
||||||
|
if (sym_check == 1)
|
||||||
|
pflags |= PATH_LNK;
|
||||||
|
debug_printf ("Got symlink from EA: %s", contents);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sym_check)
|
switch (sym_check)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -1405,7 +1405,8 @@ get_file_attribute (int use_ntsec, HANDLE handle, const char *file,
|
|||||||
if (allow_ntea)
|
if (allow_ntea)
|
||||||
{
|
{
|
||||||
int oatt = *attribute;
|
int oatt = *attribute;
|
||||||
res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof (*attribute));
|
res = read_ea (handle, file, ".UNIXATTR", (char *)attribute,
|
||||||
|
sizeof (*attribute));
|
||||||
*attribute |= oatt;
|
*attribute |= oatt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1801,8 +1802,8 @@ set_file_attribute (bool use_ntsec, HANDLE handle, const char *file,
|
|||||||
|
|
||||||
if (use_ntsec && allow_ntsec)
|
if (use_ntsec && allow_ntsec)
|
||||||
ret = set_nt_attribute (handle, file, uid, gid, attribute);
|
ret = set_nt_attribute (handle, file, uid, gid, attribute);
|
||||||
else if (allow_ntea && !NTWriteEA (file, ".UNIXATTR", (char *) &attribute,
|
else if (allow_ntea && !write_ea (handle, file, ".UNIXATTR",
|
||||||
sizeof (attribute)))
|
(char *) &attribute, sizeof (attribute)))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -378,8 +378,10 @@ extern SECURITY_ATTRIBUTES *__stdcall __sec_user (PVOID sa_buf, PSID sid1, PSID
|
|||||||
extern bool sec_acl (PACL acl, bool original, bool admins, PSID sid1 = NO_SID,
|
extern bool sec_acl (PACL acl, bool original, bool admins, PSID sid1 = NO_SID,
|
||||||
PSID sid2 = NO_SID, DWORD access2 = 0);
|
PSID sid2 = NO_SID, DWORD access2 = 0);
|
||||||
|
|
||||||
int __stdcall NTReadEA (const char *file, const char *attrname, char *buf, int len);
|
int __stdcall read_ea (HANDLE hdl, const char *file, const char *attrname,
|
||||||
BOOL __stdcall NTWriteEA (const char *file, const char *attrname, const char *buf, int len);
|
char *buf, int len);
|
||||||
|
BOOL __stdcall write_ea (HANDLE hdl, const char *file, const char *attrname,
|
||||||
|
const char *buf, int len);
|
||||||
|
|
||||||
/* Note: sid1 is usually (read: currently always) the current user's
|
/* Note: sid1 is usually (read: currently always) the current user's
|
||||||
effective sid (cygheap->user.sid ()). */
|
effective sid (cygheap->user.sid ()). */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user