NFSv4: Standardize how we create cb data for split path lookups.
Split path lookups is where we have a path '/this/is/the/path' and we split it up into doing a lookup on '/this/is/the' and append a different operation on 'path'. Create a dedicated function that performs this initialization and remove a lot of code duplication. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>libnfs-4.0.0-vitalif
parent
a72dbc248d
commit
840c9b7367
378
lib/nfs_v4.c
378
lib/nfs_v4.c
|
@ -162,6 +162,40 @@ struct nfs4_cb_data {
|
|||
struct rw_data rw_data;
|
||||
};
|
||||
|
||||
/* Caller will free the returned path. */
|
||||
static char *
|
||||
nfs4_resolve_path(struct nfs_context *nfs, const char *path)
|
||||
{
|
||||
char *new_path = NULL;
|
||||
|
||||
/* Absolute paths we just use as is.
|
||||
* Relateive paths have cwd prepended to them and then become
|
||||
* absolute paths too.
|
||||
*/
|
||||
if (path[0] == '/') {
|
||||
new_path = strdup(path);
|
||||
} else {
|
||||
new_path = malloc(strlen(path) + strlen(nfs->cwd) + 2);
|
||||
if (new_path != NULL) {
|
||||
sprintf(new_path, "%s/%s", nfs->cwd, path);
|
||||
}
|
||||
}
|
||||
if (new_path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory: failed to "
|
||||
"allocate path string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nfs_normalize_path(nfs, new_path)) {
|
||||
nfs_set_error(nfs, "Failed to normalize real path. %s",
|
||||
nfs_get_error(nfs));
|
||||
free(new_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new_path;
|
||||
}
|
||||
|
||||
static void
|
||||
free_nfs4_cb_data(struct nfs4_cb_data *data)
|
||||
{
|
||||
|
@ -179,6 +213,58 @@ free_nfs4_cb_data(struct nfs4_cb_data *data)
|
|||
free(data);
|
||||
}
|
||||
|
||||
static struct nfs4_cb_data *
|
||||
init_cb_data_full_path(struct nfs_context *nfs, const char *path)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return NULL;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
data->nfs = nfs;
|
||||
data->path = nfs4_resolve_path(nfs, path);
|
||||
if (data->path == NULL) {
|
||||
free_nfs4_cb_data(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct nfs4_cb_data *
|
||||
init_cb_data_split_path(struct nfs_context *nfs, const char *orig_path)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
char *path;
|
||||
|
||||
data = init_cb_data_full_path(nfs, orig_path);
|
||||
if (data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = strrchr(data->path, '/');
|
||||
if (path == data->path) {
|
||||
char *ptr;
|
||||
|
||||
for (ptr = data->path; *ptr; ptr++) {
|
||||
*ptr = *(ptr + 1);
|
||||
}
|
||||
/* No path to lookup */
|
||||
data->filler.data = data->path;
|
||||
data->path = strdup("/");
|
||||
} else {
|
||||
*path++ = 0;
|
||||
data->filler.data = strdup(path);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int
|
||||
check_nfs4_error(struct nfs_context *nfs, int status,
|
||||
struct nfs4_cb_data *data, void *command_data,
|
||||
|
@ -387,40 +473,6 @@ nfs_parse_attributes(struct nfs_context *nfs, struct nfs4_cb_data *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Caller will free the returned path. */
|
||||
static char *
|
||||
nfs4_resolve_path(struct nfs_context *nfs, const char *path)
|
||||
{
|
||||
char *new_path = NULL;
|
||||
|
||||
/* Absolute paths we just use as is.
|
||||
* Relateive paths have cwd prepended to them and then become
|
||||
* absolute paths too.
|
||||
*/
|
||||
if (path[0] == '/') {
|
||||
new_path = strdup(path);
|
||||
} else {
|
||||
new_path = malloc(strlen(path) + strlen(nfs->cwd) + 2);
|
||||
if (new_path != NULL) {
|
||||
sprintf(new_path, "%s/%s", nfs->cwd, path);
|
||||
}
|
||||
}
|
||||
if (new_path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory: failed to "
|
||||
"allocate path string");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nfs_normalize_path(nfs, new_path)) {
|
||||
nfs_set_error(nfs, "Failed to normalize real path. %s",
|
||||
nfs_get_error(nfs));
|
||||
free(new_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new_path;
|
||||
}
|
||||
|
||||
static int
|
||||
nfs4_num_path_components(struct nfs_context *nfs, const char *path)
|
||||
{
|
||||
|
@ -1068,27 +1120,16 @@ int nfs4_chdir_async(struct nfs_context *nfs, const char *path,
|
|||
{
|
||||
struct nfs4_cb_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_full_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->path = nfs4_resolve_path(nfs, path);
|
||||
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory duplicating path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->filler.func = nfs4_populate_getattr;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->filler.func = nfs4_populate_getattr;
|
||||
data->filler.max_op = 1;
|
||||
data->filler.data = malloc(2 * sizeof(uint32_t));
|
||||
data->filler.data = malloc(2 * sizeof(uint32_t));
|
||||
if (data->filler.data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"data structure.");
|
||||
|
@ -1147,29 +1188,19 @@ nfs4_stat64_async(struct nfs_context *nfs, const char *path,
|
|||
{
|
||||
struct nfs4_cb_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_full_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
if (no_follow) {
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
}
|
||||
data->path = nfs4_resolve_path(nfs, path);
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory duplicating path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->filler.func = nfs4_populate_getattr;
|
||||
if (no_follow) {
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
}
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->filler.func = nfs4_populate_getattr;
|
||||
data->filler.max_op = 1;
|
||||
data->filler.data = malloc(2 * sizeof(uint32_t));
|
||||
data->filler.data = malloc(2 * sizeof(uint32_t));
|
||||
if (data->filler.data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"data structure.");
|
||||
|
@ -1230,46 +1261,19 @@ nfs4_mkdir_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
int
|
||||
nfs4_mkdir2_async(struct nfs_context *nfs, const char *orig_path, int mode,
|
||||
nfs4_mkdir2_async(struct nfs_context *nfs, const char *path, int mode,
|
||||
nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
uint32_t *u32ptr;
|
||||
char *path;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
|
||||
data->path = nfs4_resolve_path(nfs, orig_path);
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory resolving path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = strrchr(data->path, '/');
|
||||
if (path == data->path) {
|
||||
char *ptr;
|
||||
|
||||
for (ptr = data->path; *ptr; ptr++) {
|
||||
*ptr = *(ptr + 1);
|
||||
}
|
||||
/* No path to lookup */
|
||||
data->filler.data = data->path;
|
||||
data->path = strdup("/");
|
||||
} else {
|
||||
*path++ = 0;
|
||||
data->filler.data = strdup(path);
|
||||
}
|
||||
data->filler.func = nfs4_populate_mkdir;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
|
@ -1342,45 +1346,18 @@ nfs4_remove_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
static int
|
||||
nfs4_remove_async(struct nfs_context *nfs, const char *orig_path,
|
||||
nfs4_remove_async(struct nfs_context *nfs, const char *path,
|
||||
nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
char *path;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
|
||||
data->path = nfs4_resolve_path(nfs, orig_path);
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory resolving path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = strrchr(data->path, '/');
|
||||
if (path == data->path) {
|
||||
char *ptr;
|
||||
|
||||
for (ptr = data->path; *ptr; ptr++) {
|
||||
*ptr = *(ptr + 1);
|
||||
}
|
||||
/* No path to lookup */
|
||||
data->filler.data = data->path;
|
||||
data->path = strdup("/");
|
||||
} else {
|
||||
*path++ = 0;
|
||||
data->filler.data = strdup(path);
|
||||
}
|
||||
data->filler.func = nfs4_populate_remove;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
|
@ -1820,11 +1797,15 @@ nfs4_populate_open(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
* data.blob2 is the attribute value in case of O_CREAT
|
||||
*/
|
||||
int
|
||||
nfs4_open_async(struct nfs_context *nfs, const char *orig_path, int flags,
|
||||
nfs4_open_async(struct nfs_context *nfs, const char *path, int flags,
|
||||
int mode, nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
char *path;
|
||||
|
||||
data = init_cb_data_split_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* O_TRUNC is only valid for O_RDWR or O_WRONLY */
|
||||
if (flags & O_TRUNC && !(flags & (O_RDWR|O_WRONLY))) {
|
||||
|
@ -1835,25 +1816,6 @@ nfs4_open_async(struct nfs_context *nfs, const char *orig_path, int flags,
|
|||
flags &= ~O_APPEND;
|
||||
}
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
|
||||
data->path = nfs4_resolve_path(nfs, orig_path);
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory resolving path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
uint32_t *d;
|
||||
|
||||
|
@ -1886,21 +1848,8 @@ nfs4_open_async(struct nfs_context *nfs, const char *orig_path, int flags,
|
|||
data->filler.blob2.free = free;
|
||||
}
|
||||
|
||||
path = strrchr(data->path, '/');
|
||||
if (path == data->path) {
|
||||
char *ptr;
|
||||
|
||||
for (ptr = data->path; *ptr; ptr++) {
|
||||
*ptr = *(ptr + 1);
|
||||
}
|
||||
/* No path to lookup */
|
||||
data->filler.data = data->path;
|
||||
data->path = strdup("/");
|
||||
} else {
|
||||
*path++ = 0;
|
||||
data->filler.data = strdup(path);
|
||||
}
|
||||
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->filler.func = nfs4_populate_open;
|
||||
data->filler.max_op = 3;
|
||||
data->filler.flags = flags;
|
||||
|
@ -2190,40 +2139,14 @@ nfs4_symlink_async(struct nfs_context *nfs, const char *target,
|
|||
const char *linkname, nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
char *path;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_split_path(nfs, linkname);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->nfs = nfs;
|
||||
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
|
||||
data->path = nfs4_resolve_path(nfs, linkname);
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory resolving path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = strrchr(data->path, '/');
|
||||
if (path == data->path) {
|
||||
char *ptr;
|
||||
|
||||
for (ptr = data->path; *ptr; ptr++) {
|
||||
*ptr = *(ptr + 1);
|
||||
}
|
||||
/* No path to lookup */
|
||||
data->filler.data = data->path;
|
||||
data->path = strdup("/");
|
||||
} else {
|
||||
*path++ = 0;
|
||||
data->filler.data = strdup(path);
|
||||
}
|
||||
data->filler.func = nfs4_populate_symlink;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
|
@ -2279,27 +2202,16 @@ nfs4_readlink_async(struct nfs_context *nfs, const char *path, nfs_cb cb,
|
|||
{
|
||||
struct nfs4_cb_data *data;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_full_path(nfs, path);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
data->nfs = nfs;
|
||||
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->path = nfs4_resolve_path(nfs, path);
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory duplicating path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->filler.func = nfs4_populate_readlink;
|
||||
data->filler.max_op = 1;
|
||||
data->flags |= LOOKUP_FLAG_NO_FOLLOW;
|
||||
|
||||
if (nfs4_lookup_path_async(nfs, data, nfs4_readlink_cb) < 0) {
|
||||
free_nfs4_cb_data(data);
|
||||
|
@ -2574,8 +2486,8 @@ nfs4_populate_link(struct nfs4_cb_data *data, nfs_argop4 *op)
|
|||
op[2].argop = OP_LINK;
|
||||
largs = &op[2].nfs_argop4_u.oplink;
|
||||
memset(largs, 0, sizeof(*largs));
|
||||
largs->newname.utf8string_len = strlen(data->filler.blob1.val);
|
||||
largs->newname.utf8string_val = data->filler.blob1.val;
|
||||
largs->newname.utf8string_len = strlen(data->filler.data);
|
||||
largs->newname.utf8string_val = data->filler.data;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
@ -2632,9 +2544,9 @@ nfs4_link_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
data->filler.max_op = 3;
|
||||
|
||||
free(data->path);
|
||||
data->path = data->filler.blob2.val;
|
||||
data->filler.blob2.val = NULL;
|
||||
data->filler.blob2.free = NULL;
|
||||
data->path = data->filler.blob1.val;
|
||||
data->filler.blob1.val = NULL;
|
||||
data->filler.blob1.free = NULL;
|
||||
|
||||
if (nfs4_lookup_path_async(nfs, data, nfs4_link_2_cb) < 0) {
|
||||
data->cb(-EFAULT, nfs, nfs_get_error(nfs), data->private_data);
|
||||
|
@ -2644,64 +2556,34 @@ nfs4_link_cb(struct rpc_context *rpc, int status, void *command_data,
|
|||
}
|
||||
|
||||
/*
|
||||
* filler.data is the name of the new object
|
||||
* blob0 is the filehandle for newpath parent directory.
|
||||
* blob1 is the name of the new object
|
||||
* blob2 is oldpath.
|
||||
* blob1 is oldpath.
|
||||
*/
|
||||
int
|
||||
nfs4_link_async(struct nfs_context *nfs, const char *oldpath,
|
||||
const char *newpath, nfs_cb cb, void *private_data)
|
||||
{
|
||||
struct nfs4_cb_data *data;
|
||||
char *path;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
data = init_cb_data_split_path(nfs, newpath);
|
||||
if (data == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory. Failed to allocate "
|
||||
"cb data");
|
||||
return -1;
|
||||
}
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
data->nfs = nfs;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
|
||||
data->path = nfs4_resolve_path(nfs, newpath);
|
||||
if (data->path == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory resolving path");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = strrchr(data->path, '/');
|
||||
if (path == data->path) {
|
||||
char *ptr;
|
||||
|
||||
for (ptr = data->path; *ptr; ptr++) {
|
||||
*ptr = *(ptr + 1);
|
||||
}
|
||||
/* No path to lookup */
|
||||
data->filler.blob1.val = data->path;
|
||||
data->filler.blob1.free = free;
|
||||
data->path = strdup("/");
|
||||
} else {
|
||||
*path++ = 0;
|
||||
data->filler.blob1.val = strdup(path);
|
||||
data->filler.blob1.free = free;
|
||||
}
|
||||
|
||||
data->filler.func = nfs4_populate_getfh;
|
||||
data->cb = cb;
|
||||
data->private_data = private_data;
|
||||
data->filler.func = nfs4_populate_getfh;
|
||||
data->filler.max_op = 1;
|
||||
|
||||
/* oldpath */
|
||||
data->filler.blob2.val = strdup(oldpath);
|
||||
if (data->filler.blob2.val == NULL) {
|
||||
data->filler.blob1.val = strdup(oldpath);
|
||||
if (data->filler.blob1.val == NULL) {
|
||||
nfs_set_error(nfs, "Out of memory");
|
||||
free_nfs4_cb_data(data);
|
||||
return -1;
|
||||
}
|
||||
data->filler.blob2.free = free;
|
||||
data->filler.blob1.free = free;
|
||||
|
||||
if (nfs4_lookup_path_async(nfs, data, nfs4_link_cb) < 0) {
|
||||
free_nfs4_cb_data(data);
|
||||
|
|
Loading…
Reference in New Issue