X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=af7dd0c55857215bec1153a9077134ca491bfde4;hb=7cd23ccc676f7438de933d55ba081d99b79bd735;hp=f8b294a5589ebcffba9a0b8d9e7f345ab8788469;hpb=c5e346e15c043a6253cc5a838dd9c77febf624aa;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index f8b294a..af7dd0c 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -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; @@ -219,6 +372,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) { @@ -275,6 +577,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 +595,11 @@ 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.data.data_len = nfs->rootfh.data.data_len; + args.object.data.data_val = nfs->rootfh.data.data_val; + + 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 +610,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 +625,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 +655,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 +729,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 +757,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; @@ -625,6 +934,7 @@ 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; + LOOKUP3args args; while (*data->path == '/') { data->path++; @@ -655,7 +965,13 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb 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.data.data_len = fh->data.data_len; + args.what.dir.data.data_val = fh->data.data_val; + 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); @@ -764,7 +1080,13 @@ 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.data_len = data->fh.data.data_len; + args.object.data.data_val = data->fh.data.data_val; + + 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); @@ -868,6 +1190,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,7 +1202,12 @@ 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) { + memset(&args, 0, sizeof(ACCESS3args)); + args.object.data.data_len = data->fh.data.data_len; + args.object.data.data_val = data->fh.data.data_val; + 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); @@ -1017,7 +1345,15 @@ 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.data.data_len = nfsfh->fh.data.data_len; + args.file.data.data_val = nfsfh->fh.data.data_val; + 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 +1364,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 +1380,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 +1395,14 @@ 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.data.data_len = nfsfh->fh.data.data_len; + args.file.data.data_val = nfsfh->fh.data.data_val; + 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 +1541,18 @@ 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.data.data_len = nfsfh->fh.data.data_len; + args.file.data.data_val = nfsfh->fh.data.data_val; + 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); @@ -1208,7 +1563,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; @@ -1216,6 +1571,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); @@ -1231,7 +1587,16 @@ 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.data.data_len = nfsfh->fh.data.data_len; + args.file.data.data_val = nfsfh->fh.data.data_val; + 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); @@ -1283,6 +1648,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 +1660,11 @@ 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.data.data_len = nfsfh->fh.data.data_len; + args.object.data.data_val = nfsfh->fh.data.data_val; + + 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 +1712,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 +1724,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); @@ -1420,7 +1794,7 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, uint64_t l 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); @@ -1519,7 +1893,7 @@ static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_da 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); @@ -1599,10 +1973,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); @@ -1700,6 +2077,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 +2097,16 @@ 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.data_len = data->fh.data.data_len; + args.what.dir.data.data_val = data->fh.data.data_val; + 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); @@ -1747,7 +2130,7 @@ static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_da 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); @@ -1826,10 +2209,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); @@ -1922,10 +2308,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; @@ -2133,12 +2553,18 @@ 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.data_len = data->fh.data.data_len; + args.what.dir.data.data_val = data->fh.data.data_val; + 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 @@ -2369,6 +2795,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 +2820,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 +2885,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); @@ -2519,7 +2952,7 @@ static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb 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) { + 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); @@ -2585,7 +3018,7 @@ static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_da 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); @@ -2697,7 +3130,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); @@ -2833,7 +3266,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 +3388,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 +3400,12 @@ 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.data_len = data->fh.data.data_len; + args.object.data.data_val = data->fh.data.data_val; + 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); @@ -3047,17 +3486,17 @@ 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.data_len = data->fh.data.data_len; + args.where.dir.data.data_val = data->fh.data.data_val; + 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); @@ -3184,13 +3623,18 @@ 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; 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); @@ -3342,13 +3786,18 @@ 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; 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); @@ -3446,11 +3895,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, ...) @@ -3530,7 +3975,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;