xattr.c revision f5f5959bd78f309ae446ddd7d5051717490edd2a
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/isa_defs.h>
#include <sys/sysmacros.h>
#include <sys/pathname.h>
typedef struct {
} xattr_file_t;
/* ARGSUSED */
static int
{
return (EACCES);
return (0);
}
/* ARGSUSED */
static int
{
return (EACCES);
return (0);
}
/* ARGSUSED */
static int
{
return (0);
}
static int
{
int error;
return (ENOSPC);
}
}
if (error) {
return (error);
}
return (0);
}
/* ARGSUSED */
static int
{
int error;
const char *domain;
return (EINVAL);
/*
*/
/*
* We need to access the real fs object.
* vp points to a GFS file; ppvp points to the real object.
*/
/*
* Iterate through the attrs associated with this view
*/
continue;
}
switch (attr) {
case F_SYSTEM:
break;
case F_READONLY:
break;
case F_HIDDEN:
break;
case F_ARCHIVE:
break;
case F_IMMUTABLE:
break;
case F_APPENDONLY:
break;
case F_NOUNLINK:
break;
case F_OPAQUE:
break;
case F_NODUMP:
break;
case F_AV_QUARANTINED:
break;
case F_AV_MODIFIED:
break;
case F_AV_SCANSTAMP:
break;
case F_CRTIME:
break;
case F_FSID:
0xffffffff));
fsid) == 0);
break;
default:
break;
}
}
if (error)
return (error);
/*
* Process all the optional attributes together here. Notice that
* xoap was set when the optional attribute bits were set above.
*/
xoap->xoa_readonly) == 0);
}
xoap->xoa_hidden) == 0);
}
xoap->xoa_system) == 0);
}
xoap->xoa_archive) == 0);
}
xoap->xoa_immutable) == 0);
}
xoap->xoa_nounlink) == 0);
}
xoap->xoa_appendonly) == 0);
}
xoap->xoa_nodump) == 0);
}
xoap->xoa_opaque) == 0);
}
xoap->xoa_av_quarantined) == 0);
}
xoap->xoa_av_modified) == 0);
}
sizeof (xoap->xoa_av_scanstamp)) == 0);
}
sizeof (xoap->xoa_createtime) /
sizeof (uint64_t)) == 0);
}
}
/*
*/
return (ENOMEM);
SID_DOMAIN, domain) == 0);
nvl_sid) == 0);
}
}
return (ENOMEM);
SID_DOMAIN, domain) == 0);
nvl_sid) == 0);
}
}
return (0);
}
/*
* The size of a sysattr file is the size of the nvlist that will be
* returned by xattr_file_read(). A call to xattr_file_write() could
* change the size of that nvlist. That size is not stored persistently
* so xattr_fill_nvlist() calls VOP_GETATTR so that it can be calculated.
*/
static int
{
return (ENOMEM);
}
return (EFAULT);
}
return (0);
}
/* ARGSUSED */
static int
{
int error;
if (error) {
return (error);
}
gethrestime(&now);
return (error);
}
/* ARGSUSED */
static int
{
char *buf;
int error;
/*
* Validate file offset and fasttrack empty reads
*/
return (EINVAL);
return (0);
return (ENOMEM);
return (EFAULT);
}
return (0);
}
KM_SLEEP) == 0);
return (error);
}
/* ARGSUSED */
static int
{
int error = 0;
char *buf;
char *domain;
/*
* Validate file offset and size.
*/
return (EINVAL);
if (size == 0)
return (EINVAL);
return (EINVAL);
}
/*
* Copy and unpack the nvlist
*/
return (EFAULT);
}
return (EINVAL);
}
/*
* Fasttrack empty writes (nvlist with no nvpairs)
*/
return (0);
/*
* Validate the name and type of each attribute.
* Log any unknown names and continue. This will
* help if additional attributes are added later.
*/
nvpair_name(pair));
continue;
}
/*
* Verify nvlist type matches required type and view is OK
*/
return (EINVAL);
}
/*
* file system support ephemeral ID's
*/
return (EINVAL);
}
/*
* Retrieve data from nvpair
*/
switch (type) {
case DATA_TYPE_BOOLEAN_VALUE:
return (EINVAL);
}
break;
case DATA_TYPE_UINT64_ARRAY:
return (EINVAL);
}
break;
case DATA_TYPE_NVLIST:
return (EINVAL);
}
break;
case DATA_TYPE_UINT8_ARRAY:
return (EINVAL);
}
break;
default:
return (EINVAL);
}
switch (attr) {
/*
* If we have several similar optional attributes to
* process then we should do it all together here so that
* xoap and the requested bitmap can be set in one place.
*/
case F_READONLY:
break;
case F_HIDDEN:
break;
case F_SYSTEM:
break;
case F_ARCHIVE:
break;
case F_IMMUTABLE:
break;
case F_NOUNLINK:
break;
case F_APPENDONLY:
break;
case F_NODUMP:
break;
case F_AV_QUARANTINED:
break;
case F_AV_MODIFIED:
break;
case F_CRTIME:
break;
case F_OWNERSID:
case F_GROUPSID:
&rid)) {
return (EINVAL);
}
/*
* Now map domain+rid to ephemeral id's
*
* be set to UID_NOBODY by Winchester.
*/
if (attr == F_OWNERSID) {
} else {
}
break;
case F_AV_SCANSTAMP:
} else {
return (EINVAL);
}
break;
default:
break;
}
}
if (error)
return (error);
}
static int
{
switch (cmd) {
case _PC_XATTR_EXISTS:
case _PC_SATTR_ENABLED:
case _PC_SATTR_EXISTS:
*valp = 0;
return (0);
default:
}
}
static const fs_operation_def_t xattr_file_tops[] = {
{ NULL }
};
vnode_t *
{
return (vp);
}
vnode_t *
{
}
vnode_t *
{
}
static gfs_dirent_t xattr_dirents[] = {
{ NULL },
};
static int
is_sattr_name(char *s)
{
int i;
for (i = 0; i < XATTRDIR_NENTS; ++i) {
return (1);
}
}
return (0);
}
/*
* Given the name of an extended attribute file, determine if there is a
* normalization conflict with a sysattr view name.
*/
int
xattr_sysattr_casechk(char *s)
{
int i;
for (i = 0; i < XATTRDIR_NENTS; ++i) {
return (1);
}
return (0);
}
static int
{
int error;
/*
* Only copy system attrs if the views are the same
*/
return (EINVAL);
if (error)
return (error);
return (error);
}
static int
{
int error;
char *startnm = "";
if (error) {
return (error);
}
/*
* Set the LOOKUP_HAVE_SYSATTR_DIR flag so that we don't get into an
* infinite loop with fop_lookup calling back to xattr_dir_lookup.
*/
return (error);
}
/* ARGSUSED */
static int
{
return (EACCES);
}
return (0);
}
/* ARGSUSED */
static int
{
return (0);
}
/* ARGSUSED */
static int
{
int error;
if (error == 0) {
if (error) {
return (error);
}
return (0);
}
/*
* There is no real xattr directory. Cobble together
* an entry using info from the parent object.
*/
if (error) {
return (error);
}
gethrestime(&now);
vap->va_blksize = 0;
vap->va_nblocks = 0;
return (0);
}
static int
{
int error;
/*
* If there is a real xattr directory, do the setattr there.
* Otherwise, just return success. The GFS directory is transient,
* and any setattr changes can disappear anyway.
*/
if (error == 0) {
}
error = 0;
}
return (error);
}
/* ARGSUSED */
static int
{
int error;
return (EACCES);
}
if (realvp)
/*
* No real xattr dir isn't an error
* an error of EINVAL indicates attributes on attributes
* are not supported. In that case just allow access to the
* transient directory.
*/
}
static int
{
int error;
/*
* Don't allow creation of extended attributes with sysattr names.
*/
if (is_sattr_name(name)) {
}
if (error == 0) {
}
return (error);
}
static int
int flags)
{
int error;
if (is_sattr_name(name)) {
return (EACCES);
}
if (error == 0) {
}
return (error);
}
static int
{
int error;
return (EINVAL);
}
if (error == 0) {
}
return (error);
}
static int
{
int error;
int held_tgt;
/*
* We know that sdvp is a GFS dir, or we wouldn't be here.
* Get the real unnamed directory.
*/
if (error) {
return (error);
}
/*
* If the source and target are the same GFS directory, the
* underlying unnamed source and target dir will be the same.
*/
held_tgt = 1;
/*
* If the target dir is a different GFS directory,
* find its underlying unnamed dir.
*/
if (error) {
return (error);
}
held_tgt = 1;
} else {
/*
* Target dir is outside of GFS, pass it on through.
*/
held_tgt = 0;
}
if (held_tgt) {
}
return (error);
}
/*
* readdir_xattr_casecmp: given a system attribute name, see if there
* is a real xattr with the same normalized name.
*/
static int
int *eflags)
{
int error;
int flags = FIGNORECASE;
*eflags = 0;
if (error == 0) {
if (error == 0) {
error = 0;
}
}
return (error);
}
static int
{
int error;
int local_eof;
int reset_off = 0;
int has_xattrs = 0;
}
*eofp = 0;
/*
* See if there is a real extended attribute directory.
*/
if (error == 0) {
has_xattrs = 1;
}
/*
* Start by reading up the static entries.
*/
if (uiop->uio_loffset == 0) {
if (has_xattrs) {
/*
* If there is a real xattr dir, skip . and ..
* in the GFS dir. We'll pick them up below
* when we call into the underlying fs.
*/
}
if (error == 0) {
}
if (error) {
if (has_xattrs)
return (error);
}
!*eofp) {
int eflags = 0;
/*
* Check to see if this sysattr set name has a
* case-insensitive conflict with a real xattr
* name.
*/
if (error)
break;
}
eflags);
if (error)
break;
} else {
*eofp = 1;
}
}
if (error) {
if (has_xattrs)
return (error);
}
/*
* We must read all of the static entries in the first
* call. Otherwise we won't know if uio_loffset in a
* subsequent call refers to the static entries or to those
* in an underlying fs.
*/
reset_off = 1;
}
if (!has_xattrs) {
*eofp = 1;
return (0);
}
*eofp = 0;
if (reset_off) {
uiop->uio_loffset = 0;
}
return (error);
}
/* ARGSUSED */
static void
{
gfs_file_t *fp;
}
}
static int
{
switch (cmd) {
case _PC_XATTR_EXISTS:
case _PC_SATTR_ENABLED:
case _PC_SATTR_EXISTS:
*valp = 0;
return (0);
default:
}
}
static const fs_operation_def_t xattr_dir_tops[] = {
};
static gfs_opsvec_t xattr_opsvec[] = {
};
static int
{
int error;
*inop = 0;
/*
* Return ENOENT for EACCES requests during lookup. Once an
* attribute create is attempted EACCES will be returned.
*/
if (error) {
return (ENOENT);
return (error);
}
if (error == 0) {
}
return (error);
}
/* ARGSUSED */
static ino64_t
{
/*
* We use index 0 for the directory fid. Start
* the file numbering at 1.
*/
}
void
xattr_init(void)
{
}
int
{
int error = 0;
return (EINVAL);
/*
* If we're already in sysattr space, don't allow creation
* of another level of sysattrs.
*/
return (EINVAL);
}
} else {
int sysattrs_allowed = 1;
/*
* We have to drop the lock on dvp. gfs_dir_create will
* grab it for a VN_HOLD.
*/
/*
* If dvp allows xattr creation, but not sysattr
* creation, return the real xattr dir vp. We can't
* use the vfs feature mask here because _PC_SATTR_ENABLED
* has vnode-level granularity (e.g. .zfs).
*/
sysattrs_allowed = 0;
if (!xattrs_allowed && !sysattrs_allowed)
return (EINVAL);
if (!sysattrs_allowed) {
char *nm = "";
if (error)
return (error);
return (error);
}
/*
* Note that we act as if we were given CREATE_XATTR_DIR,
* but only for creation of the GFS directory.
*/
*vpp = gfs_dir_create(
/*
* We lost the race to create the xattr dir.
* Destroy this one, use the winner. We can't
* just call VN_RELE(*vpp), because the vnode
* is only partially initialized.
*/
/*
* There is an implied VN_HOLD(dvp) here. We should
* be doing a VN_RELE(dvp) to clean up the reference
* from *vpp, and then a VN_HOLD(dvp) for the new
* reference. Instead, we just leave the count alone.
*/
} else {
}
}
return (error);
}
int
{
int error;
char *nm;
return (EINVAL);
if (error)
return (error);
/*
* Start by getting the GFS sysattr directory. We might need
* to recreate it during the VOP_LOOKUP.
*/
nm = "";
if (error) {
return (EINVAL);
}
if (error)
return (error);
if (xfidp->dir_offset == 0) {
/*
* If we were looking for the directory, we're done.
*/
return (0);
}
return (EINVAL);
}
if (error) {
return (EINVAL);
}
return (error);
}