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
parent
0ce4917afd
commit
65a0110476
|
@ -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
|
||||
|
|
66
lib/nfs_v4.c
66
lib/nfs_v4.c
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue