From 8ea0ca1893bdb06777c856c3adde7e8be156b222 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Fri, 24 Sep 2010 14:12:37 -0400 Subject: [PATCH] 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 --- daemon/nfs41_ops.h | 6 +++++ daemon/open.c | 3 ++- daemon/symlink.c | 57 ++++++++++++++++++++++++---------------------- 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index 56b941d..85f8d02 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -1020,6 +1020,12 @@ int nfs41_link( IN const nfs41_component *target, 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( IN nfs41_session *session, IN nfs41_path_fh *file, diff --git a/daemon/open.c b/daemon/open.c index e2b65bb..40a425f 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -265,7 +265,8 @@ int handle_open(nfs41_upcall *upcall) upcall->last_error = ERROR_REPARSE; /* 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; } } else diff --git a/daemon/symlink.c b/daemon/symlink.c index 2ea6e01..14f6b2c 100644 --- a/daemon/symlink.c +++ b/daemon/symlink.c @@ -30,7 +30,7 @@ #include "daemon_debug.h" -int abs_path_link( +static int abs_path_link( OUT nfs41_abs_path *path, IN char *path_pos, IN const char *link, @@ -48,15 +48,13 @@ int abs_path_link( if (is_delimiter(*link)) 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 */ while (next_component(link_pos, link_end, &name)) { link_pos = name.name + name.len; + if (is_delimiter(*path_pos)) + path_pos++; + /* handle special components . and .. */ if (name.len == 1 && name.name[0] == '.') continue; @@ -71,19 +69,18 @@ int abs_path_link( continue; } - /* add a \ and copy the component */ - if (FAILED(StringCchCopyNA(path_pos, - path_max-path_pos, "\\", 1))) { - status = ERROR_BUFFER_OVERFLOW; - goto out; - } - path_pos++; + /* copy the component and add a \ */ if (FAILED(StringCchCopyNA(path_pos, path_max-path_pos, name.name, name.len))) { status = ERROR_BUFFER_OVERFLOW; goto out; } 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 */ @@ -98,43 +95,49 @@ out: return status; } -static int follow_link( - IN open_upcall_args *args, - IN nfs41_open_state *state) +int nfs41_symlink_follow( + IN nfs41_session *session, + IN nfs41_path_fh *file, + OUT nfs41_abs_path *target) { char link[NFS41_MAX_PATH_LEN]; + const nfs41_abs_path *path = file->path; ptrdiff_t path_offset; uint32_t link_len; int status; /* read the link */ - status = nfs41_readlink(state->session, &state->file, - NFS41_MAX_PATH_LEN, link, &link_len); + status = nfs41_readlink(session, file, NFS41_MAX_PATH_LEN, link, &link_len); if (status) { - eprintf("nfs41_readlink() failed with %s\n", - nfs_error_string(status)); + eprintf("nfs41_readlink() failed with %s\n", nfs_error_string(status)); status = ERROR_PATH_NOT_FOUND; goto out; } /* overwrite the last component of the path; get the starting offset */ - path_offset = (state->parent.name.name + state->parent.name.len) - - state->path.path; + path_offset = file->name.name - path->path; /* copy the path and update it with the results from link */ - args->symlink.len = state->path.len; - if (FAILED(StringCchCopyNA(args->symlink.path, NFS41_MAX_PATH_LEN, - state->path.path, state->path.len))) { + target->len = path->len; + if (FAILED(StringCchCopyNA(target->path, NFS41_MAX_PATH_LEN, + path->path, path->len))) { status = ERROR_BUFFER_OVERFLOW; goto out; } - status = abs_path_link(&args->symlink, - args->symlink.path + path_offset, link, link_len); + status = abs_path_link(target, target->path + path_offset, link, link_len); if (status) { eprintf("abs_path_link() failed with %d\n", status); status = ERROR_PATH_NOT_FOUND; 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: return status; }