diff options
Diffstat (limited to 'fs/nfs_common/nfsacl.c')
| -rw-r--r-- | fs/nfs_common/nfsacl.c | 70 |
1 files changed, 35 insertions, 35 deletions
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 251e5a1bb1c4..0c2be8c0307d 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c | |||
| @@ -48,43 +48,26 @@ xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem) | |||
| 48 | (struct nfsacl_encode_desc *) desc; | 48 | (struct nfsacl_encode_desc *) desc; |
| 49 | u32 *p = (u32 *) elem; | 49 | u32 *p = (u32 *) elem; |
| 50 | 50 | ||
| 51 | if (nfsacl_desc->count < nfsacl_desc->acl->a_count) { | 51 | struct posix_acl_entry *entry = |
| 52 | struct posix_acl_entry *entry = | 52 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; |
| 53 | &nfsacl_desc->acl->a_entries[nfsacl_desc->count++]; | ||
| 54 | 53 | ||
| 55 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); | 54 | *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag); |
| 56 | switch(entry->e_tag) { | 55 | switch(entry->e_tag) { |
| 57 | case ACL_USER_OBJ: | 56 | case ACL_USER_OBJ: |
| 58 | *p++ = htonl(nfsacl_desc->uid); | 57 | *p++ = htonl(nfsacl_desc->uid); |
| 59 | break; | 58 | break; |
| 60 | case ACL_GROUP_OBJ: | 59 | case ACL_GROUP_OBJ: |
| 61 | *p++ = htonl(nfsacl_desc->gid); | 60 | *p++ = htonl(nfsacl_desc->gid); |
| 62 | break; | 61 | break; |
| 63 | case ACL_USER: | 62 | case ACL_USER: |
| 64 | case ACL_GROUP: | 63 | case ACL_GROUP: |
| 65 | *p++ = htonl(entry->e_id); | 64 | *p++ = htonl(entry->e_id); |
| 66 | break; | 65 | break; |
| 67 | default: /* Solaris depends on that! */ | 66 | default: /* Solaris depends on that! */ |
| 68 | *p++ = 0; | 67 | *p++ = 0; |
| 69 | break; | 68 | break; |
| 70 | } | ||
| 71 | *p++ = htonl(entry->e_perm & S_IRWXO); | ||
| 72 | } else { | ||
| 73 | const struct posix_acl_entry *pa, *pe; | ||
| 74 | int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE; | ||
| 75 | |||
| 76 | FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) { | ||
| 77 | if (pa->e_tag == ACL_GROUP_OBJ) { | ||
| 78 | group_obj_perm = pa->e_perm & S_IRWXO; | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | /* fake up ACL_MASK entry */ | ||
| 83 | *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag); | ||
| 84 | *p++ = htonl(0); | ||
| 85 | *p++ = htonl(group_obj_perm); | ||
| 86 | } | 69 | } |
| 87 | 70 | *p++ = htonl(entry->e_perm & S_IRWXO); | |
| 88 | return 0; | 71 | return 0; |
| 89 | } | 72 | } |
| 90 | 73 | ||
| @@ -105,11 +88,28 @@ nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, | |||
| 105 | .gid = inode->i_gid, | 88 | .gid = inode->i_gid, |
| 106 | }; | 89 | }; |
| 107 | int err; | 90 | int err; |
| 91 | struct posix_acl *acl2 = NULL; | ||
| 108 | 92 | ||
| 109 | if (entries > NFS_ACL_MAX_ENTRIES || | 93 | if (entries > NFS_ACL_MAX_ENTRIES || |
| 110 | xdr_encode_word(buf, base, entries)) | 94 | xdr_encode_word(buf, base, entries)) |
| 111 | return -EINVAL; | 95 | return -EINVAL; |
| 96 | if (encode_entries && acl && acl->a_count == 3) { | ||
| 97 | /* Fake up an ACL_MASK entry. */ | ||
| 98 | acl2 = posix_acl_alloc(4, GFP_KERNEL); | ||
| 99 | if (!acl2) | ||
| 100 | return -ENOMEM; | ||
| 101 | /* Insert entries in canonical order: other orders seem | ||
| 102 | to confuse Solaris VxFS. */ | ||
| 103 | acl2->a_entries[0] = acl->a_entries[0]; /* ACL_USER_OBJ */ | ||
| 104 | acl2->a_entries[1] = acl->a_entries[1]; /* ACL_GROUP_OBJ */ | ||
| 105 | acl2->a_entries[2] = acl->a_entries[1]; /* ACL_MASK */ | ||
| 106 | acl2->a_entries[2].e_tag = ACL_MASK; | ||
| 107 | acl2->a_entries[3] = acl->a_entries[2]; /* ACL_OTHER */ | ||
| 108 | nfsacl_desc.acl = acl2; | ||
| 109 | } | ||
| 112 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); | 110 | err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc); |
| 111 | if (acl2) | ||
| 112 | posix_acl_release(acl2); | ||
| 113 | if (!err) | 113 | if (!err) |
| 114 | err = 8 + nfsacl_desc.desc.elem_size * | 114 | err = 8 + nfsacl_desc.desc.elem_size * |
| 115 | nfsacl_desc.desc.array_len; | 115 | nfsacl_desc.desc.array_len; |
