root/usr/src/uts/common/sys/fs/ufs_acl.h
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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 (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _SYS_FS_UFS_ACL_H
#define _SYS_FS_UFS_ACL_H

#include <sys/types.h>
#include <sys/cred.h>
#include <sys/vfs.h>
#include <sys/acl.h>
#include <sys/fs/ufs_fs.h>

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * On-disk UFS ACL structure
 */

typedef struct ufs_acl {
        union {
                uint32_t        acl_next;       /* Pad for old structure */
                ushort_t        acl_tag;        /* Entry type */
        } acl_un;
        o_mode_t        acl_perm;               /* Permission bits */
        uid_t           acl_who;                /* User or group ID */
} ufs_acl_t;

#define acl_tag acl_un.acl_tag
#define acl_next acl_un.acl_next

/*
 * In-core UFS ACL structure
 */

typedef struct ufs_ic_acl {
        struct ufs_ic_acl       *acl_ic_next;   /* Next ACL for this inode */
        o_mode_t                acl_ic_perm;    /* Permission bits */
        uid_t                   acl_ic_who;     /* User or group ID */
} ufs_ic_acl_t;

/*
 * In-core ACL mask
 */
typedef struct ufs_aclmask {
        short           acl_ismask;     /* Is mask defined? */
        o_mode_t        acl_maskbits;   /* Permission mask */
} ufs_aclmask_t;

/*
 * full acl
 */
typedef struct ic_acl {
        ufs_ic_acl_t    *owner;         /* owner object */
        ufs_ic_acl_t    *group;         /* group object */
        ufs_ic_acl_t    *other;         /* other object */
        ufs_ic_acl_t    *users;         /* list of users */
        ufs_ic_acl_t    *groups;        /* list of groups */
        ufs_aclmask_t   mask;           /* mask */
} ic_acl_t;

/*
 * In-core shadow inode
 */
typedef struct si {
        struct si *s_next;              /* signature hash next */
        struct si *s_forw;              /* inode hash next */
        struct si *s_fore;              /* unref'd list next */

        int     s_flags;                /* see below */
        ino_t   s_shadow;               /* shadow inode number */
        dev_t   s_dev;                  /* device (major,minor) */
        int     s_signature;            /* signature for all ACLs */
        int     s_use;                  /* on disk use count */
        int     s_ref;                  /* in core reference count */
        krwlock_t s_lock;               /* lock for this structure */

        ic_acl_t  s_a;                  /* acls */
        ic_acl_t  s_d;                  /* def acls */
} si_t;

#define aowner  s_a.owner
#define agroup  s_a.group
#define aother  s_a.other
#define ausers  s_a.users
#define agroups s_a.groups
#define aclass  s_a.mask

#define downer  s_d.owner
#define dgroup  s_d.group
#define dother  s_d.other
#define dusers  s_d.users
#define dgroups s_d.groups
#define dclass  s_d.mask

#define s_prev  s_forw

/*
 * s_flags
 */
#define SI_CACHED 0x0001                /* Is in si_cache */

/*
 * Header to identify data on disk
 */
typedef struct ufs_fsd {
        int     fsd_type;               /* type of data */
        int     fsd_size;               /* size in bytes of ufs_fsd and data */
        char    fsd_data[1];            /* data */
} ufs_fsd_t;

/*
 * Data types  (fsd_type)
 */
#define FSD_FREE        (0)             /* Free entry */
#define FSD_ACL         (1)             /* Access Control Lists */
#define FSD_DFACL       (2)             /* reserved for future use */
#define FSD_RESERVED3   (3)             /* reserved for future use */
#define FSD_RESERVED4   (4)             /* reserved for future use */
#define FSD_RESERVED5   (5)             /* reserved for future use */
#define FSD_RESERVED6   (6)             /* reserved for future use */
#define FSD_RESERVED7   (7)             /* reserved for future use */

/*
 * FSD manipulation macros
 * The FSD macros are aligned on integer boundary even if the preceeding
 * record had a byte aligned length. So the record length is always
 * integer length. All increments of the data pointers must use the
 * FSD_RECSZ macro.
 */
#define FSD_TPSZ(fsdp)          (sizeof (fsdp->fsd_type))
#define FSD_TPMSK(fsdp)         (FSD_TPSZ(fsdp) - 1)
#define FSD_RECSZ(fsdp, size)   ((size + FSD_TPMSK(fsdp)) & ~FSD_TPMSK(fsdp))
/*
 * flags for acl_validate
 */
#define ACL_CHECK       0x01
#define DEF_ACL_CHECK   0x02

#define MODE_CHECK(O, M, PERM, C, I) \
    secpolicy_vnode_access2(C, ITOV(I), O, (PERM), M)

/*
 * Check that the file type is one that accepts ACLs
 */
#define CHECK_ACL_ALLOWED(MODE) (((MODE) == IFDIR) || ((MODE) == IFREG) || \
                                ((MODE) == IFIFO) || ((MODE) == IFCHR) || \
                                ((MODE) == IFBLK) || ((MODE) == IFATTRDIR))

/*
 * Get ACL group permissions if the mask is not present, and the ACL
 * group permission intersected with the mask if the mask is present
 */
#define MASK2MODE(ACL)                                                  \
        ((ACL)->aclass.acl_ismask ?                                     \
                ((((ACL)->aclass.acl_maskbits &                         \
                        (ACL)->agroup->acl_ic_perm) & 07) << 3) :       \
                (((ACL)->agroup->acl_ic_perm & 07) << 3))

#define MODE2ACL(P, MODE, CRED)                                 \
        ASSERT((P));                                            \
        (P)->acl_ic_next = NULL;                                \
        (P)->acl_ic_perm &= ((MODE) & 7);                       \
        (P)->acl_ic_who = (CRED);

#define ACL_MOVE(P, T, B)                                       \
{                                                               \
        ufs_ic_acl_t *acl;                                      \
        for (acl = (P); acl; acl = acl->acl_ic_next) {          \
                (B)->acl_tag = (T);                             \
                (B)->acl_perm = acl->acl_ic_perm;               \
                (B)->acl_who = acl->acl_ic_who;                 \
                (B)++;                                          \
        }                                                       \
}

#ifdef  __cplusplus
}
#endif

#endif  /* _SYS_FS_UFS_ACL_H */