Implement O_EXCL for NFSv4
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>libnfs-4.0.0-vitalif
parent
273182748d
commit
9454d9f4c1
90
lib/nfs_v4.c
90
lib/nfs_v4.c
|
@ -1963,6 +1963,37 @@ nfs4_open_truncate_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nfs4_open_chmod_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;
|
||||
struct nfsfh *fh = data->filler.blob0.val;
|
||||
COMPOUND4res *res = command_data;
|
||||
COMPOUND4args args;
|
||||
nfs_argop4 op[2];
|
||||
int i;
|
||||
|
||||
if (check_nfs4_error(nfs, status, data, res, "OPEN")) {
|
||||
return;
|
||||
}
|
||||
|
||||
i = nfs4_op_putfh(nfs, op, fh);
|
||||
i += nfs4_op_chmod(nfs, &op[i], fh, data->filler.blob3.val);
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
args.argarray.argarray_len = i;
|
||||
args.argarray.argarray_val = op;
|
||||
|
||||
if (rpc_nfs4_compound_async(nfs->rpc, nfs4_open_setattr_cb, &args,
|
||||
data) != 0) {
|
||||
data->cb(-ENOMEM, nfs, nfs_get_error(nfs), data->private_data);
|
||||
free_nfs4_cb_data(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nfs4_open_confirm_cb(struct rpc_context *rpc, int status, void *command_data,
|
||||
void *private_data)
|
||||
|
@ -2118,6 +2149,25 @@ nfs4_open_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
free_nfs4_cb_data(data);
|
||||
}
|
||||
|
||||
static void
|
||||
nfs4_init_random_verifier(char *verifier)
|
||||
{
|
||||
static uint64_t seed = 0, v;
|
||||
int i;
|
||||
|
||||
if (seed == 0) {
|
||||
seed = ~rpc_current_time() << 32 | getpid();
|
||||
} else {
|
||||
seed *= 1337;
|
||||
}
|
||||
|
||||
v = seed;
|
||||
for (i = 0; i < NFS4_VERIFIER_SIZE; i++) {
|
||||
verifier[i] = v & 0xff;
|
||||
v >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* filler.flags are the open flags
|
||||
* filler.data is the object name
|
||||
*/
|
||||
|
@ -2127,6 +2177,7 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
struct nfs_context *nfs = data->nfs;
|
||||
OPEN4args *oargs;
|
||||
uint32_t access_mask = 0;
|
||||
verifier4 verifier;
|
||||
int i;
|
||||
|
||||
if (data->filler.flags & O_WRONLY) {
|
||||
|
@ -2135,7 +2186,7 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
if (data->filler.flags & O_RDWR) {
|
||||
access_mask |= ACCESS4_READ|ACCESS4_MODIFY;
|
||||
}
|
||||
if (!(data->filler.flags & (O_WRONLY|O_RDWR))) {
|
||||
if (!(data->filler.flags & O_WRONLY)) {
|
||||
access_mask |= ACCESS4_READ;
|
||||
}
|
||||
|
||||
|
@ -2166,12 +2217,20 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
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;
|
||||
if (data->filler.flags|O_EXCL) {
|
||||
ch->mode = EXCLUSIVE4;
|
||||
|
||||
fa->attr_vals.attrlist4_len = data->filler.blob2.len;
|
||||
fa->attr_vals.attrlist4_val = data->filler.blob2.val;
|
||||
nfs4_init_random_verifier(&verifier[0]);
|
||||
memcpy(ch->createhow4_u.createverf, verifier,
|
||||
sizeof(verifier4));
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
@ -2373,6 +2432,7 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
|
|||
int mode, nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
uint32_t m;
|
||||
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
|
@ -2386,6 +2446,10 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
|
|||
if (flags & O_TRUNC && !(flags & (O_RDWR|O_WRONLY))) {
|
||||
flags &= ~O_TRUNC;
|
||||
}
|
||||
/* Successful O_EXCL means the file is 0 size already. */
|
||||
if (flags & O_EXCL) {
|
||||
flags &= ~O_TRUNC;
|
||||
}
|
||||
|
||||
if (flags & O_TRUNC) {
|
||||
data->open_cb = nfs4_open_truncate_cb;
|
||||
|
@ -2400,6 +2464,20 @@ nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
|
|||
|
||||
memset(data->filler.blob3.val, 0, 12);
|
||||
}
|
||||
if (flags & O_EXCL) {
|
||||
data->open_cb = nfs4_open_chmod_cb;
|
||||
|
||||
data->filler.blob3.val = malloc(4);
|
||||
if (data->filler.blob3.val == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
data->filler.blob3.free = free;
|
||||
|
||||
m = htonl(mode);
|
||||
memcpy(data->filler.blob3.val, &m, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return nfs4_open_async_internal(nfs, data, flags, mode);
|
||||
}
|
||||
|
|
|
@ -197,8 +197,9 @@ open_file(const char *url, int flags)
|
|||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (nfs_creat(file_context->nfs, file_context->url->file, 0660,
|
||||
&file_context->nfsfh) != 0) {
|
||||
if (nfs_create(file_context->nfs, file_context->url->file,
|
||||
flags, 0660,
|
||||
&file_context->nfsfh) != 0) {
|
||||
fprintf(stderr, "Failed to creat file %s: %s\n",
|
||||
file_context->url->file,
|
||||
nfs_get_error(file_context->nfs));
|
||||
|
@ -241,7 +242,7 @@ int main(int argc, char *argv[])
|
|||
return 10;
|
||||
}
|
||||
|
||||
dst = open_file(argv[2], O_WRONLY|O_CREAT|O_TRUNC);
|
||||
dst = open_file(argv[2], O_WRONLY|O_CREAT|O_EXCL|O_TRUNC);
|
||||
if (dst == NULL) {
|
||||
fprintf(stderr, "Failed to open %s\n", argv[2]);
|
||||
free_file_context(src);
|
||||
|
|
Loading…
Reference in New Issue