From: Ronnie Sahlberg Date: Sun, 20 Jul 2014 18:13:04 +0000 (-0700) Subject: Merge pull request #89 from rosslagerwall/create-trunc X-Git-Tag: upstream/1.9.6^2~17 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=0672f75b57b9e0fbf56079944fde5b2fc9de27be;hp=8dea7c3e2dce362f7a49a2193881a3e291f2fdbe;p=deb_libnfs.git Merge pull request #89 from rosslagerwall/create-trunc Support use of O_TRUNC with nfs_create --- diff --git a/include/nfsc/libnfs.h b/include/nfsc/libnfs.h index ff0d4e4..d3ce1aa 100644 --- a/include/nfsc/libnfs.h +++ b/include/nfsc/libnfs.h @@ -330,7 +330,7 @@ EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat * * Async open() * * mode is a combination of the flags : - * O_RDOLNY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND + * O_RDOLNY, O_WRONLY, O_RDWR , O_SYNC, O_APPEND, O_TRUNC * * Function returns * 0 : The operation was initiated. Once the operation finishes, the callback will be invoked. @@ -341,6 +341,7 @@ EXTERN int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh, struct stat * * O_RDONLY * O_WRONLY * O_RDWR + * O_SYNC * O_TRUNC (Only valid with O_RDWR or O_WRONLY. Ignored otherwise.) * * When the callback is invoked, status indicates the result: @@ -689,6 +690,7 @@ EXTERN int nfs_creat(struct nfs_context *nfs, const char *path, int mode, struct * O_APPEND * O_SYNC * O_EXCL + * O_TRUNC * * Function returns * 0 : The operation was initiated. Once the operation finishes, the callback will be invoked. diff --git a/lib/libnfs.c b/lib/libnfs.c index 459ebd7..a134a2c 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -696,6 +696,16 @@ static void free_nfs_cb_data(struct nfs_cb_data *data) free(data); } +static void free_nfsfh(struct nfsfh *nfsfh) +{ + if (nfsfh->fh.data.data_val != NULL) { + free(nfsfh->fh.data.data_val); + nfsfh->fh.data.data_val = NULL; + } + free(nfsfh->ra.buf); + free(nfsfh); +} + static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { @@ -2135,13 +2145,7 @@ int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { - if (nfsfh->fh.data.data_val != NULL){ - free(nfsfh->fh.data.data_val); - nfsfh->fh.data.data_val = NULL; - } - free(nfsfh->ra.buf); - free(nfsfh); - + free_nfsfh(nfsfh); cb(0, nfs, NULL, private_data); return 0; }; @@ -2541,6 +2545,41 @@ static void free_create_cb_data(void *ptr) free(data); } +static void nfs_create_trunc_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + struct nfsfh *nfsfh; + SETATTR3res *res; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { + data->cb(-EFAULT, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + free_nfsfh(nfsfh); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + free_nfs_cb_data(data); + free_nfsfh(nfsfh); + return; + } + + res = command_data; + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); + data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + free_nfsfh(nfsfh); + return; + } + + data->cb(0, nfs, data->nfsfh, data->private_data); + free_nfs_cb_data(data); +} + static void nfs_create_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { LOOKUP3res *res; @@ -2591,8 +2630,39 @@ static void nfs_create_2_cb(struct rpc_context *rpc, int status, void *command_d /* copy the filehandle */ nfsfh->fh.data.data_len = res->LOOKUP3res_u.resok.object.data.data_len; nfsfh->fh.data.data_val = malloc(nfsfh->fh.data.data_len); + if (nfsfh->fh.data.data_val == NULL) { + rpc_set_error(nfs->rpc, "Out of memory: Failed to allocate fh structure"); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + free(nfsfh); + return -1; + } memcpy(nfsfh->fh.data.data_val, res->LOOKUP3res_u.resok.object.data.data_val, nfsfh->fh.data.data_len); + /* Try to truncate it if we were requested to */ + if (cb_data->flags & O_TRUNC) { + SETATTR3args args; + + data->nfsfh = nfsfh; + + memset(&args, 0, sizeof(SETATTR3args)); + args.object = nfsfh->fh; + args.new_attributes.size.set_it = 1; + args.new_attributes.size.set_size3_u.size = 0; + + if (rpc_nfs3_setattr_async(nfs->rpc, nfs_create_trunc_cb, + &args, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send " + "SETATTR call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), + data->private_data); + free_nfs_cb_data(data); + free_nfsfh(nfsfh); + return; + } + return; + } + data->cb(0, nfs, nfsfh, data->private_data); free_nfs_cb_data(data); }