* High level api to nfs filesystems
*/
+#define _GNU_SOURCE
+
+#if defined(WIN32)
+#include <winsock2.h>
+#define DllExport
+#define O_SYNC 0
+typedef int uid_t;
+typedef int gid_t;
+#else
+#include <strings.h>
+#include <sys/statvfs.h>
+#include <utime.h>
+#include <unistd.h>
+#endif
+
#include <stdio.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <utime.h>
-#include <unistd.h>
#include <fcntl.h>
#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;
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)
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);
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)
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;
}
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);
+ bzero((char *)data, sizeof(struct nfs_cb_data));
+ 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;
}
path = data->path;
- str = index(path, '/');
+ str = strchr(path, '/');
if (str != NULL) {
*str = 0;
data->path = str+1;
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->continue_cb = continue_cb;
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;
}
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;
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;
}
free_nfs_cb_data(data);
return;
}
- bzero(nfsfh, sizeof(struct nfsfh));
+ bzero((char *)nfsfh, sizeof(struct nfsfh));
if (data->continue_int & O_SYNC) {
nfsfh->is_sync = 1;
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;
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;
+ }
}
}
}
return;
}
-
if (data->error != 0) {
data->cb(-EFAULT, nfs, command_data, data->private_data);
free_nfs_cb_data(data);
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);
}
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
* 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);
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));
+ bzero((char *)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);
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
- bzero(&args, sizeof(SETATTR3args));
+ bzero((char *)&args, sizeof(SETATTR3args));
args.object.data.data_len = nfsfh->fh.data.data_len;
args.object.data.data_val = nfsfh->fh.data.data_val;
args.new_attributes.size.set_it = 1;
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;
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;
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;
free_nfs_cb_data(data);
return;
}
- bzero(nfsfh, sizeof(struct nfsfh));
+ bzero((char *)nfsfh, sizeof(struct nfsfh));
/* steal the filehandle */
nfsfh->fh.data.data_len = data->fh.data.data_len;
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;
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;
*/
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);
return;
}
- entry =res->READDIR3res_u.resok.reply.entries;
+ entry =res->READDIRPLUS3res_u.resok.reply.entries;
while (entry != NULL) {
struct nfsdirent *nfsdirent;
free_nfs_cb_data(data);
return;
}
- bzero(nfsdirent, sizeof(struct nfsdirent));
+ bzero((char *)nfsdirent, sizeof(struct nfsdirent));
nfsdirent->name = strdup(entry->name);
if (nfsdirent->name == NULL) {
data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
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;
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;
{
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);
+ bzero((char *)cv, sizeof(cookieverf3));
+ 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;
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));
+ bzero((char *)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;
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;
}
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;
}
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;
}
{
SETATTR3args args;
- bzero(&args, sizeof(SETATTR3args));
+ bzero((char *)&args, sizeof(SETATTR3args));
args.object.data.data_len = data->fh.data.data_len;
args.object.data.data_val = data->fh.data.data_val;
args.new_attributes.mode.set_it = 1;
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;
}
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
SETATTR3args args;
struct nfs_chown_data *chown_data = data->continue_data;
- bzero(&args, sizeof(SETATTR3args));
+ bzero((char *)&args, sizeof(SETATTR3args));
args.object.data.data_len = data->fh.data.data_len;
args.object.data.data_val = data->fh.data.data_val;
if (chown_data->uid != (uid_t)-1) {
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;
}
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;
}
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;
}
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));
+ bzero((char *)data, sizeof(struct nfs_cb_data));
data->nfs = nfs;
data->cb = cb;
data->private_data = private_data;
SETATTR3args args;
struct timeval *utimes_data = data->continue_data;
- bzero(&args, sizeof(SETATTR3args));
+ bzero((char *)&args, sizeof(SETATTR3args));
args.object.data.data_len = data->fh.data.data_len;
args.object.data.data_val = data->fh.data.data_val;
if (utimes_data != NULL) {
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;
}
}
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;
}
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;
}
}
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;
}
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;
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));
+ bzero((char *)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;
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));
+ bzero((char *)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++;
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++;
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;
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));
+ bzero((char *)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++;
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;
{
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((char *)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
+