- From 9359eb1f3b2fb1173bd78096cb5df3299de8ba70 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 6 Feb 2025 12:38:50 +0100
- Subject: [PATCH 1/3] daemon: Split symlink handlers into symlink get/set
- variations
- Cleanup: Split symlink handlers into symlink get/set variations
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/symlink.c | 216 +++++++++++++++++++++++++++--------------------
- 1 file changed, 125 insertions(+), 91 deletions(-)
- diff --git a/daemon/symlink.c b/daemon/symlink.c
- index b601f01..4eeece3 100644
- --- a/daemon/symlink.c
- +++ b/daemon/symlink.c
- @@ -69,7 +69,7 @@ static int abs_path_link(
- }
- /* copy the component and add a \ */
- - if (FAILED(StringCchCopyNA(path_pos, path_max-path_pos, name.name,
- + if (FAILED(StringCchCopyNA(path_pos, path_max-path_pos, name.name,
- name.len))) {
- status = ERROR_BUFFER_OVERFLOW;
- goto out;
- @@ -189,116 +189,61 @@ out:
- }
- -/* NFS41_SYSOP_SYMLINK_GET, NFS41_SYSOP_SYMLINK_SET */
- -static int parse_symlink(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
- +/* NFS41_SYSOP_SYMLINK_GET */
- +static int parse_symlink_get(unsigned char *buffer, uint32_t length,
- + nfs41_upcall *upcall)
- {
- symlink_upcall_args *args = &upcall->args.symlink;
- int status;
- status = get_name(&buffer, &length, &args->path);
- - if (status) goto out;
- -
- - if (upcall->opcode == NFS41_SYSOP_SYMLINK_SET) {
- - /*
- - * args->target_set is not const because handle_symlink() might
- - * have to replace '\\' with '/'
- - */
- - status = get_name(&buffer, &length,
- - (const char **)(&args->target_set));
- -
- - DPRINTF(1,
- - ("parsing NFS41_SYSOP_SYMLINK_SET: "
- - "path='%s' target='%s'\n",
- - args->path, args->target_set));
- - }
- - else if (upcall->opcode == NFS41_SYSOP_SYMLINK_GET) {
- - args->target_set = NULL;
- + if (status)
- + goto out;
- - DPRINTF(1,
- - ("parsing NFS41_SYSOP_SYMLINK_GET: "
- - "path='%s' target='%s'\n",
- - args->path, args->target_set));
- - }
- - else {
- - status = ERROR_INVALID_PARAMETER;
- - eprintf("parse_symlink: Unknown upcall->opcode=%d\n",
- - (int)upcall->opcode);
- - }
- + args->target_set = NULL;
- +
- + DPRINTF(1,
- + ("parse_symlink_get: parsing NFS41_SYSOP_SYMLINK_GET: "
- + "path='%s' target='%s'\n",
- + args->path, args->target_set));
- out:
- return status;
- }
- -static int handle_symlink(void *daemon_context, nfs41_upcall *upcall)
- +static int handle_symlink_get(void *daemon_context, nfs41_upcall *upcall)
- {
- symlink_upcall_args *args = &upcall->args.symlink;
- nfs41_open_state *state = upcall->state_ref;
- int status = NO_ERROR;
- - if (upcall->opcode == NFS41_SYSOP_SYMLINK_SET) {
- - nfs41_file_info info, createattrs;
- -
- - /* don't send windows slashes to the server */
- - char *p;
- - for (p = args->target_set; *p; p++) if (*p == '\\') *p = '/';
- -
- - if (state->file.fh.len) {
- - /* the check in handle_open() didn't catch that we're creating
- - * a symlink, so we have to remove the file it already created */
- - eprintf("handle_symlink: attempting to create a symlink when "
- - "the file=%s was already created on open; sending REMOVE "
- - "first\n", state->file.path->path);
- - status = nfs41_remove(state->session, &state->parent,
- - &state->file.name, state->file.fh.fileid);
- - if (status) {
- - eprintf("nfs41_remove() for symlink='%s' failed with '%s'\n",
- - args->target_set, nfs_error_string(status));
- - status = map_symlink_errors(status);
- - goto out;
- - }
- - }
- + uint32_t len;
- - /* create the symlink */
- - createattrs.attrmask.count = 2;
- - createattrs.attrmask.arr[0] = 0;
- - createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE;
- - createattrs.mode = 0777;
- - status = nfs41_create(state->session, NF4LNK, &createattrs,
- - args->target_set, &state->parent, &state->file, &info);
- - if (status) {
- - eprintf("nfs41_create() for symlink='%s' failed with '%s'\n",
- - args->target_set, nfs_error_string(status));
- - status = map_symlink_errors(status);
- - goto out;
- - }
- - } else {
- - uint32_t len;
- -
- - /* read the link */
- - status = nfs41_readlink(state->session, &state->file,
- - NFS41_MAX_PATH_LEN, args->target_get.path, &len);
- - if (status) {
- - eprintf("nfs41_readlink() for filename='%s' failed with '%s'\n",
- - state->file.path->path, nfs_error_string(status));
- - status = map_symlink_errors(status);
- - goto out;
- - }
- - args->target_get.len = (unsigned short)len;
- - DPRINTF(2, ("returning symlink target '%s'\n", args->target_get.path));
- + /* read the link */
- + status = nfs41_readlink(state->session, &state->file,
- + NFS41_MAX_PATH_LEN, args->target_get.path, &len);
- + if (status) {
- + eprintf("handle_symlink_get: "
- + "nfs41_readlink() for filename='%s' failed with '%s'\n",
- + state->file.path->path, nfs_error_string(status));
- + status = map_symlink_errors(status);
- + goto out;
- }
- + args->target_get.len = (unsigned short)len;
- + DPRINTF(2,
- + ("returning symlink target '%s'\n", args->target_get.path));
- +
- out:
- return status;
- }
- -static int marshall_symlink(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
- +static int marshall_symlink_get(unsigned char *buffer, uint32_t *length,
- + nfs41_upcall *upcall)
- {
- symlink_upcall_args *args = &upcall->args.symlink;
- unsigned short len = (args->target_get.len + 1) * sizeof(WCHAR);
- int status = NO_ERROR;
- - if (upcall->opcode == NFS41_SYSOP_SYMLINK_SET)
- - goto out;
- -
- status = safe_write(&buffer, length, &len, sizeof(len));
- if (status) goto out;
- @@ -311,7 +256,7 @@ static int marshall_symlink(unsigned char *buffer, uint32_t *length, nfs41_upcal
- MB_ERR_INVALID_CHARS,
- args->target_get.path, args->target_get.len,
- (LPWSTR)buffer, len / sizeof(WCHAR))) {
- - eprintf("marshall_symlink: "
- + eprintf("marshall_symlink_get: "
- "MultiByteToWideChar() failed, lasterr=%d\n",
- (int)GetLastError());
- status = ERROR_BUFFER_OVERFLOW;
- @@ -323,15 +268,104 @@ out:
- const nfs41_upcall_op nfs41_op_symlink_get = {
- - .parse = parse_symlink,
- - .handle = handle_symlink,
- - .marshall = marshall_symlink,
- + .parse = parse_symlink_get,
- + .handle = handle_symlink_get,
- + .marshall = marshall_symlink_get,
- .arg_size = sizeof(symlink_upcall_args)
- };
- +/* NFS41_SYSOP_SYMLINK_SET */
- +static int parse_symlink_set(unsigned char *buffer, uint32_t length,
- + nfs41_upcall *upcall)
- +{
- + symlink_upcall_args *args = &upcall->args.symlink;
- + int status;
- +
- + status = get_name(&buffer, &length, &args->path);
- + if (status)
- + goto out;
- +
- + /*
- + * args->target_set is not const because |handle_symlink_set()|
- + * might have to replace '\\' with '/'
- + */
- + status = get_name(&buffer, &length,
- + (const char **)(&args->target_set));
- +
- + DPRINTF(1,
- + ("parse_symlink_set: parsing NFS41_SYSOP_SYMLINK_SET: "
- + "path='%s' target='%s'\n",
- + args->path, args->target_set));
- +
- +out:
- + return status;
- +}
- +
- +static int handle_symlink_set(void *daemon_context, nfs41_upcall *upcall)
- +{
- + symlink_upcall_args *args = &upcall->args.symlink;
- + nfs41_open_state *state = upcall->state_ref;
- + int status = NO_ERROR;
- +
- + nfs41_file_info info, createattrs;
- +
- + /* don't send windows slashes to the server */
- + char *p;
- + for (p = args->target_set; *p; p++) {
- + if (*p == '\\') *p = '/';
- + }
- +
- + if (state->file.fh.len) {
- + /*
- + * the check in handle_open() didn't catch that we're creating
- + * a symlink, so we have to remove the file it already created
- + */
- + eprintf("handle_symlink_set: "
- + "attempting to create a symlink when "
- + "the file='%s' was already created on open; sending "
- + "REMOVE first\n", state->file.path->path);
- + status = nfs41_remove(state->session, &state->parent,
- + &state->file.name, state->file.fh.fileid);
- + if (status) {
- + eprintf("handle_symlink_set: "
- + "nfs41_remove() for symlink='%s' failed with '%s'\n",
- + args->target_set, nfs_error_string(status));
- + status = map_symlink_errors(status);
- + goto out;
- + }
- + }
- +
- + /* create the symlink */
- + createattrs.attrmask.count = 2;
- + createattrs.attrmask.arr[0] = 0;
- + createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE;
- + createattrs.mode = 0777;
- +
- + /* FIXME: What about newgrp support ? */
- +
- + status = nfs41_create(state->session, NF4LNK, &createattrs,
- + args->target_set, &state->parent, &state->file, &info);
- + if (status) {
- + eprintf("handle_symlink_set: "
- + "nfs41_create() for symlink='%s' failed with '%s'\n",
- + args->target_set, nfs_error_string(status));
- + status = map_symlink_errors(status);
- + goto out;
- + }
- +
- +out:
- + return status;
- +}
- +
- +static int marshall_symlink_set(unsigned char *buffer, uint32_t *length,
- + nfs41_upcall *upcall)
- +{
- + return NO_ERROR;
- +}
- +
- const nfs41_upcall_op nfs41_op_symlink_set = {
- - .parse = parse_symlink,
- - .handle = handle_symlink,
- - .marshall = marshall_symlink,
- + .parse = parse_symlink_set,
- + .handle = handle_symlink_set,
- + .marshall = marshall_symlink_set,
- .arg_size = sizeof(symlink_upcall_args)
- };
- --
- 2.45.1
- From 405dee2f37fd0d5ec43d428ebd08752606250c6c Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 6 Feb 2025 12:41:07 +0100
- Subject: [PATCH 2/3] sys,tests: Fix cmd.exe mklink relative links
- Fix cmd.exe mklink relative links, e.g.
- $ cmd /C 'mklink /D targetdir1_sym targetdir1' # should work + add
- testcases
- Reported-by: Lionel Cons <lionelcons1972@gmail.com>
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- sys/nfs41sys_symlink.c | 43 +++++++++++++++++++++++++++++++---------
- tests/manual_testing.txt | 4 ++++
- 2 files changed, 38 insertions(+), 9 deletions(-)
- diff --git a/sys/nfs41sys_symlink.c b/sys/nfs41sys_symlink.c
- index eea2db8..8f4447b 100644
- --- a/sys/nfs41sys_symlink.c
- +++ b/sys/nfs41sys_symlink.c
- @@ -293,17 +293,15 @@ NTSTATUS nfs41_SetSymlinkReparsePoint(
- "absolute path TargetName='%wZ'\n",
- &TargetName);
- - /* Strip "\\??\\" prefix */
- - if (!memcmp(&TargetName.Buffer[0], L"\\??\\",
- - (4*sizeof(wchar_t)))) {
- + /* UNC path ? */
- + if ((TargetName.Length > 8*sizeof(wchar_t)) &&
- + (!memcmp(&TargetName.Buffer[0], L"\\??\\UNC\\",
- + (8*sizeof(wchar_t))))) {
- +
- + /* Strip "\\??\\" prefix */
- TargetName.Buffer += 4;
- TargetName.MaximumLength = TargetName.Length =
- TargetName.Length-(4*sizeof(wchar_t));
- - }
- -
- - /* UNC path ? */
- - if (!memcmp(&TargetName.Buffer[0], L"UNC\\",
- - (4*sizeof(wchar_t)))) {
- /*
- * Turn "UNC\" into "\\"
- @@ -319,13 +317,22 @@ NTSTATUS nfs41_SetSymlinkReparsePoint(
- "UNC TargetName='%wZ'\n",
- &TargetName);
- }
- - else {
- + /* DEVICELETTR path ? */
- + else if ((TargetName.Length >= 6*sizeof(wchar_t)) &&
- + (!memcmp(&TargetName.Buffer[0], L"\\??\\",
- + (4*sizeof(wchar_t)))) &&
- + (TargetName.Buffer[5] == L':')) {
- wchar_t devletter;
- DbgP("nfs41_SetSymlinkReparsePoint: "
- "DEVLETTER TargetName='%wZ'\n",
- &TargetName);
- + /* Strip "\\??\\" prefix */
- + TargetName.Buffer += 4;
- + TargetName.MaximumLength = TargetName.Length =
- + TargetName.Length-(4*sizeof(wchar_t));
- +
- if ((TargetName.Buffer[1] != L':') ||
- (TargetName.Buffer[2] != L'\\')) {
- status = STATUS_INVALID_PARAMETER;
- @@ -374,6 +381,24 @@ NTSTATUS nfs41_SetSymlinkReparsePoint(
- "new TargetName='%wZ'\n",
- &TargetName);
- }
- + else if ((TargetName.Length > 1*sizeof(wchar_t)) &&
- + (
- + (TargetName.Buffer[0] == L'\\') ||
- + (TargetName.Buffer[0] == L'/') ||
- + (TargetName.Buffer[0] == L':')
- + )) {
- + DbgP("nfs41_SetSymlinkReparsePoint: "
- + "TargetName='%wZ' should not start "
- + "with '/', '\\' or ':'\n",
- + &TargetName);
- + status = STATUS_INVALID_PARAMETER;
- + goto out;
- + }
- + else {
- + DbgP("nfs41_SetSymlinkReparsePoint: "
- + "relative symlink TargetName='%wZ'\n",
- + &TargetName);
- + }
- }
- status = nfs41_UpcallCreate(NFS41_SYSOP_SYMLINK_SET, &Fobx->sec_ctx,
- diff --git a/tests/manual_testing.txt b/tests/manual_testing.txt
- index f8a006c..173c753 100644
- --- a/tests/manual_testing.txt
- +++ b/tests/manual_testing.txt
- @@ -179,6 +179,10 @@ powershell -Command 'New-Item -Path sym_mypsdir1 -ItemType SymbolicLink -Value m
- # 4. powershell mklink file
- mkdir mypsfile1
- powershell -Command 'New-Item -Path sym_mypsfile1 -ItemType SymbolicLink -Value mypsfile1'
- +# 5. Relative links:
- +mkdir targetdir1
- +cmd /C 'mklink /D targetdir1_sym targetdir1'
- +cmd /C 'mklink /D targetdir2_sym .\targetdir1'
- #
- # Tests for groups
- --
- 2.45.1
- From b52dad8aecf95ed8e32b6b3df66d1d7b77c965ec Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 6 Feb 2025 14:53:12 +0100
- Subject: [PATCH 3/3] daemon: |abs_path_link()| should preserve link's UNC
- prefix ("\\") in path argument
- |abs_path_link()| should preserve link's UNC prefix ("\\") in path
- argument
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/symlink.c | 26 +++++++++++++++++++++++++-
- 1 file changed, 25 insertions(+), 1 deletion(-)
- diff --git a/daemon/symlink.c b/daemon/symlink.c
- index 4eeece3..59894e2 100644
- --- a/daemon/symlink.c
- +++ b/daemon/symlink.c
- @@ -43,9 +43,21 @@ static int abs_path_link(
- const char *link_end = link + link_len;
- int status = NO_ERROR;
- + DPRINTF(2,
- + ("--> abs_path_link(path_pos='%s', link='%.*s', link_len=%d)\n",
- + path_pos, (int)link_len, link, (int)link_len));
- +
- + /* UNC path ? Make sure we return \\... */
- + if ((link_len > 2) && (!memcmp(link, "//", 2))) {
- + path->path[0] = '\\';
- + path->path[1] = '\\';
- + path_pos = path->path+2;
- + link_pos += 2;
- + }
- /* if link is an absolute path, start path_pos at the beginning */
- - if (is_delimiter(*link))
- + else if (is_delimiter(*link)) {
- path_pos = path->path;
- + }
- /* copy each component of link into the path */
- while (next_component(link_pos, link_end, &name)) {
- @@ -89,6 +101,18 @@ static int abs_path_link(
- *path_pos = '\0';
- out:
- path->len = (unsigned short)(path_pos - path->path);
- +
- + if (status) {
- + DPRINTF(2,
- + ("<-- abs_path_link(), status=%d\n",
- + status));
- + }
- + else {
- + DPRINTF(2,
- + ("<-- abs_path_link(path='%.*s'), status=%d\n",
- + (int)path->len, path->path, status));
- + }
- +
- return status;
- }
- --
- 2.45.1
msnfs41client: Patches for mklink fixes, symlink translation fixes+misc, 2025-02-06
Posted by Anonymous on Thu 6th Feb 2025 14:00
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.