struct nfs_fh3 rootfh;
uint64_t readmax;
uint64_t writemax;
+ char *cwd;
};
void nfs_free_nfsdir(struct nfsdir *nfsdir)
static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh);
-
void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth)
{
rpc_set_auth(nfs->rpc, auth);
return NULL;
}
+ memset(urls, 0x00, sizeof(struct nfs_url));
urls->server = strdup(url + 6);
if (urls->server == NULL) {
nfs_destroy_url(urls);
}
}
- if (urls->server && strlen(urls->server) <= 1) {
- free(urls->server);
- urls->server = NULL;
- }
-
while (flagsp != NULL && *(flagsp+1) != 0) {
strp = flagsp + 1;
flagsp = strchr(strp, '&');
}
}
+ if (urls->server && strlen(urls->server) <= 1) {
+ free(urls->server);
+ urls->server = NULL;
+ }
+
return urls;
}
if (nfs == NULL) {
return NULL;
}
+ memset(nfs, 0, sizeof(struct nfs_context));
+
nfs->rpc = rpc_init_context();
if (nfs->rpc == NULL) {
free(nfs);
return NULL;
}
- nfs->server = NULL;
- nfs->export = NULL;
-
- nfs->rootfh.data.data_len = 0;
- nfs->rootfh.data.data_val = NULL;
+ nfs->cwd = strdup("/");
return nfs;
}
nfs->export = NULL;
}
+ if (nfs->cwd) {
+ free(nfs->cwd);
+ nfs->cwd = NULL;
+ }
+
if (nfs->rootfh.data.data_val != NULL) {
free(nfs->rootfh.data.data_val);
nfs->rootfh.data.data_val = NULL;
rpc_cb cb;
void *private_data;
-};
+};
void free_rpc_cb_data(struct rpc_cb_data *data)
{
assert(rpc->magic == RPC_CONTEXT_MAGIC);
- if (status == RPC_STATUS_ERROR) {
+ if (status == RPC_STATUS_ERROR) {
data->cb(rpc, status, command_data, data->private_data);
free_rpc_cb_data(data);
return;
nfs->writemax = res->FSINFO3res_u.resok.wtmax;
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;
+ args.object = nfs->rootfh;
if (rpc_nfs3_getattr_async(rpc, nfs_mount_10_cb, &args, data) != 0) {
data->cb(-ENOMEM, nfs, command_data, data->private_data);
{
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
+ struct FSINFO3args args;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
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;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
- if (status == RPC_STATUS_ERROR) {
+ if (status == RPC_STATUS_ERROR) {
data->cb(-EFAULT, nfs, command_data, data->private_data);
free_nfs_cb_data(data);
return;
static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh)
{
- char *path, *str;
+ char *path, *slash;
LOOKUP3args args;
while (*data->path == '/') {
}
path = data->path;
- str = strchr(path, '/');
- if (str != NULL) {
- *str = 0;
- data->path = str+1;
+ slash = strchr(path, '/');
+ if (slash != NULL) {
+ /* Clear slash so that path is a zero terminated string for
+ * the current path component. Set it back to '/' again later
+ * when we are finished referencing this component so that
+ * data->saved_path will still point to the full
+ * normalized path.
+ */
+ *slash = 0;
+ data->path = slash+1;
} else {
while (*data->path != 0) {
data->path++;
return -1;
}
memcpy(data->fh.data.data_val, fh->data.data_val, data->fh.data.data_len);
+ if (slash != NULL) {
+ *slash = '/';
+ }
data->continue_cb(nfs, data);
return 0;
}
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;
+ args.what.dir = *fh;
+ args.what.name = path;
if (rpc_nfs3_lookup_async(nfs->rpc, nfs_lookup_path_1_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s", data->path);
free_nfs_cb_data(data);
return -1;
}
+ if (slash != NULL) {
+ *slash = '/';
+ }
+ return 0;
+}
+
+static int nfs_normalize_path(struct nfs_context *nfs, char *path)
+{
+ char *str;
+ int len;
+
+ /* // -> / */
+ while ((str = strstr(path, "//"))) {
+ while(*str) {
+ *str = *(str + 1);
+ str++;
+ }
+ }
+
+ /* /./ -> / */
+ while ((str = strstr(path, "/./"))) {
+ while(*(str + 1)) {
+ *str = *(str + 2);
+ str++;
+ }
+ }
+
+ /* ^/../ -> error */
+ if (!strncmp(path, "/../", 4)) {
+ rpc_set_error(nfs->rpc,
+ "Absolute path starts with '/../' "
+ "during normalization");
+ return -1;
+ }
+
+ /* ^[^/] -> error */
+ if (path[0] != '/') {
+ rpc_set_error(nfs->rpc,
+ "Absolute path does not start with '/'");
+ return -1;
+ }
+
+ /* /string/../ -> / */
+ while ((str = strstr(path, "/../"))) {
+ char *tmp;
+
+ if (!strncmp(path, "/../", 4)) {
+ rpc_set_error(nfs->rpc,
+ "Absolute path starts with '/../' "
+ "during normalization");
+ return -1;
+ }
+
+ tmp = str - 1;
+ while (*tmp != '/') {
+ tmp--;
+ }
+ str += 3;
+ while((*(tmp++) = *(str++)) != '\0')
+ ;
+ }
+
+ /* /$ -> \0 */
+ len = strlen(path);
+ if (len >= 1) {
+ if (path[len - 1] == '/') {
+ path[len - 1] = '\0';
+ len--;
+ }
+ }
+ if (path[0] == '\0') {
+ rpc_set_error(nfs->rpc,
+ "Absolute path became '' "
+ "during normalization");
+ return -1;
+ }
+
+ /* /.$ -> \0 */
+ if (len >= 2) {
+ if (!strcmp(&path[len - 2], "/.")) {
+ path[len - 2] = '\0';
+ len -= 2;
+ }
+ }
+
+ /* ^/..$ -> error */
+ if (!strcmp(path, "/..")) {
+ rpc_set_error(nfs->rpc,
+ "Absolute path is '/..' "
+ "during normalization");
+ return -1;
+ }
+
+ /* /string/..$ -> / */
+ if (len >= 3) {
+ if (!strcmp(&path[len - 3], "/..")) {
+ char *tmp = &path[len - 3];
+ while (*--tmp != '/')
+ ;
+ *tmp = '\0';
+ }
+ }
+
return 0;
}
{
struct nfs_cb_data *data;
- if (path[0] != 0 && path[0] != '/') {
- rpc_set_error(nfs->rpc, "Pathname is not absolute %s", path);
- return -1;
+ if (path[0] == '\0') {
+ path = ".";
}
data = malloc(sizeof(struct nfs_cb_data));
if (data == NULL) {
- rpc_set_error(nfs->rpc, "out of memory: failed to allocate nfs_cb_data structure");
+ rpc_set_error(nfs->rpc, "out of memory: failed to allocate "
+ "nfs_cb_data structure");
+ if (free_continue_data)
+ free_continue_data(continue_data);
return -1;
}
memset(data, 0, sizeof(struct nfs_cb_data));
data->free_continue_data = free_continue_data;
data->continue_int = continue_int;
data->private_data = private_data;
- data->saved_path = strdup(path);
+ if (path[0] == '/') {
+ data->saved_path = strdup(path);
+ } else {
+ data->saved_path = malloc(strlen(path) + strlen(nfs->cwd) + 2);
+ if (data->saved_path == NULL) {
+ rpc_set_error(nfs->rpc, "out of memory: failed to "
+ "malloc path string");
+ free_nfs_cb_data(data);
+ return -1;
+ }
+ sprintf(data->saved_path, "%s/%s", nfs->cwd, path);
+ }
+
if (data->saved_path == NULL) {
rpc_set_error(nfs->rpc, "out of memory: failed to copy path string");
free_nfs_cb_data(data);
return -1;
}
+ if (nfs_normalize_path(nfs, data->saved_path) != 0) {
+ free_nfs_cb_data(data);
+ return -1;
+ }
+
data->path = data->saved_path;
if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) {
GETATTR3res *res;
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
+#ifdef WIN32
+ struct __stat64 st;
+#else
struct stat st;
+#endif
assert(rpc->magic == RPC_CONTEXT_MAGIC);
#ifndef WIN32
st.st_blksize = 4096;
st.st_blocks = res->GETATTR3res_u.resok.obj_attributes.size / 4096;
-#endif//WIN32
+#endif//WIN32
st.st_atime = res->GETATTR3res_u.resok.obj_attributes.atime.seconds;
st.st_mtime = res->GETATTR3res_u.resok.obj_attributes.mtime.seconds;
st.st_ctime = res->GETATTR3res_u.resok.obj_attributes.ctime.seconds;
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;
+ args.object = data->fh;
if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat_1_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
-
-
/*
* Async open()
*/
+static void nfs_open_trunc_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
+{
+ struct nfs_cb_data *data = private_data;
+ struct nfs_context *nfs = data->nfs;
+ struct nfsfh *nfsfh;
+ SETATTR3res *res;
+
+ assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+ if (status == RPC_STATUS_ERROR) {
+ data->cb(-EFAULT, nfs, command_data, data->private_data);
+ free_nfs_cb_data(data);
+ return;
+ }
+ if (status == RPC_STATUS_CANCEL) {
+ data->cb(-EINTR, nfs, "Command was cancelled", data->private_data);
+ free_nfs_cb_data(data);
+ return;
+ }
+
+ res = command_data;
+ if (res->status != NFS3_OK) {
+ rpc_set_error(nfs->rpc, "NFS: Setattr failed with %s(%d)", nfsstat3_to_str(res->status), nfsstat3_to_errno(res->status));
+ data->cb(nfsstat3_to_errno(res->status), nfs, rpc_get_error(nfs->rpc), data->private_data);
+ free_nfs_cb_data(data);
+ return;
+ }
+
+ nfsfh = malloc(sizeof(struct nfsfh));
+ if (nfsfh == NULL) {
+ rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
+ data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
+ free_nfs_cb_data(data);
+ return;
+ }
+ memset(nfsfh, 0, sizeof(struct nfsfh));
+
+ if (data->continue_int & O_SYNC) {
+ nfsfh->is_sync = 1;
+ }
+
+ /* steal the filehandle */
+ nfsfh->fh = data->fh;
+ data->fh.data.data_val = NULL;
+
+ data->cb(0, nfs, nfsfh, data->private_data);
+ free_nfs_cb_data(data);
+}
+
static void nfs_open_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
ACCESS3res *res;
return;
}
+ /* Try to truncate it if we were requested to */
+ if ((data->continue_int & O_TRUNC) &&
+ (data->continue_int & (O_RDWR|O_WRONLY))) {
+ SETATTR3args args;
+
+ memset(&args, 0, sizeof(SETATTR3args));
+ args.object = data->fh;
+ args.new_attributes.size.set_it = 1;
+ args.new_attributes.size.set_size3_u.size = 0;
+
+ if (rpc_nfs3_setattr_async(nfs->rpc, nfs_open_trunc_cb, &args,
+ data) != 0) {
+ rpc_set_error(nfs->rpc, "RPC error: Failed to send "
+ "SETATTR call for %s", data->path);
+ data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc),
+ data->private_data);
+ free_nfs_cb_data(data);
+ return;
+ }
+ return;
+ }
+
nfsfh = malloc(sizeof(struct nfsfh));
if (nfsfh == NULL) {
rpc_set_error(nfs->rpc, "NFS: Failed to allocate nfsfh structure");
}
/* steal the filehandle */
- nfsfh->fh.data.data_len = data->fh.data.data_len;
- nfsfh->fh.data.data_val = data->fh.data.data_val;
+ nfsfh->fh = data->fh;
data->fh.data.data_val = NULL;
data->cb(0, nfs, nfsfh, data->private_data);
}
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.object = data->fh;
args.access = nfsmode;
if (rpc_nfs3_access_async(nfs->rpc, nfs_open_cb, &args, data) != 0) {
- rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS call for %s", data->path);
- data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
+ rpc_set_error(nfs->rpc, "RPC error: Failed to send OPEN ACCESS "
+ "call for %s", data->path);
+ data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc),
+ data->private_data);
free_nfs_cb_data(data);
return -1;
}
return 0;
}
-int nfs_open_async(struct nfs_context *nfs, const char *path, int mode, nfs_cb cb, void *private_data)
+int nfs_open_async(struct nfs_context *nfs, const char *path, int flags, nfs_cb cb, void *private_data)
{
- if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, mode) != 0) {
+ if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_open_continue_internal, NULL, NULL, flags) != 0) {
rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
return -1;
}
}
+/*
+ * Async chdir()
+ */
+static int nfs_chdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+{
+ /* steal saved_path */
+ free(nfs->cwd);
+ nfs->cwd = data->saved_path;
+ data->saved_path = NULL;
+
+ data->cb(0, nfs, NULL, data->private_data);
+ free_nfs_cb_data(data);
+ return 0;
+}
+
+int nfs_chdir_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data)
+{
+ if (nfs_lookuppath_async(nfs, path, cb, private_data, nfs_chdir_continue_internal, NULL, NULL, 0) != 0) {
+ rpc_set_error(nfs->rpc, "Out of memory: failed to start parsing the path components");
+ return -1;
+ }
+
+ return 0;
+}
/*
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.file = nfsfh->fh;
args.offset = offset;
args.count = count;
mdata->count = readcount;
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.file = nfsfh->fh;
args.offset = offset;
args.count = readcount;
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.file = nfsfh->fh;
args.offset = offset;
args.count = count;
args.stable = nfsfh->is_sync?FILE_SYNC:UNSTABLE;
mdata->count = writecount;
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.file = nfsfh->fh;
args.offset = offset;
args.count = writecount;
args.stable = nfsfh->is_sync?FILE_SYNC:UNSTABLE;
/*
* close
*/
-
+
int nfs_close_async(struct nfs_context *nfs, struct nfsfh *nfsfh, nfs_cb cb, void *private_data)
{
if (nfsfh->fh.data.data_val != NULL){
data->private_data = private_data;
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;
+ args.object = nfsfh->fh;
if (rpc_nfs3_getattr_async(nfs->rpc, nfs_stat_1_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send STAT GETATTR call for %s", data->path);
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) {
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);
data->private_data = private_data;
memset(&args, 0, sizeof(SETATTR3args));
- args.object.data.data_len = nfsfh->fh.data.data_len;
- args.object.data.data_val = nfsfh->fh.data.data_val;
+ args.object = nfsfh->fh;
args.new_attributes.size.set_it = 1;
args.new_attributes.size.set_size3_u.size = length;
- if (rpc_nfs_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
+ if (rpc_nfs3_setattr_async(nfs->rpc, nfs_ftruncate_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
uint64_t offset = data->continue_int;
struct nfsfh nfsfh;
- nfsfh.fh.data.data_val = data->fh.data.data_val;
- nfsfh.fh.data.data_len = data->fh.data.data_len;
+ nfsfh.fh = data->fh;
if (nfs_ftruncate_async(nfs, &nfsfh, offset, data->cb, data->private_data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
char *str = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
str = &str[strlen(str) + 1];
str = &str[strlen(str) + 1];
memset(&args, 0, sizeof(MKDIR3args));
- args.where.dir.data.data_len = data->fh.data.data_len;
- args.where.dir.data.data_val = data->fh.data.data_val;
+ args.where.dir = data->fh;
args.where.name = str;
args.attributes.mode.set_it = 1;
args.attributes.mode.set_mode3_u.mode = 0755;
- if (rpc_nfs_mkdir_async(nfs->rpc, nfs_mkdir_cb, &args, data) != 0) {
+ if (rpc_nfs3_mkdir_async(nfs->rpc, nfs_mkdir_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send MKDIR call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
char *str = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
str = &str[strlen(str) + 1];
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);
}
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;
+ args.what.dir = data->fh;
+ args.what.name = str;
if (rpc_nfs3_lookup_async(nfs->rpc, nfs_create_2_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send lookup call for %s/%s", data->saved_path, str);
str = &str[strlen(str) + 1];
memset(&args, 0, sizeof(CREATE3args));
- args.where.dir.data.data_len = data->fh.data.data_len;
- args.where.dir.data.data_val = data->fh.data.data_val;
+ args.where.dir = data->fh;
args.where.name = str;
args.how.mode = UNCHECKED;
args.how.createhow3_u.obj_attributes.mode.set_it = 1;
args.how.createhow3_u.obj_attributes.mode.set_mode3_u.mode = data->continue_int;
- if (rpc_nfs_create_async(nfs->rpc, nfs_creat_1_cb, &args, data) != 0) {
+ if (rpc_nfs3_create_async(nfs->rpc, nfs_creat_1_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send CREATE call for %s/%s", data->path, str);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
char *str = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
str = &str[strlen(str) + 1];
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);
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
char *str = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
str = &str[strlen(str) + 1];
{
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;
cb_data->path = strdup(path);
if (cb_data->path == NULL) {
rpc_set_error(nfs->rpc, "Out of memory, failed to allocate mode buffer for path");
- free(cb_data);
+ free(cb_data);
return -1;
}
ptr = strrchr(cb_data->path, '/');
if (ptr == NULL) {
rpc_set_error(nfs->rpc, "Invalid path %s", path);
+ free_mknod_cb_data(cb_data);
return -1;
}
*ptr = 0;
nfsdirent->mtime.tv_usec = attributes->mtime.nseconds/1000;
nfsdirent->ctime.tv_sec = attributes->ctime.seconds;
nfsdirent->ctime.tv_usec = attributes->ctime.nseconds/1000;
+ nfsdirent->uid = attributes->uid;
+ nfsdirent->gid = attributes->gid;
}
}
struct nfsdir *nfsdir = data->continue_data;
struct nfsdirent *nfsdirent;
struct entry3 *entry;
- uint64_t cookie;
+ uint64_t cookie = 0;
struct rdpe_cb_data *rdpe_cb_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR) {
}
if (res->READDIR3res_u.resok.reply.eof == 0) {
- if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, cookie, res->READDIR3res_u.resok.cookieverf, 8192, data) != 0) {
+ READDIR3args args;
+
+ args.dir = data->fh;
+ args.cookie = cookie;
+ memcpy(&args.cookieverf, res->READDIR3res_u.resok.cookieverf, sizeof(cookieverf3));
+ args.count = 8192;
+
+ if (rpc_nfs3_readdir_async(nfs->rpc, nfs_opendir2_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
nfs_free_nfsdir(nfsdir);
rdpe_lookup_cb_data->nfsdirent = nfsdirent;
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;
+ args.what.dir = data->fh;
+ args.what.name = nfsdirent->name;
if (rpc_nfs3_lookup_async(nfs->rpc, nfs_opendir3_cb, &args, rdpe_lookup_cb_data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR LOOKUP call");
struct nfs_context *nfs = data->nfs;
struct nfsdir *nfsdir = data->continue_data;
struct entryplus3 *entry;
- uint64_t cookie;
-
+ uint64_t cookie = 0;
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR || (status == RPC_STATUS_SUCCESS && res->status == NFS3ERR_NOTSUPP) ){
- cookieverf3 cv;
+ READDIR3args args;
- if (rpc_nfs_readdir_async(nfs->rpc, nfs_opendir2_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
+ args.dir = data->fh;
+ args.cookie = cookie;
+ memset(&args.cookieverf, 0, sizeof(cookieverf3));
+ args.count = 8192;
+
+ if (rpc_nfs3_readdir_async(nfs->rpc, nfs_opendir2_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIR call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
nfs_free_nfsdir(nfsdir);
nfsdirent->name = strdup(entry->name);
if (nfsdirent->name == NULL) {
data->cb(-ENOMEM, nfs, "Failed to allocate dirent->name", data->private_data);
+ free(nfsdirent);
nfs_free_nfsdir(nfsdir);
data->continue_data = NULL;
free_nfs_cb_data(data);
nfsdirent->mtime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.mtime.nseconds/1000;
nfsdirent->ctime.tv_sec = entry->name_attributes.post_op_attr_u.attributes.ctime.seconds;
nfsdirent->ctime.tv_usec = entry->name_attributes.post_op_attr_u.attributes.ctime.nseconds/1000;
+ nfsdirent->uid = entry->name_attributes.post_op_attr_u.attributes.uid;
+ nfsdirent->gid = entry->name_attributes.post_op_attr_u.attributes.gid;
}
nfsdirent->next = nfsdir->entries;
}
if (res->READDIRPLUS3res_u.resok.reply.eof == 0) {
- if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, cookie, res->READDIRPLUS3res_u.resok.cookieverf, 8192, data) != 0) {
+ READDIRPLUS3args args;
+
+ args.dir = data->fh;
+ args.cookie = cookie;
+ memcpy(&args.cookieverf, res->READDIRPLUS3res_u.resok.cookieverf, sizeof(cookieverf3));
+ args.dircount = 8192;
+ args.maxcount = 8192;
+
+ if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs_opendir_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
nfs_free_nfsdir(nfsdir);
static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
{
- cookieverf3 cv;
+ READDIRPLUS3args args;
- memset(cv, 0, sizeof(cookieverf3));
- if (rpc_nfs_readdirplus_async(nfs->rpc, nfs_opendir_cb, &data->fh, 0, (char *)&cv, 8192, data) != 0) {
+ args.dir = data->fh;
+ args.cookie = 0;
+ memset(&args.cookieverf, 0, sizeof(cookieverf3));
+ args.dircount = 8192;
+ args.maxcount = 8192;
+ if (rpc_nfs3_readdirplus_async(nfs->rpc, nfs_opendir_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READDIRPLUS call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
}
+/*
+ * closedir()
+ */
void nfs_closedir(struct nfs_context *nfs _U_, struct nfsdir *nfsdir)
{
nfs_free_nfsdir(nfsdir);
}
-
-
-
+/*
+ * getcwd()
+ */
+void nfs_getcwd(struct nfs_context *nfs, const char **cwd)
+{
+ if (cwd) {
+ *cwd = nfs->cwd;
+ }
+}
/*
data->private_data = private_data;
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;
+ 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");
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);
return;
}
-
+
data->cb(0, nfs, res->READLINK3res_u.resok.data, data->private_data);
free_nfs_cb_data(data);
}
{
READLINK3args args;
- args.symlink.data.data_len = data->fh.data.data_len;
- args.symlink.data.data_val = data->fh.data.data_val;
+ args.symlink = data->fh;
- if (rpc_nfs_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) {
+ if (rpc_nfs3_readlink_async(nfs->rpc, nfs_readlink_1_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send READLINK call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
SETATTR3args args;
memset(&args, 0, sizeof(SETATTR3args));
- args.object.data.data_len = data->fh.data.data_len;
- args.object.data.data_val = data->fh.data.data_val;
+ args.object = data->fh;
args.new_attributes.mode.set_it = 1;
args.new_attributes.mode.set_mode3_u.mode = data->continue_int;
- if (rpc_nfs_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
+ if (rpc_nfs3_setattr_async(nfs->rpc, nfs_chmod_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send SETATTR call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
struct nfs_chown_data *chown_data = data->continue_data;
memset(&args, 0, sizeof(SETATTR3args));
- args.object.data.data_len = data->fh.data.data_len;
- args.object.data.data_val = data->fh.data.data_val;
+ args.object = data->fh;
if (chown_data->uid != (uid_t)-1) {
args.new_attributes.uid.set_it = 1;
args.new_attributes.uid.set_uid3_u.uid = chown_data->uid;
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);
struct timeval *utimes_data = data->continue_data;
memset(&args, 0, sizeof(SETATTR3args));
- args.object.data.data_len = data->fh.data.data_len;
- args.object.data.data_val = data->fh.data.data_val;
+ args.object = data->fh;
if (utimes_data != NULL) {
args.new_attributes.atime.set_it = SET_TO_CLIENT_TIME;
args.new_attributes.atime.set_atime_u.atime.seconds = utimes_data[0].tv_sec;
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);
}
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.object = data->fh;
args.access = nfsmode;
if (rpc_nfs3_access_async(nfs->rpc, nfs_access_cb, &args, data) != 0) {
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
struct nfs_symlink_data *symlink_data = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR) {
static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
{
struct nfs_symlink_data *symlink_data = data->continue_data;
- SYMLINK3args sa;
+ SYMLINK3args args;
- memset(&sa, 0, sizeof(SYMLINK3args));
- sa.where.dir.data.data_len = data->fh.data.data_len;
- sa.where.dir.data.data_val = data->fh.data.data_val;
- sa.where.name = symlink_data->newpathobject;
- sa.symlink.symlink_attributes.mode.set_it = 1;
- sa.symlink.symlink_attributes.mode.set_mode3_u.mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH;
- sa.symlink.symlink_data = symlink_data->oldpath;
+ memset(&args, 0, sizeof(SYMLINK3args));
+ args.where.dir = data->fh;
+ args.where.name = symlink_data->newpathobject;
+ args.symlink.symlink_attributes.mode.set_it = 1;
+ args.symlink.symlink_attributes.mode.set_mode3_u.mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH;
+ args.symlink.symlink_data = symlink_data->oldpath;
- if (rpc_nfs_symlink_async(nfs->rpc, nfs_symlink_cb, &sa, data) != 0) {
+ if (rpc_nfs3_symlink_async(nfs->rpc, nfs_symlink_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send SYMLINK call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
struct nfs_rename_data *rename_data = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR) {
static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
{
struct nfs_rename_data *rename_data = data->continue_data;
+ RENAME3args args;
/* steal the filehandle */
- rename_data->newdir.data.data_len = data->fh.data.data_len;
- rename_data->newdir.data.data_val = data->fh.data.data_val;
+ rename_data->newdir = data->fh;
data->fh.data.data_val = NULL;
- if (rpc_nfs_rename_async(nfs->rpc, nfs_rename_cb, &rename_data->olddir, rename_data->oldobject, &rename_data->newdir, rename_data->newobject, data) != 0) {
+ args.from.dir = rename_data->olddir;
+ args.from.name = rename_data->oldobject;
+ args.to.dir = rename_data->newdir;
+ args.to.name = rename_data->newobject;
+ if (rpc_nfs3_rename_async(nfs->rpc, nfs_rename_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send RENAME call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
struct nfs_rename_data *rename_data = data->continue_data;
/* steal the filehandle */
- rename_data->olddir.data.data_len = data->fh.data.data_len;
- rename_data->olddir.data.data_val = data->fh.data.data_val;
+ rename_data->olddir = data->fh;
data->fh.data.data_val = NULL;
if (nfs_lookuppath_async(nfs, rename_data->newpath, data->cb, data->private_data, nfs_rename_continue_2_internal, rename_data, free_nfs_rename_data, 0) != 0) {
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
struct nfs_link_data *link_data = data->continue_data;
-
+
assert(rpc->magic == RPC_CONTEXT_MAGIC);
if (status == RPC_STATUS_ERROR) {
static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
{
struct nfs_link_data *link_data = data->continue_data;
+ LINK3args args;
/* steal the filehandle */
- link_data->newdir.data.data_len = data->fh.data.data_len;
- link_data->newdir.data.data_val = data->fh.data.data_val;
+ link_data->newdir = data->fh;
data->fh.data.data_val = NULL;
- if (rpc_nfs_link_async(nfs->rpc, nfs_link_cb, &link_data->oldfh, &link_data->newdir, link_data->newobject, data) != 0) {
+ memset(&args, 0, sizeof(LINK3args));
+ args.file = link_data->oldfh;
+ args.link.dir = link_data->newdir;
+ args.link.name = link_data->newobject;
+ if (rpc_nfs3_link_async(nfs->rpc, nfs_link_cb, &args, data) != 0) {
rpc_set_error(nfs->rpc, "RPC error: Failed to send LINK call for %s", data->path);
data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
free_nfs_cb_data(data);
struct nfs_link_data *link_data = data->continue_data;
/* steal the filehandle */
- link_data->oldfh.data.data_len = data->fh.data.data_len;
- link_data->oldfh.data.data_val = data->fh.data.data_val;
+ link_data->oldfh = data->fh;
data->fh.data.data_val = NULL;
if (nfs_lookuppath_async(nfs, link_data->newpath, data->cb, data->private_data, nfs_link_continue_2_internal, link_data, free_nfs_link_data, 0) != 0) {
return nfs->writemax;
}
+void nfs_set_tcp_syncnt(struct nfs_context *nfs, int v) {
+ rpc_set_tcp_syncnt(nfs->rpc, v);
+}
+
+void nfs_set_uid(struct nfs_context *nfs, int uid) {
+ rpc_set_uid(nfs->rpc, uid);
+}
+
+void nfs_set_gid(struct nfs_context *nfs, int gid) {
+ rpc_set_gid(nfs->rpc, gid);
+}
+
void nfs_set_error(struct nfs_context *nfs, char *error_string, ...)
{
va_list ap;
free(nfs->rpc->error_string);
}
nfs->rpc->error_string = str;
- va_end(ap);
+ va_end(ap);
}
/* Dont want any more callbacks even if the socket is closed */
rpc->connect_cb = NULL;
- if (status == RPC_STATUS_ERROR) {
+ if (status == RPC_STATUS_ERROR) {
data->cb(rpc, -EFAULT, command_data, data->private_data);
free_mount_cb_data(data);
return;
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;