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