acl: add support and helpers to read nfsv4 acls

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
master
Ronnie Sahlberg 2021-07-17 20:08:43 +10:00
parent 1cdc8657de
commit cdb377532a
10 changed files with 295 additions and 4 deletions

View File

@ -55,6 +55,7 @@ WSADATA wsaData;
#include "../include/nfsc/libnfs.h"
#include "../include/nfsc/libnfs-raw.h"
#include "../mount/libnfs-raw-mount.h"
#include "../nfs4/libnfs-raw-nfs4.h"
void print_usage(void)
{
@ -67,6 +68,8 @@ int main(int argc, char *argv[])
struct nfs_context *nfs = NULL;
struct nfsfh *nfsfh = NULL;
struct nfs_url *url = NULL;
fattr4_acl acl4;
int i;
#ifdef WIN32
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
@ -179,6 +182,32 @@ int main(int argc, char *argv[])
printf(" mtime: %lu %lu", st.nfs_mtime, st.nfs_mtime_nsec);
printf("\n");
}
} else if (!strncmp(argv[1], "acl", 3)) {
printf("ACL version:%d\n", nfs_get_version(nfs));
if (nfs_get_version(nfs) != NFS_V4) {
printf("acl support only for nfsv4 for now\n");
goto finished;
}
/* NFS_V4 */
ret = nfs_open(nfs, url->file, 0600, &nfsfh);
if (ret != 0) {
printf("failed to open %s\n", url->file);
goto finished;
}
if (nfs4_getacl(nfs, nfsfh, &acl4)) {
printf("Failed to read ACLs %s\n", nfs_get_error(nfs));
goto finished;
}
for (i = 0; i < acl4.fattr4_acl_len; i++) {
printf("Type:%d Flag:%d Mask:0x%08x Who:%s\n",
acl4.fattr4_acl_val[i].type,
acl4.fattr4_acl_val[i].flag,
acl4.fattr4_acl_val[i].access_mask,
acl4.fattr4_acl_val[i].who.utf8string_val);
}
nfs4_acl_free(&acl4);
ret = 0;
} else {
goto finished;
}

View File

@ -275,6 +275,12 @@ EXTERN void nfs_set_autoreconnect(struct nfs_context *nfs, int num_retries);
* NFS_V4
*/
EXTERN int nfs_set_version(struct nfs_context *nfs, int version);
/*
* Get NFS version of a connected share. Supported versions are
* NFS_V3
* NFS_V4
*/
EXTERN int nfs_get_version(struct nfs_context *nfs);
/*
* Invalidate the pagecache

View File

@ -100,6 +100,7 @@
#include "libnfs-raw.h"
#include "libnfs-raw-mount.h"
#include "libnfs-raw-nfs.h"
#include "libnfs-raw-nfs4.h"
#include "libnfs-private.h"
struct sync_cb_data {
@ -1850,6 +1851,81 @@ nfs_link(struct nfs_context *nfs, const char *oldpath, const char *newpath)
return cb_data.status;
}
/*
* nfs4_getacl()
*/
void nfs4_acl_free(fattr4_acl *acl)
{
int i;
for (i = 0; i < acl->fattr4_acl_len; i++) {
free(acl->fattr4_acl_val[i].who.utf8string_val);
}
free(acl->fattr4_acl_val);
}
static void
nfs4_getacl_cb(int status, struct nfs_context *nfs, void *data, void *private_data)
{
struct sync_cb_data *cb_data = private_data;
fattr4_acl *src = data;
fattr4_acl *dst = cb_data->return_data;
int i;
cb_data->is_finished = 1;
cb_data->status = status;
if (status < 0) {
nfs_set_error(nfs, "getacl call failed with \"%s\"",
(char *)data);
return;
}
dst->fattr4_acl_len = src->fattr4_acl_len;
dst->fattr4_acl_val = calloc(dst->fattr4_acl_len, sizeof(nfsace4));
if (dst->fattr4_acl_val == NULL) {
cb_data->status = -ENOMEM;
nfs_set_error(nfs, "Failed to allocate fattr4_acl_val");
return;
}
for (i = 0; i < dst->fattr4_acl_len; i++) {
dst->fattr4_acl_val[i].type = src->fattr4_acl_val[i].type;
dst->fattr4_acl_val[i].flag = src->fattr4_acl_val[i].flag;
dst->fattr4_acl_val[i].access_mask = src->fattr4_acl_val[i].access_mask;
dst->fattr4_acl_val[i].who.utf8string_len = src->fattr4_acl_val[i].who.utf8string_len;
dst->fattr4_acl_val[i].who.utf8string_val = calloc(dst->fattr4_acl_val[i].who.utf8string_len + 1, 1);
if (dst->fattr4_acl_val[i].who.utf8string_val == NULL) {
cb_data->status = -ENOMEM;
nfs4_acl_free(dst);
nfs_set_error(nfs, "Failed to allocate acl name");
return;
}
memcpy(dst->fattr4_acl_val[i].who.utf8string_val,
src->fattr4_acl_val[i].who.utf8string_val,
dst->fattr4_acl_val[i].who.utf8string_len);
}
}
int
nfs4_getacl(struct nfs_context *nfs, struct nfsfh *nfsfh,
fattr4_acl *acl)
{
struct sync_cb_data cb_data;
cb_data.is_finished = 0;
cb_data.return_data = acl;
if (nfs4_getacl_async(nfs, nfsfh, nfs4_getacl_cb, &cb_data) != 0) {
nfs_set_error(nfs, "nfs_getacl_async failed. %s",
nfs_get_error(nfs));
return -1;
}
wait_for_nfs_reply(nfs, &cb_data);
return cb_data.status;
}
void
mount_getexports_cb(struct rpc_context *mount_context, int status, void *data,
void *private_data)

View File

@ -35,6 +35,7 @@ nfs_get_fd
nfs_get_readmax
nfs_get_writemax
nfs_getcwd
nfs_get_version
nfs_get_timeout
nfs_init_context
nfs_link
@ -118,6 +119,9 @@ nfsstat4_to_errno
nfsstat4_to_str
nfs4_set_client_name
nfs4_set_verifier
nfs4_acl_free
nfs4_getacl
nfs4_getacl_async
win32_poll
rpc_connect_async
rpc_connect_port_async

View File

@ -1848,6 +1848,11 @@ nfs_set_version(struct nfs_context *nfs, int version) {
return 0;
}
int
nfs_get_version(struct nfs_context *nfs) {
return nfs->version;
}
void
nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
{

View File

@ -99,6 +99,7 @@
#include "slist.h"
#include "libnfs.h"
#include "libnfs-raw.h"
#include "libnfs-raw-nfs4.h"
#include "libnfs-private.h"
#ifndef discard_const
@ -193,6 +194,10 @@ static uint32_t statvfs_attributes[2] = {
1 << (FATTR4_SPACE_TOTAL - 32))
};
static uint32_t getacl_attributes[1] = {
(1 << FATTR4_ACL )
};
static int
nfs4_open_async_internal(struct nfs_context *nfs, struct nfs4_cb_data *data,
int flags, int mode);
@ -2530,6 +2535,86 @@ nfs4_fstat64_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
return 0;
}
static void
nfs4_getacl_cb(struct rpc_context *rpc, int status, void *command_data,
void *private_data)
{
struct nfs4_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
COMPOUND4res *res = command_data;
GETATTR4resok *garesok;
fattr4_acl acl;
ZDR zdr;
int i;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (check_nfs4_error(nfs, status, data, res, "GETACL")) {
data->cb(-EIO, nfs, "GETACL failed", data->private_data);
free_nfs4_cb_data(data);
return;
}
if ((i = nfs4_find_op(nfs, data, res, OP_GETATTR, "GETATTR")) < 0) {
data->cb(-EIO, nfs, "GETACL failed", data->private_data);
free_nfs4_cb_data(data);
return;
}
garesok = &res->resarray.resarray_val[i].nfs_resop4_u.opgetattr.GETATTR4res_u.resok4;
memset(&acl, 0, sizeof(acl));
zdrmem_create(&zdr,
garesok->obj_attributes.attr_vals.attrlist4_val,
garesok->obj_attributes.attr_vals.attrlist4_len,
ZDR_DECODE);
if (zdr_fattr4_acl(&zdr, &acl)) {
data->cb(0, nfs, &acl, data->private_data);
} else {
data->cb(-EIO, nfs, "Failed to unmarshall fattr4_acl", data->private_data);
}
zdr_destroy(&zdr);
free_nfs4_cb_data(data);
}
int
nfs4_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb,
void *private_data)
{
COMPOUND4args args;
nfs_argop4 op[2];
struct nfs4_cb_data *data;
int i;
data = malloc(sizeof(*data));
if (data == NULL) {
nfs_set_error(nfs, "Out of memory. Failed to allocate "
"cb data");
return -1;
}
memset(data, 0, sizeof(*data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
i = nfs4_op_putfh(nfs, &op[0], nfsfh);
i += nfs4_op_getattr(nfs, &op[i], getacl_attributes, 1);
memset(&args, 0, sizeof(args));
args.argarray.argarray_len = i;
args.argarray.argarray_val = op;
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_getacl_cb, &args,
data) != 0) {
free_nfs4_cb_data(data);
return -1;
}
return 0;
}
static void
nfs4_close_cb(struct rpc_context *rpc, int status, void *command_data,
void *private_data)

View File

@ -2754,3 +2754,46 @@ extern uint32_t zdr_CB_COMPOUND4res ();
#endif
#endif /* !_NFS4_H_RPCGEN */
#include <nfsc/libnfs.h>
#if defined(WIN32) && defined(libnfs_EXPORTS)
#define EXTERN __declspec( dllexport )
#else
#ifndef EXTERN
#define EXTERN
#endif
#endif
/*
* NFSv4 ACL
*/
/*
* Async nfs4 get acl
* Function returns
* 0 : The command was queued successfully. The callback will be invoked once
* the command completes.
* <0 : An error occured when trying to queue the command.
* The callback will not be invoked.
*
* When the callback is invoked, status indicates the result:
* 0 : Success.
* data is fattr4_acl *
* -errno : An error occured.
* data is the error string.
*/
EXTERN int nfs4_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
nfs_cb cb, void *private_data);
/*
* Sync nfs4 get acl
* Function returns
* 0 : The operation was successful.
* -errno : The command failed.
*
* If the command was successful, the returned data in nfs4acl must be freed
* by calling nfs4_acl_free()
*/
EXTERN int nfs4_getacl(struct nfs_context *nfs, struct nfsfh *nfsfh,
fattr4_acl *nfs4acl);
EXTERN void nfs4_acl_free(fattr4_acl *nfs4acl);

View File

@ -0,0 +1,43 @@
#include <nfsc/libnfs.h>
#if defined(WIN32) && defined(libnfs_EXPORTS)
#define EXTERN __declspec( dllexport )
#else
#ifndef EXTERN
#define EXTERN
#endif
#endif
/*
* NFSv4 ACL
*/
/*
* Async nfs4 get acl
* Function returns
* 0 : The command was queued successfully. The callback will be invoked once
* the command completes.
* <0 : An error occured when trying to queue the command.
* The callback will not be invoked.
*
* When the callback is invoked, status indicates the result:
* 0 : Success.
* data is fattr4_acl *
* -errno : An error occured.
* data is the error string.
*/
EXTERN int nfs4_getacl_async(struct nfs_context *nfs, struct nfsfh *nfsfh,
nfs_cb cb, void *private_data);
/*
* Sync nfs4 get acl
* Function returns
* 0 : The operation was successful.
* -errno : The command failed.
*
* If the command was successful, the returned data in nfs4acl must be freed
* by calling nfs4_acl_free()
*/
EXTERN int nfs4_getacl(struct nfs_context *nfs, struct nfsfh *nfsfh,
fattr4_acl *nfs4acl);
EXTERN void nfs4_acl_free(fattr4_acl *nfs4acl);

View File

@ -1,7 +1,7 @@
set(UTILITIES nfs-cat nfs-ls nfs-stat)
set(UTILITIES nfs-cat nfs-ls)
if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
list(APPEND UTILITIES nfs-cp)
list(APPEND UTILITIES nfs-cp nfs-stat)
endif()
foreach(TARGET ${UTILITIES})

View File

@ -1,7 +1,7 @@
bin_PROGRAMS = nfs-cat nfs-ls nfs-stat
bin_PROGRAMS = nfs-cat nfs-ls
if !HAVE_WIN32
bin_PROGRAMS += nfs-cp
bin_PROGRAMS += nfs-cp nfs-stat
endif
AM_CPPFLAGS = \