- From 9e91e7fa39fb97a07b11b8078a9050b71c570337 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Sat, 6 Sep 2025 17:11:33 +0200
- Subject: [PATCH 01/12] cygwin: Add codepath to copy®ister kernel module and
- network provider dll manually
- Add codepath to copy®ister kernel module and network provider dll
- manually. We need this for testing the Windows 11/ARM64 port, because
- right now
- $ rundll32 setupapi.dll,InstallHinfSection DefaultInstall 132 ./nfs41rdr.inf #
- does not work on Windows 11/ARM64.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin/devel/msnfs41client.bash | 79 ++++++++++++++++++++++++++++++---
- 1 file changed, 73 insertions(+), 6 deletions(-)
- diff --git a/cygwin/devel/msnfs41client.bash b/cygwin/devel/msnfs41client.bash
- index cc104a6..1c495d0 100755
- --- a/cygwin/devel/msnfs41client.bash
- +++ b/cygwin/devel/msnfs41client.bash
- @@ -381,8 +381,12 @@ function nfsclient_disable_autostartservices
- sc config 'ms-nfs41-client-globalmountall-service' start=disabled
- }
- +typeset -r use_nfs41rdrinf=true
- +
- function nfsclient_adddriver
- {
- + typeset -i res
- +
- set -o nounset
- set -o xtrace
- set -o errexit
- @@ -404,7 +408,37 @@ function nfsclient_adddriver
- nfs_install -D
- printf 'after nfs_install: ProviderOrder="%s"\n' "$( strings -a '/proc/registry/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/NetworkProvider/Order/ProviderOrder')"
- - rundll32 setupapi.dll,InstallHinfSection DefaultInstall 132 ./nfs41rdr.inf
- + if ${use_nfs41rdrinf} ; then
- + rundll32 setupapi.dll,InstallHinfSection DefaultInstall 132 ./nfs41rdr.inf
- + else
- + #
- + # Install kernel driver and network provider DLL "manually"
- + # (this is the same functionality which the nfs41rdr.inf should do)
- + #
- + rm -f '/cygdrive/c/Windows/System32/drivers/nfs41_driver.sys'
- + cp 'nfs41_driver.sys' '/cygdrive/c/Windows/System32/drivers/nfs41_driver.sys'
- + rm -f '/cygdrive/c/Windows/System32/nfs41_np.dll'
- + cp 'nfs41_np.dll' '/cygdrive/c/Windows/System32/nfs41_np.dll'
- +
- + #
- + # create nfs41_driver service if it does not exists
- + # (ERROR_SERVICE_DOES_NOT_EXIST==1060, 1060-1024==36)
- + #
- + set +o errexit
- + sc query nfs41_driver >'/dev/null' 2>&1
- + (( res=$? ))
- + set -o errexit
- +
- + if (( res == 36 )) ; then
- + sc create nfs41_driver binPath='C:\Windows\System32\drivers\nfs41_driver.sys' type=filesys group=network start=system tag=8
- + fi
- +
- + regtool add '/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/nfs41_driver'
- + regtool add '/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/nfs41_driver/NetworkProvider'
- + regtool -s set '/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/nfs41_driver/NetworkProvider/DeviceName' '\Device\nfs41_driver'
- + regtool -s set '/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/nfs41_driver/NetworkProvider/Name' 'NFS41 Network'
- + regtool -s set '/HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/nfs41_driver/NetworkProvider/ProviderPath' 'System32\nfs41_np.dll'
- + fi
- #
- # Hack: Manually Add 32bit provider DLL to a 64bit system, so
- @@ -413,7 +447,8 @@ function nfsclient_adddriver
- #
- if is_windows_64bit ; then
- # copy from the 32bit install dir
- - cp './i686/nfs41_np.dll' '/cygdrive/c/Windows/SysWOW64/'
- + rm -f '/cygdrive/c/Windows/SysWOW64/nfs41_np.dll'
- + cp './i686/nfs41_np.dll' '/cygdrive/c/Windows/SysWOW64/nfs41_np.dll'
- fi
- return 0
- @@ -436,12 +471,44 @@ function nfsclient_removedriver
- fi
- nfs_install.exe 0
- - rundll32.exe setupapi.dll,InstallHinfSection DefaultUninstall 132 ./nfs41rdr.inf
- - rm /cygdrive/c/Windows/System32/nfs41_np.dll || true
- +
- + if ${use_nfs41rdrinf} ; then
- + rundll32.exe setupapi.dll,InstallHinfSection DefaultUninstall 132 ./nfs41rdr.inf
- +
- + # nfs41rdr.inf should do this, but we do this here for testing
- + if [[ -f '/cygdrive/c/Windows/System32/drivers/nfs41_driver.sys' ]] ; then
- + printf '# %q leftover from INF uninstall, removing...\n' \
- + '/cygdrive/c/Windows/System32/drivers/nfs41_driver.sys'
- + rm -f '/cygdrive/c/Windows/System32/drivers/nfs41_driver.sys' || true
- + fi
- + if [[ -f '/cygdrive/c/Windows/System32/nfs41_np.dll' ]] ; then
- + printf '# %q leftover from INF uninstall, removing...\n' \
- + '/cygdrive/c/Windows/System32/nfs41_np.dll'
- + rm -f '/cygdrive/c/Windows/System32/nfs41_np.dll' || true
- + fi
- + else
- + #
- + # Remove kernel driver and network provider DLL "manually"
- + # (this is the same functionality which the nfs41rdr.inf should do)
- + #
- +
- + #sc stop nfs41_driver
- + #sc delete nfs41_driver
- +
- + # regtool fails with an error if we try to delete the nfs41_driver dir
- + reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\nfs41_driver" /f || true
- +
- + rm -f '/cygdrive/c/Windows/System32/drivers/nfs41_driver.sys' || true
- + rm -f '/cygdrive/c/Windows/System32/nfs41_np.dll' || true
- + fi
- +
- + #
- + # Hack: Manually remove 32bit provider DLL on a 64bit system,
- + # (see comment in "nfsclient_adddriver")
- + #
- if is_windows_64bit ; then
- - rm '/cygdrive/c/Windows/SysWOW64/nfs41_np.dll' || true
- + rm -f '/cygdrive/c/Windows/SysWOW64/nfs41_np.dll' || true
- fi
- - rm /cygdrive/c/Windows/System32/drivers/nfs41_driver.sys || true
- sync
- --
- 2.51.0
- From a0b77cbe3111c807ac6758838898363947ee96bb Mon Sep 17 00:00:00 2001
- From: Aurelien Couderc <aurelien.couderc2002@gmail.com>
- Date: Mon, 8 Sep 2025 22:06:00 +0200
- Subject: [PATCH 02/12] cygwin,nfs41rdr.inf: Provide a catalog file for
- nfs41rdr.inf
- Provide a catalog file for nfs41rdr.inf.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin/Makefile.install | 2 ++
- nfs41rdr.inf | 2 +-
- 2 files changed, 3 insertions(+), 1 deletion(-)
- diff --git a/cygwin/Makefile.install b/cygwin/Makefile.install
- index e9f68df..6d2aaaa 100644
- --- a/cygwin/Makefile.install
- +++ b/cygwin/Makefile.install
- @@ -72,7 +72,9 @@ installdest:
- # workaround for coreutils 9.5-1 /bin/cp bug stuck in an endless loop with compressed files
- chattr -V -c $(VS_BUILD_DIR)/nfs41_driver.*
- cp $(VS_BUILD_DIR)/nfs41_driver.* $(DESTDIR)/$(CYGWIN_BASEPATH)/lib/msnfs41client/.
- + # Copy kernel driver INF file and generate signature catalog
- cp $(PROJECT_BASEDIR_DIR)/nfs41rdr.inf $(DESTDIR)/$(CYGWIN_BASEPATH)/lib/msnfs41client/.
- + (cd "$(DESTDIR)/$(CYGWIN_BASEPATH)/lib/msnfs41client/" && '/cygdrive/c/Program Files (x86)/Windows Kits/10/bin/x86/Inf2Cat.exe' /driver:. /os:10_X86,10_X64,10_VB_ARM64)
- cp $(PROJECT_BASEDIR_DIR)/etc_netconfig $(DESTDIR)/$(CYGWIN_BASEPATH)/lib/msnfs41client/.
- cp $(PROJECT_BASEDIR_DIR)/ms-nfs41-idmap.conf $(DESTDIR)/$(CYGWIN_BASEPATH)/lib/msnfs41client/.
- cp $(CYGWIN_MAKEFILE_DIR)/devel/msnfs41client.bash $(DESTDIR)/$(CYGWIN_BASEPATH)/lib/msnfs41client/msnfs41client
- diff --git a/nfs41rdr.inf b/nfs41rdr.inf
- index 4274370..03339bb 100644
- --- a/nfs41rdr.inf
- +++ b/nfs41rdr.inf
- @@ -3,7 +3,7 @@ Signature="$CHICAGO$"
- DriverVer=06/12/2024,1.0.0.0
- Class=NetService
- ClassGUID={4d36e974-e325-11ce-bfc1-08002be10318}
- -CatalogFile=catalogfile.cat
- +CatalogFile=nfs41rdr.cat
- Provider=%ProviderName%
- [SourceDisksNames]
- --
- 2.51.0
- From c194bd9eab4c51517f144d1fbc2f09dfb220b2cd Mon Sep 17 00:00:00 2001
- From: Aurelien Couderc <aurelien.couderc2002@gmail.com>
- Date: Mon, 8 Sep 2025 22:08:11 +0200
- Subject: [PATCH 03/12] cygwin: /sbin/msnfs41client run_service+sys_run_service
- should start nfs41_driver
- /sbin/msnfs41client run_service+sys_run_service should start nfs41_driver,
- otherwise a reboot is always neccesary even for a new install.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin/devel/msnfs41client.bash | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
- diff --git a/cygwin/devel/msnfs41client.bash b/cygwin/devel/msnfs41client.bash
- index 1c495d0..0dfc94a 100755
- --- a/cygwin/devel/msnfs41client.bash
- +++ b/cygwin/devel/msnfs41client.bash
- @@ -567,6 +567,12 @@ function nfsclient_rundeamon
- set -o xtrace
- + #
- + # start kernel driver if it is not running yet
- + # (can happen directly after installation if no reboot was made)
- + #
- + sc start nfs41_driver || true
- +
- # switch to UTF-8 codepage so debug output with non-ASCII characters
- # gets printed correctly on a terminal
- chcp.com 65001
- @@ -687,6 +693,12 @@ function nfsclient_system_rundeamon
- set -o xtrace
- + #
- + # start kernel driver if it is not running yet
- + # (can happen directly after installation if no reboot was made)
- + #
- + sc start nfs41_driver || true
- +
- # switch to UTF-8 codepage so debug output with non-ASCII characters
- # gets printed correctly on a terminal
- chcp.com 65001
- --
- 2.51.0
- From 4b5e06bb9f11dab575c02c9b560f732bc76367e6 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 9 Sep 2025 12:58:32 +0200
- Subject: [PATCH 04/12] cygwin,tests: Reimplement nfs_globalmount.ksh as
- nfs_globalmount.exe
- Reimplement nfs_globalmount.ksh as nfs_globalmount.exe, so it can be
- easily called from cmd.exe, powershell.exe, and be whitelisted in MS Defender.
- Fixes: https://sourceforge.net/p/ms-nfs41-client/mailman/message/59230996/
- Reported-by: Mark Liam Brown <brownmarkliam@gmail.com>
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- cygwin/Makefile.install | 11 +-
- .../utils/nfs_globalmount/nfs_globalmount.ksh | 30 ------
- tests/winrunassystem/Makefile | 38 ++++++-
- tests/winrunassystem/winrunassystem.c | 100 ++++++++++++++----
- 4 files changed, 123 insertions(+), 56 deletions(-)
- delete mode 100644 cygwin/utils/nfs_globalmount/nfs_globalmount.ksh
- diff --git a/cygwin/Makefile.install b/cygwin/Makefile.install
- index 6d2aaaa..ea3dc0f 100644
- --- a/cygwin/Makefile.install
- +++ b/cygwin/Makefile.install
- @@ -88,10 +88,6 @@ installdest:
- git diff -w >"$(DESTDIR)/$(CYGWIN_BASEPATH)/usr/src/msnfs41client/msnfs41client_diff_w.diff"
- git diff >"$(DESTDIR)/$(CYGWIN_BASEPATH)/usr/src/msnfs41client/msnfs41client_diff.diff"
- @ printf "# Package utilties\n"
- - cp $(CYGWIN_MAKEFILE_DIR)/utils/nfs_globalmount/nfs_globalmount.ksh $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/nfs_globalmount
- - chmod a+x $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/nfs_globalmount
- - PATH+=":$(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/" \
- - /usr/bin/ksh93 $(CYGWIN_MAKEFILE_DIR)/utils/nfs_globalmount/nfs_globalmount.ksh --nroff 2>"$(DESTDIR)/$(CYGWIN_BASEPATH)/usr/share/man/man1/nfs_globalmount.1" || true
- cp $(CYGWIN_MAKEFILE_DIR)/utils/mountall_msnfs41client/mountall_msnfs41client.ksh $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/mountall_msnfs41client
- chmod a+x $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/mountall_msnfs41client
- PATH+=":$(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/" \
- @@ -139,6 +135,13 @@ installdest:
- else \
- (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/ && $(LINKEXE) winrunassystem.i686.exe winrunassystem.exe) \
- fi
- + cp "$(PROJECT_BASEDIR_DIR)/tests/winrunassystem/nfs_globalmount.x86_64.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/nfs_globalmount.x86_64.exe
- + cp "$(PROJECT_BASEDIR_DIR)/tests/winrunassystem/nfs_globalmount.i686.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/nfs_globalmount.i686.exe
- + if [[ "$(CYGWIN_BASEPATH)" == *64* ]] ; then \
- + (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/ && $(LINKEXE) nfs_globalmount.x86_64.exe nfs_globalmount.exe) \
- + else \
- + (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/sbin/ && $(LINKEXE) nfs_globalmount.i686.exe nfs_globalmount.exe) \
- + fi
- cp "$(PROJECT_BASEDIR_DIR)/tests/lssparse/lssparse.x86_64.exe" $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/lssparse.x86_64.exe
- if [[ "$(CYGWIN_BASEPATH)" == *64* ]] ; then \
- (cd $(DESTDIR)/$(CYGWIN_BASEPATH)/bin/ && $(LINKEXE) lssparse.x86_64.exe lssparse.exe) \
- diff --git a/cygwin/utils/nfs_globalmount/nfs_globalmount.ksh b/cygwin/utils/nfs_globalmount/nfs_globalmount.ksh
- deleted file mode 100644
- index c4edd41..0000000
- --- a/cygwin/utils/nfs_globalmount/nfs_globalmount.ksh
- +++ /dev/null
- @@ -1,30 +0,0 @@
- -#!/bin/ksh93
- -
- -# ksh93 scripts using AST getopts(1) support --nroff,
- -# but we do not do that yet
- -[[ "$1" == '--nroff' ]] && exit 1
- -
- -function is_windows_admin_account
- -{
- - #
- - # Test whether we have the Windows permissions to install DLLs
- - # and the kernel module
- - #
- - # Usually Windows Adminstrator rights are indicated by the
- - # membership in group "544(Administratoren)" (Cygwin maps
- - # "SID S-1-5-32-544" to GID 544)
- - #
- - if [[ "$(/bin/id -G)" =~ (^|[[:space:]]+)544([[:space:]]+|$) ]] ; then
- - return 0
- - fi
- - return 1
- -}
- -
- -if ! is_windows_admin_account ; then
- - printf $"%s: Requires Windows Adminstator permissions.\n" "$0"
- - exit 1
- -fi
- -
- -/sbin/winrunassystem "$(cygpath -w '/sbin/nfs_mount.exe')" "$@"
- -exit $?
- -# EOF.
- diff --git a/tests/winrunassystem/Makefile b/tests/winrunassystem/Makefile
- index 69ce1ab..881396d 100644
- --- a/tests/winrunassystem/Makefile
- +++ b/tests/winrunassystem/Makefile
- @@ -5,22 +5,52 @@
- # POSIX Makefile
- SIGNTOOL="/cygdrive/c/Program Files (x86)/Microsoft SDKs/ClickOnce/SignTool/signtool.exe"
- -all: winrunassystem.i686.exe winrunassystem.x86_64.exe winrunassystem.exe
- +all: \
- + winrunassystem.i686.exe \
- + winrunassystem.x86_64.exe \
- + winrunassystem.exe \
- + nfs_globalmount.i686.exe \
- + nfs_globalmount.x86_64.exe \
- + nfs_globalmount.exe
- +#
- +# winrunassystem.exe
- +#
- winrunassystem.i686.exe: winrunassystem.c
- - clang -target i686-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o $@
- + clang -target i686-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DBUILD_WINRUNASSYSTEM=1 -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o $@
- bash -x -c '$(SIGNTOOL) sign /ph /fd "sha256" /sha1 "$${CERTIFICATE_THUMBPRINT%$$(printf "\r")}" $@'
- winrunassystem.x86_64.exe: winrunassystem.c
- - clang -target x86_64-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o $@
- + clang -target x86_64-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DBUILD_WINRUNASSYSTEM=1 -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o $@
- bash -x -c '$(SIGNTOOL) sign /ph /fd "sha256" /sha1 "$${CERTIFICATE_THUMBPRINT%$$(printf "\r")}" $@'
- winrunassystem.exe: winrunassystem.x86_64.exe
- ln -s winrunassystem.x86_64.exe $@
- +
- +#
- +# nfs_globalmount.exe
- +#
- +# (implemented *.exe instead of a script,so it can be easily called from
- +# cmd.exe, powershell.exe, and be whitelisted in MS Defender)
- +#
- +nfs_globalmount.i686.exe: winrunassystem.c
- + clang -target i686-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DBUILD_NFS_GLOBALMOUNT=1 -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o $@
- + bash -x -c '$(SIGNTOOL) sign /ph /fd "sha256" /sha1 "$${CERTIFICATE_THUMBPRINT%$$(printf "\r")}" $@'
- +
- +nfs_globalmount.x86_64.exe: winrunassystem.c
- + clang -target x86_64-pc-windows-gnu -std=gnu17 -municode -Wall -Wextra -DBUILD_NFS_GLOBALMOUNT=1 -DUNICODE=1 -D_UNICODE=1 -g winrunassystem.c -lWtsapi32 -o $@
- + bash -x -c '$(SIGNTOOL) sign /ph /fd "sha256" /sha1 "$${CERTIFICATE_THUMBPRINT%$$(printf "\r")}" $@'
- +
- +nfs_globalmount.exe: nfs_globalmount.x86_64.exe
- + ln -s nfs_globalmount.x86_64.exe $@
- +
- clean:
- rm -fv \
- winrunassystem.i686.exe \
- winrunassystem.x86_64.exe \
- - winrunassystem.exe
- + winrunassystem.exe \
- + nfs_globalmount.i686.exe \
- + nfs_globalmount.x86_64.exe \
- + nfs_globalmount.exe
- # EOF.
- diff --git a/tests/winrunassystem/winrunassystem.c b/tests/winrunassystem/winrunassystem.c
- index 07b166d..c37ebfd 100644
- --- a/tests/winrunassystem/winrunassystem.c
- +++ b/tests/winrunassystem/winrunassystem.c
- @@ -80,7 +80,6 @@ static void LaunchInteractiveProcess(void);
- static void WINAPI ServiceCtrlHandler(DWORD CtrlCode);
- static void WINAPI ServiceMain(DWORD argc, LPWSTR* argv);
- -
- // #define DBG 1
- #ifdef DBG
- @@ -573,26 +572,10 @@ done:
- }
- static
- -void usage(const wchar_t *av0)
- -{
- - (void)fwprintf(stderr,
- - L"%ls: Run command as user SYSTEM\n",
- - av0);
- -}
- -
- -int wmain(int argc, wchar_t *argv[])
- +int winrunassystem_main(int argc, wchar_t *argv[])
- {
- int retval = EXIT_FAILURE;
- - if ((argc == 1) ||
- - ((argc == 2) &&
- - ((wcscmp(argv[1], L"--help") == 0) ||
- - (wcscmp(argv[1], L"-h") == 0) ||
- - (wcscmp(argv[1], L"/?") == 0)))) {
- - usage(argv[0]);
- - return EXIT_USAGE;
- - }
- -
- /*
- * If started with "--service", run as a service
- */
- @@ -663,3 +646,84 @@ int wmain(int argc, wchar_t *argv[])
- return retval;
- }
- +
- +#ifdef BUILD_WINRUNASSYSTEM
- +static
- +void usage(const wchar_t *av0)
- +{
- + (void)fwprintf(stderr,
- + L"%ls: Run command as user SYSTEM\n",
- + av0);
- +}
- +
- +int wmain(int argc, wchar_t *argv[])
- +{
- + if ((argc == 1) ||
- + ((argc == 2) &&
- + ((wcscmp(argv[1], L"--help") == 0) ||
- + (wcscmp(argv[1], L"-h") == 0) ||
- + (wcscmp(argv[1], L"/?") == 0)))) {
- + usage(argv[0]);
- + return EXIT_USAGE;
- + }
- +
- + return winrunassystem_main(argc, argv);
- +}
- +#elif BUILD_NFS_GLOBALMOUNT
- +
- +/*
- + * Implement /sbin/nfs_globalmount.exe as EXE instead of a script,
- + * so it can be easily called from cmd.exe, powershell.exe, and
- + * be whitelisted in MS Defender
- + */
- +
- +/* Paths to nfs_mount*.exe */
- +#ifdef _WIN64
- +#define NFS_MOUNT_PATH L"C:\\cygwin64\\sbin\\nfs_mount.exe"
- +#define NFS_MOUNT_PATH_X86 L"C:\\cygwin64\\sbin\\nfs_mount.i686.exe"
- +#define NFS_MOUNT_PATH_AMD64 L"C:\\cygwin64\\sbin\\nfs_mount.x86_64.exe"
- +#else
- +#define NFS_MOUNT_PATH L"C:\\cygwin\\sbin\\nfs_mount.exe"
- +#define NFS_MOUNT_PATH_X86 L"C:\\cygwin\\sbin\\nfs_mount.i686.exe"
- +#define NFS_MOUNT_PATH_AMD64 L"C:\\cygwin\\sbin\\nfs_mount.x86_64.exe"
- +#endif /* _WIN64 */
- +/* FIXME: What about ARM64 ? */
- +
- +int wmain(int argc, wchar_t *argv[])
- +{
- + int i;
- + const wchar_t *nfs_mount_path;
- +
- + /*
- + * Select nfs_mount.exe binary based on our argv[0] name, e.g.
- + * "nfs_globalmount.i686.exe" ---> "/sbin/nfs_mount.i686.exe",
- + * "nfs_globalmount.x86_64.exe" ---> "/sbin/nfs_mount.x86_64.exe",
- + * etc
- + *
- + * FIXME: What about ARM64 ?
- + */
- + if (wcsstr(argv[0], L".i686") != NULL) {
- + nfs_mount_path = NFS_MOUNT_PATH_X86;
- + }
- + else if (wcsstr(argv[0], L".x86_64") != NULL) {
- + nfs_mount_path = NFS_MOUNT_PATH_AMD64;
- + }
- + else {
- + nfs_mount_path = NFS_MOUNT_PATH;
- + }
- +
- + if ((argc > 2) && (wcscmp(argv[1], L"--service") == 0)) {
- + return winrunassystem_main(argc, argv);
- + }
- + else {
- + wchar_t **new_argv = (wchar_t **)alloca(sizeof(wchar_t *)*(argc+3));
- + new_argv[0] = argv[0];
- + new_argv[1] = (wchar_t *)nfs_mount_path;
- + for (i=1 ; i < argc ; i++)
- + new_argv[i+1] = argv[i];
- + return winrunassystem_main(argc+1, new_argv);
- + }
- +}
- +#else
- +#error Unknown target, BUILD_WINRUNASSYSTEM+BUILD_NFS_GLOBALMOUNT not set
- +#endif
- --
- 2.51.0
- From d526e0efecdd298a7d6f0f3e8b2cbdaa49366498 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 9 Sep 2025 13:10:09 +0200
- Subject: [PATCH 05/12] tests: winrunassystem should not hang if it cannot
- create the child process
- winrunassystem should not hang if it cannot create the child process.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- tests/winrunassystem/winrunassystem.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
- diff --git a/tests/winrunassystem/winrunassystem.c b/tests/winrunassystem/winrunassystem.c
- index c37ebfd..c0e415c 100644
- --- a/tests/winrunassystem/winrunassystem.c
- +++ b/tests/winrunassystem/winrunassystem.c
- @@ -249,8 +249,18 @@ void LaunchInteractiveProcess(void)
- NULL,
- &si,
- &pi)) {
- - (void)printf("CreateProcess failed (%d).\n", (int)GetLastError());
- - return;
- + char errbuff[16384];
- + DWORD lasterr = GetLastError();
- +
- + (void)snprintf(errbuff, sizeof(errbuff),
- + "Cannot create process for '%s', lasterr=%d\n",
- + buffer, (int)lasterr);
- + (void)WriteFile(hFile_stderr,
- + errbuff, strlen(errbuff), NULL, NULL);
- +
- + child_retval = 127;
- +
- + goto done;
- }
- (void)WaitForSingleObject(pi.hProcess, INFINITE);
- --
- 2.51.0
- From 700c738ec1444e7bcedec131d3277b2d692fe9b2 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 9 Sep 2025 13:35:14 +0200
- Subject: [PATCH 06/12] tests: winrunassystem should print an error message if
- called from non-admin user
- winrunassystem should print an error message if called from non-admin user.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- tests/winrunassystem/winrunassystem.c | 26 +++++++++++++++++++++++++-
- 1 file changed, 25 insertions(+), 1 deletion(-)
- diff --git a/tests/winrunassystem/winrunassystem.c b/tests/winrunassystem/winrunassystem.c
- index c0e415c..68b2e30 100644
- --- a/tests/winrunassystem/winrunassystem.c
- +++ b/tests/winrunassystem/winrunassystem.c
- @@ -127,6 +127,22 @@ ULONG _cdecl RASDbgPrint(__in LPWSTR fmt, ...)
- }
- #endif /* DBG */
- +static
- +bool isprocesselevated(void)
- +{
- + bool isElevated = false;
- + HANDLE hToken = GetCurrentProcessToken();
- + TOKEN_ELEVATION elevation;
- + DWORD cbSize = sizeof(elevation);
- +
- + if (GetTokenInformation(hToken, TokenElevation,
- + &elevation, cbSize, &cbSize)) {
- + isElevated = elevation.TokenIsElevated?true:false;
- + }
- +
- + return isElevated;
- +}
- +
- static
- void ReportError(const char* context)
- {
- @@ -605,9 +621,17 @@ int winrunassystem_main(int argc, wchar_t *argv[])
- return 0;
- }
- - /* Otherwise, run as the client to manage the service */
- + /*
- + * Otherwise, run as the client to manage the service
- + */
- D((void)wprintf(L"Running as client to install and start the service...\n"));
- + if (!isprocesselevated()) {
- + (void)fwprintf(stderr,
- + L"%ls: Requires Windows Adminstator permissions.\n", argv[0]);
- + return EXIT_FAILURE;
- + }
- +
- SetupTemporaryServiceName();
- /* Remove old status file */
- --
- 2.51.0
- From ffd290e5393b094acd89fea8761fa24c4bbd0118 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 11 Sep 2025 12:10:17 +0200
- Subject: [PATCH 07/12] build.vc19: Name cache should handle case-insensitive
- filesystems
- Name cache should handle case-insensitive filesystems.
- This implements case-insensitive UTF-8 file name comparisations via
- ICU.
- Notes:
- - This still has issues related to the different Unicode versions
- and Unicode implementations on Windows, Windows libicu, NFS server
- and the exported filesystem on the NFS server side.
- - NTFS is only case-insensitive, but compares details like
- Frnech accents 1:1 as is, so we use |ucol_setStrength(cache->icu_coll,
- UCOL_SECONDARY)| for the Unicode collator to be compatible with NTFS.
- We might want to make this a mount option to choose between
- |UCOL_SECONDARY| and |UCOL_PRIMARY|.
- Reported-by: Cedric Blancher <cedric.blancher@gmail.com>
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- build.vc19/nfsd/nfsd.vcxproj | 12 +--
- daemon/name_cache.c | 138 +++++++++++++++++++++++++++++++++--
- daemon/name_cache.h | 8 +-
- daemon/nfs41_superblock.c | 17 +++++
- 4 files changed, 163 insertions(+), 12 deletions(-)
- diff --git a/build.vc19/nfsd/nfsd.vcxproj b/build.vc19/nfsd/nfsd.vcxproj
- index 22e4f8b..7cfa57a 100644
- --- a/build.vc19/nfsd/nfsd.vcxproj
- +++ b/build.vc19/nfsd/nfsd.vcxproj
- @@ -148,7 +148,7 @@
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- - <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;ntdll.lib;..\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- + <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;icu.lib;ntdll.lib;..\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- @@ -174,7 +174,7 @@
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- - <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- + <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;icu.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
- @@ -199,7 +199,7 @@
- <Link>
- <SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- - <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- + <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;icu.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- @@ -226,7 +226,7 @@
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- - <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;ntdll.lib;..\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- + <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;icu.lib;ntdll.lib;..\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- </Link>
- </ItemDefinitionGroup>
- @@ -255,7 +255,7 @@
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- - <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- + <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;icu.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- </Link>
- </ItemDefinitionGroup>
- @@ -282,7 +282,7 @@
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- - <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- + <AdditionalDependencies>iphlpapi.lib;ws2_32.lib;wldap32.lib;icu.lib;ntdll.lib;..\$(Platform)\$(Configuration)\libtirpc.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
- </Link>
- </ItemDefinitionGroup>
- diff --git a/daemon/name_cache.c b/daemon/name_cache.c
- index 202e466..f025983 100644
- --- a/daemon/name_cache.c
- +++ b/daemon/name_cache.c
- @@ -23,6 +23,7 @@
- #include <Windows.h>
- #include <strsafe.h>
- +#include <icu.h>
- #include <time.h>
- #include "nfs41_ops.h"
- @@ -502,6 +503,8 @@ static void copy_attrs(
- /* name cache */
- +struct nfs41_name_cache;
- +
- RB_HEAD(name_tree, name_cache_entry);
- struct name_cache_entry {
- char component[NFS41_MAX_COMPONENT_LEN+1];
- @@ -512,15 +515,13 @@ struct name_cache_entry {
- struct name_cache_entry *parent;
- struct list_entry exp_entry;
- util_reltimestamp expiration;
- + struct nfs41_name_cache *name_cache;
- unsigned short component_len;
- };
- #define NAME_ENTRY_SIZE sizeof(struct name_cache_entry)
- -static int name_cmp(struct name_cache_entry *lhs, struct name_cache_entry *rhs)
- -{
- - const int diff = rhs->component_len - lhs->component_len;
- - return diff ? diff : strncmp(lhs->component, rhs->component, lhs->component_len);
- -}
- +static int name_cmp(struct name_cache_entry *lhs, struct name_cache_entry *rhs);
- +
- RB_GENERATE(name_tree, name_cache_entry, rbnode, name_cmp)
- struct nfs41_name_cache {
- @@ -534,8 +535,86 @@ struct nfs41_name_cache {
- uint32_t delegations;
- uint32_t max_delegations;
- SRWLOCK lock;
- + bool casesensitivesearch;
- + UCollator *icu_coll;
- };
- +static
- +int icu_strcmpcoll(UCollator *coll, const char *str1, const char *str2, int32_t len)
- +{
- + UErrorCode status = U_ZERO_ERROR;
- + UCollationResult result;
- +
- + result = ucol_strcollUTF8(coll, str1, len, str2, len, &status);
- + if (U_FAILURE(status)) {
- + eprintf("icu_strcmpcoll: "
- + "ucol_strcollUTF8(str1='%s',str2='%s') returned status='%s'\n",
- + u_errorName(status));
- + return -1;
- + }
- +
- + switch (result) {
- + case UCOL_LESS:
- + return -1;
- + case UCOL_EQUAL:
- + return 0;
- + case UCOL_GREATER:
- + return 1;
- + }
- +
- + eprintf("icu_strcmpcoll: "
- + "ucol_strcollUTF8(str1='%s',str2='%s') returned unexpected result=0x%lx\n",
- + (long)result);
- + return -1;
- +}
- +
- +static
- +int name_cmp(struct name_cache_entry *lhs, struct name_cache_entry *rhs)
- +{
- + const int diff = rhs->component_len - lhs->component_len;
- + int res;
- +
- + if (diff != 0)
- + return diff;
- +
- + unsigned short clen = lhs->component_len;
- +
- + if (lhs->name_cache->casesensitivesearch) {
- + /* FIXME: Can we use |memcmp()| here ? */
- + res = strncmp(lhs->component, rhs->component, clen);
- + }
- + else {
- + res = icu_strcmpcoll(lhs->name_cache->icu_coll,
- + lhs->component, rhs->component, (int32_t)clen);
- +
- +//#define DEBUG_CASEINSENSITIVE_NAMECMP 1
- +#ifdef DEBUG_CASEINSENSITIVE_NAMECMP
- + int casesensitive_res;
- +
- + /* FIXME: Can we use |memcmp()| here ? */
- + casesensitive_res = strncmp(lhs->component, rhs->component,
- + clen);
- +
- + if (res != casesensitive_res) {
- + /*
- + * Explicitly call |clen| "byte_clen" in the output to make sure
- + * people do not get confused, e.g. if |<Ae><ae>| has the same
- + * terminal character width as "dir1
- + */
- + DPRINTF(0,
- + ("name_cmp: "
- + "(lhs='%.*s',rhs='%.*s',byte_clen=%d), "
- + "res(=%d) != casesensitive_res(=%d)\n",
- + (int)clen, lhs->component,
- + (int)clen, rhs->component,
- + (int)clen,
- + res, casesensitive_res));
- + }
- +#endif /* DEBUG_CASEINSENSITIVE_NAMECMP */
- + }
- +
- + return res;
- +}
- /* internal name cache functions used by the public name cache interface;
- * these functions expect the caller to hold a lock on the cache */
- @@ -626,6 +705,9 @@ static int name_cache_entry_create(
- list_add_tail(&cache->exp_entries, &entry->exp_entry);
- }
- + /* Add back pointer to entry */
- + entry->name_cache = cache;
- +
- name_cache_entry_rename(entry, component);
- *entry_out = entry;
- @@ -755,6 +837,7 @@ static struct name_cache_entry* name_cache_search(
- StringCchCopyNA(tmp.component, NFS41_MAX_COMPONENT_LEN+1,
- component->name, component->len);
- tmp.component_len = component->len;
- + tmp.name_cache = cache;
- entry = RB_FIND(name_tree, &parent->rbchildren, &tmp);
- if (entry) {
- @@ -911,6 +994,33 @@ int nfs41_name_cache_create(
- goto out;
- }
- + /*
- + * We need to set this to the real value later, once we have the value
- + * of the |FATTR4_WORD0_CASE_INSENSITIVE| attribute...
- + * FIXME: This is suboptimal...
- + */
- + cache->casesensitivesearch = false;
- +
- + UErrorCode xstatus = U_ZERO_ERROR;
- + cache->icu_coll = ucol_open("en_US", &xstatus);
- + if (U_FAILURE(xstatus)) {
- + eprintf("nfs41_name_cache_create: "
- + "ucol_open() failued with icu_error='%s'\n",
- + u_errorName(xstatus));
- + goto out_err_cache;
- + }
- +
- +
- + /*
- + * FIXME: Which strength should be use ?
- + * - |UCOL_SECONDARY| --> ignore case, keep accents
- + * - |UCOL_PRIMARY| --> ignore case AND accents
- + *
- + * NTFS is case-insensitive by default but compares accents 1:1,
- + * so we stick with |UCOL_SECONDARY|
- + */
- + ucol_setStrength(cache->icu_coll, UCOL_SECONDARY);
- +
- list_init(&cache->exp_entries);
- cache->expiration = NAME_CACHE_EXPIRATION;
- cache->max_entries = NAME_CACHE_MAX_ENTRIES;
- @@ -936,6 +1046,9 @@ out:
- out_err_pool:
- free(cache->pool);
- out_err_cache:
- + if (cache->icu_coll) {
- + ucol_close(cache->icu_coll);
- + }
- free(cache);
- goto out;
- }
- @@ -951,6 +1064,11 @@ int nfs41_name_cache_free(
- /* free the attribute cache */
- attr_cache_free(&cache->attributes);
- + /* free the ICU object */
- + if (cache->icu_coll) {
- + ucol_close(cache->icu_coll);
- + }
- +
- /* free the name entry pool */
- free(cache->pool);
- free(cache);
- @@ -958,6 +1076,16 @@ int nfs41_name_cache_free(
- return status;
- }
- +void nfs41_name_cache_set_casesensitivesearch(
- + IN struct nfs41_name_cache *cache,
- + IN bool casesensitivesearch)
- +{
- + cache->casesensitivesearch = casesensitivesearch;
- + DPRINTF(1,
- + ("nfs41_name_cache_set_casesensitivesearch: casesensitivesearch=%d\n",
- + (int)casesensitivesearch));
- +}
- +
- static __inline void copy_fh(
- OUT nfs41_fh *dst,
- IN OPTIONAL const struct name_cache_entry *src)
- diff --git a/daemon/name_cache.h b/daemon/name_cache.h
- index f7399e1..ff7fb00 100644
- --- a/daemon/name_cache.h
- +++ b/daemon/name_cache.h
- @@ -1,8 +1,10 @@
- /* NFSv4.1 client for Windows
- - * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2012 The Regents of the University of Michigan
- + * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- + * Roland Mainz <roland.mainz@nrubsig.org>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- @@ -54,6 +56,10 @@ int nfs41_attr_cache_update(
- int nfs41_name_cache_create(
- OUT struct nfs41_name_cache **cache_out);
- +void nfs41_name_cache_set_casesensitivesearch(
- + IN struct nfs41_name_cache *cache,
- + IN bool casesensitivesearch);
- +
- int nfs41_name_cache_free(
- IN OUT struct nfs41_name_cache **cache_out);
- diff --git a/daemon/nfs41_superblock.c b/daemon/nfs41_superblock.c
- index eb8a938..3689fe5 100644
- --- a/daemon/nfs41_superblock.c
- +++ b/daemon/nfs41_superblock.c
- @@ -28,6 +28,7 @@
- #include "daemon_debug.h"
- #include "nfs41.h"
- #include "nfs41_ops.h"
- +#include "name_cache.h"
- #include "from_kernel.h"
- #include "nfs41_driver.h"
- #include "util.h"
- @@ -124,8 +125,20 @@ static int get_superblock_attrs(
- superblock->link_support = info.link_support;
- superblock->symlink_support = info.symlink_support;
- superblock->ea_support = supports_named_attrs;
- +//#define TEST_LINUX_FORCE_FAT32 1
- +#ifdef TEST_LINUX_FORCE_FAT32
- + /*
- + * Testing-ONLY: Force FAT32 behaviour, because Linux nfsd returns
- + * |info.case_insensitive==0| even on FAT32
- + * Windows Server 2019 nfsd and OpenText nfsd do this correctly
- + */
- + DPRINTF(0, ("get_superblock_attrs: TEST_LINUX_FORCE_FAT32 enabled!\n"));
- + superblock->case_preserving = 0/*info.case_preserving*/;
- + superblock->case_insensitive = 1/*info.case_insensitive*/;
- +#else
- superblock->case_preserving = info.case_preserving;
- superblock->case_insensitive = info.case_insensitive;
- +#endif /* TEST_FS_FORCE_FAT32 */
- superblock->sparse_file_support = 1; /* always ON for now */
- if (session->client->root->nfsminorvers >= 2) {
- superblock->block_clone_support = 1;
- @@ -134,6 +147,10 @@ static int get_superblock_attrs(
- superblock->block_clone_support = 0;
- }
- + nfs41_name_cache_set_casesensitivesearch(
- + session->client->server->name_cache,
- + superblock->case_insensitive?false:true);
- +
- if (bitmap_isset(&info.attrmask, 0, FATTR4_WORD0_CANSETTIME))
- superblock->cansettime = info.cansettime;
- else /* cansettime is not supported, try setting them anyway */
- --
- 2.51.0
- From dd0e776517cc1229451d8493c5456edff9b23459 Mon Sep 17 00:00:00 2001
- From: Cedric Blancher <cedric.blancher@gmail.com>
- Date: Thu, 11 Sep 2025 12:24:01 +0200
- Subject: [PATCH 08/12] tests: nfs_server_setup: FAT test filesystem setup: Add
- ",fmask=0000,dmask=0000" mount options
- nfs_server_setup: FAT test filesystem setup: Add ",fmask=0000,dmask=0000"
- mount options - FAT does not have uid/gid support, so all users/groups
- should get the same r/w flags.
- Signed-off-by: Roland Mainz <roland.mainz@nrubsig.org>
- ---
- tests/nfs_server_setup.txt | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
- diff --git a/tests/nfs_server_setup.txt b/tests/nfs_server_setup.txt
- index 2a5e7af..825bffa 100644
- --- a/tests/nfs_server_setup.txt
- +++ b/tests/nfs_server_setup.txt
- @@ -47,8 +47,8 @@ mkfs.fat -F 32 '/bigdisk/fat32_image.img'
- mkdir /fat32_mount
- chmod -R a+rwx /fat32_mount
- chown 65534:65534 /fat32_mount
- -#mount -o loop,uid=65534,gid=65534 /bigdisk/fat32_image.img /fat32_mount
- -echo '/bigdisk/fat32_image.img /fat32_mount fat loop,uid=65534,gid=65534 0 0' >>'/etc/fstab'
- +#mount -o loop,uid=65534,gid=65534,fmask=0000,dmask=0000 /bigdisk/fat32_image.img /fat32_mount
- +echo '/bigdisk/fat32_image.img /fat32_mount fat loop,uid=65534,gid=65534,fmask=0000,dmask=0000 0 0' >>'/etc/fstab'
- mount /fat32_mount
- echo '/fat32_mount *(sec=sys,rw,async,insecure,all_squash,anonuid=65534,anongid=65534,fsid=5272429)' >>'/etc/exports'
- service nfs-server restart
- --
- 2.51.0
- From 994bcbd482f2402e1b9e5b3fce526f5bd40f2c75 Mon Sep 17 00:00:00 2001
- From: Cedric Blancher <cedric.blancher@gmail.com>
- Date: Thu, 11 Sep 2025 12:26:19 +0200
- Subject: [PATCH 09/12] tests: nfs_server_setup: Use "vfat" and not "fat" in
- /etc/fstab
- Use "vfat" and not "fat" in /etc/fstab. Not all Linux versions
- support the "fat" alias for "vfat".
- Signed-off-by: Roland Mainz <roland.mainz@nrubsig.org>
- ---
- tests/nfs_server_setup.txt | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
- diff --git a/tests/nfs_server_setup.txt b/tests/nfs_server_setup.txt
- index 825bffa..ba86526 100644
- --- a/tests/nfs_server_setup.txt
- +++ b/tests/nfs_server_setup.txt
- @@ -48,7 +48,7 @@ mkdir /fat32_mount
- chmod -R a+rwx /fat32_mount
- chown 65534:65534 /fat32_mount
- #mount -o loop,uid=65534,gid=65534,fmask=0000,dmask=0000 /bigdisk/fat32_image.img /fat32_mount
- -echo '/bigdisk/fat32_image.img /fat32_mount fat loop,uid=65534,gid=65534,fmask=0000,dmask=0000 0 0' >>'/etc/fstab'
- +echo '/bigdisk/fat32_image.img /fat32_mount vfat loop,uid=65534,gid=65534,fmask=0000,dmask=0000 0 0' >>'/etc/fstab'
- mount /fat32_mount
- echo '/fat32_mount *(sec=sys,rw,async,insecure,all_squash,anonuid=65534,anongid=65534,fsid=5272429)' >>'/etc/exports'
- service nfs-server restart
- --
- 2.51.0
- From 7f1f4ca468d07f5c43c0e6c531a410882b5efac4 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 11 Sep 2025 18:09:43 +0200
- Subject: [PATCH 10/12] daemon: |nfs41_superblock.aclsupport| should be able to
- store all |ACL4_SUPPORT_*| flags
- |nfs41_superblock.aclsupport| should be able to store all |ACL4_SUPPORT_*|
- flags. Just three bits is not enough.
- Reported-by: Lionel Cons <Lionelcons1972@gmail.com>
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/nfs41.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
- diff --git a/daemon/nfs41.h b/daemon/nfs41.h
- index 242417e..670ce9c 100644
- --- a/daemon/nfs41.h
- +++ b/daemon/nfs41.h
- @@ -50,8 +50,8 @@ typedef struct __nfs41_superblock {
- uint64_t maxwrite;
- /* constant filesystem attributes */
- + uint32_t aclsupport; /* |ACL4_SUPPORT_*| */
- unsigned int layout_types : 3;
- - unsigned int aclsupport : 3;
- unsigned int cansettime : 1;
- unsigned int link_support : 1;
- unsigned int symlink_support : 1;
- --
- 2.51.0
- From 21640bb60b25f4563b8995dbc7623e03ff2b2e0d Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Thu, 11 Sep 2025 19:22:37 +0200
- Subject: [PATCH 11/12] daemon: Log superblock info about supported filesystem
- features
- Log superblock info about supported filesystem features.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/nfs41_superblock.c | 57 +++++++++++++++++++++++++++++++++++++++
- 1 file changed, 57 insertions(+)
- diff --git a/daemon/nfs41_superblock.c b/daemon/nfs41_superblock.c
- index 3689fe5..23b4024 100644
- --- a/daemon/nfs41_superblock.c
- +++ b/daemon/nfs41_superblock.c
- @@ -175,6 +175,63 @@ static int get_superblock_attrs(
- nfs41_superblock_supported_attrs(superblock, &superblock->default_getattr);
- + /*
- + * Print infos for admins
- + */
- + char infobuff[256];
- + char *is;
- +
- + /* ACL info */
- + if (superblock->aclsupport) {
- + is = infobuff;
- + *is = '\0';
- + if (bitmap_isset(&superblock->supported_attrs, 0, FATTR4_WORD0_ACL)) {
- + is = stpcpy(is, "ACL");
- + }
- + if (bitmap_isset(&superblock->supported_attrs, 1, FATTR4_WORD1_DACL)) {
- + if (is != infobuff)
- + *is++ = ',';
- + is = stpcpy(is, "DACL");
- + }
- + if (bitmap_isset(&superblock->supported_attrs, 1, FATTR4_WORD1_SACL)) {
- + if (is != infobuff)
- + *is++ = ',';
- + is = stpcpy(is, "SACL");
- + }
- +
- + logprintf("get_superblock_attrs: Supported ACL types: { %s }\n",
- + infobuff);
- + }
- + else {
- + logprintf("get_superblock_attrs: No ACL support\n");
- + }
- +
- + /* Windows/DOS attributes */
- + is = infobuff;
- + *is = '\0';
- + if (bitmap_isset(&superblock->supported_attrs, 0, FATTR4_WORD0_HIDDEN)) {
- + is = stpcpy(is, "HIDDEN");
- + }
- + if (bitmap_isset(&superblock->supported_attrs, 0, FATTR4_WORD0_ARCHIVE)) {
- + if (is != infobuff)
- + *is++ = ',';
- + is = stpcpy(is, "ARCHIVE");
- + }
- + if (bitmap_isset(&superblock->supported_attrs, 1, FATTR4_WORD1_SYSTEM)) {
- + if (is != infobuff)
- + *is++ = ',';
- + is = stpcpy(is, "SYSTEM");
- + }
- + logprintf("get_superblock_attrs: "
- + "Supported Windows/DOS attributes: { %s }\n",
- + infobuff);
- +
- + /* Filename case handling */
- + logprintf("get_superblock_attrs: "
- + "Case handling: case_insensitive=%d, case_preserving=%d\n",
- + (int)superblock->case_insensitive,
- + (int)superblock->case_preserving);
- +
- DPRINTF(SBLVL, ("attributes for fsid(%llu,%llu): "
- "maxread=%llu, maxwrite=%llu, layout_types: 0x%X, "
- "cansettime=%u, time_delta={%llu,%u}, aclsupport=%u, "
- --
- 2.51.0
- From de4e8fb4c4790a295c8547643403e07d92956d9d Mon Sep 17 00:00:00 2001
- From: Cedric Blancher <cedric.blancher@gmail.com>
- Date: Thu, 11 Sep 2025 20:00:40 +0200
- Subject: [PATCH 12/12] tests: nfs_server_setup: Add instructions how to set up
- a case-insensitive ext4 share
- nfs_server_setup: Add instructions how to set up a case-insensitive ext4
- share with Linux nfsd.
- Signed-off-by: Roland Mainz <roland.mainz@nrubsig.org>
- ---
- tests/nfs_server_setup.txt | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
- diff --git a/tests/nfs_server_setup.txt b/tests/nfs_server_setup.txt
- index ba86526..00f802d 100644
- --- a/tests/nfs_server_setup.txt
- +++ b/tests/nfs_server_setup.txt
- @@ -55,6 +55,28 @@ service nfs-server restart
- ---- snip ----
- +##### 4. Setup a 32GB EXT4 filesystem in case-INSENSITIVE mode for testing:
- +# * Notes:
- +# - requires CONFIG_UNICODE in the kernel, otherwise mount will FAIL
- +# - Linux nfsd has a bug which will report FATTR4_WORD0_CASE_INSENSITIVE==0 even
- +# if the filesystem is case-insensitive (FATTR4_WORD0_CASE_INSENSITIVE and
- +# FATTR4_WORD0_CASE_PRESERVING are currently hardcoded in Linux nfsd)
- +---- snip ----
- +dd if='/dev/zero' of='/bigdisk/ext4_caseinsensitive_image.img' bs=$((1024*1024)) count=$((32*1024))
- +mkfs.ext4 -O casefold -E encoding=utf8 /bigdisk/ext4_caseinsensitive_image.img
- +mkdir /ext4caseinsensitive
- +chmod -R a+rwx /ext4caseinsensitive
- +echo '/bigdisk/ext4_caseinsensitive_image.img /ext4caseinsensitive ext4 loop 0 0' >>'/etc/fstab'
- +mount /ext4caseinsensitive
- +mkdir /ext4caseinsensitive/nfsexport
- +# chattr +F is inherited by subdirs (of /ext4caseinsensitive/nfsexport) automatically
- +chattr +F /ext4caseinsensitive/nfsexport
- +chmod a+rwxt /ext4caseinsensitive/nfsexport
- +echo '/ext4caseinsensitive/nfsexport *(sec=sys,rw,async,insecure,no_root_squash,fsid=3272524)' >>'/etc/exports'
- +service nfs-server restart
- +---- snip ----
- +
- +
- #
- # Windows Server 2019 NFSv4.1 server setup
- #
- --
- 2.51.0
msnfs41client: Patches for ARM64 support, global mount issues, case-insensitive filesystem support+misc, 2025-09-11
Posted by Anonymous on Thu 11th Sep 2025 19:40
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.