nwnss: enable OtherFS XATTR smoke roundtrip

This commit is contained in:
OpenAI
2026-06-19 07:58:42 +00:00
committed by Mario Fetka
parent 91d459f6b8
commit f3b2291a09
3 changed files with 231 additions and 26 deletions

View File

@@ -15,6 +15,7 @@
#include <errno.h>
#include <string.h>
#include <sys/xattr.h>
#include <lsa/lsaPrivate.h>
@@ -119,25 +120,62 @@ NssLsaXattrUserspaceInodePrivate(struct inode *inode)
return inode ? (LsaInode_s *)inode->i_private : NULL;
}
static const char *
NssLsaXattrUserspaceOtherfsPath(const NssLsaXattrUserspace_s *xattr)
{
const char *path;
path = NssUserspaceProviderPath(xattr ? &xattr->provider : NULL);
return path && path[0] != '\0' ? path : NULL;
}
static int
NssLsaXattrUserspaceOtherfsHostName(const char *name,
char *buffer,
size_t bufferSize)
{
return NssLsaXattrUserspaceOtherfsName(name, buffer, bufferSize);
}
ssize_t
NssLsaXattrUserspaceGet(NssLsaXattrUserspace_s *xattr,
const char *name,
void *value,
size_t size)
{
char hostName[256];
const char *path;
ssize_t result;
if (!xattr || !name)
{
return -EINVAL;
}
if (NssLsaXattrUserspaceGetProvider(xattr) !=
NSS_USERSPACE_PROVIDER_NSS_VOLUME)
switch (NssLsaXattrUserspaceGetProvider(xattr))
{
return -ENOTSUP;
case NSS_USERSPACE_PROVIDER_NSS_VOLUME:
return netware_getxattr(NssLsaXattrUserspaceDentry(xattr),
NssLsaXattrUserspaceNssName(name),
value,
size);
case NSS_USERSPACE_PROVIDER_OTHERFS_XATTR:
path = NssLsaXattrUserspaceOtherfsPath(xattr);
if (!path)
{
return -EINVAL;
}
result = NssLsaXattrUserspaceOtherfsHostName(name,
hostName,
sizeof(hostName));
if (result != 0)
{
return result;
}
result = getxattr(path, hostName, value, size);
return result < 0 ? -errno : result;
default:
return -ENOTSUP;
}
return netware_getxattr(NssLsaXattrUserspaceDentry(xattr),
NssLsaXattrUserspaceNssName(name),
value,
size);
}
ssize_t
@@ -146,36 +184,76 @@ NssLsaXattrUserspaceSet(NssLsaXattrUserspace_s *xattr,
const void *value,
size_t size)
{
char hostName[256];
const char *path;
int result;
if (!xattr || !name)
{
return -EINVAL;
}
if (NssLsaXattrUserspaceGetProvider(xattr) !=
NSS_USERSPACE_PROVIDER_NSS_VOLUME)
switch (NssLsaXattrUserspaceGetProvider(xattr))
{
return -ENOTSUP;
case NSS_USERSPACE_PROVIDER_NSS_VOLUME:
return netware_setxattr(NssLsaXattrUserspaceDentry(xattr),
NssLsaXattrUserspaceNssName(name),
value,
size);
case NSS_USERSPACE_PROVIDER_OTHERFS_XATTR:
path = NssLsaXattrUserspaceOtherfsPath(xattr);
if (!path)
{
return -EINVAL;
}
result = NssLsaXattrUserspaceOtherfsHostName(name,
hostName,
sizeof(hostName));
if (result != 0)
{
return result;
}
result = setxattr(path, hostName, value, size, 0);
return result < 0 ? -errno : result;
default:
return -ENOTSUP;
}
return netware_setxattr(NssLsaXattrUserspaceDentry(xattr),
NssLsaXattrUserspaceNssName(name),
value,
size);
}
int
NssLsaXattrUserspaceRemove(NssLsaXattrUserspace_s *xattr,
const char *name)
{
char hostName[256];
const char *path;
int result;
if (!xattr || !name)
{
return -EINVAL;
}
if (NssLsaXattrUserspaceGetProvider(xattr) !=
NSS_USERSPACE_PROVIDER_NSS_VOLUME)
switch (NssLsaXattrUserspaceGetProvider(xattr))
{
return -ENOTSUP;
case NSS_USERSPACE_PROVIDER_NSS_VOLUME:
return netware_removexattr(NssLsaXattrUserspaceDentry(xattr),
NssLsaXattrUserspaceNssName(name));
case NSS_USERSPACE_PROVIDER_OTHERFS_XATTR:
path = NssLsaXattrUserspaceOtherfsPath(xattr);
if (!path)
{
return -EINVAL;
}
result = NssLsaXattrUserspaceOtherfsHostName(name,
hostName,
sizeof(hostName));
if (result != 0)
{
return result;
}
result = removexattr(path, hostName);
return result < 0 ? -errno : result;
default:
return -ENOTSUP;
}
return netware_removexattr(NssLsaXattrUserspaceDentry(xattr),
NssLsaXattrUserspaceNssName(name));
}
#endif /* NSS_USERSPACE */

View File

@@ -1,3 +1,4 @@
add_executable(test_nwnss_xattr test_nwnss_xattr.c)
target_link_libraries(test_nwnss_xattr PRIVATE mars_nwe::nwnss)
add_test(NAME nwnss.xattr COMMAND test_nwnss_xattr)
set_tests_properties(nwnss.xattr PROPERTIES SKIP_RETURN_CODE 77)

View File

@@ -3,7 +3,10 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/xattr.h>
#include <unistd.h>
#define CHECK(expr) \
do { \
@@ -13,12 +16,103 @@
} \
} while (0)
#define SKIP_CODE 77
static int is_xattr_unsupported(int err)
{
return err == -ENOTSUP || err == -EOPNOTSUPP || err == -ENOSYS ||
err == -EPERM || err == -EACCES;
}
static int make_temp_file(char *path, size_t pathSize)
{
const char *tmpdir;
int fd;
tmpdir = getenv("TMPDIR");
if (!tmpdir || tmpdir[0] == '\0')
{
tmpdir = ".";
}
if (snprintf(path, pathSize, "%s/nwnss-xattr-XXXXXX", tmpdir) < 0 ||
strlen(path) >= pathSize)
{
return -ENAMETOOLONG;
}
fd = mkstemp(path);
if (fd < 0)
{
return -errno;
}
close(fd);
return 0;
}
static int check_otherfs_roundtrip(NssLsaXattrUserspace_s *xattr,
const char *nssName,
const char *expectedHostName,
const char *payload)
{
char hostName[128];
char hostValue[128];
char nssValue[128];
ssize_t got;
ssize_t result;
CHECK(NssLsaXattrUserspaceOtherfsName(nssName,
hostName,
sizeof(hostName)) == 0);
CHECK(strcmp(hostName, expectedHostName) == 0);
result = NssLsaXattrUserspaceSet(xattr,
nssName,
payload,
strlen(payload));
if (is_xattr_unsupported((int)result))
{
fprintf(stderr,
"SKIP/WARN: host filesystem does not allow user xattrs on test file\n");
return SKIP_CODE;
}
CHECK(result == 0);
memset(hostValue, 0, sizeof(hostValue));
got = getxattr(NssUserspaceProviderPath(NssLsaXattrUserspaceProvider(xattr)),
expectedHostName,
hostValue,
sizeof(hostValue));
CHECK(got == (ssize_t)strlen(payload));
CHECK(memcmp(hostValue, payload, strlen(payload)) == 0);
memset(nssValue, 0, sizeof(nssValue));
got = NssLsaXattrUserspaceGet(xattr,
nssName,
nssValue,
sizeof(nssValue));
CHECK(got == (ssize_t)strlen(payload));
CHECK(memcmp(nssValue, payload, strlen(payload)) == 0);
got = NssLsaXattrUserspaceGet(xattr, nssName, NULL, 0);
CHECK(got == (ssize_t)strlen(payload));
CHECK(NssLsaXattrUserspaceRemove(xattr, nssName) == 0);
got = getxattr(NssUserspaceProviderPath(NssLsaXattrUserspaceProvider(xattr)),
expectedHostName,
hostValue,
sizeof(hostValue));
CHECK(got < 0 && errno == ENODATA);
return 0;
}
int main(void)
{
NssUserspaceProvider_s provider;
NssLsaXattrUserspace_s xattr;
VolumeID_t volumeId;
char hostName[128];
char tempPath[4096];
int result;
NssUserspaceProviderInit(&provider);
CHECK(NssUserspaceProviderGetKind(&provider) == NSS_USERSPACE_PROVIDER_UNSET);
@@ -65,17 +159,49 @@ int main(void)
CHECK(strcmp(NssLsaXattrUserspaceNssName("netware.metadata"),
"metadata") == 0);
CHECK(NssLsaXattrUserspaceInitOtherfsPath(&xattr, ".") == 0);
CHECK(make_temp_file(tempPath, sizeof(tempPath)) == 0);
result = NssLsaXattrUserspaceInitOtherfsPath(&xattr, tempPath);
if (result != 0)
{
unlink(tempPath);
CHECK(result == 0);
}
CHECK(NssLsaXattrUserspaceGetProvider(&xattr) ==
NSS_USERSPACE_PROVIDER_OTHERFS_XATTR);
CHECK(NssLsaXattrUserspaceOtherfsName("netware.trustees",
hostName,
sizeof(hostName)) == 0);
hostName,
sizeof(hostName)) == 0);
CHECK(strcmp(hostName, "user.netware.trustees") == 0);
CHECK(NssLsaXattrUserspaceGet(&xattr,
"netware.metadata",
NULL,
0) == -ENOTSUP);
result = check_otherfs_roundtrip(&xattr,
"netware.metadata",
"user.netware.metadata",
"metadata:v1;rights=rwcemf");
if (result == SKIP_CODE)
{
unlink(tempPath);
return SKIP_CODE;
}
CHECK(result == 0);
result = check_otherfs_roundtrip(&xattr,
"metadata",
"user.netware.metadata",
"metadata:v2;name=short");
CHECK(result == 0);
result = check_otherfs_roundtrip(&xattr,
"user.netware.metadata",
"user.netware.metadata",
"metadata:v3;direct-host-name");
CHECK(result == 0);
result = check_otherfs_roundtrip(&xattr,
"netware.trustees",
"user.netware.trustees",
"trustee:1001:RWCEMF");
CHECK(result == 0);
unlink(tempPath);
return 0;
}