pastebin - collaborative debugging tool
rovema.kpaste.net RSS


msnfs41client: PUBFH support, cleanup+docs+misc, 2024-07-15
Posted by Anonymous on Mon 15th Jul 2024 16:19
raw | new post

  1. From 4ac90a5878be7ed0e90b8ee6fa5a4ce1ddc1e199 Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Fri, 12 Jul 2024 11:50:01 +0200
  4. Subject: [PATCH 01/11] daemon: Add support for |OP_PUTPUBFH|
  5.  encoding/decoding/handling
  6.  
  7. Add support for |OP_PUTPUBFH| encoding/decoding/handling.
  8.  
  9. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  10. ---
  11. daemon/lookup.c         |  4 ++++
  12.  daemon/nfs41_compound.c | 12 +++++++-----
  13.  daemon/nfs41_ops.c      | 18 ++++++++++++++++--
  14.  daemon/nfs41_ops.h      |  6 ++++++
  15.  daemon/nfs41_xdr.c      | 29 ++++++++++++++++++++++++++++-
  16.  5 files changed, 61 insertions(+), 8 deletions(-)
  17.  
  18. diff --git a/daemon/lookup.c b/daemon/lookup.c
  19. index 0cddbde..f747e8a 100644
  20. --- a/daemon/lookup.c
  21. +++ b/daemon/lookup.c
  22. @@ -141,7 +141,11 @@ static int lookup_rpc(
  23.      nfs41_session_sequence(&args->sequence, session, 0);
  24.  
  25.      if (dir == &res->root) {
  26. +#ifdef USE_PUBFH
  27. +        compound_add_op(&compound, OP_PUTPUBFH, NULL, &res->putfh);
  28. +#else
  29.          compound_add_op(&compound, OP_PUTROOTFH, NULL, &res->putfh);
  30. +#endif
  31.          compound_add_op(&compound, OP_GETFH, NULL, &res->getrootfh);
  32.          compound_add_op(&compound, OP_GETATTR, &args->getrootattr,
  33.              &res->getrootattr);
  34. diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c
  35. index 6aaea45..933ca6d 100644
  36. --- a/daemon/nfs41_compound.c
  37. +++ b/daemon/nfs41_compound.c
  38. @@ -335,6 +335,7 @@ retry:
  39.              case OP_RESTOREFH:
  40.              case OP_LINK:
  41.              case OP_RENAME:
  42. +            case OP_PUTPUBFH:
  43.              case OP_PUTROOTFH:
  44.              case OP_LOOKUP:
  45.              case OP_OPEN:
  46. @@ -349,11 +350,12 @@ retry:
  47.                   * from SECINFO or SECINFO_NO_NAME.
  48.                   */
  49.                  if (op1 == OP_SEQUENCE &&
  50. -                        (argarray[1].op == OP_PUTFH ||
  51. -                        argarray[1].op == OP_PUTROOTFH) &&
  52. -                        (argarray[2].op == OP_SECINFO_NO_NAME ||
  53. -                        argarray[2].op == OP_SECINFO)) {
  54. -                    DPRINTF(1, ("SECINFO: BROKEN SERVER\n"));
  55. +                        ((argarray[1].op == OP_PUTFH) ||
  56. +                        (argarray[1].op == OP_PUTPUBFH) ||
  57. +                        (argarray[1].op == OP_PUTROOTFH)) &&
  58. +                        ((argarray[2].op == OP_SECINFO_NO_NAME) ||
  59. +                        (argarray[2].op == OP_SECINFO))) {
  60. +                    eprintf("SECINFO: BROKEN SERVER\n");
  61.                      goto out;
  62.                  }
  63.                  if (!try_recovery)
  64. diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
  65. index 6aa2ff7..9ab7cef 100644
  66. --- a/daemon/nfs41_ops.c
  67. +++ b/daemon/nfs41_ops.c
  68. @@ -1154,7 +1154,11 @@ int nfs41_getattr(
  69.          putfh_args.file = file;
  70.          putfh_args.in_recovery = 0;
  71.      } else {
  72. +#ifdef USE_PUBFH
  73. +        compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  74. +#else
  75.          compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  76. +#endif
  77.      }
  78.  
  79.      compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
  80. @@ -1896,8 +1900,13 @@ int nfs41_secinfo(
  81.      compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
  82.      nfs41_session_sequence(&sequence_args, session, 0);
  83.  
  84. -    if (file == NULL)
  85. +    if (file == NULL) {
  86. +#ifdef USE_PUBFH
  87. +        compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  88. +#else
  89.          compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  90. +#endif
  91. +    }
  92.      else {
  93.          compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
  94.          putfh_args.file = file;
  95. @@ -1938,8 +1947,13 @@ int nfs41_secinfo_noname(
  96.      compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
  97.      nfs41_session_sequence(&sequence_args, session, 0);
  98.  
  99. -    if (file == NULL)
  100. +    if (file == NULL) {
  101. +#ifdef USE_PUBFH
  102. +        compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  103. +#else
  104.          compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  105. +#endif
  106. +    }
  107.      else {
  108.          compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
  109.          putfh_args.file = file;
  110. diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h
  111. index 4c8f7d0..230dfa4 100644
  112. --- a/daemon/nfs41_ops.h
  113. +++ b/daemon/nfs41_ops.h
  114. @@ -516,6 +516,12 @@ typedef struct __nfs41_putfh_res {
  115.  } nfs41_putfh_res;
  116.  
  117.  
  118. +/* OP_PUTPUBFH */
  119. +typedef struct __nfs41_putpubfh_res {
  120. +    uint32_t                status;
  121. +} nfs41_putpubfh_res;
  122. +
  123. +
  124.  /* OP_PUTROOTFH */
  125.  typedef struct __nfs41_putrootfh_res {
  126.      uint32_t                status;
  127. diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c
  128. index 903b2b5..09cc523 100644
  129. --- a/daemon/nfs41_xdr.c
  130. +++ b/daemon/nfs41_xdr.c
  131. @@ -3,6 +3,7 @@
  132.   *
  133.   * Olga Kornievskaia <aglo@umich.edu>
  134.   * Casey Bodley <cbodley@umich.edu>
  135. + * Roland Mainz <roland.mainz@nrubsig.org>
  136.   *
  137.   * This library is free software; you can redistribute it and/or modify it
  138.   * under the terms of the GNU Lesser General Public License as published by
  139. @@ -1102,6 +1103,32 @@ static bool_t decode_op_putfh(
  140.  }
  141.  
  142.  
  143. +/*
  144. + * OP_PUTPUBFH
  145. + */
  146. +static bool_t encode_op_putpubfh(
  147. +    XDR *xdr,
  148. +    nfs_argop4* argop)
  149. +{
  150. +    if (unexpected_op(argop->op, OP_PUTPUBFH))
  151. +        return FALSE;
  152. +    /* void */
  153. +    return TRUE;
  154. +}
  155. +
  156. +static bool_t decode_op_putpubfh(
  157. +    XDR *xdr,
  158. +    nfs_resop4 *resop)
  159. +{
  160. +    nfs41_putpubfh_res *res = (nfs41_putpubfh_res*)resop->res;
  161. +
  162. +    if (unexpected_op(resop->op, OP_PUTPUBFH))
  163. +        return FALSE;
  164. +
  165. +    return xdr_u_int32_t(xdr, &res->status);
  166. +}
  167. +
  168. +
  169.  /*
  170.   * OP_PUTROOTFH
  171.   */
  172. @@ -3553,7 +3580,7 @@ static const op_table_entry g_op_table[] = {
  173.      { NULL, NULL }, /* OP_OPEN_CONFIRM = 20 */
  174.      { NULL, NULL }, /* OP_OPEN_DOWNGRADE = 21 */
  175.      { encode_op_putfh, decode_op_putfh }, /* OP_PUTFH = 22 */
  176. -    { NULL, NULL }, /* OP_PUTPUBFH = 23 */
  177. +    { encode_op_putpubfh, decode_op_putpubfh }, /* OP_PUTPUBFH = 23 */
  178.      { encode_op_putrootfh, decode_op_putrootfh }, /* OP_PUTROOTFH = 24 */
  179.      { encode_op_read, decode_op_read }, /* OP_READ = 25 */
  180.      { encode_op_readdir, decode_op_readdir }, /* OP_READDIR = 26 */
  181. --
  182. 2.45.1
  183.  
  184. From 2c517c6573405993076e82251ac0bdd777e785a3 Mon Sep 17 00:00:00 2001
  185. From: Roland Mainz <roland.mainz@nrubsig.org>
  186. Date: Mon, 15 Jul 2024 11:21:39 +0200
  187. Subject: [PATCH 02/11] cygwin,daemon,dll,mount,sys: Add support for public
  188.  filehandles (PUTPUBFH)
  189.  
  190. Add support for public filehandles (PUTPUBFH)
  191.  
  192. Example:
  193. ---- snip ----
  194. $ nfs_mount -o sec=sys,rw,public '*' nfs://derfwnb4966_ipv4//bigdisk
  195. Successfully mounted 'derfwnb4966_ipv4@2049' to drive 'Y:'
  196. $ nfs_mount | grep -F '/pubnfs4/'
  197. (null) \\derfwnb4966_ipv4@2049\pubnfs4\bigdisk //derfwnb4966_ipv4@2049/pubnfs4/bigdisk nfs://derfwnb4966_ipv4:2049//bigdisk?public=1
  198. $ cd '//derfwnb4966_ipv4@2049/pubnfs4/bigdisk'
  199. ---- snip ----
  200.  
  201. Reported-by: Dan Shelton <dan.f.shelton@gmail.com>
  202. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  203. ---
  204. cygwin/README.bintarball.txt |  3 ++
  205.  daemon/lookup.c              | 12 +++--
  206.  daemon/mount.c               | 27 +++++++----
  207.  daemon/namespace.c           |  5 +-
  208.  daemon/nfs41.h               |  3 ++
  209.  daemon/nfs41_client.c        |  8 ++++
  210.  daemon/nfs41_ops.c           | 33 +++++++------
  211.  daemon/upcall.h              |  2 +
  212.  dll/nfs41_np.c               |  6 ++-
  213.  mount/enum.c                 | 35 +++++++++++++-
  214.  mount/mount.c                | 31 ++++++++++--
  215.  sys/nfs41_driver.c           | 92 ++++++++++++++++++++++++++++--------
  216.  12 files changed, 201 insertions(+), 56 deletions(-)
  217.  
  218. diff --git a/cygwin/README.bintarball.txt b/cygwin/README.bintarball.txt
  219. index edd1c55..1596066 100644
  220. --- a/cygwin/README.bintarball.txt
  221. +++ b/cygwin/README.bintarball.txt
  222. @@ -35,6 +35,9 @@ NFSv4.1 client and filesystem driver for Windows 10/11
  223.      tunnel
  224.  - Support for long paths (up to 4096 bytes), no Windows MAXPATH limit
  225.  
  226. +- Support for NFSv4 public mounts (i.e. use the NFSv4 public file handle
  227. +    lookup protocol via $ nfs_mount -o public ... #)
  228. +
  229.  - Unicode support
  230.  
  231.  - UNC paths
  232. diff --git a/daemon/lookup.c b/daemon/lookup.c
  233. index f747e8a..eebb71e 100644
  234. --- a/daemon/lookup.c
  235. +++ b/daemon/lookup.c
  236. @@ -141,11 +141,13 @@ static int lookup_rpc(
  237.      nfs41_session_sequence(&args->sequence, session, 0);
  238.  
  239.      if (dir == &res->root) {
  240. -#ifdef USE_PUBFH
  241. -        compound_add_op(&compound, OP_PUTPUBFH, NULL, &res->putfh);
  242. -#else
  243. -        compound_add_op(&compound, OP_PUTROOTFH, NULL, &res->putfh);
  244. -#endif
  245. +        if (session->client->root->use_nfspubfh) {
  246. +            compound_add_op(&compound, OP_PUTPUBFH, NULL, &res->putfh);
  247. +        }
  248. +        else {
  249. +            compound_add_op(&compound, OP_PUTROOTFH, NULL, &res->putfh);
  250. +        }
  251. +
  252.          compound_add_op(&compound, OP_GETFH, NULL, &res->getrootfh);
  253.          compound_add_op(&compound, OP_GETATTR, &args->getrootattr,
  254.              &res->getrootattr);
  255. diff --git a/daemon/mount.c b/daemon/mount.c
  256. index cc9053b..8d756c5 100644
  257. --- a/daemon/mount.c
  258. +++ b/daemon/mount.c
  259. @@ -50,11 +50,13 @@ static int parse_mount(unsigned char *buffer, uint32_t length, nfs41_upcall *upc
  260.      if (status) goto out;
  261.      status = safe_read(&buffer, &length, &args->wsize, sizeof(DWORD));
  262.      if (status) goto out;
  263. +    status = safe_read(&buffer, &length, &args->use_nfspubfh, sizeof(DWORD));
  264. +    if (status) goto out;
  265.  
  266.      DPRINTF(1, ("parsing NFS41_MOUNT: hostport='%s' root='%s' "
  267. -        "sec_flavor='%s' rsize=%d wsize=%d\n",
  268. +        "sec_flavor='%s' rsize=%d wsize=%d use_nfspubfh=%d\n",
  269.          args->hostport, args->path, secflavorop2name(args->sec_flavor),
  270. -        args->rsize, args->wsize));
  271. +        args->rsize, args->wsize, args->use_nfspubfh));
  272.      return status;
  273.  out:
  274.      DPRINTF(1, ("parsing NFS41_MOUNT: failed %d\n", status));
  275. @@ -83,9 +85,11 @@ static int handle_mount(void *daemon_context, nfs41_upcall *upcall)
  276.      (void)get_token_authenticationid(upcall->currentthread_token,
  277.          &authenticationid);
  278.  
  279. -    logprintf("mount(hostport='%s', path='%s', "
  280. +    logprintf("mount(hostport='%s', "
  281. +        "use_nfspubfh=%d, path='%s', "
  282.          "authid=(0x%lx.0x%lx)) request\n",
  283.          args->hostport?args->hostport:"<NULL>",
  284. +        (int)args->use_nfspubfh,
  285.          args->path?args->path:"<NULL>",
  286.          (long)authenticationid.HighPart,
  287.          (long)authenticationid.LowPart);
  288. @@ -143,7 +147,8 @@ static int handle_mount(void *daemon_context, nfs41_upcall *upcall)
  289.          root = upcall->root_ref;
  290.      } else {
  291.          // create root
  292. -        status = nfs41_root_create(hostname, port, args->sec_flavor,
  293. +        status = nfs41_root_create(hostname, port,
  294. +            args->use_nfspubfh?true:false, args->sec_flavor,
  295.              args->wsize + WRITE_OVERHEAD, args->rsize + READ_OVERHEAD, &root);
  296.          if (status) {
  297.              eprintf("nfs41_root_create(hostname='%s', port=%d) failed %d\n",
  298. @@ -187,32 +192,38 @@ static int handle_mount(void *daemon_context, nfs41_upcall *upcall)
  299.  out:
  300.      if (status == 0) {
  301.  #ifdef NFS41_DRIVER_USE_AUTHENTICATIONID_FOR_MOUNT_NAMESPACE
  302. -        logprintf("mount(hostport='%s', path='%s', "
  303. +        logprintf("mount(hostport='%s', use_nfspubfh=%d, path='%s', "
  304.              "authid=(0x%lx.0x%lx)) success, root=0x%p\n",
  305.              args->hostport?args->hostport:"<NULL>",
  306. +            (int)args->use_nfspubfh,
  307.              args->path?args->path:"<NULL>",
  308.              (long)authenticationid.HighPart,
  309.              (long)authenticationid.LowPart,
  310.              root);
  311.  #else
  312. -        logprintf("mount(hostport='%s', path='%s') success, root=0x%p\n",
  313. +        logprintf("mount(hostport='%s', use_nfspubfh=%d, path='%s') success, "
  314. +            "root=0x%p\n",
  315.              args->hostport?args->hostport:"<NULL>",
  316. +            (int)args->use_nfspubfh,
  317.              args->path?args->path:"<NULL>",
  318.              root);
  319.  #endif /* NFS41_DRIVER_USE_AUTHENTICATIONID_FOR_MOUNT_NAMESPACE */
  320.      }
  321.      else {
  322.  #ifdef NFS41_DRIVER_USE_AUTHENTICATIONID_FOR_MOUNT_NAMESPACE
  323. -        logprintf("mount(hostport='%s', path='%s', "
  324. +        logprintf("mount(hostport='%s', use_nfspubfh=%d, path='%s', "
  325.              "authid=(0x%lx.0x%lx))) failed, status=%d\n",
  326.              args->hostport?args->hostport:"<NULL>",
  327. +            (int)args->use_nfspubfh,
  328.              args->path?args->path:"<NULL>",
  329.              (long)authenticationid.HighPart,
  330.              (long)authenticationid.LowPart,
  331.              (int)status);
  332.  #else
  333. -        logprintf("mount(hostport='%s', path='%s') failed, status=%d\n",
  334. +        logprintf("mount(hostport='%s', use_nfspubfh=%d, path='%s') "
  335. +            "failed, status=%d\n",
  336.              args->hostport?args->hostport:"<NULL>",
  337. +            (int)args->use_nfspubfh,
  338.              args->path?args->path:"<NULL>",
  339.              (int)status);
  340.  #endif /* NFS41_DRIVER_USE_AUTHENTICATIONID_FOR_MOUNT_NAMESPACE */
  341. diff --git a/daemon/namespace.c b/daemon/namespace.c
  342. index e490aad..7391854 100644
  343. --- a/daemon/namespace.c
  344. +++ b/daemon/namespace.c
  345. @@ -3,6 +3,7 @@
  346.   *
  347.   * Olga Kornievskaia <aglo@umich.edu>
  348.   * Casey Bodley <cbodley@umich.edu>
  349. + * Roland Mainz <roland.mainz@nrubsig.org>
  350.   *
  351.   * This library is free software; you can redistribute it and/or modify it
  352.   * under the terms of the GNU Lesser General Public License as published by
  353. @@ -37,6 +38,7 @@
  354.  int nfs41_root_create(
  355.      IN const char *name,
  356.      IN uint32_t port,
  357. +    IN bool use_nfspubfh,
  358.      IN uint32_t sec_flavor,
  359.      IN uint32_t wsize,
  360.      IN uint32_t rsize,
  361. @@ -54,6 +56,7 @@ int nfs41_root_create(
  362.      }
  363.  
  364.      list_init(&root->clients);
  365. +    root->use_nfspubfh = use_nfspubfh;
  366.      root->wsize = wsize;
  367.      root->rsize = rsize;
  368.      InitializeCriticalSection(&root->lock);
  369. @@ -61,7 +64,7 @@ int nfs41_root_create(
  370.      root->sec_flavor = sec_flavor;
  371.  
  372.      /* generate a unique client_owner */
  373. -    status = nfs41_client_owner(name, port, sec_flavor, &root->client_owner);
  374. +    status = nfs41_client_owner(name, port, use_nfspubfh, sec_flavor, &root->client_owner);
  375.      if (status) {
  376.          eprintf("nfs41_client_owner() failed with %d\n", status);
  377.          free(root);
  378. diff --git a/daemon/nfs41.h b/daemon/nfs41.h
  379. index f1617a9..5956d86 100644
  380. --- a/daemon/nfs41.h
  381. +++ b/daemon/nfs41.h
  382. @@ -299,6 +299,7 @@ typedef struct __nfs41_root {
  383.      client_owner4 client_owner;
  384.      CRITICAL_SECTION lock;
  385.      struct list_entry clients;
  386. +    bool use_nfspubfh;
  387.      uint32_t wsize;
  388.      uint32_t rsize;
  389.  #pragma warning( push )
  390. @@ -316,6 +317,7 @@ typedef struct __nfs41_root {
  391.  int nfs41_root_create(
  392.      IN const char *name,
  393.      IN uint32_t port,
  394. +    IN bool use_nfspubfh,
  395.      IN uint32_t sec_flavor,
  396.      IN uint32_t wsize,
  397.      IN uint32_t rsize,
  398. @@ -434,6 +436,7 @@ void nfs41_server_addrs(
  399.  int nfs41_client_owner(
  400.      IN const char *name,
  401.      IN uint32_t port,
  402. +    IN bool use_nfspubfh,
  403.      IN uint32_t sec_flavor,
  404.      OUT client_owner4 *owner);
  405.  
  406. diff --git a/daemon/nfs41_client.c b/daemon/nfs41_client.c
  407. index 847aa0c..6a1f04a 100644
  408. --- a/daemon/nfs41_client.c
  409. +++ b/daemon/nfs41_client.c
  410. @@ -362,6 +362,7 @@ out:
  411.  int nfs41_client_owner(
  412.      IN const char *name,
  413.      IN uint32_t port,
  414. +    IN bool use_nfspubfh,
  415.      IN uint32_t sec_flavor,
  416.      OUT client_owner4 *owner)
  417.  {
  418. @@ -420,6 +421,13 @@ int nfs41_client_owner(
  419.          goto out_context;
  420.      }
  421.  
  422. +    if (!CryptHashData(hash,
  423. +        (const BYTE*)&use_nfspubfh, (DWORD)sizeof(bool), 0)) {
  424. +        status = GetLastError();
  425. +        eprintf("CryptHashData() failed with %d\n", status);
  426. +        goto out_hash;
  427. +    }
  428. +
  429.      if (!CryptHashData(hash, (const BYTE*)&sec_flavor, (DWORD)sizeof(sec_flavor), 0)) {
  430.          status = GetLastError();
  431.          eprintf("CryptHashData() failed with %d\n", status);
  432. diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
  433. index 9ab7cef..11578cb 100644
  434. --- a/daemon/nfs41_ops.c
  435. +++ b/daemon/nfs41_ops.c
  436. @@ -1154,11 +1154,12 @@ int nfs41_getattr(
  437.          putfh_args.file = file;
  438.          putfh_args.in_recovery = 0;
  439.      } else {
  440. -#ifdef USE_PUBFH
  441. -        compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  442. -#else
  443. -        compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  444. -#endif
  445. +        if (session->client->root->use_nfspubfh) {
  446. +            compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  447. +        }
  448. +        else {
  449. +            compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  450. +        }
  451.      }
  452.  
  453.      compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res);
  454. @@ -1901,11 +1902,12 @@ int nfs41_secinfo(
  455.      nfs41_session_sequence(&sequence_args, session, 0);
  456.  
  457.      if (file == NULL) {
  458. -#ifdef USE_PUBFH
  459. -        compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  460. -#else
  461. -        compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  462. -#endif
  463. +        if (session->client->root->use_nfspubfh) {
  464. +            compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  465. +        }
  466. +        else {
  467. +            compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  468. +        }
  469.      }
  470.      else {
  471.          compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
  472. @@ -1948,11 +1950,12 @@ int nfs41_secinfo_noname(
  473.      nfs41_session_sequence(&sequence_args, session, 0);
  474.  
  475.      if (file == NULL) {
  476. -#ifdef USE_PUBFH
  477. -        compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  478. -#else
  479. -        compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  480. -#endif
  481. +        if (session->client->root->use_nfspubfh) {
  482. +            compound_add_op(&compound, OP_PUTPUBFH, NULL, &putfh_res);
  483. +        }
  484. +        else {
  485. +            compound_add_op(&compound, OP_PUTROOTFH, NULL, &putfh_res);
  486. +        }
  487.      }
  488.      else {
  489.          compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res);
  490. diff --git a/daemon/upcall.h b/daemon/upcall.h
  491. index 50b62be..48b1631 100644
  492. --- a/daemon/upcall.h
  493. +++ b/daemon/upcall.h
  494. @@ -3,6 +3,7 @@
  495.   *
  496.   * Olga Kornievskaia <aglo@umich.edu>
  497.   * Casey Bodley <cbodley@umich.edu>
  498. + * Roland Mainz <roland.mainz@nrubsig.org>
  499.   *
  500.   * This library is free software; you can redistribute it and/or modify it
  501.   * under the terms of the GNU Lesser General Public License as published by
  502. @@ -35,6 +36,7 @@ typedef struct __mount_upcall_args {
  503.      DWORD       sec_flavor;
  504.      DWORD       rsize;
  505.      DWORD       wsize;
  506. +    DWORD       use_nfspubfh;
  507.      DWORD       lease_time;
  508.      FILE_FS_ATTRIBUTE_INFORMATION FsAttrs;
  509.  } mount_upcall_args;
  510. diff --git a/dll/nfs41_np.c b/dll/nfs41_np.c
  511. index 1720558..6e24e21 100644
  512. --- a/dll/nfs41_np.c
  513. +++ b/dll/nfs41_np.c
  514. @@ -638,8 +638,10 @@ NPAddConnection3(
  515.  #endif
  516.  
  517.  #ifdef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  518. -    if (wcsncmp(&p[i], L"\\nfs4", 5) != 0) {
  519. -        DbgP((L"Connection name '%s' not prefixed with '\\nfs41'\n",
  520. +    if (wcsncmp(&p[i], L"\\nfs4", 5) &&
  521. +        wcsncmp(&p[i], L"\\pubnfs4", 8)) {
  522. +        DbgP((L"Connection name '%s' not prefixed with "
  523. +            "'\\nfs41' or '\\pubnfs41'\n",
  524.              &p[i]));
  525.          Status = WN_BAD_NETNAME;
  526.          goto out;
  527. diff --git a/mount/enum.c b/mount/enum.c
  528. index 8a30260..97043dd 100644
  529. --- a/mount/enum.c
  530. +++ b/mount/enum.c
  531. @@ -21,6 +21,7 @@
  532.  
  533.  #include <Windows.h>
  534.  #include <tchar.h>
  535. +#include <stdbool.h>
  536.  #include <stdio.h>
  537.  #include <malloc.h>
  538.  
  539. @@ -38,13 +39,17 @@ void PrintMountLine(
  540.      LPCTSTR remote)
  541.  {
  542.      TCHAR *cygwin_unc_buffer = alloca((_tcslen(remote)+32)*sizeof(TCHAR));
  543. -    char *cygwin_nfsurl_buffer = alloca(((_tcslen(remote)+32)*3)+8);
  544. +    char *cygwin_nfsurl_buffer = alloca(
  545. +        ((_tcslen(remote)+32)*3)+8 +
  546. +        9 /* "?public=1" */
  547. +        );
  548.      TCHAR *b;
  549.      LPCTSTR s;
  550.      TCHAR sc;
  551.  #ifndef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  552.      unsigned int backslash_counter;
  553.  #endif
  554. +    bool is_pubfh = false;
  555.  
  556.      for(b = cygwin_unc_buffer, s = remote
  557.  #ifndef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  558. @@ -127,7 +132,22 @@ void PrintMountLine(
  559.           */
  560.          if (slash_counter == 1) {
  561.              *us++ = uc;
  562. -            utf8unc_p+=4;
  563. +            if (*utf8unc_p == 'p') {
  564. +                /* Skip "pubnfs4" */
  565. +                utf8unc_p += 7;
  566. +                is_pubfh = true;
  567. +            }
  568. +            else if (*utf8unc_p == 'n') {
  569. +                /* Skip "nfs4" */
  570. +                utf8unc_p += 4;
  571. +            }
  572. +            else {
  573. +                (void)fwprintf(stderr,
  574. +                    L"PrintMountLine: ## Internal error, "
  575. +                    "unknown provider prefix\n");
  576. +                return;
  577. +            }
  578. +
  579.              continue;
  580.          }
  581.  
  582. @@ -150,6 +170,17 @@ void PrintMountLine(
  583.          }
  584.      }
  585.      *us = '\0';
  586. +
  587. +    if (is_pubfh) {
  588. +#pragma warning( push )
  589. +    /*
  590. +     * Disable "'strcat': This function or variable may be unsafe",
  591. +     * in this context it is safe to use
  592. +     */
  593. +#pragma warning (disable : 4996)
  594. +        (void)strcat(cygwin_nfsurl_buffer, "?public=1");
  595. +#pragma warning( pop )
  596. +    }
  597.  
  598.      (void)_tprintf(TEXT("%-8s\t%-50s\t%-50s\t%-50S\n"),
  599.          local, remote, cygwin_unc_buffer, cygwin_nfsurl_buffer);
  600. diff --git a/mount/mount.c b/mount/mount.c
  601. index c4d8170..f0c41e9 100644
  602. --- a/mount/mount.c
  603. +++ b/mount/mount.c
  604. @@ -30,6 +30,7 @@
  605.  #include <strsafe.h>
  606.  #include <Winnetwk.h> /* for WNet*Connection */
  607.  #include <stdlib.h>
  608. +#include <stdbool.h>
  609.  #include <stdio.h>
  610.  
  611.  #include "nfs41_build_features.h"
  612. @@ -51,6 +52,7 @@ DWORD EnumMounts(
  613.      IN LPNETRESOURCE pContainer);
  614.  
  615.  static DWORD ParseRemoteName(
  616. +    IN bool use_nfspubfh,
  617.      IN LPTSTR pRemoteName,
  618.      IN OUT PMOUNT_OPTION_LIST pOptions,
  619.      OUT LPTSTR pParsedRemoteName,
  620. @@ -91,6 +93,8 @@ static VOID PrintUsage(LPTSTR pProcess)
  621.          TEXT("\t-w\tAlias for -o rw (read-write mount)\n")
  622.  
  623.          TEXT("* Mount options:\n")
  624. +        TEXT("\tpublic\tconnect to the server using the public file handle lookup protocol.\n")
  625. +        TEXT("\t\t(See WebNFS Client Specification, RFC 2054).\n")
  626.          TEXT("\tro\tmount as read-only\n")
  627.          TEXT("\trw\tmount as read-write (default)\n")
  628.          TEXT("\tport=#\tTCP port to use (defaults to 2049)\n")
  629. @@ -176,6 +180,8 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  630.          goto out;
  631.      }
  632.  
  633. +    bool use_nfspubfh = false;
  634. +
  635.      /* parse command line */
  636.      for (i = 1; i < argc; i++)
  637.      {
  638. @@ -218,6 +224,20 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  639.                  }
  640.  
  641.                  mntopts[num_mntopts++] = argv[i];
  642. +
  643. +                /*
  644. +                 * Extract "public" option here, as we need this for
  645. +                 * |ParseRemoteName()|. General parsing of -o options
  646. +                 * happens *AFTER* |ParseRemoteName()|, so any
  647. +                 * settings from a nfs://-URL can be overridden
  648. +                 * via -o options.
  649. +                 */
  650. +                if (wcsstr(argv[i], L"public=0")) {
  651. +                    use_nfspubfh = false;
  652. +                }
  653. +                else if (wcsstr(argv[i], L"public")) {
  654. +                    use_nfspubfh = true;
  655. +                }
  656.              }
  657.              else if (_tcscmp(argv[i], TEXT("-r")) == 0) /* mount option */
  658.              {
  659. @@ -333,7 +353,7 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  660.           * options for a NFS mount point, which can be overridden via
  661.           * -o below.
  662.           */
  663. -        result = ParseRemoteName(pRemoteName, &Options,
  664. +        result = ParseRemoteName(use_nfspubfh, pRemoteName, &Options,
  665.              szParsedRemoteName, szRemoteName, NFS41_SYS_MAX_PATH_LEN);
  666.          if (result)
  667.              goto out;
  668. @@ -411,6 +431,7 @@ wchar_t *utf8str2wcs(const char *utf8str)
  669.  }
  670.  
  671.  static DWORD ParseRemoteName(
  672. +    IN bool use_nfspubfh,
  673.      IN LPTSTR pRemoteName,
  674.      IN OUT PMOUNT_OPTION_LIST pOptions,
  675.      OUT LPTSTR pParsedRemoteName,
  676. @@ -712,7 +733,8 @@ static DWORD ParseRemoteName(
  677.      if (FAILED(result))
  678.          goto out;
  679.  #ifdef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  680. -    result = StringCbCat(pConnectionName, cchConnectionLen, TEXT("\\nfs4"));
  681. +    result = StringCbCat(pConnectionName, cchConnectionLen,
  682. +        (use_nfspubfh?(TEXT("\\pubnfs4")):(TEXT("\\nfs4"))));
  683.      if (FAILED(result))
  684.          goto out;
  685.  #endif /* NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX */
  686. @@ -723,9 +745,10 @@ static DWORD ParseRemoteName(
  687.  
  688.  #ifdef DEBUG_MOUNT
  689.      (void)_ftprintf(stderr,
  690. -        TEXT("pConnectionName='%s', pParsedRemoteName='%s'\n"),
  691. +        TEXT("pConnectionName='%s', pParsedRemoteName='%s', use_nfspubfh='%d'\n"),
  692.          pConnectionName,
  693. -        pParsedRemoteName);
  694. +        pParsedRemoteName,
  695. +        (int)use_nfspubfh);
  696.  #endif
  697.  
  698.  out:
  699. diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
  700. index 613f7df..9d16b5d 100644
  701. --- a/sys/nfs41_driver.c
  702. +++ b/sys/nfs41_driver.c
  703. @@ -189,6 +189,7 @@ typedef struct _updowncall_entry {
  704.              DWORD rsize;
  705.              DWORD wsize;
  706.              DWORD lease_time;
  707. +            DWORD use_nfspubfh;
  708.          } Mount;
  709.          struct {                      
  710.              PMDL MdlAddress;
  711. @@ -276,9 +277,13 @@ nfs41_updowncall_list upcall, downcall;
  712.  
  713.  
  714.  
  715. -/* In order to cooperate with other network providers,
  716. - * we only claim paths of the format '\\server\nfs4\path' */
  717. +/*
  718. + * In order to cooperate with other network providers,
  719. + * we only claim paths of the format '\\server\nfs4\path' or
  720. + * '\\server\pubnfs4\path'
  721. + */
  722.  DECLARE_CONST_UNICODE_STRING(NfsPrefix, L"\\nfs4");
  723. +DECLARE_CONST_UNICODE_STRING(PubNfsPrefix, L"\\pubnfs4");
  724.  DECLARE_CONST_UNICODE_STRING(AUTH_SYS_NAME, L"sys");
  725.  DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5_NAME, L"krb5");
  726.  DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5I_NAME, L"krb5i");
  727. @@ -294,6 +299,7 @@ DECLARE_CONST_UNICODE_STRING(EMPTY_STRING, L"");
  728.  #define UPCALL_TIMEOUT_DEFAULT          50  /* in seconds */
  729.  
  730.  typedef struct _NFS41_MOUNT_CONFIG {
  731. +    BOOLEAN use_nfspubfh;
  732.      DWORD ReadSize;
  733.      DWORD WriteSize;
  734.      BOOLEAN ReadOnly;
  735. @@ -682,7 +688,7 @@ NTSTATUS marshal_nfs41_mount(
  736.          goto out;
  737.      }
  738.      header_len = *len + length_as_utf8(entry->u.Mount.srv_name) +
  739. -        length_as_utf8(entry->u.Mount.root) + 3 * sizeof(DWORD);
  740. +        length_as_utf8(entry->u.Mount.root) + 4 * sizeof(DWORD);
  741.      if (header_len > buf_len) {
  742.          status = STATUS_INSUFFICIENT_RESOURCES;
  743.          goto out;
  744. @@ -696,15 +702,18 @@ NTSTATUS marshal_nfs41_mount(
  745.      RtlCopyMemory(tmp, &entry->u.Mount.rsize, sizeof(DWORD));
  746.      tmp += sizeof(DWORD);
  747.      RtlCopyMemory(tmp, &entry->u.Mount.wsize, sizeof(DWORD));
  748. +    tmp += sizeof(DWORD);
  749. +    RtlCopyMemory(tmp, &entry->u.Mount.use_nfspubfh, sizeof(DWORD));
  750.  
  751.      *len = header_len;
  752.  
  753.  #ifdef DEBUG_MARSHAL_DETAIL
  754.      DbgP("marshal_nfs41_mount: server name='%wZ' mount point='%wZ' "
  755. -         "sec_flavor='%s' rsize=%d wsize=%d\n",
  756. +         "sec_flavor='%s' rsize=%d wsize=%d use_nfspubfh=%d\n",
  757.          entry->u.Mount.srv_name, entry->u.Mount.root,
  758. -         secflavorop2name(entry->u.Mount.sec_flavor), entry->u.Mount.rsize,
  759. -         entry->u.Mount.wsize);
  760. +         secflavorop2name(entry->u.Mount.sec_flavor),
  761. +         (int)entry->u.Mount.rsize, (int)entry->u.Mount.wsize,
  762. +         (int)entry->u.Mount.use_nfspubfh);
  763.  #endif
  764.  out:
  765.      return status;
  766. @@ -2812,6 +2821,7 @@ NTSTATUS nfs41_mount(
  767.      entry->u.Mount.root = &config->MntPt;
  768.      entry->u.Mount.rsize = config->ReadSize;
  769.      entry->u.Mount.wsize = config->WriteSize;
  770. +    entry->u.Mount.use_nfspubfh = config->use_nfspubfh;
  771.      entry->u.Mount.sec_flavor = sec_flavor;
  772.      entry->u.Mount.FsAttrs = FsAttrs;
  773.  
  774. @@ -2846,6 +2856,7 @@ void nfs41_MountConfig_InitDefaults(
  775.  
  776.      Config->ReadSize = MOUNT_CONFIG_RW_SIZE_DEFAULT;
  777.      Config->WriteSize = MOUNT_CONFIG_RW_SIZE_DEFAULT;
  778. +    Config->use_nfspubfh = FALSE;
  779.      Config->ReadOnly = FALSE;
  780.      Config->write_thru = FALSE;
  781.      Config->nocache = FALSE;
  782. @@ -2992,6 +3003,15 @@ NTSTATUS nfs41_MountConfig_ParseOptions(
  783.                  &Config->WriteSize, MOUNT_CONFIG_RW_SIZE_MIN,
  784.                  MOUNT_CONFIG_RW_SIZE_MAX);
  785.          }
  786. +        else if (wcsncmp(L"public", Name, NameLen) == 0) {
  787. +            /*
  788. +             + We ignore this value here, and instead rely on the
  789. +             * /pubnfs4 prefix
  790. +             */
  791. +            BOOLEAN dummy;
  792. +            status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
  793. +                FALSE, &dummy);
  794. +        }
  795.          else if (wcsncmp(L"srvname", Name, NameLen) == 0) {
  796.              if (usValue.Length > Config->SrvName.MaximumLength)
  797.                  status = STATUS_NAME_TOO_LONG;
  798. @@ -3107,7 +3127,8 @@ out:
  799.  
  800.  NTSTATUS has_nfs_prefix(
  801.      IN PUNICODE_STRING SrvCallName,
  802. -    IN PUNICODE_STRING NetRootName)
  803. +    IN PUNICODE_STRING NetRootName,
  804. +    OUT BOOLEAN *pubfh_prefix)
  805.  {
  806.      NTSTATUS status = STATUS_BAD_NETWORK_NAME;
  807.  
  808. @@ -3140,20 +3161,42 @@ NTSTATUS has_nfs_prefix(
  809.              }
  810.          }
  811.  
  812. -        if ((state == 3) &&
  813. -            (!memcmp(&NetRootName->Buffer[i], L"\\nfs4",
  814. +        if (state == 3) {
  815. +            if (!memcmp(&NetRootName->Buffer[i], L"\\nfs4",
  816.                  (4*sizeof(wchar_t))))) {
  817. -            status = STATUS_SUCCESS;
  818. +                *pubfh_prefix = FALSE;
  819. +                status = STATUS_SUCCESS;
  820. +            }
  821. +            if ((NetRootName->Length >=
  822. +                (SrvCallName->Length + PubNfsPrefix.Length)) &&
  823. +                (!memcmp(&NetRootName->Buffer[i], L"\\pubnfs4",
  824. +                    (4*sizeof(wchar_t))))) {
  825. +                *pubfh_prefix = TRUE;
  826. +                status = STATUS_SUCCESS;
  827. +            }
  828.          }
  829.      }
  830.  #else
  831. -    if (NetRootName->Length == SrvCallName->Length + NfsPrefix.Length) {
  832. +    if (NetRootName->Length ==
  833. +        (SrvCallName->Length + NfsPrefix.Length)) {
  834.          const UNICODE_STRING NetRootPrefix = {
  835.              NfsPrefix.Length,
  836.              NetRootName->MaximumLength - SrvCallName->Length,
  837.              &NetRootName->Buffer[SrvCallName->Length/2]
  838.          };
  839. -        if (RtlCompareUnicodeString(&NetRootPrefix, &NfsPrefix, FALSE) == 0)
  840. +        if (!RtlCompareUnicodeString(&NetRootPrefix, &NfsPrefix, FALSE))
  841. +            *pubfh_prefix = FALSE;
  842. +            status = STATUS_SUCCESS;
  843. +    }
  844. +    else if (NetRootName->Length ==
  845. +        (SrvCallName->Length + PubNfsPrefix.Length)) {
  846. +        const UNICODE_STRING PubNetRootPrefix = {
  847. +            PubNfsPrefix.Length,
  848. +            NetRootName->MaximumLength - SrvCallName->Length,
  849. +            &NetRootName->Buffer[SrvCallName->Length/2]
  850. +        };
  851. +        if (!RtlCompareUnicodeString(&PubNetRootPrefix, &PubNfsPrefix, FALSE))
  852. +            *pubfh_prefix = TRUE;
  853.              status = STATUS_SUCCESS;
  854.      }
  855.  #endif
  856. @@ -3296,12 +3339,16 @@ NTSTATUS nfs41_CreateVNetRoot(
  857.  
  858.      pVNetRootContext->session = INVALID_HANDLE_VALUE;
  859.  
  860. -    /* In order to cooperate with other network providers, we must
  861. -     * only claim paths of the form '\\server\nfs4\path' */
  862. -    status = has_nfs_prefix(pSrvCall->pSrvCallName, pNetRoot->pNetRootName);
  863. +    /*
  864. +     * In order to cooperate with other network providers, we
  865. +     * must only claim paths of the form '\\server\nfs4\path'
  866. +     * or '\\server\pubnfs4\path'
  867. +     */
  868. +    BOOLEAN pubfh_prefix = FALSE;
  869. +    status = has_nfs_prefix(pSrvCall->pSrvCallName, pNetRoot->pNetRootName, &pubfh_prefix);
  870.      if (status) {
  871.          print_error("nfs41_CreateVNetRoot: NetRootName '%wZ' doesn't match "
  872. -            "'\\nfs4'!\n", pNetRoot->pNetRootName);
  873. +            "'\\nfs4' or '\\pubnfs4'!\n", pNetRoot->pNetRootName);
  874.          goto out;
  875.      }
  876.      pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
  877. @@ -3335,8 +3382,11 @@ NTSTATUS nfs41_CreateVNetRoot(
  878.          pVNetRootContext->write_thru = Config->write_thru;
  879.          pVNetRootContext->nocache = Config->nocache;
  880.      } else {
  881. -        /* Codepath for \\server@port\nfs4\path */
  882. -        DbgP("Codepath for \\\\server@port\\nfs4\\path\n");
  883. +        /*
  884. +         * Codepath for \\server@port\nfs4\path or
  885. +         * \\server@port\pubnfs4\path
  886. +         */
  887. +        DbgP("Codepath for \\\\server@port\\@(pubnfs4|nfs4)\\path\n");
  888.  
  889.          /*
  890.           * STATUS_NFS_SHARE_NOT_MOUNTED - status code for the case
  891. @@ -3427,9 +3477,12 @@ NTSTATUS nfs41_CreateVNetRoot(
  892.          pVNetRootContext->nocache = Config->nocache;
  893.      }
  894.  
  895. +    Config->use_nfspubfh = pubfh_prefix;
  896. +
  897.      DbgP("Config->{ "
  898.          "MntPt='%wZ', "
  899.          "SrvName='%wZ', "
  900. +        "use_nfspubfh=%d, "
  901.          "ReadOnly=%d, "
  902.          "write_thru=%d, "
  903.          "nocache=%d "
  904. @@ -3439,6 +3492,7 @@ NTSTATUS nfs41_CreateVNetRoot(
  905.          "}\n",
  906.          &Config->MntPt,
  907.          &Config->SrvName,
  908. +        Config->use_nfspubfh?1:0,
  909.          Config->ReadOnly?1:0,
  910.          Config->write_thru?1:0,
  911.          Config->nocache?1:0,
  912. @@ -3564,7 +3618,7 @@ NTSTATUS nfs41_CreateVNetRoot(
  913.          RtlCopyLuid(&entry->login_id, &luid);
  914.          /*
  915.           * Save mount config so we can use it for
  916. -         * \\server@port\nfs4\path mounts later
  917. +         * \\server@port\@(pubnfs4|nfs4)\path mounts later
  918.           */
  919.          copy_nfs41_mount_config(&entry->Config, Config);
  920.          nfs41_AddEntry(pNetRootContext->mountLock,
  921. --
  922. 2.45.1
  923.  
  924. From 2e981771fad01253e1389a3c97b9086d8b01d935 Mon Sep 17 00:00:00 2001
  925. From: Roland Mainz <roland.mainz@nrubsig.org>
  926. Date: Mon, 15 Jul 2024 11:28:15 +0200
  927. Subject: [PATCH 03/11] daemon,sys: Map |NFS4ERR_NOTSUPP| to
  928.  |ERROR_NOT_SUPPORTED|/|STATUS_NOT_SUPPORTED|
  929.  
  930. Map |NFS4ERR_NOTSUPP| to |ERROR_NOT_SUPPORTED|/|STATUS_NOT_SUPPORTED|,
  931. e.g. so nfs_mount.exe can report to the user if a specific mount
  932. option is not supported by the NFS server.
  933.  
  934. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  935. ---
  936. daemon/util.c      | 1 +
  937.  sys/nfs41_driver.c | 1 +
  938.  2 files changed, 2 insertions(+)
  939.  
  940. diff --git a/daemon/util.c b/daemon/util.c
  941. index c764303..c22bc6e 100644
  942. --- a/daemon/util.c
  943. +++ b/daemon/util.c
  944. @@ -345,6 +345,7 @@ int nfs_to_windows_error(int status, int default_error)
  945.      case NFS4ERR_STALE:         return ERROR_NETNAME_DELETED;
  946.      case NFS4ERR_NOTEMPTY:      return ERROR_NOT_EMPTY;
  947.      case NFS4ERR_DENIED:        return ERROR_LOCK_FAILED;
  948. +    case NFS4ERR_NOTSUPP:       return ERROR_NOT_SUPPORTED;
  949.      case NFS4ERR_TOOSMALL:      return ERROR_BUFFER_OVERFLOW;
  950.      case NFS4ERR_LOCKED:        return ERROR_LOCK_VIOLATION;
  951.      case NFS4ERR_SHARE_DENIED:  return ERROR_SHARING_VIOLATION;
  952. diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
  953. index 9d16b5d..aedd80d 100644
  954. --- a/sys/nfs41_driver.c
  955. +++ b/sys/nfs41_driver.c
  956. @@ -2789,6 +2789,7 @@ NTSTATUS map_mount_errors(
  957.      case ERROR_BAD_NET_RESP:    return STATUS_UNEXPECTED_NETWORK_ERROR;
  958.      case ERROR_BAD_NET_NAME:    return STATUS_BAD_NETWORK_NAME;
  959.      case ERROR_BAD_NETPATH:     return STATUS_BAD_NETWORK_PATH;
  960. +    case ERROR_NOT_SUPPORTED:   return STATUS_NOT_SUPPORTED;
  961.      case ERROR_INTERNAL_ERROR:  return STATUS_INTERNAL_ERROR;
  962.      default:
  963.          print_error("map_mount_errors: "
  964. --
  965. 2.45.1
  966.  
  967. From 55cd519f5cb409adc62d3fb1ee4700f4b65bd738 Mon Sep 17 00:00:00 2001
  968. From: Roland Mainz <roland.mainz@nrubsig.org>
  969. Date: Mon, 15 Jul 2024 12:03:32 +0200
  970. Subject: [PATCH 04/11] mount: DEBUG_MOUNT: Print mount options
  971.  
  972. DEBUG_MOUNT: Print mount options
  973.  
  974. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  975. ---
  976. mount/mount.c   | 10 +++++++---
  977.  mount/options.c |  2 +-
  978.  mount/options.h |  3 +++
  979.  3 files changed, 11 insertions(+), 4 deletions(-)
  980.  
  981. diff --git a/mount/mount.c b/mount/mount.c
  982. index f0c41e9..6a39064 100644
  983. --- a/mount/mount.c
  984. +++ b/mount/mount.c
  985. @@ -773,16 +773,20 @@ static DWORD DoMount(
  986.      DWORD dwLength;
  987.      NETRESOURCE NetResource;
  988.  
  989. -
  990.      if (pOptions->Buffer->Length) {
  991.          if (pOptions->Current)
  992.              pOptions->Current->NextEntryOffset = 0;
  993.          NetResource.lpComment = (LPTSTR)&pOptions->Buffer[0];
  994.      }
  995.  
  996. -#if 0
  997. +#ifdef DEBUG_MOUNT
  998. +    (void)_ftprintf(stderr,
  999. +        TEXT("DoMount(pLocalName='%s', pRemoteName='%s', pParsedRemoteName='%s')\n"),
  1000. +        pLocalName,
  1001. +        pRemoteName,
  1002. +        pParsedRemoteName);
  1003.      RecursivePrintEaInformation((PFILE_FULL_EA_INFORMATION)pOptions->Buffer->Buffer);
  1004. -#endif
  1005. +#endif /* DEBUG_MOUNT */
  1006.  
  1007.      /* fail if the connection already exists */
  1008.      dwLength = NFS41_SYS_MAX_PATH_LEN;
  1009. diff --git a/mount/options.c b/mount/options.c
  1010. index 1655162..8910eb7 100644
  1011. --- a/mount/options.c
  1012. +++ b/mount/options.c
  1013. @@ -158,7 +158,7 @@ BOOL InsertOption(
  1014.      return TRUE;
  1015.  }
  1016.  
  1017. -static void RecursivePrintEaInformation(
  1018. +void RecursivePrintEaInformation(
  1019.      IN PFILE_FULL_EA_INFORMATION EA)
  1020.  {
  1021.      _tprintf(
  1022. diff --git a/mount/options.h b/mount/options.h
  1023. index 5132615..ea6d9c6 100644
  1024. --- a/mount/options.h
  1025. +++ b/mount/options.h
  1026. @@ -89,4 +89,7 @@ BOOL InsertOption(
  1027.      IN LPCTSTR Value,
  1028.      IN OUT PMOUNT_OPTION_LIST Options);
  1029.  
  1030. +void RecursivePrintEaInformation(
  1031. +    IN PFILE_FULL_EA_INFORMATION EA);
  1032. +
  1033.  #endif /* !__NFS41_MOUNT_OPTIONS_H__ */
  1034. --
  1035. 2.45.1
  1036.  
  1037. From e0fce3e9aceead065d23c21cb8617ce54f70e2af Mon Sep 17 00:00:00 2001
  1038. From: Roland Mainz <roland.mainz@nrubsig.org>
  1039. Date: Mon, 15 Jul 2024 13:34:44 +0200
  1040. Subject: [PATCH 05/11] mount: nfs_mount -o port=1234 should override the port
  1041.  number in an nfs://-URL
  1042.  
  1043. nfs_mount.exe -o port=1234 should override the port number in an nfs://-URL
  1044.  
  1045. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1046. ---
  1047. mount/mount.c | 83 +++++++++++++++++++++++++++++++++++++++------------
  1048.  1 file changed, 64 insertions(+), 19 deletions(-)
  1049.  
  1050. diff --git a/mount/mount.c b/mount/mount.c
  1051. index 6a39064..119d46b 100644
  1052. --- a/mount/mount.c
  1053. +++ b/mount/mount.c
  1054. @@ -53,6 +53,7 @@ DWORD EnumMounts(
  1055.  
  1056.  static DWORD ParseRemoteName(
  1057.      IN bool use_nfspubfh,
  1058. +    IN int override_portnum,
  1059.      IN LPTSTR pRemoteName,
  1060.      IN OUT PMOUNT_OPTION_LIST pOptions,
  1061.      OUT LPTSTR pParsedRemoteName,
  1062. @@ -151,6 +152,7 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  1063.      BOOL    bUnmount = FALSE;
  1064.      BOOL    bForceUnmount = FALSE;
  1065.      BOOL    bPersistent = FALSE;
  1066. +    int     port_num = -1;
  1067.      MOUNT_OPTION_LIST Options;
  1068.  #define MAX_MNTOPTS 128
  1069.      TCHAR   *mntopts[MAX_MNTOPTS] = { 0 };
  1070. @@ -225,18 +227,70 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  1071.  
  1072.                  mntopts[num_mntopts++] = argv[i];
  1073.  
  1074. +                wchar_t *argv_i = argv[i];
  1075. +                bool found_opt;
  1076. +
  1077. +opt_o_argv_i_again:
  1078.                  /*
  1079. -                 * Extract "public" option here, as we need this for
  1080. +                 * Extract options here, which are needed by
  1081.                   * |ParseRemoteName()|. General parsing of -o options
  1082.                   * happens *AFTER* |ParseRemoteName()|, so any
  1083.                   * settings from a nfs://-URL can be overridden
  1084.                   * via -o options.
  1085.                   */
  1086. -                if (wcsstr(argv[i], L"public=0")) {
  1087. +                found_opt = false;
  1088. +
  1089. +                /*
  1090. +                 * Extract "public" option
  1091. +                 */
  1092. +                if (wcsstr(argv_i, L"public=0")) {
  1093.                      use_nfspubfh = false;
  1094. +                    argv_i += 8;
  1095. +                    found_opt = true;
  1096.                  }
  1097. -                else if (wcsstr(argv[i], L"public")) {
  1098. +                else if (wcsstr(argv_i, L"public")) {
  1099.                      use_nfspubfh = true;
  1100. +                    argv_i += 6;
  1101. +                    found_opt = true;
  1102. +                }
  1103. +
  1104. +                /*
  1105. +                 * Extract port number
  1106. +                 */
  1107. +                wchar_t *pns; /* port number string */
  1108. +                pns = wcsstr(argv_i, L"port=");
  1109. +                if (pns) {
  1110. +                    wchar_t *db;
  1111. +                    wchar_t digit_buff[20];
  1112. +
  1113. +                    pns += 5; /* skip "port=" */
  1114. +
  1115. +                    /* Copy digits... */
  1116. +                    for(db = digit_buff ;
  1117. +                        iswdigit(*pns) &&
  1118. +                        ((db-digit_buff) < sizeof(digit_buff)) ; )
  1119. +                        *db++ = *pns++;
  1120. +                    *db = L'\0';
  1121. +
  1122. +                    /* ... and convert them to a port number */
  1123. +                    port_num = wcstol(digit_buff, NULL, 0);
  1124. +                    if ((port_num < 1) || (port_num > 65535)) {
  1125. +                        (void)_ftprintf(stderr, TEXT("NFSv4 TCP port number out of range.\n"));
  1126. +                        result = ERROR_BAD_ARGUMENTS;
  1127. +                        goto out;
  1128. +                    }
  1129. +
  1130. +                    argv_i = pns-1;
  1131. +                    found_opt = true;
  1132. +                }
  1133. +
  1134. +                /*
  1135. +                 * Try again with the remainder of the |argv[i]| string,
  1136. +                 * so "port=666,port=888" will result in the port number
  1137. +                 * "888"
  1138. +                 */
  1139. +                if (found_opt) {
  1140. +                    goto opt_o_argv_i_again;
  1141.                  }
  1142.              }
  1143.              else if (_tcscmp(argv[i], TEXT("-r")) == 0) /* mount option */
  1144. @@ -353,8 +407,10 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  1145.           * options for a NFS mount point, which can be overridden via
  1146.           * -o below.
  1147.           */
  1148. -        result = ParseRemoteName(use_nfspubfh, pRemoteName, &Options,
  1149. -            szParsedRemoteName, szRemoteName, NFS41_SYS_MAX_PATH_LEN);
  1150. +        result = ParseRemoteName(use_nfspubfh, port_num,
  1151. +            pRemoteName, &Options,
  1152. +            szParsedRemoteName, szRemoteName,
  1153. +            NFS41_SYS_MAX_PATH_LEN);
  1154.          if (result)
  1155.              goto out;
  1156.  
  1157. @@ -432,6 +488,7 @@ wchar_t *utf8str2wcs(const char *utf8str)
  1158.  
  1159.  static DWORD ParseRemoteName(
  1160.      IN bool use_nfspubfh,
  1161. +    IN int override_portnum,
  1162.      IN LPTSTR pRemoteName,
  1163.      IN OUT PMOUNT_OPTION_LIST pOptions,
  1164.      OUT LPTSTR pParsedRemoteName,
  1165. @@ -442,7 +499,6 @@ static DWORD ParseRemoteName(
  1166.      LPTSTR pEnd;
  1167.      wchar_t *mountstrmem = NULL;
  1168.      int port = MOUNT_CONFIG_NFS_PORT_DEFAULT;
  1169. -    PFILE_FULL_EA_INFORMATION port_option_val;
  1170.      wchar_t remotename[NFS41_SYS_MAX_PATH_LEN];
  1171.      wchar_t *premotename = remotename;
  1172.  /* sizeof(hostname+'@'+integer) */
  1173. @@ -618,19 +674,8 @@ static DWORD ParseRemoteName(
  1174.       * Override the NFSv4 TCP port with the -o port=<num> option,
  1175.       * inclding for nfs://-URLs with port numbers
  1176.       */
  1177. -    if (FindOptionByName(TEXT("port"), pOptions,
  1178. -        &port_option_val)) {
  1179. -        wchar_t *port_value_wstr =
  1180. -            (PTCH)(port_option_val->EaName +
  1181. -                port_option_val->EaNameLength + sizeof(TCHAR));
  1182. -
  1183. -        port = _wtoi(port_value_wstr);
  1184. -    }
  1185. -
  1186. -    if ((port < 1) || (port > 65535)) {
  1187. -        (void)_ftprintf(stderr, TEXT("NFSv4 TCP port number out of range.\n"));
  1188. -        result = ERROR_BAD_ARGUMENTS;
  1189. -        goto out;
  1190. +    if (override_portnum != -1) {
  1191. +        port = override_portnum;
  1192.      }
  1193.  
  1194.      /*
  1195. --
  1196. 2.45.1
  1197.  
  1198. From f40205f70cf33041aea9eae88013bce632ee0ceb Mon Sep 17 00:00:00 2001
  1199. From: Roland Mainz <roland.mainz@nrubsig.org>
  1200. Date: Mon, 15 Jul 2024 13:52:34 +0200
  1201. Subject: [PATCH 06/11] mount,sys: nfs_mount should no longer send "port"
  1202.  option, obsoleted by hostport
  1203.  
  1204. nfs_mount.exe should no longer send "port" option, the port number
  1205. is already encoded in the hostport value.
  1206.  
  1207. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1208. ---
  1209. mount/options.c    |  8 ++++++++
  1210.  sys/nfs41_driver.c | 11 -----------
  1211.  2 files changed, 8 insertions(+), 11 deletions(-)
  1212.  
  1213. diff --git a/mount/options.c b/mount/options.c
  1214. index 8910eb7..73d92ce 100644
  1215. --- a/mount/options.c
  1216. +++ b/mount/options.c
  1217. @@ -108,6 +108,14 @@ BOOL InsertOption(
  1218.      USHORT ValueLen = (USHORT)_tcslen(Value) * sizeof(TCHAR);
  1219.      ULONG SpaceRequired = EaBufferSize(NameLen, ValueLen);
  1220.  
  1221. +    /*
  1222. +     * Filter "port" option, as it's value has already been encoded
  1223. +     *  in the hostname as hostport
  1224. +     */
  1225. +    if (!_tcscmp(Name, L"port")) {
  1226. +        return TRUE;
  1227. +    }
  1228. +
  1229.      /*
  1230.       * FIXME: Some duplicates are wanted, e.g. "rw" overriding "ro" etc
  1231.       * So better just let the kernel do the work
  1232. diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c
  1233. index aedd80d..ad71496 100644
  1234. --- a/sys/nfs41_driver.c
  1235. +++ b/sys/nfs41_driver.c
  1236. @@ -3019,17 +3019,6 @@ NTSTATUS nfs41_MountConfig_ParseOptions(
  1237.              else
  1238.                  RtlCopyUnicodeString(&Config->SrvName, &usValue);
  1239.          }
  1240. -       /*
  1241. -        * gisburn: fixme: for now we accept "port=" as dummy here
  1242. -        * Technically nfs_mount.exe should filter this out. We leave
  1243. -        * this in for backwards-compatibilty with our internal test
  1244. -        * suite
  1245. -        */
  1246. -        else if (wcsncmp(L"port", Name, NameLen) == 0) {
  1247. -           DWORD dummy;
  1248. -            status = nfs41_MountConfig_ParseDword(Option, &usValue,
  1249. -                &dummy, 1, 65535);
  1250. -        }
  1251.          else if (wcsncmp(L"mntpt", Name, NameLen) == 0) {
  1252.              if (usValue.Length > Config->MntPt.MaximumLength)
  1253.                  status = STATUS_NAME_TOO_LONG;
  1254. --
  1255. 2.45.1
  1256.  
  1257. From c60bb5ac0d32a4afd6a11c022c4c0857baa36d9b Mon Sep 17 00:00:00 2001
  1258. From: Roland Mainz <roland.mainz@nrubsig.org>
  1259. Date: Mon, 15 Jul 2024 15:39:21 +0200
  1260. Subject: [PATCH 07/11] daemon,mount,sys: Remove <tchar.h> usage
  1261.  
  1262. Remove <tchar.h> usage per review feedback.
  1263.  
  1264. Reported-by: Josh Hurst <joshhurst@gmail.com>
  1265. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  1266. ---
  1267. daemon/nfs41_daemon.c |  45 ++---
  1268.  mount/enum.c          |  50 ++---
  1269.  mount/mount.c         | 428 +++++++++++++++++++++---------------------
  1270.  mount/options.c       |  80 ++++----
  1271.  sys/nfs41_driver.h    |   1 -
  1272.  5 files changed, 302 insertions(+), 302 deletions(-)
  1273.  
  1274. diff --git a/daemon/nfs41_daemon.c b/daemon/nfs41_daemon.c
  1275. index 70979ef..73cfe4c 100644
  1276. --- a/daemon/nfs41_daemon.c
  1277. +++ b/daemon/nfs41_daemon.c
  1278. @@ -26,7 +26,6 @@
  1279.  
  1280.  #include <Windows.h>
  1281.  #include <process.h>
  1282. -#include <tchar.h>
  1283.  #include <stdio.h>
  1284.  
  1285.  #include <devioctl.h>
  1286. @@ -273,7 +272,9 @@ static void PrintUsage()
  1287.  #endif /* _DEBUG */
  1288.          "\n", MAX_NUM_THREADS);
  1289.  }
  1290. -static bool_t parse_cmdlineargs(int argc, TCHAR *argv[], nfsd_args *out)
  1291. +
  1292. +static
  1293. +bool_t parse_cmdlineargs(int argc, wchar_t *argv[], nfsd_args *out)
  1294.  {
  1295.      int i;
  1296.  
  1297. @@ -283,24 +284,24 @@ static bool_t parse_cmdlineargs(int argc, TCHAR *argv[], nfsd_args *out)
  1298.  
  1299.      /* parse command line */
  1300.      for (i = 1; i < argc; i++) {
  1301. -        if (argv[i][0] == TEXT('-')) {
  1302. -            if (_tcscmp(argv[i], TEXT("-h")) == 0) { /* help */
  1303. +        if (argv[i][0] == L'-') {
  1304. +            if (!wcscmp(argv[i], L"-h")) { /* help */
  1305.                  PrintUsage();
  1306.                  return FALSE;
  1307.              }
  1308. -            else if (_tcscmp(argv[i], TEXT("-d")) == 0) { /* debug level */
  1309. +            else if (!wcscmp(argv[i], L"-d")) { /* debug level */
  1310.                  ++i;
  1311.                  if (i >= argc) {
  1312.                      fprintf(stderr, "Missing debug level value\n");
  1313.                      PrintUsage();
  1314.                      return FALSE;
  1315.                  }
  1316. -                out->debug_level = _ttoi(argv[i]);
  1317. +                out->debug_level = wcstol(argv[i], NULL, 0);
  1318.              }
  1319.  #ifdef _DEBUG
  1320. -            else if (_tcscmp(argv[i], TEXT("--crtdbgmem")) == 0) {
  1321. +            else if (!wcscmp(argv[i], L"--crtdbgmem")) {
  1322.                  ++i;
  1323. -                const TCHAR *memdbgoptions = argv[i];
  1324. +                const wchar_t *memdbgoptions = argv[i];
  1325.                  if (i >= argc) {
  1326.                      fprintf(stderr, "Missing options\n");
  1327.                      PrintUsage();
  1328. @@ -312,62 +313,62 @@ static bool_t parse_cmdlineargs(int argc, TCHAR *argv[], nfsd_args *out)
  1329.                      nfs41_dg.crtdbgmem_flags = 0;
  1330.  
  1331.                  nfs41_dg.crtdbgmem_flags |=
  1332. -                    (_tcsstr(memdbgoptions, TEXT("allocmem")) != NULL)?
  1333. +                    (wcsstr(memdbgoptions, L"allocmem") != NULL)?
  1334.                      _CRTDBG_ALLOC_MEM_DF:0;
  1335.                  nfs41_dg.crtdbgmem_flags |=
  1336. -                    (_tcsstr(memdbgoptions, TEXT("leakcheck")) != NULL)?
  1337. +                    (wcsstr(memdbgoptions, L"leakcheck") != NULL)?
  1338.                      _CRTDBG_LEAK_CHECK_DF:0;
  1339.                  nfs41_dg.crtdbgmem_flags |=
  1340. -                    (_tcsstr(memdbgoptions, TEXT("delayfree")) != NULL)?
  1341. +                    (wcsstr(memdbgoptions, L"delayfree") != NULL)?
  1342.                      _CRTDBG_DELAY_FREE_MEM_DF:0;
  1343.                  nfs41_dg.crtdbgmem_flags |=
  1344. -                    (_tcsstr(memdbgoptions, TEXT("all")) != NULL)?
  1345. +                    (wcsstr(memdbgoptions, L"all") != NULL)?
  1346.                      (_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF|_CRTDBG_DELAY_FREE_MEM_DF):0;
  1347.  
  1348. -                if (_tcsstr(memdbgoptions, TEXT("none")) != NULL) {
  1349. +                if (wcsstr(memdbgoptions, L"none") != NULL) {
  1350.                      nfs41_dg.crtdbgmem_flags = 0;
  1351.                  }
  1352.  
  1353. -                if (_tcsstr(memdbgoptions, TEXT("default")) != NULL) {
  1354. +                if (wcsstr(memdbgoptions, L"default") != NULL) {
  1355.                      nfs41_dg.crtdbgmem_flags =
  1356.                          NFS41D_GLOBALS_CRTDBGMEM_FLAGS_NOT_SET;
  1357.                  }
  1358.              }
  1359.  #endif /* _DEBUG */
  1360. -            else if (_tcscmp(argv[i], TEXT("--noldap")) == 0) { /* no LDAP */
  1361. +            else if (!wcscmp(argv[i], L"--noldap")) { /* no LDAP */
  1362.                  out->ldap_enable = FALSE;
  1363.              }
  1364. -            else if (_tcscmp(argv[i], TEXT("--uid")) == 0) { /* no LDAP, setting default uid */
  1365. +            else if (!wcscmp(argv[i], L"--uid")) { /* no LDAP, setting default uid */
  1366.                  ++i;
  1367.                  if (i >= argc) {
  1368.                      fprintf(stderr, "Missing uid value\n");
  1369.                      PrintUsage();
  1370.                      return FALSE;
  1371.                  }
  1372. -                nfs41_dg.default_uid = _ttoi(argv[i]);
  1373. +                nfs41_dg.default_uid = wcstol(argv[i], NULL, 0);
  1374.                  if (!nfs41_dg.default_uid) {
  1375.                      fprintf(stderr, "Invalid (or missing) anonymous uid value of %d\n",
  1376.                          nfs41_dg.default_uid);
  1377.                      return FALSE;
  1378.                  }
  1379.              }
  1380. -            else if (_tcscmp(argv[i], TEXT("--gid")) == 0) { /* no LDAP, setting default gid */
  1381. +            else if (!wcscmp(argv[i], L"--gid")) { /* no LDAP, setting default gid */
  1382.                  ++i;
  1383.                  if (i >= argc) {
  1384.                      fprintf(stderr, "Missing gid value\n");
  1385.                      PrintUsage();
  1386.                      return FALSE;
  1387.                  }
  1388. -                nfs41_dg.default_gid = _ttoi(argv[i]);
  1389. +                nfs41_dg.default_gid = wcstol(argv[i], NULL, 0);
  1390.              }
  1391. -            else if (_tcscmp(argv[i], TEXT("--numworkerthreads")) == 0) {
  1392. +            else if (!wcscmp(argv[i], L"--numworkerthreads")) {
  1393.                  ++i;
  1394.                  if (i >= argc) {
  1395.                      fprintf(stderr, "Missing value for num_worker_threads\n");
  1396.                      PrintUsage();
  1397.                      return FALSE;
  1398.                  }
  1399. -                nfs41_dg.num_worker_threads = _ttoi(argv[i]);
  1400. +                nfs41_dg.num_worker_threads = wcstol(argv[i], NULL, 0);
  1401.                  if (nfs41_dg.num_worker_threads < 16) {
  1402.                      fprintf(stderr, "--numworkerthreads requires at least 16 worker threads\n");
  1403.                      PrintUsage();
  1404. @@ -705,7 +706,7 @@ void set_nfs_daemon_privileges(void)
  1405.  
  1406.  
  1407.  #ifdef STANDALONE_NFSD
  1408. -void __cdecl _tmain(int argc, TCHAR *argv[])
  1409. +void __cdecl wmain(int argc, wchar_t *argv[])
  1410.  #else
  1411.  VOID ServiceStart(DWORD argc, LPTSTR *argv)
  1412.  #endif
  1413. diff --git a/mount/enum.c b/mount/enum.c
  1414. index 97043dd..9a74bca 100644
  1415. --- a/mount/enum.c
  1416. +++ b/mount/enum.c
  1417. @@ -3,6 +3,7 @@
  1418.   *
  1419.   * Olga Kornievskaia <aglo@umich.edu>
  1420.   * Casey Bodley <cbodley@umich.edu>
  1421. + * Roland Mainz <roland.mainz@nrubsig.org>
  1422.   *
  1423.   * This library is free software; you can redistribute it and/or modify it
  1424.   * under the terms of the GNU Lesser General Public License as published by
  1425. @@ -20,13 +21,12 @@
  1426.   */
  1427.  
  1428.  #include <Windows.h>
  1429. -#include <tchar.h>
  1430.  #include <stdbool.h>
  1431.  #include <stdio.h>
  1432.  #include <malloc.h>
  1433.  
  1434.  #include "nfs41_build_features.h"
  1435. -#include "nfs41_driver.h" /* NFS41_PROVIDER_NAME_A */
  1436. +#include "nfs41_driver.h" /* |NFS41_PROVIDER_NAME_U| */
  1437.  
  1438.  /* prototypes */
  1439.  char *wcs2utf8str(const wchar_t *wstr);
  1440. @@ -35,17 +35,19 @@ void PrintErrorMessage(IN DWORD dwError);
  1441.  /* fixme: this function needs a cleanup */
  1442.  static __inline
  1443.  void PrintMountLine(
  1444. -    LPCTSTR local,
  1445. -    LPCTSTR remote)
  1446. +    LPCWSTR local,
  1447. +    LPCWSTR remote)
  1448.  {
  1449. -    TCHAR *cygwin_unc_buffer = alloca((_tcslen(remote)+32)*sizeof(TCHAR));
  1450. -    char *cygwin_nfsurl_buffer = alloca(
  1451. -        ((_tcslen(remote)+32)*3)+8 +
  1452. +    size_t remote_len = wcslen(remote);
  1453. +    wchar_t *cygwin_unc_buffer =
  1454. +        alloca((remote_len+32)*sizeof(wchar_t));
  1455. +    char *cygwin_nfsurl_buffer =
  1456. +        alloca(((remote_len+32)*3)+8 +
  1457.          9 /* "?public=1" */
  1458.          );
  1459. -    TCHAR *b;
  1460. -    LPCTSTR s;
  1461. -    TCHAR sc;
  1462. +    wchar_t *b;
  1463. +    LPCWSTR s;
  1464. +    wchar_t sc;
  1465.  #ifndef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  1466.      unsigned int backslash_counter;
  1467.  #endif
  1468. @@ -56,13 +58,13 @@ void PrintMountLine(
  1469.       , backslash_counter = 0
  1470.  #endif
  1471.       ;
  1472. -        (sc = *s++) != TEXT('\0') ; ) {
  1473. +        (sc = *s++) != L'\0' ; ) {
  1474.          switch(sc) {
  1475. -            case TEXT('\\'):
  1476. -                *b++ = TEXT('/');
  1477. +            case L'\\':
  1478. +                *b++ = L'/';
  1479.  #ifndef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  1480.                  if (backslash_counter++ == 2) {
  1481. -                    (void)wcscpy_s(b, 6, TEXT("nfs4/"));
  1482. +                    (void)wcscpy_s(b, 6, L"nfs4/");
  1483.                      b+=5;
  1484.                  }
  1485.  #endif
  1486. @@ -72,7 +74,7 @@ void PrintMountLine(
  1487.                  break;
  1488.          }
  1489.      }
  1490. -    *b = TEXT('\0');
  1491. +    *b = L'\0';
  1492.  
  1493.  
  1494.      /*
  1495. @@ -182,7 +184,7 @@ void PrintMountLine(
  1496.  #pragma warning( pop )
  1497.      }
  1498.  
  1499. -    (void)_tprintf(TEXT("%-8s\t%-50s\t%-50s\t%-50S\n"),
  1500. +    (void)wprintf(L"%-8s\t%-50s\t%-50s\t%-50S\n",
  1501.          local, remote, cygwin_unc_buffer, cygwin_nfsurl_buffer);
  1502.  
  1503.      free(utf8unc);
  1504. @@ -217,10 +219,10 @@ DWORD EnumMounts(
  1505.      if (result)
  1506.          goto out_free;
  1507.  
  1508. -    (void)_tprintf(TEXT("Listing '%s' mounts:\n\n"),
  1509. -        TEXT(NFS41_PROVIDER_NAME_A));
  1510. -    (void)_tprintf(TEXT("%-8s\t%-50s\t%-50s\t%-50S\n"),
  1511. -        TEXT("Volume"), TEXT("Remote path"), TEXT("Cygwin UNC path"), "URL");
  1512. +    (void)wprintf(L"Listing '%s' mounts:\n\n",
  1513. +        NFS41_PROVIDER_NAME_U);
  1514. +    (void)wprintf(L"%-8s\t%-50s\t%-50s\t%-50s\n",
  1515. +        L"Volume", L"Remote path", L"Cygwin UNC path", L"URL");
  1516.  
  1517.      do
  1518.      {
  1519. @@ -232,8 +234,8 @@ DWORD EnumMounts(
  1520.          {
  1521.              for (i = 0; i < dwCount; i++)
  1522.              {
  1523. -                if (_tcscmp(pResources[i].lpProvider,
  1524. -                    TEXT(NFS41_PROVIDER_NAME_A)) == 0)
  1525. +                if (!wcscmp(pResources[i].lpProvider,
  1526. +                    NFS41_PROVIDER_NAME_U))
  1527.                  {
  1528.                      PrintMountLine(pResources[i].lpLocalName,
  1529.                          pResources[i].lpRemoteName);
  1530. @@ -248,8 +250,8 @@ DWORD EnumMounts(
  1531.  
  1532.      result = WNetCloseEnum(hEnum);
  1533.  
  1534. -    _tprintf(TEXT("\nFound %d share%s.\n"), dwTotal,
  1535. -        dwTotal == 1 ? TEXT("") : TEXT("s"));
  1536. +    (void)wprintf(L"\nFound %d share%s.\n", dwTotal,
  1537. +        (dwTotal == 1) ? L"" : L"s");
  1538.  
  1539.  out_free:
  1540.      GlobalFree((HGLOBAL)pResources);
  1541. diff --git a/mount/mount.c b/mount/mount.c
  1542. index 119d46b..d4a6680 100644
  1543. --- a/mount/mount.c
  1544. +++ b/mount/mount.c
  1545. @@ -26,7 +26,6 @@
  1546.  
  1547.  #include <crtdbg.h>
  1548.  #include <Windows.h>
  1549. -#include <tchar.h>
  1550.  #include <strsafe.h>
  1551.  #include <Winnetwk.h> /* for WNet*Connection */
  1552.  #include <stdlib.h>
  1553. @@ -34,7 +33,7 @@
  1554.  #include <stdio.h>
  1555.  
  1556.  #include "nfs41_build_features.h"
  1557. -#include "nfs41_driver.h" /* NFS41_PROVIDER_NAME_A */
  1558. +#include "nfs41_driver.h" /* |NFS41_PROVIDER_NAME_U| */
  1559.  #include "options.h"
  1560.  #include "urlparser1.h"
  1561.  
  1562. @@ -54,109 +53,110 @@ DWORD EnumMounts(
  1563.  static DWORD ParseRemoteName(
  1564.      IN bool use_nfspubfh,
  1565.      IN int override_portnum,
  1566. -    IN LPTSTR pRemoteName,
  1567. +    IN LPWSTR pRemoteName,
  1568.      IN OUT PMOUNT_OPTION_LIST pOptions,
  1569. -    OUT LPTSTR pParsedRemoteName,
  1570. -    OUT LPTSTR pConnectionName,
  1571. +    OUT LPWSTR pParsedRemoteName,
  1572. +    OUT LPWSTR pConnectionName,
  1573.      IN size_t cchConnectionLen);
  1574.  static DWORD DoMount(
  1575. -    IN LPTSTR pLocalName,
  1576. -    IN LPTSTR pRemoteName,
  1577. -    IN LPTSTR pParsedRemoteName,
  1578. +    IN LPWSTR pLocalName,
  1579. +    IN LPWSTR pRemoteName,
  1580. +    IN LPWSTR pParsedRemoteName,
  1581.      IN BOOL bPersistent,
  1582.      IN PMOUNT_OPTION_LIST pOptions);
  1583.  static DWORD DoUnmount(
  1584. -    IN LPTSTR pLocalName,
  1585. +    IN LPWSTR pLocalName,
  1586.      IN BOOL bForce);
  1587.  static BOOL ParseDriveLetter(
  1588. -    IN LPTSTR pArg,
  1589. +    IN LPWSTR pArg,
  1590.      OUT PTCH pDriveLetter);
  1591.  void PrintErrorMessage(
  1592.      IN DWORD dwError);
  1593.  
  1594. -static VOID PrintUsage(LPTSTR pProcess)
  1595. +static VOID PrintUsage(LPWSTR pProcess)
  1596.  {
  1597. -    (void)_tprintf(
  1598. -        TEXT("Usage: %s [options] <drive letter|*> <hostname>:<path>\n")
  1599. -
  1600. -        TEXT("* Options:\n")
  1601. -        TEXT("\t-h\thelp\n")
  1602. -        TEXT("\t/?\thelp\n")
  1603. -        TEXT("\t-d\tunmount\n")
  1604. -        TEXT("\t-f\tforce unmount if the drive is in use\n")
  1605. -        TEXT("\t-F <type>\tFilesystem type to use (only 'nfs' supported)"
  1606. -           " (Solaris/Illumos compat)\n")
  1607. -        TEXT("\t-t <type>\tFilesystem type to use (only 'nfs' supported)"
  1608. -           " (Linux compat)\n")
  1609. -        TEXT("\t-p\tmake the mount persist over reboots\n")
  1610. -        TEXT("\t-o <comma-separated mount options>\n")
  1611. -        TEXT("\t-r\tAlias for -o ro (read-only mount)\n")
  1612. -        TEXT("\t-w\tAlias for -o rw (read-write mount)\n")
  1613. -
  1614. -        TEXT("* Mount options:\n")
  1615. -        TEXT("\tpublic\tconnect to the server using the public file handle lookup protocol.\n")
  1616. -        TEXT("\t\t(See WebNFS Client Specification, RFC 2054).\n")
  1617. -        TEXT("\tro\tmount as read-only\n")
  1618. -        TEXT("\trw\tmount as read-write (default)\n")
  1619. -        TEXT("\tport=#\tTCP port to use (defaults to 2049)\n")
  1620. -        TEXT("\trsize=#\tread buffer size in bytes\n")
  1621. -        TEXT("\twsize=#\twrite buffer size in bytes\n")
  1622. -        TEXT("\tsec=sys:krb5:krb5i:krb5p\tspecify (gss) security flavor\n")
  1623. -        TEXT("\twritethru\tturns off rdbss caching for writes\n")
  1624. -        TEXT("\tnowritethru\tturns on rdbss caching for writes (default)\n")
  1625. -        TEXT("\tcache\tturns on rdbss caching (default)\n")
  1626. -        TEXT("\tnocache\tturns off rdbss caching\n")
  1627. -        TEXT("\twsize=#\twrite buffer size in bytes\n")
  1628. -        TEXT("\tcreatemode=\tspecify default POSIX permission mode\n"
  1629. +    (void)fprintf(stderr,
  1630. +        "Usage: %S [options] <drive letter|*> <hostname>:<path>\n"
  1631. +
  1632. +        "* Options:\n"
  1633. +        "\t-h\thelp\n"
  1634. +        "\t/?\thelp\n"
  1635. +        "\t-d\tunmount\n"
  1636. +        "\t-f\tforce unmount if the drive is in use\n"
  1637. +            "\t-F <type>\tFilesystem type to use (only 'nfs' supported)"
  1638. +           " (Solaris/Illumos compat)\n"
  1639. +        "\t-t <type>\tFilesystem type to use (only 'nfs' supported)"
  1640. +           " (Linux compat)\n"
  1641. +        "\t-p\tmake the mount persist over reboots\n"
  1642. +        "\t-o <comma-separated mount options>\n"
  1643. +        "\t-r\tAlias for -o ro (read-only mount)\n"
  1644. +        "\t-w\tAlias for -o rw (read-write mount)\n"
  1645. +
  1646. +        "* Mount options:\n"
  1647. +        "\tpublic\tconnect to the server using the public file handle lookup protocol.\n"
  1648. +        "\t\t(See WebNFS Client Specification, RFC 2054).\n"
  1649. +        "\tro\tmount as read-only\n"
  1650. +        "\trw\tmount as read-write (default)\n"
  1651. +        "\tport=#\tTCP port to use (defaults to 2049)\n"
  1652. +        "\trsize=#\tread buffer size in bytes\n"
  1653. +        "\twsize=#\twrite buffer size in bytes\n"
  1654. +        "\tsec=sys:krb5:krb5i:krb5p\tspecify (gss) security flavor\n"
  1655. +        "\twritethru\tturns off rdbss caching for writes\n"
  1656. +        "\tnowritethru\tturns on rdbss caching for writes (default)\n"
  1657. +        "\tcache\tturns on rdbss caching (default)\n"
  1658. +        "\tnocache\tturns off rdbss caching\n"
  1659. +        "\twsize=#\twrite buffer size in bytes\n"
  1660. +        "\tcreatemode=\tspecify default POSIX permission mode\n"
  1661.              "\t\tfor new files created on the NFS share.\n"
  1662.              "\t\tArgument is an octal value prefixed with '0o',\n"
  1663.              "\t\tif this value is prefixed with 'nfsv3attrmode+'\n"
  1664.              "\t\tthe mode value from a \"NfsV3Attributes\" EA will be used\n"
  1665. -            "\t\t(defaults \"nfsv3attrmode+0o%o\").\n")
  1666. -
  1667. -        TEXT("* URL parameters:\n")
  1668. -        TEXT("\tro=1\tmount as read-only\n")
  1669. -        TEXT("\trw=1\tmount as read-write (default)\n")
  1670. -
  1671. -        TEXT("* Hostname:\n")
  1672. -        TEXT("\tDNS name, or hostname in domain\n")
  1673. -        TEXT("\tentry in C:\\Windows\\System32\\drivers\\etc\\hosts\n")
  1674. -        TEXT("\tIPv4 address\n")
  1675. -        TEXT("\tIPv6 address within '[', ']' "
  1676. -            "(will be converted to *.ipv6-literal.net)\n")
  1677. -
  1678. -        TEXT("* Examples:\n")
  1679. -        TEXT("\tnfs_mount.exe -p -o rw 'H' derfwpc5131_ipv4:/export/home2/rmainz\n")
  1680. -        TEXT("\tnfs_mount.exe -o rw '*' bigramhost:/tmp\n")
  1681. -        TEXT("\tnfs_mount.exe -o ro '*' archive1:/tmp\n")
  1682. -        TEXT("\tnfs_mount.exe '*' archive1:/tmp?ro=1\n")
  1683. -        TEXT("\tnfs_mount.exe -o rw,sec=sys,port=30000 T grendel:/net_tmpfs2\n")
  1684. -        TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//net_tmpfs2/test2\n")
  1685. -        TEXT("\tnfs_mount.exe -o sec=sys S nfs://myhost1//net_tmpfs2/test2?rw=1\n")
  1686. -        TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1:1234//net_tmpfs2/test2\n")
  1687. -        TEXT("\tnfs_mount.exe -o sec=sys,rw,port=1234 S nfs://myhost1//net_tmpfs2/test2\n")
  1688. -        TEXT("\tnfs_mount.exe -o sec=sys,rw '*' [fe80::21b:1bff:fec3:7713]://net_tmpfs2/test2\n")
  1689. -        TEXT("\tnfs_mount.exe -o sec=sys,rw '*' nfs://[fe80::21b:1bff:fec3:7713]//net_tmpfs2/test2\n")
  1690. -        TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir%%20space/test2\n")
  1691. -        TEXT("\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir+space/test2\n")
  1692. -        TEXT("\tnfs_mount.exe -o sec=sys S nfs://myhost1//dirwithspace/dir+space/test2?rw=1\n"),
  1693. +            "\t\t(defaults \"nfsv3attrmode+0o%o\").\n"
  1694. +
  1695. +        "* URL parameters:\n"
  1696. +        "\tro=1\tmount as read-only\n"
  1697. +        "\trw=1\tmount as read-write (default)\n"
  1698. +
  1699. +        "* Hostname:\n"
  1700. +        "\tDNS name, or hostname in domain\n"
  1701. +        "\tentry in C:\\Windows\\System32\\drivers\\etc\\hosts\n"
  1702. +        "\tIPv4 address\n"
  1703. +        "\tIPv6 address within '[', ']' "
  1704. +            "(will be converted to *.ipv6-literal.net)\n"
  1705. +
  1706. +        "* Examples:\n"
  1707. +        "\tnfs_mount.exe -p -o rw 'H' derfwpc5131_ipv4:/export/home2/rmainz\n"
  1708. +        "\tnfs_mount.exe -o rw '*' bigramhost:/tmp\n"
  1709. +        "\tnfs_mount.exe -o ro '*' archive1:/tmp\n"
  1710. +        "\tnfs_mount.exe '*' archive1:/tmp?ro=1\n"
  1711. +        "\tnfs_mount.exe -o rw,sec=sys,port=30000 T grendel:/net_tmpfs2\n"
  1712. +        "\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//net_tmpfs2/test2\n"
  1713. +        "\tnfs_mount.exe -o sec=sys S nfs://myhost1//net_tmpfs2/test2?rw=1\n"
  1714. +        "\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1:1234//net_tmpfs2/test2\n"
  1715. +        "\tnfs_mount.exe -o sec=sys,rw,port=1234 S nfs://myhost1//net_tmpfs2/test2\n"
  1716. +        "\tnfs_mount.exe -o sec=sys,rw '*' [fe80::21b:1bff:fec3:7713]://net_tmpfs2/test2\n"
  1717. +        "\tnfs_mount.exe -o sec=sys,rw '*' nfs://[fe80::21b:1bff:fec3:7713]//net_tmpfs2/test2\n"
  1718. +        "\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir%%20space/test2\n"
  1719. +        "\tnfs_mount.exe -o sec=sys,rw S nfs://myhost1//dirwithspace/dir+space/test2\n"
  1720. +        "\tnfs_mount.exe -o sec=sys S nfs://myhost1//dirwithspace/dir+space/test2?rw=1\n",
  1721.          pProcess, (int)NFS41_DRIVER_DEFAULT_CREATE_MODE);
  1722.  }
  1723.  
  1724. -DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  1725. +int __cdecl wmain(int argc, wchar_t *argv[])
  1726.  {
  1727. -    DWORD   i, result = NO_ERROR;
  1728. -    TCHAR   szLocalName[] = TEXT("C:\0");
  1729. -    LPTSTR  pLocalName = NULL;
  1730. -    LPTSTR  pRemoteName = NULL;
  1731. +    int     i;
  1732. +    DWORD   result = NO_ERROR;
  1733. +    wchar_t szLocalName[] = L"C:\0";
  1734. +    LPWSTR  pLocalName = NULL;
  1735. +    LPWSTR  pRemoteName = NULL;
  1736.      BOOL    bUnmount = FALSE;
  1737.      BOOL    bForceUnmount = FALSE;
  1738.      BOOL    bPersistent = FALSE;
  1739.      int     port_num = -1;
  1740.      MOUNT_OPTION_LIST Options;
  1741.  #define MAX_MNTOPTS 128
  1742. -    TCHAR   *mntopts[MAX_MNTOPTS] = { 0 };
  1743. -    size_t  num_mntopts = 0;
  1744. +    wchar_t *mntopts[MAX_MNTOPTS] = { 0 };
  1745. +    int     num_mntopts = 0;
  1746.  
  1747.      int crtsetdbgflags = 0;
  1748.      crtsetdbgflags |= _CRTDBG_ALLOC_MEM_DF;  /* use debug heap */
  1749. @@ -187,41 +187,36 @@ DWORD __cdecl _tmain(DWORD argc, LPTSTR argv[])
  1750.      /* parse command line */
  1751.      for (i = 1; i < argc; i++)
  1752.      {
  1753. -        if (argv[i][0] == TEXT('-'))
  1754. +        if (argv[i][0] == L'-')
  1755.          {
  1756. -            if (_tcscmp(argv[i], TEXT("-h")) == 0) /* help */
  1757. -            {
  1758. +            if (!wcscmp(argv[i], L"-h")) { /* help */
  1759.                  PrintUsage(argv[0]);
  1760.                  goto out;
  1761.              }
  1762. -            else if (_tcscmp(argv[i], TEXT("-d")) == 0) /* unmount */
  1763. -            {
  1764. +            else if (!wcscmp(argv[i], L"-d")) { /* unmount */
  1765.                  bUnmount = TRUE;
  1766.              }
  1767. -            else if (_tcscmp(argv[i], TEXT("-f")) == 0) /* force unmount */
  1768. -            {
  1769. +            else if (!wcscmp(argv[i], L"-f")) { /* force unmount */
  1770.                  bForceUnmount = TRUE;
  1771.              }
  1772. -            else if (_tcscmp(argv[i], TEXT("-p")) == 0) /* persistent */
  1773. -            {
  1774. +            else if (!wcscmp(argv[i], L"-p")) { /* persistent */
  1775.                  bPersistent = TRUE;
  1776.              }
  1777. -            else if (_tcscmp(argv[i], TEXT("-o")) == 0) /* mount option */
  1778. -            {
  1779. +            else if (!wcscmp(argv[i], L"-o")) { /* mount option */
  1780.                  ++i;
  1781.                  if (i >= argc)
  1782.                  {
  1783.                      result = ERROR_BAD_ARGUMENTS;
  1784. -                    _ftprintf(stderr, TEXT("Mount options missing ")
  1785. -                        TEXT("after '-o'.\n\n"));
  1786. +                    (void)fwprintf(stderr,
  1787. +                        L"Mount options missing after '-o'.\n\n");
  1788.                      PrintUsage(argv[0]);
  1789.                      goto out_free;
  1790.                  }
  1791.  
  1792.                  if (num_mntopts >= (MAX_MNTOPTS-1)) {
  1793.                      result = ERROR_BAD_ARGUMENTS;
  1794. -                    _ftprintf(stderr, TEXT("Too many -o ")
  1795. -                        TEXT("options.\n\n"));
  1796. +                    (void)fwprintf(stderr,
  1797. +                        L"Too many -o options.\n\n");
  1798.                      goto out_free;
  1799.                  }
  1800.  
  1801. @@ -275,7 +270,8 @@ opt_o_argv_i_again:
  1802.                      /* ... and convert them to a port number */
  1803.                      port_num = wcstol(digit_buff, NULL, 0);
  1804.                      if ((port_num < 1) || (port_num > 65535)) {
  1805. -                        (void)_ftprintf(stderr, TEXT("NFSv4 TCP port number out of range.\n"));
  1806. +                        (void)fwprintf(stderr,
  1807. +                            L"NFSv4 TCP port number out of range.\n");
  1808.                          result = ERROR_BAD_ARGUMENTS;
  1809.                          goto out;
  1810.                      }
  1811. @@ -293,59 +289,56 @@ opt_o_argv_i_again:
  1812.                      goto opt_o_argv_i_again;
  1813.                  }
  1814.              }
  1815. -            else if (_tcscmp(argv[i], TEXT("-r")) == 0) /* mount option */
  1816. -            {
  1817. +            else if (!wcscmp(argv[i], L"-r")) { /* mount option */
  1818.                  if (num_mntopts >= (MAX_MNTOPTS-1)) {
  1819.                      result = ERROR_BAD_ARGUMENTS;
  1820. -                    (void)_ftprintf(stderr, TEXT("Too many options.\n\n"));
  1821. +                    (void)fwprintf(stderr, L"Too many options.\n\n");
  1822.                      goto out_free;
  1823.                  }
  1824.  
  1825. -                mntopts[num_mntopts++] = TEXT("ro");
  1826. +                mntopts[num_mntopts++] = L"ro";
  1827.              }
  1828. -            else if (_tcscmp(argv[i], TEXT("-w")) == 0) /* mount option */
  1829. -            {
  1830. +            else if (!wcscmp(argv[i], L"-w")) { /* mount option */
  1831.                  if (num_mntopts >= (MAX_MNTOPTS-1)) {
  1832.                      result = ERROR_BAD_ARGUMENTS;
  1833. -                    (void)_ftprintf(stderr, TEXT("Too many options.\n\n"));
  1834. +                    (void)fwprintf(stderr, L"Too many options.\n\n");
  1835.                      goto out_free;
  1836.                  }
  1837.  
  1838. -                mntopts[num_mntopts++] = TEXT("rw");
  1839. +                mntopts[num_mntopts++] = L"rw";
  1840.              }
  1841.             /*
  1842.              * Filesystem type, we use this for Solaris
  1843.              * $ mount(1M) -F nfs ... # and Linux
  1844.              * $ mount.nfs4 -t nfs ... # compatiblity
  1845.              */
  1846. -            else if ((_tcscmp(argv[i], TEXT("-F")) == 0) ||
  1847. -                    (_tcscmp(argv[i], TEXT("-t")) == 0))
  1848. +            else if ((!wcscmp(argv[i], L"-F")) ||
  1849. +                    (!wcscmp(argv[i], L"-t")))
  1850.              {
  1851.                  ++i;
  1852.                  if (i >= argc)
  1853.                  {
  1854.                      result = ERROR_BAD_ARGUMENTS;
  1855. -                    _ftprintf(stderr, TEXT("Filesystem type missing ")
  1856. -                        TEXT("after '-t'/'-F'.\n\n"));
  1857. +                    (void)fwprintf(stderr, L"Filesystem type missing "
  1858. +                        L"after '-t'/'-F'.\n\n");
  1859.                      PrintUsage(argv[0]);
  1860.                      goto out_free;
  1861.                  }
  1862.  
  1863. -                if (_tcscmp(argv[i], TEXT("nfs")) != 0)
  1864. -                {
  1865. +                if (!wcscmp(argv[i], L"nfs")) {
  1866.                      result = ERROR_BAD_ARGUMENTS;
  1867. -                    _ftprintf(stderr, TEXT("Filesystem type '%s' ")
  1868. -                        TEXT("not supported.\n\n"), argv[i]);
  1869. +                    (void)fwprintf(stderr, L"Filesystem type '%s' "
  1870. +                        L"not supported.\n\n", argv[i]);
  1871.                      PrintUsage(argv[0]);
  1872.                      goto out_free;
  1873.                  }
  1874.              }
  1875.              else
  1876. -                _ftprintf(stderr, TEXT("Unrecognized option ")
  1877. -                    TEXT("'%s', disregarding.\n"), argv[i]);
  1878. +                (void)fwprintf(stderr, L"Unrecognized option "
  1879. +                    L"'%s', disregarding.\n",
  1880. +                    argv[i]);
  1881.          }
  1882. -        else if (_tcscmp(argv[i], TEXT("/?")) == 0)
  1883. -       {
  1884. +        else if (!wcscmp(argv[i], L"/?")) {
  1885.             /* Windows-style "nfs_mount /?" help */
  1886.              PrintUsage(argv[0]);
  1887.              goto out;
  1888. @@ -359,23 +352,25 @@ opt_o_argv_i_again:
  1889.              pRemoteName = argv[i];
  1890.          }
  1891.          else
  1892. -            _ftprintf(stderr, TEXT("Unrecognized argument ")
  1893. -                TEXT("'%s', disregarding.\n"), argv[i]);
  1894. +            (void)fwprintf(stderr, L"Unrecognized argument "
  1895. +                L"'%s', disregarding.\n",
  1896. +                argv[i]);
  1897.      }
  1898.  
  1899.      /* validate local drive letter */
  1900.      if (pLocalName == NULL)
  1901.      {
  1902.          result = ERROR_BAD_ARGUMENTS;
  1903. -        _ftprintf(stderr, TEXT("Missing argument for drive letter.\n\n"));
  1904. +        (void)fwprintf(stderr, L"Missing argument for drive letter.\n\n");
  1905.          PrintUsage(argv[0]);
  1906.          goto out_free;
  1907.      }
  1908.      if (FALSE == ParseDriveLetter(pLocalName, szLocalName))
  1909.      {
  1910.          result = ERROR_BAD_ARGUMENTS;
  1911. -        _ftprintf(stderr, TEXT("Invalid drive letter '%s'. ")
  1912. -            TEXT("Expected 'C' or 'C:'.\n\n"), pLocalName);
  1913. +        (void)fwprintf(stderr, L"Invalid drive letter '%s'. "
  1914. +            L"Expected 'C' or 'C:'.\n\n",
  1915. +            pLocalName);
  1916.          PrintUsage(argv[0]);
  1917.          goto out_free;
  1918.      }
  1919. @@ -388,15 +383,15 @@ opt_o_argv_i_again:
  1920.      }
  1921.      else /* mount */
  1922.      {
  1923. -        TCHAR szRemoteName[NFS41_SYS_MAX_PATH_LEN];
  1924. -        TCHAR szParsedRemoteName[NFS41_SYS_MAX_PATH_LEN];
  1925. +        wchar_t szRemoteName[NFS41_SYS_MAX_PATH_LEN];
  1926. +        wchar_t szParsedRemoteName[NFS41_SYS_MAX_PATH_LEN];
  1927.  
  1928. -        *szRemoteName = TEXT('\0');
  1929. +        *szRemoteName = L'\0';
  1930.  
  1931.          if (pRemoteName == NULL)
  1932.          {
  1933.              result = ERROR_BAD_NET_NAME;
  1934. -            _ftprintf(stderr, TEXT("Missing argument for remote path.\n\n"));
  1935. +            (void)fwprintf(stderr, L"Missing argument for remote path.\n\n");
  1936.              PrintUsage(argv[0]);
  1937.              goto out_free;
  1938.          }
  1939. @@ -437,12 +432,12 @@ out:
  1940.  }
  1941.  
  1942.  static void ConvertUnixSlashes(
  1943. -    IN OUT LPTSTR pRemoteName)
  1944. +    IN OUT LPWSTR pRemoteName)
  1945.  {
  1946. -    LPTSTR pos = pRemoteName;
  1947. +    LPWSTR pos = pRemoteName;
  1948.      for (pos = pRemoteName; *pos; pos++)
  1949. -        if (*pos == TEXT('/'))
  1950. -            *pos = TEXT('\\');
  1951. +        if (*pos == L'/')
  1952. +            *pos = L'\\';
  1953.  }
  1954.  
  1955.  
  1956. @@ -489,14 +484,14 @@ wchar_t *utf8str2wcs(const char *utf8str)
  1957.  static DWORD ParseRemoteName(
  1958.      IN bool use_nfspubfh,
  1959.      IN int override_portnum,
  1960. -    IN LPTSTR pRemoteName,
  1961. +    IN LPWSTR pRemoteName,
  1962.      IN OUT PMOUNT_OPTION_LIST pOptions,
  1963. -    OUT LPTSTR pParsedRemoteName,
  1964. -    OUT LPTSTR pConnectionName,
  1965. +    OUT LPWSTR pParsedRemoteName,
  1966. +    OUT LPWSTR pConnectionName,
  1967.      IN size_t cchConnectionLen)
  1968.  {
  1969.      DWORD result = NO_ERROR;
  1970. -    LPTSTR pEnd;
  1971. +    LPWSTR pEnd;
  1972.      wchar_t *mountstrmem = NULL;
  1973.      int port = MOUNT_CONFIG_NFS_PORT_DEFAULT;
  1974.      wchar_t remotename[NFS41_SYS_MAX_PATH_LEN];
  1975. @@ -513,7 +508,7 @@ static DWORD ParseRemoteName(
  1976.       * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
  1977.       * including port support (nfs://hostname@port/path/...)
  1978.       */
  1979. -    if (!wcsncmp(premotename, TEXT("nfs://"), 6)) {
  1980. +    if (!wcsncmp(premotename, L"nfs://", 6)) {
  1981.          char *premotename_utf8;
  1982.          wchar_t *hostname_wstr;
  1983.  
  1984. @@ -542,13 +537,14 @@ static DWORD ParseRemoteName(
  1985.  
  1986.          if (url_parser_parse(uctx) < 0) {
  1987.              result = ERROR_BAD_ARGUMENTS;
  1988. -            (void)_ftprintf(stderr, TEXT("Error parsing nfs://-URL.\n"));
  1989. +            (void)fwprintf(stderr, L"Error parsing nfs://-URL.\n");
  1990.              goto out;
  1991.          }
  1992.  
  1993.          if (uctx->login.username || uctx->login.passwd) {
  1994.              result = ERROR_BAD_ARGUMENTS;
  1995. -            (void)_ftprintf(stderr, TEXT("Username/Password are not defined for nfs://-URL.\n"));
  1996. +            (void)fwprintf(stderr,
  1997. +                L"Username/Password are not defined for nfs://-URL.\n");
  1998.              goto out;
  1999.          }
  2000.  
  2001. @@ -572,40 +568,41 @@ static DWORD ParseRemoteName(
  2002.  
  2003.                  if (!strcmp(pname, "rw")) {
  2004.                      if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
  2005. -                        (void)InsertOption(TEXT("rw"), TEXT("1"), pOptions);
  2006. +                        (void)InsertOption(L"rw", L"1", pOptions);
  2007.                      }
  2008.                      else if (!strcmp(pvalue, "0")) {
  2009. -                        (void)InsertOption(TEXT("ro"), TEXT("1"), pOptions);
  2010. +                        (void)InsertOption(L"ro", L"1", pOptions);
  2011.                      }
  2012.                      else {
  2013.                          result = ERROR_BAD_ARGUMENTS;
  2014. -                        (void)_ftprintf(stderr,
  2015. -                            TEXT("Unsupported nfs://-URL parameter ")
  2016. -                            TEXT("'%S' value '%S'.\n"),
  2017. +                        (void)fwprintf(stderr,
  2018. +                            L"Unsupported nfs://-URL parameter "
  2019. +                            L"'%S' value '%S'.\n",
  2020.                              pname, pvalue);
  2021.                          goto out;
  2022.                      }
  2023.                  }
  2024.                  else if (!strcmp(pname, "ro")) {
  2025.                      if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
  2026. -                        (void)InsertOption(TEXT("ro"), TEXT("1"), pOptions);
  2027. +                        (void)InsertOption(L"ro", L"1", pOptions);
  2028.                      }
  2029.                      else if (!strcmp(pvalue, "0")) {
  2030. -                        (void)InsertOption(TEXT("rw"), TEXT("1"), pOptions);
  2031. +                        (void)InsertOption(L"rw", L"1", pOptions);
  2032.                      }
  2033.                      else {
  2034.                          result = ERROR_BAD_ARGUMENTS;
  2035. -                        (void)_ftprintf(stderr,
  2036. -                            TEXT("Unsupported nfs://-URL parameter ")
  2037. -                            TEXT("'%S' value '%S'.\n"),
  2038. +                        (void)fwprintf(stderr,
  2039. +                            L"Unsupported nfs://-URL parameter "
  2040. +                            L"'%S' value '%S'.\n",
  2041.                              pname, pvalue);
  2042.                          goto out;
  2043.                      }
  2044.                  }
  2045.                  else {
  2046.                      result = ERROR_BAD_ARGUMENTS;
  2047. -                    (void)_ftprintf(stderr,
  2048. -                        TEXT("Unsupported nfs://-URL parameter '%S'.\n"), pname);
  2049. +                    (void)fwprintf(stderr,
  2050. +                        L"Unsupported nfs://-URL parameter '%S'.\n",
  2051. +                        pname);
  2052.                      goto out;
  2053.                  }
  2054.              }
  2055. @@ -625,13 +622,13 @@ static DWORD ParseRemoteName(
  2056.  
  2057.          if (!uctx->path) {
  2058.              result = ERROR_BAD_ARGUMENTS;
  2059. -            (void)_ftprintf(stderr, TEXT("Path missing in nfs://-URL\n"));
  2060. +            (void)fwprintf(stderr, L"Path missing in nfs://-URL\n");
  2061.              goto out;
  2062.          }
  2063.  
  2064.          if (uctx->path[0] != '/') {
  2065.              result = ERROR_BAD_ARGUMENTS;
  2066. -            (void)_ftprintf(stderr, TEXT("Relative nfs://-URLs are not supported\n"));
  2067. +            (void)fwprintf(stderr, L"Relative nfs://-URLs are not supported\n");
  2068.              goto out;
  2069.          }
  2070.  
  2071. @@ -651,23 +648,23 @@ static DWORD ParseRemoteName(
  2072.           * users, but we explicitly allow the nfs://-URLs to have a
  2073.           * port number, and -o port=<num> to override that.
  2074.           */
  2075. -        if (_tcsrchr(premotename, TEXT('@'))) {
  2076. -            (void)_ftprintf(stderr,
  2077. -                TEXT("Remote path should not contain '@', ")
  2078. -                TEXT("use -o port=tcpportnum.\n"));
  2079. +        if (wcsrchr(premotename, L'@')) {
  2080. +            (void)fwprintf(stderr,
  2081. +                L"Remote path should not contain '@', "
  2082. +                L"use -o port=tcpportnum.\n");
  2083.              result = ERROR_BAD_ARGUMENTS;
  2084.              goto out;
  2085.          }
  2086.  
  2087.          /* fail if the server name doesn't end with :\ */
  2088. -        pEnd = _tcsrchr(premotename, TEXT(':'));
  2089. -        if (pEnd == NULL || pEnd[1] != TEXT('\\')) {
  2090. -            (void)_ftprintf(stderr, TEXT("Failed to parse the remote path. ")
  2091. -                TEXT("Expected 'hostname:\\path'.\n"));
  2092. +        pEnd = wcsrchr(premotename, L':');
  2093. +        if (pEnd == NULL || pEnd[1] != L'\\') {
  2094. +            (void)fwprintf(stderr, L"Failed to parse the remote path. "
  2095. +                L"Expected 'hostname:\\path'.\n");
  2096.              result = ERROR_BAD_ARGUMENTS;
  2097.              goto out;
  2098.          }
  2099. -        *pEnd++ = TEXT('\0');
  2100. +        *pEnd++ = L'\0';
  2101.      }
  2102.  
  2103.      /*
  2104. @@ -693,31 +690,31 @@ static DWORD ParseRemoteName(
  2105.       * See https://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_UNC_path_names
  2106.       * for details
  2107.       */
  2108. -    if (premotename[0] == TEXT('[')) {
  2109. +    if (premotename[0] == L'[') {
  2110.          size_t len = wcslen(premotename);
  2111.          size_t i;
  2112.          wchar_t c;
  2113.  
  2114.          /* Check for minimum length and trailing ']' */
  2115. -        if ((len < 4) || (premotename[len-1] != TEXT(']'))) {
  2116. -            _ftprintf(stderr, TEXT("Failed to parse raw IPv6 address,")
  2117. -               TEXT(" trailing ']' is missing, ")
  2118. -               TEXT("or address string too short.\n"));
  2119. +        if ((len < 4) || (premotename[len-1] != L']')) {
  2120. +            fwprintf(stderr, L"Failed to parse raw IPv6 address,"
  2121. +               L" trailing ']' is missing, "
  2122. +               L"or address string too short.\n");
  2123.              result = ERROR_BAD_ARGUMENTS;
  2124.              goto out;
  2125.         }
  2126.  
  2127.          /* Skip '[', stomp ']' */
  2128. -        premotename[len-1] = TEXT('\0');
  2129. +        premotename[len-1] = L'\0';
  2130.          premotename++;
  2131.          len -= 2;
  2132.  
  2133.          /* Check whether this is a valid IPv6 address */
  2134.          for (i=0 ; i < len ; i++) {
  2135.              c = premotename[i];
  2136. -            if (!(iswxdigit(c) || (c == TEXT(':')))) {
  2137. -                _ftprintf(stderr, TEXT("Failed to parse raw IPv6 ")
  2138. -                   TEXT("address, illegal character '%c' found.\n"),
  2139. +            if (!(iswxdigit(c) || (c == L':'))) {
  2140. +                fwprintf(stderr, L"Failed to parse raw IPv6 "
  2141. +                   L"address, illegal character '%c' found.\n",
  2142.                     c);
  2143.                  result = ERROR_BAD_ARGUMENTS;
  2144.                  goto out;
  2145. @@ -726,11 +723,11 @@ static DWORD ParseRemoteName(
  2146.  
  2147.         for (i = 0 ; i < len ; i++) {
  2148.             /* IPv6 separator */
  2149. -            if (premotename[i] == TEXT(':'))
  2150. -                premotename[i] = TEXT('-');
  2151. +            if (premotename[i] == L':')
  2152. +                premotename[i] = L'-';
  2153.             /* zone index */
  2154. -           else if (premotename[i] == TEXT('%'))
  2155. -                premotename[i] = TEXT('s');
  2156. +           else if (premotename[i] == L'%')
  2157. +                premotename[i] = L's';
  2158.          }
  2159.  
  2160.          /*
  2161. @@ -739,11 +736,11 @@ static DWORD ParseRemoteName(
  2162.          *   too
  2163.          */
  2164.          (void)swprintf(srvname, SRVNAME_LEN,
  2165. -           TEXT("%s.ipv6-literal.net@%d"), premotename, port);
  2166. +           L"%s.ipv6-literal.net@%d", premotename, port);
  2167.      }
  2168.      else {
  2169.          /* ALWAYS add port number to hostname, so UNC paths use it too */
  2170. -        (void)swprintf(srvname, SRVNAME_LEN, TEXT("%s@%d"),
  2171. +        (void)swprintf(srvname, SRVNAME_LEN, L"%s@%d",
  2172.             premotename, port);
  2173.      }
  2174.  
  2175. @@ -751,27 +748,27 @@ static DWORD ParseRemoteName(
  2176.       * Safeguard against ':' in UNC paths, e.g if we pass raw IPv6
  2177.       * address without ':', or just random garbage
  2178.       */
  2179. -    if (wcschr(srvname, TEXT(':'))) {
  2180. -        _ftprintf(stderr,
  2181. -           TEXT("Illegal ':' character hostname '%s'.\n"), srvname);
  2182. +    if (wcschr(srvname, L':')) {
  2183. +        fwprintf(stderr,
  2184. +           L"Illegal ':' character hostname '%s'.\n", srvname);
  2185.          result = ERROR_BAD_ARGUMENTS;
  2186.          goto out;
  2187.      }
  2188.  
  2189.  #ifdef DEBUG_MOUNT
  2190. -    (void)_ftprintf(stderr,
  2191. -        TEXT("srvname='%s', mntpt='%s'\n"),
  2192. +    (void)fwprintf(stderr,
  2193. +        L"srvname='%s', mntpt='%s'\n",
  2194.          srvname,
  2195.          pEnd);
  2196.  #endif
  2197.  
  2198. -    if (!InsertOption(TEXT("srvname"), srvname, pOptions) ||
  2199. -        !InsertOption(TEXT("mntpt"), *pEnd ? pEnd : TEXT("\\"), pOptions)) {
  2200. +    if (!InsertOption(L"srvname", srvname, pOptions) ||
  2201. +        !InsertOption(L"mntpt", (*pEnd ? pEnd : L"\\"), pOptions)) {
  2202.          result = ERROR_BAD_ARGUMENTS;
  2203.          goto out;
  2204.      }
  2205.  
  2206. -    result = StringCchCopy(pConnectionName, cchConnectionLen, TEXT("\\\\"));
  2207. +    result = StringCchCopy(pConnectionName, cchConnectionLen, L"\\\\");
  2208.      if (FAILED(result))
  2209.          goto out;
  2210.      result = StringCbCat(pConnectionName, cchConnectionLen, srvname);
  2211. @@ -779,7 +776,7 @@ static DWORD ParseRemoteName(
  2212.          goto out;
  2213.  #ifdef NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX
  2214.      result = StringCbCat(pConnectionName, cchConnectionLen,
  2215. -        (use_nfspubfh?(TEXT("\\pubnfs4")):(TEXT("\\nfs4"))));
  2216. +        (use_nfspubfh?(L"\\pubnfs4"):(L"\\nfs4")));
  2217.      if (FAILED(result))
  2218.          goto out;
  2219.  #endif /* NFS41_DRIVER_MOUNT_DOES_NFS4_PREFIX */
  2220. @@ -789,8 +786,8 @@ static DWORD ParseRemoteName(
  2221.      result = StringCchCopy(pParsedRemoteName, cchConnectionLen, srvname);
  2222.  
  2223.  #ifdef DEBUG_MOUNT
  2224. -    (void)_ftprintf(stderr,
  2225. -        TEXT("pConnectionName='%s', pParsedRemoteName='%s', use_nfspubfh='%d'\n"),
  2226. +    (void)fwprintf(stderr,
  2227. +        L"pConnectionName='%s', pParsedRemoteName='%s', use_nfspubfh='%d'\n",
  2228.          pConnectionName,
  2229.          pParsedRemoteName,
  2230.          (int)use_nfspubfh);
  2231. @@ -807,26 +804,26 @@ out:
  2232.  }
  2233.  
  2234.  static DWORD DoMount(
  2235. -    IN LPTSTR pLocalName,
  2236. -    IN LPTSTR pRemoteName,
  2237. -    IN LPTSTR pParsedRemoteName,
  2238. +    IN LPWSTR pLocalName,
  2239. +    IN LPWSTR pRemoteName,
  2240. +    IN LPWSTR pParsedRemoteName,
  2241.      IN BOOL bPersistent,
  2242.      IN PMOUNT_OPTION_LIST pOptions)
  2243.  {
  2244.      DWORD result = NO_ERROR;
  2245. -    TCHAR szExisting[NFS41_SYS_MAX_PATH_LEN];
  2246. +    wchar_t szExisting[NFS41_SYS_MAX_PATH_LEN];
  2247.      DWORD dwLength;
  2248.      NETRESOURCE NetResource;
  2249.  
  2250.      if (pOptions->Buffer->Length) {
  2251.          if (pOptions->Current)
  2252.              pOptions->Current->NextEntryOffset = 0;
  2253. -        NetResource.lpComment = (LPTSTR)&pOptions->Buffer[0];
  2254. +        NetResource.lpComment = (LPWSTR)&pOptions->Buffer[0];
  2255.      }
  2256.  
  2257.  #ifdef DEBUG_MOUNT
  2258. -    (void)_ftprintf(stderr,
  2259. -        TEXT("DoMount(pLocalName='%s', pRemoteName='%s', pParsedRemoteName='%s')\n"),
  2260. +    (void)fwprintf(stderr,
  2261. +        L"DoMount(pLocalName='%s', pRemoteName='%s', pParsedRemoteName='%s')\n",
  2262.          pLocalName,
  2263.          pRemoteName,
  2264.          pParsedRemoteName);
  2265. @@ -835,29 +832,29 @@ static DWORD DoMount(
  2266.  
  2267.      /* fail if the connection already exists */
  2268.      dwLength = NFS41_SYS_MAX_PATH_LEN;
  2269. -    result = WNetGetConnection(pLocalName, (LPTSTR)szExisting, &dwLength);
  2270. +    result = WNetGetConnection(pLocalName, (LPWSTR)szExisting, &dwLength);
  2271.      if (result == NO_ERROR)
  2272.      {
  2273.          result = ERROR_ALREADY_ASSIGNED;
  2274. -        _ftprintf(stderr, TEXT("Mount failed, drive %s is ")
  2275. -            TEXT("already assigned to '%s'.\n"),
  2276. +        (void)fwprintf(stderr, L"Mount failed, drive %s is "
  2277. +            L"already assigned to '%s'.\n",
  2278.              pLocalName, szExisting);
  2279.      }
  2280.      else
  2281.      {
  2282. -        TCHAR szConnection[NFS41_SYS_MAX_PATH_LEN];
  2283. +        wchar_t szConnection[NFS41_SYS_MAX_PATH_LEN];
  2284.          DWORD ConnectSize = NFS41_SYS_MAX_PATH_LEN, ConnectResult, Flags = 0;
  2285.  
  2286.          ZeroMemory(&NetResource, sizeof(NETRESOURCE));
  2287.          NetResource.dwType = RESOURCETYPE_DISK;
  2288.          /* drive letter is chosen automatically if lpLocalName == NULL */
  2289. -        NetResource.lpLocalName = *pLocalName == TEXT('*') ? NULL : pLocalName;
  2290. +        NetResource.lpLocalName = *pLocalName == L'*' ? NULL : pLocalName;
  2291.          NetResource.lpRemoteName = pRemoteName;
  2292.          /* ignore other network providers */
  2293. -        NetResource.lpProvider = TEXT(NFS41_PROVIDER_NAME_A);
  2294. +        NetResource.lpProvider = NFS41_PROVIDER_NAME_U;
  2295.          /* pass mount options via lpComment */
  2296.          if (pOptions->Buffer->Length) {
  2297. -            NetResource.lpComment = (LPTSTR)pOptions->Buffer;
  2298. +            NetResource.lpComment = (LPWSTR)pOptions->Buffer;
  2299.          }
  2300.  
  2301.          if (bPersistent)
  2302. @@ -868,11 +865,11 @@ static DWORD DoMount(
  2303.              szConnection, &ConnectSize, &ConnectResult);
  2304.  
  2305.          if (result == NO_ERROR)
  2306. -            _tprintf(TEXT("Successfully mounted '%s' to drive '%s'\n"),
  2307. +            (void)wprintf(L"Successfully mounted '%s' to drive '%s'\n",
  2308.                  pParsedRemoteName, szConnection);
  2309.          else
  2310. -            _ftprintf(stderr, TEXT("WNetUseConnection(%s, %s) ")
  2311. -                TEXT("failed with error code %u.\n"),
  2312. +            (void)fwprintf(stderr, L"WNetUseConnection(%s, %s) "
  2313. +                L"failed with error code %u.\n",
  2314.                  pLocalName, pRemoteName, result);
  2315.      }
  2316.  
  2317. @@ -880,7 +877,7 @@ static DWORD DoMount(
  2318.  }
  2319.  
  2320.  static DWORD DoUnmount(
  2321. -    IN LPTSTR pLocalName,
  2322. +    IN LPWSTR pLocalName,
  2323.      IN BOOL bForce)
  2324.  {
  2325.      DWORD result;
  2326. @@ -891,35 +888,36 @@ static DWORD DoUnmount(
  2327.      switch (result)
  2328.      {
  2329.      case NO_ERROR:
  2330. -        _tprintf(TEXT("Drive %s unmounted successfully.\n"), pLocalName);
  2331. +        (void)wprintf(L"Drive %s unmounted successfully.\n",
  2332. +            pLocalName);
  2333.          break;
  2334.      case ERROR_NOT_CONNECTED:
  2335. -        _ftprintf(stderr, TEXT("Drive %s is not currently ")
  2336. -            TEXT("connected.\n"), pLocalName);
  2337. +        (void)fwprintf(stderr, L"Drive %s is not currently "
  2338. +            L"connected.\n", pLocalName);
  2339.          break;
  2340.      default:
  2341. -        _ftprintf(stderr, TEXT("WNetCancelConnection2(%s) failed ")
  2342. -            TEXT("with error code %u.\n"), pLocalName, result);
  2343. +        (void)fwprintf(stderr, L"WNetCancelConnection2(%s) failed "
  2344. +            L"with error code %u.\n", pLocalName, result);
  2345.          break;
  2346.      }
  2347.      return result;
  2348.  }
  2349.  
  2350.  static BOOL ParseDriveLetter(
  2351. -    IN LPTSTR pArg,
  2352. +    IN LPWSTR pArg,
  2353.      OUT PTCH pDriveLetter)
  2354.  {
  2355.      /* accept 'C' or 'C:' */
  2356. -    switch (_tcslen(pArg))
  2357. +    switch (wcslen(pArg))
  2358.      {
  2359.      case 2:
  2360. -        if (pArg[1] != TEXT(':'))
  2361. +        if (pArg[1] != L':')
  2362.              return FALSE;
  2363.          /* break intentionally missing */
  2364.      case 1:
  2365. -        if (_istlower(*pArg))
  2366. -            *pArg = (TCHAR)_totupper(*pArg);
  2367. -        else if (!_istupper(*pArg) && *pArg != TEXT('*'))
  2368. +        if (iswlower(*pArg))
  2369. +            *pArg = (wchar_t)towupper(*pArg);
  2370. +        else if (!iswupper(*pArg) && *pArg != L'*')
  2371.              return FALSE;
  2372.  
  2373.          *pDriveLetter = *pArg;
  2374. @@ -931,10 +929,10 @@ static BOOL ParseDriveLetter(
  2375.  void PrintErrorMessage(
  2376.      IN DWORD dwError)
  2377.  {
  2378. -    LPTSTR lpMsgBuf = NULL;
  2379. +    LPWSTR lpMsgBuf = NULL;
  2380.      FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  2381.          NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  2382. -        (LPTSTR)&lpMsgBuf, 0, NULL);
  2383. -    _fputts(lpMsgBuf, stderr);
  2384. +        (LPWSTR)&lpMsgBuf, 0, NULL);
  2385. +    (void)fputws(lpMsgBuf, stderr);
  2386.      LocalFree(lpMsgBuf);
  2387.  }
  2388. diff --git a/mount/options.c b/mount/options.c
  2389. index 73d92ce..eb2d84a 100644
  2390. --- a/mount/options.c
  2391. +++ b/mount/options.c
  2392. @@ -3,6 +3,7 @@
  2393.   *
  2394.   * Olga Kornievskaia <aglo@umich.edu>
  2395.   * Casey Bodley <cbodley@umich.edu>
  2396. + * Roland Mainz <roland.mainz@nrubsig.org>
  2397.   *
  2398.   * This library is free software; you can redistribute it and/or modify it
  2399.   * under the terms of the GNU Lesser General Public License as published by
  2400. @@ -21,7 +22,6 @@
  2401.  
  2402.  #include <crtdbg.h>
  2403.  #include <Windows.h>
  2404. -#include <tchar.h>
  2405.  #include <strsafe.h>
  2406.  #include <stdio.h>
  2407.  
  2408. @@ -55,19 +55,18 @@ void FreeMountOptions(
  2409.  }
  2410.  
  2411.  BOOL FindOptionByName(
  2412. -    IN LPCTSTR Name,
  2413. +    IN LPCWSTR Name,
  2414.      IN PMOUNT_OPTION_LIST Options,
  2415.      OUT PFILE_FULL_EA_INFORMATION* ppOption)
  2416.  {
  2417.      PFILE_FULL_EA_INFORMATION Current =
  2418.          (PFILE_FULL_EA_INFORMATION)Options->Buffer->Buffer;
  2419. -    ULONG NameLength = (ULONG)_tcslen(Name) * sizeof(TCHAR);
  2420. +    ULONG NameLength = (ULONG)wcslen(Name) * sizeof(wchar_t);
  2421.  
  2422.      for (;;)
  2423.      {
  2424. -        if (Current->EaNameLength == NameLength &&
  2425. -            _tcscmp((LPTSTR)Current->EaName, Name) == 0)
  2426. -        {
  2427. +        if ((Current->EaNameLength == NameLength) &&
  2428. +            (!wcscmp((LPTSTR)Current->EaName, Name))) {
  2429.              *ppOption = Current;
  2430.              return TRUE;
  2431.          }
  2432. @@ -84,7 +83,7 @@ static FORCEINLINE ULONG EaBufferSize(
  2433.      IN USHORT ValueSize)
  2434.  {
  2435.      ULONG Size = sizeof(ULONG) + 2 * sizeof(UCHAR) + sizeof(USHORT)
  2436. -        + NameSize + ValueSize + sizeof(TCHAR);
  2437. +        + NameSize + ValueSize + sizeof(wchar_t);
  2438.      /* extended attributes require ULONG alignment;
  2439.       * see documentation for IoCheckEaBufferValidity() */
  2440.      return ( (Size + (sizeof(ULONG)-1)) / sizeof(ULONG) ) * sizeof(ULONG);
  2441. @@ -99,20 +98,20 @@ static FORCEINLINE ULONG EaBufferNextOffset(
  2442.  }
  2443.  
  2444.  BOOL InsertOption(
  2445. -    IN LPCTSTR Name,
  2446. -    IN LPCTSTR Value,
  2447. +    IN LPCWSTR Name,
  2448. +    IN LPCWSTR Value,
  2449.      IN OUT PMOUNT_OPTION_LIST Options)
  2450.  {
  2451.      PFILE_FULL_EA_INFORMATION Current;
  2452. -    UCHAR NameLen = (UCHAR)_tcslen(Name) * sizeof(TCHAR);
  2453. -    USHORT ValueLen = (USHORT)_tcslen(Value) * sizeof(TCHAR);
  2454. +    UCHAR NameLen = (UCHAR)wcslen(Name) * sizeof(wchar_t);
  2455. +    USHORT ValueLen = (USHORT)wcslen(Value) * sizeof(wchar_t);
  2456.      ULONG SpaceRequired = EaBufferSize(NameLen, ValueLen);
  2457.  
  2458.      /*
  2459.       * Filter "port" option, as it's value has already been encoded
  2460.       *  in the hostname as hostport
  2461.       */
  2462. -    if (!_tcscmp(Name, L"port")) {
  2463. +    if (!wcscmp(Name, L"port")) {
  2464.          return TRUE;
  2465.      }
  2466.  
  2467. @@ -123,19 +122,19 @@ BOOL InsertOption(
  2468.  #if 0
  2469.      /* don't allow duplicate options */
  2470.      if (FindOptionByName(Name, Options, &Current)) {
  2471. -        _ftprintf(stderr, TEXT("Found a duplicate option ")
  2472. -            TEXT("'%s%s%s' while parsing '%s%s%s'.\n"),
  2473. +        (void)fwprintf(stderr, L"Found a duplicate option "
  2474. +            L"'%s%s%s' while parsing '%s%s%s'.\n",
  2475.              (PTCH)Current->EaName,
  2476. -            Current->EaValueLength ? TEXT("=") : TEXT(""),
  2477. -            (PTCH)(Current->EaName + Current->EaNameLength + sizeof(TCHAR)),
  2478. -            Name, ValueLen ? TEXT("=") : Value, Value);
  2479. +            Current->EaValueLength ? L"=" : L"",
  2480. +            (PTCH)(Current->EaName + Current->EaNameLength + sizeof(wchar_t)),
  2481. +            Name, ValueLen ? L"=" : Value, Value);
  2482.          return FALSE;
  2483.      }
  2484.  #endif
  2485.  
  2486.      /* fail if we're out of space */
  2487.      if (SpaceRequired > Options->Remaining) {
  2488. -        _ftprintf(stderr, TEXT("Out of space for options!\n"));
  2489. +        (void)fwprintf(stderr, L"Out of space for options!\n");
  2490.          return FALSE;
  2491.      }
  2492.  
  2493. @@ -149,18 +148,18 @@ BOOL InsertOption(
  2494.      Current->EaNameLength = NameLen;
  2495.      if (NameLen) /* copy attribute name */
  2496.          StringCbCopy((LPTSTR)Current->EaName,
  2497. -            NameLen + sizeof(TCHAR), Name);
  2498. +            NameLen + sizeof(wchar_t), Name);
  2499.  
  2500.      Current->EaValueLength = ValueLen;
  2501.      if (ValueLen) /* copy attribute value */
  2502. -        StringCbCopy((LPTSTR)(Current->EaName + NameLen + sizeof(TCHAR)),
  2503. -            ValueLen + sizeof(TCHAR), Value);
  2504. +        StringCbCopy((LPTSTR)(Current->EaName + NameLen + sizeof(wchar_t)),
  2505. +            ValueLen + sizeof(wchar_t), Value);
  2506.  
  2507.      Current->Flags = 0;
  2508.      Current->NextEntryOffset = EaBufferNextOffset(Options->Current);
  2509.  
  2510.      Options->Buffer->Length = (ULONG)(
  2511. -        (Current->EaName + NameLen + ValueLen + 2 * sizeof(TCHAR))
  2512. +        (Current->EaName + NameLen + ValueLen + 2 * sizeof(wchar_t))
  2513.              - Options->Buffer->Buffer );
  2514.      Options->Remaining -= SpaceRequired;
  2515.      return TRUE;
  2516. @@ -169,30 +168,30 @@ BOOL InsertOption(
  2517.  void RecursivePrintEaInformation(
  2518.      IN PFILE_FULL_EA_INFORMATION EA)
  2519.  {
  2520. -    _tprintf(
  2521. -        TEXT("----------------------\n")
  2522. -        TEXT("Alignment:           %5lu\n")
  2523. -        TEXT("NextEntryOffset:     %5lu\n")
  2524. -        TEXT("Flags:               %5u\n")
  2525. -        TEXT("EaNameLength:        %5u\n")
  2526. -        TEXT("EaValueLength:       %5u\n")
  2527. -        TEXT("EaName:   %16ls\n")
  2528. -        TEXT("EaValue:  %16ls\n\n"),
  2529. +    (void)wprintf(
  2530. +        L"----------------------\n"
  2531. +        L"Alignment:           %5lu\n"
  2532. +        L"NextEntryOffset:     %5lu\n"
  2533. +        L"Flags:               %5u\n"
  2534. +        L"EaNameLength:        %5u\n"
  2535. +        L"EaValueLength:       %5u\n"
  2536. +        L"EaName:   %16ls\n"
  2537. +        L"EaValue:  %16ls\n\n",
  2538.          (unsigned long)((ULONG_PTR)EA % sizeof(ULONG)),
  2539.          EA->NextEntryOffset,
  2540.          EA->Flags,
  2541.          EA->EaNameLength,
  2542.          EA->EaValueLength,
  2543.          (LPTSTR)EA->EaName,
  2544. -        (LPTSTR)(EA->EaName + EA->EaNameLength + sizeof(TCHAR)));
  2545. +        (LPTSTR)(EA->EaName + EA->EaNameLength + sizeof(wchar_t)));
  2546.  
  2547.      if (EA->NextEntryOffset)
  2548.          RecursivePrintEaInformation((PFILE_FULL_EA_INFORMATION)
  2549.              ((PBYTE)EA + EA->NextEntryOffset));
  2550.  }
  2551.  
  2552. -static const TCHAR COMMA_T = TEXT(',');
  2553. -static const TCHAR EQUAL_T = TEXT('=');
  2554. +static const wchar_t COMMA_T = L',';
  2555. +static const wchar_t EQUAL_T = L'=';
  2556.  
  2557.  BOOL ParseMountOptions(
  2558.      IN LPTSTR Arg,
  2559. @@ -203,18 +202,18 @@ BOOL ParseMountOptions(
  2560.      pos = Arg;
  2561.      for (;;)
  2562.      {
  2563. -        comma = _tcschr(pos, COMMA_T);
  2564. +        comma = wcschr(pos, COMMA_T);
  2565.          if (comma)
  2566.          {
  2567.              if (comma == pos)
  2568.                  goto out_empty_option;
  2569.              *comma = 0;
  2570.          }
  2571. -        else if (_tcslen(pos) == 0)
  2572. +        else if (wcslen(pos) == 0)
  2573.              goto out_empty_option;
  2574.  
  2575.          /* accept 'option=value' or 'option' */
  2576. -        equals = _tcschr(pos, EQUAL_T);
  2577. +        equals = wcschr(pos, EQUAL_T);
  2578.          if (equals)
  2579.          {
  2580.              if (equals == pos)
  2581. @@ -223,7 +222,7 @@ BOOL ParseMountOptions(
  2582.              if (!InsertOption(pos, equals + 1, Options))
  2583.                  return FALSE;
  2584.          }
  2585. -        else if (!InsertOption(pos, TEXT(""), Options))
  2586. +        else if (!InsertOption(pos, L"", Options))
  2587.              return FALSE;
  2588.  
  2589.          if (comma == NULL)
  2590. @@ -237,7 +236,8 @@ BOOL ParseMountOptions(
  2591.      return TRUE;
  2592.  
  2593.  out_empty_option:
  2594. -    _ftprintf(stderr, TEXT("Found an empty option while ")
  2595. -        TEXT("reading mount options at '%s'.\n"), pos);
  2596. +    (void)fwprintf(stderr, L"Found an empty option while "
  2597. +        L"reading mount options at '%s'.\n",
  2598. +        pos);
  2599.      return FALSE;
  2600.  }
  2601. diff --git a/sys/nfs41_driver.h b/sys/nfs41_driver.h
  2602. index 01e34e2..6f62300 100644
  2603. --- a/sys/nfs41_driver.h
  2604. +++ b/sys/nfs41_driver.h
  2605. @@ -26,7 +26,6 @@
  2606.  #define NFS41_SHADOW_DEVICE_NAME L"\\??\\nfs41_driver"
  2607.  #define NFS41_USER_DEVICE_NAME L"\\\\.\\nfs41_driver"
  2608.  #define NFS41_USER_DEVICE_NAME_A "\\\\.\\nfs41_driver"
  2609. -#define NFS41_PROVIDER_NAME_A "NFS41 Network"
  2610.  #define NFS41_PROVIDER_NAME_U L"NFS41 Network"
  2611.  
  2612.  #define NFS41_PIPE_NAME L"\\Device\\nfs41_pipe"
  2613. --
  2614. 2.45.1
  2615.  
  2616. From 8566e5ef231b73945ac77450a8bedd93f6d56f6d Mon Sep 17 00:00:00 2001
  2617. From: Roland Mainz <roland.mainz@nrubsig.org>
  2618. Date: Mon, 15 Jul 2024 15:43:27 +0200
  2619. Subject: [PATCH 08/11] mount: Put single-quotes around '%s' in output
  2620.  
  2621. Put single-quotes around '%s' in output.
  2622.  
  2623. Reported-by: Josh Hurst <joshhurst@gmail.com>
  2624. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2625. ---
  2626. mount/mount.c | 10 +++++-----
  2627.  1 file changed, 5 insertions(+), 5 deletions(-)
  2628.  
  2629. diff --git a/mount/mount.c b/mount/mount.c
  2630. index d4a6680..a649641 100644
  2631. --- a/mount/mount.c
  2632. +++ b/mount/mount.c
  2633. @@ -836,7 +836,7 @@ static DWORD DoMount(
  2634.      if (result == NO_ERROR)
  2635.      {
  2636.          result = ERROR_ALREADY_ASSIGNED;
  2637. -        (void)fwprintf(stderr, L"Mount failed, drive %s is "
  2638. +        (void)fwprintf(stderr, L"Mount failed, drive '%s' is "
  2639.              L"already assigned to '%s'.\n",
  2640.              pLocalName, szExisting);
  2641.      }
  2642. @@ -868,7 +868,7 @@ static DWORD DoMount(
  2643.              (void)wprintf(L"Successfully mounted '%s' to drive '%s'\n",
  2644.                  pParsedRemoteName, szConnection);
  2645.          else
  2646. -            (void)fwprintf(stderr, L"WNetUseConnection(%s, %s) "
  2647. +            (void)fwprintf(stderr, L"WNetUseConnection('%s', '%s') "
  2648.                  L"failed with error code %u.\n",
  2649.                  pLocalName, pRemoteName, result);
  2650.      }
  2651. @@ -888,15 +888,15 @@ static DWORD DoUnmount(
  2652.      switch (result)
  2653.      {
  2654.      case NO_ERROR:
  2655. -        (void)wprintf(L"Drive %s unmounted successfully.\n",
  2656. +        (void)wprintf(L"Drive '%s' unmounted successfully.\n",
  2657.              pLocalName);
  2658.          break;
  2659.      case ERROR_NOT_CONNECTED:
  2660. -        (void)fwprintf(stderr, L"Drive %s is not currently "
  2661. +        (void)fwprintf(stderr, L"Drive '%s' is not currently "
  2662.              L"connected.\n", pLocalName);
  2663.          break;
  2664.      default:
  2665. -        (void)fwprintf(stderr, L"WNetCancelConnection2(%s) failed "
  2666. +        (void)fwprintf(stderr, L"WNetCancelConnection2('%s') failed "
  2667.              L"with error code %u.\n", pLocalName, result);
  2668.          break;
  2669.      }
  2670. --
  2671. 2.45.1
  2672.  
  2673. From 830f5a140c459aa157b9f47726f52bcc50e94eba Mon Sep 17 00:00:00 2001
  2674. From: Roland Mainz <roland.mainz@nrubsig.org>
  2675. Date: Mon, 15 Jul 2024 15:50:36 +0200
  2676. Subject: [PATCH 09/11] mount: Remove "FIXME" comment about -o overriding
  2677.  defaults from nfs://-URLs.
  2678.  
  2679. Remove obsolete "FIXME" comment about -o overriding defaults from
  2680. nfs://-URLs.
  2681.  
  2682. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2683. ---
  2684. mount/mount.c | 8 ++------
  2685.  1 file changed, 2 insertions(+), 6 deletions(-)
  2686.  
  2687. diff --git a/mount/mount.c b/mount/mount.c
  2688. index a649641..694ef0f 100644
  2689. --- a/mount/mount.c
  2690. +++ b/mount/mount.c
  2691. @@ -554,13 +554,9 @@ static DWORD ParseRemoteName(
  2692.              const char *pvalue;
  2693.  
  2694.              /*
  2695. -             * FIXME: Values added here based on URL parameters
  2696. -             * should be added at the front of the list of options,
  2697. +             * Values added here based on URL parameters
  2698. +             * are added at the front of the list of options,
  2699.               * so users can override the nfs://-URL given default.
  2700. -             * Right now this does not work, e.g.
  2701. -             * $ nfs_mount.exe -o rw nfs://foo//bar?ro=1 # will
  2702. -             * result in a read-only mount, while the expectation
  2703. -             * is that -o overrides URL settings.
  2704.               */
  2705.              for (pi = 0; pi < uctx->num_parameters ; pi++) {
  2706.                  pname = uctx->parameters[pi].name;
  2707. --
  2708. 2.45.1
  2709.  
  2710. From fa252ec057414db0d7e97ec4c6c1f7b5cbd20930 Mon Sep 17 00:00:00 2001
  2711. From: Roland Mainz <roland.mainz@nrubsig.org>
  2712. Date: Mon, 15 Jul 2024 16:06:12 +0200
  2713. Subject: [PATCH 10/11] cygwin: Update README.bintarball.txt
  2714.  
  2715. Update README.bintarball.txt
  2716.  
  2717. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  2718. ---
  2719. cygwin/README.bintarball.txt | 38 +++++++++++++++++++++---------------
  2720.  1 file changed, 22 insertions(+), 16 deletions(-)
  2721.  
  2722. diff --git a/cygwin/README.bintarball.txt b/cygwin/README.bintarball.txt
  2723. index 1596066..8101f2b 100644
  2724. --- a/cygwin/README.bintarball.txt
  2725. +++ b/cygwin/README.bintarball.txt
  2726. @@ -24,7 +24,7 @@ NFSv4.1 client and filesystem driver for Windows 10/11
  2727.  - Support for custom ports (NFSv4 defaults to TCP port 2049, this
  2728.      client can use different ports per mount)
  2729.  
  2730. -- Support for nfs://-URL
  2731. +- Support for nfs://-URLs
  2732.      * Why ? nfs://-URLs are crossplatform, portable and Character-Encoding
  2733.        independent descriptions of NFSv4 server resources (exports).
  2734.      - including custom ports and raw IPv6 addresses
  2735. @@ -33,12 +33,14 @@ NFSv4.1 client and filesystem driver for Windows 10/11
  2736.  
  2737.  - Support ssh forwarding, e.g. mounting NFSv4 filesystems via ssh
  2738.      tunnel
  2739. -- Support for long paths (up to 4096 bytes), no Windows MAXPATH limit
  2740.  
  2741. -- Support for NFSv4 public mounts (i.e. use the NFSv4 public file handle
  2742. -    lookup protocol via $ nfs_mount -o public ... #)
  2743. +- Support for long paths (up to 4096 bytes), no Windows MAXPATH limit
  2744.  
  2745.  - Unicode support
  2746. +    - File names can use any Unicode character supported by
  2747. +      the NFS server's filesystem.
  2748. +    - nfs://-URLs can be used to mount filesystems with non-ASCII
  2749. +      characters in the mount path, independent of current locale.
  2750.  
  2751.  - UNC paths
  2752.      - IPv6 support in UNC paths
  2753. @@ -50,11 +52,14 @@ NFSv4.1 client and filesystem driver for Windows 10/11
  2754.      - IPv6 address within '[', ']'
  2755.        (will be converted to *.ipv6-literal.net)
  2756.  
  2757. -- Windows ACLs
  2758. +- Windows ACLs <---> NFSv4 ACL translation
  2759.      - Win32 C:\Windows\system32\icacls.exe
  2760.      - Cygwin /usr/bin/setfacl+/usr/bin/getfacl
  2761.      - Windows Explorer ACL dialog
  2762.  
  2763. +- Support for NFSv4 public mounts (i.e. use the NFSv4 public file handle
  2764. +    lookup protocol via $ nfs_mount -o public ... #)
  2765. +
  2766.  - SFU/Cygwin support, including:
  2767.      - uid/gid
  2768.      - Cygwin symlinks
  2769. @@ -137,24 +142,25 @@ echo %PROCESSOR_ARCHITECTURE%
  2770.  # If you get any other value then this is a (documentation) bug.
  2771.  
  2772.  - Cygwin 64bit can be installed like this:
  2773. ----- snip ----
  2774. +# ---- snip ----
  2775.  # Install Cygwin 64bit on Windows 64bit with packages required by "ms-nfs41-client"
  2776.  # (Windows NFSv4.1 client):
  2777.  # 1. Get installer from https://cygwin.com/setup-x86_64.exe
  2778.  curl --remote-name "https://www.cygwin.com/setup-x86_64.exe"
  2779.  # 2. Run installer with these arguments:
  2780.  setup-x86_64.exe -q --site "https://mirrors.kernel.org/sourceware/cygwin" -P cygwin,cygwin-devel,cygrunsrv,cygutils,cygutils-extra,bash,bzip2,coreutils,getent,gdb,grep,hostname,less,libiconv,libiconv2,pax,pbzip2,procps-ng,sed,tar,time,util-linux,wget,libnfs-utils,make,git,dos2unix,unzip
  2781. +# ---- snip ----
  2782.  
  2783.  
  2784.  - Cygwin 32bit can be installed like this:
  2785. ----- snip ----
  2786. +# ---- snip ----
  2787.  # Install Cygwin 32bit on Windows 32bit with packages required by "ms-nfs41-client"
  2788.  # (Windows NFSv4.1 client):
  2789.  # 1. Get installer from https://www.cygwin.com/setup-x86.exe
  2790.  curl --remote-name "https://www.cygwin.com/setup-x86.exe"
  2791.  # 2. Run installer with these arguments:
  2792.  setup-x86.exe --allow-unsupported-windows -q --no-verify --site "http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/2022/11/23/063457" -P cygwin,cygwin-devel,cygrunsrv,cygutils,cygutils-extra,bash,bzip2,coreutils,getent,gdb,grep,hostname,less,libiconv,libiconv2,pax,pbzip2,procps-ng,sed,tar,time,util-linux,wget,libnfs-utils,make,git,dos2unix,unzip
  2793. ----- snip ----
  2794. +# ---- snip ----
  2795.  
  2796.  
  2797.  #
  2798. @@ -307,26 +313,26 @@ $ /sbin/nfs_mount
  2799.    - On Windows on a NFSv4 filesystem:
  2800.    $ icacls myhorribledata.txt /grant "siegfried_wulsch:WD" #
  2801.    - On Linux NFSv4 clients you will then see this:
  2802. -  ---- snip ----
  2803. +  # ---- snip ----
  2804.    $ nfs4_getfacl myhorribledata.txt
  2805.    A::OWNER@:rwatTcCy
  2806.    A::siegfried_wulsch@global.loc:rwatcy
  2807.    A::GROUP@:rtcy
  2808.    A::EVERYONE@:rtcy
  2809. -  ---- snip ----
  2810. +  # ---- snip ----
  2811.  
  2812.    * Example 2 (assuming that Windows, Linux NFSv4 client and NFSv4
  2813.    server have a group "cygwingrp2"):
  2814.    - On Windows on a NFSv4 filesystem:
  2815.    $ icacls myhorribledata.txt /grant "cygwingrp2:(WDAC)" /t /c #
  2816.    - On Linux NFSv4 clients you will then see this:
  2817. -  ---- snip ----
  2818. +  # ---- snip ----
  2819.    $ nfs4_getfacl myhorribledata.txt
  2820.    A::OWNER@:rwatTcCy
  2821.    A::GROUP@:rtcy
  2822.    A:g:cygwingrp2@global.loc:rtcy
  2823.    A::EVERYONE@:rtcy
  2824. -  ---- snip ----
  2825. +  # ---- snip ----
  2826.  
  2827.  - nfs_mount.exe vs. reserved ports:
  2828.    By default the NFSv4 server on Solaris, Illumos, Linux
  2829. @@ -396,7 +402,7 @@ $ /sbin/nfs_mount
  2830.  
  2831.  - Bug: Subversion checkout can fail with
  2832.    "sqlite[S11]: database disk image is malformed" like this:
  2833. -  ---- snip ----
  2834. +  # ---- snip ----
  2835.    $ svn checkout https://svn.FreeBSD.org/base/head/share/man
  2836.    A    man/man4
  2837.    A    man/man4/tcp.4
  2838. @@ -419,7 +425,7 @@ $ /sbin/nfs_mount
  2839.    svn: E200030: sqlite[S11]: database disk image is malformed
  2840.    svn: E200030: sqlite[S11]: database disk image is malformed
  2841.    svn: E200030: sqlite[S11]: database disk image is malformed
  2842. -  ---- snip ----
  2843. +  # ---- snip ----
  2844.    Workaround is to mount the NFS filesystem with the "writethru"
  2845.    option, e.g.
  2846.    $ /sbin/nfs_mount -o rw,writethru 'j' derfwpc5131:/export/home/rmainz #
  2847. @@ -450,10 +456,10 @@ $ /sbin/nfs_mount
  2848.    (for NFSv4 default TCP port "2049", replace "2049" with the
  2849.    desired port if you use a custom port ; use "ipconfig" to find the
  2850.    correct interface name, in this case "Ethernet0"):
  2851. -  ---- snip ----
  2852. +  # ---- snip ----
  2853.    $ nfsv4port=2049 ; /cygdrive/c/Program\ Files/Wireshark/tshark \
  2854.      -f "port $nfsv4port" -d "tcp.port==${nfsv4port},rpc" -i Ethernet0
  2855. -  ---- snip ----
  2856. +  # ---- snip ----
  2857.  
  2858.    If you are running inside a VMware VM on a Linux host it
  2859.    might require $ chmod a+rw /dev/vmnet0 # on VMware host, so that
  2860. --
  2861. 2.45.1
  2862.  
  2863. From 7dd9ab5cd47b6866bc1353aefeed99f62dd75fc3 Mon Sep 17 00:00:00 2001
  2864. From: Cedric Blancher <cedric.blancher@gmail.com>
  2865. Date: Mon, 15 Jul 2024 16:56:34 +0200
  2866. Subject: [PATCH 11/11] daemon,libtirpc: Put #define(arg) arg into brackets
  2867.  
  2868. Put #define(arg) arg into brackets.
  2869.  
  2870. Signed-off-by: Roland Mainz <roland.mainz@nrubsig.org>
  2871. ---
  2872. daemon/ea.c               | 3 ++-
  2873.  daemon/nfs41_const.h      | 6 +++---
  2874.  libtirpc/src/svc.c        | 2 +-
  2875.  libtirpc/src/xdr_float.c  | 2 +-
  2876.  libtirpc/tirpc/wintirpc.h | 4 ++--
  2877.  5 files changed, 9 insertions(+), 8 deletions(-)
  2878.  
  2879. diff --git a/daemon/ea.c b/daemon/ea.c
  2880. index 2c94530..17b14c7 100644
  2881. --- a/daemon/ea.c
  2882. +++ b/daemon/ea.c
  2883. @@ -317,7 +317,8 @@ out_free:
  2884.      goto out;
  2885.  }
  2886.  
  2887. -#define ALIGNED_EASIZE(len) (align4(sizeof(FILE_GET_EA_INFORMATION) + len))
  2888. +#define ALIGNED_EASIZE(len) \
  2889. +    (align4(sizeof(FILE_GET_EA_INFORMATION) + (len)))
  2890.  
  2891.  static uint32_t calculate_ea_list_length(
  2892.      IN const unsigned char *position,
  2893. diff --git a/daemon/nfs41_const.h b/daemon/nfs41_const.h
  2894. index 9326d5c..c63931d 100644
  2895. --- a/daemon/nfs41_const.h
  2896. +++ b/daemon/nfs41_const.h
  2897. @@ -227,9 +227,9 @@ enum nfsstat4 {
  2898.      NFS4ERR_XATTR2BIG           = 10096
  2899.  };
  2900.  
  2901. -#define MAKE_WORD0(XXX) (1 << XXX)
  2902. -#define MAKE_WORD1(XXX) (1 << (XXX-32))
  2903. -#define MAKE_WORD2(XXX) (1 << (XXX-64))
  2904. +#define MAKE_WORD0(XXX) (1 << (XXX))
  2905. +#define MAKE_WORD1(XXX) (1 << ((XXX)-32))
  2906. +#define MAKE_WORD2(XXX) (1 << ((XXX)-64))
  2907.  
  2908.  enum {
  2909.  /*
  2910. diff --git a/libtirpc/src/svc.c b/libtirpc/src/svc.c
  2911. index c975286..7bfc1cc 100644
  2912. --- a/libtirpc/src/svc.c
  2913. +++ b/libtirpc/src/svc.c
  2914. @@ -60,7 +60,7 @@
  2915.  #define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET)
  2916.  
  2917.  #ifndef max
  2918. -#define max(a, b) (a > b ? a : b)
  2919. +#define max(a, b) ((a) > (b) ? (a) : (b))
  2920.  #endif
  2921.  
  2922.  /*
  2923. diff --git a/libtirpc/src/xdr_float.c b/libtirpc/src/xdr_float.c
  2924. index 8f2426f..18551f2 100644
  2925. --- a/libtirpc/src/xdr_float.c
  2926. +++ b/libtirpc/src/xdr_float.c
  2927. @@ -178,7 +178,7 @@ struct  vax_double {
  2928.  
  2929.  #define VAX_DBL_BIAS   0x81
  2930.  #define IEEE_DBL_BIAS  0x3ff
  2931. -#define MASK(nbits)    ((1 << nbits) - 1)
  2932. +#define MASK(nbits)    ((1 << (nbits)) - 1)
  2933.  
  2934.  static struct dbl_limits {
  2935.         struct  vax_double d;
  2936. diff --git a/libtirpc/tirpc/wintirpc.h b/libtirpc/tirpc/wintirpc.h
  2937. index 62142ca..31df285 100644
  2938. --- a/libtirpc/tirpc/wintirpc.h
  2939. +++ b/libtirpc/tirpc/wintirpc.h
  2940. @@ -70,8 +70,8 @@
  2941.  #define getpid _getpid
  2942.  
  2943.  #define bcmp memcmp
  2944. -#define bcopy(d,s,l) memcpy(d,s,l)
  2945. -#define bzero(d,s) memset(d,0,s)
  2946. +#define bcopy(d,s,l) memcpy((d),(s),(l))
  2947. +#define bzero(d,s) memset((d),0,(s))
  2948.  #define strtok_r strtok_s
  2949.  
  2950.  #define poll WSAPoll
  2951. --
  2952. 2.45.1

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