NFSv4: Add support for open(O_CREAT)

Add support for O_CREAT for NFSv4. Note, it is not implemented for NFSv3.
While it creates files we still need to add plumbing to get umask
implemented or else all files created will have mode 0.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
libnfs-4.0.0-vitalif
Ronnie Sahlberg 2017-08-06 18:43:28 +10:00
parent 0ce4917afd
commit 65a0110476
4 changed files with 84 additions and 5 deletions

View File

@ -511,7 +511,8 @@ EXTERN uint16_t nfs_umask(struct nfs_context *nfs, uint16_t mask);
* Async open(<filename>)
*
* mode is a combination of the flags :
* O_RDONLY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND, O_TRUNC, O_NOFOLLOW
* O_RDONLY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND, O_TRUNC, O_NOFOLLOW,
* O_CREAT
*
* Function returns
* 0 : The command was queued successfully. The callback will be invoked once
@ -522,6 +523,7 @@ EXTERN uint16_t nfs_umask(struct nfs_context *nfs, uint16_t mask);
* Supported flags are
* O_NOFOLLOW
* O_APPEND
* O_CREAT (Only NFSv4)
* O_RDONLY
* O_WRONLY
* O_RDWR

View File

@ -125,6 +125,11 @@ struct lookup_filler {
void *val;
blob_free free;
} blob1;
struct {
int len;
void *val;
blob_free free;
} blob2;
};
struct rw_data {
@ -168,6 +173,9 @@ free_nfs4_cb_data(struct nfs4_cb_data *data)
if (data->filler.blob1.val && data->filler.blob1.free) {
data->filler.blob1.free(data->filler.blob1.val);
}
if (data->filler.blob2.val && data->filler.blob2.free) {
data->filler.blob2.free(data->filler.blob2.val);
}
free(data);
}
@ -1486,8 +1494,6 @@ nfs4_open_confirm_cb(struct rpc_context *rpc, int status, void *command_data,
free_nfs4_cb_data(data);
}
/* Stores nfsfh in data.blob0.
*/
static void
nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data,
void *private_data)
@ -1764,7 +1770,23 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
oargs->owner.clientid = nfs->clientid;
oargs->owner.owner.owner_len = strlen(nfs->client_name);
oargs->owner.owner.owner_val = nfs->client_name;
oargs->openhow.opentype = OPEN4_NOCREATE;
if (data->filler.flags & O_CREAT) {
createhow4 *ch;
fattr4 *fa;
ch = &oargs->openhow.openflag4_u.how;
fa = &ch->createhow4_u.createattrs;
oargs->openhow.opentype = OPEN4_CREATE;
ch->mode = UNCHECKED4;
fa->attrmask.bitmap4_len = data->filler.blob1.len;
fa->attrmask.bitmap4_val = data->filler.blob1.val;
fa->attr_vals.attrlist4_len = data->filler.blob2.len;
fa->attr_vals.attrlist4_val = data->filler.blob2.val;
} else {
oargs->openhow.opentype = OPEN4_NOCREATE;
}
oargs->claim.claim = CLAIM_NULL;
oargs->claim.open_claim4_u.file.utf8string_len =
strlen(data->filler.data);
@ -1777,7 +1799,11 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
return 3;
}
/* TODO add the plumbing for mode */
/*
* data.blob0 is used for nfsfh
* data.blob1 is used for the attribute mask in case on O_CREAT
* data.blob2 is the attribute value in case of O_CREAT
*/
int
nfs4_open_async(struct nfs_context *nfs, const char *orig_path, int flags,
int mode, nfs_cb cb, void *private_data)
@ -1813,6 +1839,38 @@ nfs4_open_async(struct nfs_context *nfs, const char *orig_path, int flags,
return -1;
}
if (flags & O_CREAT) {
uint32_t *d;
/* Attribute mask */
d = malloc(2 * sizeof(uint32_t));
if (d == NULL) {
nfs_set_error(nfs, "Out of memory");
free_nfs4_cb_data(data);
return -1;
}
d[0] = 0;
d[1] = 1 << (FATTR4_MODE - 32);
data->filler.blob1.val = d;
data->filler.blob1.len = 2;
data->filler.blob1.free = free;
/* Attribute value */
d = malloc(sizeof(uint32_t));
if (d == NULL) {
nfs_set_error(nfs, "Out of memory");
free_nfs4_cb_data(data);
return -1;
}
*d = mode;
data->filler.blob2.val = d;
data->filler.blob2.len = 4;
data->filler.blob2.free = free;
}
path = strrchr(data->path, '/');
if (path == data->path) {
char *ptr;

View File

@ -68,6 +68,9 @@ int main(int argc, char *argv[])
if (strstr(argv[4], "O_TRUNC")) {
flags |= O_TRUNC;
}
if (strstr(argv[4], "O_CREAT")) {
flags |= O_CREAT;
}
nfs = nfs_init_context();
if (nfs == NULL) {

16
tests/test_0225_open_O_CREAT.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
. ./functions.sh
echo "NFSv${VERS} Open(O_CREAT) test."
start_share
echo -n "test open(O_RDWR|O_CREAT) (1) ... "
./prog_open_write "${TESTURL}/?version=${VERS}" "." /open1 O_WRONLY,O_CREAT "LordOfCinder" >/dev/null || failure
success
stop_share
exit 0