pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: Patches for winstreamutil catstream subcmd, tests, unlocking fixes+misc, 2026-01-24
Posted by Anonymous on Sat 24th Jan 2026 18:38
raw | new post

  1. From 3e6d626c9d8d96b046191f31bf3478ec8f20a8df Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Fri, 23 Jan 2026 18:33:14 +0100
  4. Subject: [PATCH 1/5] daemon: Fix DrMemory UNINITIALIZED READ hit in
  5.  nfs41_|unlock()|
  6.  
  7. Fix DrMemory UNINITIALIZED READ hit in nfs41_|unlock()|:
  8. ---- snip ----
  9. Error #1: UNINITIALIZED READ: reading 4 byte(s)
  10. libtirpc.dll!xdr_u_int32_t       [ms-nfs41-client\libtirpc\src\xdr.c:242]
  11. libtirpc.dll!xdr_uint32_t        [ms-nfs41-client\libtirpc\src\xdr.c:268]
  12. nfs_encode_compound              [ms-nfs41-client\daemon\nfs41_xdr.c:3739]
  13. libtirpc.dll!authunix_wrap       [ms-nfs41-client\libtirpc\src\auth_unix.c:386]
  14. libtirpc.dll!clnt_vc_call        [ms-nfs41-client\libtirpc\src\clnt_vc.c:634]
  15. nfs41_send_compound              [ms-nfs41-client\daemon\nfs41_rpc.c:391]
  16. compound_encode_send_decode      [ms-nfs41-client\daemon\nfs41_compound.c:195]
  17. nfs41_unlock                     [ms-nfs41-client\daemon\nfs41_ops.c:1212]
  18. map_current_user_to_ids          [ms-nfs41-client\daemon\nfs41_daemon.c:111]
  19. handle_unlock                    [ms-nfs41-client\daemon\lock.c:412]
  20. upcall_handle                    [ms-nfs41-client\daemon\upcall.c:216]
  21. nfsd_worker_thread_main          [ms-nfs41-client\daemon\nfs41_daemon.c:230]
  22. nfsd_thread_main                 [ms-nfs41-client\daemon\nfs41_daemon.c:279]
  23. KERNEL32.dll!BaseThreadInitThunk +0x13     (0x00007ff82a207374 <KERNEL32.dll+0x17374>)
  24. ---- snip ----
  25.  
  26. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  27. ---
  28. daemon/nfs41_ops.c | 1 +
  29.  1 file changed, 1 insertion(+)
  30.  
  31. diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
  32. index 9d3d720..6bc62b0 100644
  33. --- a/daemon/nfs41_ops.c
  34. +++ b/daemon/nfs41_ops.c
  35. @@ -1204,6 +1204,7 @@ int nfs41_unlock(
  36.      compound_add_op(&compound, OP_LOCKU, &locku_args, &locku_res);
  37.      /* 18.12.3: the server MUST accept any legal value for locktype */
  38.      locku_args.locktype = READ_LT;
  39. +    locku_args.seqid = 0; /* ignored */
  40.      locku_args.offset = offset;
  41.      locku_args.length = length;
  42.      locku_args.lock_stateid = stateid;
  43. --
  44. 2.51.0
  45.  
  46. From 0959ef20a6c9dcab408132d3f2782808f3a4065a Mon Sep 17 00:00:00 2001
  47. From: Roland Mainz <roland.mainz@nrubsig.org>
  48. Date: Fri, 23 Jan 2026 19:40:25 +0100
  49. Subject: [PATCH 2/5] daemon: Add more detailed debug output in lock+unlock
  50.  error codepaths
  51.  
  52. Add more detailed debug output in lock+unlock error codepaths.
  53.  
  54. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  55. ---
  56. daemon/lock.c | 33 ++++++++++++++++++++++++++++++++-
  57.  1 file changed, 32 insertions(+), 1 deletion(-)
  58.  
  59. diff --git a/daemon/lock.c b/daemon/lock.c
  60. index 7265fd4..96d1f03 100644
  61. --- a/daemon/lock.c
  62. +++ b/daemon/lock.c
  63. @@ -250,7 +250,14 @@ static int handle_lock_retry(void *deamon_context, nfs41_upcall *upcall)
  64.      status = nfs41_lock(state->session, &state->file, &state->owner,
  65.          type, lock->offset, lock->length, FALSE, TRUE, &stateid);
  66.      if (status) {
  67. -        DPRINTF(LKLVL, ("nfs41_lock failed with '%s'\n",
  68. +        DPRINTF(0/*LKLVL*/,
  69. +            ("handle_lock_retry(state->path.path='%s' "
  70. +            "args->(offset=%llu,length=%llu,exclusive=%d)): "
  71. +            "nfs41_lock() failed with '%s'\n",
  72. +            state->path.path,
  73. +            (unsigned long long)args->offset,
  74. +            (unsigned long long)args->length,
  75. +            (int)args->exclusive,
  76.              nfs_error_string(status)));
  77.          status = nfs_to_windows_error(status, ERROR_BAD_NET_RESP);
  78.          LeaveCriticalSection(&state->locks.lock);
  79. @@ -343,6 +350,16 @@ static void cancel_lock(IN nfs41_upcall *upcall)
  80.  
  81.      status = nfs41_unlock(state->session, &state->file,
  82.          args->offset, args->length, &stateid);
  83. +    if (status) {
  84. +        DPRINTF(0/*LKLVL*/,
  85. +            ("cancel_lock(state->path.path='%s' "
  86. +            "args->(offset=%llu,length=%llu)): "
  87. +            "nfs41_unlock() failed with '%s'\n",
  88. +            state->path.path,
  89. +            (unsigned long long)args->offset,
  90. +            (unsigned long long)args->length,
  91. +            nfs_error_string(status)));
  92. +    }
  93.  
  94.      open_unlock_remove(state, &stateid, &input);
  95.      LeaveCriticalSection(&state->locks.lock);
  96. @@ -406,6 +423,20 @@ static int handle_unlock(void *daemon_context, nfs41_upcall *upcall)
  97.          status = nfs41_unlock(state->session, &state->file,
  98.              input.offset, input.length, &stateid);
  99.  
  100. +        if (status) {
  101. +            DPRINTF(0/*LKLVL*/,
  102. +                ("handle_unlock(state->path.path='%s' "
  103. +                "args->count=%d i=%d\n"
  104. +                "input.(offset=%llu,length=%llu)): "
  105. +                "nfs41_unlock() failed with '%s'\n",
  106. +                state->path.path,
  107. +                (int)args->count,
  108. +                (int)i,
  109. +                (unsigned long long)input.offset,
  110. +                (unsigned long long)input.length,
  111. +                nfs_error_string(status)));
  112. +        }
  113. +
  114.          open_unlock_remove(state, &stateid, &input);
  115.          LeaveCriticalSection(&state->locks.lock);
  116.  
  117. --
  118. 2.51.0
  119.  
  120. From 946f059ff6abc212d5003a9824c4bbad2d645350 Mon Sep 17 00:00:00 2001
  121. From: Roland Mainz <roland.mainz@nrubsig.org>
  122. Date: Sat, 24 Jan 2026 14:26:07 +0100
  123. Subject: [PATCH 3/5] daemon,sys: Add infrastructure so |nfs41_unlock()| can
  124.  use the kernel |LOWIO_LOCK_LIST.ExclusiveLock|
  125.  
  126. Add infrastructure so |nfs41_unlock()| can use the kernel
  127. |LOWIO_LOCK_LIST.ExclusiveLock|.
  128.  
  129. This technically works, except that Windows 10 has a bug which does not
  130. assign a value to |LOWIO_LOCK_LIST.ExclusiveLock| (yet). For
  131. now we always assume |LOWIO_LOCK_LIST.ExclusiveLock==1|, but keep the
  132. code around so it can be used when the Windows 10 bug has been fixed.
  133.  
  134. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  135. ---
  136. daemon/lock.c         | 39 +++++++++++++++++++++++-------
  137.  daemon/nfs41_ops.c    |  9 +++++--
  138.  daemon/nfs41_ops.h    |  3 ++-
  139.  sys/nfs41sys_driver.h |  1 +
  140.  sys/nfs41sys_lock.c   | 56 +++++++++++++++++++++++++++++++++++++++----
  141.  5 files changed, 91 insertions(+), 17 deletions(-)
  142.  
  143. diff --git a/daemon/lock.c b/daemon/lock.c
  144. index 96d1f03..3dcec3e 100644
  145. --- a/daemon/lock.c
  146. +++ b/daemon/lock.c
  147. @@ -1,6 +1,6 @@
  148.  /* NFSv4.1 client for Windows
  149.   * Copyright (C) 2012 The Regents of the University of Michigan
  150. - * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
  151. + * Copyright (C) 2023-2026 Roland Mainz <roland.mainz@nrubsig.org>
  152.   *
  153.   * Olga Kornievskaia <aglo@umich.edu>
  154.   * Casey Bodley <cbodley@umich.edu>
  155. @@ -187,9 +187,14 @@ static int parse_lock(
  156.  
  157.      EASSERT(length == 0);
  158.  
  159. -    DPRINTF(1, ("parsing NFS41_SYSOP_LOCK: offset=0x%llx length=0x%llx exclusive=%u "
  160. -            "blocking=%u\n", args->offset, args->length, args->exclusive,
  161. -            args->blocking));
  162. +    /* Catch non-boolean values */
  163. +    EASSERT((args->exclusive == TRUE) || (args->exclusive == FALSE));
  164. +    EASSERT((args->blocking == TRUE) || (args->blocking == FALSE));
  165. +
  166. +    DPRINTF(1, ("parsing NFS41_SYSOP_LOCK: offset=0x%llx length=0x%llx exclusive=%d "
  167. +            "blocking=%d\n", args->offset, args->length,
  168. +            (int)args->exclusive,
  169. +            (int)args->blocking));
  170.  out:
  171.      return status;
  172.  }
  173. @@ -329,6 +334,7 @@ static void cancel_lock(IN nfs41_upcall *upcall)
  174.      lock_upcall_args *args = &upcall->args.lock;
  175.      nfs41_open_state *state = upcall->state_ref;
  176.      int status = NO_ERROR;
  177. +    bool exclusivelock;
  178.  
  179.      DPRINTF(1, ("--> cancel_lock()\n"));
  180.  
  181. @@ -339,6 +345,11 @@ static void cancel_lock(IN nfs41_upcall *upcall)
  182.  
  183.      input.offset = args->offset;
  184.      input.length = args->length;
  185. +    exclusivelock = (bool)args->exclusive;
  186. +
  187. +    /* Catch non-boolean values */
  188. +    EASSERT((exclusivelock == TRUE) || (exclusivelock == FALSE));
  189. +
  190.  
  191.      /* search for the range to unlock, and remove if delegated */
  192.      status = open_unlock_delegate(state, &input);
  193. @@ -349,15 +360,17 @@ static void cancel_lock(IN nfs41_upcall *upcall)
  194.      lock_stateid_arg(state, &stateid);
  195.  
  196.      status = nfs41_unlock(state->session, &state->file,
  197. -        args->offset, args->length, &stateid);
  198. +        (exclusivelock?WRITE_LT:READ_LT), args->offset, args->length,
  199. +        &stateid);
  200.      if (status) {
  201.          DPRINTF(0/*LKLVL*/,
  202.              ("cancel_lock(state->path.path='%s' "
  203. -            "args->(offset=%llu,length=%llu)): "
  204. +            "args->(offset=%llu,length=%llu,exclusive=%d)): "
  205.              "nfs41_unlock() failed with '%s'\n",
  206.              state->path.path,
  207.              (unsigned long long)args->offset,
  208.              (unsigned long long)args->length,
  209. +            (int)args->exclusive,
  210.              nfs_error_string(status)));
  211.      }
  212.  
  213. @@ -381,7 +394,7 @@ static int parse_unlock(
  214.  
  215.      status = safe_read(&buffer, &length, &args->count, sizeof(ULONG));
  216.      if (status) goto out;
  217. -    args->buf_len = args->count*2L*sizeof(LONGLONG);
  218. +    args->buf_len = args->count*(2L*sizeof(LONGLONG)+sizeof(BOOLEAN));
  219.      status = get_safe_read_bufferpos(&buffer, &length,
  220.          args->buf_len, (const void **)&args->buf);
  221.      if (status) goto out;
  222. @@ -405,8 +418,14 @@ static int handle_unlock(void *daemon_context, nfs41_upcall *upcall)
  223.      int status = NO_ERROR;
  224.  
  225.      for (i = 0; i < args->count; i++) {
  226. +        BOOLEAN exclusivelock;
  227. +
  228.          if (safe_read(&buf, &buf_len, &input.offset, sizeof(LONGLONG))) break;
  229.          if (safe_read(&buf, &buf_len, &input.length, sizeof(LONGLONG))) break;
  230. +        if (safe_read(&buf, &buf_len, &exclusivelock, sizeof(BOOLEAN))) break;
  231. +
  232. +        /* Catch non-boolean values */
  233. +        EASSERT((exclusivelock == TRUE) || (exclusivelock == FALSE));
  234.  
  235.          /* do the same translation as LOCK, or the ranges won't match */
  236.          if (input.length >= NFS4_UINT64_MAX - input.offset)
  237. @@ -421,19 +440,21 @@ static int handle_unlock(void *daemon_context, nfs41_upcall *upcall)
  238.          lock_stateid_arg(state, &stateid);
  239.  
  240.          status = nfs41_unlock(state->session, &state->file,
  241. -            input.offset, input.length, &stateid);
  242. +            (exclusivelock?WRITE_LT:READ_LT), input.offset, input.length,
  243. +            &stateid);
  244.  
  245.          if (status) {
  246.              DPRINTF(0/*LKLVL*/,
  247.                  ("handle_unlock(state->path.path='%s' "
  248.                  "args->count=%d i=%d\n"
  249. -                "input.(offset=%llu,length=%llu)): "
  250. +                "input.(offset=%llu,length=%llu) exclusivelock=%d): "
  251.                  "nfs41_unlock() failed with '%s'\n",
  252.                  state->path.path,
  253.                  (int)args->count,
  254.                  (int)i,
  255.                  (unsigned long long)input.offset,
  256.                  (unsigned long long)input.length,
  257. +                (int)exclusivelock,
  258.                  nfs_error_string(status)));
  259.          }
  260.  
  261. diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
  262. index 6bc62b0..2dfd1e6 100644
  263. --- a/daemon/nfs41_ops.c
  264. +++ b/daemon/nfs41_ops.c
  265. @@ -1176,6 +1176,7 @@ out:
  266.  int nfs41_unlock(
  267.      IN nfs41_session *session,
  268.      IN nfs41_path_fh *file,
  269. +    IN uint32_t type,
  270.      IN uint64_t offset,
  271.      IN uint64_t length,
  272.      IN OUT stateid_arg *stateid)
  273. @@ -1202,8 +1203,12 @@ int nfs41_unlock(
  274.      putfh_args.in_recovery = 0;
  275.  
  276.      compound_add_op(&compound, OP_LOCKU, &locku_args, &locku_res);
  277. -    /* 18.12.3: the server MUST accept any legal value for locktype */
  278. -    locku_args.locktype = READ_LT;
  279. +    /*
  280. +     * https://datatracker.ietf.org/doc/html/rfc5661 Section 18.12.3 says:
  281. +     * "... the server MUST accept any legal value for locktype ..."
  282. +     * but we try to be nice and pass the correct value anyway.
  283. +     */
  284. +    locku_args.locktype = type;
  285.      locku_args.seqid = 0; /* ignored */
  286.      locku_args.offset = offset;
  287.      locku_args.length = length;
  288. diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h
  289. index c7d45a8..c186359 100644
  290. --- a/daemon/nfs41_ops.h
  291. +++ b/daemon/nfs41_ops.h
  292. @@ -1,6 +1,6 @@
  293.  /* NFSv4.1 client for Windows
  294.   * Copyright (C) 2012 The Regents of the University of Michigan
  295. - * Copyright (C) 2024-2025 Roland Mainz <roland.mainz@nrubsig.org>
  296. + * Copyright (C) 2024-2026 Roland Mainz <roland.mainz@nrubsig.org>
  297.   *
  298.   * Olga Kornievskaia <aglo@umich.edu>
  299.   * Casey Bodley <cbodley@umich.edu>
  300. @@ -1365,6 +1365,7 @@ int nfs41_lock(
  301.  int nfs41_unlock(
  302.      IN nfs41_session *session,
  303.      IN nfs41_path_fh *file,
  304. +    IN uint32_t type,
  305.      IN uint64_t offset,
  306.      IN uint64_t length,
  307.      IN OUT stateid_arg *stateid);
  308. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  309. index 670285c..3835bca 100644
  310. --- a/sys/nfs41sys_driver.h
  311. +++ b/sys/nfs41sys_driver.h
  312. @@ -222,6 +222,7 @@ typedef struct _updowncall_entry {
  313.              BOOLEAN blocking;
  314.          } Lock;
  315.          struct {
  316. +            USHORT lowio_operation;
  317.              ULONG count;
  318.              LOWIO_LOCK_LIST locks;
  319.          } Unlock;
  320. diff --git a/sys/nfs41sys_lock.c b/sys/nfs41sys_lock.c
  321. index be7bcb5..d31b0e4 100644
  322. --- a/sys/nfs41sys_lock.c
  323. +++ b/sys/nfs41sys_lock.c
  324. @@ -139,7 +139,7 @@ NTSTATUS marshal_nfs41_unlock(
  325.      tmp += *len;
  326.  
  327.      header_len = *len + sizeof(ULONG) +
  328. -        ((size_t)entry->u.Unlock.count * 2) * sizeof(LONGLONG);
  329. +        ((size_t)entry->u.Unlock.count) * (2L*sizeof(LONGLONG)+sizeof(BOOLEAN));
  330.      if (header_len > buf_len) {
  331.          DbgP("marshal_nfs41_unlock: "
  332.              "upcall buffer too small: header_len(=%ld) > buf_len(=%ld)\n",
  333. @@ -152,10 +152,42 @@ NTSTATUS marshal_nfs41_unlock(
  334.  
  335.      lock = &entry->u.Unlock.locks;
  336.      while (lock) {
  337. +        BOOLEAN exclusivelock;
  338. +
  339.          RtlCopyMemory(tmp, &lock->ByteOffset, sizeof(LONGLONG));
  340.          tmp += sizeof(LONGLONG);
  341.          RtlCopyMemory(tmp, &lock->Length, sizeof(LONGLONG));
  342.          tmp += sizeof(LONGLONG);
  343. +#define WINDOWS_LOWIO_OP_UNLOCK_HAS_RANDOM_VALUE_IN_LOWIO_LOCK_LIST_BUG 1
  344. +
  345. +#ifdef WINDOWS_LOWIO_OP_UNLOCK_HAS_RANDOM_VALUE_IN_LOWIO_LOCK_LIST_BUG
  346. +        if (entry->u.Unlock.lowio_operation == LOWIO_OP_UNLOCK_MULTIPLE) {
  347. +            /*
  348. +             * Windows 10 bugs:
  349. +             * 1. For |LOWIO_OP_UNLOCK_MULTIPLE| |lock->ExclusiveLock| has
  350. +             *   random(uninitialised var ?)
  351. +             * 2. For |LOWIO_OP_UNLOCK| |lock->ExclusiveLock| is always |0|
  352. +             *
  353. +             * As workaround for both [1] and [2] we always set the value
  354. +             * to |TRUE| for now.
  355. +             * This only works because |nfs41_unlock()| states:
  356. +             * ---- snip ----
  357. +             * https://datatracker.ietf.org/doc/html/rfc5661 Section 18.12.3 says:
  358. +             * "... the server MUST accept any legal value for locktype ..."
  359. +             * ---- snip ----
  360. +             */
  361. +            exclusivelock = TRUE/*lock->ExclusiveLock?TRUE:FALSE*/;
  362. +        }
  363. +        else {
  364. +            exclusivelock = TRUE/*lock->ExclusiveLock?TRUE:FALSE*/;
  365. +        }
  366. +#else
  367. +        exclusivelock = lock->ExclusiveLock?TRUE:FALSE;
  368. +#endif /* WINDOWS_LOWIO_OP_UNLOCK_HAS_RANDOM_VALUE_IN_LOWIO_LOCK_LIST_BUG */
  369. +
  370. +        RtlCopyMemory(tmp, &exclusivelock, sizeof(BOOLEAN));
  371. +        tmp += sizeof(BOOLEAN);
  372. +
  373.          lock = lock->Next;
  374.      }
  375.  
  376. @@ -355,14 +387,21 @@ static void print_unlock_args(
  377.          PLOWIO_LOCK_LIST lock = LowIoContext->ParamsFor.Locks.LockList;
  378.          DbgP("LOWIO_OP_UNLOCK_MULTIPLE:");
  379.          while (lock) {
  380. -            DbgP(" (offset=%llu, length=%llu)", lock->ByteOffset, lock->Length);
  381. +            DbgP(" (offset=%llu, length=%llu, exclusivelock=%d)",
  382. +                lock->ByteOffset,
  383. +                lock->Length,
  384. +                (int)lock->ExclusiveLock);
  385.              lock = lock->Next;
  386.          }
  387.          DbgP("\n");
  388.      } else {
  389. -        DbgP("LOWIO_OP_UNLOCK: offset=%llu, length=%llu\n",
  390. +        ULONG flags = LowIoContext->ParamsFor.Locks.Flags;
  391. +        DbgP("LOWIO_OP_UNLOCK: "
  392. +            "offset=%llu, length=%llu, exclusivelock=%d, flags=0x%lx\n",
  393.              LowIoContext->ParamsFor.Locks.ByteOffset,
  394. -            LowIoContext->ParamsFor.Locks.Length);
  395. +            LowIoContext->ParamsFor.Locks.Length,
  396. +            (int)BooleanFlagOn(flags, SL_EXCLUSIVE_LOCK),
  397. +            (long)flags);
  398.      }
  399.  }
  400.  
  401. @@ -406,6 +445,8 @@ NTSTATUS nfs41_Unlock(
  402.  /*  RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb,
  403.          LowIoContext->ResourceThreadId); */
  404.  
  405. +    print_unlock_args(RxContext);
  406. +
  407.  #ifdef NFS41_DRIVER_HACK_LOCKING_STORAGE32_RANGELOCK_PROBING
  408.      /*
  409.       * FIXME: This does NOT handle |LOWIO_OP_UNLOCK_MULTIPLE|
  410. @@ -425,7 +466,9 @@ NTSTATUS nfs41_Unlock(
  411.          pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  412.      if (status) goto out;
  413.  
  414. -    if (LowIoContext->Operation == LOWIO_OP_UNLOCK_MULTIPLE) {
  415. +    entry->u.Unlock.lowio_operation = LowIoContext->Operation;
  416. +
  417. +    if (entry->u.Unlock.lowio_operation == LOWIO_OP_UNLOCK_MULTIPLE) {
  418.          entry->u.Unlock.count = unlock_list_count(
  419.              LowIoContext->ParamsFor.Locks.LockList);
  420.          RtlCopyMemory(&entry->u.Unlock.locks,
  421. @@ -437,6 +480,9 @@ NTSTATUS nfs41_Unlock(
  422.              LowIoContext->ParamsFor.Locks.ByteOffset;
  423.          entry->u.Unlock.locks.Length =
  424.              LowIoContext->ParamsFor.Locks.Length;
  425. +        entry->u.Unlock.locks.ExclusiveLock =
  426. +            BooleanFlagOn(LowIoContext->ParamsFor.Locks.Flags, SL_EXCLUSIVE_LOCK);
  427. +        entry->u.Unlock.locks.Next = NULL;
  428.      }
  429.  
  430.      status = nfs41_UpcallWaitForReply(entry, pVNetRootContext->timeout);
  431. --
  432. 2.51.0
  433.  
  434. From 0a2bd708c6b17a9f08c7c5599c861bfec08b3c89 Mon Sep 17 00:00:00 2001
  435. From: Roland Mainz <roland.mainz@nrubsig.org>
  436. Date: Sat, 24 Jan 2026 14:53:26 +0100
  437. Subject: [PATCH 4/5] sys: Fix |printf()|-style format "0x%ld" to "0x%lx"
  438.  
  439. Fix |printf()|-style format "0x%ld" to "0x%lx".
  440.  
  441. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  442. ---
  443. sys/nfs41sys_fsctl.c | 2 +-
  444.  sys/nfs41sys_lock.c  | 4 ++--
  445.  2 files changed, 3 insertions(+), 3 deletions(-)
  446.  
  447. diff --git a/sys/nfs41sys_fsctl.c b/sys/nfs41sys_fsctl.c
  448. index 27c0946..43925eb 100644
  449. --- a/sys/nfs41sys_fsctl.c
  450. +++ b/sys/nfs41sys_fsctl.c
  451. @@ -315,7 +315,7 @@ NTSTATUS marshal_nfs41_queryallocatedranges(
  452.      }
  453.  
  454.      DbgP("marshal_nfs41_queryallocatedranges: name='%wZ' "
  455. -        "buffersize=0x%ld, buffer=0x%p\n",
  456. +        "buffersize=0x%lx, buffer=0x%p\n",
  457.           entry->filename,
  458.           (long)entry->u.QueryAllocatedRanges.BufferSize,
  459.           (void *)entry->u.QueryAllocatedRanges.Buffer);
  460. diff --git a/sys/nfs41sys_lock.c b/sys/nfs41sys_lock.c
  461. index d31b0e4..c4dad13 100644
  462. --- a/sys/nfs41sys_lock.c
  463. +++ b/sys/nfs41sys_lock.c
  464. @@ -331,7 +331,7 @@ NTSTATUS nfs41_Lock(
  465.  
  466.  #ifdef NFS41_DRIVER_HACK_LOCKING_STORAGE32_RANGELOCK_PROBING
  467.      if (rangelock_hack_skiplock(LowIoContext, nfs41_fcb)) {
  468. -        DbgP("nfs41_Lock: RANGELOCK hack 0x%ld\n",
  469. +        DbgP("nfs41_Lock: RANGELOCK hack 0x%lx\n",
  470.              (long)LowIoContext->ParamsFor.Locks.ByteOffset);
  471.          status = STATUS_SUCCESS;
  472.          goto out;
  473. @@ -454,7 +454,7 @@ NTSTATUS nfs41_Unlock(
  474.       * use it
  475.       */
  476.      if (rangelock_hack_skiplock(LowIoContext, nfs41_fcb)) {
  477. -        DbgP("nfs41_Unlock: RANGELOCK hack 0x%ld\n",
  478. +        DbgP("nfs41_Unlock: RANGELOCK hack 0x%lx\n",
  479.              (long)LowIoContext->ParamsFor.Locks.ByteOffset);
  480.          status = STATUS_SUCCESS;
  481.          goto out;
  482. --
  483. 2.51.0
  484.  
  485. From c5542c985e0c85195a4a70223213fe5d66230b2f Mon Sep 17 00:00:00 2001
  486. From: Roland Mainz <roland.mainz@nrubsig.org>
  487. Date: Sat, 24 Jan 2026 19:23:02 +0100
  488. Subject: [PATCH 5/5] tests: winstreamutil: Implement cat(1)-like catstream
  489.  subcmd
  490.  
  491. winstreamutil: Implement cat(1)-like catstream subcmd to
  492. print out the contents of a stream (without depending in cmd.exe
  493. or powershell).
  494.  
  495. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  496. ---
  497. tests/winstreamsutil/winstreamsutil.c | 116 ++++++++++++++++++++++++++
  498.  1 file changed, 116 insertions(+)
  499.  
  500. diff --git a/tests/winstreamsutil/winstreamsutil.c b/tests/winstreamsutil/winstreamsutil.c
  501. index 54e2429..bb63249 100644
  502. --- a/tests/winstreamsutil/winstreamsutil.c
  503. +++ b/tests/winstreamsutil/winstreamsutil.c
  504. @@ -197,6 +197,118 @@ int cmd_find(int ac, wchar_t *av[])
  505.      return EXIT_SUCCESS;
  506.  }
  507.  
  508. +static
  509. +bool CopyHANDLEToHANDLE(HANDLE hSrc, HANDLE hDest)
  510. +{
  511. +    BYTE buffer[4096];
  512. +    DWORD dwBytesRead = 0;
  513. +    DWORD dwBytesWritten = 0;
  514. +    BOOL bSuccess = FALSE;
  515. +    bool retval = false;
  516. +
  517. +    while (ReadFile(hSrc, buffer, sizeof(buffer), &dwBytesRead, NULL) &&
  518. +        (dwBytesRead > 0)) {
  519. +        bSuccess = WriteFile(hDest,
  520. +            buffer,
  521. +            dwBytesRead,
  522. +            &dwBytesWritten,
  523. +            NULL);
  524. +
  525. +        if (!bSuccess || (dwBytesRead != dwBytesWritten)) {
  526. +            (void)fwprintf(stderr,
  527. +                L"Failed to write to the destination file, lasterr=%d\n",
  528. +                (int)GetLastError());
  529. +            retval = false;
  530. +            goto done;
  531. +        }
  532. +    }
  533. +
  534. +    retval = true;
  535. +
  536. +done:
  537. +    return retval;
  538. +}
  539. +
  540. +static
  541. +int cmd_catstream(int ac, wchar_t *av[])
  542. +{
  543. +    int res;
  544. +    HANDLE h;
  545. +    bool ok;
  546. +    bool print_usage = false;
  547. +    int i;
  548. +    const wchar_t *progname = av[0];
  549. +    wchar_t *base_path = NULL;
  550. +    wchar_t *src_streamname = NULL;
  551. +
  552. +    for (i=2 ; i < ac ; i++) {
  553. +        if (av[i][0] == L'/') {
  554. +            if (wcscmp(av[i], L"/?") == 0)
  555. +                print_usage = true;
  556. +            else {
  557. +                (void)fwprintf(stderr, L"%ls: Unknown option '%ls'\n",
  558. +                    progname, av[i]);
  559. +                return EXIT_FAILURE;
  560. +            }
  561. +        }
  562. +        else {
  563. +            if (base_path == NULL)
  564. +                base_path = av[i];
  565. +            else if (src_streamname == NULL)
  566. +                src_streamname = av[i];
  567. +            else {
  568. +                (void)fwprintf(stderr,
  569. +                    L"%ls: Too many filenames\n", progname);
  570. +                return EXIT_FAILURE;
  571. +            }
  572. +        }
  573. +    }
  574. +
  575. +    if ((base_path == NULL) && (src_streamname == NULL))
  576. +        print_usage = true;
  577. +
  578. +    if (print_usage) {
  579. +        (void)fwprintf(stderr,
  580. +            L"Usage: winstreamutil catstream path srcstreamname\n"
  581. +            L"\tpath\tPath of base file/dir (e.g. C:\\foo.txt)\n"
  582. +            L"\tsrcstreamname\tsrc stream name (e.g. \":mystr1:$DATA\")\n");
  583. +        return EXIT_USAGE;
  584. +    }
  585. +
  586. +    if ((base_path == NULL) || (src_streamname == NULL)) {
  587. +        (void)fwprintf(stderr,
  588. +            L"%ls: Missing paths/stream.\n", progname);
  589. +            return EXIT_FAILURE;
  590. +    }
  591. +
  592. +    if (src_streamname[0] != L':') {
  593. +        (void)fwprintf(stderr,
  594. +            L"%ls: Stream name must start with ':'\n", progname);
  595. +            return EXIT_FAILURE;
  596. +    }
  597. +
  598. +    wchar_t src_stream_path[NT_MAX_LONG_PATH];
  599. +    (void)swprintf(src_stream_path, NT_MAX_LONG_PATH,
  600. +        L"%ls%ls", base_path, src_streamname);
  601. +
  602. +    h = CreateFileW(src_stream_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  603. +    if (h == INVALID_HANDLE_VALUE) {
  604. +        (void)fwprintf(stderr,
  605. +            L"%ls: Cannot open src stream '%ls', lasterr=%d\n",
  606. +            progname,
  607. +            src_stream_path, (int)GetLastError());
  608. +        return EXIT_FAILURE;
  609. +    }
  610. +
  611. +    ok = CopyHANDLEToHANDLE(h, GetStdHandle(STD_OUTPUT_HANDLE));
  612. +    res = ok?EXIT_SUCCESS:EXIT_FAILURE;
  613. +
  614. +    (void)CloseHandle(h);
  615. +
  616. +    return res;
  617. +}
  618. +
  619. +
  620.  typedef LONG NTSTATUS;
  621.  #ifndef NT_SUCCESS
  622.  #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
  623. @@ -551,6 +663,7 @@ void usage(const wchar_t *restrict progname)
  624.          L"Available commands:\n"
  625.          L"info\tprint info about a stream as ksh93 compound variable\n"
  626.          L"find\tfind all non-default named streams in path\n"
  627. +        L"catstream\tCopy data of stream to stdout\n"
  628.          L"renamestream\trename stream\n"
  629.          L"deletestream\tdelete stream\n",
  630.          progname);
  631. @@ -574,6 +687,9 @@ int wmain(int ac, wchar_t *av[])
  632.      else if (wcscmp(av[1], L"find") == 0) {
  633.          return cmd_find(ac, av);
  634.      }
  635. +    else if (wcscmp(av[1], L"catstream") == 0) {
  636. +        return cmd_catstream(ac, av);
  637. +    }
  638.      else if (wcscmp(av[1], L"renamestream") == 0) {
  639.          return cmd_renamestream(ac, av);
  640.      }
  641. --
  642. 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