mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-18 15:09:32 +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>
|
||||
|
||||
* fhandler.h (class dev_console): Add `metabit' indicating the
|
||||
|
@ -392,6 +392,7 @@ LoadDLLfuncNt (NtOpenFile, 24, ntdll)
|
||||
LoadDLLfuncNt (NtOpenSection, 12, ntdll)
|
||||
LoadDLLfuncNt (NtQueryDirectoryObject, 28, ntdll)
|
||||
LoadDLLfuncNt (NtQueryDirectoryFile, 44, ntdll)
|
||||
LoadDLLfuncNt (NtQueryEaFile, 36, ntdll)
|
||||
LoadDLLfuncNt (NtQueryInformationFile, 20, ntdll)
|
||||
LoadDLLfuncNt (NtQueryInformationProcess, 20, ntdll)
|
||||
LoadDLLfuncNt (NtQueryObject, 20, ntdll)
|
||||
@ -399,6 +400,7 @@ LoadDLLfuncNt (NtQuerySystemInformation, 16, ntdll)
|
||||
LoadDLLfuncNt (NtQuerySecurityObject, 20, ntdll)
|
||||
LoadDLLfuncNt (NtQueryVirtualMemory, 24, ntdll)
|
||||
LoadDLLfuncNt (NtQueryVolumeInformationFile, 20, ntdll)
|
||||
LoadDLLfuncNt (NtSetEaFile, 16, ntdll)
|
||||
LoadDLLfuncNt (NtSetSecurityObject, 12, ntdll)
|
||||
LoadDLLfuncNt (NtUnlockVirtualMemory, 16, ntdll)
|
||||
LoadDLLfuncNt (NtUnmapViewOfSection, 8, ntdll)
|
||||
|
@ -590,11 +590,13 @@ fhandler_base::open (int flags, mode_t mode)
|
||||
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
case query_write_attributes:
|
||||
|
@ -581,6 +581,23 @@ typedef struct _DIRECTORY_BASIC_INFORMATION
|
||||
UNICODE_STRING ObjectTypeName;
|
||||
} 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
|
||||
standard Win32 header. */
|
||||
extern "C"
|
||||
@ -611,6 +628,8 @@ extern "C"
|
||||
PUNICODE_STRING, BOOLEAN);
|
||||
NTSTATUS NTAPI NtQueryDirectoryObject (HANDLE, PVOID, ULONG, BOOLEAN,
|
||||
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,
|
||||
ULONG, FILE_INFORMATION_CLASS);
|
||||
NTSTATUS NTAPI NtQueryInformationProcess (HANDLE, PROCESSINFOCLASS,
|
||||
@ -626,6 +645,7 @@ extern "C"
|
||||
NTSTATUS NTAPI NtQueryVolumeInformationFile (HANDLE, IO_STATUS_BLOCK *,
|
||||
VOID *, ULONG,
|
||||
FS_INFORMATION_CLASS);
|
||||
NTSTATUS NTAPI NtSetEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG);
|
||||
NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
|
||||
PSECURITY_DESCRIPTOR);
|
||||
NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* 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)
|
||||
|
||||
@ -11,315 +11,162 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||||
details. */
|
||||
|
||||
#include "winsup.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ntdef.h>
|
||||
#include "security.h"
|
||||
#include "ntdll.h"
|
||||
|
||||
/* Default to not using NTEA information */
|
||||
bool allow_ntea;
|
||||
|
||||
/*
|
||||
From Windows NT DDK:
|
||||
|
||||
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.
|
||||
* read_ea - read file's Extended Attribute.
|
||||
*
|
||||
* Parameters:
|
||||
* file - pointer to filename
|
||||
* attrname- pointer to EA name (case insensitivy. EAs are sored in upper
|
||||
* case).
|
||||
* attrname- pointer to EA name (case insensitiv)
|
||||
* attrbuf - pointer to buffer to store EA's value.
|
||||
* len - length of attrbuf.
|
||||
* Return value:
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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;
|
||||
int eafound = 0;
|
||||
PFILE_FULL_EA_INFORMATION ea, sea;
|
||||
int easize = 0;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
hFileSource = CreateFile (file, FILE_READ_EA,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
&sec_none_nih, // sa
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
/* Prepare buffer which receives the result. */
|
||||
ULONG flen = sizeof (FILE_FULL_EA_INFORMATION) + strlen (attrname)
|
||||
+ len + 1;
|
||||
PFILE_FULL_EA_INFORMATION fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
|
||||
/* Prepare buffer specifying the EA to search for. */
|
||||
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)
|
||||
return 0;
|
||||
|
||||
/* Read in raw array of EAs */
|
||||
ea = sea = NTReadEARaw (hFileSource, &easize);
|
||||
|
||||
/* Search for requested attribute */
|
||||
while (sea)
|
||||
{
|
||||
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))
|
||||
/* If no incoming hdl is given, the loop only runs once, trying to
|
||||
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.
|
||||
If this fails it tries to open the file and to query with that
|
||||
handle again. */
|
||||
HANDLE h = hdl;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
int ret = 0;
|
||||
while (true)
|
||||
{
|
||||
DWORD sl,sh;
|
||||
|
||||
if (dwBytesWritten == 0) /* No more Stream IDs */
|
||||
break;
|
||||
/* skip StreamName */
|
||||
if (StreamId.dwStreamNameSize)
|
||||
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)
|
||||
{
|
||||
unsigned char *buf;
|
||||
buf = (unsigned char *) malloc (StreamId.dwStreamNameSize);
|
||||
|
||||
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);
|
||||
debug_printf ("Opening %s for querying EA %s failed, %E",
|
||||
file, attrname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Is it EA stream? */
|
||||
if (StreamId.dwStreamId == BACKUP_EA_DATA)
|
||||
{
|
||||
unsigned char *buf;
|
||||
buf = (unsigned char *) malloc (StreamId.Size.LowPart);
|
||||
|
||||
if (buf == NULL)
|
||||
break;
|
||||
if (!BackupRead (hFileSource, buf, // buffer to read
|
||||
StreamId.Size.LowPart, // num bytes to write
|
||||
&dwBytesWritten,
|
||||
FALSE, // don't abort yet
|
||||
FALSE, // don't process security
|
||||
&lpContext))
|
||||
{
|
||||
free (buf); /* EA read error */
|
||||
break;
|
||||
}
|
||||
eafound = (PFILE_FULL_EA_INFORMATION) buf;
|
||||
*len = StreamId.Size.LowPart;
|
||||
break;
|
||||
}
|
||||
/* Skip current stream */
|
||||
if (!BackupSeek (hFileSource,
|
||||
StreamId.Size.LowPart,
|
||||
StreamId.Size.HighPart,
|
||||
&sl,
|
||||
&sh,
|
||||
&lpContext))
|
||||
break;
|
||||
status = NtQueryEaFile (h, &io, fea, flen, FALSE, gea, glen, NULL, TRUE);
|
||||
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))
|
||||
{
|
||||
ret = -1;
|
||||
debug_printf ("%x = NtQueryEaFile (%s, %s), Win32 error %d",
|
||||
status, file, attrname, RtlNtStatusToDosError (status));
|
||||
}
|
||||
if (!fea->EaValueLength)
|
||||
ret = 0;
|
||||
else
|
||||
{
|
||||
memcpy (attrbuf, fea->EaName + fea->EaNameLength + 1,
|
||||
fea->EaValueLength);
|
||||
ret = fea->EaValueLength;
|
||||
}
|
||||
|
||||
/* free context */
|
||||
BackupRead (
|
||||
hFileSource,
|
||||
NULL, // buffer to write
|
||||
0, // number of bytes to write
|
||||
&dwBytesWritten,
|
||||
TRUE, // abort
|
||||
FALSE, // don't process security
|
||||
&lpContext);
|
||||
|
||||
return eafound;
|
||||
out:
|
||||
debug_printf ("%d = read_ea (%x, %s, %s, %x, %d)", ret, hdl, file, attrname,
|
||||
attrbuf, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* NTWriteEA - write file's Extended Attribute.
|
||||
* write_ea - write file's Extended Attribute.
|
||||
*
|
||||
* Parameters:
|
||||
* file - pointer to filename
|
||||
* attrname- pointer to EA name (case insensitivy. EAs are sored in upper
|
||||
* case).
|
||||
* buf - pointer to buffer with EA value.
|
||||
* len - length of buf.
|
||||
* attrname- pointer to EA name (case insensitiv)
|
||||
* attrbuf - pointer to buffer with EA value.
|
||||
* len - length of attrbuf.
|
||||
* Return value:
|
||||
* true if success, false otherwice.
|
||||
* Note: if len=0 given EA will be deleted.
|
||||
*/
|
||||
|
||||
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;
|
||||
WIN32_STREAM_ID StreamId;
|
||||
DWORD dwBytesWritten;
|
||||
LPVOID lpContext;
|
||||
DWORD StreamSize, easize;
|
||||
bool bSuccess = false;
|
||||
PFILE_FULL_EA_INFORMATION ea;
|
||||
IO_STATUS_BLOCK io;
|
||||
|
||||
hFileSource = CreateFile (file, FILE_WRITE_EA,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
&sec_none_nih, // sa
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
NULL);
|
||||
/* Prepare buffer specifying the EA to write back. */
|
||||
ULONG flen = sizeof (FILE_FULL_EA_INFORMATION) + strlen (attrname)
|
||||
+ len + 1;
|
||||
PFILE_FULL_EA_INFORMATION fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
|
||||
fea->NextEntryOffset = 0;
|
||||
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)
|
||||
return FALSE;
|
||||
/* If no incoming hdl is given, the loop only runs once, trying to
|
||||
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;
|
||||
StreamSize = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**);
|
||||
|
||||
/* FILE_FULL_EA_INFORMATION structure is longword-aligned */
|
||||
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;
|
||||
out:
|
||||
debug_printf ("%d = write_ea (%x, %s, %s, %x, %d)", ret, hdl, file, attrname,
|
||||
attrbuf, len);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2694,20 +2694,20 @@ endmntent (FILE *)
|
||||
/********************** Symbolic Link Support **************************/
|
||||
|
||||
/* Read symlink from Extended Attribute */
|
||||
int
|
||||
get_symlink_ea (const char* frompath, char* buf, int buf_size)
|
||||
static int
|
||||
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)
|
||||
debug_printf ("Cannot read symlink from EA");
|
||||
return (res - 1);
|
||||
}
|
||||
|
||||
/* Save symlink to Extended Attribute */
|
||||
bool
|
||||
set_symlink_ea (const char* frompath, const char* topath)
|
||||
static bool
|
||||
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");
|
||||
return false;
|
||||
@ -2926,6 +2926,8 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
if (!isdevice && win32_path.fs_has_ea ())
|
||||
set_symlink_ea (h, win32_path, oldpath);
|
||||
CloseHandle (h);
|
||||
if (!allow_ntsec && allow_ntea)
|
||||
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
|
||||
SetFileAttributes (win32_path, attr);
|
||||
|
||||
if (!isdevice && win32_path.fs_has_ea ())
|
||||
set_symlink_ea (win32_path, oldpath);
|
||||
res = 0;
|
||||
}
|
||||
else
|
||||
@ -3340,16 +3340,6 @@ symlink_info::check (char *path, const suffix_info *suffixes, unsigned opt)
|
||||
if (!sym_check)
|
||||
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. */
|
||||
|
||||
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)
|
||||
goto file_not_symlink;
|
||||
|
||||
/* FIXME: if symlink isn't present in EA, but EAs are supported,
|
||||
should we write it there? */
|
||||
if (sym_check > 0 && opt & PC_CHECK_EA
|
||||
&& (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)
|
||||
{
|
||||
case 1:
|
||||
|
@ -1405,7 +1405,8 @@ get_file_attribute (int use_ntsec, HANDLE handle, const char *file,
|
||||
if (allow_ntea)
|
||||
{
|
||||
int oatt = *attribute;
|
||||
res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof (*attribute));
|
||||
res = read_ea (handle, file, ".UNIXATTR", (char *)attribute,
|
||||
sizeof (*attribute));
|
||||
*attribute |= oatt;
|
||||
}
|
||||
else
|
||||
@ -1801,8 +1802,8 @@ set_file_attribute (bool use_ntsec, HANDLE handle, const char *file,
|
||||
|
||||
if (use_ntsec && allow_ntsec)
|
||||
ret = set_nt_attribute (handle, file, uid, gid, attribute);
|
||||
else if (allow_ntea && !NTWriteEA (file, ".UNIXATTR", (char *) &attribute,
|
||||
sizeof (attribute)))
|
||||
else if (allow_ntea && !write_ea (handle, file, ".UNIXATTR",
|
||||
(char *) &attribute, sizeof (attribute)))
|
||||
{
|
||||
__seterrno ();
|
||||
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,
|
||||
PSID sid2 = NO_SID, DWORD access2 = 0);
|
||||
|
||||
int __stdcall NTReadEA (const char *file, const char *attrname, char *buf, int len);
|
||||
BOOL __stdcall NTWriteEA (const char *file, const char *attrname, const char *buf, int len);
|
||||
int __stdcall read_ea (HANDLE hdl, const char *file, const char *attrname,
|
||||
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
|
||||
effective sid (cygheap->user.sid ()). */
|
||||
|
Loading…
x
Reference in New Issue
Block a user