X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=bb89d4a8c10bb34fd541801af242d7d3704ce1f6;hb=1c1e09ad51aa210cabbcdc0a795aae1ceb8e9495;hp=969721e0330909f45e1906afba418d7b9c057c7e;hpb=a1287496488a3d04e205cb1999e0639768bf5b95;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index 969721e..bb89d4a 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -130,9 +130,12 @@ struct nfs_cb_data { /* for multi-read/write calls. */ int error; int cancel; + int oom; int num_calls; uint64_t start_offset, max_offset; char *buffer; + size_t request_size; + char *usrbuf; }; struct nfs_mcb_data { @@ -524,27 +527,16 @@ int rpc_connect_program_async(struct rpc_context *rpc, char *server, int program return 0; } -void free_nfs_cb_data(struct nfs_cb_data *data) +static void free_nfs_cb_data(struct nfs_cb_data *data) { - if (data->saved_path != NULL) { - free(data->saved_path); - data->saved_path = NULL; - } - if (data->continue_data != NULL) { + assert(data->free_continue_data); data->free_continue_data(data->continue_data); - data->continue_data = NULL; } - if (data->fh.data.data_val != NULL) { - free(data->fh.data.data_val); - data->fh.data.data_val = NULL; - } - - if (data->buffer != NULL) { - free(data->buffer); - data->buffer = NULL; - } + free(data->saved_path); + free(data->fh.data.data_val); + free(data->buffer); free(data); } @@ -1241,6 +1233,84 @@ int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *p } +/* + * Async nfs_stat64() + */ +static void nfs_stat64_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + GETATTR3res *res; + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + struct nfs_stat_64 st; + + 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); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + free_nfs_cb_data(data); + return; + } + + res = command_data; + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: GETATTR of %s failed with %s(%d)", data->saved_path, 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); + return; + } + + st.nfs_dev = -1; + st.nfs_ino = res->GETATTR3res_u.resok.obj_attributes.fileid; + st.nfs_mode = res->GETATTR3res_u.resok.obj_attributes.mode; + if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) { + st.nfs_mode |= S_IFDIR ; + } + if (res->GETATTR3res_u.resok.obj_attributes.type == NF3REG) { + st.nfs_mode |= S_IFREG ; + } + st.nfs_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink; + st.nfs_uid = res->GETATTR3res_u.resok.obj_attributes.uid; + st.nfs_gid = res->GETATTR3res_u.resok.obj_attributes.gid; + st.nfs_rdev = 0; + st.nfs_size = res->GETATTR3res_u.resok.obj_attributes.size; + st.nfs_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds; + st.nfs_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds; + st.nfs_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds; + + data->cb(0, nfs, &st, data->private_data); + free_nfs_cb_data(data); +} + +static int nfs_stat64_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +{ + struct GETATTR3args args; + + memset(&args, 0, sizeof(GETATTR3args)); + args.object = data->fh; + + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat64_1_cb, &args, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } + return 0; +} + +int nfs_stat64_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) +{ + if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_stat64_continue_internal, NULL, NULL, 0) != 0) { + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; + } + + return 0; +} /* * Async open() @@ -1461,36 +1531,12 @@ int nfs_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * /* * Async pread() */ -static void nfs_pread_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +static void nfs_fill_READ3args(READ3args *args, struct nfsfh *fh, uint64_t offset, uint64_t count) { - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - READ3res *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); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - res = command_data; - if (res->status != NFS3_OK) { - rpc_set_error(nfs->rpc, "NFS: Read 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); - return; - } - - data->nfsfh->offset += res->READ3res_u.resok.count; - data->cb(res->READ3res_u.resok.count, nfs, res->READ3res_u.resok.data.data_val, data->private_data); - free_nfs_cb_data(data); + memset(args, 0, sizeof(READ3args)); + args->file = fh->fh; + args->offset = offset; + args->count = count; } static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data) @@ -1513,46 +1559,89 @@ static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_dat data->cancel = 1; } - /* reassemble the data into the buffer */ if (status == RPC_STATUS_SUCCESS) { res = command_data; if (res->status != NFS3_OK) { rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; } else { + /* if we have more than one call or we have received a short read we need a reassembly buffer */ + if (data->num_calls || (res->READ3res_u.resok.count < mdata->count && !res->READ3res_u.resok.eof)) { + if (data->buffer == NULL) { + data->buffer = malloc(data->request_size); + if (data->buffer == NULL) { + rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)data->request_size); + data->oom = 1; + } + } + } if (res->READ3res_u.resok.count > 0) { - memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count); - if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) { - data->max_offset = mdata->offset + res->READ3res_u.resok.count; + if (res->READ3res_u.resok.count <= mdata->count) { + /* copy data into reassembly buffer if we have one */ + if (data->buffer != NULL) { + memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count); + } + if (data->max_offset < mdata->offset + res->READ3res_u.resok.count) { + data->max_offset = mdata->offset + res->READ3res_u.resok.count; + } + } else { + rpc_set_error(nfs->rpc, "NFS: Read overflow. Server has sent more data than requested!"); + data->error = 1; + } + } + /* check if we have received a short read */ + if (res->READ3res_u.resok.count < mdata->count && !res->READ3res_u.resok.eof) { + if (res->READ3res_u.resok.count == 0) { + rpc_set_error(nfs->rpc, "NFS: Read failed. No bytes read and not at EOF!"); + data->error = 1; + } else { + /* reissue reminder of this read request */ + READ3args args; + mdata->offset += res->READ3res_u.resok.count; + mdata->count -= res->READ3res_u.resok.count; + nfs_fill_READ3args(&args, data->nfsfh, mdata->offset, mdata->count); + if (rpc_nfs3_read_async(nfs->rpc, nfs_pread_mcb, &args, mdata) == 0) { + data->num_calls++; + return; + } else { + rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path); + data->oom = 1; + } } } } } + free(mdata); + if (data->num_calls > 0) { /* still waiting for more replies */ - free(mdata); return; } - + if (data->oom != 0) { + data->cb(-ENOMEM, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + return; + } if (data->error != 0) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); - free(mdata); return; } if (data->cancel != 0) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free_nfs_cb_data(data); - free(mdata); return; } data->nfsfh->offset = data->max_offset; - data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data); + if (data->buffer) { + data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data); + } else { + data->cb(res->READ3res_u.resok.count, nfs, res->READ3res_u.resok.data.data_val, data->private_data); + } free_nfs_cb_data(data); - free(mdata); } int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data) @@ -1569,42 +1658,19 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse data->cb = cb; data->private_data = private_data; data->nfsfh = nfsfh; + data->request_size = count; nfsfh->offset = offset; - if (count <= nfs_get_readmax(nfs)) { - READ3args args; - - memset(&args, 0, sizeof(READ3args)); - args.file = nfsfh->fh; - args.offset = offset; - args.count = count; - - if (rpc_nfs3_read_async(nfs->rpc, nfs_pread_cb, &args, data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); - free_nfs_cb_data(data); - return -1; - } - return 0; - } + assert(data->num_calls == 0); - /* trying to read more than maximum server read size, we has to chop it up into smaller - * reads and collect into a reassembly buffer. + /* chop requests into chunks of at most READMAX bytes if necessary. * we send all reads in parallel so that performance is still good. */ data->max_offset = offset; data->start_offset = offset; - data->buffer = malloc(count); - if (data->buffer == NULL) { - rpc_set_error(nfs->rpc, "Out-Of-Memory: Failed to allocate reassembly buffer for %d bytes", (int)count); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); - free_nfs_cb_data(data); - return -1; - } - - while (count > 0) { + do { uint64_t readcount = count; struct nfs_mcb_data *mdata; READ3args args; @@ -1616,29 +1682,35 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse mdata = malloc(sizeof(struct nfs_mcb_data)); if (mdata == NULL) { rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure"); - return -1; + if (data->num_calls == 0) { + free_nfs_cb_data(data); + return -1; + } + data->oom = 1; + break; } memset(mdata, 0, sizeof(struct nfs_mcb_data)); mdata->data = data; mdata->offset = offset; mdata->count = readcount; - memset(&args, 0, sizeof(READ3args)); - args.file = nfsfh->fh; - args.offset = offset; - args.count = readcount; + nfs_fill_READ3args(&args, nfsfh, offset, readcount); if (rpc_nfs3_read_async(nfs->rpc, nfs_pread_mcb, &args, mdata) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send READ call for %s", data->path); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free(mdata); - return -1; + if (data->num_calls == 0) { + free_nfs_cb_data(data); + return -1; + } + data->oom = 1; + break; } count -= readcount; offset += readcount; data->num_calls++; - } + } while (count > 0); return 0; } @@ -1656,36 +1728,16 @@ int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, /* * Async pwrite() */ -static void nfs_pwrite_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +static void nfs_fill_WRITE3args (WRITE3args *args, struct nfsfh *fh, uint64_t offset, uint64_t count, + void *buf) { - struct nfs_cb_data *data = private_data; - struct nfs_context *nfs = data->nfs; - WRITE3res *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); - return; - } - if (status == RPC_STATUS_CANCEL) { - data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); - free_nfs_cb_data(data); - return; - } - - res = command_data; - if (res->status != NFS3_OK) { - rpc_set_error(nfs->rpc, "NFS: Write 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); - return; - } - - data->nfsfh->offset += res->WRITE3res_u.resok.count; - data->cb(res->WRITE3res_u.resok.count, nfs, NULL, data->private_data); - free_nfs_cb_data(data); + memset(args, 0, sizeof(WRITE3args)); + args->file = fh->fh; + args->offset = offset; + args->count = count; + args->stable = fh->is_sync?FILE_SYNC:UNSTABLE; + args->data.data_len = count; + args->data.data_val = buf; } static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data) @@ -1714,30 +1766,53 @@ static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_da rpc_set_error(nfs->rpc, "NFS: Write failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; } else { + if (res->WRITE3res_u.resok.count < mdata->count) { + if (res->WRITE3res_u.resok.count == 0) { + rpc_set_error(nfs->rpc, "NFS: Write failed. No bytes written!"); + data->error = 1; + } else { + /* reissue reminder of this write request */ + WRITE3args args; + mdata->offset += res->WRITE3res_u.resok.count; + mdata->count -= res->WRITE3res_u.resok.count; + nfs_fill_WRITE3args(&args, data->nfsfh, mdata->offset, mdata->count, + &data->usrbuf[mdata->offset - data->start_offset]); + if (rpc_nfs3_write_async(nfs->rpc, nfs_pwrite_mcb, &args, mdata) == 0) { + data->num_calls++; + return; + } else { + rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); + data->oom = 1; + } + } + } if (res->WRITE3res_u.resok.count > 0) { - if ((unsigned)data->max_offset < mdata->offset + res->WRITE3res_u.resok.count) { + if (data->max_offset < mdata->offset + res->WRITE3res_u.resok.count) { data->max_offset = mdata->offset + res->WRITE3res_u.resok.count; } } } } + free(mdata); + if (data->num_calls > 0) { /* still waiting for more replies */ - free(mdata); return; } - + if (data->oom != 0) { + data->cb(-ENOMEM, nfs, command_data, data->private_data); + free_nfs_cb_data(data); + return; + } if (data->error != 0) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); - free(mdata); return; } if (data->cancel != 0) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); free_nfs_cb_data(data); - free(mdata); return; } @@ -1745,7 +1820,6 @@ static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_da data->cb(data->max_offset - data->start_offset, nfs, NULL, data->private_data); free_nfs_cb_data(data); - free(mdata); } @@ -1763,37 +1837,20 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs data->cb = cb; data->private_data = private_data; data->nfsfh = nfsfh; + data->usrbuf = buf; nfsfh->offset = offset; - if (count <= nfs_get_writemax(nfs)) { - WRITE3args args; - - memset(&args, 0, sizeof(WRITE3args)); - args.file = nfsfh->fh; - args.offset = offset; - args.count = count; - args.stable = nfsfh->is_sync?FILE_SYNC:UNSTABLE; - args.data.data_len = count; - args.data.data_val = buf; - - if (rpc_nfs3_write_async(nfs->rpc, nfs_pwrite_cb, &args, data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); - free_nfs_cb_data(data); - return -1; - } - return 0; - } + /* hello, clang-analyzer */ + assert(data->num_calls == 0); - /* trying to write more than maximum server write size, we has to chop it up into smaller - * chunks. + /* chop requests into chunks of at most WRITEMAX bytes if necessary. * we send all writes in parallel so that performance is still good. */ data->max_offset = offset; data->start_offset = offset; - while (count > 0) { + do { uint64_t writecount = count; struct nfs_mcb_data *mdata; WRITE3args args; @@ -1805,32 +1862,35 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs mdata = malloc(sizeof(struct nfs_mcb_data)); if (mdata == NULL) { rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_mcb_data structure"); - return -1; + if (data->num_calls == 0) { + free_nfs_cb_data(data); + return -1; + } + data->oom = 1; + break; } memset(mdata, 0, sizeof(struct nfs_mcb_data)); mdata->data = data; mdata->offset = offset; mdata->count = writecount; - memset(&args, 0, sizeof(WRITE3args)); - args.file = nfsfh->fh; - args.offset = offset; - args.count = writecount; - args.stable = nfsfh->is_sync?FILE_SYNC:UNSTABLE; - args.data.data_len = writecount; - args.data.data_val = &buf[offset - data->start_offset]; + nfs_fill_WRITE3args(&args, nfsfh, offset, writecount, &buf[offset - data->start_offset]); if (rpc_nfs3_write_async(nfs->rpc, nfs_pwrite_mcb, &args, mdata) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send WRITE call for %s", data->path); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free(mdata); - return -1; + if (data->num_calls == 0) { + free_nfs_cb_data(data); + return -1; + } + data->oom = 1; + break; } count -= writecount; offset += writecount; data->num_calls++; - } + } while (count > 0); return 0; } @@ -2135,6 +2195,7 @@ int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * ptr = strrchr(new_path, '/'); if (ptr == NULL) { + free(new_path); rpc_set_error(nfs->rpc, "Invalid path %s", path); return -1; } @@ -2221,6 +2282,7 @@ int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * ptr = strrchr(new_path, '/'); if (ptr == NULL) { + free(new_path); rpc_set_error(nfs->rpc, "Invalid path %s", path); return -1; } @@ -2456,6 +2518,7 @@ int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void ptr = strrchr(new_path, '/'); if (ptr == NULL) { + free(new_path); rpc_set_error(nfs->rpc, "Invalid path %s", path); return -1; } @@ -2605,7 +2668,6 @@ int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev /* data->path now points to the parent directory, and beyond the nul terminateor is the new directory to create */ if (nfs_lookuppath_async(nfs, cb_data->path, cb, private_data, nfs_mknod_continue_internal, cb_data, free_mknod_cb_data, 0) != 0) { rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); - free_mknod_cb_data(cb_data); return -1; } @@ -2647,14 +2709,15 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d rdpe_cb_data->getattrcount--; if (status == RPC_STATUS_ERROR) { + rpc_set_error(nfs->rpc, "LOOKUP during READDIRPLUS emulation " + "failed with RPC_STATUS_ERROR"); rdpe_cb_data->status = RPC_STATUS_ERROR; } if (status == RPC_STATUS_CANCEL) { + rpc_set_error(nfs->rpc, "LOOKUP during READDIRPLUS emulation " + "failed with RPC_STATUS_CANCEL"); rdpe_cb_data->status = RPC_STATUS_CANCEL; } - if (status == RPC_STATUS_SUCCESS && res->status != NFS3_OK) { - rdpe_cb_data->status = RPC_STATUS_ERROR; - } if (status == RPC_STATUS_SUCCESS && res->status == NFS3_OK) { if (res->LOOKUP3res_u.resok.obj_attributes.attributes_follow) { fattr3 *attributes = &res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes; @@ -2676,7 +2739,10 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d if (rdpe_cb_data->getattrcount == 0) { if (rdpe_cb_data->status != RPC_STATUS_SUCCESS) { - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + rpc_set_error(nfs->rpc, "READDIRPLUS emulation " + "failed: %s", rpc_get_error(rpc)); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), + data->private_data); nfs_free_nfsdir(nfsdir); } else { data->cb(0, nfs, nfsdir, data->private_data); @@ -2740,6 +2806,7 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d nfsdirent->name = strdup(entry->name); if (nfsdirent->name == NULL) { data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data); + free(nfsdirent); nfs_free_nfsdir(nfsdir); data->continue_data = NULL; free_nfs_cb_data(data); @@ -2799,6 +2866,9 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d * commands in flight to complete */ if (rdpe_cb_data->getattrcount > 0) { + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); rdpe_cb_data->status = RPC_STATUS_ERROR; free(rdpe_lookup_cb_data); return; @@ -2816,7 +2886,6 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d } } - static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { READDIRPLUS3res *res = command_data; @@ -3320,7 +3389,6 @@ int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len); if (nfs_chmod_continue_internal(nfs, data) != 0) { - free_nfs_cb_data(data); return -1; } @@ -3433,10 +3501,10 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int chown_data->uid = uid; chown_data->gid = gid; - data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for fchown data"); + free(chown_data); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); @@ -3444,6 +3512,7 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int data->cb = cb; data->private_data = private_data; data->continue_data = chown_data; + data->free_continue_data = free; data->fh.data.data_len = nfsfh->fh.data.data_len; data->fh.data.data_val = malloc(data->fh.data.data_len); if (data->fh.data.data_val == NULL) { @@ -3453,9 +3522,7 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int } memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len); - if (nfs_chown_continue_internal(nfs, data) != 0) { - free_nfs_cb_data(data); return -1; } @@ -3897,19 +3964,28 @@ static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { struct nfs_rename_data *rename_data = data->continue_data; + char* newpath = strdup(rename_data->newpath); + if (!newpath) { + rpc_set_error(nfs->rpc, "Out of memory. Could not allocate memory to store target path for rename"); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } /* steal the filehandle */ rename_data->olddir = data->fh; data->fh.data.data_val = NULL; if (nfs_lookuppath_async(nfs, rename_data->newpath, data->cb, data->private_data, nfs_rename_continue_2_internal, rename_data, free_nfs_rename_data, 0) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", rename_data->newpath); + rpc_set_error(nfs->rpc, "RPC error: Failed to send LOOKUP call for %s", newpath); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); + free(newpath); return -1; } data->continue_data = NULL; free_nfs_cb_data(data); + free(newpath); return 0; }