From 945f8c7b459598af60f9dbe6a2ee5c8bc7812d2d Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Fri, 19 Jun 2026 05:51:49 +0000 Subject: [PATCH] nwnss: import NSS extended attribute runtime --- include/nwnss/internal/NssPageRuntime.h | 20 + include/nwnss/lsa/lsaPrivate.h | 71 ++ include/nwnss/public/zXattr.h | 207 ++++ src/nwnss/CMakeLists.txt | 2 + src/nwnss/comn/common/extAttrBeast.c | 210 +++++ src/nwnss/lsa/lsaXattr.c | 1145 +++++++++++++++++++++++ 6 files changed, 1655 insertions(+) create mode 100644 include/nwnss/lsa/lsaPrivate.h create mode 100644 include/nwnss/public/zXattr.h create mode 100644 src/nwnss/comn/common/extAttrBeast.c create mode 100644 src/nwnss/lsa/lsaXattr.c diff --git a/include/nwnss/internal/NssPageRuntime.h b/include/nwnss/internal/NssPageRuntime.h index 0c2ae13..5cd1483 100644 --- a/include/nwnss/internal/NssPageRuntime.h +++ b/include/nwnss/internal/NssPageRuntime.h @@ -10,8 +10,28 @@ struct page { void *data; }; +struct super_block { + void *s_fs_info; +}; + +struct NssRuntimeTime_s { + long tv_sec; + long tv_nsec; +}; + struct inode { void *i_mapping; + struct super_block *i_sb; + unsigned long i_ino; + long i_mode; + long i_uid; + struct NssRuntimeTime_s i_atime; + struct NssRuntimeTime_s i_ctime; + struct NssRuntimeTime_s i_mtime; +}; + +struct dentry { + struct inode *d_inode; }; typedef struct NssRuntimeKmemCache_s { diff --git a/include/nwnss/lsa/lsaPrivate.h b/include/nwnss/lsa/lsaPrivate.h new file mode 100644 index 0000000..802b248 --- /dev/null +++ b/include/nwnss/lsa/lsaPrivate.h @@ -0,0 +1,71 @@ +/**************************************************************************** + | + | (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 + | + |--------------------------------------------------------------------------- + | + | $Author: taysom $ + | $Date: 2008-05-08 21:52:15 +0530 (Thu, 08 May 2008) $ + | + | $RCSfile$ + | $Revision: 2335 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Define common functions that are private to lsa (should move most + | of lsa.h to here). + +-------------------------------------------------------------------------*/ + +#ifndef _LSAPRIVATE_H_ +#define _LSAPRIVATE_H_ 1 + +#include + +struct dentry; + +extern BOOL LSASendfile; +extern BOOL LSACtimeIsMetadataModTime; +extern BOOL LSAReturnNWmetadata; +extern BOOL LSAUpdateDirAccessTime; +extern LONG LSAPosixPermissionMask; + +extern LONG getMode (LONG attr); +extern LONG getUid (UserID_t *ownerGuid); + +extern ssize_t netware_setxattr ( + struct dentry *dentry, + const char *name, + const void *value, + size_t size); + +extern ssize_t netware_getxattr ( + struct dentry *dentry, + const char *name, + void *value, + size_t size); + +extern int netware_removexattr ( + struct dentry *dentry, + const char *name); + +#endif diff --git a/include/nwnss/public/zXattr.h b/include/nwnss/public/zXattr.h new file mode 100644 index 0000000..6d19ae7 --- /dev/null +++ b/include/nwnss/public/zXattr.h @@ -0,0 +1,207 @@ +/**************************************************************************** + | + | (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 + +#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 + +#endif diff --git a/src/nwnss/CMakeLists.txt b/src/nwnss/CMakeLists.txt index cdf2ad0..feb5e42 100644 --- a/src/nwnss/CMakeLists.txt +++ b/src/nwnss/CMakeLists.txt @@ -186,6 +186,7 @@ add_library(nwnss SHARED comn/common/beastHash.c comn/common/beastRelease.c comn/common/beastClass.c + comn/common/extAttrBeast.c comn/common/comnMacShortName.c comn/common/comnUnicode.c comn/common/registerLSS.c @@ -307,6 +308,7 @@ add_library(nwnss SHARED nss/lib/setErrno.c nss/msg/slab.c nsslnxlib/unilib.c + lsa/lsaXattr.c utcUserland.c) add_library(mars_nwe::nwnss ALIAS nwnss) diff --git a/src/nwnss/comn/common/extAttrBeast.c b/src/nwnss/comn/common/extAttrBeast.c new file mode 100644 index 0000000..28de5d8 --- /dev/null +++ b/src/nwnss/comn/common/extAttrBeast.c @@ -0,0 +1,210 @@ +/**************************************************************************** + | + | (C) Copyright 1995-1997 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 + | + |*************************************************************************** + | + | NetWare Advance File Services (NSS) module + | + |--------------------------------------------------------------------------- + | + | $Author: blarsen $ + | $Date: 2006-01-21 04:09:53 +0530 (Sat, 21 Jan 2006) $ + | + | $RCSfile$ + | $Revision: 1315 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | This defines all of the primitive BEASTS inside of PSS + +-------------------------------------------------------------------------*/ +#include +#include + +#include "comnBeasts.h" +#include "comnParams.h" +#include "comnPublics.h" +#include "zParams.h" +#include "extAttrBeast.h" + +///**************************************************************************** +// * +// *****************************************************************************/ +//STATUS extAttrConstruct( +// GeneralMsg_s *genMsg, +// ExtAttrBeast_s *beast) +//{ +// return zOK; +//} + +/**************************************************************************** + * + *****************************************************************************/ +//void extAttrDestruct( +// ExtAttrBeast_s *beast) +//{ +//} + +/**************************************************************************** + * This function returns metadata information for an extAttrBeast object + *****************************************************************************/ +STATUS EXTATTR_BST_GetInfo( + GeneralMsg_s *genMsg, + RootBeast_s *extAttr_LX, + GetInfoMsg_s *infoMsg) +{ + ExtAttrBeast_s *extAttr = (ExtAttrBeast_s *)extAttr_LX; + zExtAttrInfo_s *extAttrInfo; + statusfunc_t derivedFromGetInfo; + + ASSERT_MPKNSS_LOCK(); +/*--------------------------------------------------------------------------- + * First, call the generic namedBeast information routine and fill in any + * requested named beast information. If it fails, do not continue... + *---------------------------------------------------------------------------*/ + derivedFromGetInfo = COMN_GetNextParentBeastComnOp(extAttr->EAbeastClass, + COMNOPS_INDEX(BST_getInfo),EXTATTR_BST_GetInfo); + if (derivedFromGetInfo(genMsg,extAttr,infoMsg) != zOK) + return(zFAILURE); + +/*--------------------------------------------------------------------------- + * Now, if the caller requested, fill in any extAttr specific information + *---------------------------------------------------------------------------*/ + if ((extAttrInfo = infoMsg->ret_getTypeInfo) == NULL) + return(zOK); /* No type specific info requeted */ + + if (infoMsg->sizeRetGetTypeInfo < sizeof(zExtAttrInfo_s)) + { + SetErrno(genMsg,zERR_BUFFER_TOO_SMALL); + return(zFAILURE); + } + +/*--------------------------------------------------------------------------- + * Make sure the beast is latched to access its meta data + *---------------------------------------------------------------------------*/ + ASSERT_LATCH(&extAttr->EAbeastLatch); + +/*--------------------------------------------------------------------------- + * Return optional information + *---------------------------------------------------------------------------*/ + if (infoMsg->getTypeInfoMask & zGET_EXTATTR_FLAGS) + { + extAttrInfo->extAttrUserFlags = extAttr->EAextAttrUserFlags; + } + + return zOK; +} + + +/**************************************************************************** + * This function modifies metadata information for an extAttr beast object + *****************************************************************************/ +STATUS EXTATTR_BST_ModifyInfo( + GeneralMsg_s *genMsg, + RootBeast_s *extAttr_LX, + ModifyInfoMsg_s *modifyMsg, + Xaction_s *xaction) /* Optional xaction, may be NULL */ +{ + ExtAttrBeast_s *extAttr = (ExtAttrBeast_s *)extAttr_LX; + zExtAttrInfo_s *extAttrInfo; + ASSERT_MPKNSS_LOCK(); +// statusfunc_t derivedFromModifyInfo; + +///*--------------------------------------------------------------------------- +// * First, call the generic namedBeast information routine and fill in any +// * requested named beast information. If it fails, do not continue... +// *---------------------------------------------------------------------------*/ +// derivedFromModifyInfo = BST_GetNextParentMethod(extAttr->EAbeastClass, +// COMNOPS_INDEX(modifyInfo),extAttrModifyInfo); +// if (derivedFromModifyInfo(genMsg,extAttr,modifyMsg) != zOK) +// return(zFAILURE); + +/*--------------------------------------------------------------------------- + * Now, if the caller requested, modify any extAttr specific information + *---------------------------------------------------------------------------*/ + if ((extAttrInfo = modifyMsg->modifyTypeInfo) == NULL) + return(zOK); /* No type specific info to modify */ + + ASSERT_XLATCH(&extAttr->EAbeastLatch); + zASSERT(!(modifyMsg->modifyTypeInfoMask & ~zVALID_MOD_EXTATTR_INFO_MASK)); + if (modifyMsg->modifyTypeInfoMask & zMOD_EXTATTR_FLAGS) + { + extAttr->EAextAttrUserFlags = extAttrInfo->extAttrUserFlags; + if (xaction == NULL) + { + /* No transaction. Just mark the beast dirty and let it get flushed + * at some later point in time */ + COMN_MARK_BEAST_DIRTY(&extAttr->EAroot); + } + else + { + /* We have a transaction. Mark the beast as part of that + * transaction and force write it as part of that transaction */ + COMN_MARK_BEAST_XLOCAL(&extAttr->EAroot,xaction); + if (COMN_ForceBeastWrite(genMsg,extAttr,xaction) != zOK) + { + return zFAILURE; + } + } + } + return zOK; +} + + +/**************************************************************************** + * COMMON OPS definition + * + *****************************************************************************/ + +/*--------------------------------------------------------------------------- + * Defines all of the FileBeast operations + *---------------------------------------------------------------------------*/ +CommonBeastOps_s ExtAttrBeastComnOps = +{ + NULL, /* construct */ + NULL, /* destruct */ + +// cnt NULL, /* BST_getNameUniquifier */ + NULL, /* BST_setupNameTypeSpecificInfo */ + NULL, /* BST_lookupByNameInDirectory*/ + NULL, /* BST_isDirectoryEmpty*/ + NULL, /* BST_addNameToDirectory*/ + NULL, /* BST_removeNameFromDirectory*/ + NULL, /* BST_modifyNameSpaceMaskInDirectory*/ + NULL, /* BST_setMatchAttributesInDirectory*/ + NULL, /* BST_wildcardLookup*/ + + NULL, /* BST_truncateFile*/ + NULL, /* BST_getStorageInfo*/ + NULL, /* BST_getExtentList*/ + NULL, /* BST_getPhysicalExtent*/ + NULL, /* BST_isBlockInBeast*/ + + NULL, /* BST_asyncReadFileBlk*/ + NULL, /* BST_getFileBlk*/ + NULL, /* BST_dfsReadUnits*/ + NULL, /* BST_dfsWriteUnits*/ + + NULL, /* BST_getZID*/ + NULL, /* BST_beastNotify*/ + EXTATTR_BST_GetInfo, /* BST_getInfo*/ + EXTATTR_BST_ModifyInfo, /* BST_modifyInfo*/ + NULL, /* BST_getInfoXML*/ + NULL /* BST_modifyInfoXML*/ +}; diff --git a/src/nwnss/lsa/lsaXattr.c b/src/nwnss/lsa/lsaXattr.c new file mode 100644 index 0000000..d5396e1 --- /dev/null +++ b/src/nwnss/lsa/lsaXattr.c @@ -0,0 +1,1145 @@ +/**************************************************************************** + | + | (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 + | + |--------------------------------------------------------------------------- + | + | $Author: vandana $ + | $Date: 2006-11-14 22:03:40 +0530 (Tue, 14 Nov 2006) $ + | + | $RCSfile$ + | $Revision: 1635 $ + | + |--------------------------------------------------------------------------- + | This module is used to: + | Implement "netware." name space for extended attributes. + +-------------------------------------------------------------------------*/ +#include +#include + +#define _LOOSE_KERNEL_NAMES + +//#include +//#include +//#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef NSS_USERSPACE +static void +mpkEnter(void) +{ +} +static void +mpkExit(void) +{ +} +static struct { + LONG fsuid; +} nssLsaCurrent = { 0 }; +#define current (&nssLsaCurrent) +#endif + +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif + +/* xattr_get_ncpstat: gets attributes used by NCP */ +int xattr_get_ncpstat ( + struct dentry *dentry, + const char *name, + void *value, + size_t size) +{ + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + LsaInode_s *lsaInode = STRUCT(inode, LsaInode_s, li_inode); + zNW_ncpstat_s *ncpstat = value; + LSAInfo_s lsaInfo; + int rc; + +pr("xattr_get_ncpstat"); + + if (value == NULL) + { + return sizeof(*ncpstat); + } + if (size < sizeof(*ncpstat)) + { + return -ERANGE; + } + + mpkEnter(); + rc = LSACOMN_Lookup( &super->sb_volID, inode->i_ino, super->sb_nameSpace, + NULL, &lsaInfo, lsaInode); + if (rc != zOK) + { + rc = nss2linuxError(rc); + goto error; + } + ncpstat->nws_byteorder = zNW_BYTEORDER; + ncpstat->nws_version = zNW_NCPSTAT_VERSION; + ncpstat->nws_reserved_1 = 0; + ncpstat->nws_info_mask = 0; + ncpstat->nws_file_attributes = lsaInfo.fileAttributes; + ncpstat->nws_file_attr_mask = 0; + ncpstat->nws_zid = inode->i_ino; + ncpstat->nws_zid_primary = lsaInfo.zid; + ncpstat->nws_zid_parent = lsaInfo.parentZid; + ncpstat->nws_volume_id = super->sb_volID; + ncpstat->nws_size_logical = lsaInfo.logicalEOF; + ncpstat->nws_size_physical = lsaInfo.dataBytes; + ncpstat->nws_created = lsaInfo.createdTime; +// ncpstat->nws_archived = lsaInfo.archivedTime; + ncpstat->nws_modified = lsaInfo.modifiedTime; + ncpstat->nws_accessed = lsaInfo.accessedTime; +// ncpstat->nws_metaDataModified = lsaInfo.metaDataModifiedTime; + + rc = sizeof(*ncpstat); +error: + mpkExit(); + return rc; +} +/* xattr_set_ncpstat: sets attributes used by NCP */ +int xattr_set_ncpstat ( + struct dentry *dentry, + const char *name, + const void *value, + size_t size) +{ + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + const zNW_ncpstat_s *ncpstat = value; + STATUS rc = 0; + QUAD infoMask; + + typedef struct Stack_s { + zInfo_s zinfo; + } Stack_s; + Stack_s *aStack; + +pr("xattr_set_ncpstat"); + + infoMask = ncpstat->nws_info_mask & zNW_ALLOWED_MODIFY_FLAGS; + if (infoMask != ncpstat->nws_info_mask) + { + return -EINVAL; + } + if (infoMask == 0) + { + return zOK; + } + + mpkEnter(); + STACK_ALLOC_NO_ASTACK(); + +// Check the byte order and version number + + if (infoMask & zMOD_FILE_ATTRIBUTES) + { + aStack->zinfo.std.fileAttributes = ncpstat->nws_file_attributes; + aStack->zinfo.std.fileAttributesModMask = ncpstat->nws_file_attr_mask; + } + if (infoMask & zMOD_CREATED_TIME) + { + aStack->zinfo.time.created = ncpstat->nws_created; + } + if (infoMask & zMOD_MODIFIED_TIME) + { + aStack->zinfo.time.modified = ncpstat->nws_modified; + } + if (infoMask & zMOD_ACCESSED_TIME) + { + aStack->zinfo.time.accessed = ncpstat->nws_accessed; + } + rc = LSACOMN_ModifyInfo(&super->sb_volID, super->sb_nameSpace, + inode->i_ino, infoMask, sizeof(zInfo_s), + zINFO_VERSION_A, &aStack->zinfo); + if (rc != zOK) + { + goto error; + } + if (infoMask & zMOD_FILE_ATTRIBUTES) + { + inode->i_mode = getMode(aStack->zinfo.std.fileAttributes); + } + if (infoMask & zMOD_CREATED_TIME) + { + if (LSACtimeIsMetadataModTime) + { + inode->i_ctime.tv_sec = aStack->zinfo.time.metaDataModified; + } + else + { + inode->i_ctime.tv_sec = aStack->zinfo.time.created; + } + inode->i_ctime.tv_nsec = 0; + } + if (infoMask & zMOD_MODIFIED_TIME) + { + inode->i_mtime.tv_sec = aStack->zinfo.time.modified; + inode->i_mtime.tv_nsec = 0; + } + if (infoMask & zMOD_ACCESSED_TIME) + { + inode->i_atime.tv_nsec = aStack->zinfo.time.accessed; + inode->i_atime.tv_nsec = 0; + } + +error: + STACK_FREE(); + mpkExit(); + return rc ? nss2linuxError(rc) : 0; +} +/* + * xattr_get_quota: gets the lesser of user's quota and + * directory space restriction + */ +int xattr_get_quota ( + struct dentry *dentry, + const char *name, + void *value, + size_t size) +{ + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + LsaInode_s *lsaInode = STRUCT(inode, LsaInode_s, li_inode); + zNW_quota_s *quota = value; + GUID_t guid; + GUID_t *gp = NULL; + int n; + int rc; + +pr("xattr_get_quota"); + + if (value == NULL) + { + return sizeof(*quota); + } + if (size < sizeof(*quota)) + { + return -ERANGE; + } + n = dotlen(name); + if (name[n]) + { /* get guid */ + hex2guid( &name[n+1], &guid); + gp = &guid; + } + mpkEnter(); + rc = LSACOMN_Quotas( &super->sb_volID, inode->i_ino, + super->sb_nameSpace, lsaInode, + gp, quota); + mpkExit(); + return rc ? nss2linuxError(rc) : sizeof(*quota); +} +/* + * xattr_get_metadata: returns file metadata and trustees for back-up. + */ +int xattr_get_metadata ( + struct dentry *dentry, + const char *name, + void *value, + size_t val_size) +{ + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + LsaInode_s *lsaInode = STRUCT(inode, LsaInode_s, li_inode); + zNW_metadata_s *metadata = value; + NINT size = val_size; + int rc; + +pr("xattr_get_metadata"); + + mpkEnter(); + rc = LSACOMN_Metadata( &super->sb_volID, inode->i_ino, + super->sb_nameSpace, lsaInode, + &size, metadata); + mpkExit(); + return rc ? nss2linuxError(rc) : size; +} +int xattr_set_metadata ( + struct dentry *dentry, + const char *name, + const void *value, + size_t size) +{ + const zNW_metadata_s *metadata = value; + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + zInfoC_s *zinfo = NULL; + QUAD infoMask; + NINT metadata_size; + NINT info_size; + int rc; + +pr("xattr_set_metadata"); + + infoMask = metadata->nwm_modify_mask & zNW_METADATA_MASK; + + if (infoMask != metadata->nwm_modify_mask) + { + return -EINVAL; + } + if (infoMask == 0) + { + return zOK; + } + + metadata_size = offsetof(zNW_metadata_s, nwm_trustee); + info_size = sizeof(zInfoC_s) - sizeof(zinfo->variableData); + if (infoMask & zMOD_ALL_TRUSTEES) + { + if (metadata->nwm_trustee_num != 0) + { + metadata_size += metadata->nwm_trustee_num * sizeof(zNW_trustee_s); + info_size += sizeof(zTrusteeInfo_s) * metadata->nwm_trustee_num; + } + else + { + infoMask &= ~zMOD_ALL_TRUSTEES; + } + } + if (metadata_size > size) + { + return -EFAULT; + } + if ((metadata->nwm_byteorder != zNW_BYTEORDER) + || (metadata->nwm_version != zNW_METADATA_VERSION)) + { + return -EINVAL; + } + mpkEnter(); + + zinfo = zalloc(info_size); + if (!zinfo) + { + mpkExit(); + return -ENOMEM; + } + + if (infoMask & zMOD_FILE_ATTRIBUTES) + { + zinfo->std.fileAttributes = metadata->nwm_file_attributes; + zinfo->std.fileAttributesModMask = metadata->nwm_file_attributes_mask; + } + if (infoMask & zMOD_CREATED_TIME) + { + zinfo->time.created = metadata->nwm_time_created; + } + if (infoMask & zMOD_ARCHIVED_TIME) + { + zinfo->time.archived = metadata->nwm_time_archived; + } + if (infoMask & zMOD_MODIFIED_TIME) + { + zinfo->time.modified = metadata->nwm_time_modified; + } + if (infoMask & zMOD_ACCESSED_TIME) + { + zinfo->time.accessed = metadata->nwm_time_accessed; + } + if (infoMask & zMOD_METADATA_MODIFIED_TIME) + { + zinfo->time.metaDataModified = metadata->nwm_time_meta_data_modified; + } + if (infoMask & zMOD_OWNER_ID) + { + zinfo->id.owner = metadata->nwm_id_owner; + } + if (infoMask & zMOD_ARCHIVER_ID) + { + zinfo->id.archiver = metadata->nwm_id_archiver; + } + if (infoMask & zMOD_MODIFIER_ID) + { + zinfo->id.modifier = metadata->nwm_id_modifier; + } + if (infoMask & zMOD_METADATA_MODIFIER_ID) + { + zinfo->id.metaDataModifier = metadata->nwm_id_metadata_modifier; + } + if (infoMask & zMOD_DIR_QUOTA) + { + zinfo->dirQuota.quota = metadata->nwm_quota_limit; + } + if (infoMask & zMOD_INH_RIGHTS_MASK) + { + zinfo->inheritedRightsMask = metadata->nwm_inherited_rights_mask; + } + if (infoMask & zMOD_ALL_TRUSTEES) + { + const zNW_trustee_s *trustee; + zTrusteeInfo_s *acl; + NINT i; + + trustee = metadata->nwm_trustee; + acl = (zTrusteeInfo_s *)zinfo->variableData; + for (i = 0; i < metadata->nwm_trustee_num; i++, acl++, trustee++) + { + acl->trustee = trustee->nwt_id; + acl->rights = trustee->nwt_rights; + } + zinfo->trustees.numEntries = i; + zinfo->trustees.trusteeArray = offsetof(zInfoC_s, variableData); + } + + rc = LSACOMN_ModifyInfo(&super->sb_volID, super->sb_nameSpace, + inode->i_ino, infoMask, info_size, + zINFO_VERSION_C, zinfo); + if (rc != zOK) + { + goto error; + } + if (infoMask & zMOD_FILE_ATTRIBUTES) + { + inode->i_mode = getMode(zinfo->std.fileAttributes); + } + if (infoMask & zMOD_CREATED_TIME) + { + if (LSACtimeIsMetadataModTime) + { + inode->i_ctime.tv_sec = zinfo->time.metaDataModified; + } + else + { + inode->i_ctime.tv_sec = zinfo->time.created; + } + inode->i_ctime.tv_nsec = 0; + } + if (infoMask & zMOD_MODIFIED_TIME) + { + inode->i_mtime.tv_sec = zinfo->time.modified; + inode->i_mtime.tv_nsec = 0; + } + if (infoMask & zMOD_ACCESSED_TIME) + { + inode->i_atime.tv_nsec = zinfo->time.accessed; + inode->i_atime.tv_nsec = 0; + } + if (infoMask & zMOD_OWNER_ID) + { + inode->i_uid = getUid(&zinfo->id.owner); + } + +error: + if (zinfo) + { + free(zinfo); + } + mpkExit(); + return rc ? nss2linuxError(rc) : 0; +} +int xattr_get_volumeinfo ( + struct dentry *dentry, + const char *name, + void *value, + size_t val_size) +{ + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + zVolumeInfo_s *volInfo = value; + NINT size = sizeof(*volInfo); + Key_t volKey; + int rc; + + typedef struct Stack_s { + zInfo_s zinfo; + } Stack_s; + Stack_s *aStack; + +pr("xattr_get_volumeinfo"); + + if (value == NULL) + { + return size; + } + if (val_size < size) + { + return -ERANGE; + } + + mpkEnter(); + STACK_ALLOC_NO_ASTACK(); + + bzero(&aStack->zinfo.vol, sizeof(aStack->zinfo.vol)); + rc = zOpen(super->sb_rootKey, zNO_TASK, zNSPACE_LONG | zMODE_UTF8, + super->sb_volName, + zRR_DONT_UPDATE_ACCESS_TIME, + &volKey); + if (rc != zOK) + { + goto exit; + } + + rc = zGetInfo( volKey, + zGET_VOLUME_INFO | zGET_VOL_SALVAGE_INFO, + LINUX_INFO_SIZE, zINFO_VERSION_A, &aStack->zinfo); + zClose(volKey); + if (rc != zOK) + { + goto exit; + } + + *volInfo = aStack->zinfo.vol; + +exit: + STACK_FREE(); + mpkExit(); + return rc ? nss2linuxError(rc) : size; +} +int xattr_get_userquota ( + struct dentry *dentry, + const char *name, + void *value, + size_t val_size) +{ + NINT size = 0; + STATUS rc; + NINT totalUsers; + int n, i; + int index; + NINT userCount = 0; + NINT startUser; + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + zNW_user_quota_s *userQuota = value; + zUserRest_s *userEntries; + + n = dotlen(name); + if (!name[n] || (name[n] != '.') || !name[n+1]) + { + return -ENOATTR; + } + mpkEnter(); + + index = strtoul( &name[n+1], NULL, 0); + + rc = LSACOMN_BrowseUsers(zSYS_CONNECTION, &super->sb_volID, + 0, NULL, NULL, &totalUsers, + BROWSE_USERS_GET_ONLY_RESTRICTED| BROWSE_USERS_GET_COUNT); + if (rc != 0) + { + goto exit; + } + startUser = index * zMAX_XATTR_USERS; + if (totalUsers > startUser) + { + userCount = totalUsers - startUser; + } + if (userCount > zMAX_XATTR_USERS) + { + userCount = zMAX_XATTR_USERS; + } + + size = offsetof(zNW_user_quota_s, nwuq_user) + + userCount * sizeof(zNW_user_restriction_s); + + if (value == NULL) + { + /* return size */ + goto exit; + } + if (val_size < size) + { + rc = -ERANGE; + goto exit; + } + + bzero(userQuota, val_size); + userQuota->nwuq_byteorder = zNW_BYTEORDER; + userQuota->nwuq_version = zNW_USERQUOTA_VERSION; + userQuota->nwuq_index = index; + userQuota->nwuq_reserved_1 = 0; + + if (userCount == 0) + { + goto exit; + } + userEntries = malloc(userCount * sizeof(zUserRest_s)); + if (userEntries == NULL) + { + rc = -ENOMEM; + goto exit; + } +//printk("<1> Pre userCount = %d, startUser = %d\n", userCount, startUser); + rc = LSACOMN_BrowseUsers(zSYS_CONNECTION, &super->sb_volID, + userCount, NULL, userEntries, &startUser, + BROWSE_USERS_GET_ONLY_RESTRICTED| BROWSE_USERS_START_AT_COUNT); + if (rc != 0) + { + free(userEntries); + goto exit; + } + +//printk("<1> Post userCount = %d, startUser = %d\n", userCount, startUser); + userCount = startUser; + MPKNSS_LOCK(); + for (i = 0; i < userCount; i++) + { + userQuota->nwuq_user[i].nwur_restriction = + userEntries[i].restrictionAmount; + userQuota->nwuq_user[i].nwur_reserved_2 = 0; +#if 0 + rc = COMN_MapNDSGUIDToName( &userEntries[i].userID, + sizeof(userQuota->nwuq_user[i].nwur_dnsname), + userQuota->nwuq_user[i].nwur_dnsname); + if (rc != 0) + { +//printk("<1> rc from COMN_MapNDSGUIDToName = %d \n", rc); + i--; + userCount--; + rc = 0; + } +#endif + userQuota->nwuq_user[i].nwur_user = userEntries[i].userID; + } + userQuota->nwuq_num_users = userCount; + + MPKNSS_UNLOCK(); + free(userEntries); + +exit: + mpkExit(); + return rc ? nss2linuxError(rc) : size; +} +int xattr_set_userquota ( + struct dentry *dentry, + const char *name, + const void *value, + size_t size) +{ + zNW_user_quota_s *userQuota = (zNW_user_quota_s *)value; + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + NINT users_size; + int rc = zOK; + int saverc = zOK; + int i; + + GeneralMsg_s genMsg; + Volume_s *volume; + +pr("xattr_set_userquota"); + + if (userQuota->nwuq_num_users == 0) + { + return 0; + } + users_size = offsetof(zNW_user_quota_s, nwuq_user); + users_size += userQuota->nwuq_num_users * sizeof(zNW_user_restriction_s); + + if (users_size > size) + { + return -EFAULT; + } + + if ((userQuota->nwuq_byteorder != zNW_BYTEORDER) + || (userQuota->nwuq_version != zNW_METADATA_VERSION)) + { + return -EINVAL; + } + mpkEnter(); + + MPKNSS_LOCK(); + COMN_SETUP_GENERAL_MSG(&genMsg, current->fsuid, zNO_TASK,zSAGENT_NONE); + volume = COMN_VolumeIDLookup(&genMsg, &super->sb_volID, TRUE); + if (!volume) + { + rc = GetErrno(&genMsg); + goto error; + } + if (COMN_LockVolumeActive(&genMsg, volume, FALSE) != zOK) + { + rc = GetErrno(&genMsg); + goto errorRelease; + } + + for (i = 0; i < userQuota->nwuq_num_users; i++) + { + S_LATCH(&volume->rootdir->FILEbeastLatch); + rc = VOL_SetUserSpaceRestriction(&genMsg, volume, &userQuota->nwuq_user[i].nwur_user, userQuota->nwuq_user[i].nwur_restriction); + UNS_LATCH(&volume->rootdir->FILEbeastLatch); + if (rc) + { + if (!saverc) + { + saverc = GetErrno(&genMsg); + } + ClearErrno(&genMsg); + } + } + + COMN_UnlockVolumeActive(volume, FALSE); +errorRelease: + COMN_Release(&volume); +error: + MPKNSS_UNLOCK(); + mpkExit(); + return rc ? nss2linuxError(rc) : size; +} +#if 0 +int xattr_get_trustee ( + struct dentry *dentry, + const char *name, + void *value, + size_t val_size) +{ + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + NINT size = 0; + Key_t fileKey; + int rc; + NINT nameSpace = super->sb_nameSpace; + NINT totalUsers; + int n, i, j; + int index; + NINT userCount = 0; + NINT startUser; + zNW_trustee_name_s *trustee = value; + ACLEntry_s *acl_list; + +pr("xattr_get_trustee"); + + n = dotlen(name); + if (!name[n] || (name[n] != '.') || !name[n+1]) + { + return -ENOATTR; + } + mpkEnter(); + + index = strtoul( &name[n+1], NULL, 0); + + if (inode->i_mode & S_IFLNK) + { + nameSpace |= zMODE_LINK; + } + + rc = zZIDOpen(userKey(current->fsuid), zNO_TASK, nameSpace, + &super->sb_volID, inode->i_ino, + zRR_DONT_UPDATE_ACCESS_TIME, &fileKey); + if (rc != 0) + { + goto exit; + } + rc = LSACOMN_GetTrusteeCountByKey(fileKey, &totalUsers); + if (rc != 0) + { + zClose(fileKey); + goto exit; + } + + startUser = index * zMAX_XATTR_USERS; + if (totalUsers > startUser) + { + userCount = totalUsers - startUser; + } + if (userCount > zMAX_XATTR_USERS) + { + userCount = zMAX_XATTR_USERS; + } + + size = offsetof(zNW_trustee_name_s, nwtn_user) + + userCount * sizeof(zNW_user_trustee_s); + + if (value == NULL) + { + /* return size */ + zClose(fileKey); + goto exit; + } + if (val_size < size) + { + rc = -ERANGE; + zClose(fileKey); + goto exit; + } + bzero(trustee, val_size); + trustee->nwtn_byteorder = zNW_BYTEORDER; + trustee->nwtn_version = zNW_TRUSTEE_VERSION; + trustee->nwtn_index = index; + trustee->nwtn_reserved_1 = 0; + trustee->nwtn_num_trustees = userCount; +printk("usercount = %d\n", userCount); + if (userCount == 0) + { + zClose(fileKey); + goto exit; + } + acl_list = malloc(totalUsers * sizeof(ACLEntry_s)); + if (acl_list == NULL) + { + rc = -ENOMEM; + goto exit; + } + rc = LSACOMN_GetTrusteeListByKey(fileKey, acl_list, totalUsers); + if (rc != 0) + { + free(acl_list); + goto exit; + } + MPKNSS_LOCK(); + for (i = 0, j = 0; (i < totalUsers && j < userCount); i++) + { + if (i < startUser) + { + continue; + } + trustee->nwtn_user[j].nwut_rights = acl_list[i].rights; + trustee->nwtn_user[j].nwut_reserved_2 = 0; + rc = COMN_MapNDSGUIDToName( &acl_list[i].trusteeID, + sizeof(trustee->nwtn_user[j].nwut_dnsname), + trustee->nwtn_user[j].nwut_dnsname); + j++; + if (rc != 0) + { + j--; + userCount--; + rc = 0; + } + } + trustee->nwtn_num_trustees = userCount; + + MPKNSS_UNLOCK(); + free(acl_list); + +exit: + mpkExit(); + return rc ? nss2linuxError(rc) : size; +} + +int xattr_set_trustee ( + struct dentry *dentry, + const char *name, + const void *value, + size_t size) +{ + zNW_trustee_name_s *trustee = value; + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + zInfoC_s *zinfo = NULL; + NINT trustee_size; + int rc; + +pr("xattr_set_trustee"); + + if (nwtn_num_trustees == 0) + { + return 0; + } + trustee_size = offsetof(zNW_trustee_name_s, nwtn_user); + trustee_size += trustee->nwtn_num_trustees * sizeof(zNW_user_trustee_s); + + if (trustee_size > size) + { + return -EFAULT; + } + +#if TODO + mpkEnter(); + + { + const zNW_trustee_s *trustee; + zTrusteeInfo_s *acl; + NINT i; + + trustee = metadata->nwm_trustee; + acl = (zTrusteeInfo_s *)zinfo->variableData; + for (i = 0; i < metadata->nwm_trustee_num; i++, acl++, trustee++) + { + acl->trustee = trustee->nwt_id; + acl->rights = trustee->nwt_rights; + } + zinfo->trustees.numEntries = i; + zinfo->trustees.trusteeArray = offsetof(zInfoC_s, variableData); + } + +error: + + mpkExit(); + return rc ? nss2linuxError(rc) : 0; +#endif + return 0; +} +#endif + +int xattr_remove_metadata ( + struct dentry *dentry, + const char *name) +{ + STATUS rc = 0; + NINT sequence; + NINT rights; + NINT attributes; + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + + typedef struct Stack_s { + GeneralMsg_s genMsg; + NamingMsg_s nameMsg; + UserID_t userID; + } Stack_s; + Stack_s *aStack; + + mpkEnter(); + + STACK_ALLOC_NO_ASTACK(); + + MPKNSS_LOCK(); + + COMN_SETUP_GENERAL_MSG_NOSA(&aStack->genMsg); + COMN_INIT_NAMING_MSG(&aStack->nameMsg); + + COMN_SETUP_NAMING_MSG_VOLUME_ZID( &aStack->nameMsg, super->sb_volID, + zINVALID_ZID, inode->i_ino, inode->i_ino, XLATCHED, + super->sb_nameSpace, zNTYPE_FILE, NULL); + + COMN_SET_NAMING_MSG_OPERATE_ON_LINK(&aStack->nameMsg); + + if (COMN_Lookup(&aStack->genMsg, &aStack->nameMsg) != zOK) + { + rc = GetErrno(&aStack->genMsg); + goto exit; + } + + for(;;) + { + sequence = 0; + if (COMN_ZAS_getACLEntry(&aStack->genMsg, &aStack->nameMsg, &sequence, + &aStack->userID, &rights, &attributes) != zOK) + { + rc = GetErrno(&aStack->genMsg); + goto exit; + } + if (sequence == -1) + { + break; + } + + /* actually remove the trustee */ + if (COMN_ZAS_removeACLEntry(&aStack->genMsg, &aStack->nameMsg, + &aStack->userID, FALSE) != zOK) + { + rc = GetErrno(&aStack->genMsg); + goto exit; + } + } + DIRQ_RemoveDirectoryQuota(&aStack->genMsg, aStack->nameMsg.curvol, aStack->nameMsg.curFile); +exit: + COMN_CleanupNameMsg(&aStack->genMsg, &aStack->nameMsg); + MPKNSS_UNLOCK(); + STACK_FREE(); + mpkExit(); + return rc ? nss2linuxError(rc) : 0; +} +int xattr_remove_userquota ( + struct dentry *dentry, + const char *name) +{ + /* Should this routine remove all the user space restrictions on the + * volume? + */ + return 0; +#if 0 + /* This is not the complete code, just the beginning */ + STATUS rc; + struct inode *inode = dentry->d_inode; + LsaSuper_s *super = inode->i_sb->s_fs_info; + UserID_t lastUserReturned = zINVALID_USERID; + zUserRest_s *userEntries; + NINT userCount = 100; + NINT userReturned; + + if (inode->i_ino != zROOTDIR_ZID) + { + return 0; + } + + userEntries = kmalloc(userCount * sizeof(zUserRest_s)); + if (userEntries == NULL) + { + return -ENOMEM; + } + + mpkEnter(); + + while (1) + { + // set up genmsg, volume, and use VOL_BrowseUsers + rc = LSACOMN_BrowseUsers(zSYS_CONNECTION, &super->sb_volID, + userCount, &lastUserReturned, userEntries, &userReturned, + BROWSE_USERS_GET_ONLY_RESTRICTED); + if ((rc != 0) || (userReturned == 0)) + { + goto exit; + } + + MPKNSS_LOCK(); + for (i = 0; i < userReturned; i++) + { + S_LATCH(&volume->rootdir->FILEbeastLatch); + rc = VOL_SetUserSpaceRestriction(&genMsg, volume, &userQuota->nwuq_user[i].nwur_user, userQuota->nwuq_user[i].nwur_restriction /* Set to no restriction */); + UNS_LATCH(&volume->rootdir->FILEbeastLatch); + if (rc) + { + rc = GetErrno(&genMsg); + goto errorRelease; + } + } + MPKNSS_UNLOCK(); + + } +exit: + mpkExit(); + kfree(userEntries); + return rc ? nss2linuxError(rc) : 0; +#endif +} +typedef int (*xget_f)( + struct dentry *dentry, + const char *name, + void *value, + size_t size); + +typedef int (*xset_f)( + struct dentry *dentry, + const char *name, + const void *value, + size_t size); + +typedef int (*xremove_f)( + struct dentry *dentry, + const char *name); + +typedef struct Xattr_s { + char *x_name; + xget_f x_get; + xset_f x_set; + xremove_f x_remove; +} Xattr_s; + +Xattr_s Xattr[] = { + { "ncpstat", xattr_get_ncpstat, xattr_set_ncpstat, NULL }, + { "quota", xattr_get_quota, NULL, NULL }, + { "volumeinfo", xattr_get_volumeinfo, NULL, NULL }, + { "metadata", xattr_get_metadata, xattr_set_metadata, xattr_remove_metadata }, + { "userquota", xattr_get_userquota, xattr_set_userquota, xattr_remove_userquota }, +// { "trustee", xattr_get_trustee, xattr_set_trustee, NULL }, + + { NULL, NULL } +}; + +/* xattr_lookup: finds name in table. "netware." prefix has been removed. */ +Xattr_s *xattr_lookup (const char *name) +{ + Xattr_s *xattr; + + for (xattr = Xattr; xattr->x_name; xattr++) + { + if (dotcmp(name, xattr->x_name) == 0) + { + return xattr; + } + } + return NULL; +} +/* netware_getxattr: call the get function for the named attribute */ +ssize_t netware_getxattr ( + struct dentry *dentry, + const char *name, + void *value, + size_t size) +{ + Xattr_s *xattr; + +pr("netware_getxattr"); + xattr = xattr_lookup(name); + if (!xattr) + { + return -ENOATTR; + } + if (!xattr->x_get) + { + return -ENOATTR; + } + return xattr->x_get(dentry, name, value, size); +} + +/* netware_setxattr: call the set function for the named attribute */ +ssize_t netware_setxattr ( + struct dentry *dentry, + const char *name, + const void *value, + size_t size) +{ + Xattr_s *xattr; + +pr("netware_setxattr"); + xattr = xattr_lookup(name); + if (!xattr) + { + return -ENOATTR; + } + if (!xattr->x_set) + { + return -ENOATTR; + } + return xattr->x_set(dentry, name, value, size); +} +int netware_removexattr ( + struct dentry *dentry, + const char *name) +{ + Xattr_s *xattr; + +pr("netware_removexattr"); + xattr = xattr_lookup(name); + if (!xattr) + { + return -ENOATTR; + } + if (!xattr->x_remove) + { + return 0; + } + return xattr->x_remove(dentry, name); +}