Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147921595
D10807.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
35 KB
Referenced Files
None
Subscribers
None
D10807.id.diff
View Options
Index: head/sys/conf/files
===================================================================
--- head/sys/conf/files
+++ head/sys/conf/files
@@ -3525,6 +3525,7 @@
geom/virstor/g_virstor.c optional geom_virstor
geom/virstor/g_virstor_md.c optional geom_virstor
geom/zero/g_zero.c optional geom_zero
+fs/ext2fs/ext2_acl.c optional ext2fs
fs/ext2fs/ext2_alloc.c optional ext2fs
fs/ext2fs/ext2_balloc.c optional ext2fs
fs/ext2fs/ext2_bmap.c optional ext2fs
Index: head/sys/fs/ext2fs/ext2_acl.h
===================================================================
--- head/sys/fs/ext2fs/ext2_acl.h
+++ head/sys/fs/ext2fs/ext2_acl.h
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2017, Fedor Uporov
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FS_EXT2FS_EXT2_ACL_H_
+#define _FS_EXT2FS_EXT2_ACL_H_
+
+#define EXT4_ACL_VERSION 0x0001
+
+struct ext2_acl_entry {
+ int16_t ae_tag;
+ int16_t ae_perm;
+ int32_t ae_id;
+};
+
+struct ext2_acl_entry_short {
+ int16_t ae_tag;
+ int16_t ae_perm;
+};
+
+struct ext2_acl_header {
+ int32_t a_version;
+};
+
+void ext2_sync_acl_from_inode(struct inode *ip, struct acl *acl);
+
+int ext2_getacl(struct vop_getacl_args *);
+int ext2_setacl(struct vop_setacl_args *);
+int ext2_aclcheck(struct vop_aclcheck_args *);
+
+#endif /* !_FS_EXT2FS_EXT2_ACL_H_ */
Index: head/sys/fs/ext2fs/ext2_acl.c
===================================================================
--- head/sys/fs/ext2fs/ext2_acl.c
+++ head/sys/fs/ext2fs/ext2_acl.c
@@ -0,0 +1,521 @@
+/*-
+ * Copyright (c) 2017, Fedor Uporov
+ * 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.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/stat.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/mount.h>
+#include <sys/extattr.h>
+
+#include <fs/ext2fs/fs.h>
+#include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/ext2_acl.h>
+#include <fs/ext2fs/ext2_extattr.h>
+#include <fs/ext2fs/ext2_extern.h>
+#include <fs/ext2fs/ext2_dinode.h>
+#include <fs/ext2fs/ext2_mount.h>
+
+void
+ext2_sync_acl_from_inode(struct inode *ip, struct acl *acl)
+{
+ struct acl_entry *acl_mask, *acl_group_obj;
+ int i;
+
+ /*
+ * Update ACL_USER_OBJ, ACL_OTHER, but simply identify ACL_MASK
+ * and ACL_GROUP_OBJ for use after we know whether ACL_MASK is
+ * present.
+ */
+ acl_mask = NULL;
+ acl_group_obj = NULL;
+ for (i = 0; i < acl->acl_cnt; i++) {
+ switch (acl->acl_entry[i].ae_tag) {
+ case ACL_USER_OBJ:
+ acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm(
+ ACL_USER_OBJ, ip->i_mode);
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_GROUP_OBJ:
+ acl_group_obj = &acl->acl_entry[i];
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_OTHER:
+ acl->acl_entry[i].ae_perm = acl_posix1e_mode_to_perm(
+ ACL_OTHER, ip->i_mode);
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_MASK:
+ acl_mask = &acl->acl_entry[i];
+ acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ break;
+
+ default:
+ panic("ext2_sync_acl_from_inode(): bad ae_tag");
+ }
+ }
+
+ if (acl_group_obj == NULL)
+ panic("ext2_sync_acl_from_inode(): no ACL_GROUP_OBJ");
+
+ if (acl_mask == NULL) {
+ /*
+ * There is no ACL_MASK, so update ACL_GROUP_OBJ.
+ */
+ acl_group_obj->ae_perm = acl_posix1e_mode_to_perm(
+ ACL_GROUP_OBJ, ip->i_mode);
+ } else {
+ /*
+ * Update the ACL_MASK entry instead of ACL_GROUP_OBJ.
+ */
+ acl_mask->ae_perm = acl_posix1e_mode_to_perm(ACL_GROUP_OBJ,
+ ip->i_mode);
+ }
+}
+
+static void
+ext2_sync_inode_from_acl(struct acl *acl, struct inode *ip)
+{
+
+ ip->i_mode &= ACL_PRESERVE_MASK;
+ ip->i_mode |= acl_posix1e_acl_to_mode(acl);
+}
+
+/*
+ * Convert from filesystem to in-memory representation.
+ */
+static int
+ext4_acl_from_disk(char *value, size_t size, struct acl *acl)
+{
+ const char *end = value + size;
+ int n, count, s;
+
+ if (((struct ext2_acl_header *)value)->a_version != EXT4_ACL_VERSION)
+ return (EINVAL);
+
+ if (!value || size < sizeof(struct ext2_acl_header))
+ return (EINVAL);
+
+ s = size - sizeof(struct ext2_acl_header);
+ s -= 4 * sizeof(struct ext2_acl_entry_short);
+ if (s < 0)
+ if ((size - sizeof(struct ext2_acl_header)) %
+ sizeof(struct ext2_acl_entry_short))
+ count = -1;
+ else
+ count = (size - sizeof(struct ext2_acl_header)) /
+ sizeof(struct ext2_acl_entry_short);
+ else
+ if (s % sizeof(struct ext2_acl_entry))
+ count = -1;
+ else
+ count = s / sizeof(struct ext2_acl_entry) + 4;
+
+ if (count <= 0 || count > acl->acl_maxcnt)
+ return (EINVAL);
+
+ value = value + sizeof(struct ext2_acl_header);
+
+ for (n = 0; n < count; n++) {
+ struct ext2_acl_entry *entry = (struct ext2_acl_entry *)value;
+ if ((char *)value + sizeof(struct ext2_acl_entry_short) > end)
+ return (EINVAL);
+
+ acl->acl_entry[n].ae_tag = entry->ae_tag;
+ acl->acl_entry[n].ae_perm = entry->ae_perm;
+
+ switch (acl->acl_entry[n].ae_tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ value = (char *)value + sizeof(struct ext2_acl_entry_short);
+ break;
+
+ case ACL_USER:
+ value = (char *)value + sizeof(struct ext2_acl_entry);
+ if ((char *)value > end)
+ return (EINVAL);
+
+ acl->acl_entry[n].ae_id = entry->ae_id;
+ break;
+
+ case ACL_GROUP:
+ value = (char *)value + sizeof(struct ext2_acl_entry);
+ if ((char *)value > end)
+ return (EINVAL);
+
+ acl->acl_entry[n].ae_id = entry->ae_id;
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ }
+
+ if (value != end)
+ return (EINVAL);
+
+ acl->acl_cnt = count;
+
+ return (0);
+}
+
+static int
+ext2_getacl_posix1e(struct vop_getacl_args *ap)
+{
+ int attrnamespace;
+ const char *attrname;
+ char *value;
+ int len;
+ int error;
+
+ len = sizeof(*ap->a_aclp) + sizeof(struct ext2_acl_header);
+ value = malloc(len, M_ACL, M_WAITOK);
+ if (!value)
+ return (ENOMEM);
+
+ switch (ap->a_type) {
+ case ACL_TYPE_DEFAULT:
+ attrnamespace = POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE;
+ attrname = POSIX1E_ACL_DEFAULT_EXTATTR_NAME;
+ break;
+ case ACL_TYPE_ACCESS:
+ attrnamespace = POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE;
+ attrname = POSIX1E_ACL_ACCESS_EXTATTR_NAME;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ error = vn_extattr_get(ap->a_vp, IO_NODELOCKED, attrnamespace, attrname,
+ &len, value, ap->a_td);
+ switch (error) {
+ case ENOATTR:
+ switch (ap->a_type) {
+ case ACL_TYPE_ACCESS:
+ ap->a_aclp->acl_cnt = 3;
+ ap->a_aclp->acl_entry[0].ae_tag = ACL_USER_OBJ;
+ ap->a_aclp->acl_entry[0].ae_id = ACL_UNDEFINED_ID;
+ ap->a_aclp->acl_entry[0].ae_perm = ACL_PERM_NONE;
+ ap->a_aclp->acl_entry[1].ae_tag = ACL_GROUP_OBJ;
+ ap->a_aclp->acl_entry[1].ae_id = ACL_UNDEFINED_ID;
+ ap->a_aclp->acl_entry[1].ae_perm = ACL_PERM_NONE;
+ ap->a_aclp->acl_entry[2].ae_tag = ACL_OTHER;
+ ap->a_aclp->acl_entry[2].ae_id = ACL_UNDEFINED_ID;
+ ap->a_aclp->acl_entry[2].ae_perm = ACL_PERM_NONE;
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ ap->a_aclp->acl_cnt = 0;
+ break;
+ }
+ case 0:
+ if (!error) {
+ error = ext4_acl_from_disk(value, len, ap->a_aclp);
+ if (error)
+ goto out;
+ }
+
+ if (error == ENOATTR)
+ error = 0;
+
+ if (ap->a_type == ACL_TYPE_ACCESS)
+ ext2_sync_acl_from_inode(VTOI(ap->a_vp), ap->a_aclp);
+ default:
+ break;
+ }
+
+out:
+ free(value, M_TEMP);
+ return (error);
+}
+
+int
+ext2_getacl(struct vop_getacl_args *ap)
+{
+
+ if (((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) ||
+ ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 1))
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ENOTSUP);
+
+ return (ext2_getacl_posix1e(ap));
+}
+
+/*
+ * Convert from in-memory to filesystem representation.
+ */
+static int
+ext4_acl_to_disk(const struct acl *acl, size_t *size, char *value)
+{
+ struct ext2_acl_header *ext_acl;
+ int disk_size;
+ char *e;
+ size_t n;
+
+ if (acl->acl_cnt <= 4)
+ disk_size = sizeof(struct ext2_acl_header) +
+ acl->acl_cnt * sizeof(struct ext2_acl_entry_short);
+ else
+ disk_size = sizeof(struct ext2_acl_header) +
+ 4 * sizeof(struct ext2_acl_entry_short) +
+ (acl->acl_cnt - 4) * sizeof(struct ext2_acl_entry);
+
+ if (disk_size > *size)
+ return (EINVAL);
+
+ *size = disk_size;
+ ext_acl = (struct ext2_acl_header *)value;
+
+ ext_acl->a_version = EXT4_ACL_VERSION;
+ e = (char *)ext_acl + sizeof(struct ext2_acl_header);
+ for (n = 0; n < acl->acl_cnt; n++) {
+ const struct acl_entry *acl_e = &acl->acl_entry[n];
+ struct ext2_acl_entry *entry = (struct ext2_acl_entry *)e;
+ entry->ae_tag = acl_e->ae_tag;
+ entry->ae_perm = acl_e->ae_perm;
+ switch (acl_e->ae_tag) {
+ case ACL_USER:
+ entry->ae_id = acl_e->ae_id;
+ e += sizeof(struct ext2_acl_entry);
+ break;
+
+ case ACL_GROUP:
+ entry->ae_id = acl_e->ae_id;
+ e += sizeof(struct ext2_acl_entry);
+ break;
+
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ e += sizeof(struct ext2_acl_entry_short);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ }
+
+ return (0);
+}
+
+static int
+ext2_setacl_posix1e(struct vop_setacl_args *ap)
+{
+ struct inode *ip = VTOI(ap->a_vp);
+ char *value;
+ size_t len;
+ int error;
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
+ return (EINVAL);
+
+ /*
+ * If this is a set operation rather than a delete operation,
+ * invoke VOP_ACLCHECK() on the passed ACL to determine if it is
+ * valid for the target. This will include a check on ap->a_type.
+ */
+ if (ap->a_aclp != NULL) {
+ /*
+ * Set operation.
+ */
+ error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp,
+ ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
+ } else {
+ /*
+ * Delete operation.
+ * POSIX.1e allows only deletion of the default ACL on a
+ * directory (ACL_TYPE_DEFAULT).
+ */
+ if (ap->a_type != ACL_TYPE_DEFAULT)
+ return (EINVAL);
+ if (ap->a_vp->v_type != VDIR)
+ return (ENOTDIR);
+ }
+
+ if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
+ return (EROFS);
+
+ /*
+ * Authorize the ACL operation.
+ */
+ if (ip->i_flags & (IMMUTABLE | APPEND))
+ return (EPERM);
+
+ /*
+ * Must hold VADMIN (be file owner) or have appropriate privilege.
+ */
+ if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td)))
+ return (error);
+
+ switch (ap->a_type) {
+ case ACL_TYPE_ACCESS:
+ len = sizeof(*ap->a_aclp) + sizeof(struct ext2_acl_header);
+ value = malloc(len, M_ACL, M_WAITOK | M_ZERO);
+ error = ext4_acl_to_disk(ap->a_aclp, &len, value);
+ if (error == 0)
+ error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
+ POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_ACCESS_EXTATTR_NAME, len,
+ value, ap->a_td);
+
+ free(value, M_ACL);
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ if (ap->a_aclp == NULL) {
+ error = vn_extattr_rm(ap->a_vp, IO_NODELOCKED,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAME, ap->a_td);
+
+ /*
+ * Attempting to delete a non-present default ACL
+ * will return success for portability purposes.
+ * (TRIX)
+ *
+ * XXX: Note that since we can't distinguish
+ * "that EA is not supported" from "that EA is not
+ * defined", the success case here overlaps the
+ * the ENOATTR->EOPNOTSUPP case below.
+ */
+ if (error == ENOATTR)
+ error = 0;
+ } else {
+ len = sizeof(*ap->a_aclp) + sizeof(struct ext2_acl_header);
+ value = malloc(len, M_ACL, M_WAITOK | M_ZERO);
+ error = ext4_acl_to_disk(ap->a_aclp, &len, value);
+ if (error == 0)
+ error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
+ POSIX1E_ACL_DEFAULT_EXTATTR_NAME, len,
+ value, ap->a_td);
+
+ free(value, M_ACL);
+ }
+ break;
+
+ default:
+ error = EINVAL;
+ }
+
+ /*
+ * Map lack of attribute definition in UFS_EXTATTR into lack of
+ * support for ACLs on the filesystem.
+ */
+ if (error == ENOATTR)
+ return (EOPNOTSUPP);
+
+ if (error != 0)
+ return (error);
+
+ if (ap->a_type == ACL_TYPE_ACCESS) {
+ /*
+ * Now that the EA is successfully updated, update the
+ * inode and mark it as changed.
+ */
+ ext2_sync_inode_from_acl(ap->a_aclp, ip);
+ ip->i_flag |= IN_CHANGE;
+ error = ext2_update(ip->i_vnode, 1);
+ }
+
+ VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB);
+
+ return (error);
+}
+
+int
+ext2_setacl(struct vop_setacl_args *ap)
+{
+ if (((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) ||
+ ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 1))
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ENOTSUP);
+
+ return (ext2_setacl_posix1e(ap));
+}
+
+/*
+ * Check the validity of an ACL for a file.
+ */
+int
+ext2_aclcheck(struct vop_aclcheck_args *ap)
+{
+
+ if (((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0) ||
+ ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 1))
+ return (EOPNOTSUPP);
+
+ if (ap->a_type == ACL_TYPE_NFS4)
+ return (ENOTSUP);
+
+ if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
+ return (EINVAL);
+
+ /*
+ * Verify we understand this type of ACL, and that it applies
+ * to this kind of object.
+ * Rely on the acl_posix1e_check() routine to verify the contents.
+ */
+ switch (ap->a_type) {
+ case ACL_TYPE_ACCESS:
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ if (ap->a_vp->v_type != VDIR)
+ return (EINVAL);
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ return (acl_posix1e_check(ap->a_aclp));
+}
\ No newline at end of file
Index: head/sys/fs/ext2fs/ext2_extattr.c
===================================================================
--- head/sys/fs/ext2fs/ext2_extattr.c
+++ head/sys/fs/ext2fs/ext2_extattr.c
@@ -46,35 +46,92 @@
#include <fs/ext2fs/ext2_extattr.h>
#include <fs/ext2fs/ext2_extern.h>
-
static int
-ext2_extattr_index_to_bsd(int index)
+ext2_extattr_attrnamespace_to_bsd(int attrnamespace)
{
- switch (index) {
- case EXT4_XATTR_INDEX_SYSTEM:
- return (EXTATTR_NAMESPACE_SYSTEM);
- case EXT4_XATTR_INDEX_USER:
- return (EXTATTR_NAMESPACE_USER);
+ switch (attrnamespace) {
+ case EXT4_XATTR_INDEX_SYSTEM:
+ return (EXTATTR_NAMESPACE_SYSTEM);
+
+ case EXT4_XATTR_INDEX_USER:
+ return (EXTATTR_NAMESPACE_USER);
+
+ case EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT:
+ return (POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE);
+
+ case EXT4_XATTR_INDEX_POSIX_ACL_ACCESS:
+ return (POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE);
}
return (EXTATTR_NAMESPACE_EMPTY);
}
+static const char *
+ext2_extattr_name_to_bsd(int attrnamespace, const char *name, int* name_len)
+{
+
+ if (attrnamespace == EXT4_XATTR_INDEX_SYSTEM)
+ return (name);
+ else if (attrnamespace == EXT4_XATTR_INDEX_USER)
+ return (name);
+ else if (attrnamespace == EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT) {
+ *name_len = strlen(POSIX1E_ACL_DEFAULT_EXTATTR_NAME);
+ return (POSIX1E_ACL_DEFAULT_EXTATTR_NAME);
+ } else if (attrnamespace == EXT4_XATTR_INDEX_POSIX_ACL_ACCESS) {
+ *name_len = strlen(POSIX1E_ACL_ACCESS_EXTATTR_NAME);
+ return (POSIX1E_ACL_ACCESS_EXTATTR_NAME);
+ }
+
+ /*
+ * XXX: Not all linux namespaces are mapped to bsd for now,
+ * return NULL, which will be converted to ENOTSUP on upper layer.
+ */
+#ifdef EXT2FS_DEBUG
+ printf("can not convert ext2fs name to bsd: namespace=%d\n", attrnamespace);
+#endif /* DEBUG */
+
+ return (NULL);
+}
+
static int
-ext2_extattr_index_to_linux(int index)
+ext2_extattr_attrnamespace_to_linux(int attrnamespace, const char *name)
{
- switch (index) {
- case EXTATTR_NAMESPACE_SYSTEM:
- return (EXT4_XATTR_INDEX_SYSTEM);
- case EXTATTR_NAMESPACE_USER:
- return (EXT4_XATTR_INDEX_USER);
+ if (attrnamespace == POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE &&
+ !strcmp(name, POSIX1E_ACL_DEFAULT_EXTATTR_NAME))
+ return (EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT);
+
+ if (attrnamespace == POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE &&
+ !strcmp(name, POSIX1E_ACL_ACCESS_EXTATTR_NAME))
+ return (EXT4_XATTR_INDEX_POSIX_ACL_ACCESS);
+
+ switch (attrnamespace) {
+ case EXTATTR_NAMESPACE_SYSTEM:
+ return (EXT4_XATTR_INDEX_SYSTEM);
+
+ case EXTATTR_NAMESPACE_USER:
+ return (EXT4_XATTR_INDEX_USER);
}
+ /*
+ * In this case namespace conversion should be unique,
+ * so this point is unreachable.
+ */
return (-1);
}
+static const char *
+ext2_extattr_name_to_linux(int attrnamespace, const char *name)
+{
+
+ if (attrnamespace == POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE ||
+ attrnamespace == POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE)
+ return ("");
+ else
+ return (name);
+}
+
int
ext2_extattr_valid_attrname(int attrnamespace, const char *attrname)
{
@@ -114,6 +171,8 @@
struct buf *bp;
struct ext2fs_extattr_dinode_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
int error;
fs = ip->i_e2fs;
@@ -147,17 +206,26 @@
for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) !=
+ attrnamespace)
continue;
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
if (uio == NULL)
- *size += entry->e_name_len + 1;
+ *size += 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);
+ char *name = malloc(name_len + 1, M_TEMP, M_WAITOK);
+ name[0] = name_len;
+ memcpy(&name[1], attr_name, name_len);
+ error = uiomove(name, name_len + 1, uio);
+ free(name, M_TEMP);
if (error)
break;
}
@@ -176,6 +244,8 @@
struct buf *bp;
struct ext2fs_extattr_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
int error;
fs = ip->i_e2fs;
@@ -202,17 +272,26 @@
for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) !=
+ attrnamespace)
continue;
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
if (uio == NULL)
- *size += entry->e_name_len + 1;
+ *size += 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);
+ char *name = malloc(name_len + 1, M_TEMP, M_WAITOK);
+ name[0] = name_len;
+ memcpy(&name[1], attr_name, name_len);
+ error = uiomove(name, name_len + 1, uio);
+ free(name, M_TEMP);
if (error)
break;
}
@@ -231,6 +310,8 @@
struct buf *bp;
struct ext2fs_extattr_dinode_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
int error;
fs = ip->i_e2fs;
@@ -264,11 +345,20 @@
for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_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)) {
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len)) {
if (uio == NULL)
*size += entry->e_value_size;
else {
@@ -294,6 +384,8 @@
struct buf *bp;
struct ext2fs_extattr_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
int error;
fs = ip->i_e2fs;
@@ -320,11 +412,20 @@
for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_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)) {
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len)) {
if (uio == NULL)
*size += entry->e_value_size;
else {
@@ -411,6 +512,8 @@
struct buf *bp;
struct ext2fs_extattr_dinode_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
int error;
fs = ip->i_e2fs;
@@ -444,9 +547,20 @@
/* If I am last entry, just make magic zero */
entry = EXT2_IFIRST(header);
- if (EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry))) {
- if (strlen(name) == entry->e_name_len &&
- 0 == strncmp(entry->e_name, name, entry->e_name_len)) {
+ if ((EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry))) &&
+ (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) ==
+ attrnamespace)) {
+
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len)) {
memset(header, 0, sizeof(struct ext2fs_extattr_dinode_header));
return (bwrite(bp));
@@ -455,11 +569,20 @@
for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_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)) {
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len)) {
ext2_extattr_delete_entry((char *)EXT2_IFIRST(header),
EXT2_IFIRST(header), entry,
(char *)dinode + EXT2_INODE_SIZE(fs));
@@ -521,6 +644,8 @@
struct buf *bp;
struct ext2fs_extattr_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
int error;
fs = ip->i_e2fs;
@@ -555,9 +680,20 @@
/* If I am last entry, clean me and free the block */
entry = EXT2_FIRST_ENTRY(bp);
- if (EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry))) {
- if (strlen(name) == entry->e_name_len &&
- 0 == strncmp(entry->e_name, name, entry->e_name_len)) {
+ if (EXT2_IS_LAST_ENTRY(EXT2_EXTATTR_NEXT(entry)) &&
+ (ext2_extattr_attrnamespace_to_bsd(entry->e_name_index) ==
+ attrnamespace)) {
+
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len)) {
ip->i_blocks -= btodb(fs->e2fs_bsize);
ext2_blkfree(ip, ip->i_facl, fs->e2fs_bsize);
ip->i_facl = 0;
@@ -570,11 +706,20 @@
for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_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)) {
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len)) {
ext2_extattr_delete_entry(bp->b_data,
EXT2_FIRST_ENTRY(bp), entry,
bp->b_data + bp->b_bufsize);
@@ -592,15 +737,18 @@
allocate_entry(const char *name, int attrnamespace, uint16_t offs,
uint32_t size, uint32_t hash)
{
- size_t name_len;
+ const char *attr_name;
+ int name_len;
struct ext2fs_extattr_entry *entry;
- name_len = strlen(name);
+ attr_name = ext2_extattr_name_to_linux(attrnamespace, name);
+ name_len = strlen(attr_name);
+
entry = malloc(sizeof(struct ext2fs_extattr_entry) + name_len,
M_TEMP, M_WAITOK);
entry->e_name_len = name_len;
- entry->e_name_index = ext2_extattr_index_to_linux(attrnamespace);
+ entry->e_name_index = ext2_extattr_attrnamespace_to_linux(attrnamespace, name);
entry->e_value_offs = offs;
entry->e_value_block = 0;
entry->e_value_size = size;
@@ -727,6 +875,8 @@
struct buf *bp;
struct ext2fs_extattr_dinode_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
size_t size = 0, max_size;
int error;
@@ -762,11 +912,20 @@
/* Find if entry exist */
for (entry = EXT2_IFIRST(header); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_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))
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len))
break;
}
@@ -876,6 +1035,8 @@
struct buf *bp;
struct ext2fs_extattr_header *header;
struct ext2fs_extattr_entry *entry;
+ const char *attr_name;
+ int name_len;
size_t size;
int error;
@@ -916,11 +1077,20 @@
/* Find if entry exist */
for (entry = EXT2_FIRST_ENTRY(bp); !EXT2_IS_LAST_ENTRY(entry);
entry = EXT2_EXTATTR_NEXT(entry)) {
- if (ext2_extattr_index_to_bsd(entry->e_name_index) != attrnamespace)
+ if (ext2_extattr_attrnamespace_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))
+ name_len = entry->e_name_len;
+ attr_name = ext2_extattr_name_to_bsd(entry->e_name_index,
+ entry->e_name, &name_len);
+ if (!attr_name) {
+ brelse(bp);
+ return (ENOTSUP);
+ }
+
+ if (strlen(name) == name_len &&
+ 0 == strncmp(attr_name, name, name_len))
break;
}
@@ -961,7 +1131,8 @@
}
size = ext2_extattr_get_size(NULL, NULL,
- sizeof(struct ext2fs_extattr_header), strlen(name), uio->uio_resid);
+ sizeof(struct ext2fs_extattr_header),
+ strlen(ext2_extattr_name_to_linux(attrnamespace, name)), uio->uio_resid);
if (size > fs->e2fs_bsize)
return (ENOSPC);
Index: head/sys/fs/ext2fs/ext2_vnops.c
===================================================================
--- head/sys/fs/ext2fs/ext2_vnops.c
+++ head/sys/fs/ext2fs/ext2_vnops.c
@@ -81,6 +81,7 @@
#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/inode.h>
+#include <fs/ext2fs/ext2_acl.h>
#include <fs/ext2fs/ext2_extern.h>
#include <fs/ext2fs/ext2fs.h>
#include <fs/ext2fs/ext2_dinode.h>
@@ -163,6 +164,9 @@
.vop_getextattr = ext2_getextattr,
.vop_listextattr = ext2_listextattr,
.vop_setextattr = ext2_setextattr,
+ .vop_getacl = ext2_getacl,
+ .vop_setacl = ext2_setacl,
+ .vop_aclcheck = ext2_aclcheck,
.vop_vptofh = ext2_vptofh,
};
@@ -1083,6 +1087,150 @@
return (error);
}
+static int
+ext2_do_posix1e_acl_inheritance_dir(struct vnode *dvp, struct vnode *tvp,
+ mode_t dmode, struct ucred *cred, struct thread *td)
+{
+ int error;
+ struct inode *ip = VTOI(tvp);
+ struct acl *dacl, *acl;
+
+ acl = acl_alloc(M_WAITOK);
+ dacl = acl_alloc(M_WAITOK);
+
+ /*
+ * Retrieve default ACL from parent, if any.
+ */
+ error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred, td);
+ switch (error) {
+ case 0:
+ /*
+ * Retrieved a default ACL, so merge mode and ACL if
+ * necessary. If the ACL is empty, fall through to
+ * the "not defined or available" case.
+ */
+ if (acl->acl_cnt != 0) {
+ dmode = acl_posix1e_newfilemode(dmode, acl);
+ ip->i_mode = dmode;
+ *dacl = *acl;
+ ext2_sync_acl_from_inode(ip, acl);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EOPNOTSUPP:
+ /*
+ * Just use the mode as-is.
+ */
+ ip->i_mode = dmode;
+ error = 0;
+ goto out;
+
+ default:
+ goto out;
+ }
+
+ error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred, td);
+ if (error == 0)
+ error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl, cred, td);
+ switch (error) {
+ case 0:
+ break;
+
+ case EOPNOTSUPP:
+ /*
+ * XXX: This should not happen, as EOPNOTSUPP above
+ * was supposed to free acl.
+ */
+#ifdef DEBUG
+ printf("ext2_mkdir: VOP_GETACL() but no VOP_SETACL()\n");
+#endif /* DEBUG */
+ break;
+
+ default:
+ goto out;
+ }
+
+out:
+ acl_free(acl);
+ acl_free(dacl);
+
+ return (error);
+}
+
+static int
+ext2_do_posix1e_acl_inheritance_file(struct vnode *dvp, struct vnode *tvp,
+ mode_t mode, struct ucred *cred, struct thread *td)
+{
+ int error;
+ struct inode *ip = VTOI(tvp);
+ struct acl *acl;
+
+ acl = acl_alloc(M_WAITOK);
+
+ /*
+ * Retrieve default ACL for parent, if any.
+ */
+ error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred, td);
+ switch (error) {
+ case 0:
+ /*
+ * Retrieved a default ACL, so merge mode and ACL if
+ * necessary.
+ */
+ if (acl->acl_cnt != 0) {
+ /*
+ * Two possible ways for default ACL to not
+ * be present. First, the EA can be
+ * undefined, or second, the default ACL can
+ * be blank. If it's blank, fall through to
+ * the it's not defined case.
+ */
+ mode = acl_posix1e_newfilemode(mode, acl);
+ ip->i_mode = mode;
+ ext2_sync_acl_from_inode(ip, acl);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case EOPNOTSUPP:
+ /*
+ * Just use the mode as-is.
+ */
+ ip->i_mode = mode;
+ error = 0;
+ goto out;
+
+ default:
+ goto out;
+ }
+
+ error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred, td);
+ switch (error) {
+ case 0:
+ break;
+
+ case EOPNOTSUPP:
+ /*
+ * XXX: This should not happen, as EOPNOTSUPP above was
+ * supposed to free acl.
+ */
+ printf("ufs_do_posix1e_acl_inheritance_file: VOP_GETACL() "
+ "but no VOP_SETACL()\n");
+ /* panic("ufs_do_posix1e_acl_inheritance_file: VOP_GETACL() "
+ "but no VOP_SETACL()"); */
+ break;
+
+ default:
+ goto out;
+ }
+
+out:
+ acl_free(acl);
+
+ return (error);
+}
+
/*
* Mkdir system call
*/
@@ -1192,6 +1340,13 @@
ip->i_flag |= IN_CHANGE;
}
+ if (dvp->v_mount->mnt_flag & MNT_ACLS) {
+ error = ext2_do_posix1e_acl_inheritance_dir(dvp, tvp, dmode,
+ cnp->cn_cred, cnp->cn_thread);
+ if (error)
+ goto bad;
+ }
+
/* Directory set up, now install its entry in the parent directory. */
error = ext2_direnter(ip, dvp, cnp);
if (error) {
@@ -1446,6 +1601,18 @@
case _PC_NO_TRUNC:
*ap->a_retval = 1;
break;
+ case _PC_ACL_EXTENDED:
+ if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
+ *ap->a_retval = 1;
+ else
+ *ap->a_retval = 0;
+ break;
+ case _PC_ACL_PATH_MAX:
+ if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
+ *ap->a_retval = ACL_MAX_ENTRIES;
+ else
+ *ap->a_retval = 3;
+ break;
case _PC_MIN_HOLE_SIZE:
*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
break;
@@ -1513,6 +1680,8 @@
if (error)
return (error);
+ error = ENOATTR;
+
if (EXT2_INODE_SIZE(fs) != E2FS_REV0_INODE_SIZE) {
error = ext2_extattr_inode_delete(ip, ap->a_attrnamespace, ap->a_name);
if (error != ENOATTR)
@@ -1552,6 +1721,8 @@
if (ap->a_size != NULL)
*ap->a_size = 0;
+ error = ENOATTR;
+
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);
@@ -1755,6 +1926,14 @@
error = ext2_update(tvp, !DOINGASYNC(tvp));
if (error)
goto bad;
+
+ if (dvp->v_mount->mnt_flag & MNT_ACLS) {
+ error = ext2_do_posix1e_acl_inheritance_file(dvp, tvp, mode,
+ cnp->cn_cred, cnp->cn_thread);
+ if (error)
+ goto bad;
+ }
+
error = ext2_direnter(ip, dvp, cnp);
if (error)
goto bad;
Index: head/sys/modules/ext2fs/Makefile
===================================================================
--- head/sys/modules/ext2fs/Makefile
+++ head/sys/modules/ext2fs/Makefile
@@ -3,8 +3,8 @@
.PATH: ${SRCTOP}/sys/fs/ext2fs
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_extattr.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_acl.c ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_extattr.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
.include <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 15, 4:35 PM (4 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29723639
Default Alt Text
D10807.id.diff (35 KB)
Attached To
Mode
D10807: ext2fs: Add posix ACLs support
Attached
Detach File
Event Timeline
Log In to Comment