* ntea.cc (read_ea): Try to open file first to have more sensible
error codes. Always refuse non "user." EAs for Linux compatibility and return EOPNOTSUPP. Fix handling of empty (== non-existant) EAs. Always prepend "user." prefix to EA names. (write_ea): Try to open file first to have more sensible error codes. Always refuse non "user." EAs for Linux compatibility and return EOPNOTSUPP. Delay skipping "user." prefix until after potential call to read_ea.
This commit is contained in:
parent
b4fee5273e
commit
7b426e9f4a
|
@ -1,3 +1,14 @@
|
||||||
|
2009-11-18 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* ntea.cc (read_ea): Try to open file first to have more sensible
|
||||||
|
error codes. Always refuse non "user." EAs for Linux compatibility
|
||||||
|
and return EOPNOTSUPP. Fix handling of empty (== non-existant) EAs.
|
||||||
|
Always prepend "user." prefix to EA names.
|
||||||
|
(write_ea): Try to open file first to have more sensible error codes.
|
||||||
|
Always refuse non "user." EAs for Linux compatibility and return
|
||||||
|
EOPNOTSUPP. Delay skipping "user." prefix until after potential call
|
||||||
|
to read_ea.
|
||||||
|
|
||||||
2009-11-17 Corinna Vinschen <corinna@vinschen.de>
|
2009-11-17 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
Reintegrate socket duplication via WSADuplicateSocket/WSASocket.
|
Reintegrate socket duplication via WSADuplicateSocket/WSASocket.
|
||||||
|
|
|
@ -56,22 +56,34 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
|
||||||
debug_printf ("read_ea (%S, %s, %p, %lu)",
|
debug_printf ("read_ea (%S, %s, %p, %lu)",
|
||||||
attr.ObjectName, name, value, size);
|
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);
|
fea = (PFILE_FULL_EA_INFORMATION) alloca (EA_BUFSIZ);
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
size_t nlen;
|
size_t nlen;
|
||||||
|
|
||||||
/* Samba hides the user namespace from Windows clients. If we try to
|
/* For compatibility with Linux, we only allow user xattrs and
|
||||||
retrieve a user namespace item, we remove the leading namespace from
|
return EOPNOTSUPP otherwise. */
|
||||||
the name, otherwise the search fails. */
|
if (ascii_strncasematch (name, "user.", 5))
|
||||||
if (!pc.fs_is_samba ())
|
|
||||||
/* nothing to do */;
|
|
||||||
else if (ascii_strncasematch (name, "user.", 5))
|
|
||||||
name += 5;
|
name += 5;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_errno (ENOATTR);
|
set_errno (EOPNOTSUPP);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +129,16 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
|
||||||
}
|
}
|
||||||
if (name)
|
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 > 0)
|
||||||
{
|
{
|
||||||
if (size < fea->EaValueLength)
|
if (size < fea->EaValueLength)
|
||||||
|
@ -124,19 +146,8 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
|
||||||
set_errno (ERANGE);
|
set_errno (ERANGE);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Another weird behaviour of ZwQueryEaFile. If you ask for a
|
memcpy (value, fea->EaName + fea->EaNameLength + 1,
|
||||||
specific EA which is not present in the file's EA list, you don't
|
fea->EaValueLength);
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memcpy (value, fea->EaName + fea->EaNameLength + 1,
|
|
||||||
fea->EaValueLength);
|
|
||||||
}
|
}
|
||||||
ret = fea->EaValueLength;
|
ret = fea->EaValueLength;
|
||||||
}
|
}
|
||||||
|
@ -158,8 +169,7 @@ read_ea (HANDLE hdl, path_conv &pc, const char *name, char *value, size_t size)
|
||||||
it in EA listings to keep tools like attr/getfattr/setfattr
|
it in EA listings to keep tools like attr/getfattr/setfattr
|
||||||
happy. */
|
happy. */
|
||||||
char tmpbuf[MAX_EA_NAME_LEN * 2], *tp = tmpbuf;
|
char tmpbuf[MAX_EA_NAME_LEN * 2], *tp = tmpbuf;
|
||||||
if (pc.fs_is_samba ())
|
tp = stpcpy (tmpbuf, "user.");
|
||||||
tp = stpcpy (tmpbuf, "user.");
|
|
||||||
stpcpy (tp, fea->EaName);
|
stpcpy (tp, fea->EaName);
|
||||||
/* NTFS stores all EA names in uppercase unfortunately. To keep
|
/* NTFS stores all EA names in uppercase unfortunately. To keep
|
||||||
compatibility with ext/xfs EA namespaces and accompanying
|
compatibility with ext/xfs EA namespaces and accompanying
|
||||||
|
@ -210,20 +220,26 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
|
||||||
debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
|
debug_printf ("write_ea (%S, %s, %p, %lu, %d)",
|
||||||
attr.ObjectName, name, value, size, flags);
|
attr.ObjectName, name, value, size, flags);
|
||||||
|
|
||||||
/* Samba hides the user namespace from Windows clients. If we get a
|
/* Early open if handle is NULL. This allows to return error codes like
|
||||||
user namespace item, we remove the leading namespace from the name.
|
ENOENT before we actually check for the correctness of the EA name and
|
||||||
This keeps tools like attr/getfattr/setfattr happy. Otherwise
|
stuff like that. */
|
||||||
setting the EA fails as if we don't have the permissions. */
|
if (!hdl)
|
||||||
/* Samba hides the user namespace from Windows clients. If we try to
|
|
||||||
retrieve a user namespace item, we remove the leading namespace from
|
|
||||||
the name, otherwise the search fails. */
|
|
||||||
if (!pc.fs_is_samba ())
|
|
||||||
/* nothing to do */;
|
|
||||||
else if (ascii_strncasematch (name, "user.", 5))
|
|
||||||
name += 5;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
set_errno (ENOATTR);
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +265,9 @@ write_ea (HANDLE hdl, path_conv &pc, const char *name, const char *value,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip "user." prefix. */
|
||||||
|
name += 5;
|
||||||
|
|
||||||
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
|
if ((nlen = strlen (name)) >= MAX_EA_NAME_LEN)
|
||||||
{
|
{
|
||||||
set_errno (EINVAL);
|
set_errno (EINVAL);
|
||||||
|
|
Loading…
Reference in New Issue