symlink: generalized follow_link()
no longer depends on nfs41_open_state or open_upcall_args renamed to nfs41_symlink_follow() and added prototype to nfs41_ops.h Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
dd48ca17c3
commit
8ea0ca1893
3 changed files with 38 additions and 28 deletions
|
|
@ -1020,6 +1020,12 @@ int nfs41_link(
|
||||||
IN const nfs41_component *target,
|
IN const nfs41_component *target,
|
||||||
OUT OPTIONAL nfs41_path_fh *link_out);
|
OUT OPTIONAL nfs41_path_fh *link_out);
|
||||||
|
|
||||||
|
/* symlink.c */
|
||||||
|
int nfs41_symlink_follow(
|
||||||
|
IN nfs41_session *session,
|
||||||
|
IN nfs41_path_fh *file,
|
||||||
|
OUT nfs41_abs_path *target);
|
||||||
|
|
||||||
int nfs41_readlink(
|
int nfs41_readlink(
|
||||||
IN nfs41_session *session,
|
IN nfs41_session *session,
|
||||||
IN nfs41_path_fh *file,
|
IN nfs41_path_fh *file,
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,8 @@ int handle_open(nfs41_upcall *upcall)
|
||||||
upcall->last_error = ERROR_REPARSE;
|
upcall->last_error = ERROR_REPARSE;
|
||||||
|
|
||||||
/* replace the path with the symlink target */
|
/* replace the path with the symlink target */
|
||||||
status = follow_link(args, state);
|
status = nfs41_symlink_follow(state->session,
|
||||||
|
&state->parent, &state->file, &args->symlink);
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
#include "daemon_debug.h"
|
#include "daemon_debug.h"
|
||||||
|
|
||||||
|
|
||||||
int abs_path_link(
|
static int abs_path_link(
|
||||||
OUT nfs41_abs_path *path,
|
OUT nfs41_abs_path *path,
|
||||||
IN char *path_pos,
|
IN char *path_pos,
|
||||||
IN const char *link,
|
IN const char *link,
|
||||||
|
|
@ -48,15 +48,13 @@ int abs_path_link(
|
||||||
if (is_delimiter(*link))
|
if (is_delimiter(*link))
|
||||||
path_pos = path->path;
|
path_pos = path->path;
|
||||||
|
|
||||||
/* eat trailing slashes from the path */
|
|
||||||
path_pos = (char*)prev_non_delimiter(path_pos, path->path);
|
|
||||||
if (path_pos > path->path)
|
|
||||||
path_pos = (char*)next_delimiter(path_pos, path_pos);
|
|
||||||
|
|
||||||
/* copy each component of link into the path */
|
/* copy each component of link into the path */
|
||||||
while (next_component(link_pos, link_end, &name)) {
|
while (next_component(link_pos, link_end, &name)) {
|
||||||
link_pos = name.name + name.len;
|
link_pos = name.name + name.len;
|
||||||
|
|
||||||
|
if (is_delimiter(*path_pos))
|
||||||
|
path_pos++;
|
||||||
|
|
||||||
/* handle special components . and .. */
|
/* handle special components . and .. */
|
||||||
if (name.len == 1 && name.name[0] == '.')
|
if (name.len == 1 && name.name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -71,19 +69,18 @@ int abs_path_link(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a \ and copy the component */
|
/* copy the component and add a \ */
|
||||||
if (FAILED(StringCchCopyNA(path_pos,
|
|
||||||
path_max-path_pos, "\\", 1))) {
|
|
||||||
status = ERROR_BUFFER_OVERFLOW;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
path_pos++;
|
|
||||||
if (FAILED(StringCchCopyNA(path_pos,
|
if (FAILED(StringCchCopyNA(path_pos,
|
||||||
path_max-path_pos, name.name, name.len))) {
|
path_max-path_pos, name.name, name.len))) {
|
||||||
status = ERROR_BUFFER_OVERFLOW;
|
status = ERROR_BUFFER_OVERFLOW;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
path_pos += name.len;
|
path_pos += name.len;
|
||||||
|
if (FAILED(StringCchCopyNA(path_pos,
|
||||||
|
path_max-path_pos, "\\", 1))) {
|
||||||
|
status = ERROR_BUFFER_OVERFLOW;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure the path is null terminated */
|
/* make sure the path is null terminated */
|
||||||
|
|
@ -98,43 +95,49 @@ out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int follow_link(
|
int nfs41_symlink_follow(
|
||||||
IN open_upcall_args *args,
|
IN nfs41_session *session,
|
||||||
IN nfs41_open_state *state)
|
IN nfs41_path_fh *file,
|
||||||
|
OUT nfs41_abs_path *target)
|
||||||
{
|
{
|
||||||
char link[NFS41_MAX_PATH_LEN];
|
char link[NFS41_MAX_PATH_LEN];
|
||||||
|
const nfs41_abs_path *path = file->path;
|
||||||
ptrdiff_t path_offset;
|
ptrdiff_t path_offset;
|
||||||
uint32_t link_len;
|
uint32_t link_len;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* read the link */
|
/* read the link */
|
||||||
status = nfs41_readlink(state->session, &state->file,
|
status = nfs41_readlink(session, file, NFS41_MAX_PATH_LEN, link, &link_len);
|
||||||
NFS41_MAX_PATH_LEN, link, &link_len);
|
|
||||||
if (status) {
|
if (status) {
|
||||||
eprintf("nfs41_readlink() failed with %s\n",
|
eprintf("nfs41_readlink() failed with %s\n", nfs_error_string(status));
|
||||||
nfs_error_string(status));
|
|
||||||
status = ERROR_PATH_NOT_FOUND;
|
status = ERROR_PATH_NOT_FOUND;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* overwrite the last component of the path; get the starting offset */
|
/* overwrite the last component of the path; get the starting offset */
|
||||||
path_offset = (state->parent.name.name + state->parent.name.len) -
|
path_offset = file->name.name - path->path;
|
||||||
state->path.path;
|
|
||||||
|
|
||||||
/* copy the path and update it with the results from link */
|
/* copy the path and update it with the results from link */
|
||||||
args->symlink.len = state->path.len;
|
target->len = path->len;
|
||||||
if (FAILED(StringCchCopyNA(args->symlink.path, NFS41_MAX_PATH_LEN,
|
if (FAILED(StringCchCopyNA(target->path, NFS41_MAX_PATH_LEN,
|
||||||
state->path.path, state->path.len))) {
|
path->path, path->len))) {
|
||||||
status = ERROR_BUFFER_OVERFLOW;
|
status = ERROR_BUFFER_OVERFLOW;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
status = abs_path_link(&args->symlink,
|
status = abs_path_link(target, target->path + path_offset, link, link_len);
|
||||||
args->symlink.path + path_offset, link, link_len);
|
|
||||||
if (status) {
|
if (status) {
|
||||||
eprintf("abs_path_link() failed with %d\n", status);
|
eprintf("abs_path_link() failed with %d\n", status);
|
||||||
status = ERROR_PATH_NOT_FOUND;
|
status = ERROR_PATH_NOT_FOUND;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* append any components after the symlink */
|
||||||
|
if (FAILED(StringCchCopyA(target->path + target->len,
|
||||||
|
NFS41_MAX_PATH_LEN - target->len, file->name.name + file->name.len))) {
|
||||||
|
status = ERROR_BUFFER_OVERFLOW;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
target->len = (unsigned short)strlen(target->path);
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue