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:
Casey Bodley 2010-09-24 14:12:37 -04:00 committed by unknown
parent dd48ca17c3
commit 8ea0ca1893
3 changed files with 38 additions and 28 deletions

View file

@ -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,

View 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

View file

@ -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;
} }