diff options
-rw-r--r-- | source3/modules/vfs_gpfs.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index e2058e1832..c0d6fb2046 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -219,6 +219,79 @@ static void gpfs_dumpacl(int level, struct gpfs_acl *gacl) } } +/* + * get the ACL from GPFS, allocated on the specified mem_ctx + * internally retries when initial buffer was too small + * + * caller needs to cast result to either + * raw = yes: struct gpfs_opaque_acl + * raw = no: struct gpfs_acl + * + */ +static void *vfs_gpfs_getacl(TALLOC_CTX *mem_ctx, + const char *fname, + const bool raw, + const gpfs_aclType_t type) +{ + + void *aclbuf; + size_t size = 512; + int ret, flags; + unsigned int *len; + size_t struct_size; + +again: + + aclbuf = talloc_zero_size(mem_ctx, size); + if (aclbuf == NULL) { + errno = ENOMEM; + return NULL; + } + + if (raw) { + struct gpfs_opaque_acl *buf = (struct gpfs_opaque_acl *) aclbuf; + buf->acl_type = type; + flags = GPFS_GETACL_NATIVE; + len = (unsigned int *) &(buf->acl_buffer_len); + struct_size = sizeof(struct gpfs_opaque_acl); + } else { + struct gpfs_acl *buf = (struct gpfs_acl *) aclbuf; + buf->acl_type = type; + flags = GPFS_GETACL_STRUCT; + len = &(buf->acl_len); + struct_size = sizeof(struct gpfs_acl); + } + + /* set the length of the buffer as input value */ + *len = size; + + errno = 0; + ret = smbd_gpfs_getacl((char *)fname, flags, aclbuf); + if ((ret != 0) && (errno == ENOSPC)) { + /* + * get the size needed to accommodate the complete buffer + * + * the value returned only applies to the ACL blob in the + * struct so make sure to also have headroom for the first + * struct members by adding room for the complete struct + * (might be a few bytes too much then) + */ + size = *len + struct_size; + talloc_free(aclbuf); + DEBUG(10, ("Increasing ACL buffer size to %zu\n", size)); + goto again; + } + + if (ret != 0) { + DEBUG(5, ("smbd_gpfs_getacl failed with %s\n", + strerror(errno))); + talloc_free(aclbuf); + return NULL; + } + + return aclbuf; +} + static struct gpfs_acl *gpfs_getacl_alloc(const char *fname, gpfs_aclType_t type) { struct gpfs_acl *acl; |