X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=lib%2Flibnfs.c;h=eee5d5a6dbb8e4b6c8f755f7adbe2129289d35e6;hb=41d82d7d825b9b4e73bb227f5b2fafa86067cba0;hp=6687180a66de7abeab7fb1a76e1a7049893f4fe2;hpb=921f877be4ac27e50e60dfa855513612c1103388;p=deb_libnfs.git diff --git a/lib/libnfs.c b/lib/libnfs.c index 6687180..eee5d5a 100644 --- a/lib/libnfs.c +++ b/lib/libnfs.c @@ -18,21 +18,39 @@ * High level api to nfs filesystems */ +#define _GNU_SOURCE + +#if defined(WIN32) +#include +#define DllExport +#define O_SYNC 0 +typedef int uid_t; +typedef int gid_t; +#else +#include +#include +#include +#include +#endif + #include +#include #include #include -#include #include #include #include -#include -#include -#include #include #include "libnfs.h" #include "libnfs-raw.h" #include "libnfs-raw-mount.h" #include "libnfs-raw-nfs.h" +#include "libnfs-private.h" + +struct nfsdir { + struct nfsdirent *entries; + struct nfsdirent *current; +}; struct nfsfh { struct nfs_fh3 fh; @@ -40,9 +58,13 @@ struct nfsfh { off_t offset; }; -struct nfsdir { - struct nfsdirent *entries; - struct nfsdirent *current; +struct nfs_context { + struct rpc_context *rpc; + char *server; + char *export; + struct nfs_fh3 rootfh; + size_t readmax; + size_t writemax; }; void nfs_free_nfsdir(struct nfsdir *nfsdir) @@ -58,15 +80,6 @@ void nfs_free_nfsdir(struct nfsdir *nfsdir) free(nfsdir); } -struct nfs_context { - struct rpc_context *rpc; - char *server; - char *export; - struct nfs_fh3 rootfh; - size_t readmax; - size_t writemax; -}; - struct nfs_cb_data; typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data); @@ -104,7 +117,7 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth) { - return rpc_set_auth(nfs->rpc, auth); + rpc_set_auth(nfs->rpc, auth); } int nfs_get_fd(struct nfs_context *nfs) @@ -133,16 +146,20 @@ struct nfs_context *nfs_init_context(void) nfs = malloc(sizeof(struct nfs_context)); if (nfs == NULL) { - printf("Failed to allocate nfs context\n"); return NULL; } nfs->rpc = rpc_init_context(); if (nfs->rpc == NULL) { - printf("Failed to allocate rpc sub-context\n"); free(nfs); return NULL; } + nfs->server = NULL; + nfs->export = NULL; + + nfs->rootfh.data.data_len = 0; + nfs->rootfh.data.data_val = NULL; + return nfs; } @@ -469,24 +486,34 @@ static void nfs_mount_1_cb(struct rpc_context *rpc, int status, void *command_da int nfs_mount_async(struct nfs_context *nfs, const char *server, const char *export, nfs_cb cb, void *private_data) { struct nfs_cb_data *data; + char *new_server, *new_export; data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { - rpc_set_error(nfs->rpc, "out of memory"); - printf("failed to allocate memory for nfs mount data\n"); + rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); - nfs->server = strdup(server); - nfs->export = strdup(export); + new_server = strdup(server); + new_export = strdup(export); + if (nfs->server != NULL) { + free(nfs->server); + nfs->server = NULL; + } + nfs->server = new_server; + if (nfs->export != NULL) { + free(nfs->export); + nfs->export = NULL; + } + nfs->export = new_export; data->nfs = nfs; data->cb = cb; data->private_data = private_data; if (rpc_connect_async(nfs->rpc, server, 111, nfs_mount_1_cb, data) != 0) { - printf("Failed to start connection\n"); + rpc_set_error(nfs->rpc, "Failed to start connection"); free_nfs_cb_data(data); - return -4; + return -1; } return 0; @@ -540,7 +567,7 @@ static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb } path = data->path; - str = index(path, '/'); + str = strchr(path, '/'); if (str != NULL) { *str = 0; data->path = str+1; @@ -585,8 +612,7 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c 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"); - printf("failed to allocate memory for nfs cb data\n"); - return -2; + return -1; } bzero(data, sizeof(struct nfs_cb_data)); data->nfs = nfs; @@ -599,14 +625,12 @@ static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_c data->saved_path = strdup(path); if (data->saved_path == NULL) { rpc_set_error(nfs->rpc, "out of memory: failed to copy path string"); - printf("failed to allocate memory for path string\n"); free_nfs_cb_data(data); - return -2; + return -1; } data->path = data->saved_path; if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) { - printf("failed to lookup path\n"); /* return 0 here since the callback will be invoked if there is a failure */ return 0; } @@ -649,13 +673,18 @@ static void nfs_stat_1_cb(struct rpc_context *rpc _U_, int status, void *command st.st_dev = -1; st.st_ino = res->GETATTR3res_u.resok.obj_attributes.fileid; st.st_mode = res->GETATTR3res_u.resok.obj_attributes.mode; + if (res->GETATTR3res_u.resok.obj_attributes.type == NF3DIR) { + st.st_mode |= S_IFDIR ; + } st.st_nlink = res->GETATTR3res_u.resok.obj_attributes.nlink; st.st_uid = res->GETATTR3res_u.resok.obj_attributes.uid; st.st_gid = res->GETATTR3res_u.resok.obj_attributes.gid; st.st_rdev = 0; st.st_size = res->GETATTR3res_u.resok.obj_attributes.size; +#if !defined(WIN32) st.st_blksize = 4096; st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / 4096; +#endif 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; @@ -678,7 +707,7 @@ static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_dat int nfs_stat_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_stat_continue_internal, NULL, NULL, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -791,8 +820,8 @@ static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_dat int nfs_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, mode) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -2; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -859,10 +888,12 @@ static void nfs_pread_mcb(struct rpc_context *rpc _U_, int status, void *command if (res->status != NFS3_OK) { rpc_set_error(nfs->rpc, "NFS: Read failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status)); data->error = 1; - } else { - memcpy(&data->buffer[mdata->offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count); - if (data->max_offset < mdata->offset + res->READ3res_u.resok.count) { - data->max_offset = mdata->offset + res->READ3res_u.resok.count; + } else { + if (res->READ3res_u.resok.count > 0) { + memcpy(&data->buffer[mdata->offset - data->start_offset], res->READ3res_u.resok.data.data_val, res->READ3res_u.resok.count); + if ((unsigned)data->max_offset < mdata->offset + res->READ3res_u.resok.count) { + data->max_offset = mdata->offset + res->READ3res_u.resok.count; + } } } } @@ -873,7 +904,6 @@ static void nfs_pread_mcb(struct rpc_context *rpc _U_, int status, void *command return; } - if (data->error != 0) { data->cb(-EFAULT, nfs, command_data, data->private_data); free_nfs_cb_data(data); @@ -889,6 +919,7 @@ static void nfs_pread_mcb(struct rpc_context *rpc _U_, int status, void *command data->nfsfh->offset = data->max_offset; data->cb(data->max_offset - data->start_offset, nfs, data->buffer, data->private_data); + free_nfs_cb_data(data); free(mdata); } @@ -900,7 +931,6 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, 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"); - printf("failed to allocate memory for nfs cb data\n"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -925,6 +955,7 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, * reads and collect into a reassembly buffer. * we send all reads in parallell so that performance is still good. */ + data->max_offset = offset; data->start_offset = offset; data->buffer = malloc(count); @@ -946,14 +977,12 @@ int nfs_pread_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, 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"); - printf("failed to allocate memory for nfs mcb data\n"); return -1; } bzero(mdata, sizeof(struct nfs_mcb_data)); 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) { 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); @@ -1019,7 +1048,6 @@ int nfs_pwrite_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, 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"); - printf("failed to allocate memory for nfs cb data\n"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -1079,7 +1107,6 @@ int nfs_fstat_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi 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"); - printf("failed to allocate memory for nfs cb data\n"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -1137,7 +1164,6 @@ int nfs_fsync_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, voi 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"); - printf("failed to allocate memory for nfs cb data\n"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -1197,7 +1223,6 @@ int nfs_ftruncate_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t leng 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"); - printf("failed to allocate memory for nfs cb data\n"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -1249,8 +1274,8 @@ int nfs_truncate_async(struct nfs_context *nfs, const char *path, off_t length, offset = length; if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_truncate_continue_internal, NULL, NULL, offset) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -2; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -1316,21 +1341,21 @@ int nfs_mkdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * new_path = strdup(path); if (new_path == NULL) { - printf("Out of memory, failed to allocate mode buffer for path\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path"); return -1; } - ptr = rindex(new_path, '/'); + ptr = strrchr(new_path, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", path); - return -2; + rpc_set_error(nfs->rpc, "Invalid path %s", path); + return -1; } *ptr = 0; /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */ if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_mkdir_continue_internal, new_path, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -3; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path component"); + return -1; } return 0; @@ -1397,21 +1422,21 @@ int nfs_rmdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void * new_path = strdup(path); if (new_path == NULL) { - printf("Out of memory, failed to allocate mode buffer for path\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path"); return -1; } - ptr = rindex(new_path, '/'); + ptr = strrchr(new_path, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", path); - return -2; + rpc_set_error(nfs->rpc, "Invalid path %s", path); + return -1; } *ptr = 0; /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */ if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_rmdir_continue_internal, new_path, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -3; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -1529,21 +1554,21 @@ int nfs_creat_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb new_path = strdup(path); if (new_path == NULL) { - printf("Out of memory, failed to allocate mode buffer for path\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path"); return -1; } - ptr = rindex(new_path, '/'); + ptr = strrchr(new_path, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", path); - return -2; + rpc_set_error(nfs->rpc, "Invalid path %s", path); + return -1; } *ptr = 0; /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */ if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_creat_continue_internal, new_path, free, mode) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -3; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -1609,21 +1634,21 @@ int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void new_path = strdup(path); if (new_path == NULL) { - printf("Out of memory, failed to allocate mode buffer for path\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path"); return -1; } - ptr = rindex(new_path, '/'); + ptr = strrchr(new_path, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", path); - return -2; + rpc_set_error(nfs->rpc, "Invalid path %s", path); + return -1; } *ptr = 0; /* new_path now points to the parent directory, and beyond the nul terminateor is the new directory to create */ if (nfs_lookuppath_async(nfs, new_path, cb, private_data, nfs_unlink_continue_internal, new_path, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -3; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -1638,13 +1663,13 @@ int nfs_unlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void */ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *command_data, void *private_data) { - READDIR3res *res; + READDIRPLUS3res *res; struct nfs_cb_data *data = private_data; struct nfs_context *nfs = data->nfs; - struct nfsdir *nfsdir = data->continue_data;; - struct entry3 *entry; + struct nfsdir *nfsdir = data->continue_data; + struct entryplus3 *entry; uint64_t cookie; - + if (status == RPC_STATUS_ERROR) { data->cb(-EFAULT, nfs, command_data, data->private_data); nfs_free_nfsdir(nfsdir); @@ -1670,7 +1695,7 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman return; } - entry =res->READDIR3res_u.resok.reply.entries; + entry =res->READDIRPLUS3res_u.resok.reply.entries; while (entry != NULL) { struct nfsdirent *nfsdirent; @@ -1692,6 +1717,19 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman return; } nfsdirent->inode = entry->fileid; + if (entry->name_attributes.attributes_follow) { + nfsdirent->type = entry->name_attributes.post_op_attr_u.attributes.type; + nfsdirent->mode = entry->name_attributes.post_op_attr_u.attributes.mode; + nfsdirent->size = entry->name_attributes.post_op_attr_u.attributes.size; + + nfsdirent->atime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.atime.seconds; + nfsdirent->atime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.atime.nseconds/1000; + nfsdirent->mtime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.mtime.seconds; + 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->next = nfsdir->entries; nfsdir->entries = nfsdirent; @@ -1699,9 +1737,9 @@ static void nfs_opendir_cb(struct rpc_context *rpc _U_, int status, void *comman entry = entry->nextentry; } - if (res->READDIR3res_u.resok.reply.eof == 0) { - if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 20000, data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path); + 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) { + 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); data->continue_data = NULL; @@ -1724,8 +1762,8 @@ static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_ cookieverf3 cv; bzero(cv, sizeof(cookieverf3)); - if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 20000, data) != 0) { - rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path); + if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, 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); return -1; @@ -1739,14 +1777,14 @@ int nfs_opendir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void nfsdir = malloc(sizeof(struct nfsdir)); if (nfsdir == NULL) { - printf("failed to allocate buffer for nfsdir\n"); + rpc_set_error(nfs->rpc, "failed to allocate buffer for nfsdir"); return -1; } bzero(nfsdir, sizeof(struct nfsdir)); if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_opendir_continue_internal, nfsdir, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -2; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -1846,7 +1884,7 @@ int nfs_lseek_async(struct nfs_context *nfs, struct nfsfh *nfsfh, off_t offset, if (rpc_nfs_getattr_async(nfs->rpc, nfs_lseek_1_cb, &nfsfh->fh, data) != 0) { rpc_set_error(nfs->rpc, "RPC error: Failed to send LSEEK GETATTR call"); free(data); - return -2; + return -1; } return 0; } @@ -1913,7 +1951,7 @@ static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_ int nfs_statvfs_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_statvfs_continue_internal, NULL, NULL, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -1970,7 +2008,7 @@ static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb int nfs_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data) { if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_readlink_continue_internal, NULL, NULL, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -2035,7 +2073,7 @@ static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_da int nfs_chmod_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chmod_continue_internal, NULL, NULL, mode) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -2051,8 +2089,7 @@ int nfs_fchmod_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int mode, nfs data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { - rpc_set_error(nfs->rpc, "out of memory"); - printf("failed to allocate memory for nfs mount data\n"); + rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for nfs mount data"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -2149,7 +2186,7 @@ int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, chown_data = malloc(sizeof(struct nfs_chown_data)); if (chown_data == NULL) { - printf("Failed to allocate memory for chown data structure\n"); + rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure"); return -1; } @@ -2157,7 +2194,7 @@ int nfs_chown_async(struct nfs_context *nfs, const char *path, int uid, int gid, chown_data->gid = gid; if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chown_continue_internal, chown_data, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -2175,7 +2212,7 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int chown_data = malloc(sizeof(struct nfs_chown_data)); if (chown_data == NULL) { - printf("Failed to allocate memory for chown data structure\n"); + rpc_set_error(nfs->rpc, "Failed to allocate memory for chown data structure"); return -1; } @@ -2185,8 +2222,7 @@ int nfs_fchown_async(struct nfs_context *nfs, struct nfsfh *nfsfh, int uid, int data = malloc(sizeof(struct nfs_cb_data)); if (data == NULL) { - rpc_set_error(nfs->rpc, "out of memory"); - printf("failed to allocate memory for fchown data\n"); + rpc_set_error(nfs->rpc, "out of memory. failed to allocate memory for fchown data"); return -1; } bzero(data, sizeof(struct nfs_cb_data)); @@ -2285,7 +2321,7 @@ int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval * if (times != NULL) { new_times = malloc(sizeof(struct timeval)*2); if (new_times == NULL) { - printf("Failed to allocate memory for timeval structure\n"); + rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure"); return -1; } @@ -2293,7 +2329,7 @@ int nfs_utimes_async(struct nfs_context *nfs, const char *path, struct timeval * } if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -2310,7 +2346,7 @@ int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *t if (times != NULL) { new_times = malloc(sizeof(struct timeval)*2); if (new_times == NULL) { - printf("Failed to allocate memory for timeval structure\n"); + rpc_set_error(nfs->rpc, "Failed to allocate memory for timeval structure"); return -1; } @@ -2321,7 +2357,7 @@ int nfs_utime_async(struct nfs_context *nfs, const char *path, struct utimbuf *t } if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_utimes_continue_internal, new_times, free, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); return -1; } @@ -2414,8 +2450,8 @@ static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_d int nfs_access_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data) { if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_access_continue_internal, NULL, NULL, mode) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -2; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -2498,44 +2534,44 @@ int nfs_symlink_async(struct nfs_context *nfs, const char *oldpath, const char * symlink_data = malloc(sizeof(struct nfs_symlink_data)); if (symlink_data == NULL) { - printf("Out of memory, failed to allocate buffer for symlink data\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for symlink data"); return -1; } bzero(symlink_data, sizeof(struct nfs_symlink_data)); symlink_data->oldpath = strdup(oldpath); if (symlink_data->oldpath == NULL) { - printf("Out of memory, failed to allocate buffer for oldpath\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath"); free_nfs_symlink_data(symlink_data); - return -2; + return -1; } symlink_data->newpathparent = strdup(newpath); if (symlink_data->newpathparent == NULL) { - printf("Out of memory, failed to allocate mode buffer for new path\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path"); free_nfs_symlink_data(symlink_data); - return -3; + return -1; } - ptr = rindex(symlink_data->newpathparent, '/'); + ptr = strrchr(symlink_data->newpathparent, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", oldpath); + rpc_set_error(nfs->rpc, "Invalid path %s", oldpath); free_nfs_symlink_data(symlink_data); - return -4; + return -1; } *ptr = 0; ptr++; symlink_data->newpathobject = strdup(ptr); if (symlink_data->newpathobject == NULL) { - printf("Out of memory, failed to allocate mode buffer for new path\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for new path"); free_nfs_symlink_data(symlink_data); - return -5; + return -1; } if (nfs_lookuppath_async(nfs, symlink_data->newpathparent, cb, private_data, nfs_symlink_continue_internal, symlink_data, free_nfs_symlink_data, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -6; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -2652,22 +2688,22 @@ int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *n rename_data = malloc(sizeof(struct nfs_rename_data)); if (rename_data == NULL) { - printf("Out of memory, failed to allocate buffer for rename data\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for rename data"); return -1; } bzero(rename_data, sizeof(struct nfs_rename_data)); rename_data->oldpath = strdup(oldpath); if (rename_data->oldpath == NULL) { - printf("Out of memory, failed to allocate buffer for oldpath\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath"); free_nfs_rename_data(rename_data); - return -2; + return -1; } - ptr = rindex(rename_data->oldpath, '/'); + ptr = strrchr(rename_data->oldpath, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", oldpath); + rpc_set_error(nfs->rpc, "Invalid path %s", oldpath); free_nfs_rename_data(rename_data); - return -3; + return -1; } *ptr = 0; ptr++; @@ -2676,15 +2712,15 @@ int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *n rename_data->newpath = strdup(newpath); if (rename_data->newpath == NULL) { - printf("Out of memory, failed to allocate buffer for newpath\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath"); free_nfs_rename_data(rename_data); - return -4; + return -1; } - ptr = rindex(rename_data->newpath, '/'); + ptr = strrchr(rename_data->newpath, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", newpath); + rpc_set_error(nfs->rpc, "Invalid path %s", newpath); free_nfs_rename_data(rename_data); - return -5; + return -1; } *ptr = 0; ptr++; @@ -2692,8 +2728,8 @@ int nfs_rename_async(struct nfs_context *nfs, const char *oldpath, const char *n if (nfs_lookuppath_async(nfs, rename_data->oldpath, cb, private_data, nfs_rename_continue_1_internal, rename_data, free_nfs_rename_data, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -6; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -2808,29 +2844,29 @@ int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *new link_data = malloc(sizeof(struct nfs_link_data)); if (link_data == NULL) { - printf("Out of memory, failed to allocate buffer for link data\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for link data"); return -1; } bzero(link_data, sizeof(struct nfs_link_data)); link_data->oldpath = strdup(oldpath); if (link_data->oldpath == NULL) { - printf("Out of memory, failed to allocate buffer for oldpath\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for oldpath"); free_nfs_link_data(link_data); - return -2; + return -1; } link_data->newpath = strdup(newpath); if (link_data->newpath == NULL) { - printf("Out of memory, failed to allocate buffer for newpath\n"); + rpc_set_error(nfs->rpc, "Out of memory, failed to allocate buffer for newpath"); free_nfs_link_data(link_data); - return -4; + return -1; } - ptr = rindex(link_data->newpath, '/'); + ptr = strrchr(link_data->newpath, '/'); if (ptr == NULL) { - printf("Invalid path %s\n", newpath); + rpc_set_error(nfs->rpc, "Invalid path %s", newpath); free_nfs_link_data(link_data); - return -5; + return -1; } *ptr = 0; ptr++; @@ -2838,8 +2874,8 @@ int nfs_link_async(struct nfs_context *nfs, const char *oldpath, const char *new if (nfs_lookuppath_async(nfs, link_data->oldpath, cb, private_data, nfs_link_continue_1_internal, link_data, free_nfs_link_data, 0) != 0) { - printf("Out of memory: failed to start parsing the path components\n"); - return -6; + rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components"); + return -1; } return 0; @@ -2869,3 +2905,226 @@ size_t nfs_get_writemax(struct nfs_context *nfs) { return nfs->writemax; } + +void nfs_set_error(struct nfs_context *nfs, char *error_string, ...) +{ + va_list ap; + char *str = NULL; + + va_start(ap, error_string); + str = malloc(1024); + vsnprintf(str, 1024, error_string, ap); + if (nfs->rpc->error_string != NULL) { + free(nfs->rpc->error_string); + } + nfs->rpc->error_string = str; + va_end(ap); +} + + + +struct mount_cb_data { + rpc_cb cb; + void *private_data; + char *server; +}; + +static void free_mount_cb_data(struct mount_cb_data *data) +{ + if (data->server != NULL) { + free(data->server); + data->server = NULL; + } + + free(data); +} + +static void mount_export_5_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct mount_cb_data *data = private_data; + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, -EFAULT, command_data, data->private_data); + free_mount_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); + free_mount_cb_data(data); + return; + } + + data->cb(rpc, 0, command_data, data->private_data); + if (rpc_disconnect(rpc, "normal disconnect") != 0) { + rpc_set_error(rpc, "Failed to disconnect\n"); + } + free_mount_cb_data(data); +} + +static void mount_export_4_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct mount_cb_data *data = private_data; + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, -EFAULT, command_data, data->private_data); + free_mount_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); + free_mount_cb_data(data); + return; + } + + if (rpc_mount_export_async(rpc, mount_export_5_cb, data) != 0) { + data->cb(rpc, -ENOMEM, command_data, data->private_data); + free_mount_cb_data(data); + return; + } +} + +static void mount_export_3_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct mount_cb_data *data = private_data; + uint32_t mount_port; + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, -EFAULT, command_data, data->private_data); + free_mount_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); + free_mount_cb_data(data); + return; + } + + mount_port = *(uint32_t *)command_data; + if (mount_port == 0) { + rpc_set_error(rpc, "RPC error. Mount program is not available"); + data->cb(rpc, -ENOENT, command_data, data->private_data); + free_mount_cb_data(data); + return; + } + + rpc_disconnect(rpc, "normal disconnect"); + if (rpc_connect_async(rpc, data->server, mount_port, mount_export_4_cb, data) != 0) { + data->cb(rpc, -ENOMEM, command_data, data->private_data); + free_mount_cb_data(data); + return; + } +} + +static void mount_export_2_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct mount_cb_data *data = private_data; + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, -EFAULT, command_data, data->private_data); + free_mount_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); + free_mount_cb_data(data); + return; + } + + if (rpc_pmap_getport_async(rpc, MOUNT_PROGRAM, MOUNT_V3, mount_export_3_cb, private_data) != 0) { + data->cb(rpc, -ENOMEM, command_data, data->private_data); + free_mount_cb_data(data); + return; + } +} + +static void mount_export_1_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data) +{ + struct mount_cb_data *data = private_data; + + if (status == RPC_STATUS_ERROR) { + data->cb(rpc, -EFAULT, command_data, data->private_data); + free_mount_cb_data(data); + return; + } + if (status == RPC_STATUS_CANCEL) { + data->cb(rpc, -EINTR, "Command was cancelled", data->private_data); + free_mount_cb_data(data); + return; + } + + if (rpc_pmap_null_async(rpc, mount_export_2_cb, data) != 0) { + data->cb(rpc, -ENOMEM, command_data, data->private_data); + free_mount_cb_data(data); + return; + } +} + +int mount_getexports_async(struct rpc_context *rpc, const char *server, rpc_cb cb, void *private_data) +{ + struct mount_cb_data *data; + + data = malloc(sizeof(struct mount_cb_data)); + if (data == NULL) { + return -1; + } + bzero(data, sizeof(struct mount_cb_data)); + data->cb = cb; + data->private_data = private_data; + data->server = strdup(server); + 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; + } + + return 0; +} + +struct rpc_context *nfs_get_rpc_context(struct nfs_context *nfs) +{ + return nfs->rpc; +} + +const char *nfs_get_server(struct nfs_context *nfs) { + return nfs->server; +} + +const char *nfs_get_export(struct nfs_context *nfs) { + return nfs->export; +} + + +#if defined(WIN32) +int poll(struct pollfd *fds, int nfsd, int timeout) +{ + fd_set rfds, wfds, efds; + int ret; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + if (fds->events & POLLIN) { + FD_SET(fds->fd, &rfds); + } + if (fds->events & POLLOUT) { + FD_SET(fds->fd, &wfds); + } + FD_SET(fds->fd, &efds); + select(fds->fd + 1, &rfds, &wfds, &efds, NULL); + fds->revents = 0; + if (FD_ISSET(fds->fd, &rfds)) { + fds->revents |= POLLIN; + } + if (FD_ISSET(fds->fd, &wfds)) { + fds->revents |= POLLOUT; + } + if (FD_ISSET(fds->fd, &efds)) { + fds->revents |= POLLHUP; + } + return 1; +} +#endif +