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:
authorCorinna Vinschen <corinna@vinschen.de>2014-08-22 13:21:33 +0400
committerCorinna Vinschen <corinna@vinschen.de>2014-08-22 13:21:33 +0400
commit3f3bd10104550243781f0b4d9248975e35d91ac7 (patch)
treec7ac2839d2c3da2321bd9979a1574667ed39bc26 /winsup/cygwin/ntea.cc
parent33ed7bb5bc2cb41259df064229968933d9c898ca (diff)
* Throughout, use __try/__except/__endtry blocks, rather than myfault
handler. * cygtls.cc (_cygtls::remove): Accommodate the fact that pathbufs has been moved from _local_storage to _cygtls. * cygtls.h (class tls_pathbuf): Add comment to hint to gendef usage of counters. Change type of counters to uint32_t for clarity. Remove _cygtls as friend class. (struct _local_storage): Move pathbufs from here... (struct _cygtls): ...to here, allowing to access it from _sigbe. (class san): Only define on 32 bit. Remove errno, _c_cnt and _w_cnt members. (san::setup): Drop parameter. Don't initialize removed members. (san::leave): Don't set removed members. (class myfault): Only define on 32 bit. (myfault::faulted): Only keep implementation not taking any parameter. Drop argument in call to sebastian.setup. (__try/__leave/__except/__endtry): Implement to support real SEH. For now stick to SJLJ on 32 bit. * dcrt0.cc (dll_crt0_0): Drop 64 bit call to exception::install_myfault_handler. * exception.h (exception_handler): Define with EXCEPTION_DISPOSITION as return type. (PDISPATCHER_CONTEXT): Define as void * on 32 bit. Define as pointer to _DISPATCHER_CONTEXT on 64 bit. (class exception): Define separately for 32 and 64 bit. (exception::myfault): Add handler for myfault SEH handling on 64 bit. (exception::exception): Fix mangled method name to account for change in type of last parameter. (exception::install_myfault_handler): Remove. * exceptions.cc (exception::myfault_handle): Remove. (exception::myfault): New SEH handler for 64 bit. * gendef (_sigbe): Set tls_pathbuf counters to 0 explicitely when returning to the caller. * ntdll.h: Move a comment to a better place. (struct _SCOPE_TABLE): Define on 64 bit. * thread.cc (verifyable_object_isvalid): Remove gcc 4.7 workaround. * tls_pbuf.cc (tls_pbuf): Fix to accommodate new place of pathbufs. (tls_pathbuf::destroy): Change type of loop variables to uint32_t. * tls_pbuf.h (class tmp_pathbuf): Change type of buffer counters to uint32_t. Accommodate new place of pathbufs. * tlsoffsets.h: Regenerate. * tlsoffsets64.h: Regenerate.
Diffstat (limited to 'winsup/cygwin/ntea.cc')
-rw-r--r--winsup/cygwin/ntea.cc465
1 files changed, 235 insertions, 230 deletions
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
index 2fb205a04..d0c50775e 100644
--- a/winsup/cygwin/ntea.cc
+++ b/winsup/cygwin/ntea.cc
@@ -60,167 +60,171 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
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);
+ __try
+ {
+ pc.get_object_attr (attr, sec_none_nih);
- debug_printf ("read_ea (%S, %s, %p, %lu)",
- attr.ObjectName, name, value, size);
+ 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))
+ /* 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)
{
- __seterrno_from_nt_status (status);
- goto out;
+ 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);
+ __leave;
+ }
+ hdl = NULL;
}
- hdl = NULL;
- }
-
- fea = (PFILE_FULL_EA_INFORMATION) tp.w_get ();
- if (name)
- {
- size_t nlen;
+ fea = (PFILE_FULL_EA_INFORMATION) tp.w_get ();
- /* For compatibility with Linux, we only allow user xattrs and
- return ENOTSUP otherwise. */
- if (ascii_strncasematch (name, "user.", 5))
- name += 5;
- else
+ if (name)
{
- set_errno (ENOTSUP);
- goto out;
- }
+ size_t nlen;
- 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);
+ /* For compatibility with Linux, we only allow user xattrs and
+ return ENOTSUP otherwise. */
+ if (ascii_strncasematch (name, "user.", 5))
+ name += 5;
+ else
+ {
+ set_errno (ENOTSUP);
+ __leave;
+ }
- gea->NextEntryOffset = 0;
- gea->EaNameLength = nlen;
- strcpy (gea->EaName, name);
- }
+ 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);
- while (true)
- {
- if (h)
+ gea->NextEntryOffset = 0;
+ gea->EaNameLength = nlen;
+ strcpy (gea->EaName, name);
+ }
+
+ while (true)
{
- status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, gea, glen,
- NULL, TRUE);
- if (status != STATUS_ACCESS_DENIED || !hdl)
+ 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;
}
- 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))
- {
- switch (status)
- {
- case STATUS_NO_EAS_ON_FILE:
- ret = 0;
- break;
- case STATUS_INVALID_DEVICE_REQUEST:
- set_errno (ENOTSUP);
- break;
- case STATUS_NOT_FOUND:
- /* STATUS_NOT_FOUND is returned when calling NtQueryEaFile on NFS.
- In theory this should mean that the file just has no EAs, but in
- fact NFS doesn't support EAs, other than the EAs which are used
- for NFS requests. We're playing safe and convert STATUS_NOT_FOUND
- to ENOATTR, unless we're on NFS, where we convert it to ENOTSUP. */
- set_errno (pc.fs_is_nfs () ? ENOTSUP : ENOATTR);
- break;
- case STATUS_NONEXISTENT_EA_ENTRY:
- /* Actually STATUS_NONEXISTENT_EA_ENTRY is either never generated, or
- it was only generated in some old and long forgotton NT version.
- See below. For safty reasons, we handle it here, nevertheless. */
- set_errno (ENOATTR);
- break;
- default:
- __seterrno_from_nt_status (status);
- break;
- }
- goto out;
- }
- if (name)
- {
- /* Another weird behaviour of NtQueryEaFile. 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
- NtQueryEaFile 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)
+ switch (status)
{
- set_errno (ERANGE);
- goto out;
+ case STATUS_NO_EAS_ON_FILE:
+ ret = 0;
+ break;
+ case STATUS_INVALID_DEVICE_REQUEST:
+ set_errno (ENOTSUP);
+ break;
+ case STATUS_NOT_FOUND:
+ /* STATUS_NOT_FOUND is returned when calling NtQueryEaFile on NFS.
+ In theory this should mean that the file just has no EAs, but
+ in fact NFS doesn't support EAs, other than the EAs which are
+ used for NFS requests. We're playing safe and convert
+ STATUS_NOT_FOUND to ENOATTR, unless we're on NFS, where we
+ convert it to ENOTSUP. */
+ set_errno (pc.fs_is_nfs () ? ENOTSUP : ENOATTR);
+ break;
+ case STATUS_NONEXISTENT_EA_ENTRY:
+ /* Actually STATUS_NONEXISTENT_EA_ENTRY is either never generated,
+ or it was only generated in some old and long forgotton NT
+ version. See below. For safty reasons, we handle it here,
+ nevertheless. */
+ set_errno (ENOATTR);
+ break;
+ default:
+ __seterrno_from_nt_status (status);
+ break;
}
- memcpy (value, fea->EaName + fea->EaNameLength + 1,
- fea->EaValueLength);
+ __leave;
}
- ret = fea->EaValueLength;
- }
- else
- {
- ret = 0;
- do
+ if (name)
{
- fea->EaNameLength += 5; /* "user." */
+ /* Another weird behaviour of NtQueryEaFile. 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
+ NtQueryEaFile returns success with the entry's EaValueLength
+ set to 0. */
+ if (!fea->EaValueLength)
+ {
+ set_errno (ENOATTR);
+ __leave;
+ }
if (size > 0)
{
- if ((size_t) ret + fea->EaNameLength + 1 > size)
+ if (size < fea->EaValueLength)
{
set_errno (ERANGE);
- goto out;
+ __leave;
}
- /* 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;
+ memcpy (value, fea->EaName + fea->EaNameLength + 1,
+ fea->EaValueLength);
}
- else
- ret += fea->EaNameLength + 1;
- strcpy (lastname, fea->EaName);
- status = NtQueryEaFile (h, &io, fea, EA_BUFSIZ, TRUE, NULL, 0,
- NULL, FALSE);
+ 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);
+ __leave;
+ }
+ /* 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);
}
- while (NT_SUCCESS (status) && strcmp (lastname, fea->EaName) != 0);
}
-
-out:
+ __except (EFAULT) {}
+ __endtry
if (!hdl)
CloseHandle (h);
debug_printf ("%d = read_ea(%S, %s, %p, %lu)",
@@ -241,120 +245,121 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
ULONG flen;
size_t nlen;
- myfault efault;
- if (efault.faulted (EFAULT))
- goto out;
-
- pc.get_object_attr (attr, sec_none_nih);
+ __try
+ {
+ pc.get_object_attr (attr, sec_none_nih);
- debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
- attr.ObjectName, name, value, size, flags);
+ 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))
+ /* 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)
{
- __seterrno_from_nt_status (status);
- goto out;
+ 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);
+ __leave;
+ }
+ hdl = NULL;
}
- hdl = NULL;
- }
-
- /* For compatibility with Linux, we only allow user xattrs and
- return ENOTSUP otherwise. */
- if (!ascii_strncasematch (name, "user.", 5))
- {
- set_errno (ENOTSUP);
- 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)
+ /* For compatibility with Linux, we only allow user xattrs and
+ return ENOTSUP otherwise. */
+ if (!ascii_strncasematch (name, "user.", 5))
{
- set_errno (EINVAL);
- goto out;
+ set_errno (ENOTSUP);
+ __leave;
}
- ssize_t rret = read_ea (hdl, pc, name, NULL, 0);
- if (flags == XATTR_CREATE && rret > 0)
+
+ /* removexattr is supposed to fail with ENOATTR if the requested EA is
+ not available. This is equivalent to XATTR_REPLACE for setxattr. */
+ if (!value)
+ flags = XATTR_REPLACE;
+
+ if (flags)
{
- set_errno (EEXIST);
- goto out;
+ if (flags != XATTR_CREATE && flags != XATTR_REPLACE)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ ssize_t rret = read_ea (hdl, pc, name, NULL, 0);
+ if (flags == XATTR_CREATE && rret > 0)
+ {
+ set_errno (EEXIST);
+ __leave;
+ }
+ if (flags == XATTR_REPLACE && rret < 0)
+ __leave;
}
- if (flags == XATTR_REPLACE && rret < 0)
- goto out;
- }
- /* Skip "user." prefix. */
- name += 5;
+ /* 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)
+ if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
+ {
+ set_errno (EINVAL);
+ __leave;
+ }
+ 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)
{
- status = NtSetEaFile (h, &io, fea, flen);
- if (status != STATUS_ACCESS_DENIED || !hdl)
+ 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;
}
- 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))
- {
- switch (status)
{
- case STATUS_EA_TOO_LARGE:
- /* STATUS_EA_TOO_LARGE has a matching Win32 error ERROR_EA_TABLE_FULL.
- For some unknown reason RtlNtStatusToDosError does not translate
- STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL, but instead 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. */
- set_errno (ENOSPC);
- break;
- case STATUS_INVALID_DEVICE_REQUEST:
- set_errno (ENOTSUP);
- break;
- default:
- __seterrno_from_nt_status (status);
- break;
+ switch (status)
+ {
+ case STATUS_EA_TOO_LARGE:
+ /* STATUS_EA_TOO_LARGE has a matching Win32 error code
+ ERROR_EA_TABLE_FULL. For some reason RtlNtStatusToDosError
+ does not translate STATUS_EA_TOO_LARGE to ERROR_EA_TABLE_FULL,
+ but instead 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. */
+ set_errno (ENOSPC);
+ break;
+ case STATUS_INVALID_DEVICE_REQUEST:
+ set_errno (ENOTSUP);
+ break;
+ default:
+ __seterrno_from_nt_status (status);
+ break;
+ }
}
+ else
+ ret = 0;
}
- else
- ret = 0;
-
-out:
+ __except (EFAULT) {}
+ __endtry
if (!hdl)
CloseHandle (h);
debug_printf ("%d = write_ea(%S, %s, %p, %lu, %d)",