X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=2e3e7f2d77e473bd6ccbee459bc442d316efce58;hb=d47c989d886e5398143d43d3b6d25fdf7210cb11;hp=543b0ce9ec89a7293e129213e7158c6d150ded77;hpb=728970051cb7420c08c3c4860f09f971880e3244;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index 543b0ce..2e3e7f2 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -27,10 +27,11 @@ #ifdef WIN32 #include "win32_compat.h" -#else -#include +#endif + +#ifdef HAVE_UTIME_H #include -#endif /*WIN32*/ +#endif #ifdef ANDROID #define statvfs statfs @@ -54,6 +55,10 @@ #include #endif +#ifdef HAVE_STRINGS_H +#include +#endif + #include #include #include @@ -214,6 +219,155 @@ void nfs_destroy_context(struct nfs_context *nfs) free(nfs); } +struct rpc_cb_data { + char *server; + uint32_t program; + uint32_t version; + + rpc_cb cb; + void *private_data; +}; + +void free_rpc_cb_data(struct rpc_cb_data *data) +{ + free(data->server); + data->server = NULL; + free(data); +} + +static void rpc_connect_program_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct rpc_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, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, status, "Command was cancelled", data->private_data); + free_rpc_cb_data(data); + return; + } + + data->cb(rpc, status, NULL, data->private_data); + free_rpc_cb_data(data); +} + +static void rpc_connect_program_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct rpc_cb_data *data = private_data; + uint32_t rpc_port; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, status, "Command was cancelled", data->private_data); + free_rpc_cb_data(data); + return; + } + + rpc_port = *(uint32_t *)command_data; + if (rpc_port == 0) { + rpc_set_error(rpc, "RPC error. Program is not available on %s", data->server); + data->cb(rpc, RPC_STATUS_ERROR, rpc_get_error(rpc), data->private_data); + free_rpc_cb_data(data); + return; + } + + rpc_disconnect(rpc, "normal disconnect"); + if (rpc_connect_async(rpc, data->server, rpc_port, rpc_connect_program_4_cb, data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } +} + +static void rpc_connect_program_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct rpc_cb_data *data = private_data; + + assert(rpc->magic == RPC_CONTEXT_MAGIC); + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, status, "Command was cancelled", data->private_data); + free_rpc_cb_data(data); + return; + } + + if (rpc_pmap_getport_async(rpc, data->program, data->version, IPPROTO_TCP, rpc_connect_program_3_cb, private_data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } +} + +static void rpc_connect_program_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct rpc_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, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, status, "Command was cancelled", data->private_data); + free_rpc_cb_data(data); + return; + } + + if (rpc_pmap_null_async(rpc, rpc_connect_program_2_cb, data) != 0) { + data->cb(rpc, status, command_data, data->private_data); + free_rpc_cb_data(data); + return; + } +} + +int rpc_connect_program_async(struct rpc_context *rpc, char *server, int program, int version, rpc_cb cb, void *private_data) +{ + struct rpc_cb_data *data; + + data = malloc(sizeof(struct rpc_cb_data)); + if (data == NULL) { + return -1; + } + memset(data, 0, sizeof(struct rpc_cb_data)); + data->server = strdup(server); + data->program = program; + data->version = version; + + data->cb = cb; + data->private_data = private_data; + + if (rpc_connect_async(rpc, server, 111, rpc_connect_program_1_cb, data) != 0) { + rpc_set_error(rpc, "Failed to start connection"); + free_rpc_cb_data(data); + return -1; + } + return 0; +} + void free_nfs_cb_data(struct nfs_cb_data *data) { if (data->saved_path != NULL) { @@ -1023,7 +1177,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse /* trying to read more than maximum server read size, we has to chop it up into smaller * reads and collect into a reassembly buffer. - * we send all reads in parallell so that performance is still good. + * we send all reads in parallel so that performance is still good. */ data->max_offset = offset; data->start_offset = offset; @@ -1203,7 +1357,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs /* trying to write more than maximum server write size, we has to chop it up into smaller * chunks. - * we send all writes in parallell so that performance is still good. + * we send all writes in parallel so that performance is still good. */ data->max_offset = offset; data->start_offset = offset; @@ -1714,7 +1868,7 @@ static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_da if (res->status != NFS3_OK) { rpc_set_error(nfs->rpc, "NFS: CREATE 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; } @@ -2889,9 +3043,6 @@ int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *t } - - - /* * Async access() */ @@ -3444,11 +3595,7 @@ uint64_t nfs_get_readmax(struct nfs_context *nfs) */ uint64_t nfs_get_writemax(struct nfs_context *nfs) { - /* Some ZDR libraries can not marshall PDUs bigger than this */ - if (nfs->writemax < 32768) { - return nfs->writemax; - } - return 32768; + return nfs->writemax; } void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)