static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) { char *ea_name; struct jfs_inode_info *ji = JFS_IP(inode); struct posix_acl **p_acl; int rc; int size = 0; char *value = NULL; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; switch(type) { case ACL_TYPE_ACCESS: ea_name = XATTR_NAME_ACL_ACCESS; p_acl = &ji->i_acl; break; case ACL_TYPE_DEFAULT: ea_name = XATTR_NAME_ACL_DEFAULT; p_acl = &ji->i_default_acl; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { size = xattr_acl_size(acl->a_count); value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; rc = posix_acl_to_xattr(acl, value, size); if (rc < 0) goto out; } rc = __jfs_setxattr(inode, ea_name, value, size, 0); out: if (value) kfree(value); if (!rc) { if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) posix_acl_release(*p_acl); *p_acl = posix_acl_dup(acl); } return rc; }
/* * Convert from in-memory to extended attribute representation. */ int posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size) { xattr_acl_header *ext_acl = (xattr_acl_header *)buffer; xattr_acl_entry *ext_entry = ext_acl->a_entries; int real_size, n; real_size = xattr_acl_size(acl->a_count); if (!buffer) return real_size; if (real_size > size) return -ERANGE; ext_acl->a_version = cpu_to_le32(XATTR_ACL_VERSION); for (n=0; n < acl->a_count; n++, ext_entry++) { ext_entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); ext_entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); ext_entry->e_id = cpu_to_le32(acl->a_entries[n].e_id); } return real_size; }