X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=c697895f68c4ab88893ee18111306575b22f34a6;hb=63d4a0583d83c3b335d411c64911905faa35b97f;hp=f8b294a5589ebcffba9a0b8d9e7f345ab8788469;hpb=c5e346e15c043a6253cc5a838dd9c77febf624aa;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index f8b294a..c697895 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -93,6 +93,7 @@ struct nfs_context { struct nfs_fh3 rootfh; uint64_t readmax; uint64_t writemax; + char *cwd; }; void nfs_free_nfsdir(struct nfsdir *nfsdir) @@ -142,7 +143,6 @@ struct nfs_mcb_data { static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh); - void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth) { rpc_set_auth(nfs->rpc, auth); @@ -173,6 +173,159 @@ char *nfs_get_error(struct nfs_context *nfs) return rpc_get_error(nfs->rpc); }; +static int nfs_set_context_args(struct nfs_context *nfs, char *arg, char *val) +{ + if (!strncmp(arg, "tcp-syncnt", 10)) { + rpc_set_tcp_syncnt(nfs_get_rpc_context(nfs), atoi(val)); + } else if (!strncmp(arg, "uid", 3)) { + rpc_set_uid(nfs_get_rpc_context(nfs), atoi(val)); + } else if (!strncmp(arg, "gid", 3)) { + rpc_set_gid(nfs_get_rpc_context(nfs), atoi(val)); + } + return 0; +} + +static struct nfs_url *nfs_parse_url(struct nfs_context *nfs, const char *url, int dir, int incomplete) +{ + struct nfs_url *urls; + char *strp, *flagsp, *strp2; + + if (strncmp(url, "nfs://", 6)) { + rpc_set_error(nfs->rpc, "Invalid URL specified"); + return NULL; + } + + urls = malloc(sizeof(struct nfs_url)); + if (urls == NULL) { + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + + memset(urls, 0x00, sizeof(struct nfs_url)); + urls->server = strdup(url + 6); + if (urls->server == NULL) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + + if (urls->server[0] == '/' || urls->server[0] == '\0' || + urls->server[0] == '?') { + if (incomplete) { + flagsp = strchr(urls->server, '?'); + goto flags; + } + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Invalid server string"); + return NULL; + } + + strp = strchr(urls->server, '/'); + if (strp == NULL) { + if (incomplete) { + flagsp = strchr(urls->server, '?'); + goto flags; + } + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified."); + return NULL; + } + + urls->path = strdup(strp); + if (urls->path == NULL) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + *strp = 0; + + if (dir) { + flagsp = strchr(urls->path, '?'); + goto flags; + } + + strp = strrchr(urls->path, '/'); + if (strp == NULL) { + if (incomplete) { + flagsp = strchr(urls->path, '?'); + goto flags; + } + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified."); + return NULL; + } + urls->file = strdup(strp); + if (urls->path == NULL) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Out of memory"); + return NULL; + } + *strp = 0; + flagsp = strchr(urls->file, '?'); + +flags: + if (flagsp) { + *flagsp = 0; + } + + if (urls->file && !strlen(urls->file)) { + free(urls->file); + urls->file = NULL; + if (!incomplete) { + nfs_destroy_url(urls); + rpc_set_error(nfs->rpc, "Incomplete or invalid URL specified."); + return NULL; + } + } + + while (flagsp != NULL && *(flagsp+1) != 0) { + strp = flagsp + 1; + flagsp = strchr(strp, '&'); + if (flagsp) { + *flagsp = 0; + } + strp2 = strchr(strp, '='); + if (strp2) { + *strp2 = 0; + strp2++; + nfs_set_context_args(nfs, strp, strp2); + } + } + + if (urls->server && strlen(urls->server) <= 1) { + free(urls->server); + urls->server = NULL; + } + + return urls; +} + +struct nfs_url *nfs_parse_url_full(struct nfs_context *nfs, const char *url) +{ + return nfs_parse_url(nfs, url, 0, 0); +} + +struct nfs_url *nfs_parse_url_dir(struct nfs_context *nfs, const char *url) +{ + return nfs_parse_url(nfs, url, 1, 0); +} + +struct nfs_url *nfs_parse_url_incomplete(struct nfs_context *nfs, const char *url) +{ + return nfs_parse_url(nfs, url, 0, 1); +} + + +void nfs_destroy_url(struct nfs_url *url) +{ + if (url) { + free(url->server); + free(url->path); + free(url->file); + } + free(url); +} + struct nfs_context *nfs_init_context(void) { struct nfs_context *nfs; @@ -181,17 +334,15 @@ struct nfs_context *nfs_init_context(void) if (nfs == NULL) { return NULL; } + memset(nfs, 0, sizeof(struct nfs_context)); + nfs->rpc = rpc_init_context(); if (nfs->rpc == NULL) { free(nfs); return NULL; } - nfs->server = NULL; - nfs->export = NULL; - - nfs->rootfh.data.data_len = 0; - nfs->rootfh.data.data_val = NULL; + nfs->cwd = strdup("/"); return nfs; } @@ -211,6 +362,11 @@ void nfs_destroy_context(struct nfs_context *nfs) nfs->export = NULL; } + if (nfs->cwd) { + free(nfs->cwd); + nfs->cwd = NULL; + } + if (nfs->rootfh.data.data_val != NULL) { free(nfs->rootfh.data.data_val); nfs->rootfh.data.data_val = NULL; @@ -219,27 +375,165 @@ void nfs_destroy_context(struct nfs_context *nfs) free(nfs); } -void free_nfs_cb_data(struct nfs_cb_data *data) +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) { - if (data->saved_path != NULL) { - free(data->saved_path); - data->saved_path = NULL; + 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 (data->continue_data != NULL) { - data->free_continue_data(data->continue_data); - data->continue_data = NULL; + 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 (data->fh.data.data_val != NULL) { - free(data->fh.data.data_val); - data->fh.data.data_val = NULL; + 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; } +} - if (data->buffer != NULL) { - free(data->buffer); - data->buffer = NULL; +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; +} + +static void free_nfs_cb_data(struct nfs_cb_data *data) +{ + if (data->continue_data != NULL) { + assert(data->free_continue_data); + data->free_continue_data(data->continue_data); + } + + free(data->saved_path); + free(data->fh.data.data_val); + free(data->buffer); free(data); } @@ -275,6 +569,7 @@ static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; FSINFO3res *res = command_data; + struct GETATTR3args args; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -292,7 +587,10 @@ static void nfs_mount_9_cb(struct rpc_context *rpc, int status, void *command_da nfs->readmax = res->FSINFO3res_u.resok.rtmax; nfs->writemax = res->FSINFO3res_u.resok.wtmax; - if (rpc_nfs_getattr_async(rpc, nfs_mount_10_cb, &nfs->rootfh, data) != 0) { + memset(&args, 0, sizeof(GETATTR3args)); + args.object = nfs->rootfh; + + if (rpc_nfs3_getattr_async(rpc, nfs_mount_10_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -303,6 +601,7 @@ 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; + struct FSINFO3args args; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -317,7 +616,8 @@ static void nfs_mount_8_cb(struct rpc_context *rpc, int status, void *command_da return; } - if (rpc_nfs_fsinfo_async(rpc, nfs_mount_9_cb, &nfs->rootfh, data) != 0) { + args.fsroot = nfs->rootfh; + if (rpc_nfs3_fsinfo_async(rpc, nfs_mount_9_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -346,7 +646,7 @@ static void nfs_mount_7_cb(struct rpc_context *rpc, int status, void *command_da return; } - if (rpc_nfs_null_async(rpc, nfs_mount_8_cb, data) != 0) { + if (rpc_nfs3_null_async(rpc, nfs_mount_8_cb, data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -420,7 +720,7 @@ static void nfs_mount_5_cb(struct rpc_context *rpc, int status, void *command_da return; } - if (rpc_mount_mnt_async(rpc, nfs_mount_6_cb, nfs->export, data) != 0) { + if (rpc_mount3_mnt_async(rpc, nfs_mount_6_cb, nfs->export, data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -448,7 +748,7 @@ static void nfs_mount_4_cb(struct rpc_context *rpc, int status, void *command_da return; } - if (rpc_mount_null_async(rpc, nfs_mount_5_cb, data) != 0) { + if (rpc_mount3_null_async(rpc, nfs_mount_5_cb, data) != 0) { data->cb(-ENOMEM, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -463,7 +763,7 @@ static void nfs_mount_3_cb(struct rpc_context *rpc, int status, void *command_da assert(rpc->magic == RPC_CONTEXT_MAGIC); - if (status == RPC_STATUS_ERROR) { + if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); return; @@ -624,17 +924,24 @@ static void nfs_lookup_path_1_cb(struct rpc_context *rpc, int status, void *comm static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh) { - char *path, *str; + char *path, *slash; + LOOKUP3args args; while (*data->path == '/') { data->path++; } path = data->path; - str = strchr(path, '/'); - if (str != NULL) { - *str = 0; - data->path = str+1; + slash = strchr(path, '/'); + if (slash != NULL) { + /* Clear slash so that path is a zero terminated string for + * the current path component. Set it back to '/' again later + * when we are finished referencing this component so that + * data->saved_path will still point to the full + * normalized path. + */ + *slash = 0; + data->path = slash+1; } else { while (*data->path != 0) { data->path++; @@ -651,16 +958,127 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb return -1; } memcpy(data->fh.data.data_val, fh->data.data_val, data->fh.data.data_len); + if (slash != NULL) { + *slash = '/'; + } data->continue_cb(nfs, data); return 0; } - if (rpc_nfs_lookup_async(nfs->rpc, nfs_lookup_path_1_cb, fh, path, data) != 0) { + + memset(&args, 0, sizeof(LOOKUP3args)); + args.what.dir = *fh; + args.what.name = path; + + if (rpc_nfs3_lookup_async(nfs->rpc, nfs_lookup_path_1_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); return -1; } + if (slash != NULL) { + *slash = '/'; + } + return 0; +} + +static int nfs_normalize_path(struct nfs_context *nfs, char *path) +{ + char *str; + int len; + + /* // -> / */ + while ((str = strstr(path, "//"))) { + while(*str) { + *str = *(str + 1); + str++; + } + } + + /* /./ -> / */ + while ((str = strstr(path, "/./"))) { + while(*(str + 1)) { + *str = *(str + 2); + str++; + } + } + + /* ^/../ -> error */ + if (!strncmp(path, "/../", 4)) { + rpc_set_error(nfs->rpc, + "Absolute path starts with '/../' " + "during normalization"); + return -1; + } + + /* ^[^/] -> error */ + if (path[0] != '/') { + rpc_set_error(nfs->rpc, + "Absolute path does not start with '/'"); + return -1; + } + + /* /string/../ -> / */ + while ((str = strstr(path, "/../"))) { + char *tmp; + + if (!strncmp(path, "/../", 4)) { + rpc_set_error(nfs->rpc, + "Absolute path starts with '/../' " + "during normalization"); + return -1; + } + + tmp = str - 1; + while (*tmp != '/') { + tmp--; + } + str += 3; + while((*(tmp++) = *(str++)) != '\0') + ; + } + + /* /$ -> \0 */ + len = strlen(path); + if (len >= 1) { + if (path[len - 1] == '/') { + path[len - 1] = '\0'; + len--; + } + } + if (path[0] == '\0') { + rpc_set_error(nfs->rpc, + "Absolute path became '' " + "during normalization"); + return -1; + } + + /* /.$ -> \0 */ + if (len >= 2) { + if (!strcmp(&path[len - 2], "/.")) { + path[len - 2] = '\0'; + len -= 2; + } + } + + /* ^/..$ -> error */ + if (!strcmp(path, "/..")) { + rpc_set_error(nfs->rpc, + "Absolute path is '/..' " + "during normalization"); + return -1; + } + + /* /string/..$ -> / */ + if (len >= 3) { + if (!strcmp(&path[len - 3], "/..")) { + char *tmp = &path[len - 3]; + while (*--tmp != '/') + ; + *tmp = '\0'; + } + } + return 0; } @@ -668,14 +1086,16 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c { struct nfs_cb_data *data; - if (path[0] != 0 && path[0] != '/') { - rpc_set_error(nfs->rpc, "Pathname is not absolute %s", path); - return -1; + if (path[0] == '\0') { + path = "."; } data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { - rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure"); + rpc_set_error(nfs->rpc, "out of memory: failed to allocate " + "nfs_cb_data structure"); + if (free_continue_data) + free_continue_data(continue_data); return -1; } memset(data, 0, sizeof(struct nfs_cb_data)); @@ -686,12 +1106,29 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c data->free_continue_data = free_continue_data; data->continue_int = continue_int; data->private_data = private_data; - data->saved_path = strdup(path); + if (path[0] == '/') { + data->saved_path = strdup(path); + } else { + data->saved_path = malloc(strlen(path) + strlen(nfs->cwd) + 2); + if (data->saved_path == NULL) { + rpc_set_error(nfs->rpc, "out of memory: failed to " + "malloc path string"); + free_nfs_cb_data(data); + return -1; + } + sprintf(data->saved_path, "%s/%s", nfs->cwd, path); + } + if (data->saved_path == NULL) { rpc_set_error(nfs->rpc, "out of memory: failed to copy path string"); free_nfs_cb_data(data); return -1; } + if (nfs_normalize_path(nfs, data->saved_path) != 0) { + free_nfs_cb_data(data); + return -1; + } + data->path = data->saved_path; if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) { @@ -713,7 +1150,11 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat GETATTR3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; +#ifdef WIN32 + struct __stat64 st; +#else struct stat st; +#endif assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -753,7 +1194,7 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat #ifndef WIN32 st.st_blksize = 4096; st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / 4096; -#endif//WIN32 +#endif//WIN32 st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds; st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds; st.st_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds; @@ -764,7 +1205,12 @@ static void nfs_stat_1_cb(struct rpc_context *rpc, int status, void *command_dat static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { - if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &data->fh, data) != 0) { + struct GETATTR3args args; + + memset(&args, 0, sizeof(GETATTR3args)); + args.object = data->fh; + + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat_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); @@ -785,11 +1231,58 @@ int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *p - - /* * Async open() */ +static void nfs_open_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); + 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: 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); + return; + } + + nfsfh = malloc(sizeof(struct nfsfh)); + if (nfsfh == NULL) { + rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure"); + data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return; + } + memset(nfsfh, 0, sizeof(struct nfsfh)); + + if (data->continue_int & O_SYNC) { + nfsfh->is_sync = 1; + } + + /* steal the filehandle */ + nfsfh->fh = data->fh; + data->fh.data.data_val = NULL; + + data->cb(0, nfs, nfsfh, data->private_data); + free_nfs_cb_data(data); +} + static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) { ACCESS3res *res; @@ -843,6 +1336,28 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, return; } + /* Try to truncate it if we were requested to */ + if ((data->continue_int & O_TRUNC) && + (data->continue_int & (O_RDWR|O_WRONLY))) { + SETATTR3args args; + + memset(&args, 0, sizeof(SETATTR3args)); + args.object = data->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_open_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); + return; + } + return; + } + nfsfh = malloc(sizeof(struct nfsfh)); if (nfsfh == NULL) { rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure"); @@ -857,8 +1372,7 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, } /* steal the filehandle */ - nfsfh->fh.data.data_len = data->fh.data.data_len; - nfsfh->fh.data.data_val = data->fh.data.data_val; + nfsfh->fh = data->fh; data->fh.data.data_val = NULL; data->cb(0, nfs, nfsfh, data->private_data); @@ -868,6 +1382,7 @@ static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { int nfsmode = 0; + ACCESS3args args; if (data->continue_int & O_WRONLY) { nfsmode |= ACCESS3_MODIFY; @@ -879,18 +1394,24 @@ static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_dat nfsmode |= ACCESS3_READ; } - if (rpc_nfs_access_async(nfs->rpc, nfs_open_cb, &data->fh, nfsmode, data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path); - data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); + memset(&args, 0, sizeof(ACCESS3args)); + args.object = data->fh; + args.access = nfsmode; + + if (rpc_nfs3_access_async(nfs->rpc, nfs_open_cb, &args, data) != 0) { + rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS " + "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_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) +int nfs_open_async(struct nfs_context *nfs, const char *path, int flags, nfs_cb cb, void *private_data) { - if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, mode) != 0) { + if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, flags) != 0) { rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -899,7 +1420,31 @@ int nfs_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb c } +/* + * Async chdir() + */ +static int nfs_chdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) +{ + /* steal saved_path */ + free(nfs->cwd); + nfs->cwd = data->saved_path; + data->saved_path = NULL; + data->cb(0, nfs, NULL, data->private_data); + free_nfs_cb_data(data); + + return 0; +} + +int nfs_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) +{ + if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chdir_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; +} /* @@ -1017,7 +1562,14 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse nfsfh->offset = offset; if (count <= nfs_get_readmax(nfs)) { - if (rpc_nfs_read_async(nfs->rpc, nfs_pread_cb, &nfsfh->fh, offset, count, data) != 0) { + 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); @@ -1028,7 +1580,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; @@ -1044,6 +1596,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse while (count > 0) { uint64_t readcount = count; struct nfs_mcb_data *mdata; + READ3args args; if (readcount > nfs_get_readmax(nfs)) { readcount = nfs_get_readmax(nfs); @@ -1058,7 +1611,13 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse mdata->data = data; mdata->offset = offset; mdata->count = readcount; - if (rpc_nfs_read_async(nfs->rpc, nfs_pread_mcb, &nfsfh->fh, offset, readcount, mdata) != 0) { + + memset(&args, 0, sizeof(READ3args)); + args.file = nfsfh->fh; + args.offset = offset; + args.count = 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); @@ -1197,7 +1756,17 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs nfsfh->offset = offset; if (count <= nfs_get_writemax(nfs)) { - if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_cb, &nfsfh->fh, buf, offset, count, nfsfh->is_sync?FILE_SYNC:UNSTABLE, data) != 0) { + 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); @@ -1206,9 +1775,13 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs return 0; } + /* hello, clang-analyzer */ + assert(count > 0); + assert(data->num_calls == 0); + /* 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; @@ -1216,6 +1789,7 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs while (count > 0) { uint64_t writecount = count; struct nfs_mcb_data *mdata; + WRITE3args args; if (writecount > nfs_get_writemax(nfs)) { writecount = nfs_get_writemax(nfs); @@ -1224,6 +1798,8 @@ 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"); + if (data->num_calls == 0) + free_nfs_cb_data(data); return -1; } memset(mdata, 0, sizeof(struct nfs_mcb_data)); @@ -1231,10 +1807,21 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offs mdata->offset = offset; mdata->count = writecount; - if (rpc_nfs_write_async(nfs->rpc, nfs_pwrite_mcb, &nfsfh->fh, &buf[offset - data->start_offset], offset, writecount, nfsfh->is_sync?FILE_SYNC:UNSTABLE, mdata) != 0) { + 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]; + + 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); + if (data->num_calls == 0) + free_nfs_cb_data(data); + return -1; } @@ -1260,7 +1847,7 @@ int nfs_write_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t count /* * close */ - + int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { if (nfsfh->fh.data.data_val != NULL){ @@ -1283,6 +1870,7 @@ int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; + struct GETATTR3args args; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { @@ -1294,7 +1882,10 @@ int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi data->cb = cb; data->private_data = private_data; - if (rpc_nfs_getattr_async(nfs->rpc, nfs_stat_1_cb, &nfsfh->fh, data) != 0) { + memset(&args, 0, sizeof(GETATTR3args)); + args.object = nfsfh->fh; + + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat_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); @@ -1342,6 +1933,7 @@ static void nfs_fsync_cb(struct rpc_context *rpc, int status, void *command_data int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; + struct COMMIT3args args; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { @@ -1353,7 +1945,10 @@ int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi data->cb = cb; data->private_data = private_data; - if (rpc_nfs_commit_async(nfs->rpc, nfs_fsync_cb, &nfsfh->fh, data) != 0) { + args.file = nfsfh->fh; + args.offset = 0; + args.count = 0; + if (rpc_nfs3_commit_async(nfs->rpc, nfs_fsync_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send COMMIT call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -1415,12 +2010,11 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t l data->private_data = private_data; memset(&args, 0, sizeof(SETATTR3args)); - args.object.data.data_len = nfsfh->fh.data.data_len; - args.object.data.data_val = nfsfh->fh.data.data_val; + args.object = nfsfh->fh; args.new_attributes.size.set_it = 1; args.new_attributes.size.set_size3_u.size = length; - if (rpc_nfs_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) { + if (rpc_nfs3_setattr_async(nfs->rpc, nfs_ftruncate_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); @@ -1438,8 +2032,7 @@ static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb uint64_t offset = data->continue_int; struct nfsfh nfsfh; - nfsfh.fh.data.data_val = data->fh.data.data_val; - nfsfh.fh.data.data_len = data->fh.data.data_len; + nfsfh.fh = data->fh; if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path); @@ -1477,7 +2070,7 @@ static void nfs_mkdir_cb(struct rpc_context *rpc, int status, void *command_data 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]; @@ -1513,13 +2106,12 @@ static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_da str = &str[strlen(str) + 1]; 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.dir = data->fh; 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) { + if (rpc_nfs3_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); @@ -1541,6 +2133,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; } @@ -1568,7 +2161,7 @@ static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data 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]; @@ -1599,10 +2192,13 @@ static void nfs_rmdir_cb(struct rpc_context *rpc, int status, void *command_data static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { char *str = data->continue_data; - + RMDIR3args args; + str = &str[strlen(str) + 1]; - if (rpc_nfs_rmdir_async(nfs->rpc, nfs_rmdir_cb, &data->fh, str, data) != 0) { + args.object.dir = data->fh; + args.object.name = str; + if (rpc_nfs3_rmdir_async(nfs->rpc, nfs_rmdir_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send RMDIR call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -1624,6 +2220,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; } @@ -1700,6 +2297,7 @@ static void nfs_creat_1_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; char *str = data->continue_data; + LOOKUP3args args; assert(rpc->magic == RPC_CONTEXT_MAGIC); @@ -1719,11 +2317,15 @@ 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; } - if (rpc_nfs_lookup_async(nfs->rpc, nfs_create_2_cb, &data->fh, str, data) != 0) { + memset(&args, 0, sizeof(LOOKUP3args)); + args.what.dir = data->fh; + args.what.name = str; + + if (rpc_nfs3_lookup_async(nfs->rpc, nfs_create_2_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s/%s", data->saved_path, str); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -1740,14 +2342,13 @@ static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_da str = &str[strlen(str) + 1]; 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.dir = data->fh; 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) { + if (rpc_nfs3_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); @@ -1770,6 +2371,7 @@ int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb ptr = strrchr(new_path, '/'); if (ptr == NULL) { rpc_set_error(nfs->rpc, "Invalid path %s", path); + free(new_path); return -1; } *ptr = 0; @@ -1795,7 +2397,7 @@ static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_dat 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]; @@ -1826,10 +2428,13 @@ static void nfs_unlink_cb(struct rpc_context *rpc, int status, void *command_dat static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { char *str = data->continue_data; - + struct REMOVE3args args; + str = &str[strlen(str) + 1]; - if (rpc_nfs_remove_async(nfs->rpc, nfs_unlink_cb, &data->fh, str, data) != 0) { + args.object.dir = data->fh; + args.object.name = str; + if (rpc_nfs3_remove_async(nfs->rpc, nfs_unlink_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send REMOVE call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -1851,6 +2456,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; } @@ -1890,7 +2496,7 @@ static void nfs_mknod_cb(struct rpc_context *rpc, int status, void *command_data 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]; @@ -1922,10 +2528,44 @@ static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_da { struct mknod_cb_data *cb_data = data->continue_data; char *str = cb_data->path; - + MKNOD3args args; + 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) { + args.where.dir = data->fh; + args.where.name = str; + switch (cb_data->mode & S_IFMT) { + case S_IFCHR: + args.what.type = NF3CHR; + args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_it = 1; + args.what.mknoddata3_u.chr_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); + args.what.mknoddata3_u.chr_device.spec.specdata1 = cb_data->major; + args.what.mknoddata3_u.chr_device.spec.specdata2 = cb_data->minor; + break; + case S_IFBLK: + args.what.type = NF3BLK; + args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_it = 1; + args.what.mknoddata3_u.blk_device.dev_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); + args.what.mknoddata3_u.blk_device.spec.specdata1 = cb_data->major; + args.what.mknoddata3_u.blk_device.spec.specdata2 = cb_data->minor; + case S_IFSOCK: + args.what.type = NF3SOCK; + args.what.mknoddata3_u.sock_attributes.mode.set_it = 1; + args.what.mknoddata3_u.sock_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); + break; + case S_IFIFO: + args.what.type = NF3FIFO; + args.what.mknoddata3_u.pipe_attributes.mode.set_it = 1; + args.what.mknoddata3_u.pipe_attributes.mode.set_mode3_u.mode = cb_data->mode & (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH); + break; + default: + rpc_set_error(nfs->rpc, "Invalid file type for NFS3/MKNOD call"); + data->cb(-EINVAL, nfs, rpc_get_error(nfs->rpc), data->private_data); + free_nfs_cb_data(data); + return -1; + } + + if (rpc_nfs3_mknod_async(nfs->rpc, nfs_mknod_cb, &args, data) != 0) { data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); return -1; @@ -1947,13 +2587,14 @@ int nfs_mknod_async(struct nfs_context *nfs, const char *path, int mode, int dev 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); + free(cb_data); return -1; } ptr = strrchr(cb_data->path, '/'); if (ptr == NULL) { rpc_set_error(nfs->rpc, "Invalid path %s", path); + free_mknod_cb_data(cb_data); return -1; } *ptr = 0; @@ -1965,7 +2606,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; } @@ -2029,6 +2669,8 @@ static void nfs_opendir3_cb(struct rpc_context *rpc, int status, void *command_d nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000; nfsdirent->ctime.tv_sec = attributes->ctime.seconds; nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000; + nfsdirent->uid = attributes->uid; + nfsdirent->gid = attributes->gid; } } @@ -2054,9 +2696,9 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d struct nfsdir *nfsdir = data->continue_data; struct nfsdirent *nfsdirent; struct entry3 *entry; - uint64_t cookie; + uint64_t cookie = 0; struct rdpe_cb_data *rdpe_cb_data; - + assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status == RPC_STATUS_ERROR) { @@ -2098,6 +2740,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); @@ -2113,7 +2756,14 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d } 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) { + READDIR3args args; + + args.dir = data->fh; + args.cookie = cookie; + memcpy(&args.cookieverf, res->READDIR3res_u.resok.cookieverf, sizeof(cookieverf3)); + args.count = 8192; + + if (rpc_nfs3_readdir_async(nfs->rpc, nfs_opendir2_cb, &args, 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); @@ -2133,18 +2783,26 @@ static void nfs_opendir2_cb(struct rpc_context *rpc, int status, void *command_d rdpe_cb_data->data = data; for (nfsdirent = nfsdir->entries; nfsdirent; nfsdirent = nfsdirent->next) { struct rdpe_lookup_cb_data *rdpe_lookup_cb_data; + LOOKUP3args args; 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) { + memset(&args, 0, sizeof(LOOKUP3args)); + args.what.dir = data->fh; + args.what.name = nfsdirent->name; + + if (rpc_nfs3_lookup_async(nfs->rpc, nfs_opendir3_cb, &args, 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) { + 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; @@ -2162,7 +2820,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; @@ -2170,14 +2827,19 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da struct nfs_context *nfs = data->nfs; struct nfsdir *nfsdir = data->continue_data; struct entryplus3 *entry; - uint64_t cookie; - + uint64_t cookie = 0; + assert(rpc->magic == RPC_CONTEXT_MAGIC); if (status == RPC_STATUS_ERROR || (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) ){ - cookieverf3 cv; + READDIR3args args; + + args.dir = data->fh; + args.cookie = cookie; + memset(&args.cookieverf, 0, sizeof(cookieverf3)); + args.count = 8192; - if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) { + if (rpc_nfs3_readdir_async(nfs->rpc, nfs_opendir2_cb, &args, 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); @@ -2221,6 +2883,7 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da 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); @@ -2238,6 +2901,8 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da nfsdirent->mtime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.mtime.nseconds/1000; nfsdirent->ctime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.ctime.seconds; nfsdirent->ctime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.ctime.nseconds/1000; + nfsdirent->uid = entry->name_attributes.post_op_attr_u.attributes.uid; + nfsdirent->gid = entry->name_attributes.post_op_attr_u.attributes.gid; } nfsdirent->next = nfsdir->entries; @@ -2248,7 +2913,15 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da } if (res->READDIRPLUS3res_u.resok.reply.eof == 0) { - if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIRPLUS3res_u.resok.cookieverf, 8192, data) != 0) { + READDIRPLUS3args args; + + args.dir = data->fh; + args.cookie = cookie; + memcpy(&args.cookieverf, res->READDIRPLUS3res_u.resok.cookieverf, sizeof(cookieverf3)); + args.dircount = 8192; + args.maxcount = 8192; + + if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs_opendir_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); nfs_free_nfsdir(nfsdir); @@ -2269,10 +2942,14 @@ static void nfs_opendir_cb(struct rpc_context *rpc, int status, void *command_da static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { - cookieverf3 cv; - - memset(cv, 0, sizeof(cookieverf3)); - if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) { + READDIRPLUS3args args; + + args.dir = data->fh; + args.cookie = 0; + memset(&args.cookieverf, 0, sizeof(cookieverf3)); + args.dircount = 8192; + args.maxcount = 8192; + if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs_opendir_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -2312,15 +2989,24 @@ struct nfsdirent *nfs_readdir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir } +/* + * closedir() + */ void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir) { nfs_free_nfsdir(nfsdir); } - - - +/* + * getcwd() + */ +void nfs_getcwd(struct nfs_context *nfs, const char **cwd) +{ + if (cwd) { + *cwd = nfs->cwd; + } +} /* @@ -2369,6 +3055,7 @@ static void nfs_lseek_1_cb(struct rpc_context *rpc, int status, void *command_da 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; + struct GETATTR3args args; if (whence == SEEK_SET) { nfsfh->offset = offset; @@ -2393,7 +3080,10 @@ int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t offse data->cb = cb; data->private_data = private_data; - if (rpc_nfs_getattr_async(nfs->rpc, nfs_lseek_1_cb, &nfsfh->fh, data) != 0) { + memset(&args, 0, sizeof(GETATTR3args)); + args.object = nfsfh->fh; + + if (rpc_nfs3_getattr_async(nfs->rpc, nfs_lseek_1_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send LSEEK GETATTR call"); free(data); return -1; @@ -2455,7 +3145,10 @@ static void nfs_statvfs_1_cb(struct rpc_context *rpc, int status, void *command_ static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { - if (rpc_nfs_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &data->fh, data) != 0) { + FSSTAT3args args; + + args.fsroot = data->fh; + if (rpc_nfs3_fsstat_async(nfs->rpc, nfs_statvfs_1_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send FSSTAT call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -2507,7 +3200,7 @@ static void nfs_readlink_1_cb(struct rpc_context *rpc, int status, void *command return; } - + data->cb(0, nfs, res->READLINK3res_u.resok.data, data->private_data); free_nfs_cb_data(data); } @@ -2516,10 +3209,9 @@ static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb { READLINK3args args; - args.symlink.data.data_len = data->fh.data.data_len; - args.symlink.data.data_val = data->fh.data.data_val; + args.symlink = data->fh; - if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) { + if (rpc_nfs3_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); @@ -2580,12 +3272,11 @@ static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_da SETATTR3args args; memset(&args, 0, sizeof(SETATTR3args)); - args.object.data.data_len = data->fh.data.data_len; - args.object.data.data_val = data->fh.data.data_val; + args.object = data->fh; args.new_attributes.mode.set_it = 1; args.new_attributes.mode.set_mode3_u.mode = data->continue_int; - if (rpc_nfs_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) { + if (rpc_nfs3_setattr_async(nfs->rpc, nfs_chmod_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); @@ -2632,7 +3323,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; } @@ -2686,8 +3376,7 @@ static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_da struct nfs_chown_data *chown_data = data->continue_data; memset(&args, 0, sizeof(SETATTR3args)); - args.object.data.data_len = data->fh.data.data_len; - args.object.data.data_val = data->fh.data.data_val; + args.object = data->fh; if (chown_data->uid != (uid_t)-1) { args.new_attributes.uid.set_it = 1; args.new_attributes.uid.set_uid3_u.uid = chown_data->uid; @@ -2697,7 +3386,7 @@ static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_da args.new_attributes.gid.set_gid3_u.gid = chown_data->gid; } - if (rpc_nfs_setattr_async(nfs->rpc, nfs_chown_cb, &args, data) != 0) { + if (rpc_nfs3_setattr_async(nfs->rpc, nfs_chown_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); @@ -2746,10 +3435,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)); @@ -2757,6 +3446,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) { @@ -2766,9 +3456,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; } @@ -2819,8 +3507,7 @@ static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_d struct timeval *utimes_data = data->continue_data; memset(&args, 0, sizeof(SETATTR3args)); - args.object.data.data_len = data->fh.data.data_len; - args.object.data.data_val = data->fh.data.data_val; + args.object = data->fh; if (utimes_data != NULL) { args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME; args.new_attributes.atime.set_atime_u.atime.seconds = utimes_data[0].tv_sec; @@ -2833,7 +3520,7 @@ static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_d args.new_attributes.mtime.set_it = SET_TO_SERVER_TIME; } - if (rpc_nfs_setattr_async(nfs->rpc, nfs_utimes_cb, &args, data) != 0) { + if (rpc_nfs3_setattr_async(nfs->rpc, nfs_utimes_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); @@ -2955,6 +3642,7 @@ static void nfs_access_cb(struct rpc_context *rpc, int status, void *command_dat static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { int nfsmode = 0; + ACCESS3args args; if (data->continue_int & R_OK) { nfsmode |= ACCESS3_READ; @@ -2966,7 +3654,11 @@ static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_d nfsmode |= ACCESS3_EXECUTE; } - if (rpc_nfs_access_async(nfs->rpc, nfs_access_cb, &data->fh, nfsmode, data) != 0) { + memset(&args, 0, sizeof(ACCESS3args)); + args.object = data->fh; + args.access = nfsmode; + + if (rpc_nfs3_access_async(nfs->rpc, nfs_access_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -3018,7 +3710,7 @@ static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_da 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) { @@ -3047,17 +3739,16 @@ static void nfs_symlink_cb(struct rpc_context *rpc, int status, void *command_da 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; + SYMLINK3args args; - 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; + memset(&args, 0, sizeof(SYMLINK3args)); + args.where.dir = data->fh; + args.where.name = symlink_data->newpathobject; + args.symlink.symlink_attributes.mode.set_it = 1; + args.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; + args.symlink.symlink_data = symlink_data->oldpath; - if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &sa, data) != 0) { + if (rpc_nfs3_symlink_async(nfs->rpc, nfs_symlink_cb, &args, 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); @@ -3155,7 +3846,7 @@ static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_dat 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) { @@ -3184,13 +3875,17 @@ static void nfs_rename_cb(struct rpc_context *rpc, int status, void *command_dat static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { struct nfs_rename_data *rename_data = data->continue_data; + RENAME3args args; /* steal the filehandle */ - rename_data->newdir.data.data_len = data->fh.data.data_len; - rename_data->newdir.data.data_val = data->fh.data.data_val; + rename_data->newdir = data->fh; data->fh.data.data_val = NULL; - if (rpc_nfs_rename_async(nfs->rpc, nfs_rename_cb, &rename_data->olddir, rename_data->oldobject, &rename_data->newdir, rename_data->newobject, data) != 0) { + args.from.dir = rename_data->olddir; + args.from.name = rename_data->oldobject; + args.to.dir = rename_data->newdir; + args.to.name = rename_data->newobject; + if (rpc_nfs3_rename_async(nfs->rpc, nfs_rename_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send RENAME call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -3203,20 +3898,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.data_len = data->fh.data.data_len; - rename_data->olddir.data.data_val = data->fh.data.data_val; + 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; } @@ -3313,7 +4016,7 @@ static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data, 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) { @@ -3342,13 +4045,17 @@ static void nfs_link_cb(struct rpc_context *rpc, int status, void *command_data, static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data) { struct nfs_link_data *link_data = data->continue_data; + LINK3args args; /* steal the filehandle */ - link_data->newdir.data.data_len = data->fh.data.data_len; - link_data->newdir.data.data_val = data->fh.data.data_val; + link_data->newdir = data->fh; data->fh.data.data_val = NULL; - if (rpc_nfs_link_async(nfs->rpc, nfs_link_cb, &link_data->oldfh, &link_data->newdir, link_data->newobject, data) != 0) { + memset(&args, 0, sizeof(LINK3args)); + args.file = link_data->oldfh; + args.link.dir = link_data->newdir; + args.link.name = link_data->newobject; + if (rpc_nfs3_link_async(nfs->rpc, nfs_link_cb, &args, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send LINK call for %s", data->path); data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data); free_nfs_cb_data(data); @@ -3363,8 +4070,7 @@ static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_d struct nfs_link_data *link_data = data->continue_data; /* steal the filehandle */ - link_data->oldfh.data.data_len = data->fh.data.data_len; - link_data->oldfh.data.data_val = data->fh.data.data_val; + link_data->oldfh = data->fh; data->fh.data.data_val = NULL; if (nfs_lookuppath_async(nfs, link_data->newpath, data->cb, data->private_data, nfs_link_continue_2_internal, link_data, free_nfs_link_data, 0) != 0) { @@ -3446,11 +4152,19 @@ 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_tcp_syncnt(struct nfs_context *nfs, int v) { + rpc_set_tcp_syncnt(nfs->rpc, v); +} + +void nfs_set_uid(struct nfs_context *nfs, int uid) { + rpc_set_uid(nfs->rpc, uid); +} + +void nfs_set_gid(struct nfs_context *nfs, int gid) { + rpc_set_gid(nfs->rpc, gid); } void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) @@ -3465,7 +4179,7 @@ void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) free(nfs->rpc->error_string); } nfs->rpc->error_string = str; - va_end(ap); + va_end(ap); } @@ -3519,7 +4233,7 @@ static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command /* Dont want any more callbacks even if the socket is closed */ rpc->connect_cb = NULL; - if (status == RPC_STATUS_ERROR) { + if (status == RPC_STATUS_ERROR) { data->cb(rpc, -EFAULT, command_data, data->private_data); free_mount_cb_data(data); return; @@ -3530,7 +4244,7 @@ static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command return; } - if (rpc_mount_export_async(rpc, mount_export_5_cb, data) != 0) { + if (rpc_mount3_export_async(rpc, mount_export_5_cb, data) != 0) { data->cb(rpc, -ENOMEM, command_data, data->private_data); free_mount_cb_data(data); return; @@ -3639,7 +4353,7 @@ int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb c if (data->server == NULL) { free_mount_cb_data(data); return -1; - } + } if (rpc_connect_async(rpc, data->server, 111, mount_export_1_cb, data) != 0) { free_mount_cb_data(data); return -1;