Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/ntea.cc')
-rw-r--r--winsup/cygwin/ntea.cc514
1 files changed, 0 insertions, 514 deletions
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
deleted file mode 100644
index 25ba6db1f..000000000
--- a/winsup/cygwin/ntea.cc
+++ /dev/null
@@ -1,514 +0,0 @@
-/* ntea.cc: code for manipulating Extended Attributes
-
- Copyright 1997, 1998, 2000, 2001, 2006, 2008, 2009, 2010 Red Hat, Inc.
-
-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 "cygtls.h"
-#include "security.h"
-#include "path.h"
-#include "fhandler.h"
-#include "dtable.h"
-#include "cygheap.h"
-#include "ntdll.h"
-#include <stdlib.h>
-#include <attr/xattr.h>
-
-#define MAX_EA_NAME_LEN 256
-#define MAX_EA_VALUE_LEN 65536
-
-/* At least one maximum sized entry fits. */
-#define EA_BUFSIZ (sizeof (FILE_FULL_EA_INFORMATION) + MAX_EA_NAME_LEN \
- + MAX_EA_VALUE_LEN)
-
-#define NEXT_FEA(p) ((PFILE_FULL_EA_INFORMATION) (p->NextEntryOffset \
- ? (char *) p + p->NextEntryOffset : NULL))
-
-ssize_t __stdcall
-read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
-{
- OBJECT_ATTRIBUTES attr;
- NTSTATUS status;
- IO_STATUS_BLOCK io;
- ssize_t ret = -1;
- HANDLE h = hdl;
- ULONG glen = 0;
- PFILE_GET_EA_INFORMATION gea = NULL;
- PFILE_FULL_EA_INFORMATION fea;
- /* We have to store the latest EaName to compare with the next one, since
- ZwQueryEaFile has a bug when accessing files on a remote share. It
- returns the last EA entry of the file infinitely. Even utilizing the
- optional EaIndex only helps marginally. If you use that, the last
- EA in the file is returned twice. */
- char lastname[MAX_EA_NAME_LEN];
-
- myfault efault;
- if (efault.faulted (EFAULT))
- goto out;
-
- pc.get_object_attr (attr, sec_none_nih);
-
- debug_printf ("read_ea (%S, %s, %p, %lu)",
- attr.ObjectName, name, value, size);
-
- /* Early open if handle is NULL. This allows to return error codes like
- ENOENT before we actually check for the correctness of the EA name and
- stuff like that. */
- if (!hdl)
- {
- status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
- FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_nt_status (status);
- goto out;
- }
- hdl = NULL;
- }
-
- fea = (PFILE_FULL_EA_INFORMATION) alloca (EA_BUFSIZ);
-
- if (name)
- {
- size_t nlen;
-
- /* For compatibility with Linux, we only allow user xattrs and
- return EOPNOTSUPP otherwise. */
- if (ascii_strncasematch (name, "user.", 5))
- name += 5;
- else
- {
- set_errno (EOPNOTSUPP);
- goto out;
- }
-
- if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
- {
- set_errno (EINVAL);
- return -1;
- }
- glen = sizeof (FILE_GET_EA_INFORMATION) + nlen;
- gea = (PFILE_GET_EA_INFORMATION) alloca (glen);
-
- gea->NextEntryOffset = 0;
- gea->EaNameLength = nlen;
- strcpy (gea->EaName, name);
- }
-
- while (true)
- {
- if (h)
- {
- status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, gea, glen,
- NULL, TRUE);
- if (status != STATUS_ACCESS_DENIED || !hdl)
- break;
- }
- status = NtOpenFile (&h, READ_CONTROL | FILE_READ_EA, &attr, &io,
- FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
- break;
- hdl = NULL;
- }
- if (!NT_SUCCESS (status))
- {
- if (status == STATUS_NO_EAS_ON_FILE)
- ret = 0;
- else if (status == STATUS_NONEXISTENT_EA_ENTRY)
- /* Actually this error code is either never generated, or it was only
- generated in some old and long forgotton NT version. See below. */
- set_errno (ENOATTR);
- else
- __seterrno_from_nt_status (status);
- goto out;
- }
- if (name)
- {
- /* Another weird behaviour of ZwQueryEaFile. If you ask for a
- specific EA which is not present in the file's EA list, you don't
- get a useful error code like STATUS_NONEXISTENT_EA_ENTRY. Rather
- ZwQueryEaFile returns success with the entry's EaValueLength
- set to 0. */
- if (!fea->EaValueLength)
- {
- set_errno (ENOATTR);
- goto out;
- }
- if (size > 0)
- {
- if (size < fea->EaValueLength)
- {
- set_errno (ERANGE);
- goto out;
- }
- memcpy (value, fea->EaName + fea->EaNameLength + 1,
- fea->EaValueLength);
- }
- ret = fea->EaValueLength;
- }
- else
- {
- ret = 0;
- do
- {
- fea->EaNameLength += 5; /* "user." */
- if (size > 0)
- {
- if ((size_t) ret + fea->EaNameLength + 1 > size)
- {
- set_errno (ERANGE);
- goto out;
- }
- /* For compatibility with Linux, we always prepend "user." to
- the attribute name, so effectively we only support user
- attributes from a application point of view. */
- char tmpbuf[MAX_EA_NAME_LEN * 2];
- char *tp = stpcpy (tmpbuf, "user.");
- stpcpy (tp, fea->EaName);
- /* NTFS stores all EA names in uppercase unfortunately. To keep
- compatibility with ext/xfs EA namespaces and accompanying
- tools, which expect the namespaces to be lower case, we return
- EA names in lowercase if the file is on a native NTFS. */
- if (pc.fs_is_ntfs ())
- strlwr (tp);
- tp = stpcpy (value, tmpbuf) + 1;
- ret += tp - value;
- value = tp;
- }
- else
- ret += fea->EaNameLength + 1;
- strcpy (lastname, fea->EaName);
- status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, NULL, 0,
- NULL, FALSE);
- }
- while (NT_SUCCESS (status) && strcmp (lastname, fea->EaName) != 0);
- }
-
-out:
- if (!hdl)
- CloseHandle (h);
- debug_printf ("%d = read_ea (%S, %s, %p, %lu)",
- ret, attr.ObjectName, name, value, size);
- return ret;
-}
-
-int __stdcall
-write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
- size_t size, int flags)
-{
- OBJECT_ATTRIBUTES attr;
- NTSTATUS status;
- IO_STATUS_BLOCK io;
- int ret = -1;
- HANDLE h = hdl;
- PFILE_FULL_EA_INFORMATION fea;
- ULONG flen;
- size_t nlen;
-
- myfault efault;
- if (efault.faulted (EFAULT))
- goto out;
-
- pc.get_object_attr (attr, sec_none_nih);
-
- debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
- attr.ObjectName, name, value, size, flags);
-
- /* Early open if handle is NULL. This allows to return error codes like
- ENOENT before we actually check for the correctness of the EA name and
- stuff like that. */
- if (!hdl)
- {
- status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
- FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_nt_status (status);
- goto out;
- }
- hdl = NULL;
- }
-
- /* For compatibility with Linux, we only allow user xattrs and
- return EOPNOTSUPP otherwise. */
- if (!ascii_strncasematch (name, "user.", 5))
- {
- set_errno (EOPNOTSUPP);
- goto out;
- }
-
- /* removexattr is supposed to fail with ENOATTR if the requested EA is not
- available. This is equivalent to the XATTR_REPLACE flag for setxattr. */
- if (!value)
- flags = XATTR_REPLACE;
-
- if (flags)
- {
- if (flags != XATTR_CREATE && flags != XATTR_REPLACE)
- {
- set_errno (EINVAL);
- goto out;
- }
- ssize_t rret = read_ea (hdl, pc, name, NULL, 0);
- if (flags == XATTR_CREATE && rret > 0)
- {
- set_errno (EEXIST);
- goto out;
- }
- if (flags == XATTR_REPLACE && rret < 0)
- goto out;
- }
-
- /* Skip "user." prefix. */
- name += 5;
-
- if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
- {
- set_errno (EINVAL);
- goto out;
- }
- flen = sizeof (FILE_FULL_EA_INFORMATION) + nlen + 1 + size;
- fea = (PFILE_FULL_EA_INFORMATION) alloca (flen);
- fea->NextEntryOffset = 0;
- fea->Flags = 0;
- fea->EaNameLength = nlen;
- fea->EaValueLength = size;
- strcpy (fea->EaName, name);
- if (value)
- memcpy (fea->EaName + fea->EaNameLength + 1, value, size);
-
- while (true)
- {
- if (h)
- {
- status = NtSetEaFile (h, &io, fea, flen);
- if (status != STATUS_ACCESS_DENIED || !hdl)
- break;
- }
- status = NtOpenFile (&h, READ_CONTROL | FILE_WRITE_EA, &attr, &io,
- FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS (status))
- break;
- hdl = NULL;
- }
- if (!NT_SUCCESS (status))
- {
- /* STATUS_EA_TOO_LARGE has a matching Win32 error ERROR_EA_TABLE_FULL.
- Too bad RtlNtStatusToDosError does not translate STATUS_EA_TOO_LARGE
- to ERROR_EA_TABLE_FULL, but to ERROR_EA_LIST_INCONSISTENT. This
- error code is also returned for STATUS_EA_LIST_INCONSISTENT, which
- means the incoming EA list is... inconsistent. For obvious reasons
- we translate ERROR_EA_LIST_INCONSISTENT to EINVAL, so we have to
- handle STATUS_EA_TOO_LARGE explicitely here, to get the correct
- mapping to ENOSPC. */
- if (status == STATUS_EA_TOO_LARGE)
- set_errno (ENOSPC);
- else
- __seterrno_from_nt_status (status);
- }
- else
- ret = 0;
-
-out:
- if (!hdl)
- CloseHandle (h);
- debug_printf ("%d = write_ea (%S, %s, %p, %lu, %d)",
- ret, attr.ObjectName, name, value, size, flags);
- return ret;
-}
-
-static ssize_t __stdcall
-getxattr_worker (path_conv &pc, const char *name, void *value, size_t size)
-{
- int res = -1;
-
- if (pc.error)
- {
- debug_printf ("got %d error from path_conv", pc.error);
- set_errno (pc.error);
- }
- else if (pc.exists ())
- {
- fhandler_base *fh;
-
- if (!(fh = build_fh_pc (pc)))
- return -1;
-
- res = fh->fgetxattr (name, value, size);
- delete fh;
- }
- else
- set_errno (ENOENT);
- return res;
-}
-
-extern "C" ssize_t
-getxattr (const char *path, const char *name, void *value, size_t size)
-{
- if (!name)
- {
- set_errno (EINVAL);
- return -1;
- }
- path_conv pc (path, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
- return getxattr_worker (pc, name, value, size);
-}
-
-extern "C" ssize_t
-lgetxattr (const char *path, const char *name, void *value, size_t size)
-{
- if (!name)
- {
- set_errno (EINVAL);
- return -1;
- }
- path_conv pc (path, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
- return getxattr_worker (pc, name, value, size);
-}
-
-extern "C" ssize_t
-fgetxattr (int fd, const char *name, void *value, size_t size)
-{
- int res;
-
- if (!name)
- {
- set_errno (EINVAL);
- return -1;
- }
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- res = -1;
- else
- res = cfd->fgetxattr (name, value, size);
- return res;
-}
-
-extern "C" ssize_t
-listxattr (const char *path, char *list, size_t size)
-{
- path_conv pc (path, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
- return getxattr_worker (pc, NULL, list, size);
-}
-
-extern "C" ssize_t
-llistxattr (const char *path, char *list, size_t size)
-{
- path_conv pc (path, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
- return getxattr_worker (pc, NULL, list, size);
-}
-
-extern "C" ssize_t
-flistxattr (int fd, char *list, size_t size)
-{
- int res;
-
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- res = -1;
- else
- res = cfd->fgetxattr (NULL, list, size);
- return res;
-}
-
-static int __stdcall
-setxattr_worker (path_conv &pc, const char *name, const void *value,
- size_t size, int flags)
-{
- int res = -1;
-
- if (pc.error)
- {
- debug_printf ("got %d error from path_conv", pc.error);
- set_errno (pc.error);
- }
- else if (pc.exists ())
- {
- fhandler_base *fh;
-
- if (!(fh = build_fh_pc (pc)))
- return -1;
-
- res = fh->fsetxattr (name, value, size, flags);
- delete fh;
- }
- else
- set_errno (ENOENT);
- return res;
-}
-
-extern "C" int
-setxattr (const char *path, const char *name, const void *value, size_t size,
- int flags)
-{
- if (!size)
- {
- set_errno (EINVAL);
- return -1;
- }
- path_conv pc (path, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
- return setxattr_worker (pc, name, value, size, flags);
-}
-
-extern "C" int
-lsetxattr (const char *path, const char *name, const void *value, size_t size,
- int flags)
-{
- if (!size)
- {
- set_errno (EINVAL);
- return -1;
- }
- path_conv pc (path, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
- return setxattr_worker (pc, name, value, size, flags);
-}
-
-extern "C" int
-fsetxattr (int fd, const char *name, const void *value, size_t size, int flags)
-{
- int res;
-
- if (!size)
- {
- set_errno (EINVAL);
- return -1;
- }
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- res = -1;
- else
- res = cfd->fsetxattr (name, value, size, flags);
- return res;
-}
-
-extern "C" int
-removexattr (const char *path, const char *name)
-{
- path_conv pc (path, PC_SYM_FOLLOW | PC_POSIX, stat_suffixes);
- return setxattr_worker (pc, name, NULL, 0, 0);
-}
-
-extern "C" int
-lremovexattr (const char *path, const char *name)
-{
- path_conv pc (path, PC_SYM_NOFOLLOW | PC_POSIX, stat_suffixes);
- return setxattr_worker (pc, name, NULL, 0, 0);
-}
-
-extern "C" int
-fremovexattr (int fd, const char *name)
-{
- int res;
-
- cygheap_fdget cfd (fd);
- if (cfd < 0)
- res = -1;
- else
- res = cfd->fsetxattr (name, NULL, 0, 0);
- return res;
-}