Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs add support for extended attributes in ext2fs for ex...
details: https://anonhg.NetBSD.org/src/rev/510d4f7f2800
branches: trunk
changeset: 817220:510d4f7f2800
user: jdolecek <jdolecek%NetBSD.org@localhost>
date: Fri Aug 12 19:04:03 2016 +0000
description:
add support for extended attributes in ext2fs for ext3/ext4; read-only for now
diffstat:
sys/ufs/ext2fs/ext2fs.h | 10 +-
sys/ufs/ext2fs/ext2fs_dinode.h | 6 +-
sys/ufs/ext2fs/ext2fs_vnops.c | 17 +-
sys/ufs/ext2fs/ext2fs_xattr.c | 450 +++++++++++++++++++++++++++++++++++++++++
sys/ufs/ext2fs/ext2fs_xattr.h | 117 ++++++++++
sys/ufs/files.ufs | 3 +-
6 files changed, 596 insertions(+), 7 deletions(-)
diffs (truncated from 698 to 300 lines):
diff -r 690b8eafe3e5 -r 510d4f7f2800 sys/ufs/ext2fs/ext2fs.h
--- a/sys/ufs/ext2fs/ext2fs.h Fri Aug 12 15:26:04 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs.h Fri Aug 12 19:04:03 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs.h,v 1.41 2016/08/05 21:22:06 jdolecek Exp $ */
+/* $NetBSD: ext2fs.h,v 1.42 2016/08/12 19:04:03 jdolecek Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -341,6 +341,14 @@
"\02INCOMPAT_FTYPE" \
"\01INCOMPAT_COMP"
+#define EXT2F_HAS_COMPAT_FEATURE(ip, feature) \
+ (ip)->i_e2fs->e2fs.e2fs_rev >= E2FS_REV1 && \
+ ((ip)->i_e2fs->e2fs.e2fs_features_compat & (feature)) != 0
+
+#define EXT2F_HAS_INCOMPAT_FEATURE(ip, feature) \
+ (ip)->i_e2fs->e2fs.e2fs_rev >= E2FS_REV1 && \
+ ((ip)->i_e2fs->e2fs.e2fs_features_incompat & (feature)) != 0
+
/*
* Features supported in this implementation
*
diff -r 690b8eafe3e5 -r 510d4f7f2800 sys/ufs/ext2fs/ext2fs_dinode.h
--- a/sys/ufs/ext2fs/ext2fs_dinode.h Fri Aug 12 15:26:04 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_dinode.h Fri Aug 12 19:04:03 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_dinode.h,v 1.35 2016/08/06 09:29:28 jdolecek Exp $ */
+/* $NetBSD: ext2fs_dinode.h,v 1.36 2016/08/12 19:04:03 jdolecek Exp $ */
/*
* Copyright (c) 1982, 1989, 1993
@@ -123,11 +123,11 @@
uint32_t e2di_blocks[EXT2FS_NDADDR+EXT2FS_NIADDR];
/* 40: disk blocks */
uint32_t e2di_gen; /* 100: generation number */
- uint32_t e2di_facl; /* 104: file ACL (not implemented) (ext3) */
+ uint32_t e2di_facl; /* 104: file ACL (ext3) */
uint32_t e2di_size_high; /* 108: Size (in bytes) high */
uint32_t e2di_obso_faddr;/* 112: obsolete fragment address (ext2) */
uint16_t e2di_nblock_high; /* 116: Blocks count bits 47:32 (ext4) */
- uint16_t e2di_facl_high; /* 118: file ACL bits 47:32 (ext4) */
+ uint16_t e2di_facl_high; /* 118: file ACL bits 47:32 (ext4/64bit) */
uint16_t e2di_uid_high; /* 120: Owner UID top 16 bits (ext4) */
uint16_t e2di_gid_high; /* 122: Owner GID top 16 bits (ext4) */
uint16_t e2di_checksum_low; /* 124: crc LE (not implemented) (ext4) */
diff -r 690b8eafe3e5 -r 510d4f7f2800 sys/ufs/ext2fs/ext2fs_vnops.c
--- a/sys/ufs/ext2fs/ext2fs_vnops.c Fri Aug 12 15:26:04 2016 +0000
+++ b/sys/ufs/ext2fs/ext2fs_vnops.c Fri Aug 12 19:04:03 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_vnops.c,v 1.120 2016/08/05 20:15:41 jdolecek Exp $ */
+/* $NetBSD: ext2fs_vnops.c,v 1.121 2016/08/12 19:04:03 jdolecek Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -65,7 +65,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.120 2016/08/05 20:15:41 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vnops.c,v 1.121 2016/08/12 19:04:03 jdolecek Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -94,6 +94,7 @@
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ext2fs/ext2fs_extern.h>
#include <ufs/ext2fs/ext2fs_dir.h>
+#include <ufs/ext2fs/ext2fs_xattr.h>
extern int prtactive;
@@ -1182,6 +1183,10 @@
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ &vop_getpages_desc, genfs_getpages }, /* getpages */
{ &vop_putpages_desc, genfs_putpages }, /* putpages */
+ { &vop_getextattr_desc, ext2fs_getextattr }, /* getextattr */
+ { &vop_setextattr_desc, ext2fs_setextattr }, /* setextattr */
+ { &vop_listextattr_desc, ext2fs_listextattr }, /* listextattr */
+ { &vop_deleteextattr_desc, ext2fs_deleteextattr },/* deleteextattr */
{ NULL, NULL }
};
const struct vnodeopv_desc ext2fs_vnodeop_opv_desc =
@@ -1232,6 +1237,10 @@
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ &vop_getpages_desc, spec_getpages }, /* getpages */
{ &vop_putpages_desc, spec_putpages }, /* putpages */
+ { &vop_getextattr_desc, ext2fs_getextattr }, /* getextattr */
+ { &vop_setextattr_desc, ext2fs_setextattr }, /* setextattr */
+ { &vop_listextattr_desc, ext2fs_listextattr }, /* listextattr */
+ { &vop_deleteextattr_desc, ext2fs_deleteextattr },/* deleteextattr */
{ NULL, NULL }
};
const struct vnodeopv_desc ext2fs_specop_opv_desc =
@@ -1281,6 +1290,10 @@
{ &vop_advlock_desc, vn_fifo_bypass }, /* advlock */
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */
{ &vop_putpages_desc, vn_fifo_bypass }, /* putpages */
+ { &vop_getextattr_desc, ext2fs_getextattr }, /* getextattr */
+ { &vop_setextattr_desc, ext2fs_setextattr }, /* setextattr */
+ { &vop_listextattr_desc, ext2fs_listextattr }, /* listextattr */
+ { &vop_deleteextattr_desc, ext2fs_deleteextattr },/* deleteextattr */
{ NULL, NULL }
};
const struct vnodeopv_desc ext2fs_fifoop_opv_desc =
diff -r 690b8eafe3e5 -r 510d4f7f2800 sys/ufs/ext2fs/ext2fs_xattr.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/ufs/ext2fs/ext2fs_xattr.c Fri Aug 12 19:04:03 2016 +0000
@@ -0,0 +1,450 @@
+/* $NetBSD: ext2fs_xattr.c,v 1.1 2016/08/12 19:04:03 jdolecek Exp $ */
+
+/*-
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jaromir Dolecek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_xattr.c,v 1.1 2016/08/12 19:04:03 jdolecek Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/buf.h>
+#include <sys/vnode.h>
+#include <sys/kernel.h>
+#include <sys/kmem.h>
+#include <sys/trace.h>
+#include <sys/resourcevar.h>
+#include <sys/kauth.h>
+#include <sys/extattr.h>
+
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
+
+#include <ufs/ext2fs/ext2fs.h>
+#include <ufs/ext2fs/ext2fs_extern.h>
+#include <ufs/ext2fs/ext2fs_xattr.h>
+
+static const char * const xattr_prefix_index[] = {
+ "",
+ "user.",
+ "system.posix_acl_access",
+ "system.posix_acl_default",
+ "trusted.",
+ "", /* unused */
+ "security",
+ "system.",
+ "system.richacl",
+ "c",
+};
+
+static int
+ext2fs_find_xattr(struct ext2fs_xattr_entry *e, uint8_t *start, uint8_t *end, int attrnamespace, struct uio *uio, size_t *size, uint8_t name_index, const char *name)
+{
+ uint8_t *value;
+ int error;
+ size_t value_offs, value_len, len, old_len;
+
+ /*
+ * Individual entries follow the header. Each is aligned on 4-byte
+ * boundary.
+ */
+ for(; !EXT2FS_XATTR_IS_LAST_ENTRY(e, end); e = EXT2FS_XATTR_NEXT(e)) {
+ /*
+ * Only EXT2FS_XATTR_PREFIX_USER is USER, anything else
+ * is considered SYSTEM.
+ */
+ if ((attrnamespace == EXTATTR_NAMESPACE_USER && e->e_name_index != EXT2FS_XATTR_PREFIX_USER) ||
+ (attrnamespace == EXTATTR_NAMESPACE_SYSTEM && e->e_name_index == EXT2FS_XATTR_PREFIX_USER)) {
+ continue;
+ }
+
+ if (e->e_name_index != name_index ||
+ e->e_name_len != strlen(name) ||
+ strncmp(e->e_name, name, e->e_name_len) != 0)
+ continue;
+
+ value_offs = fs2h32(e->e_value_offs);
+ value_len = fs2h32(e->e_value_size);
+ value = &start[value_offs];
+
+ /* make sure the value offset are sane */
+ if (&value[value_len] > end)
+ return (EINVAL);
+
+ if (uio != NULL) {
+ /*
+ * Figure out maximum to transfer -- use buffer size and
+ * local data limit.
+ */
+ len = MIN(uio->uio_resid, value_len);
+ old_len = uio->uio_resid;
+ uio->uio_resid = len;
+
+ uio->uio_resid = old_len - (len - uio->uio_resid);
+
+ error = uiomove(value, value_len, uio);
+ if (error)
+ return error;
+ }
+
+ /* full data size */
+ *size += value_len;
+
+ goto found;
+ }
+
+ /* requested attribute not found */
+ return (ENODATA);
+
+ found:
+ return (0);
+}
+
+static int
+ext2fs_get_inode_xattr(struct inode *ip, int attrnamespace, struct uio *uio, size_t *size, uint8_t name_index, const char *name)
+{
+ struct ext2fs_dinode *di = ip->i_din.e2fs_din;
+ struct ext2fs_xattr_ibody_header *h;
+ uint8_t *start, *end;
+
+ start = &((uint8_t *)di)[EXT2_REV0_DINODE_SIZE + di->e2di_extra_isize];
+ h = (struct ext2fs_xattr_ibody_header *)start;
+ end = &((uint8_t *)di)[EXT2_DINODE_SIZE(ip->i_e2fs)];
+
+ if (end <= start || fs2h32(h->h_magic) != EXT2FS_XATTR_MAGIC)
+ return (ENODATA);
+
+ return ext2fs_find_xattr(EXT2FS_XATTR_IFIRST(h), start, end, attrnamespace, uio, size, name_index, name);
+}
+
+static int
+ext2fs_get_block_xattr(struct inode *ip, int attrnamespace, struct uio *uio, size_t *size, uint8_t name_index, const char *name)
+{
+ struct ext2fs_dinode *di = ip->i_din.e2fs_din;
+ uint8_t *start, *end;
+ struct ext2fs_xattr_header *h;
+ int error = 0;
+ struct buf *bp = NULL;
+ daddr_t xblk;
+
+ xblk = di->e2di_facl;
+ if (EXT2F_HAS_INCOMPAT_FEATURE(ip, EXT2F_INCOMPAT_64BIT))
+ xblk |= (((daddr_t)di->e2di_facl_high) << 32);
+
+ /* don't do anything if no attr block was allocated */
+ if (xblk == 0)
+ return (0);
+
+ error = bread(ip->i_devvp, fsbtodb(ip->i_e2fs, xblk), (int)ip->i_e2fs->e2fs_bsize, 0, &bp);
+ if (error)
+ goto out;
+
+ start = (uint8_t *)bp->b_data;
+ h = (struct ext2fs_xattr_header *)start;
+ end = &((uint8_t *)bp->b_data)[bp->b_bcount];
+
+ if (end <= start || fs2h32(h->h_magic) != EXT2FS_XATTR_MAGIC)
+ goto out;
+
+ error = ext2fs_find_xattr(EXT2FS_XATTR_BFIRST(h), start, end, attrnamespace, uio, size, name_index, name);
+
+ out:
+ if (bp)
+ brelse(bp, 0);
+ return (error);
+}
+int
+ext2fs_getextattr(void *v)
+{
+ struct vop_getextattr_args /* {
+ const struct vnodeop_desc *a_desc;
Home |
Main Index |
Thread Index |
Old Index