X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=c322c377b15d5a858da2e084c0e8aeeb03ee11b8;hb=bff8fe460dcf4b25071fff966d86877b30eeec90;hp=29a276fb5ee0b1d6f3ccfa06b696b428589efa92;hpb=fcc42bfe8501f9f4c5b69d19f5d196e5348c4c81;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index 29a276f..c322c37 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -17,26 +17,58 @@ /* * High level api to nfs filesystems */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef AROS +#include "aros_compat.h" +#endif + #ifdef WIN32 #include "win32_compat.h" -#define DllExport -#else -#include -#include +#endif + +#ifdef HAVE_UTIME_H #include -#include -#endif/*WIN32*/ +#endif + +#ifdef ANDROID +#define statvfs statfs +#endif #define _GNU_SOURCE +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_VFS_H +#include +#endif + +#ifdef HAVE_SYS_STATVFS_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + #include #include #include #include +#include #include #include #include #include +#include "libnfs-zdr.h" #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" @@ -51,7 +83,7 @@ struct nfsdir { struct nfsfh { struct nfs_fh3 fh; int is_sync; - off_t offset; + uint64_t offset; }; struct nfs_context { @@ -59,8 +91,8 @@ struct nfs_context { char *server; char *export; struct nfs_fh3 rootfh; - size_t readmax; - size_t writemax; + uint64_t readmax; + uint64_t writemax; }; void nfs_free_nfsdir(struct nfsdir *nfsdir) @@ -98,14 +130,14 @@ struct nfs_cb_data { int error; int cancel; int num_calls; - off_t start_offset, max_offset; + uint64_t start_offset, max_offset; char *buffer; }; struct nfs_mcb_data { struct nfs_cb_data *data; - off_t offset; - size_t count; + uint64_t offset; + uint64_t count; }; static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh); @@ -216,11 +248,13 @@ void free_nfs_cb_data(struct nfs_cb_data *data) -static void nfs_mount_10_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_mount_10_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; + 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); @@ -242,6 +276,8 @@ static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_context *nfs = data->nfs; FSINFO3res *res = command_data; + 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); @@ -268,6 +304,8 @@ static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + 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); @@ -292,6 +330,11 @@ static void nfs_mount_7_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); @@ -317,6 +360,8 @@ static void nfs_mount_6_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_context *nfs = data->nfs; mountres3 *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); @@ -352,6 +397,8 @@ static void nfs_mount_6_cb(struct rpc_context *rpc, int status, void *command_da free_nfs_cb_data(data); return; } + /* NFS TCP connections we want to autoreconnect after sessions are torn down (due to inactivity or error) */ + rpc_set_autoreconnect(rpc); } @@ -360,6 +407,8 @@ static void nfs_mount_5_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + 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); @@ -383,6 +432,11 @@ static void nfs_mount_4_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); @@ -407,6 +461,8 @@ static void nfs_mount_3_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_context *nfs = data->nfs; uint32_t mount_port; + 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); @@ -440,6 +496,8 @@ static void nfs_mount_2_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + 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); @@ -451,7 +509,7 @@ static void nfs_mount_2_cb(struct rpc_context *rpc, int status, void *command_da return; } - if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, nfs_mount_3_cb, private_data) != 0) { + if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, nfs_mount_3_cb, private_data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -463,6 +521,11 @@ static void nfs_mount_1_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); @@ -499,12 +562,10 @@ int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *exp new_export = strdup(export); if (nfs->server != NULL) { free(nfs->server); - nfs->server = NULL; } nfs->server = new_server; if (nfs->export != NULL) { free(nfs->export); - nfs->export = NULL; } nfs->export = new_export; data->nfs = nfs; @@ -526,12 +587,14 @@ int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *exp * Functions to first look up a path, component by component, and then finally call a specific function once * the filehandle for the final component is found. */ -static void nfs_lookup_path_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_lookup_path_1_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; LOOKUP3res *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); @@ -605,8 +668,8 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c { struct nfs_cb_data *data; - if (path[0] != '/') { - rpc_set_error(nfs->rpc, "Pathname is not absulute %s", path); + if (path[0] != 0 && path[0] != '/') { + rpc_set_error(nfs->rpc, "Pathname is not absolute %s", path); return -1; } @@ -645,13 +708,15 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c /* * Async stat() */ -static void nfs_stat_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_stat_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 stat 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); @@ -677,6 +742,9 @@ static void nfs_stat_1_cb(struct rpc_context *rpc _U_, int status, void *command if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) { st.st_mode |= S_IFDIR ; } + if (res->GETATTR3res_u.resok.obj_attributes.type == NF3REG) { + st.st_mode |= S_IFREG ; + } st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink; st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid; st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid; @@ -722,7 +790,7 @@ int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *p /* * Async open() */ -static void nfs_open_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { ACCESS3res *res; struct nfs_cb_data *data = private_data; @@ -730,6 +798,8 @@ static void nfs_open_cb(struct rpc_context *rpc _U_, int status, void *command_d struct nfsfh *nfsfh; unsigned int nfsmode = 0; + 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); @@ -835,12 +905,14 @@ int nfs_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb c /* * Async pread() */ -static void nfs_pread_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_pread_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; 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); @@ -865,13 +937,15 @@ static void nfs_pread_cb(struct rpc_context *rpc _U_, int status, void *command_ free_nfs_cb_data(data); } -static void nfs_pread_mcb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_pread_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_mcb_data *mdata = private_data; struct nfs_cb_data *data = mdata->data; struct nfs_context *nfs = data->nfs; READ3res *res; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + data->num_calls--; if (status == RPC_STATUS_ERROR) { @@ -925,7 +999,7 @@ static void nfs_pread_mcb(struct rpc_context *rpc _U_, int status, void *command free(mdata); } -int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, nfs_cb cb, void *private_data) +int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; @@ -968,7 +1042,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, } while (count > 0) { - size_t readcount = count; + uint64_t readcount = count; struct nfs_mcb_data *mdata; if (readcount > nfs_get_readmax(nfs)) { @@ -1002,7 +1076,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, /* * Async read() */ -int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, nfs_cb cb, void *private_data) +int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, nfs_cb cb, void *private_data) { return nfs_pread_async(nfs, nfsfh, nfsfh->offset, count, cb, private_data); } @@ -1012,12 +1086,14 @@ int nfs_read_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, n /* * Async pwrite() */ -static void nfs_pwrite_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_pwrite_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; 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); @@ -1042,13 +1118,15 @@ static void nfs_pwrite_cb(struct rpc_context *rpc _U_, int status, void *command free_nfs_cb_data(data); } -static void nfs_pwrite_mcb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_pwrite_mcb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { struct nfs_mcb_data *mdata = private_data; struct nfs_cb_data *data = mdata->data; struct nfs_context *nfs = data->nfs; WRITE3res *res; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + data->num_calls--; if (status == RPC_STATUS_ERROR) { @@ -1101,7 +1179,7 @@ static void nfs_pwrite_mcb(struct rpc_context *rpc _U_, int status, void *comman } -int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, size_t count, char *buf, nfs_cb cb, void *private_data) +int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, uint64_t count, char *buf, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; @@ -1136,7 +1214,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, data->start_offset = offset; while (count > 0) { - size_t writecount = count; + uint64_t writecount = count; struct nfs_mcb_data *mdata; if (writecount > nfs_get_writemax(nfs)) { @@ -1171,7 +1249,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, /* * Async write() */ -int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, size_t count, char *buf, nfs_cb cb, void *private_data) +int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count, char *buf, nfs_cb cb, void *private_data) { return nfs_pwrite_async(nfs, nfsfh, nfsfh->offset, count, buf, cb, private_data); } @@ -1230,12 +1308,14 @@ int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi /* * Async fsync() */ -static void nfs_fsync_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_fsync_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; COMMIT3res *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); @@ -1288,12 +1368,14 @@ int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi /* * Async ftruncate() */ -static void nfs_ftruncate_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_ftruncate_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; 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); @@ -1317,7 +1399,7 @@ static void nfs_ftruncate_cb(struct rpc_context *rpc _U_, int status, void *comm free_nfs_cb_data(data); } -int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t length, nfs_cb cb, void *private_data) +int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t length, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; SETATTR3args args; @@ -1353,7 +1435,7 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t leng */ static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { - off_t offset = data->continue_int; + uint64_t offset = data->continue_int; struct nfsfh nfsfh; nfsfh.fh.data.data_val = data->fh.data.data_val; @@ -1369,9 +1451,9 @@ static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb return 0; } -int nfs_truncate_async(struct nfs_context *nfs, const char *path, off_t length, nfs_cb cb, void *private_data) +int nfs_truncate_async(struct nfs_context *nfs, const char *path, uint64_t length, nfs_cb cb, void *private_data) { - off_t offset; + uint64_t offset; offset = length; @@ -1389,13 +1471,15 @@ int nfs_truncate_async(struct nfs_context *nfs, const char *path, off_t length, /* * Async mkdir() */ -static void nfs_mkdir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_mkdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { MKDIR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + str = &str[strlen(str) + 1]; if (status == RPC_STATUS_ERROR) { @@ -1424,10 +1508,18 @@ static void nfs_mkdir_cb(struct rpc_context *rpc _U_, int status, void *command_ static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { char *str = data->continue_data; - + MKDIR3args args; + str = &str[strlen(str) + 1]; - if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &data->fh, str, data) != 0) { + memset(&args, 0, sizeof(MKDIR3args)); + args.where.dir.data.data_len = data->fh.data.data_len; + args.where.dir.data.data_val = data->fh.data.data_val; + args.where.name = str; + args.attributes.mode.set_it = 1; + args.attributes.mode.set_mode3_u.mode = 0755; + + if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send MKDIR call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -1470,13 +1562,15 @@ int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * /* * Async rmdir() */ -static void nfs_rmdir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { RMDIR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + str = &str[strlen(str) + 1]; if (status == RPC_STATUS_ERROR) { @@ -1550,7 +1644,7 @@ int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * /* * Async creat() */ -static void nfs_create_2_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_create_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { LOOKUP3res *res; struct nfs_cb_data *data = private_data; @@ -1558,6 +1652,8 @@ static void nfs_create_2_cb(struct rpc_context *rpc _U_, int status, void *comma struct nfsfh *nfsfh; char *str = data->continue_data; + 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); @@ -1587,10 +1683,10 @@ static void nfs_create_2_cb(struct rpc_context *rpc _U_, int status, void *comma } memset(nfsfh, 0, sizeof(struct nfsfh)); - /* steal the filehandle */ - nfsfh->fh.data.data_len = data->fh.data.data_len; - nfsfh->fh.data.data_val = data->fh.data.data_val; - data->fh.data.data_val = NULL; + /* 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); + memcpy(nfsfh->fh.data.data_val, res->LOOKUP3res_u.resok.object.data.data_val, nfsfh->fh.data.data_len); data->cb(0, nfs, nfsfh, data->private_data); free_nfs_cb_data(data); @@ -1598,13 +1694,15 @@ static void nfs_create_2_cb(struct rpc_context *rpc _U_, int status, void *comma -static void nfs_creat_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { CREATE3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; + 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); @@ -1637,10 +1735,19 @@ static void nfs_creat_1_cb(struct rpc_context *rpc _U_, int status, void *comman static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { char *str = data->continue_data; - + CREATE3args args; + str = &str[strlen(str) + 1]; - if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &data->fh, str, data->continue_int, data) != 0) { + memset(&args, 0, sizeof(CREATE3args)); + args.where.dir.data.data_len = data->fh.data.data_len; + args.where.dir.data.data_val = data->fh.data.data_val; + args.where.name = str; + args.how.mode = UNCHECKED; + args.how.createhow3_u.obj_attributes.mode.set_it = 1; + args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = data->continue_int; + + if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send CREATE call for %s/%s", data->path, str); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -1667,7 +1774,7 @@ int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb } *ptr = 0; - /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */ + /* new_path now points to the parent directory, and beyond the nul terminator is the new directory to create */ if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_creat_continue_internal, new_path, free, mode) != 0) { rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; @@ -1682,13 +1789,15 @@ int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb /* * Async unlink() */ -static void nfs_unlink_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { REMOVE3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + str = &str[strlen(str) + 1]; if (status == RPC_STATUS_ERROR) { @@ -1757,20 +1866,198 @@ int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void } +/* + * Async mknod() + */ +struct mknod_cb_data { + char *path; + int mode; + int major; + int minor; +}; + +static void free_mknod_cb_data(void *ptr) +{ + struct mknod_cb_data *data = ptr; + + free(data->path); + free(data); +} + +static void nfs_mknod_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + MKNOD3res *res; + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + char *str = data->continue_data; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + str = &str[strlen(str) + 1]; + + 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: MKNOD of %s/%s failed with %s(%d)", data->saved_path, str, 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->cb(0, nfs, NULL, data->private_data); + free_nfs_cb_data(data); +} + +static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +{ + struct mknod_cb_data *cb_data = data->continue_data; + char *str = cb_data->path; + + str = &str[strlen(str) + 1]; + + if (rpc_nfs_mknod_async(nfs->rpc, nfs_mknod_cb, &data->fh, str, cb_data->mode, cb_data->major, cb_data->minor, data) != 0) { + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } + return 0; +} + +int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev, nfs_cb cb, void *private_data) +{ + char *ptr; + struct mknod_cb_data *cb_data; + + cb_data = malloc(sizeof(struct mknod_cb_data)); + if (cb_data == NULL) { + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for cb data"); + return -1; + } + + cb_data->path = strdup(path); + if (cb_data->path == NULL) { + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path"); + free(cb_data); + return -1; + } + + ptr = strrchr(cb_data->path, '/'); + if (ptr == NULL) { + rpc_set_error(nfs->rpc, "Invalid path %s", path); + return -1; + } + *ptr = 0; + + cb_data->mode = mode; + cb_data->major = major(dev); + cb_data->minor = minor(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; + } + return 0; +} /* * Async opendir() */ -static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) + +/* ReadDirPlus Emulation Callback data */ +struct rdpe_cb_data { + int getattrcount; + int status; + struct nfs_cb_data *data; +}; + +/* ReadDirPlus Emulation LOOKUP Callback data */ +struct rdpe_lookup_cb_data { + struct rdpe_cb_data *rdpe_cb_data; + struct nfsdirent *nfsdirent; +}; + +/* Workaround for servers lacking READDIRPLUS, use READDIR instead and a GETATTR-loop */ +static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + LOOKUP3res *res = command_data; + struct rdpe_lookup_cb_data *rdpe_lookup_cb_data = private_data; + struct rdpe_cb_data *rdpe_cb_data = rdpe_lookup_cb_data->rdpe_cb_data; + struct nfs_cb_data *data = rdpe_cb_data->data; + struct nfsdir *nfsdir = data->continue_data; + struct nfs_context *nfs = data->nfs; + struct nfsdirent *nfsdirent = rdpe_lookup_cb_data->nfsdirent; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + free(rdpe_lookup_cb_data); + + rdpe_cb_data->getattrcount--; + + if (status == RPC_STATUS_ERROR) { + rdpe_cb_data->status = RPC_STATUS_ERROR; + } + if (status == 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; + + nfsdirent->type = attributes->type; + nfsdirent->mode = attributes->mode; + nfsdirent->size = attributes->size; + + nfsdirent->atime.tv_sec = attributes->atime.seconds; + nfsdirent->atime.tv_usec = attributes->atime.nseconds/1000; + nfsdirent->mtime.tv_sec = attributes->mtime.seconds; + nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000; + nfsdirent->ctime.tv_sec = attributes->ctime.seconds; + nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000; + } + } + + 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); + nfs_free_nfsdir(nfsdir); + } else { + data->cb(0, nfs, nfsdir, data->private_data); + } + free(rdpe_cb_data); + + data->continue_data = NULL; + free_nfs_cb_data(data); + } +} + +static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { - READDIRPLUS3res *res; + READDIR3res *res = command_data; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfsdir *nfsdir = data->continue_data; - struct entryplus3 *entry; + struct nfsdirent *nfsdirent; + struct entry3 *entry; uint64_t cookie; + struct rdpe_cb_data *rdpe_cb_data; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); @@ -1779,6 +2066,7 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman free_nfs_cb_data(data); return; } + if (status == RPC_STATUS_CANCEL) { data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); nfs_free_nfsdir(nfsdir); @@ -1787,7 +2075,6 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman return; } - res = command_data; if (res->status != NFS3_OK) { rpc_set_error(nfs->rpc, "NFS: READDIR 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); @@ -1797,6 +2084,127 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman return; } + entry =res->READDIR3res_u.resok.reply.entries; + while (entry != NULL) { + nfsdirent = malloc(sizeof(struct nfsdirent)); + if (nfsdirent == NULL) { + data->cb(-ENOMEM, nfs, "Failed to allocate dirent", data->private_data); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + return; + } + memset(nfsdirent, 0, sizeof(struct nfsdirent)); + nfsdirent->name = strdup(entry->name); + if (nfsdirent->name == NULL) { + data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + return; + } + nfsdirent->inode = entry->fileid; + + nfsdirent->next = nfsdir->entries; + nfsdir->entries = nfsdirent; + + cookie = entry->cookie; + entry = entry->nextentry; + } + + if (res->READDIR3res_u.resok.reply.eof == 0) { + if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 8192, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + return; + } + return; + } + + /* steal the dirhandle */ + nfsdir->current = nfsdir->entries; + + rdpe_cb_data = malloc(sizeof(struct rdpe_cb_data)); + rdpe_cb_data->getattrcount = 0; + rdpe_cb_data->status = RPC_STATUS_SUCCESS; + rdpe_cb_data->data = data; + for (nfsdirent = nfsdir->entries; nfsdirent; nfsdirent = nfsdirent->next) { + struct rdpe_lookup_cb_data *rdpe_lookup_cb_data; + + rdpe_lookup_cb_data = malloc(sizeof(struct rdpe_lookup_cb_data)); + rdpe_lookup_cb_data->rdpe_cb_data = rdpe_cb_data; + rdpe_lookup_cb_data->nfsdirent = nfsdirent; + + if (rpc_nfs_lookup_async(nfs->rpc, nfs_opendir3_cb, &data->fh, nfsdirent->name, rdpe_lookup_cb_data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR LOOKUP call"); + + /* if we have already commands in flight, we cant just stop, we have to wait for the + * commands in flight to complete + */ + if (rdpe_cb_data->getattrcount > 0) { + rdpe_cb_data->status = RPC_STATUS_ERROR; + free(rdpe_lookup_cb_data); + return; + } + + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + free(rdpe_lookup_cb_data); + free(rdpe_cb_data); + return; + } + rdpe_cb_data->getattrcount++; + } +} + + +static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + READDIRPLUS3res *res = command_data; + struct nfs_cb_data *data = private_data; + struct nfs_context *nfs = data->nfs; + struct nfsdir *nfsdir = data->continue_data; + struct entryplus3 *entry; + uint64_t cookie; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR || (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) ){ + cookieverf3 cv; + + if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + return; + } + return; + } + + if (status == RPC_STATUS_CANCEL) { + data->cb(-EINTR, nfs, "Command was cancelled", data->private_data); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + return; + } + + if (res->status != NFS3_OK) { + rpc_set_error(nfs->rpc, "NFS: READDIRPLUS 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); + nfs_free_nfsdir(nfsdir); + data->continue_data = NULL; + free_nfs_cb_data(data); + return; + } + entry =res->READDIRPLUS3res_u.resok.reply.entries; while (entry != NULL) { struct nfsdirent *nfsdirent; @@ -1921,17 +2329,19 @@ void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir) struct lseek_cb_data { struct nfs_context *nfs; struct nfsfh *nfsfh; - off_t offset; + uint64_t offset; nfs_cb cb; void *private_data; }; -static void nfs_lseek_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_lseek_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { GETATTR3res *res; struct lseek_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); free(data); @@ -1956,7 +2366,7 @@ static void nfs_lseek_1_cb(struct rpc_context *rpc _U_, int status, void *comman free(data); } -int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, int whence, nfs_cb cb, void *private_data) +int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offset, int whence, nfs_cb cb, void *private_data) { struct lseek_cb_data *data; @@ -1997,13 +2407,15 @@ int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, /* * Async statvfs() */ -static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { FSSTAT3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct statvfs svfs; + 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); @@ -2030,10 +2442,12 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc _U_, int status, void *comm svfs.f_bavail = res->FSSTAT3res_u.resok.abytes/4096; svfs.f_files = res->FSSTAT3res_u.resok.tfiles; svfs.f_ffree = res->FSSTAT3res_u.resok.ffiles; +#if !defined(ANDROID) svfs.f_favail = res->FSSTAT3res_u.resok.afiles; svfs.f_fsid = 0; svfs.f_flag = 0; svfs.f_namemax = 256; +#endif data->cb(0, nfs, &svfs, data->private_data); free_nfs_cb_data(data); @@ -2066,12 +2480,14 @@ int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void /* * Async readlink() */ -static void nfs_readlink_1_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_readlink_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { READLINK3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; + 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); @@ -2098,7 +2514,12 @@ static void nfs_readlink_1_cb(struct rpc_context *rpc _U_, int status, void *com static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { - if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &data->fh, data) != 0) { + READLINK3args args; + + args.symlink.data.data_len = data->fh.data.data_len; + args.symlink.data.data_val = data->fh.data.data_val; + + if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send READLINK call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -2123,12 +2544,14 @@ int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, voi /* * Async chmod() */ -static void nfs_chmod_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_chmod_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; 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); @@ -2221,12 +2644,14 @@ int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs /* * Async chown() */ -static void nfs_chown_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_chown_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; 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); @@ -2357,12 +2782,14 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int /* * Async utimes() */ -static void nfs_utimes_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_utimes_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; 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); @@ -2473,13 +2900,15 @@ int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *t /* * Async access() */ -static void nfs_access_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_access_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { ACCESS3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; unsigned int nfsmode = 0; + 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); @@ -2586,13 +3015,15 @@ static void free_nfs_symlink_data(void *mem) free(data); } -static void nfs_symlink_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { SYMLINK3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_symlink_data *symlink_data = data->continue_data; + 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); @@ -2619,8 +3050,17 @@ static void nfs_symlink_cb(struct rpc_context *rpc _U_, int status, void *comman static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { struct nfs_symlink_data *symlink_data = data->continue_data; + SYMLINK3args sa; + + memset(&sa, 0, sizeof(SYMLINK3args)); + sa.where.dir.data.data_len = data->fh.data.data_len; + sa.where.dir.data.data_val = data->fh.data.data_val; + sa.where.name = symlink_data->newpathobject; + sa.symlink.symlink_attributes.mode.set_it = 1; + sa.symlink.symlink_attributes.mode.set_mode3_u.mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH; + sa.symlink.symlink_data = symlink_data->oldpath; - if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &data->fh, symlink_data->newpathobject, symlink_data->oldpath, data) != 0) { + if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &sa, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send SYMLINK call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -2712,13 +3152,15 @@ static void free_nfs_rename_data(void *mem) free(data); } -static void nfs_rename_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { RENAME3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_rename_data *rename_data = data->continue_data; + 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); @@ -2868,13 +3310,15 @@ static void free_nfs_link_data(void *mem) free(data); } -static void nfs_link_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) +static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { LINK3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; struct nfs_link_data *link_data = data->continue_data; + 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); @@ -2985,7 +3429,7 @@ int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *new //qqq replace later with lseek() -off_t nfs_get_current_offset(struct nfsfh *nfsfh) +uint64_t nfs_get_current_offset(struct nfsfh *nfsfh) { return nfsfh->offset; } @@ -2995,7 +3439,7 @@ off_t nfs_get_current_offset(struct nfsfh *nfsfh) /* * Get the maximum supported READ3 size by the server */ -size_t nfs_get_readmax(struct nfs_context *nfs) +uint64_t nfs_get_readmax(struct nfs_context *nfs) { return nfs->readmax; } @@ -3003,9 +3447,9 @@ size_t nfs_get_readmax(struct nfs_context *nfs) /* * Get the maximum supported WRITE3 size by the server */ -size_t nfs_get_writemax(struct nfs_context *nfs) +uint64_t nfs_get_writemax(struct nfs_context *nfs) { - /* Some XDR libraries can not marshall PDUs bigger than this */ + /* Some ZDR libraries can not marshall PDUs bigger than this */ if (nfs->writemax < 32768) { return nfs->writemax; } @@ -3049,7 +3493,9 @@ static void mount_export_5_cb(struct rpc_context *rpc, int status, void *command { struct mount_cb_data *data = private_data; - if (status == RPC_STATUS_ERROR) { + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); return; @@ -3071,6 +3517,11 @@ static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command { struct mount_cb_data *data = private_data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + if (status == RPC_STATUS_ERROR) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); @@ -3094,7 +3545,9 @@ static void mount_export_3_cb(struct rpc_context *rpc, int status, void *command struct mount_cb_data *data = private_data; uint32_t mount_port; - if (status == RPC_STATUS_ERROR) { + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); return; @@ -3125,6 +3578,8 @@ static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command { struct mount_cb_data *data = private_data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + if (status == RPC_STATUS_ERROR) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); @@ -3136,7 +3591,7 @@ static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command return; } - if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, mount_export_3_cb, private_data) != 0) { + if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, IPPROTO_TCP, mount_export_3_cb, private_data) != 0) { data->cb(rpc, -ENOMEM, command_data, data->private_data); free_mount_cb_data(data); return; @@ -3147,6 +3602,11 @@ static void mount_export_1_cb(struct rpc_context *rpc, int status, void *command { struct mount_cb_data *data = private_data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + /* Dont want any more callbacks even if the socket is closed */ + rpc->connect_cb = NULL; + if (status == RPC_STATUS_ERROR) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); @@ -3169,6 +3629,8 @@ int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb c { struct mount_cb_data *data; + assert(rpc->magic == RPC_CONTEXT_MAGIC); + data = malloc(sizeof(struct mount_cb_data)); if (data == NULL) { return -1; @@ -3191,6 +3653,7 @@ int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb c struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs) { + assert(nfs->rpc->magic == RPC_CONTEXT_MAGIC); return nfs->rpc; } @@ -3202,3 +3665,10 @@ const char *nfs_get_export(struct nfs_context *nfs) { return nfs->export; } +const struct nfs_fh3 *nfs_get_rootfh(struct nfs_context *nfs) { + return &nfs->rootfh; +} + +struct nfs_fh3 *nfs_get_fh(struct nfsfh *nfsfh) { + return &nfsfh->fh; +}