}
struct nfs_cb_data;
-typedef int (*continue_func)(struct nfs_context *nfs, struct nfs_cb_data *data);
+typedef int (*continue_func)(struct nfs_context *nfs, fattr3 *attr,
+ struct nfs_cb_data *data);
struct nfs_cb_data {
struct nfs_context *nfs;
int update_pos;
};
-static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh);
+static int nfs_lookup_path_async_internal(struct nfs_context *nfs, fattr3 *attr, struct nfs_cb_data *data, struct nfs_fh3 *fh);
void nfs_set_auth(struct nfs_context *nfs, struct AUTH *auth)
{
}
-
-
-
static void nfs_mount_10_cb(struct rpc_context *rpc, int status, void *command_data, void *private_data)
{
struct nfs_cb_data *data = private_data;
struct nfs_cb_data *data = private_data;
struct nfs_context *nfs = data->nfs;
LOOKUP3res *res;
+ fattr3 *attr;
assert(rpc->magic == RPC_CONTEXT_MAGIC);
return;
}
- if (nfs_lookup_path_async_internal(nfs, data, &res->LOOKUP3res_u.resok.object) != 0) {
- rpc_set_error(nfs->rpc, "Failed to create lookup pdu");
- data->cb(-ENOMEM, nfs, rpc_get_error(nfs->rpc), data->private_data);
- free_nfs_cb_data(data);
- return;
- }
+ attr = res->LOOKUP3res_u.resok.obj_attributes.attributes_follow ?
+ &res->LOOKUP3res_u.resok.obj_attributes.post_op_attr_u.attributes :
+ NULL;
+
+ /* This function will always invoke the callback and cleanup
+ * for failures. So no need to check the return value.
+ */
+ nfs_lookup_path_async_internal(nfs, attr, data, &res->LOOKUP3res_u.resok.object);
}
-static int nfs_lookup_path_async_internal(struct nfs_context *nfs, struct nfs_cb_data *data, struct nfs_fh3 *fh)
+static int nfs_lookup_path_async_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data, struct nfs_fh3 *fh)
{
char *path, *slash;
LOOKUP3args args;
if (slash != NULL) {
*slash = '/';
}
- data->continue_cb(nfs, data);
+ data->continue_cb(nfs, attr, data);
return 0;
}
-
memset(&args, 0, sizeof(LOOKUP3args));
args.what.dir = *fh;
args.what.name = path;
return 0;
}
+static void nfs_lookup_path_getattr_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;
+ GETATTR3res *res;
+ fattr3 *attr;
+
+ 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: GETATTR of %s failed with %s(%d)", data->saved_path, 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;
+ }
+
+ attr = &res->GETATTR3res_u.resok.obj_attributes;
+ /* This function will always invoke the callback and cleanup
+ * for failures. So no need to check the return value.
+ */
+ nfs_lookup_path_async_internal(nfs, attr, data, &nfs->rootfh);
+}
+
static int nfs_lookuppath_async(struct nfs_context *nfs, const char *path, nfs_cb cb, void *private_data, continue_func continue_cb, void *continue_data, void (*free_continue_data)(void *), int continue_int)
{
struct nfs_cb_data *data;
+ struct GETATTR3args args;
if (path[0] == '\0') {
path = ".";
}
data->path = data->saved_path;
-
- if (nfs_lookup_path_async_internal(nfs, data, &nfs->rootfh) != 0) {
- /* return 0 here since the callback will be invoked if there is a failure */
+ if (data->path[0]) {
+ /* This function will always invoke the callback and cleanup
+ * for failures. So no need to check the return value.
+ */
+ nfs_lookup_path_async_internal(nfs, NULL, data, &nfs->rootfh);
return 0;
}
+
+ /* We have a request for "", so just perform a GETATTR3 so we can
+ * return the attributes to the caller.
+ */
+ memset(&args, 0, sizeof(GETATTR3args));
+ args.object = nfs->rootfh;
+ if (rpc_nfs3_getattr_async(nfs->rpc, nfs_lookup_path_getattr_cb, &args, data) != 0) {
+ free_nfs_cb_data(data);
+ return -1;
+ }
return 0;
}
-
-
-
/*
* Async stat()
*/
free_nfs_cb_data(data);
}
-static int nfs_stat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_stat_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct GETATTR3args args;
free_nfs_cb_data(data);
}
-static int nfs_stat64_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_stat64_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct GETATTR3args args;
free_nfs_cb_data(data);
}
-static int nfs_open_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_open_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
int nfsmode = 0;
ACCESS3args args;
/*
* Async chdir()
*/
-static int nfs_chdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_chdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
/* steal saved_path */
free(nfs->cwd);
/*
* Async truncate()
*/
-static int nfs_truncate_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_truncate_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
uint64_t offset = data->continue_int;
struct nfsfh nfsfh;
free_nfs_cb_data(data);
}
-static int nfs_mkdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_mkdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
MKDIR3args args;
free_nfs_cb_data(data);
}
-static int nfs_rmdir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_rmdir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
RMDIR3args args;
return;
}
-static int nfs_creat_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_creat_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
CREATE3args args;
free_nfs_cb_data(data);
}
-static int nfs_unlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_unlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
char *str = data->continue_data;
struct REMOVE3args args;
free_nfs_cb_data(data);
}
-static int nfs_mknod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_mknod_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct mknod_cb_data *cb_data = data->continue_data;
char *str = cb_data->path;
free_nfs_cb_data(data);
}
-static int nfs_opendir_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_opendir_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
READDIRPLUS3args args;
free_nfs_cb_data(data);
}
-static int nfs_statvfs_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_statvfs_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
FSSTAT3args args;
free_nfs_cb_data(data);
}
-static int nfs_readlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_readlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
READLINK3args args;
free_nfs_cb_data(data);
}
-static int nfs_chmod_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_chmod_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
SETATTR3args args;
}
memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
- if (nfs_chmod_continue_internal(nfs, data) != 0) {
+ if (nfs_chmod_continue_internal(nfs, NULL, data) != 0) {
return -1;
}
gid_t gid;
};
-static int nfs_chown_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_chown_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
SETATTR3args args;
struct nfs_chown_data *chown_data = data->continue_data;
}
memcpy(data->fh.data.data_val, nfsfh->fh.data.data_val, data->fh.data.data_len);
- if (nfs_chown_continue_internal(nfs, data) != 0) {
+ if (nfs_chown_continue_internal(nfs, NULL, data) != 0) {
return -1;
}
free_nfs_cb_data(data);
}
-static int nfs_utimes_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_utimes_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
SETATTR3args args;
struct timeval *utimes_data = data->continue_data;
free_nfs_cb_data(data);
}
-static int nfs_access_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_access_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
int nfsmode = 0;
ACCESS3args args;
free_nfs_cb_data(data);
}
-static int nfs_symlink_continue_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_symlink_continue_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_symlink_data *symlink_data = data->continue_data;
SYMLINK3args args;
free_nfs_cb_data(data);
}
-static int nfs_rename_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_rename_continue_2_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_rename_data *rename_data = data->continue_data;
RENAME3args args;
}
-static int nfs_rename_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_rename_continue_1_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_rename_data *rename_data = data->continue_data;
char* newpath = strdup(rename_data->newpath);
free_nfs_cb_data(data);
}
-static int nfs_link_continue_2_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_link_continue_2_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_link_data *link_data = data->continue_data;
LINK3args args;
}
-static int nfs_link_continue_1_internal(struct nfs_context *nfs, struct nfs_cb_data *data)
+static int nfs_link_continue_1_internal(struct nfs_context *nfs, fattr3 *attr _U_, struct nfs_cb_data *data)
{
struct nfs_link_data *link_data = data->continue_data;