OSDN Git Service

* autoload.cc (NtQueryEaFile): Define.
authorcorinna <corinna>
Mon, 3 Jul 2006 18:30:08 +0000 (18:30 +0000)
committercorinna <corinna>
Mon, 3 Jul 2006 18:30:08 +0000 (18:30 +0000)
(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.

winsup/cygwin/ChangeLog
winsup/cygwin/autoload.cc
winsup/cygwin/fhandler.cc
winsup/cygwin/ntdll.h
winsup/cygwin/ntea.cc
winsup/cygwin/path.cc
winsup/cygwin/security.cc
winsup/cygwin/security.h

index f158ada..8d6559f 100644 (file)
@@ -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
index c6ce113..25c7dd8 100644 (file)
@@ -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)
index a48f3d9..50bde00 100644 (file)
@@ -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:
index ff5f0c9..2a71cd8 100644 (file)
@@ -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);
index f33d822..72463fe 100644 (file)
@@ -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)
-{
-    HANDLE hFileSource;
-    int eafound = 0;
-    PFILE_FULL_EA_INFORMATION ea, sea;
-    int easize = 0;
-
-    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)
+read_ea (HANDLE hdl, const char *file, const char *attrname, char *attrbuf,
+        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))
+  IO_STATUS_BLOCK io;
+
+  /* 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 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);
-       }
-
-       /* 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;
+         debug_printf ("Opening %s for querying EA %s failed, %E",
+                       file, attrname);
+         goto out;
        }
-       /* 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;
-
-  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;
+  IO_STATUS_BLOCK io;
+
+  /* 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 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;
+
+out:
+  debug_printf ("%d = write_ea (%x, %s, %s, %x, %d)", ret, hdl, file, attrname,
+               attrbuf, len);
+  return ret;
 }
index ea96596..f9891f5 100644 (file)
@@ -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:
index 8a994fe..23f86e3 100644 (file)
@@ -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;
index ec53dfc..a55cc03 100644 (file)
@@ -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 ()). */