summaryrefslogtreecommitdiff
path: root/winsup/cygwin/ntea.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/ntea.cc')
-rw-r--r--winsup/cygwin/ntea.cc325
1 files changed, 325 insertions, 0 deletions
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
new file mode 100644
index 00000000000..7ddff77707c
--- /dev/null
+++ b/winsup/cygwin/ntea.cc
@@ -0,0 +1,325 @@
+/* ntea.cc: code for manipulating NTEA information
+
+ Copyright 1997, 1998, 2000, 2001 Red Hat, Inc.
+
+ Written by Sergey S. Okhapkin (sos@prospect.com.ru)
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "security.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.
+ *
+ * Parameters:
+ * file - pointer to filename
+ * attrname- pointer to EA name (case insensitivy. EAs are sored in upper
+ * case).
+ * 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.
+ * -1 - attrbuf too small for EA value.
+ */
+
+int __stdcall
+NTReadEA (const char *file, const char *attrname, char *attrbuf, int len)
+{
+ HANDLE hFileSource;
+ int eafound = 0;
+ PFILE_FULL_EA_INFORMATION ea, sea;
+ int easize;
+
+ hFileSource = CreateFile (file, FILE_READ_EA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sec_none_nih, // sa
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ 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))
+ {
+ DWORD sl,sh;
+
+ if (dwBytesWritten == 0) /* No more Stream IDs */
+ break;
+ /* skip StreamName */
+ if (StreamId.dwStreamNameSize)
+ {
+ 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);
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+}
+
+/*
+ * NTWriteEA - 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.
+ * 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)
+{
+ HANDLE hFileSource;
+ 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,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ &sec_none_nih, // sa
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ if (hFileSource == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ 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;
+}