pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patches to support newgrp(1)/|setgid()| for symlinks, docs updates+misc, 2025-12-16
Posted by Anonymous on Wed 17th Dec 2025 10:30
raw | new post

  1. From 2ff6132b3aa8945db795e5ffb3824358d99b041e Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Sat, 13 Dec 2025 21:51:46 +0100
  4. Subject: [PATCH 1/7] tests: Add parallel and serial build modes to
  5.  nfsbuildtest.ksh93
  6.  
  7. Add parallel and serial build modes to nfsbuildtest.ksh93.
  8.  
  9. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  10. ---
  11. tests/manual_testing.txt              |   4 +-
  12.  tests/nfsbuildtest/nfsbuildtest.ksh93 | 136 ++++++++++++++++++++++----
  13.  2 files changed, 117 insertions(+), 23 deletions(-)
  14.  
  15. diff --git a/tests/manual_testing.txt b/tests/manual_testing.txt
  16. index 57c9013..3305a6a 100644
  17. --- a/tests/manual_testing.txt
  18. +++ b/tests/manual_testing.txt
  19. @@ -1,5 +1,5 @@
  20.  #
  21. -# ms-nfs41-client manual testing sequence, 2025-11-03
  22. +# ms-nfs41-client manual testing sequence, 2025-12-12
  23.  #
  24.  # Draft version, needs to be turned into automated tests
  25.  # if possible
  26. @@ -1185,7 +1185,7 @@ rm -f /cygdrive/n/winntfs_filedisk_001.img
  27.  filedisk /mount 2 'N:\winntfs_filedisk_001.img' 1T U:
  28.  format.com U: /FS:NTFS /A:8192 "/V:NTFSonNFS4_001" /Q /X
  29.  mkdir /cygdrive/u/test1 && cd /cygdrive/u/test1
  30. -rm -Rfv bash && time nice ksh93 /home/roland_mainz/work/msnfs41_uidmapping/ms-nfs41-client/tests/nfsbuildtest/nfsbuildtest.ksh93 bash build
  31. +rm -Rfv bash && time nice ksh93 /home/roland_mainz/work/msnfs41_uidmapping/ms-nfs41-client/tests/nfsbuildtest/nfsbuildtest.ksh93 bash build.parallel
  32.  cd
  33.  filedisk /umount U:
  34.  lssparse /cygdrive/n/winntfs_filedisk_001.img
  35. diff --git a/tests/nfsbuildtest/nfsbuildtest.ksh93 b/tests/nfsbuildtest/nfsbuildtest.ksh93
  36. index 5cd2015..11671ca 100644
  37. --- a/tests/nfsbuildtest/nfsbuildtest.ksh93
  38. +++ b/tests/nfsbuildtest/nfsbuildtest.ksh93
  39. @@ -36,17 +36,17 @@
  40.  # - build bash:
  41.  #   $ ksh93 nfsbuildtest.ksh93 bash clean
  42.  #   $ ksh93 nfsbuildtest.ksh93 bash createcache
  43. -#   $ ksh93 nfsbuildtest.ksh93 bash build
  44. +#   $ ksh93 nfsbuildtest.ksh93 bash build.parallel
  45.  #
  46.  # - build gcc:
  47.  #   $ ksh93 nfsbuildtest.ksh93 gcc clean
  48.  #   $ ksh93 nfsbuildtest.ksh93 gcc createcache
  49. -#   $ ksh93 nfsbuildtest.ksh93 gcc build
  50. +#   $ ksh93 nfsbuildtest.ksh93 gcc build.parallel
  51.  #
  52.  # - build ms-nfs41-client:
  53.  #   $ ksh93 nfsbuildtest.ksh93 msnfs41client clean
  54.  #   $ ksh93 nfsbuildtest.ksh93 msnfs41client createcache
  55. -#   $ ksh93 nfsbuildtest.ksh93 msnfs41client build
  56. +#   $ ksh93 nfsbuildtest.ksh93 msnfs41client build.serial
  57.  #
  58.  
  59.  function gcc_createcache
  60. @@ -98,6 +98,18 @@ function gcc_build
  61.         set -o errexit
  62.         set -o nounset
  63.  
  64. +       typeset subcmd="$1"
  65. +       integer build_parallel
  66. +
  67. +       if [[ "$subcmd" == *.serial* ]] ; then
  68. +               (( build_parallel=0 ))
  69. +       elif [[ "$subcmd" == *.parallel* ]] ; then
  70. +               (( build_parallel=1 ))
  71. +       else
  72. +               print -u2 -f $"Neither '.serial' or '.parallel' set in subcmd='%q'.\n" "$subcmd"
  73. +               return 1
  74. +       fi
  75. +
  76.         #
  77.         # build config
  78.         #
  79. @@ -235,10 +247,24 @@ function gcc_build
  80.         # during $ make -j32 all # missing
  81.         #
  82.         (
  83. +               typeset -a make_options=( )
  84. +
  85. +               if (( build_parallel == 1 )) ; then
  86. +                       make_options+=(
  87. +                               '--load-average 32'
  88. +                               '-j16'
  89. +                       )
  90. +               else
  91. +                       make_options+=(
  92. +                               '--load-average 32'
  93. +                               '-j1'
  94. +                       )
  95. +               fi
  96. +
  97.                 set -o xtrace
  98. -               time ksh93 -c 'export SHELL=/bin/ksh93 ; (yes | make --load-average 32 -j12 all)'
  99. +               time ksh93 -c 'set -o xtrace ; export SHELL=/bin/ksh93 ; (yes | make "$@" all)' dummy "${make_options[@]}"
  100.                 printf "######## gcc build make all returned %d\n" $?
  101. -               time ksh93 -c 'export SHELL=/bin/ksh93 ; (yes | make --load-average 32 -j12 install DESTDIR="$PWD/install_root")'
  102. +               time ksh93 -c 'set -o xtrace ; export SHELL=/bin/ksh93 ; (yes | make "$@" install DESTDIR="$PWD/install_root")' dummy "${make_options[@]}"
  103.                 printf "######## gcc build make install returned %d\n" $?
  104.         )
  105.  
  106. @@ -285,6 +311,18 @@ function bash_build
  107.         set -o errexit
  108.         set -o nounset
  109.  
  110. +       typeset subcmd="$1"
  111. +       integer build_parallel
  112. +
  113. +       if [[ "$subcmd" == *.serial* ]] ; then
  114. +               (( build_parallel=0 ))
  115. +       elif [[ "$subcmd" == *.parallel* ]] ; then
  116. +               (( build_parallel=1 ))
  117. +       else
  118. +               print -u2 -f $"Neither '.serial' or '.parallel' set in subcmd='%q'.\n" "$subcmd"
  119. +               return 1
  120. +       fi
  121. +
  122.         compound cygwin_vers
  123.  
  124.         get_cpv_cygwin_version cygwin_vers
  125. @@ -413,17 +451,26 @@ function bash_build
  126.         #
  127.         # build bash
  128.         #
  129. +       typeset -a make_options=( )
  130. +
  131. +       if (( build_parallel == 1 )) ; then
  132. +               make_options+=( '-j16' )
  133. +       else
  134. +               make_options+=( '-j1' )
  135. +       fi
  136. +
  137. +       set -o xtrace
  138.         if $config_use_posix_ksh93_builtins ; then
  139.                 if is_cygwin && (( (cygwin_vers.major*1000+cygwin_vers.minor) >= 3005 )) ; then
  140. -                       time ksh93 -c 'export SHELL=/bin/ksh93 ; bmake -j16 install DESTDIR="$PWD/install_root"'
  141. +                       time ksh93 -c 'set -o xtrace ; export SHELL=/bin/ksh93 ; bmake "$@" install DESTDIR="$PWD/install_root"' dummy "${make_options[@]}"
  142.                 else
  143. -                       time ksh93 -c 'export SHELL=/bin/ksh93 ; make -j16 install DESTDIR="$PWD/install_root"'
  144. +                       time ksh93 -c 'set -o xtrace ; export SHELL=/bin/ksh93 ; make "$@" install DESTDIR="$PWD/install_root"' dummy "${make_options[@]}"
  145.                 fi
  146.         else
  147.                 if is_cygwin && (( (cygwin_vers.major*1000+cygwin_vers.minor) >= 3005 )) ; then
  148. -                       time bash -c 'export SHELL=/bin/bash ; bmake -j16 install DESTDIR="$PWD/install_root"'
  149. +                       time bash -c 'set -o xtrace ; export SHELL=/bin/bash ; bmake "$@" install DESTDIR="$PWD/install_root"' dummy "${make_options[@]}"
  150.                 else
  151. -                       time bash -c 'export SHELL=/bin/bash ; make -j16 install DESTDIR="$PWD/install_root"'
  152. +                       time bash -c 'set -o xtrace ; export SHELL=/bin/bash ; make "$@" install DESTDIR="$PWD/install_root"' dummy "${make_options[@]}"
  153.                 fi
  154.         fi
  155.         echo $?
  156. @@ -470,6 +517,45 @@ function msnfs41client_build
  157.         set -o errexit
  158.         set -o nounset
  159.  
  160. +       typeset subcmd="$1"
  161. +       integer build_parallel
  162. +
  163. +       if [[ "$subcmd" == *.serial* ]] ; then
  164. +               (( build_parallel=0 ))
  165. +       elif [[ "$subcmd" == *.parallel* ]] ; then
  166. +               typeset file_case_sensitive_search_val
  167. +
  168. +               #
  169. +               # Visual Studio 2019/2022 randomly fails to do a parallel build
  170. +               # on a case-sensitive filesystem, usually project include
  171. +               # files cannot be found.
  172. +               # (looking at the kernel debug log it seems the characters
  173. +               # in the include filename path are turned into uppercase
  174. +               # letters, but we do not know whether this a kernel or Visual
  175. +               # Studio issue)
  176. +               #
  177. +               file_case_sensitive_search_val="$(/usr/lib/csih/getVolInfo "$PWD" | awk '/FILE_CASE_SENSITIVE_SEARCH/ { print $NF; exit }')"
  178. +
  179. +               case "$file_case_sensitive_search_val" in
  180. +                       'FALSE')
  181. +                               # OK
  182. +                               ;;
  183. +                       'TRUE')
  184. +                               print -u2 -f $"ERROR: Visual Studio MSBuild+compiler require a case-insensitive filesystem for parallel builds.\n"
  185. +                               return 1
  186. +                               ;;
  187. +                       *)
  188. +                               print -u2 -f $"ERROR: Unexpected value from getVolInfo/FILE_CASE_SENSITIVE_SEARCH '%q'\n" "$file_case_sensitive_search_val"
  189. +                               return 1
  190. +                               ;;
  191. +               esac
  192. +
  193. +               (( build_parallel=1 ))
  194. +       else
  195. +               print -u2 -f $"Neither '.serial' or '.parallel' set in subcmd='%q'.\n" "$subcmd"
  196. +               return 1
  197. +       fi
  198. +
  199.         #
  200.         # build config
  201.         #
  202. @@ -549,6 +635,14 @@ function msnfs41client_build
  203.         # build ms-nfs41-client
  204.         #
  205.         (
  206. +               typeset -a make_options=( )
  207. +
  208. +               if (( build_parallel == 1 )) ; then
  209. +                       make_options+=( '-j8' )
  210. +               else
  211. +                       make_options+=( '-j1' )
  212. +               fi
  213. +
  214.                 #
  215.                 # We assume here:
  216.                 # Visual Studio 2019 --> Win10 64bit+32bit build,
  217. @@ -564,9 +658,9 @@ function msnfs41client_build
  218.                         sed -i -E 's/<PlatformToolset>v...<\/PlatformToolset>/<PlatformToolset>v143<\/PlatformToolset>/g' $(find 'build.vc19' -name \*.vcxproj)
  219.  
  220.                         # build
  221. -                       time make -j1 -f cygwin/Makefile build64
  222. -                       time make -j1 -f cygwin/Makefile installdest64
  223. -                       time make -j1 -f cygwin/Makefile bintarball64
  224. +                       time make "${make_options[@]}" -f cygwin/Makefile build64
  225. +                       time make "${make_options[@]}" -f cygwin/Makefile installdest64
  226. +                       time make "${make_options[@]}" -f cygwin/Makefile bintarball64
  227.                 elif [[ -x '/cygdrive/c/Program Files/Microsoft Visual Studio/2019/Community/MSBuild/Current/Bin/MSBuild.exe' || \
  228.                         -x '/cygdrive/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/MSBuild/Current/Bin/MSBuild.exe' ]] ; then
  229.                         # Visual Studio 19 64bit+32bit kernel codepath
  230. @@ -582,9 +676,9 @@ function msnfs41client_build
  231.                         sed -i -E 's/<PlatformToolset>v...<\/PlatformToolset>/<PlatformToolset>v142<\/PlatformToolset>/g' $(find 'build.vc19' -name \*.vcxproj)
  232.  
  233.                         # build
  234. -                       time make -j1 -f cygwin/Makefile build
  235. -                       time make -j1 -f cygwin/Makefile installdest
  236. -                       time make -j1 -f cygwin/Makefile bintarball
  237. +                       time make "${make_options[@]}" -f cygwin/Makefile build
  238. +                       time make "${make_options[@]}" -f cygwin/Makefile installdest
  239. +                       time make "${make_options[@]}" -f cygwin/Makefile bintarball
  240.                 else
  241.                         print -u2 -f "%s: Unknown compiler.\n" "$0"
  242.                         exit 5
  243. @@ -718,7 +812,7 @@ function main
  244.                         gcc_createcache
  245.                         return $?
  246.                         ;;
  247. -               'gcc_build')
  248. +               'gcc_build'*)
  249.                         is_toolkit_pkg_installed itp 'git' || (( errc++ ))
  250.                         is_toolkit_pkg_installed itp 'gcc-core' || (( errc++ ))
  251.                         is_toolkit_pkg_installed itp 'gcc-g++' || (( errc++ ))
  252. @@ -736,7 +830,7 @@ function main
  253.                         is_toolkit_pkg_installed itp 'gettext' || (( errc++ ))
  254.                         is_toolkit_pkg_installed itp 'gettext-devel' || (( errc++ ))
  255.                         (( errc > 0 )) && return 1
  256. -                       gcc_build
  257. +                       gcc_build "${subcmd}"
  258.                         return $?
  259.                         ;;
  260.                 'gcc_clean')
  261. @@ -748,7 +842,7 @@ function main
  262.                         bash_createcache
  263.                         return $?
  264.                         ;;
  265. -               'bash_build')
  266. +               'bash_build'*)
  267.                         is_toolkit_pkg_installed itp 'git' || (( errc++ ))
  268.                         is_toolkit_pkg_installed itp 'gcc-core' || (( errc++ ))
  269.                         is_toolkit_pkg_installed itp 'gcc-g++' || (( errc++ ))
  270. @@ -776,7 +870,7 @@ function main
  271.                         is_toolkit_pkg_installed itp 'gettext-devel' || (( errc++ ))
  272.                         is_toolkit_pkg_installed itp 'texinfo' || (( errc++ ))
  273.                         (( errc > 0 )) && return 1
  274. -                       bash_build
  275. +                       bash_build "${subcmd}"
  276.                         return $?
  277.                         ;;
  278.                 'bash_clean')
  279. @@ -788,7 +882,7 @@ function main
  280.                         msnfs41client_createcache
  281.                         return $?
  282.                         ;;
  283. -               'msnfs41client_build')
  284. +               'msnfs41client_build'*)
  285.                         is_toolkit_pkg_installed itp 'git' || (( errc++ ))
  286.                         is_toolkit_pkg_installed itp 'gcc-core' || (( errc++ ))
  287.                         is_toolkit_pkg_installed itp 'gcc-g++' || (( errc++ ))
  288. @@ -799,7 +893,7 @@ function main
  289.                         is_toolkit_pkg_installed itp 'bzip2' || (( errc++ ))
  290.                         is_toolkit_pkg_installed itp 'openssl' || (( errc++ ))
  291.                         (( errc > 0 )) && return 1
  292. -                       msnfs41client_build
  293. +                       msnfs41client_build "${subcmd}"
  294.                         return $?
  295.                         ;;
  296.                 'msnfs41client_clean')
  297. --
  298. 2.51.0
  299.  
  300. From 4cad86d863d45584198a46573f0527ff0bb4401b Mon Sep 17 00:00:00 2001
  301. From: Roland Mainz <roland.mainz@nrubsig.org>
  302. Date: Sat, 13 Dec 2025 21:58:07 +0100
  303. Subject: [PATCH 2/7] tests: Update manual build instructions msnfs41client
  304.  itself in manual_testing.txt
  305.  
  306. Update manual build instructions msnfs41client itself in manual_testing.txt.
  307.  
  308. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  309. ---
  310. tests/manual_testing.txt | 11 ++++++-----
  311.  1 file changed, 6 insertions(+), 5 deletions(-)
  312.  
  313. diff --git a/tests/manual_testing.txt b/tests/manual_testing.txt
  314. index 3305a6a..a520bfb 100644
  315. --- a/tests/manual_testing.txt
  316. +++ b/tests/manual_testing.txt
  317. @@ -713,17 +713,18 @@ make clean && make -j4 all
  318.  
  319.  
  320.  #
  321. -# ms-nfs41-client
  322. +# ms-nfs41-client with Visual Studio 2019 on Windows 10/64bit
  323.  #
  324.  git clone https://github.com/kofemann/ms-nfs41-client.git
  325.  cd ms-nfs41-client
  326. -export PATH+=":/cygdrive/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/MSBuild/Current/Bin/"
  327. +git config --global --add safe.directory "$PWD"
  328. +
  329. +export PATH="/cygdrive/c/Program Files (x86)/Microsoft Visual Studio/2019/Community/MSBuild/Current/Bin/:$PATH" CERTIFICATE_THUMBPRINT="$(powershell -c 'Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object {$_.Subject -like "*WDKTestCert*"} | Select-Object -ExpandProperty Thumbprint')"
  330.  # repeat:
  331.  # clean
  332. -rm -vRf $(find . -name Debug -o -name Release)
  333. +make -f cygwin/Makefile clean ; rm -Rfv destdir
  334.  # build
  335. -MSBuild.exe build.vc19/nfs41-client.sln -t:Build  -p:Configuration=Debug -p:Platform=x64
  336. -MSBuild.exe build.vc19/nfs41-client.sln -t:Build  -p:Configuration=Release -p:Platform=x64
  337. +time ksh93 -c 'make -j8 -f cygwin/Makefile build && make -j8 -f cygwin/Makefile installdest && make -j8 -f cygwin/Makefile bintarball'
  338.  
  339.  
  340.  #
  341. --
  342. 2.51.0
  343.  
  344. From 71df20ce0904db5e3788103d9a8e260d4a734add Mon Sep 17 00:00:00 2001
  345. From: Roland Mainz <roland.mainz@nrubsig.org>
  346. Date: Sat, 13 Dec 2025 22:17:53 +0100
  347. Subject: [PATCH 3/7] README.md,docs: Update kernel debug log instructions
  348.  
  349. Update kernel debug log instructions.
  350.  
  351. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  352. ---
  353. README.md       | 19 ++++++++++++-------
  354.  docs/README.xml | 21 +++++++++++++++++----
  355.  2 files changed, 29 insertions(+), 11 deletions(-)
  356.  
  357. diff --git a/README.md b/README.md
  358. index 0b9c4a0..b8bdbe7 100644
  359. --- a/README.md
  360. +++ b/README.md
  361. @@ -829,17 +829,22 @@ Within WSL mount UNC path returned by `/sbin/nfs_mount`
  362.  
  363.  # Troubleshooting && finding bugs/debugging
  364.  
  365. -- `nfsd_debug.exe` has the `-d` option to set a level for debug output.
  366. +- Debug level of NFS Client daemon:
  367. +
  368. +  `nfsd_debug.exe` has the `-d` option to set a level for debug output.
  369.    Edit `/sbin/msnfs41client` to set the `"-d"` option.
  370.  
  371. -- The "msnfs41client" script has the option "`watch_kernel_debuglog`" to
  372. -  get the debug output of the kernel module.
  373. +- Viewing kernel debug output:
  374. +
  375. +  - The `/sbin/msnfs41client` script has the option
  376. +    "`watch_kernel_debuglog`" to get the debug output of the kernel
  377. +    module.
  378.  
  379. -  Run as Administrator: `$ /sbin/msnfs41client watch_kernel_debuglog #`
  380. +    Run as Administrator:
  381. +    `$ /sbin/msnfs41client watch_kernel_debuglog #`
  382.  
  383. -  Currently requires DebugView
  384. -  (<https://learn.microsoft.com/en-gb/sysinternals/downloads/debugview>)
  385. -  to be installed.
  386. +  - Use Windows Internals `DebugView`
  387. +    (<https://learn.microsoft.com/en-gb/sysinternals/downloads/debugview>).
  388.  
  389.  - Watching network traffic:
  390.  
  391. diff --git a/docs/README.xml b/docs/README.xml
  392. index 4821cf9..45ba334 100644
  393. --- a/docs/README.xml
  394. +++ b/docs/README.xml
  395. @@ -924,15 +924,28 @@ Datei befindet. Versuchen Sie, die Datei woanders zu speichern.</programlisting>
  396.      <title>Troubleshooting &amp;&amp; finding bugs/debugging</title>
  397.      <itemizedlist>
  398.        <listitem>
  399. +        <para>Debug level of NFS Client daemon:</para>
  400.          <para><filename>nfsd_debug.exe</filename> has the <literal>-d</literal> option to set a level for debug output. Edit <filename>/sbin/msnfs41client</filename> to set the <literal>"-d"</literal> option.</para>
  401.        </listitem>
  402.        <listitem>
  403. -        <para>The "msnfs41client" script has the option "<literal>watch_kernel_debuglog</literal>" to get the debug output of the kernel module.</para>
  404. -        <para>Run as Administrator: <command>$ /sbin/msnfs41client watch_kernel_debuglog #</command></para>
  405. -        <para>Currently requires DebugView (<link xl:href="https://learn.microsoft.com/en-gb/sysinternals/downloads/debugview">https://learn.microsoft.com/en-gb/sysinternals/downloads/debugview</link>) to be installed.</para>
  406. +        <para>Viewing kernel debug output:</para>
  407. +        <para>
  408. +          <itemizedlist>
  409. +            <listitem>
  410. +              <para>The <command>/sbin/msnfs41client</command> script has the option "<literal>watch_kernel_debuglog</literal>"
  411. +              to get the debug output of the kernel module.</para>
  412. +              <para>Run as Administrator: <command>$ /sbin/msnfs41client watch_kernel_debuglog #</command></para>
  413. +            </listitem>
  414. +            <listitem>
  415. +              <para>Use Windows Internals <command>DebugView</command>
  416. +              (<link xl:href="https://learn.microsoft.com/en-gb/sysinternals/downloads/debugview">https://learn.microsoft.com/en-gb/sysinternals/downloads/debugview</link>).</para>
  417. +            </listitem>
  418. +          </itemizedlist>
  419. +        </para>
  420.        </listitem>
  421.        <listitem>
  422. -        <para>Watching network traffic:
  423. +        <para>Watching network traffic:</para>
  424. +        <para>
  425.            <itemizedlist>
  426.              <listitem><para>Use <command>$ /sbin/msnfs41client watch_nfs_traffic #</command> to watch the NFS network traffic</para></listitem>
  427.              <listitem>
  428. --
  429. 2.51.0
  430.  
  431. From 094b610affe9e7475e9792f5278d643c1089f9b1 Mon Sep 17 00:00:00 2001
  432. From: Roland Mainz <roland.mainz@nrubsig.org>
  433. Date: Mon, 15 Dec 2025 20:38:45 +0100
  434. Subject: [PATCH 4/7] daemon,include,sys,tests: Provide future-proof unified
  435.  SID buffer size macro
  436.  
  437. Provide future-proof unified SID buffer size macro, rounded up to
  438. the next 64 byte value (=128 bytes).
  439.  
  440. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  441. ---
  442. daemon/sid.c             | 12 ++++++------
  443.  daemon/sid.h             |  4 ++--
  444.  include/nfs41_driver.h   |  7 +++++++
  445.  sys/nfs41sys_driver.h    |  7 ++-----
  446.  sys/nfs41sys_openclose.c |  4 ++--
  447.  sys/nfs41sys_util.c      |  6 +++---
  448.  sys/nfs41sys_util.h      |  2 +-
  449.  tests/winsg/winsg.c      | 13 ++++++++++---
  450.  8 files changed, 33 insertions(+), 22 deletions(-)
  451.  
  452. diff --git a/daemon/sid.c b/daemon/sid.c
  453. index afd2ee3..d866f5c 100644
  454. --- a/daemon/sid.c
  455. +++ b/daemon/sid.c
  456. @@ -47,7 +47,7 @@ int create_unknownsid(WELL_KNOWN_SID_TYPE type, PSID *sid, DWORD *sid_len)
  457.      int status;
  458.      int lasterr;
  459.  
  460. -    *sid_len = SECURITY_MAX_SID_SIZE+1;
  461. +    *sid_len = MAX_SID_BUFFER_SIZE;
  462.      *sid = malloc(*sid_len);
  463.      if (*sid == NULL) {
  464.          status = ERROR_INSUFFICIENT_BUFFER;
  465. @@ -338,7 +338,7 @@ void sidcache_addwithalias(sidcache *cache, const char *win32name, const char *a
  466.      /* Replace the cache entry */
  467.      sidcache_entry *e = &cache->entries[freeEntryIndex];
  468.      DWORD sid_len = GetLengthSid(value);
  469. -    EASSERT_MSG((sid_len <= SECURITY_MAX_SID_SIZE),
  470. +    EASSERT_MSG((sid_len <= MAX_SID_BUFFER_SIZE),
  471.          ("sid_len=%ld\n", (long)sid_len));
  472.      e->sid = (PSID)e->sid_buffer;
  473.      if (!CopySid(sid_len, e->sid, value)) {
  474. @@ -510,12 +510,12 @@ int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *si
  475.      }
  476.  #endif /* NFS41_DRIVER_FEATURE_MAP_UNMAPPED_USER_TO_UNIXUSER_SID */
  477.  
  478. -    *sid = malloc(SECURITY_MAX_SID_SIZE+1);
  479. +    *sid = malloc(MAX_SID_BUFFER_SIZE);
  480.      if (*sid == NULL) {
  481.          status = GetLastError();
  482.          goto out;
  483.      }
  484. -    *sid_len = SECURITY_MAX_SID_SIZE;
  485. +    *sid_len = MAX_SID_BUFFER_SIZE;
  486.      domain_len = sizeof(domain_buff);
  487.  
  488.      status = lookupaccountnameutf8(NULL, nfsname, *sid, sid_len,
  489. @@ -547,8 +547,8 @@ int map_nfs4servername_2_sid(nfs41_daemon_globals *nfs41dg, int query, DWORD *si
  490.      switch(status) {
  491.      case ERROR_INSUFFICIENT_BUFFER:
  492.          /*
  493. -         * This should never happen, as |SECURITY_MAX_SID_SIZE| is
  494. -         * the largest possible SID buffer size for Windows
  495. +         * This should never happen, as |MAX_SID_BUFFER_SIZE| should be
  496. +         * larger than the largest possible SID buffer size for Windows
  497.           */
  498.          eprintf("map_nfs4servername_2_sid(query=0x%x,nfsname='%s'): "
  499.                  "LookupAccountName failed with "
  500. diff --git a/daemon/sid.h b/daemon/sid.h
  501. index 3e12c6d..e6f2be8 100644
  502. --- a/daemon/sid.h
  503. +++ b/daemon/sid.h
  504. @@ -56,11 +56,11 @@ extern sidcache group_sidcache;
  505.  #ifdef _MSC_BUILD
  506.  /* Visual Studio */
  507.  #define DECLARE_SID_BUFFER(varname) \
  508. -    __declspec(align(16)) char (varname)[SECURITY_MAX_SID_SIZE+1]
  509. +    __declspec(align(16)) char (varname)[MAX_SID_BUFFER_SIZE]
  510.  #else
  511.  /* clang */
  512.  #define DECLARE_SID_BUFFER(varname) \
  513. -    char (varname)[SECURITY_MAX_SID_SIZE+1] __attribute__((aligned(16)))
  514. +    char (varname)[MAX_SID_BUFFER_SIZE] __attribute__((aligned(16)))
  515.  #endif /* _MSC_BUILD */
  516.  
  517.  
  518. diff --git a/include/nfs41_driver.h b/include/nfs41_driver.h
  519. index 8aad552..12f14bf 100644
  520. --- a/include/nfs41_driver.h
  521. +++ b/include/nfs41_driver.h
  522. @@ -65,6 +65,13 @@
  523.   */
  524.  #define NFS41_SYS_MAX_PATH_LEN          4096
  525.  
  526. +/*
  527. + * |MAX_SID_BUFFER_SIZE| - Number of bytes needed to store an SID,
  528. + * rounded up to 64byte boundaries
  529. + * (note this must ALWAYS be equal or larger than |SECURITY_MAX_SID_SIZE|)
  530. + */
  531. +#define MAX_SID_BUFFER_SIZE (128)
  532. +
  533.  /* |_nfs41_opcodes| and |g_upcall_op_table| must be in sync! */
  534.  typedef enum _nfs41_opcodes {
  535.      NFS41_SYSOP_INVALID_OPCODE0,
  536. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  537. index a998ed6..6eb05d1 100644
  538. --- a/sys/nfs41sys_driver.h
  539. +++ b/sys/nfs41sys_driver.h
  540. @@ -97,9 +97,6 @@ typedef struct __nfs41_timings {
  541.  /* Windows SMB driver also uses |IO_NETWORK_INCREMENT| */
  542.  #define IO_NFS41FS_INCREMENT IO_NETWORK_INCREMENT
  543.  
  544. -/* Number of bytes needed to store an SID */
  545. -#define SID_BUF_SIZE (SECURITY_MAX_SID_SIZE)
  546. -
  547.  #define DISABLE_CACHING 0
  548.  #define ENABLE_READ_CACHING 1
  549.  #define ENABLE_WRITE_CACHING 2
  550. @@ -517,9 +514,9 @@ typedef struct _NFS41_SRV_OPEN {
  551.       * aligned on Windows 10/32bit
  552.       */
  553.  #ifdef _MSC_BUILD
  554. -    __declspec(align(16)) char open_pg_sidbuff[SID_BUF_SIZE];
  555. +    __declspec(align(16)) char open_pg_sidbuff[MAX_SID_BUFFER_SIZE];
  556.  #else
  557. -    char open_pg_sidbuff[SID_BUF_SIZE] __attribute__((aligned(16)));
  558. +    char open_pg_sidbuff[MAX_SID_BUFFER_SIZE] __attribute__((aligned(16)));
  559.  #endif /* _MSC_BUILD */
  560.  
  561.      /* |open_pg_sid| - PrimaryGroup SID used for opening this NFS handle */
  562. diff --git a/sys/nfs41sys_openclose.c b/sys/nfs41sys_openclose.c
  563. index ba3c847..79b7e8a 100644
  564. --- a/sys/nfs41sys_openclose.c
  565. +++ b/sys/nfs41sys_openclose.c
  566. @@ -1388,9 +1388,9 @@ NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
  567.       * aligned on Windows 10/32bit
  568.       */
  569.  #ifdef _MSC_BUILD
  570. -    __declspec(align(16)) char pg_sidbuff[SID_BUF_SIZE];
  571. +    __declspec(align(16)) char pg_sidbuff[MAX_SID_BUFFER_SIZE];
  572.  #else
  573. -    char pg_sidbuff[SID_BUF_SIZE] __attribute__((aligned(16)));
  574. +    char pg_sidbuff[MAX_SID_BUFFER_SIZE] __attribute__((aligned(16)));
  575.  #endif /* _MSC_BUILD */
  576.      PSID pg_sid = (PSID)&pg_sidbuff[0];
  577.  
  578. diff --git a/sys/nfs41sys_util.c b/sys/nfs41sys_util.c
  579. index c6e95de..345a4b9 100644
  580. --- a/sys/nfs41sys_util.c
  581. +++ b/sys/nfs41sys_util.c
  582. @@ -224,7 +224,7 @@ PQUERY_ON_CREATE_ECP_CONTEXT get_queryoncreateecpcontext(
  583.  
  584.  _Success_(return == true) bool
  585.  get_primarygroup_id(
  586. -    _Out_writes_bytes_(SID_BUF_SIZE) SID *restrict ret_sid)
  587. +    _Out_writes_bytes_(MAX_SID_BUFFER_SIZE) SID *restrict ret_sid)
  588.  {
  589.      PACCESS_TOKEN token = NULL;
  590.      PVOID infoBuffer = NULL;
  591. @@ -263,10 +263,10 @@ get_primarygroup_id(
  592.      }
  593.  
  594.      ULONG sidLength = RtlLengthSid(primaryGroup->PrimaryGroup);
  595. -    if ((sidLength == 0UL) || (sidLength > SID_BUF_SIZE)) {
  596. +    if ((sidLength == 0UL) || (sidLength > MAX_SID_BUFFER_SIZE)) {
  597.          DbgP("get_primarygroup_id: "
  598.              "SID length (%lu) invalid or too large for buffer (%u)\n",
  599. -            sidLength, (unsigned)SID_BUF_SIZE);
  600. +            sidLength, (unsigned)MAX_SID_BUFFER_SIZE);
  601.          retval = false;
  602.          goto out_cleanup_sequeryinfotok;
  603.      }
  604. diff --git a/sys/nfs41sys_util.h b/sys/nfs41sys_util.h
  605. index 39f49de..a003fea 100644
  606. --- a/sys/nfs41sys_util.h
  607. +++ b/sys/nfs41sys_util.h
  608. @@ -73,7 +73,7 @@ PQUERY_ON_CREATE_ECP_CONTEXT get_queryoncreateecpcontext(
  609.      __in PIRP Irp);
  610.  _Success_(return == true) bool
  611.  get_primarygroup_id(
  612. -    _Out_writes_bytes_(SID_BUF_SIZE) SID *restrict ret_sid);
  613. +    _Out_writes_bytes_(MAX_SID_BUFFER_SIZE) SID *restrict ret_sid);
  614.  void qocec_file_stat_information(
  615.      OUT QUERY_ON_CREATE_FILE_STAT_INFORMATION *restrict qocfsi,
  616.      IN const NFS41_FCB *restrict nfs41_fcb);
  617. diff --git a/tests/winsg/winsg.c b/tests/winsg/winsg.c
  618. index bce272e..ba8e8d2 100644
  619. --- a/tests/winsg/winsg.c
  620. +++ b/tests/winsg/winsg.c
  621. @@ -62,6 +62,13 @@
  622.  #define WIN32_POWERSHELLEXE_PATH \
  623.      L"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
  624.  
  625. +/*
  626. + * |MAX_SID_BUFFER_SIZE| - Number of bytes needed to store an SID,
  627. + * rounded up to 64byte boundaries
  628. + * (note this must ALWAYS be equal or larger than |SECURITY_MAX_SID_SIZE|)
  629. + */
  630. +#define MAX_SID_BUFFER_SIZE (128)
  631. +
  632.  /*
  633.   * DECLARE_SID_BUFFER - declare a buffer for a SID value
  634.   * Note that buffers with SID values must be 16byte aligned
  635. @@ -71,11 +78,11 @@
  636.  #ifdef _MSC_BUILD
  637.  /* Visual Studio */
  638.  #define DECLARE_SID_BUFFER(varname) \
  639. -    __declspec(align(16)) char (varname)[SECURITY_MAX_SID_SIZE+1]
  640. +    __declspec(align(16)) char (varname)[MAX_SID_BUFFER_SIZE]
  641.  #else
  642.  /* clang */
  643.  #define DECLARE_SID_BUFFER(varname) \
  644. -    char (varname)[SECURITY_MAX_SID_SIZE+1] __attribute__((aligned(16)))
  645. +    char (varname)[MAX_SID_BUFFER_SIZE] __attribute__((aligned(16)))
  646.  #endif /* _MSC_BUILD */
  647.  
  648.  /*
  649. @@ -492,7 +499,7 @@ int wmain(int ac, wchar_t *av[])
  650.  
  651.      DECLARE_SID_BUFFER(sidbuff);
  652.      PSID pgsid = (PSID)sidbuff;
  653. -    DWORD pgsid_size = SECURITY_MAX_SID_SIZE;
  654. +    DWORD pgsid_size = MAX_SID_BUFFER_SIZE;
  655.  
  656.      if (!get_group_sid(newgrpname, pgsid, &pgsid_size)) {
  657.          (void)fwprintf(stderr, L"%ls: Could not find group '%ls'.\n",
  658. --
  659. 2.51.0
  660.  
  661. From edf35ddde43102820efd92fff4f12a1247ba5291 Mon Sep 17 00:00:00 2001
  662. From: Roland Mainz <roland.mainz@nrubsig.org>
  663. Date: Mon, 15 Dec 2025 22:05:33 +0100
  664. Subject: [PATCH 5/7] daemon: Symlink creation should use authtoken
  665.  PrimaryGroup for newgrp(1)/setgid() support
  666.  
  667. Symlink creation should use authtoken PrimaryGroup for
  668. newgrp(1)/setgid() support.
  669.  
  670. Reported-by: Cedric Blancher <cedric.blancher@gmail.com>
  671. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  672. ---
  673. daemon/open.c    | 58 +++++++++++++++++++++++++++++++++++++++++++-
  674.  daemon/symlink.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++--
  675.  2 files changed, 117 insertions(+), 3 deletions(-)
  676.  
  677. diff --git a/daemon/open.c b/daemon/open.c
  678. index 9cfc28b..5b120bb 100644
  679. --- a/daemon/open.c
  680. +++ b/daemon/open.c
  681. @@ -1116,13 +1116,69 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  682.              args->symlink.path, &state->parent, &state->file, &info);
  683.          if (status) {
  684.              eprintf("handle_open(args->path='%s'): "
  685. -                "nfs41_create() for symlink='%s' failed with '%s'\n",
  686. +                "nfs41_create() for cygwin symlink='%s' failed with '%s'\n",
  687.                  args->path,
  688.                  args->symlink.path,
  689.                  nfs_error_string(status));
  690.              status = map_symlink_errors(status);
  691.              goto out_free_state;
  692.          }
  693. +
  694. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  695. +        /*
  696. +         * Hack: Support |setgid()|/newgrp(1)/sg(1)/winsg(1) by
  697. +         * fetching groupname from auth token for new files and
  698. +         * do a "manual" chgrp on the new file
  699. +         *
  700. +         * Note that |RPCSEC_AUTH_NONE| does not have any
  701. +         * user/group information, therefore newgrp will be a
  702. +         * NOP here.
  703. +         */
  704. +        if (state->session->client->rpc->sec_flavor != RPCSEC_AUTH_NONE) {
  705. +            char *s;
  706. +            int chgrp_status;
  707. +            stateid_arg stateid;
  708. +            nfs41_file_info createchgrpattrs = {
  709. +                .attrmask.count = 2,
  710. +                .attrmask.arr[0] = 0,
  711. +                .attrmask.arr[1] = FATTR4_WORD1_OWNER_GROUP,
  712. +                .owner_group = createchgrpattrs.owner_group_buf
  713. +            };
  714. +
  715. +            /* fixme: we should store the |owner_group| name in |upcall| */
  716. +            if (!get_token_primarygroup_name(upcall->currentthread_token,
  717. +                createchgrpattrs.owner_group)) {
  718. +                eprintf("handle_open(args->path='%s')/cygwin symlink: "
  719. +                    "get_token_primarygroup_name() failed.\n",
  720. +                    args->path);
  721. +                goto create_symlink_chgrp_out;
  722. +            }
  723. +            s = createchgrpattrs.owner_group+
  724. +                strlen(createchgrpattrs.owner_group);
  725. +            s = stpcpy(s, "@");
  726. +            (void)stpcpy(s, nfs41dg->localdomain_name);
  727. +            DPRINTF(1,
  728. +                ("handle_open(state->file.name.name='%s')/cygwin symlink: "
  729. +                "owner_group='%s'\n",
  730. +                state->file.name.name,
  731. +                createchgrpattrs.owner_group));
  732. +
  733. +            nfs41_open_stateid_arg(state, &stateid);
  734. +            chgrp_status = nfs41_setattr(state->session,
  735. +                &state->file, &stateid, &createchgrpattrs);
  736. +            if (chgrp_status) {
  737. +                eprintf("handle_open(args->path='%s')/cygwin symlink: "
  738. +                    "nfs41_setattr(owner_group='%s') "
  739. +                    "failed with error '%s'.\n",
  740. +                    args->path,
  741. +                    createchgrpattrs.owner_group,
  742. +                    nfs_error_string(chgrp_status));
  743. +            }
  744. +create_symlink_chgrp_out:
  745. +            ;
  746. +        }
  747. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  748. +
  749.          nfs_to_basic_info(state->file.name.name,
  750.              state->file.fh.superblock,
  751.              &info,
  752. diff --git a/daemon/symlink.c b/daemon/symlink.c
  753. index d03c738..4efb022 100644
  754. --- a/daemon/symlink.c
  755. +++ b/daemon/symlink.c
  756. @@ -26,9 +26,14 @@
  757.  
  758.  #include "nfs41_driver.h"
  759.  #include "nfs41_ops.h"
  760. +#include "nfs41_daemon.h" /* Required for |nfs41_daemon_globals| */
  761.  #include "upcall.h"
  762.  #include "util.h"
  763.  #include "daemon_debug.h"
  764. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  765. +#include "accesstoken.h"
  766. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  767. +
  768.  
  769.  /* |DPRINTF()| levels for acl logging */
  770.  #define SYMLLVL1 1
  771. @@ -369,6 +374,7 @@ out:
  772.  static int handle_symlink_set(void *daemon_context, nfs41_upcall *upcall)
  773.  {
  774.      symlink_upcall_args *args = &upcall->args.symlink;
  775. +    nfs41_daemon_globals *nfs41dg = daemon_context;
  776.      nfs41_open_state *state = upcall->state_ref;
  777.      int status = NO_ERROR;
  778.  
  779. @@ -404,10 +410,9 @@ static int handle_symlink_set(void *daemon_context, nfs41_upcall *upcall)
  780.      createattrs.attrmask.count = 2;
  781.      createattrs.attrmask.arr[0] = 0;
  782.      createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE;
  783. +    /* FIXME: We should get the "mode" value from the kernel */
  784.      createattrs.mode = 0777;
  785.  
  786. -    /* FIXME: What about newgrp support ? */
  787. -
  788.      status = nfs41_create(state->session, NF4LNK, &createattrs,
  789.          args->target_set, &state->parent, &state->file, &info);
  790.      if (status) {
  791. @@ -418,6 +423,59 @@ static int handle_symlink_set(void *daemon_context, nfs41_upcall *upcall)
  792.          goto out;
  793.      }
  794.  
  795. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  796. +    /*
  797. +     * Hack: Support |setgid()|/newgrp(1)/sg(1)/winsg(1) by
  798. +     * fetching groupname from auth token for new files and
  799. +     * do a "manual" chgrp on the new file
  800. +     *
  801. +     * Note that |RPCSEC_AUTH_NONE| does not have any
  802. +     * user/group information, therefore newgrp will be a
  803. +     * NOP here.
  804. +     */
  805. +    if (state->session->client->rpc->sec_flavor != RPCSEC_AUTH_NONE) {
  806. +        char *s;
  807. +        int chgrp_status;
  808. +        stateid_arg stateid;
  809. +        nfs41_file_info createchgrpattrs = {
  810. +            .attrmask.count = 2,
  811. +            .attrmask.arr[0] = 0,
  812. +            .attrmask.arr[1] = FATTR4_WORD1_OWNER_GROUP,
  813. +            .owner_group = createchgrpattrs.owner_group_buf
  814. +        };
  815. +
  816. +        /* fixme: we should store the |owner_group| name in |upcall| */
  817. +        if (!get_token_primarygroup_name(upcall->currentthread_token,
  818. +            createchgrpattrs.owner_group)) {
  819. +            eprintf("handle_symlink_set(args->path='%s'): "
  820. +                "get_token_primarygroup_name() failed.\n",
  821. +                args->path);
  822. +            goto create_symlink_chgrp_out;
  823. +        }
  824. +        s = createchgrpattrs.owner_group+strlen(createchgrpattrs.owner_group);
  825. +        s = stpcpy(s, "@");
  826. +        (void)stpcpy(s, nfs41dg->localdomain_name);
  827. +        DPRINTF(1, ("handle_symlink_set(state->file.name.name='%s'): "
  828. +            "owner_group='%s'\n",
  829. +            state->file.name.name,
  830. +            createchgrpattrs.owner_group));
  831. +
  832. +        nfs41_open_stateid_arg(state, &stateid);
  833. +        chgrp_status = nfs41_setattr(state->session,
  834. +            &state->file, &stateid, &createchgrpattrs);
  835. +        if (chgrp_status) {
  836. +            eprintf("handle_symlink_set(args->path='%s'): "
  837. +                "nfs41_setattr(owner_group='%s') "
  838. +                "failed with error '%s'.\n",
  839. +                args->path,
  840. +                createchgrpattrs.owner_group,
  841. +                nfs_error_string(chgrp_status));
  842. +        }
  843. +create_symlink_chgrp_out:
  844. +        ;
  845. +    }
  846. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  847. +
  848.  out:
  849.      return status;
  850.  }
  851. --
  852. 2.51.0
  853.  
  854. From 3fa2e3b7f98c8307d12c3eb2efb68512d0e2edd1 Mon Sep 17 00:00:00 2001
  855. From: Lionel Cons <lionelcons1972@gmail.com>
  856. Date: Mon, 15 Dec 2025 22:57:17 +0100
  857. Subject: [PATCH 6/7] README.md,docs: Provide instructions how to get VS2022
  858.  via winget(1)
  859.  
  860. Provide instructions how to get Visual Studio 2022 Community Edition
  861. via winget(1).
  862.  
  863. Reported-by: Lionel Cons <lionelcons1972@gmail.com>
  864. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  865. ---
  866. README.md       | 38 +++++++++++++++++++++++++++++++-------
  867.  docs/README.xml | 29 ++++++++++++++++++++++++-----
  868.  2 files changed, 55 insertions(+), 12 deletions(-)
  869.  
  870. diff --git a/README.md b/README.md
  871. index b8bdbe7..2bbb83d 100644
  872. --- a/README.md
  873. +++ b/README.md
  874. @@ -901,14 +901,38 @@ Source code can be obtained from
  875.  
  876.  - **Option 2:** Windows 11 with Visual Studio 2022 Community
  877.  
  878. -  - Start Visual Studio 2022 installer and import the installer config
  879. -    file `ms-nfs41-client/build.vc19/ms-nfs41-client_vs2022.vsconfig`,
  880. -    and then install Visual Studio.
  881. +  - Compiler:
  882.  
  883. -    > [!NOTE]
  884. -    > Due to a bug in the VS installer, it is sometimes required to
  885. -    > manually add another (random) component to be installed;
  886. -    > otherwise, the imported config might be ignored.
  887. +    - **Option 2a:**Use GUI installer
  888. +
  889. +      Start Visual Studio 2022 installer and import the installer config
  890. +      file `ms-nfs41-client/build.vc19/ms-nfs41-client_vs2022.vsconfig`,
  891. +      and then install Visual Studio.
  892. +
  893. +      > [!NOTE]
  894. +      > Due to a bug in the VS installer, it is sometimes required to
  895. +      > manually add another (random) component to be installed;
  896. +      > otherwise, the imported config might be ignored.
  897. +
  898. +    - **Option 2b:**Use command-line
  899. +
  900. +      <div class="example">
  901. +
  902. +      <div class="title">
  903. +
  904. +      Install VS2022 Community Edition from a Cygwin Administrator shell
  905. +
  906. +      </div>
  907. +
  908. +      ``` bash
  909. +      # get Visual Studio 2022 installer config
  910. +      wget 'https://raw.githubusercontent.com/kofemann/ms-nfs41-client/refs/heads/master/build.vc19/ms-nfs41-client_vs2022.vsconfig'
  911. +
  912. +      # install Visual Studio 2022 via winget(1)
  913. +      winget install -e --id Microsoft.VisualStudio.2022.Community --silent --accept-package-agreements --accept-source-agreements --override "--quiet --wait --norestart --config \"$(cygpath -w "$PWD/ms-nfs41-client_vs2022.vsconfig")\""
  914. +      ```
  915. +
  916. +      </div>
  917.  
  918.    - WDK for Windows 11, version 1591, from
  919.      <https://go.microsoft.com/fwlink/?linkid=2286137>
  920. diff --git a/docs/README.xml b/docs/README.xml
  921. index 45ba334..e7f3a6c 100644
  922. --- a/docs/README.xml
  923. +++ b/docs/README.xml
  924. @@ -1004,11 +1004,30 @@ Datei befindet. Versuchen Sie, die Datei woanders zu speichern.</programlisting>
  925.              <para><emphasis role="bold">Option 2:</emphasis> Windows 11 with Visual Studio 2022 Community</para>
  926.              <itemizedlist>
  927.                <listitem>
  928. -                <para>Start Visual Studio 2022 installer and import the installer config file
  929. -                <filename>ms-nfs41-client/build.vc19/ms-nfs41-client_vs2022.vsconfig</filename>, and then install Visual Studio.</para>
  930. -                <note>
  931. -                  <para>Due to a bug in the VS installer, it is sometimes required to manually add another (random) component to be installed; otherwise, the imported config might be ignored.</para>
  932. -                </note>
  933. +                <para>Compiler:</para>
  934. +                <itemizedlist>
  935. +                  <listitem>
  936. +                    <para><emphasis role="bold">Option 2a:</emphasis>Use GUI installer</para>
  937. +                    <para>Start Visual Studio 2022 installer and import the installer config file
  938. +                    <filename>ms-nfs41-client/build.vc19/ms-nfs41-client_vs2022.vsconfig</filename>, and then install Visual Studio.</para>
  939. +                    <note>
  940. +                      <para>Due to a bug in the VS installer, it is sometimes required to manually add another (random) component to be installed; otherwise, the imported config might be ignored.</para>
  941. +                    </note>
  942. +                  </listitem>
  943. +
  944. +                  <listitem>
  945. +                    <para><emphasis role="bold">Option 2b:</emphasis>Use command-line</para>
  946. +                    <example>
  947. +                      <title>Install VS2022 Community Edition from a Cygwin Administrator shell</title>
  948. +                      <programlisting language="bash"># get Visual Studio 2022 installer config
  949. +wget 'https://raw.githubusercontent.com/kofemann/ms-nfs41-client/refs/heads/master/build.vc19/ms-nfs41-client_vs2022.vsconfig'
  950. +
  951. +# install Visual Studio 2022 via winget(1)
  952. +winget install -e --id Microsoft.VisualStudio.2022.Community --silent --accept-package-agreements --accept-source-agreements --override "--quiet --wait --norestart --config \"$(cygpath -w "$PWD/ms-nfs41-client_vs2022.vsconfig")\""
  953. +</programlisting>
  954. +                    </example>
  955. +                  </listitem>
  956. +                </itemizedlist>
  957.                </listitem>
  958.                <listitem>
  959.                  <para>WDK for Windows 11, version 1591, from <link xl:href="https://go.microsoft.com/fwlink/?linkid=2286137">https://go.microsoft.com/fwlink/?linkid=2286137</link></para>
  960. --
  961. 2.51.0
  962.  
  963. From 0a6c443a96125f192a144bdae7dd831dfb801342 Mon Sep 17 00:00:00 2001
  964. From: Roland Mainz <roland.mainz@nrubsig.org>
  965. Date: Tue, 16 Dec 2025 00:07:42 +0100
  966. Subject: [PATCH 7/7] daemon: Move code to fix gid after file/dir/symlink
  967.  creation to an utility function
  968.  
  969. Move code to fix gid after file/dir/symlink creation to an utility function.
  970.  
  971. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  972. ---
  973. daemon/open.c    | 112 +++++++----------------------------------------
  974.  daemon/symlink.c |  48 ++------------------
  975.  daemon/util.c    |  69 +++++++++++++++++++++++++++++
  976.  daemon/util.h    |  14 ++++++
  977.  4 files changed, 102 insertions(+), 141 deletions(-)
  978.  
  979. diff --git a/daemon/open.c b/daemon/open.c
  980. index 5b120bb..b5e72c7 100644
  981. --- a/daemon/open.c
  982. +++ b/daemon/open.c
  983. @@ -37,7 +37,6 @@
  984.  #include "fileinfoutil.h"
  985.  #include "util.h"
  986.  #include "idmap.h"
  987. -#include "accesstoken.h"
  988.  
  989.  static int create_open_state(
  990.      IN const char *path,
  991. @@ -1134,49 +1133,9 @@ static int handle_open(void *daemon_context, nfs41_upcall *upcall)
  992.           * user/group information, therefore newgrp will be a
  993.           * NOP here.
  994.           */
  995. -        if (state->session->client->rpc->sec_flavor != RPCSEC_AUTH_NONE) {
  996. -            char *s;
  997. -            int chgrp_status;
  998. -            stateid_arg stateid;
  999. -            nfs41_file_info createchgrpattrs = {
  1000. -                .attrmask.count = 2,
  1001. -                .attrmask.arr[0] = 0,
  1002. -                .attrmask.arr[1] = FATTR4_WORD1_OWNER_GROUP,
  1003. -                .owner_group = createchgrpattrs.owner_group_buf
  1004. -            };
  1005. -
  1006. -            /* fixme: we should store the |owner_group| name in |upcall| */
  1007. -            if (!get_token_primarygroup_name(upcall->currentthread_token,
  1008. -                createchgrpattrs.owner_group)) {
  1009. -                eprintf("handle_open(args->path='%s')/cygwin symlink: "
  1010. -                    "get_token_primarygroup_name() failed.\n",
  1011. -                    args->path);
  1012. -                goto create_symlink_chgrp_out;
  1013. -            }
  1014. -            s = createchgrpattrs.owner_group+
  1015. -                strlen(createchgrpattrs.owner_group);
  1016. -            s = stpcpy(s, "@");
  1017. -            (void)stpcpy(s, nfs41dg->localdomain_name);
  1018. -            DPRINTF(1,
  1019. -                ("handle_open(state->file.name.name='%s')/cygwin symlink: "
  1020. -                "owner_group='%s'\n",
  1021. -                state->file.name.name,
  1022. -                createchgrpattrs.owner_group));
  1023. -
  1024. -            nfs41_open_stateid_arg(state, &stateid);
  1025. -            chgrp_status = nfs41_setattr(state->session,
  1026. -                &state->file, &stateid, &createchgrpattrs);
  1027. -            if (chgrp_status) {
  1028. -                eprintf("handle_open(args->path='%s')/cygwin symlink: "
  1029. -                    "nfs41_setattr(owner_group='%s') "
  1030. -                    "failed with error '%s'.\n",
  1031. -                    args->path,
  1032. -                    createchgrpattrs.owner_group,
  1033. -                    nfs_error_string(chgrp_status));
  1034. -            }
  1035. -create_symlink_chgrp_out:
  1036. -            ;
  1037. -        }
  1038. +        (void)chgrp_to_primarygroup(nfs41dg,
  1039. +            upcall->currentthread_token,
  1040. +            state);
  1041.  #endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1042.  
  1043.          nfs_to_basic_info(state->file.name.name,
  1044. @@ -1305,58 +1264,19 @@ supersede_retry:
  1045.              goto out_free_state;
  1046.          } else {
  1047.  #ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  1048. -            /*
  1049. -             * Hack: Support |setgid()|/newgrp(1)/sg(1)/winsg(1) by
  1050. -             * fetching groupname from auth token for new files and
  1051. -             * do a "manual" chgrp on the new file
  1052. -             *
  1053. -             * Note that |RPCSEC_AUTH_NONE| does not have any
  1054. -             * user/group information, therefore newgrp will be a
  1055. -             * NOP here.
  1056. -             */
  1057. -            if ((create == OPEN4_CREATE) &&
  1058. -                (state->session->client->rpc->sec_flavor !=
  1059. -                    RPCSEC_AUTH_NONE)) {
  1060. -                char *s;
  1061. -                int chgrp_status;
  1062. -                stateid_arg stateid;
  1063. -                nfs41_file_info createchgrpattrs;
  1064. -
  1065. -                createchgrpattrs.attrmask.count = 2;
  1066. -                createchgrpattrs.attrmask.arr[0] = 0;
  1067. -                createchgrpattrs.attrmask.arr[1] = FATTR4_WORD1_OWNER_GROUP;
  1068. -                createchgrpattrs.owner_group = createchgrpattrs.owner_group_buf;
  1069. -                /* fixme: we should store the |owner_group| name in |upcall| */
  1070. -                if (!get_token_primarygroup_name(upcall->currentthread_token,
  1071. -                    createchgrpattrs.owner_group)) {
  1072. -                    eprintf("handle_open(args->path='%s'): "
  1073. -                        "OPEN4_CREATE: "
  1074. -                        "get_token_primarygroup_name() failed.\n",
  1075. -                        args->path);
  1076. -                    goto create_chgrp_out;
  1077. -                }
  1078. -                s = createchgrpattrs.owner_group+strlen(createchgrpattrs.owner_group);
  1079. -                s = stpcpy(s, "@");
  1080. -                (void)stpcpy(s, nfs41dg->localdomain_name);
  1081. -                DPRINTF(1, ("handle_open(state->file.name.name='%s'): "
  1082. -                    "OPEN4_CREATE: owner_group='%s'\n",
  1083. -                    state->file.name.name,
  1084. -                    createchgrpattrs.owner_group));
  1085. -
  1086. -                nfs41_open_stateid_arg(state, &stateid);
  1087. -                chgrp_status = nfs41_setattr(state->session,
  1088. -                    &state->file, &stateid, &createchgrpattrs);
  1089. -                if (chgrp_status) {
  1090. -                    eprintf("handle_open(args->path='%s'): "
  1091. -                        "OPEN4_CREATE: "
  1092. -                        "nfs41_setattr(owner_group='%s') "
  1093. -                        "failed with error '%s'.\n",
  1094. -                        args->path,
  1095. -                        createchgrpattrs.owner_group,
  1096. -                        nfs_error_string(chgrp_status));
  1097. -                }
  1098. -create_chgrp_out:
  1099. -                ;
  1100. +            if (create == OPEN4_CREATE) {
  1101. +                /*
  1102. +                 * Hack: Support |setgid()|/newgrp(1)/sg(1)/winsg(1) by
  1103. +                 * fetching groupname from auth token for new files and
  1104. +                 * do a "manual" chgrp on the new file
  1105. +                 *
  1106. +                 * Note that |RPCSEC_AUTH_NONE| does not have any
  1107. +                 * user/group information, therefore newgrp will be a
  1108. +                 * NOP here.
  1109. +                 */
  1110. +                (void)chgrp_to_primarygroup(nfs41dg,
  1111. +                    upcall->currentthread_token,
  1112. +                    state);
  1113.              }
  1114.  #endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1115.  
  1116. diff --git a/daemon/symlink.c b/daemon/symlink.c
  1117. index 4efb022..32bfca7 100644
  1118. --- a/daemon/symlink.c
  1119. +++ b/daemon/symlink.c
  1120. @@ -30,10 +30,6 @@
  1121.  #include "upcall.h"
  1122.  #include "util.h"
  1123.  #include "daemon_debug.h"
  1124. -#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  1125. -#include "accesstoken.h"
  1126. -#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1127. -
  1128.  
  1129.  /* |DPRINTF()| levels for acl logging */
  1130.  #define SYMLLVL1 1
  1131. @@ -433,47 +429,9 @@ static int handle_symlink_set(void *daemon_context, nfs41_upcall *upcall)
  1132.       * user/group information, therefore newgrp will be a
  1133.       * NOP here.
  1134.       */
  1135. -    if (state->session->client->rpc->sec_flavor != RPCSEC_AUTH_NONE) {
  1136. -        char *s;
  1137. -        int chgrp_status;
  1138. -        stateid_arg stateid;
  1139. -        nfs41_file_info createchgrpattrs = {
  1140. -            .attrmask.count = 2,
  1141. -            .attrmask.arr[0] = 0,
  1142. -            .attrmask.arr[1] = FATTR4_WORD1_OWNER_GROUP,
  1143. -            .owner_group = createchgrpattrs.owner_group_buf
  1144. -        };
  1145. -
  1146. -        /* fixme: we should store the |owner_group| name in |upcall| */
  1147. -        if (!get_token_primarygroup_name(upcall->currentthread_token,
  1148. -            createchgrpattrs.owner_group)) {
  1149. -            eprintf("handle_symlink_set(args->path='%s'): "
  1150. -                "get_token_primarygroup_name() failed.\n",
  1151. -                args->path);
  1152. -            goto create_symlink_chgrp_out;
  1153. -        }
  1154. -        s = createchgrpattrs.owner_group+strlen(createchgrpattrs.owner_group);
  1155. -        s = stpcpy(s, "@");
  1156. -        (void)stpcpy(s, nfs41dg->localdomain_name);
  1157. -        DPRINTF(1, ("handle_symlink_set(state->file.name.name='%s'): "
  1158. -            "owner_group='%s'\n",
  1159. -            state->file.name.name,
  1160. -            createchgrpattrs.owner_group));
  1161. -
  1162. -        nfs41_open_stateid_arg(state, &stateid);
  1163. -        chgrp_status = nfs41_setattr(state->session,
  1164. -            &state->file, &stateid, &createchgrpattrs);
  1165. -        if (chgrp_status) {
  1166. -            eprintf("handle_symlink_set(args->path='%s'): "
  1167. -                "nfs41_setattr(owner_group='%s') "
  1168. -                "failed with error '%s'.\n",
  1169. -                args->path,
  1170. -                createchgrpattrs.owner_group,
  1171. -                nfs_error_string(chgrp_status));
  1172. -        }
  1173. -create_symlink_chgrp_out:
  1174. -        ;
  1175. -    }
  1176. +    (void)chgrp_to_primarygroup(nfs41dg,
  1177. +        upcall->currentthread_token,
  1178. +        state);
  1179.  #endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1180.  
  1181.  out:
  1182. diff --git a/daemon/util.c b/daemon/util.c
  1183. index 3d36780..8d7f950 100644
  1184. --- a/daemon/util.c
  1185. +++ b/daemon/util.c
  1186. @@ -33,6 +33,9 @@
  1187.  #include "nfs41_ops.h"
  1188.  #include <devioctl.h>
  1189.  #include "nfs41_driver.h" /* for |delayxid()| */
  1190. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  1191. +#include "accesstoken.h"
  1192. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1193.  
  1194.  
  1195.  char *stpcpy(char *restrict s1, const char *restrict s2)
  1196. @@ -853,3 +856,69 @@ int delayxid(LONGLONG xid, LONGLONG moredelaysecs)
  1197.  
  1198.      return status;
  1199.  }
  1200. +
  1201. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  1202. +/*
  1203. + * Hack: Support |setgid()|/newgrp(1)/sg(1)/winsg(1) by
  1204. + * fetching groupname from auth token for new files and
  1205. + * do a "manual" chgrp on the new file
  1206. + */
  1207. +int chgrp_to_primarygroup(
  1208. +    IN nfs41_daemon_globals *nfs41dg,
  1209. +    IN HANDLE currentthread_token,
  1210. +    IN nfs41_open_state *state)
  1211. +{
  1212. +    int chgrp_status = NO_ERROR;
  1213. +
  1214. +    /*
  1215. +     * |RPCSEC_AUTH_NONE| does not have any
  1216. +     * user/group information, therefore newgrp will be a
  1217. +     * NOP here.
  1218. +     */
  1219. +    if (state->session->client->rpc->sec_flavor == RPCSEC_AUTH_NONE) {
  1220. +        return NO_ERROR;
  1221. +    }
  1222. +
  1223. +    char *s;
  1224. +    stateid_arg stateid;
  1225. +    nfs41_file_info createchgrpattrs = {
  1226. +        .attrmask.count = 2,
  1227. +        .attrmask.arr[0] = 0,
  1228. +        .attrmask.arr[1] = FATTR4_WORD1_OWNER_GROUP,
  1229. +        .owner_group = createchgrpattrs.owner_group_buf
  1230. +    };
  1231. +
  1232. +    /* fixme: we should store the |owner_group| name in |upcall| */
  1233. +    if (!get_token_primarygroup_name(currentthread_token,
  1234. +        createchgrpattrs.owner_group)) {
  1235. +        eprintf("chgrp_to_primarygroup(state->file.name.name='%s'): "
  1236. +            "get_token_primarygroup_name() failed.\n",
  1237. +            state->file.name.name);
  1238. +        goto create_symlink_chgrp_out;
  1239. +    }
  1240. +    s = createchgrpattrs.owner_group+strlen(createchgrpattrs.owner_group);
  1241. +    s = stpcpy(s, "@");
  1242. +    (void)stpcpy(s, nfs41dg->localdomain_name);
  1243. +    DPRINTF(1, ("chgrp_to_primarygroup(state->file.name.name='%s'): "
  1244. +        "owner_group='%s'\n",
  1245. +        state->file.name.name,
  1246. +        createchgrpattrs.owner_group));
  1247. +
  1248. +    nfs41_open_stateid_arg(state, &stateid);
  1249. +    chgrp_status = nfs41_setattr(state->session,
  1250. +        &state->file, &stateid, &createchgrpattrs);
  1251. +    if (chgrp_status) {
  1252. +        eprintf("chgrp_to_primarygroup(state->file.name.name='%s'): "
  1253. +            "nfs41_setattr(owner_group='%s') "
  1254. +            "failed with error '%s'.\n",
  1255. +            state->file.name.name,
  1256. +            createchgrpattrs.owner_group,
  1257. +            nfs_error_string(chgrp_status));
  1258. +    }
  1259. +
  1260. +create_symlink_chgrp_out:
  1261. +    ;
  1262. +
  1263. +    return chgrp_status;
  1264. +}
  1265. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1266. diff --git a/daemon/util.h b/daemon/util.h
  1267. index ab62721..dc0ea07 100644
  1268. --- a/daemon/util.h
  1269. +++ b/daemon/util.h
  1270. @@ -444,4 +444,18 @@ void close_nfs41sys_device_pipe(HANDLE pipe);
  1271.  
  1272.  int delayxid(LONGLONG xid, LONGLONG moredelaysecs);
  1273.  
  1274. +#ifdef NFS41_DRIVER_SETGID_NEWGRP_SUPPORT
  1275. +typedef struct __nfs41_daemon_globals nfs41_daemon_globals;
  1276. +
  1277. +/*
  1278. + * Hack: Support |setgid()|/newgrp(1)/sg(1)/winsg(1) by
  1279. + * fetching groupname from auth token for new files and
  1280. + * do a "manual" chgrp on the new file
  1281. + */
  1282. +int chgrp_to_primarygroup(
  1283. +    IN nfs41_daemon_globals *nfs41dg,
  1284. +    IN HANDLE currentthread_token,
  1285. +    IN nfs41_open_state *state);
  1286. +#endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
  1287. +
  1288.  #endif /* !__NFS41_DAEMON_UTIL_H__ */
  1289. --
  1290. 2.51.0

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.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at