diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2014-08-22 13:21:33 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2014-08-22 13:21:33 +0400 |
commit | 3f3bd10104550243781f0b4d9248975e35d91ac7 (patch) | |
tree | c7ac2839d2c3da2321bd9979a1574667ed39bc26 /winsup/cygwin/ntea.cc | |
parent | 33ed7bb5bc2cb41259df064229968933d9c898ca (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.cc | 465 |
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)", |