s3:vfs_gpfs add a generic vfs_gpfs_getacl function
authorChristian Ambach <ambi@samba.org>
Mon, 5 Nov 2012 18:26:57 +0000 (19:26 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 4 Feb 2013 11:19:30 +0000 (12:19 +0100)
in contrast to gpfs_getacl_alloc which always puts the
ACL on talloc_tos(), this one allows to specify the memory
context and if the caller is interested in the raw ACL blob
or a structured version

Signed-off-by: Christian Ambach <ambi@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/modules/vfs_gpfs.c

index e2058e18323d6864929a57db10804cc677e58ba2..c0d6fb204611343123e561085ad548ed34ea092b 100644 (file)
@@ -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;