diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bb730f..79fcf6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ option(ENABLE_XATTR "Should we build Mars Nwe with extended attribute support?" option(MARS_NWE_INSTALL_DOSUTILS "Install DOS client utilities" ON) option(MARS_NWE_INSTALL_NEW_DOSUTILS "Install the new/experimental DOS client utilities instead of legacy netold.exe" OFF) option(MARS_NWE_BUILD_TESTS "Build optional mars_nwe integration tests" OFF) +option(MARS_NWE_BUILD_NWFS_TESTS "Build libnwfs unit tests" OFF) option(ENABLE_DIRECTORY "Build the optional nwdirectory/TinyLDAP subsystem" OFF) option(MARS_NWE_BUILD_MATRIXSSL_PROGRAMS "Build MatrixSSL example apps, tests and helper tools" OFF) @@ -260,6 +261,7 @@ add_subdirectory(third_party/matrixssl) # MatrixSSL, which stays a native TLS/crypto provider. add_subdirectory(src/core) add_subdirectory(src/ssl) +add_subdirectory(src/nwfs) if(ENABLE_DIRECTORY) # Bundled FLAIM storage stack. Keep the imported sources unchanged; the CMake @@ -334,6 +336,10 @@ add_subdirectory(src) add_subdirectory(opt) add_subdirectory(sys) +if(MARS_NWE_BUILD_NWFS_TESTS) + add_subdirectory(tests/nwfs) +endif() + if(MARS_NWE_BUILD_TESTS) add_subdirectory(tests) endif() diff --git a/include/nwfs/zXattr.h b/include/nwfs/zXattr.h new file mode 100644 index 0000000..07e92a7 --- /dev/null +++ b/include/nwfs/zXattr.h @@ -0,0 +1,260 @@ +/**************************************************************************** + | + | (C) Copyright 2005 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) support module + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2006-11-14 05:57:30 +0530 (Tue, 14 Nov 2006) $ + | + | $RCSfile$ + | $Revision: 1632 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Defines the pairs for the netware extended attributes. + +-------------------------------------------------------------------------*/ + +#ifndef _ZXATTR_H_ +#define _ZXATTR_H_ 1 + +#ifndef _ZOMNI_H_ +#include +#endif + +#ifndef _ZPARAMS_H_ +#include +#endif + +#define zNW_PREFIX "netware." +#define zNW_NCPSTAT zNW_PREFIX "ncpstat" +#define zNW_QUOTA zNW_PREFIX "quota" +#define zNW_METADATA zNW_PREFIX "metadata" +#define zNW_USERQUOTA zNW_PREFIX "userquota" +//#define zNW_TRUSTEE zNW_PREFIX "trustee" + +#define zNW_BYTEORDER 0xfeff +#define zNW_NCPSTAT_VERSION 1 +#define zNW_QUOTA_VERSION 2 +#define zNW_METADATA_VERSION 1 +#define zNW_USERQUOTA_VERSION 1 +//#define zNW_TRUSTEE_VERSION 1 + +#define zNW_ALLOWED_MODIFY_FLAGS (zMOD_FILE_ATTRIBUTES \ + | zMOD_CREATED_TIME \ + | zMOD_MODIFIED_TIME \ + | zMOD_ACCESSED_TIME) + +typedef struct zNW_ncpstat_s { + WORD nws_byteorder; + WORD nws_version; + LONG nws_reserved_1; + QUAD nws_info_mask; /* Modify information indicated by mask + * (see zParams.h zMOD_*) */ + QUAD nws_file_attributes;/* All the NSS file attributes + * (see zParams.h) */ + QUAD nws_file_attr_mask; /* All the NSS file attributes */ + QUAD nws_zid; /* File ID, for hard links, this will be + * the secondary zid */ + QUAD nws_zid_primary; /* Primary ZID */ + QUAD nws_zid_parent; /* File id of parent */ + GUID_t nws_volume_id; /* 128 bit volume id */ + QUAD nws_size_logical; /* Logical size of the file in bytes */ + QUAD nws_size_physical; /* Physical size of the file in bytes */ + + QUAD nws_created; /* UTC time created */ +// QUAD nws_archived; + QUAD nws_modified; /* UTC time modified */ + QUAD nws_accessed; /* UTC time last accessed */ +// QUAD nws_metaDataModified; +} zNW_ncpstat_s; + +typedef struct zNW_quota_V1_s { + WORD nwq_byteorder; + WORD nwq_version; + LONG nwq_reserved_1; + QUAD nwq_user_used; /* Quota used by user */ + QUAD nwq_user_limit; /* Quota limit assigned to user */ + QUAD nwq_dir_left; /* Quota min left in directory ancestors */ +} zNW_quota_V1_s; + +typedef struct zNW_quota_s { + WORD nwq_byteorder; + WORD nwq_version; + LONG nwq_reserved_1; + QUAD nwq_user_used; /* Quota used by user */ + QUAD nwq_user_limit; /* Quota limit assigned to user */ + QUAD nwq_dir_left; /* Quota min left in directory ancestors */ + QUAD nwq_dir_quota; /* Quota set on the directory */ +} zNW_quota_s; + +/* + * We have picked a value for zMAX_TRUSTEES that will let the + * structure fit in 64K. + */ +#define zMAX_TRUSTEES 2043 + +typedef struct zNW_trustee_s { + GUID_t nwt_id; + QUAD nwt_rights; + QUAD nwt_reserved_2; +} zNW_trustee_s; + +typedef struct zNW_metadata_s { + WORD nwm_byteorder; + WORD nwm_version; + LONG nwm_reserved_1; + QUAD nwm_modify_mask; + QUAD nwm_file_attributes; + QUAD nwm_file_attributes_mask; + + QUAD nwm_time_created; + QUAD nwm_time_archived; + QUAD nwm_time_modified; + QUAD nwm_time_accessed; + + QUAD nwm_time_meta_data_modified; + QUAD nwm_reserved_2; + GUID_t nwm_id_owner; + + GUID_t nwm_id_archiver; + GUID_t nwm_id_modifier; + + GUID_t nwm_id_metadata_modifier; + SQUAD nwm_quota_limit; + LONG nwm_inherited_rights_mask; + LONG nwm_trustee_num; + + zNW_trustee_s nwm_trustee[zMAX_TRUSTEES]; +} zNW_metadata_s; + +/* + * We have picked a value for zMAX_USERS that will let the + * structure fit in 64K. + */ +#define zMAX_XATTR_USERS 2047 + +typedef struct zNW_user_restriction_s { + GUID_t nwur_user; + SQUAD nwur_restriction; + QUAD nwur_reserved_2; +} zNW_user_restriction_s; + +typedef struct zNW_user_quota_s { + WORD nwuq_byteorder; + WORD nwuq_version; + LONG nwuq_num_users; + LONG nwuq_index; + LONG nwuq_reserved_1; + + zNW_user_restriction_s nwuq_user[zMAX_XATTR_USERS]; +} zNW_user_quota_s; + + +#if 0 +#define zMAX_FDN_NAME 256 +#define zMAX_XATTR_USERS 124 + +typedef struct zNW_user_restriction_s { + QUAD nwur_restriction; + QUAD nwur_reserved_2; + unicode_t nwur_dnsname[zMAX_FDN_NAME]; +} zNW_user_restriction_s; + +typedef struct zNW_user_quota_s { + WORD nwuq_byteorder; + WORD nwuq_version; + LONG nwuq_num_users; + LONG nwuq_index; + LONG nwuq_reserved_1; + + zNW_user_restriction_s nwuq_user[zMAX_XATTR_USERS]; +} zNW_user_quota_s; + +typedef struct zNW_user_trustee_s{ + QUAD nwut_rights; + QUAD nwut_reserved_2; + unicode_t nwut_dnsname[zMAX_FDN_NAME]; +} zNW_user_trustee_s; + +typedef struct zNW_trustee_name_s { + WORD nwtn_byteorder; + WORD nwtn_version; + LONG nwtn_num_trustees; + LONG nwtn_index; + LONG nwtn_reserved_1; + + zNW_user_trustee_s nwtn_user[zMAX_XATTR_USERS]; +} zNW_trustee_name_s; +#endif + + +/* + * mars-nwe userspace adaptation boundary. + * + * The media structures above keep the imported OES/NSS names and layout. + * The helpers below are intentionally small: they initialise and validate the + * OES-compatible netware.* payloads without pulling in the NSS kernel, VFS, + * Semantic Agent or MPK runtime. + */ +#include + +#define NWFS_METADATA_FIXED_SIZE offsetof(zNW_metadata_s, nwm_trustee) +#define NWFS_USERQUOTA_FIXED_SIZE offsetof(zNW_user_quota_s, nwuq_user) +#define NWFS_QUOTA_BACKEND_ENV "NWFS_QUOTA_BACKEND" +#define NWFS_QUOTA_BACKEND_LINUXQUOTA "LINUXQUOTA" +#define NWFS_QUOTA_BACKEND_METADATAONLY "METADATAONLY" +#define NWFS_QUOTA_BACKEND_NSS "NSS" + +typedef enum nwfs_status_e { + NWFS_OK = 0, + NWFS_ERR_INVAL = -1, + NWFS_ERR_RANGE = -2, + NWFS_ERR_VERSION = -3, + NWFS_ERR_BYTEORDER = -4 +} nwfs_status_e; + +void nwfs_ncpstat_init(zNW_ncpstat_s *ncpstat); +int nwfs_ncpstat_validate(const zNW_ncpstat_s *ncpstat, size_t size); + +void nwfs_metadata_init(zNW_metadata_s *metadata); +int nwfs_metadata_validate(const zNW_metadata_s *metadata, size_t size); +size_t nwfs_metadata_size_for_trustees(LONG trustee_num); +LONG nwfs_metadata_max_trustees_for_size(size_t size); + +void nwfs_quota_init(zNW_quota_s *quota); +int nwfs_quota_validate(const zNW_quota_s *quota, size_t size); + +void nwfs_userquota_init(zNW_user_quota_s *userquota); +int nwfs_userquota_validate(const zNW_user_quota_s *userquota, size_t size); +size_t nwfs_userquota_size_for_users(LONG user_num); +LONG nwfs_userquota_max_users_for_size(size_t size); + +int nwfs_metadata_set_file_attributes(zNW_metadata_s *metadata, QUAD attributes); +int nwfs_metadata_get_file_attributes(const zNW_metadata_s *metadata, QUAD *attributes); +int nwfs_metadata_set_inherited_rights_mask(zNW_metadata_s *metadata, LONG inherited_rights_mask); +int nwfs_metadata_get_inherited_rights_mask(const zNW_metadata_s *metadata, LONG *inherited_rights_mask); +int nwfs_metadata_set_trustees(zNW_metadata_s *metadata, const zNW_trustee_s *trustees, LONG trustee_num); +int nwfs_metadata_get_trustees(const zNW_metadata_s *metadata, zNW_trustee_s *trustees, LONG trustee_capacity, LONG *trustee_num); + +#endif diff --git a/src/nwfs/CMakeLists.txt b/src/nwfs/CMakeLists.txt new file mode 100644 index 0000000..1ab1784 --- /dev/null +++ b/src/nwfs/CMakeLists.txt @@ -0,0 +1,32 @@ +add_library(nwfs SHARED + lsaComn.c + lsaXattr.c) +add_library(mars_nwe::nwfs ALIAS nwfs) + +set_target_properties(nwfs PROPERTIES + OUTPUT_NAME nwfs + VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" + SOVERSION "${VERSION_MAJOR}") + +target_compile_features(nwfs PRIVATE c_std_99) +target_include_directories(nwfs + PUBLIC + "$" + "$" + "$" + "$" + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}") + +install(TARGETS nwfs + EXPORT mars-nwe-nwfs-targets + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + +install(FILES "${CMAKE_SOURCE_DIR}/include/nwfs/zXattr.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/nwfs") + +install(EXPORT mars-nwe-nwfs-targets + NAMESPACE mars_nwe:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/mars-nwe") diff --git a/src/nwfs/lsaComn.c b/src/nwfs/lsaComn.c new file mode 100644 index 0000000..5ac11b3 --- /dev/null +++ b/src/nwfs/lsaComn.c @@ -0,0 +1,232 @@ +/**************************************************************************** + | + | (C) Copyright 1995 - 2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) support module + | + |--------------------------------------------------------------------------- + | mars-nwe userspace adaptation of the LSA common metadata helpers. This file + | keeps the imported OES/NSS netware.* media structures as the compatibility + | boundary and strips the original NSS kernel/VFS/runtime plumbing. + +-------------------------------------------------------------------------*/ + +#include +#include +#include "lsaPrivate.h" + +int nwfs_validate_header(WORD byteorder, WORD version, WORD expected_version) +{ + if (byteorder != zNW_BYTEORDER) { + return NWFS_ERR_BYTEORDER; + } + if (version != expected_version) { + return NWFS_ERR_VERSION; + } + return NWFS_OK; +} + +int nwfs_validate_count(LONG count, LONG max_count) +{ + if (count > max_count) { + return NWFS_ERR_RANGE; + } + return NWFS_OK; +} + +void nwfs_ncpstat_init(zNW_ncpstat_s *ncpstat) +{ + if (ncpstat == NULL) { + return; + } + + memset(ncpstat, 0, sizeof(*ncpstat)); + ncpstat->nws_byteorder = zNW_BYTEORDER; + ncpstat->nws_version = zNW_NCPSTAT_VERSION; +} + +int nwfs_ncpstat_validate(const zNW_ncpstat_s *ncpstat, size_t size) +{ + if (ncpstat == NULL) { + return NWFS_ERR_INVAL; + } + if (size < sizeof(*ncpstat)) { + return NWFS_ERR_RANGE; + } + return nwfs_validate_header(ncpstat->nws_byteorder, + ncpstat->nws_version, + zNW_NCPSTAT_VERSION); +} + +void nwfs_metadata_init(zNW_metadata_s *metadata) +{ + if (metadata == NULL) { + return; + } + + memset(metadata, 0, sizeof(*metadata)); + metadata->nwm_byteorder = zNW_BYTEORDER; + metadata->nwm_version = zNW_METADATA_VERSION; + metadata->nwm_file_attributes_mask = ~(QUAD)0; + metadata->nwm_inherited_rights_mask = (LONG)~0U; +} + +size_t nwfs_metadata_size_for_trustees(LONG trustee_num) +{ + if (trustee_num < 0 || trustee_num > zMAX_TRUSTEES) { + return 0; + } + return NWFS_METADATA_FIXED_SIZE + ((size_t)trustee_num * sizeof(zNW_trustee_s)); +} + +LONG nwfs_metadata_max_trustees_for_size(size_t size) +{ + size_t count; + + if (size < NWFS_METADATA_FIXED_SIZE) { + return -1; + } + + count = (size - NWFS_METADATA_FIXED_SIZE) / sizeof(zNW_trustee_s); + if (count > zMAX_TRUSTEES) { + count = zMAX_TRUSTEES; + } + return (LONG)count; +} + +int nwfs_metadata_validate(const zNW_metadata_s *metadata, size_t size) +{ + int rc; + size_t needed; + + if (metadata == NULL) { + return NWFS_ERR_INVAL; + } + if (size < NWFS_METADATA_FIXED_SIZE) { + return NWFS_ERR_RANGE; + } + + rc = nwfs_validate_header(metadata->nwm_byteorder, + metadata->nwm_version, + zNW_METADATA_VERSION); + if (rc != NWFS_OK) { + return rc; + } + rc = nwfs_validate_count(metadata->nwm_trustee_num, zMAX_TRUSTEES); + if (rc != NWFS_OK) { + return rc; + } + + needed = nwfs_metadata_size_for_trustees(metadata->nwm_trustee_num); + if (needed == 0 || size < needed) { + return NWFS_ERR_RANGE; + } + + return NWFS_OK; +} + +void nwfs_quota_init(zNW_quota_s *quota) +{ + if (quota == NULL) { + return; + } + + memset(quota, 0, sizeof(*quota)); + quota->nwq_byteorder = zNW_BYTEORDER; + quota->nwq_version = zNW_QUOTA_VERSION; +} + +int nwfs_quota_validate(const zNW_quota_s *quota, size_t size) +{ + if (quota == NULL) { + return NWFS_ERR_INVAL; + } + if (size < sizeof(*quota)) { + return NWFS_ERR_RANGE; + } + return nwfs_validate_header(quota->nwq_byteorder, + quota->nwq_version, + zNW_QUOTA_VERSION); +} + +void nwfs_userquota_init(zNW_user_quota_s *userquota) +{ + if (userquota == NULL) { + return; + } + + memset(userquota, 0, sizeof(*userquota)); + userquota->nwuq_byteorder = zNW_BYTEORDER; + userquota->nwuq_version = zNW_USERQUOTA_VERSION; +} + +size_t nwfs_userquota_size_for_users(LONG user_num) +{ + if (user_num < 0 || user_num > zMAX_XATTR_USERS) { + return 0; + } + return NWFS_USERQUOTA_FIXED_SIZE + ((size_t)user_num * sizeof(zNW_user_restriction_s)); +} + +LONG nwfs_userquota_max_users_for_size(size_t size) +{ + size_t count; + + if (size < NWFS_USERQUOTA_FIXED_SIZE) { + return -1; + } + + count = (size - NWFS_USERQUOTA_FIXED_SIZE) / sizeof(zNW_user_restriction_s); + if (count > zMAX_XATTR_USERS) { + count = zMAX_XATTR_USERS; + } + return (LONG)count; +} + +int nwfs_userquota_validate(const zNW_user_quota_s *userquota, size_t size) +{ + int rc; + size_t needed; + + if (userquota == NULL) { + return NWFS_ERR_INVAL; + } + if (size < NWFS_USERQUOTA_FIXED_SIZE) { + return NWFS_ERR_RANGE; + } + + rc = nwfs_validate_header(userquota->nwuq_byteorder, + userquota->nwuq_version, + zNW_USERQUOTA_VERSION); + if (rc != NWFS_OK) { + return rc; + } + rc = nwfs_validate_count(userquota->nwuq_num_users, zMAX_XATTR_USERS); + if (rc != NWFS_OK) { + return rc; + } + + needed = nwfs_userquota_size_for_users(userquota->nwuq_num_users); + if (needed == 0 || size < needed) { + return NWFS_ERR_RANGE; + } + + return NWFS_OK; +} diff --git a/src/nwfs/lsaPrivate.h b/src/nwfs/lsaPrivate.h new file mode 100644 index 0000000..ebe2219 --- /dev/null +++ b/src/nwfs/lsaPrivate.h @@ -0,0 +1,40 @@ +/**************************************************************************** + | + | (C) Copyright 1995 - 2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) support module + | + |--------------------------------------------------------------------------- + | mars-nwe userspace adaptation: private declarations shared by the initial + | libnwfs.so implementation. The original kernel/VFS/MPK hooks are + | intentionally not exposed here. + +-------------------------------------------------------------------------*/ + +#ifndef _LSAPRIVATE_H_ +#define _LSAPRIVATE_H_ 1 + +#include +#include + +int nwfs_validate_header(WORD byteorder, WORD version, WORD expected_version); +int nwfs_validate_count(LONG count, LONG max_count); + +#endif diff --git a/src/nwfs/lsaXattr.c b/src/nwfs/lsaXattr.c new file mode 100644 index 0000000..7504711 --- /dev/null +++ b/src/nwfs/lsaXattr.c @@ -0,0 +1,152 @@ +/**************************************************************************** + | + | (C) Copyright 1995 - 2000 Novell, Inc. + | All Rights Reserved. + | + | This program is free software; you can redistribute it and/or + | modify it under the terms of version 2 of the GNU General Public + | License as published by the Free Software Foundation. + | + | This program is distributed in the hope that it will be useful, + | but WITHOUT ANY WARRANTY; without even the implied warranty of + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + | GNU General Public License for more details. + | + | You should have received a copy of the GNU General Public License + | along with this program; if not, contact Novell, Inc. + | + | To contact Novell about this file by physical or electronic mail, + | you may find current contact information at www.novell.com + | + |*************************************************************************** + | + | Novell Storage Services (NSS) support module + | + |--------------------------------------------------------------------------- + | mars-nwe userspace adaptation of the LSA netware.* xattr helpers. This is + | not a wrapper around NSS: it operates directly on the adapted OES/NSS GPL-2.0 + | media structures that mars-nwe will store in netware.metadata, netware.quota + | and netware.userquota xattrs. + +-------------------------------------------------------------------------*/ + +#include +#include +#include "lsaPrivate.h" + +int nwfs_metadata_set_file_attributes(zNW_metadata_s *metadata, QUAD attributes) +{ + int rc = nwfs_metadata_validate(metadata, sizeof(*metadata)); + + if (rc != NWFS_OK) { + return rc; + } + + metadata->nwm_modify_mask |= zMOD_FILE_ATTRIBUTES; + metadata->nwm_file_attributes = attributes; + metadata->nwm_file_attributes_mask = ~(QUAD)0; + return NWFS_OK; +} + +int nwfs_metadata_get_file_attributes(const zNW_metadata_s *metadata, QUAD *attributes) +{ + int rc = nwfs_metadata_validate(metadata, + nwfs_metadata_size_for_trustees(metadata ? metadata->nwm_trustee_num : 0)); + + if (rc != NWFS_OK) { + return rc; + } + if (attributes == NULL) { + return NWFS_ERR_INVAL; + } + + *attributes = metadata->nwm_file_attributes; + return NWFS_OK; +} + +int nwfs_metadata_set_inherited_rights_mask(zNW_metadata_s *metadata, LONG inherited_rights_mask) +{ + int rc = nwfs_metadata_validate(metadata, sizeof(*metadata)); + + if (rc != NWFS_OK) { + return rc; + } + + metadata->nwm_inherited_rights_mask = inherited_rights_mask; + return NWFS_OK; +} + +int nwfs_metadata_get_inherited_rights_mask(const zNW_metadata_s *metadata, LONG *inherited_rights_mask) +{ + int rc = nwfs_metadata_validate(metadata, + nwfs_metadata_size_for_trustees(metadata ? metadata->nwm_trustee_num : 0)); + + if (rc != NWFS_OK) { + return rc; + } + if (inherited_rights_mask == NULL) { + return NWFS_ERR_INVAL; + } + + *inherited_rights_mask = metadata->nwm_inherited_rights_mask; + return NWFS_OK; +} + +int nwfs_metadata_set_trustees(zNW_metadata_s *metadata, const zNW_trustee_s *trustees, LONG trustee_num) +{ + int rc; + + if (metadata == NULL) { + return NWFS_ERR_INVAL; + } + if (trustee_num < 0 || trustee_num > zMAX_TRUSTEES) { + return NWFS_ERR_RANGE; + } + if (trustee_num != 0 && trustees == NULL) { + return NWFS_ERR_INVAL; + } + + rc = nwfs_metadata_validate(metadata, sizeof(*metadata)); + if (rc != NWFS_OK) { + return rc; + } + + if (trustee_num != 0) { + memcpy(metadata->nwm_trustee, trustees, + (size_t)trustee_num * sizeof(metadata->nwm_trustee[0])); + } + metadata->nwm_trustee_num = trustee_num; + return NWFS_OK; +} + +int nwfs_metadata_get_trustees(const zNW_metadata_s *metadata, + zNW_trustee_s *trustees, + LONG trustee_capacity, + LONG *trustee_num) +{ + int rc; + + if (metadata == NULL || trustee_num == NULL) { + return NWFS_ERR_INVAL; + } + + rc = nwfs_metadata_validate(metadata, + nwfs_metadata_size_for_trustees(metadata->nwm_trustee_num)); + if (rc != NWFS_OK) { + return rc; + } + + *trustee_num = metadata->nwm_trustee_num; + if (metadata->nwm_trustee_num == 0) { + return NWFS_OK; + } + if (trustees == NULL) { + return NWFS_OK; + } + if (trustee_capacity < metadata->nwm_trustee_num) { + return NWFS_ERR_RANGE; + } + + memcpy(trustees, metadata->nwm_trustee, + (size_t)metadata->nwm_trustee_num * sizeof(metadata->nwm_trustee[0])); + return NWFS_OK; +} diff --git a/tests/nwfs/CMakeLists.txt b/tests/nwfs/CMakeLists.txt new file mode 100644 index 0000000..9f59a37 --- /dev/null +++ b/tests/nwfs/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(nwfs_xattr_roundtrip_test nwfs_xattr_roundtrip_test.c) +target_link_libraries(nwfs_xattr_roundtrip_test PRIVATE mars_nwe::nwfs) +add_test(NAME nwfs_xattr_roundtrip_test COMMAND nwfs_xattr_roundtrip_test) diff --git a/tests/nwfs/nwfs_xattr_roundtrip_test.c b/tests/nwfs/nwfs_xattr_roundtrip_test.c new file mode 100644 index 0000000..eb3997d --- /dev/null +++ b/tests/nwfs/nwfs_xattr_roundtrip_test.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#define CHECK(expr) do { \ + if (!(expr)) { \ + fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #expr); \ + return 1; \ + } \ +} while (0) + +static void fill_guid(GUID_t *guid, unsigned seed) +{ + guid->timeLow = 0x10000000u + seed; + guid->timeMid = (WORD)(0x2000u + seed); + guid->timeHighAndVersion = (WORD)(0x3000u + seed); + guid->clockSeqHighAndReserved = (BYTE)(0x40u + seed); + guid->clockSeqLow = (BYTE)(0x50u + seed); + for (size_t i = 0; i < sizeof(guid->node); ++i) { + guid->node[i] = (BYTE)(seed + i); + } +} + +int main(void) +{ + zNW_ncpstat_s ncpstat; + zNW_metadata_s metadata; + zNW_quota_s quota; + zNW_user_quota_s userquota; + zNW_trustee_s trustees[2]; + zNW_trustee_s copy[2]; + QUAD attributes = 0; + LONG irm = 0; + LONG trustee_num = 0; + + nwfs_ncpstat_init(&ncpstat); + CHECK(nwfs_ncpstat_validate(&ncpstat, sizeof(ncpstat)) == NWFS_OK); + CHECK(ncpstat.nws_byteorder == zNW_BYTEORDER); + CHECK(ncpstat.nws_version == zNW_NCPSTAT_VERSION); + ncpstat.nws_version = zNW_NCPSTAT_VERSION + 1; + CHECK(nwfs_ncpstat_validate(&ncpstat, sizeof(ncpstat)) == NWFS_ERR_VERSION); + + nwfs_metadata_init(&metadata); + CHECK(nwfs_metadata_validate(&metadata, NWFS_METADATA_FIXED_SIZE) == NWFS_OK); + CHECK(metadata.nwm_byteorder == zNW_BYTEORDER); + CHECK(metadata.nwm_version == zNW_METADATA_VERSION); + + CHECK(nwfs_metadata_set_file_attributes(&metadata, 0x00000000000000a5ULL) == NWFS_OK); + CHECK(nwfs_metadata_get_file_attributes(&metadata, &attributes) == NWFS_OK); + CHECK(attributes == 0x00000000000000a5ULL); + CHECK((metadata.nwm_modify_mask & zMOD_FILE_ATTRIBUTES) != 0); + + CHECK(nwfs_metadata_set_inherited_rights_mask(&metadata, 0x000001ffU) == NWFS_OK); + CHECK(nwfs_metadata_get_inherited_rights_mask(&metadata, &irm) == NWFS_OK); + CHECK(irm == 0x000001ffU); + + memset(trustees, 0, sizeof(trustees)); + fill_guid(&trustees[0].nwt_id, 1); + trustees[0].nwt_rights = 0x000001ffU; + fill_guid(&trustees[1].nwt_id, 2); + trustees[1].nwt_rights = 0x00000083U; + CHECK(nwfs_metadata_set_trustees(&metadata, trustees, 2) == NWFS_OK); + CHECK(nwfs_metadata_validate(&metadata, nwfs_metadata_size_for_trustees(2)) == NWFS_OK); + memset(copy, 0, sizeof(copy)); + CHECK(nwfs_metadata_get_trustees(&metadata, copy, 2, &trustee_num) == NWFS_OK); + CHECK(trustee_num == 2); + CHECK(memcmp(copy, trustees, sizeof(trustees)) == 0); + + nwfs_quota_init("a); + quota.nwq_user_used = 1234; + quota.nwq_user_limit = 5678; + quota.nwq_dir_left = 9012; + quota.nwq_dir_quota = 3456; + CHECK(nwfs_quota_validate("a, sizeof(quota)) == NWFS_OK); + CHECK(quota.nwq_byteorder == zNW_BYTEORDER); + CHECK(quota.nwq_version == zNW_QUOTA_VERSION); + CHECK(quota.nwq_user_used == 1234); + CHECK(quota.nwq_user_limit == 5678); + CHECK(quota.nwq_dir_left == 9012); + CHECK(quota.nwq_dir_quota == 3456); + + nwfs_userquota_init(&userquota); + userquota.nwuq_num_users = 1; + userquota.nwuq_index = 7; + fill_guid(&userquota.nwuq_user[0].nwur_user, 3); + userquota.nwuq_user[0].nwur_restriction = 0x12345678LL; + CHECK(nwfs_userquota_validate(&userquota, nwfs_userquota_size_for_users(1)) == NWFS_OK); + CHECK(userquota.nwuq_byteorder == zNW_BYTEORDER); + CHECK(userquota.nwuq_version == zNW_USERQUOTA_VERSION); + CHECK(userquota.nwuq_num_users == 1); + CHECK(userquota.nwuq_index == 7); + CHECK(userquota.nwuq_user[0].nwur_restriction == 0x12345678LL); + + metadata.nwm_byteorder = 0; + CHECK(nwfs_metadata_validate(&metadata, sizeof(metadata)) == NWFS_ERR_BYTEORDER); + + return 0; +}