Date: Sun, 26 Mar 2017 11:36:48 +0300 From: Fedor Uporov <thisisadrgreenthumb@gmail.com> To: freebsd-fs@freebsd.org Subject: [PATCH] ext2fs: extended attributes read-only support Message-ID: <CAOEhZLuy4CNTP9Daz1zJhUP8=D_2Wv=2tWx3hx=cFBuMYjtsjw@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Here is the patch (attachment) to allow reading ext4 extended attributes on
FreeBSD side.
[-- Attachment #2 --]
From cc6ec0d06a28b697fca12edbd84bc139da0cff19 Mon Sep 17 00:00:00 2001
From: Fedor Uporov <thisisadrgreenthumb@gmail.com>
Date: Sun, 26 Mar 2017 11:27:58 +0300
Subject: [PATCH] ext2fs: add read-only support for extended attributes
---
sys/fs/ext2fs/ext2_extattr.c | 445 +++++++++++++++++++++++++++++++++++++++++
sys/fs/ext2fs/ext2_extattr.h | 102 ++++++++++
sys/fs/ext2fs/ext2_inode_cnv.c | 4 +
sys/fs/ext2fs/ext2_vnops.c | 3 +
sys/fs/ext2fs/ext2fs.h | 1 +
sys/fs/ext2fs/inode.h | 1 +
sys/modules/ext2fs/Makefile | 2 +-
7 files changed, 557 insertions(+), 1 deletion(-)
create mode 100644 sys/fs/ext2fs/ext2_extattr.c
create mode 100644 sys/fs/ext2fs/ext2_extattr.h
diff --git a/sys/fs/ext2fs/ext2_extattr.c b/sys/fs/ext2fs/ext2_extattr.c
new file mode 100644
index 0000000000000000000000000000000000000000..ef6a6a5aad9f9a1507ba03b28996664c6224d7d6
--- /dev/null
+++ b/sys/fs/ext2fs/ext2_extattr.c
@@ -0,0 +1,445 @@
+/*-
+ * Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * 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 AUTHOR 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 AUTHOR 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.
+ *
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from: @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95
+ * from: $FreeBSD: .../ufs/ufs_readwrite.c,v 1.96 2002/08/12 09:22:11 phk ...
+ * @(#)ffs_vnops.c 8.15 (Berkeley) 5/14/95
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/endian.h>
+#include <sys/conf.h>
+#include <sys/extattr.h>
+
+#include <fs/ext2fs/fs.h>
+#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/ext2_dinode.h>
+#include <fs/ext2fs/ext2_mount.h>
+#include <fs/ext2fs/ext2_extattr.h>
+
+
+static int
+ext2_extattr_index_to_bsd(int index)
+{
+ switch (index) {
+ case EXT4_XATTR_INDEX_USER:
+ return EXTATTR_NAMESPACE_USER;
+
+ case EXT4_XATTR_INDEX_SYSTEM:
+ return EXTATTR_NAMESPACE_SYSTEM;
+
+ default:
+ return EXTATTR_NAMESPACE_EMPTY;
+ }
+}
+
+static int
+ext2_extattr_inode_list(struct inode *ip, int attrnamespace,
+ struct uio *uio, size_t *size)
+{
+ struct m_ext2fs *fs;
+ struct buf *bp;
+ struct ext2fs_extattr_dinode_header *header;
+ struct ext2fs_extattr_entry *entry;
+ struct ext2fs_extattr_entry *next;
+ char *end;
+ int error;
+
+ fs = ip->i_e2fs;
+
+ if ((error = bread(ip->i_devvp,
+ fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
+ (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
+ brelse(bp);
+ return (error);
+ }
+
+ struct ext2fs_dinode *dinode = (struct ext2fs_dinode *)
+ ((char *)bp->b_data +
+ EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number));
+
+ /* Check attributes magic value */
+ header = (struct ext2fs_extattr_dinode_header*)((char *)dinode +
+ E2FS_REV0_INODE_SIZE + dinode->e2di_extra_isize);
+
+ if (header->h_magic != EXTATTR_MAGIC) {
+ brelse(bp);
+ return (0);
+ }
+
+ /* Check attributes integrity */
+ entry = IFIRST(header);
+ end = (char*)dinode + EXT2_INODE_SIZE(fs);
+ while (!IS_LAST_ENTRY(entry)) {
+ next = EXTATTR_NEXT(entry);
+ if ((char *)next >= end) {
+ brelse(bp);
+ return (EIO);
+ }
+
+ entry = next;
+ }
+
+ for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
+ entry = EXTATTR_NEXT(entry)) {
+ if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ continue;
+
+ if (uio == NULL) {
+ *size += entry->e_name_len + 1;
+ }
+ else {
+ char* attr_name = malloc(entry->e_name_len + 1, M_TEMP, M_WAITOK);
+ attr_name[0] = entry->e_name_len;
+ memcpy(&attr_name[1], entry->e_name, entry->e_name_len);
+ error = uiomove(attr_name, entry->e_name_len + 1, uio);
+ free(attr_name, M_TEMP);
+ }
+ }
+
+ brelse(bp);
+
+ return (0);
+}
+
+static int
+ext2_extattr_block_list(struct inode *ip, int attrnamespace,
+ struct uio *uio, size_t *size)
+{
+ struct m_ext2fs *fs;
+ struct buf *bp;
+ struct ext2fs_extattr_header* header;
+ struct ext2fs_extattr_entry *entry;
+ struct ext2fs_extattr_entry *next;
+ char *end;
+ int error;
+
+ fs = ip->i_e2fs;
+
+ error = bread(ip->i_devvp, fsbtodb(fs, ip->i_facl),
+ fs->e2fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+
+ /* Check attributes magic value */
+ header = HDR(bp);
+ if (header->h_magic != EXTATTR_MAGIC || header->h_blocks != 1) {
+ brelse(bp);
+ return (EINVAL);
+ }
+
+ /* Check attributes integrity */
+ end = bp->b_data + bp->b_bufsize;
+ entry = FIRST_ENTRY(bp);
+ while (!IS_LAST_ENTRY(entry)) {
+ next = EXTATTR_NEXT(entry);
+ if ((char *)next >= end) {
+ brelse(bp);
+ return (EIO);
+ }
+
+ entry = next;
+ }
+
+ for (entry = FIRST_ENTRY(bp); !IS_LAST_ENTRY(entry);
+ entry = EXTATTR_NEXT(entry)) {
+ if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ continue;
+
+ if (uio == NULL) {
+ *size += entry->e_name_len + 1;
+ }
+ else {
+ char* attr_name = malloc(entry->e_name_len + 1, M_TEMP, M_WAITOK);
+ attr_name[0] = entry->e_name_len;
+ memcpy(&attr_name[1], entry->e_name, entry->e_name_len);
+ error = uiomove(attr_name, entry->e_name_len + 1, uio);
+ free(attr_name, M_TEMP);
+ }
+ }
+
+ brelse(bp);
+
+ return (0);
+}
+
+int
+ext2_listextattr(struct vop_listextattr_args *ap)
+{
+ struct inode *ip;
+ struct m_ext2fs *fs;
+ int error;
+
+ ip = VTOI(ap->a_vp);
+ fs = ip->i_e2fs;
+
+ if (!EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXT_ATTR))
+ return (EOPNOTSUPP);
+
+ if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
+ return (EOPNOTSUPP);
+
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
+ ap->a_cred, ap->a_td, VREAD);
+ if (error)
+ return (error);
+
+ if (ap->a_size != NULL)
+ *ap->a_size = 0;
+
+ if (EXT2_INODE_SIZE(fs) != E2FS_REV0_INODE_SIZE)
+ error = ext2_extattr_inode_list(ip, ap->a_attrnamespace,
+ ap->a_uio, ap->a_size);
+
+ if(error)
+ return (error);
+
+ if(ip->i_facl)
+ error = ext2_extattr_block_list(ip, ap->a_attrnamespace,
+ ap->a_uio, ap->a_size);
+
+ return (error);
+}
+
+static int
+ext2_extattr_inode_get(struct inode *ip, int attrnamespace,
+ const char *name, struct uio *uio, size_t *size)
+{
+ struct m_ext2fs *fs;
+ struct buf *bp;
+ struct ext2fs_extattr_dinode_header *header;
+ struct ext2fs_extattr_entry *entry;
+ struct ext2fs_extattr_entry *next;
+ char *end;
+ int error;
+
+ fs = ip->i_e2fs;
+
+ if ((error = bread(ip->i_devvp,
+ fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
+ (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) {
+ brelse(bp);
+ return (error);
+ }
+
+ struct ext2fs_dinode *dinode = (struct ext2fs_dinode *)
+ ((char *)bp->b_data +
+ EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number));
+
+ /* Check attributes magic value */
+ header = (struct ext2fs_extattr_dinode_header*)((char *)dinode +
+ E2FS_REV0_INODE_SIZE + dinode->e2di_extra_isize);
+
+ if (header->h_magic != EXTATTR_MAGIC) {
+ brelse(bp);
+ return (0);
+ }
+
+ /* Check attributes integrity */
+ entry = IFIRST(header);
+ end = (char*)dinode + EXT2_INODE_SIZE(fs);
+ while (!IS_LAST_ENTRY(entry)) {
+ next = EXTATTR_NEXT(entry);
+ if ((char *)next >= end) {
+ brelse(bp);
+ return (EIO);
+ }
+
+ entry = next;
+ }
+
+ for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
+ entry = EXTATTR_NEXT(entry)) {
+ if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ continue;
+
+ if (strlen(name) == entry->e_name_len &&
+ 0 == strncmp(entry->e_name, name, entry->e_name_len)) {
+ if (uio == NULL) {
+ *size += entry->e_value_size;
+ }
+ else {
+ error = uiomove(((char*)IFIRST(header)) + entry->e_value_offs,
+ entry->e_value_size, uio);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+ }
+ }
+ }
+
+ brelse(bp);
+
+ return (0);
+}
+
+static int
+ext2_extattr_block_get(struct inode *ip, int attrnamespace,
+ const char *name, struct uio *uio, size_t *size)
+{
+ struct m_ext2fs *fs;
+ struct buf *bp;
+ struct ext2fs_extattr_header* header;
+ struct ext2fs_extattr_entry *entry;
+ struct ext2fs_extattr_entry *next;
+ char *end;
+ int error;
+
+ fs = ip->i_e2fs;
+
+ error = bread(ip->i_devvp, fsbtodb(fs, ip->i_facl),
+ fs->e2fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+
+ /* Check attributes magic value */
+ header = HDR(bp);
+ if (header->h_magic != EXTATTR_MAGIC || header->h_blocks != 1) {
+ brelse(bp);
+ return (EINVAL);
+ }
+
+ /* Check attributes integrity */
+ end = bp->b_data + bp->b_bufsize;
+ entry = FIRST_ENTRY(bp);
+ while (!IS_LAST_ENTRY(entry)) {
+ next = EXTATTR_NEXT(entry);
+ if ((char *)next >= end) {
+ brelse(bp);
+ return (EIO);
+ }
+
+ entry = next;
+ }
+
+ for (entry = FIRST_ENTRY(bp); !IS_LAST_ENTRY(entry);
+ entry = EXTATTR_NEXT(entry)) {
+ if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ continue;
+
+ if (strlen(name) == entry->e_name_len &&
+ 0 == strncmp(entry->e_name, name, entry->e_name_len)) {
+ if (uio == NULL) {
+ *size += entry->e_value_size;
+ }
+ else {
+ error = uiomove(bp->b_data + entry->e_value_offs,
+ entry->e_value_size, uio);
+ if (error) {
+ brelse(bp);
+ return (error);
+ }
+ }
+ }
+ }
+
+ brelse(bp);
+
+ return (0);
+}
+
+int
+ext2_getextattr(struct vop_getextattr_args *ap)
+{
+ struct inode *ip;
+ struct m_ext2fs *fs;
+ int error;
+
+ ip = VTOI(ap->a_vp);
+ fs = ip->i_e2fs;
+
+ if (!EXT2_HAS_COMPAT_FEATURE(ip->i_e2fs, EXT2F_COMPAT_EXT_ATTR))
+ return (EOPNOTSUPP);
+
+ if (ap->a_vp->v_type == VCHR || ap->a_vp->v_type == VBLK)
+ return (EOPNOTSUPP);
+
+ error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
+ ap->a_cred, ap->a_td, VREAD);
+ if (error)
+ return (error);
+
+ if (ap->a_size != NULL)
+ *ap->a_size = 0;
+
+ if (EXT2_INODE_SIZE(fs) != E2FS_REV0_INODE_SIZE)
+ error = ext2_extattr_inode_get(ip, ap->a_attrnamespace,
+ ap->a_name, ap->a_uio, ap->a_size);
+
+ if (error)
+ return (error);
+
+ if (ip->i_facl)
+ error = ext2_extattr_block_get(ip, ap->a_attrnamespace,
+ ap->a_name, ap->a_uio, ap->a_size);
+
+ return (error);
+}
diff --git a/sys/fs/ext2fs/ext2_extattr.h b/sys/fs/ext2fs/ext2_extattr.h
new file mode 100644
index 0000000000000000000000000000000000000000..82cb125ebb2bbcb3b954b667398e52a8b949b232
--- /dev/null
+++ b/sys/fs/ext2fs/ext2_extattr.h
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ufs_extern.h 8.10 (Berkeley) 5/14/95
+ * $FreeBSD$
+ */
+
+#ifndef _FS_EXT2FS_EXT2_EXTARTTR_H_
+#define _FS_EXT2FS_EXT2_EXTARTTR_H_
+
+/* Linux xattr name indexes */
+#define EXT4_XATTR_INDEX_USER 1
+#define EXT4_XATTR_INDEX_POSIX_ACL_ACCESS 2
+#define EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT 3
+#define EXT4_XATTR_INDEX_TRUSTED 4
+#define EXT4_XATTR_INDEX_LUSTRE 5
+#define EXT4_XATTR_INDEX_SECURITY 6
+#define EXT4_XATTR_INDEX_SYSTEM 7
+#define EXT4_XATTR_INDEX_RICHACL 8
+#define EXT4_XATTR_INDEX_ENCRYPTION 9
+
+/* Magic value in attribute blocks */
+#define EXTATTR_MAGIC 0xEA020000
+
+/* Maximum number of references to one attribute block */
+#define EXTATTR_REFCOUNT_MAX 1024
+
+struct ext2fs_extattr_header {
+ int32_t h_magic; /* magic number for identification */
+ int32_t h_refcount; /* reference count */
+ int32_t h_blocks; /* number of disk blocks used */
+ int32_t h_hash; /* hash value of all attributes */
+ uint32_t h_reserved[4]; /* zero right now */
+};
+
+struct ext2fs_extattr_dinode_header {
+ int32_t h_magic; /* magic number for identification */
+};
+
+struct ext2fs_extattr_entry {
+ uint8_t e_name_len; /* length of name */
+ uint8_t e_name_index; /* attribute name index */
+ uint16_t e_value_offs; /* offset in disk block of value */
+ uint32_t e_value_block; /* disk block attribute is stored on (n/i) */
+ uint32_t e_value_size; /* size of attribute value */
+ uint32_t e_hash; /* hash value of name and value */
+ char e_name[0]; /* attribute name */
+};
+
+#define IHDR(inode, raw_inode) \
+ ((struct ext4_xattr_ibody_header *) \
+ ((void *)raw_inode + \
+ EXT4_GOOD_OLD_INODE_SIZE + \
+ EXT4_I(inode)->i_extra_isize))
+
+#define IFIRST(hdr) ((struct ext2fs_extattr_entry *)((hdr)+1))
+
+#define HDR(bh) ((struct ext2fs_extattr_header *)((bh)->b_data))
+#define ENTRY(ptr) ((struct ext2fs_extattr_entry *)(ptr))
+#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
+#define IS_LAST_ENTRY(entry) (*(uint32_t *)(entry) == 0)
+
+#define EXTATTR_PAD_BITS 2
+#define EXTATTR_PAD (1<<EXTATTR_PAD_BITS)
+#define EXTATTR_ROUND (EXTATTR_PAD-1)
+#define EXTATTR_LEN(name_len) \
+ (((name_len) + EXTATTR_ROUND + \
+ sizeof(struct ext2fs_extattr_entry)) & ~EXTATTR_ROUND)
+
+#define EXTATTR_NEXT(entry) \
+ ( (struct ext2fs_extattr_entry *)( \
+ (char *)(entry) + EXTATTR_LEN((entry)->e_name_len)) )
+
+int ext2_listextattr(struct vop_listextattr_args *ap);
+int ext2_getextattr(struct vop_getextattr_args *ap);
+
+#endif /* !_FS_EXT2FS_EXT2_EXTARTTR_H_ */
diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c
index 988f0f85a912db0f0ab0cbd2664f72b96d61f37c..0845c9aa2f9f6b942557171ccbc4d4e2a5f8ab94 100644
--- a/sys/fs/ext2fs/ext2_inode_cnv.c
+++ b/sys/fs/ext2fs/ext2_inode_cnv.c
@@ -122,6 +122,10 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
ip->i_gen = ei->e2di_gen;
ip->i_uid = ei->e2di_uid;
ip->i_gid = ei->e2di_gid;
+ ip->i_facl = ei->e2di_facl;
+ if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs, EXT2F_INCOMPAT_64BIT))
+ ip->i_facl |= (((uint64_t)ei->e2di_facl_high) << 32);
+
/* XXX use memcpy */
for (i = 0; i < EXT2_NDADDR; i++)
ip->i_db[i] = ei->e2di_blocks[i];
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c
index 74ab4f053eb92762d377bd7b1d63f96d4deac04f..66c3c6c2d149799be96e8939e9f484d005040ce2 100644
--- a/sys/fs/ext2fs/ext2_vnops.c
+++ b/sys/fs/ext2fs/ext2_vnops.c
@@ -84,6 +84,7 @@
#include <fs/ext2fs/ext2_dinode.h>
#include <fs/ext2fs/ext2_dir.h>
#include <fs/ext2fs/ext2_mount.h>
+#include <fs/ext2fs/ext2_extattr.h>
static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
static void ext2_itimes_locked(struct vnode *);
@@ -153,6 +154,8 @@ struct vop_vector ext2_vnodeops = {
.vop_symlink = ext2_symlink,
.vop_write = ext2_write,
.vop_vptofh = ext2_vptofh,
+ .vop_listextattr = ext2_listextattr,
+ .vop_getextattr = ext2_getextattr,
};
struct vop_vector ext2_fifoops = {
diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h
index 0ba8a77a2bd584462355523f4fc6de498eeb3090..725e4afe65be3d3e18a5177c51565dff5dbf330c 100644
--- a/sys/fs/ext2fs/ext2fs.h
+++ b/sys/fs/ext2fs/ext2fs.h
@@ -204,6 +204,7 @@ struct csum {
*/
#define EXT2F_COMPAT_PREALLOC 0x0001
#define EXT2F_COMPAT_HASJOURNAL 0x0004
+#define EXT2F_COMPAT_EXT_ATTR 0x0008
#define EXT2F_COMPAT_RESIZE 0x0010
#define EXT2F_COMPAT_DIRHASHINDEX 0x0020
#define EXT2F_COMPAT_SPARSESUPER2 0x0200
diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h
index 4f64c35f2a18692d852a996c8620075ad611a6f9..6f67c7c978a832f2f24989e7e44475a162187fd0 100644
--- a/sys/fs/ext2fs/inode.h
+++ b/sys/fs/ext2fs/inode.h
@@ -105,6 +105,7 @@ struct inode {
int32_t i_ctimensec; /* Last inode change time. */
int32_t i_birthnsec; /* Inode creation time. */
uint32_t i_gen; /* Generation number. */
+ uint64_t i_facl; /* Extended attribute block number */
uint32_t i_flags; /* Status flags (chflags). */
uint32_t i_db[EXT2_NDADDR]; /* Direct disk blocks. */
uint32_t i_ib[EXT2_NIADDR]; /* Indirect disk blocks. */
diff --git a/sys/modules/ext2fs/Makefile b/sys/modules/ext2fs/Makefile
index 70814bfb1223c5f522b4a7a02df75d99e315f259..0c310cabf3bd1fd62c711cb7cc66757f88a75ec1 100644
--- a/sys/modules/ext2fs/Makefile
+++ b/sys/modules/ext2fs/Makefile
@@ -5,6 +5,6 @@ KMOD= ext2fs
SRCS= opt_ddb.h opt_directio.h opt_quota.h opt_suiddir.h vnode_if.h \
ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_extents.c ext2_hash.c \
ext2_htree.c ext2_inode.c ext2_inode_cnv.c ext2_lookup.c ext2_subr.c \
- ext2_vfsops.c ext2_vnops.c
+ ext2_extattr.c ext2_vfsops.c ext2_vnops.c
.include <bsd.kmod.mk>
--
2.1.4
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAOEhZLuy4CNTP9Daz1zJhUP8=D_2Wv=2tWx3hx=cFBuMYjtsjw>
