pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


nfs-utils nfs://-URL support patch
Posted by Anonymous on Fri 6th Dec 2024 14:28
raw | new post
modification of post by Anonymous (view diff)

  1. From 767e1aa096bacd4dd600d46ccaaefbc47ba863bf Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Fri, 6 Dec 2024 15:22:23 +0100
  4. Subject: [PATCH] mount.nfs4: Add support for nfs://-URLs
  5.  
  6. Add support for RFC 2224-style nfs://-URLs as alternative to the
  7. traditional hostname:/path+-o port=<tcp-port> notation,
  8. providing standardised, extensible, single-string, crossplatform,
  9. portable, Character-Encoding independent (e.g. mount point with
  10. Japanese, Chinese, French etc. characters) and ASCII-compatible
  11. descriptions of NFSv4 server resources (exports).
  12.  
  13. Reviewed-by: Martin Wege <martin.l.wege@gmail.com>
  14. Signed-off-by: Marvin Wenzel <marvin.wenzel@rovema.de>
  15. Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
  16. ---
  17. utils/mount/Makefile.am  |   3 +-
  18.  utils/mount/mount.c      |   3 +
  19.  utils/mount/nfs4mount.c  |  69 +++++++-
  20.  utils/mount/nfsmount.c   |  93 ++++++++--
  21.  utils/mount/parse_dev.c  |  67 ++++++--
  22.  utils/mount/stropts.c    |  96 ++++++++++-
  23.  utils/mount/urlparser1.c | 358 +++++++++++++++++++++++++++++++++++++++
  24.  utils/mount/urlparser1.h |  60 +++++++
  25.  utils/mount/utils.c      | 155 +++++++++++++++++
  26.  utils/mount/utils.h      |  23 +++
  27.  10 files changed, 890 insertions(+), 37 deletions(-)
  28.  create mode 100644 utils/mount/urlparser1.c
  29.  create mode 100644 utils/mount/urlparser1.h
  30.  
  31. diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am
  32. index 83a8ee1c..0e4cab3e 100644
  33. --- a/utils/mount/Makefile.am
  34. +++ b/utils/mount/Makefile.am
  35. @@ -13,7 +13,8 @@ sbin_PROGRAMS = mount.nfs
  36.  EXTRA_DIST = nfsmount.conf $(man8_MANS) $(man5_MANS)
  37.  mount_common = error.c network.c token.c \
  38.                     parse_opt.c parse_dev.c \
  39. -                   nfsmount.c nfs4mount.c stropts.c\
  40. +                   nfsmount.c nfs4mount.c \
  41. +                   urlparser1.c urlparser1.h stropts.c \
  42.                     mount_constants.h error.h network.h token.h \
  43.                     parse_opt.h parse_dev.h \
  44.                     nfs4_mount.h stropts.h version.h \
  45. diff --git a/utils/mount/mount.c b/utils/mount/mount.c
  46. index b98f9e00..2ce6209d 100644
  47. --- a/utils/mount/mount.c
  48. +++ b/utils/mount/mount.c
  49. @@ -29,6 +29,7 @@
  50.  #include <string.h>
  51.  #include <errno.h>
  52.  #include <fcntl.h>
  53. +#include <locale.h>
  54.  #include <sys/mount.h>
  55.  #include <getopt.h>
  56.  #include <mntent.h>
  57. @@ -386,6 +387,8 @@ int main(int argc, char *argv[])
  58.         char *extra_opts = NULL, *mount_opts = NULL;
  59.         uid_t uid = getuid();
  60.  
  61. +       (void)setlocale(LC_ALL, "");
  62. +
  63.         progname = basename(argv[0]);
  64.  
  65.         nfs_mount_data_version = discover_nfs_mount_data_version(&string);
  66. diff --git a/utils/mount/nfs4mount.c b/utils/mount/nfs4mount.c
  67. index 0fe142a7..8e4fbf30 100644
  68. --- a/utils/mount/nfs4mount.c
  69. +++ b/utils/mount/nfs4mount.c
  70. @@ -50,8 +50,10 @@
  71.  #include "mount_constants.h"
  72.  #include "nfs4_mount.h"
  73.  #include "nfs_mount.h"
  74. +#include "urlparser1.h"
  75.  #include "error.h"
  76.  #include "network.h"
  77. +#include "utils.h"
  78.  
  79.  #if defined(VAR_LOCK_DIR)
  80.  #define DEFAULT_DIR VAR_LOCK_DIR
  81. @@ -182,7 +184,7 @@ int nfs4mount(const char *spec, const char *node, int flags,
  82.         int num_flavour = 0;
  83.         int ip_addr_in_opts = 0;
  84.  
  85. -       char *hostname, *dirname, *old_opts;
  86. +       char *hostname, *dirname, *mb_dirname = NULL, *old_opts;
  87.         char new_opts[1024];
  88.         char *opt, *opteq;
  89.         char *s;
  90. @@ -192,15 +194,66 @@ int nfs4mount(const char *spec, const char *node, int flags,
  91.         int retry;
  92.         int retval = EX_FAIL;
  93.         time_t timeout, t;
  94. +       int nfs_port = NFS_PORT;
  95. +       parsed_nfs_url pnu;
  96. +
  97. +       (void)memset(&pnu, 0, sizeof(parsed_nfs_url));
  98.  
  99.         if (strlen(spec) >= sizeof(hostdir)) {
  100.                 nfs_error(_("%s: excessively long host:dir argument\n"),
  101.                                 progname);
  102.                 goto fail;
  103.         }
  104. -       strcpy(hostdir, spec);
  105. -       if (parse_devname(hostdir, &hostname, &dirname))
  106. -               goto fail;
  107. +
  108. +       /*
  109. +        * Support nfs://-URLS per RFC 2224 ("NFS URL
  110. +        * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
  111. +        * including custom port (nfs://hostname@port/path/...)
  112. +        * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
  113. +        * support
  114. +        */
  115. +       if (is_spec_nfs_url(spec)) {
  116. +               if (!mount_parse_nfs_url(spec, &pnu)) {
  117. +                       goto fail;
  118. +               }
  119. +
  120. +               /*
  121. +                * |pnu.uctx->path| is in UTF-8, but we need the data
  122. +                * in the current local locale's encoding, as mount(2)
  123. +                * does not have something like a |MS_UTF8_SPEC| flag
  124. +                * to indicate that the input path is in UTF-8,
  125. +                * independently of the current locale
  126. +                */
  127. +               hostname = pnu.uctx->hostport.hostname;
  128. +               dirname = mb_dirname = utf8str2mbstr(pnu.uctx->path);
  129. +
  130. +               (void)snprintf(hostdir, sizeof(hostdir), "%s:/%s",
  131. +                       hostname, dirname);
  132. +               spec = hostdir;
  133. +
  134. +               if (pnu.uctx->hostport.port != -1) {
  135. +                       nfs_port = pnu.uctx->hostport.port;
  136. +               }
  137. +
  138. +               /*
  139. +                * Values added here based on URL parameters
  140. +                * should be added the front of the list of options,
  141. +                * so users can override the nfs://-URL given default.
  142. +                *
  143. +                * FIXME: We do not do that here for |MS_RDONLY|!
  144. +                */
  145. +               if (pnu.mount_params.read_only != TRIS_BOOL_NOT_SET) {
  146. +                       if (pnu.mount_params.read_only)
  147. +                               flags |= MS_RDONLY;
  148. +                       else
  149. +                               flags &= ~MS_RDONLY;
  150. +               }
  151. +        } else {
  152. +               (void)strcpy(hostdir, spec);
  153. +
  154. +               if (parse_devname(hostdir, &hostname, &dirname))
  155. +                       goto fail;
  156. +       }
  157.  
  158.         if (fill_ipv4_sockaddr(hostname, &server_addr))
  159.                 goto fail;
  160. @@ -247,7 +300,7 @@ int nfs4mount(const char *spec, const char *node, int flags,
  161.         /*
  162.          * NFSv4 specifies that the default port should be 2049
  163.          */
  164. -       server_addr.sin_port = htons(NFS_PORT);
  165. +       server_addr.sin_port = htons(nfs_port);
  166.  
  167.         /* parse options */
  168.  
  169. @@ -474,8 +527,14 @@ int nfs4mount(const char *spec, const char *node, int flags,
  170.                 }
  171.         }
  172.  
  173. +       mount_free_parse_nfs_url(&pnu);
  174. +       free(mb_dirname);
  175. +
  176.         return EX_SUCCESS;
  177.  
  178.  fail:
  179. +       mount_free_parse_nfs_url(&pnu);
  180. +       free(mb_dirname);
  181. +
  182.         return retval;
  183.  }
  184. diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c
  185. index a1c92fe8..e61d718a 100644
  186. --- a/utils/mount/nfsmount.c
  187. +++ b/utils/mount/nfsmount.c
  188. @@ -63,11 +63,13 @@
  189.  #include "xcommon.h"
  190.  #include "mount.h"
  191.  #include "nfs_mount.h"
  192. +#include "urlparser1.h"
  193.  #include "mount_constants.h"
  194.  #include "nls.h"
  195.  #include "error.h"
  196.  #include "network.h"
  197.  #include "version.h"
  198. +#include "utils.h"
  199.  
  200.  #ifdef HAVE_RPCSVC_NFS_PROT_H
  201.  #include <rpcsvc/nfs_prot.h>
  202. @@ -493,7 +495,7 @@ nfsmount(const char *spec, const char *node, int flags,
  203.          char **extra_opts, int fake, int running_bg)
  204.  {
  205.         char hostdir[1024];
  206. -       char *hostname, *dirname, *old_opts, *mounthost = NULL;
  207. +       char *hostname, *dirname, *mb_dirname = NULL, *old_opts, *mounthost = NULL;
  208.         char new_opts[1024], cbuf[1024];
  209.         static struct nfs_mount_data data;
  210.         int val;
  211. @@ -521,29 +523,79 @@ nfsmount(const char *spec, const char *node, int flags,
  212.         time_t t;
  213.         time_t prevt;
  214.         time_t timeout;
  215. +       int nfsurl_port = -1;
  216. +       parsed_nfs_url pnu;
  217. +
  218. +       (void)memset(&pnu, 0, sizeof(parsed_nfs_url));
  219.  
  220.         if (strlen(spec) >= sizeof(hostdir)) {
  221.                 nfs_error(_("%s: excessively long host:dir argument"),
  222.                                 progname);
  223.                 goto fail;
  224.         }
  225. -       strcpy(hostdir, spec);
  226. -       if ((s = strchr(hostdir, ':'))) {
  227. -               hostname = hostdir;
  228. -               dirname = s + 1;
  229. -               *s = '\0';
  230. -               /* Ignore all but first hostname in replicated mounts
  231. -                  until they can be fully supported. (mack@sgi.com) */
  232. -               if ((s = strchr(hostdir, ','))) {
  233. +
  234. +       /*
  235. +        * Support nfs://-URLS per RFC 2224 ("NFS URL
  236. +        * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
  237. +        * including custom port (nfs://hostname@port/path/...)
  238. +        * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
  239. +        * support
  240. +        */
  241. +       if (is_spec_nfs_url(spec)) {
  242. +               if (!mount_parse_nfs_url(spec, &pnu)) {
  243. +                       goto fail;
  244. +               }
  245. +
  246. +               /*
  247. +                * |pnu.uctx->path| is in UTF-8, but we need the data
  248. +                * in the current local locale's encoding, as mount(2)
  249. +                * does not have something like a |MS_UTF8_SPEC| flag
  250. +                * to indicate that the input path is in UTF-8,
  251. +                * independently of the current locale
  252. +                */
  253. +               hostname = pnu.uctx->hostport.hostname;
  254. +               dirname = mb_dirname = utf8str2mbstr(pnu.uctx->path);
  255. +
  256. +               (void)snprintf(hostdir, sizeof(hostdir), "%s:/%s",
  257. +                       hostname, dirname);
  258. +               spec = hostdir;
  259. +
  260. +               if (pnu.uctx->hostport.port != -1) {
  261. +                       nfsurl_port = pnu.uctx->hostport.port;
  262. +               }
  263. +
  264. +               /*
  265. +                * Values added here based on URL parameters
  266. +                * should be added the front of the list of options,
  267. +                * so users can override the nfs://-URL given default.
  268. +                *
  269. +                * FIXME: We do not do that here for |MS_RDONLY|!
  270. +                */
  271. +               if (pnu.mount_params.read_only != TRIS_BOOL_NOT_SET) {
  272. +                       if (pnu.mount_params.read_only)
  273. +                               flags |= MS_RDONLY;
  274. +                       else
  275. +                               flags &= ~MS_RDONLY;
  276. +               }
  277. +        } else {
  278. +               (void)strcpy(hostdir, spec);
  279. +               if ((s = strchr(hostdir, ':'))) {
  280. +                       hostname = hostdir;
  281. +                       dirname = s + 1;
  282.                         *s = '\0';
  283. -                       nfs_error(_("%s: warning: "
  284. -                                 "multiple hostnames not supported"),
  285. +                       /* Ignore all but first hostname in replicated mounts
  286. +                          until they can be fully supported. (mack@sgi.com) */
  287. +                       if ((s = strchr(hostdir, ','))) {
  288. +                               *s = '\0';
  289. +                               nfs_error(_("%s: warning: "
  290. +                                       "multiple hostnames not supported"),
  291.                                         progname);
  292. -               }
  293. -       } else {
  294. -               nfs_error(_("%s: directory to mount not in host:dir format"),
  295. +                       }
  296. +               } else {
  297. +                       nfs_error(_("%s: directory to mount not in host:dir format"),
  298.                                 progname);
  299. -               goto fail;
  300. +                       goto fail;
  301. +               }
  302.         }
  303.  
  304.         if (!nfs_gethostbyname(hostname, nfs_saddr))
  305. @@ -579,6 +631,14 @@ nfsmount(const char *spec, const char *node, int flags,
  306.         memset(nfs_pmap, 0, sizeof(*nfs_pmap));
  307.         nfs_pmap->pm_prog = NFS_PROGRAM;
  308.  
  309. +       if (nfsurl_port != -1) {
  310. +               /*
  311. +                * Set custom TCP port defined by a nfs://-URL here,
  312. +                * so $ mount -o port ... # can be used to override
  313. +                */
  314. +               nfs_pmap->pm_port = nfsurl_port;
  315. +       }
  316. +
  317.         /* parse options */
  318.         new_opts[0] = 0;
  319.         if (!parse_options(old_opts, &data, &bg, &retry, &mnt_server, &nfs_server,
  320. @@ -863,10 +923,13 @@ noauth_flavors:
  321.                 }
  322.         }
  323.  
  324. +       mount_free_parse_nfs_url(&pnu);
  325. +
  326.         return EX_SUCCESS;
  327.  
  328.         /* abort */
  329.   fail:
  330. +       mount_free_parse_nfs_url(&pnu);
  331.         if (fsock != -1)
  332.                 close(fsock);
  333.         return retval;
  334. diff --git a/utils/mount/parse_dev.c b/utils/mount/parse_dev.c
  335. index 2ade5d5d..d9f8cf59 100644
  336. --- a/utils/mount/parse_dev.c
  337. +++ b/utils/mount/parse_dev.c
  338. @@ -27,6 +27,8 @@
  339.  #include "xcommon.h"
  340.  #include "nls.h"
  341.  #include "parse_dev.h"
  342. +#include "urlparser1.h"
  343. +#include "utils.h"
  344.  
  345.  #ifndef NFS_MAXHOSTNAME
  346.  #define NFS_MAXHOSTNAME                (255)
  347. @@ -179,17 +181,62 @@ static int nfs_parse_square_bracket(const char *dev,
  348.  }
  349.  
  350.  /*
  351. - * RFC 2224 says an NFS client must grok "public file handles" to
  352. - * support NFS URLs.  Linux doesn't do that yet.  Print a somewhat
  353. - * helpful error message in this case instead of pressing forward
  354. - * with the mount request and failing with a cryptic error message
  355. - * later.
  356. + * Support nfs://-URLS per RFC 2224 ("NFS URL
  357. + * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
  358. + * including port support (nfs://hostname@port/path/...)
  359.   */
  360. -static int nfs_parse_nfs_url(__attribute__((unused)) const char *dev,
  361. -                            __attribute__((unused)) char **hostname,
  362. -                            __attribute__((unused)) char **pathname)
  363. +static int nfs_parse_nfs_url(const char *dev,
  364. +                            char **out_hostname,
  365. +                            char **out_pathname)
  366.  {
  367. -       nfs_error(_("%s: NFS URLs are not supported"), progname);
  368. +       parsed_nfs_url pnu;
  369. +
  370. +       if (out_hostname)
  371. +               *out_hostname = NULL;
  372. +       if (out_pathname)
  373. +               *out_pathname = NULL;
  374. +
  375. +       /*
  376. +        * Support nfs://-URLS per RFC 2224 ("NFS URL
  377. +        * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
  378. +        * including custom port (nfs://hostname@port/path/...)
  379. +        * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
  380. +        * support
  381. +        */
  382. +       if (!mount_parse_nfs_url(dev, &pnu)) {
  383. +               goto fail;
  384. +       }
  385. +
  386. +       if (pnu.uctx->hostport.port != -1) {
  387. +               /* NOP here, unless we switch from hostname to hostport */
  388. +       }
  389. +
  390. +       if (out_hostname)
  391. +               *out_hostname = strdup(pnu.uctx->hostport.hostname);
  392. +       if (out_pathname)
  393. +               *out_pathname = utf8str2mbstr(pnu.uctx->path);
  394. +
  395. +       if (((out_hostname)?(*out_hostname == NULL):0) ||
  396. +               ((out_pathname)?(*out_pathname == NULL):0)) {
  397. +               nfs_error(_("%s: out of memory"),
  398. +                       progname);
  399. +               goto fail;
  400. +       }
  401. +
  402. +       mount_free_parse_nfs_url(&pnu);
  403. +
  404. +       return 1;
  405. +
  406. +fail:
  407. +       mount_free_parse_nfs_url(&pnu);
  408. +       if (out_hostname) {
  409. +               free(*out_hostname);
  410. +               *out_hostname = NULL;
  411. +       }
  412. +       if (out_pathname) {
  413. +               free(*out_pathname);
  414. +               *out_pathname = NULL;
  415. +       }
  416.         return 0;
  417.  }
  418.  
  419. @@ -223,7 +270,7 @@ int nfs_parse_devname(const char *devname,
  420.                 return nfs_pdn_nomem_err();
  421.         if (*dev == '[')
  422.                 result = nfs_parse_square_bracket(dev, hostname, pathname);
  423. -       else if (strncmp(dev, "nfs://", 6) == 0)
  424. +       else if (is_spec_nfs_url(dev))
  425.                 result = nfs_parse_nfs_url(dev, hostname, pathname);
  426.         else
  427.                 result = nfs_parse_simple_hostname(dev, hostname, pathname);
  428. diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
  429. index 23f0a8c0..ad92ab78 100644
  430. --- a/utils/mount/stropts.c
  431. +++ b/utils/mount/stropts.c
  432. @@ -42,6 +42,7 @@
  433.  #include "nls.h"
  434.  #include "nfsrpc.h"
  435.  #include "mount_constants.h"
  436. +#include "urlparser1.h"
  437.  #include "stropts.h"
  438.  #include "error.h"
  439.  #include "network.h"
  440. @@ -50,6 +51,7 @@
  441.  #include "parse_dev.h"
  442.  #include "conffile.h"
  443.  #include "misc.h"
  444. +#include "utils.h"
  445.  
  446.  #ifndef NFS_PROGRAM
  447.  #define NFS_PROGRAM    (100003)
  448. @@ -643,24 +645,106 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
  449.  {
  450.         char *options = NULL;
  451.         int result;
  452. +       int nfs_port = 2049;
  453.  
  454.         if (mi->fake)
  455.                 return 1;
  456.  
  457. -       if (po_join(opts, &options) == PO_FAILED) {
  458. -               errno = EIO;
  459. -               return 0;
  460. -       }
  461. +       /*
  462. +        * Support nfs://-URLS per RFC 2224 ("NFS URL
  463. +        * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
  464. +        * including custom port (nfs://hostname@port/path/...)
  465. +        * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
  466. +        * support
  467. +        */
  468. +       if (is_spec_nfs_url(mi->spec)) {
  469. +               parsed_nfs_url pnu;
  470. +               char *mb_path;
  471. +               char mount_source[1024];
  472. +
  473. +               if (!mount_parse_nfs_url(mi->spec, &pnu)) {
  474. +                       result = 1;
  475. +                       errno = EINVAL;
  476. +                       goto done;
  477. +               }
  478. +
  479. +               /*
  480. +                * |pnu.uctx->path| is in UTF-8, but we need the data
  481. +                * in the current local locale's encoding, as mount(2)
  482. +                * does not have something like a |MS_UTF8_SPEC| flag
  483. +                * to indicate that the input path is in UTF-8,
  484. +                * independently of the current locale
  485. +                */
  486. +               mb_path = utf8str2mbstr(pnu.uctx->path);
  487. +               if (!mb_path) {
  488. +                       nfs_error(_("%s: Could not convert path to local encoding."),
  489. +                               progname);
  490. +                       mount_free_parse_nfs_url(&pnu);
  491. +                       result = 1;
  492. +                       errno = EINVAL;
  493. +                       goto done;
  494. +               }
  495. +
  496. +               (void)snprintf(mount_source, sizeof(mount_source),
  497. +                       "%s:/%s",
  498. +                       pnu.uctx->hostport.hostname,
  499. +                       mb_path);
  500. +               free(mb_path);
  501. +
  502. +               if (pnu.uctx->hostport.port != -1) {
  503. +                       nfs_port = pnu.uctx->hostport.port;
  504. +               }
  505.  
  506. -       result = mount(mi->spec, mi->node, mi->type,
  507. +               /*
  508. +                * Insert "port=" option with the value from the nfs://
  509. +                * URL at the beginning of the list of options, so
  510. +                * users can override it with $ mount.nfs4 -o port= #,
  511. +                * e.g.
  512. +                * $ mount.nfs4 -o port=1234 nfs://10.49.202.230:400//bigdisk /mnt4 #
  513. +                * should use port 1234, and not port 400 as specified
  514. +                * in the URL.
  515. +                */
  516. +               char portoptbuf[5+32+1];
  517. +               (void)snprintf(portoptbuf, sizeof(portoptbuf), "port=%d", nfs_port);
  518. +               (void)po_insert(opts, portoptbuf);
  519. +
  520. +               if (pnu.mount_params.read_only != TRIS_BOOL_NOT_SET) {
  521. +                       if (pnu.mount_params.read_only)
  522. +                               mi->flags |= MS_RDONLY;
  523. +                       else
  524. +                               mi->flags &= ~MS_RDONLY;
  525. +               }
  526. +
  527. +               mount_free_parse_nfs_url(&pnu);
  528. +
  529. +               if (po_join(opts, &options) == PO_FAILED) {
  530. +                       errno = EIO;
  531. +                       result = 1;
  532. +                       goto done;
  533. +               }
  534. +
  535. +               result = mount(mount_source, mi->node, mi->type,
  536. +                       mi->flags & ~(MS_USER|MS_USERS), options);
  537. +               free(options);
  538. +       } else {
  539. +               if (po_join(opts, &options) == PO_FAILED) {
  540. +                       errno = EIO;
  541. +                       result = 1;
  542. +                       goto done;
  543. +               }
  544. +
  545. +               result = mount(mi->spec, mi->node, mi->type,
  546.                         mi->flags & ~(MS_USER|MS_USERS), options);
  547. -       free(options);
  548. +               free(options);
  549. +       }
  550.  
  551.         if (verbose && result) {
  552.                 int save = errno;
  553.                 nfs_error(_("%s: mount(2): %s"), progname, strerror(save));
  554.                 errno = save;
  555.         }
  556. +
  557. +done:
  558.         return !result;
  559.  }
  560.  
  561. diff --git a/utils/mount/urlparser1.c b/utils/mount/urlparser1.c
  562. new file mode 100644
  563. index 00000000..d4c6f339
  564. --- /dev/null
  565. +++ b/utils/mount/urlparser1.c
  566. @@ -0,0 +1,358 @@
  567. +/*
  568. + * MIT License
  569. + *
  570. + * Copyright (c) 2024 Roland Mainz <roland.mainz@nrubsig.org>
  571. + *
  572. + * Permission is hereby granted, free of charge, to any person obtaining a copy
  573. + * of this software and associated documentation files (the "Software"), to deal
  574. + * in the Software without restriction, including without limitation the rights
  575. + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  576. + * copies of the Software, and to permit persons to whom the Software is
  577. + * furnished to do so, subject to the following conditions:
  578. + *
  579. + * The above copyright notice and this permission notice shall be included in all
  580. + * copies or substantial portions of the Software.
  581. + *
  582. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  583. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  584. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  585. + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  586. + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  587. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  588. + * SOFTWARE.
  589. + */
  590. +
  591. +/* urlparser1.c - simple URL parser */
  592. +
  593. +#include <stdlib.h>
  594. +#include <stdbool.h>
  595. +#include <string.h>
  596. +#include <ctype.h>
  597. +#include <stdio.h>
  598. +
  599. +#ifdef DBG_USE_WIDECHAR
  600. +#include <wchar.h>
  601. +#include <locale.h>
  602. +#include <io.h>
  603. +#include <fcntl.h>
  604. +#endif /* DBG_USE_WIDECHAR */
  605. +
  606. +#include "urlparser1.h"
  607. +
  608. +typedef struct _url_parser_context_private {
  609. +       url_parser_context c;
  610. +
  611. +       /* Private data */
  612. +       char *parameter_string_buff;
  613. +} url_parser_context_private;
  614. +
  615. +#define MAX_URL_PARAMETERS 256
  616. +
  617. +/*
  618. + * Original extended regular expression:
  619. + *
  620. + * "^"
  621. + * "(.+?)"                             // scheme
  622. + * "://"                               // '://'
  623. + * "("                                 // login
  624. + *     "(?:"
  625. + *     "(.+?)"                         // user (optional)
  626. + *             "(?::(.+))?"            // password (optional)
  627. + *             "@"
  628. + *     ")?"
  629. + *     "("                             // hostport
  630. + *             "(.+?)"                 // host
  631. + *             "(?::([[:digit:]]+))?"  // port (optional)
  632. + *     ")"
  633. + * ")"
  634. + * "(?:/(.*?))?"                       // path (optional)
  635. + * "(?:\?(.*?))?"                      // URL parameters (optional)
  636. + * "$"
  637. + */
  638. +
  639. +#define DBGNULLSTR(s) (((s)!=NULL)?(s):"<NULL>")
  640. +#if 0 || defined(TEST_URLPARSER)
  641. +#define D(x) x
  642. +#else
  643. +#define D(x)
  644. +#endif
  645. +
  646. +#ifdef DBG_USE_WIDECHAR
  647. +/*
  648. + * Use wide-char APIs on WIN32, otherwise we cannot output
  649. + * Japanese/Chinese/etc correctly
  650. + */
  651. +#define DBG_PUTS(str, fp)              fputws(L"" str, (fp))
  652. +#define DBG_PUTC(c, fp)                        fputwc(btowc(c), (fp))
  653. +#define DBG_PRINTF(fp, fmt, ...)       fwprintf((fp), L"" fmt, __VA_ARGS__)
  654. +#else
  655. +#define DBG_PUTS(str, fp)              fputs((str), (fp))
  656. +#define DBG_PUTC(c, fp)                        fputc((c), (fp))
  657. +#define DBG_PRINTF(fp, fmt, ...)       fprintf((fp), fmt, __VA_ARGS__)
  658. +#endif /* DBG_USE_WIDECHAR */
  659. +
  660. +static
  661. +void urldecodestr(char *outbuff, const char *buffer, size_t len)
  662. +{
  663. +       size_t i, j;
  664. +
  665. +       for (i = j = 0 ; i < len ; ) {
  666. +               switch (buffer[i]) {
  667. +                       case '%':
  668. +                               if ((i + 2) < len) {
  669. +                                       if (isxdigit((int)buffer[i+1]) && isxdigit((int)buffer[i+2])) {
  670. +                                               const char hexstr[3] = {
  671. +                                                       buffer[i+1],
  672. +                                                       buffer[i+2],
  673. +                                                       '\0'
  674. +                                               };
  675. +                                               outbuff[j++] = (unsigned char)strtol(hexstr, NULL, 16);
  676. +                                               i += 3;
  677. +                                       } else {
  678. +                                               /* invalid hex digit */
  679. +                                               outbuff[j++] = buffer[i];
  680. +                                               i++;
  681. +                                       }
  682. +                               } else {
  683. +                                       /* incomplete hex digit */
  684. +                                       outbuff[j++] = buffer[i];
  685. +                                       i++;
  686. +                               }
  687. +                               break;
  688. +                       case '+':
  689. +                               outbuff[j++] = ' ';
  690. +                               i++;
  691. +                               break;
  692. +                       default:
  693. +                               outbuff[j++] = buffer[i++];
  694. +                               break;
  695. +               }
  696. +       }
  697. +
  698. +       outbuff[j] = '\0';
  699. +}
  700. +
  701. +url_parser_context *url_parser_create_context(const char *in_url, unsigned int flags)
  702. +{
  703. +       url_parser_context_private *uctx;
  704. +       char *s;
  705. +       size_t in_url_len;
  706. +       size_t context_len;
  707. +
  708. +       /* |flags| is for future extensions */
  709. +       (void)flags;
  710. +
  711. +       if (!in_url)
  712. +               return NULL;
  713. +
  714. +       in_url_len = strlen(in_url);
  715. +
  716. +       context_len = sizeof(url_parser_context_private) +
  717. +               ((in_url_len+1)*6) +
  718. +               (sizeof(url_parser_name_value)*MAX_URL_PARAMETERS)+sizeof(void*);
  719. +       uctx = malloc(context_len);
  720. +       if (!uctx)
  721. +               return NULL;
  722. +
  723. +       s = (void *)(uctx+1);
  724. +       uctx->c.in_url = s;             s+= in_url_len+1;
  725. +       (void)strcpy(uctx->c.in_url, in_url);
  726. +       uctx->c.scheme = s;             s+= in_url_len+1;
  727. +       uctx->c.login.username = s;     s+= in_url_len+1;
  728. +       uctx->c.hostport.hostname = s;  s+= in_url_len+1;
  729. +       uctx->c.path = s;               s+= in_url_len+1;
  730. +       uctx->c.hostport.port = -1;
  731. +       uctx->c.num_parameters = -1;
  732. +       uctx->c.parameters = (void *)s;         s+= (sizeof(url_parser_name_value)*MAX_URL_PARAMETERS)+sizeof(void*);
  733. +       uctx->parameter_string_buff = s;        s+= in_url_len+1;
  734. +
  735. +       return &uctx->c;
  736. +}
  737. +
  738. +int url_parser_parse(url_parser_context *ctx)
  739. +{
  740. +       url_parser_context_private *uctx = (url_parser_context_private *)ctx;
  741. +
  742. +       D((void)DBG_PRINTF(stderr, "## parser in_url='%s'\n", uctx->c.in_url));
  743. +
  744. +       char *s;
  745. +       const char *urlstr = uctx->c.in_url;
  746. +       size_t slen;
  747. +
  748. +       s = strstr(urlstr, "://");
  749. +       if (!s) {
  750. +               D((void)DBG_PUTS("url_parser: Not an URL\n", stderr));
  751. +               return -1;
  752. +       }
  753. +
  754. +       slen = s-urlstr;
  755. +       (void)memcpy(uctx->c.scheme, urlstr, slen);
  756. +       uctx->c.scheme[slen] = '\0';
  757. +       urlstr += slen + 3;
  758. +
  759. +       D((void)DBG_PRINTF(stdout, "scheme='%s', rest='%s'\n", uctx->c.scheme, urlstr));
  760. +
  761. +       s = strstr(urlstr, "@");
  762. +       if (s) {
  763. +               /* URL has user/password */
  764. +               slen = s-urlstr;
  765. +               urldecodestr(uctx->c.login.username, urlstr, slen);
  766. +               urlstr += slen + 1;
  767. +
  768. +               s = strstr(uctx->c.login.username, ":");
  769. +               if (s) {
  770. +                       /* found passwd */
  771. +                       uctx->c.login.passwd = s+1;
  772. +                       *s = '\0';
  773. +               }
  774. +               else {
  775. +                       uctx->c.login.passwd = NULL;
  776. +               }
  777. +
  778. +               /* catch password-only URLs */
  779. +               if (uctx->c.login.username[0] == '\0')
  780. +                       uctx->c.login.username = NULL;
  781. +       }
  782. +       else {
  783. +               uctx->c.login.username = NULL;
  784. +               uctx->c.login.passwd = NULL;
  785. +       }
  786. +
  787. +       D((void)DBG_PRINTF(stdout, "login='%s', passwd='%s', rest='%s'\n",
  788. +               DBGNULLSTR(uctx->c.login.username),
  789. +               DBGNULLSTR(uctx->c.login.passwd),
  790. +               DBGNULLSTR(urlstr)));
  791. +
  792. +       char *raw_parameters;
  793. +
  794. +       uctx->c.num_parameters = 0;
  795. +       raw_parameters = strstr(urlstr, "?");
  796. +       /* Do we have a non-empty parameter string ? */
  797. +       if (raw_parameters && (raw_parameters[1] != '\0')) {
  798. +               *raw_parameters++ = '\0';
  799. +               D((void)DBG_PRINTF(stdout, "raw parameters = '%s'\n", raw_parameters));
  800. +
  801. +               char *ps = raw_parameters;
  802. +               char *pv; /* parameter value */
  803. +               char *na; /* next '&' */
  804. +               char *pb = uctx->parameter_string_buff;
  805. +               char *pname;
  806. +               char *pvalue;
  807. +               ssize_t pi;
  808. +
  809. +               for (pi = 0; pi < MAX_URL_PARAMETERS ; pi++) {
  810. +                       pname = ps;
  811. +
  812. +                       /*
  813. +                        * Handle parameters without value,
  814. +                        * e.g. "path?name1&name2=value2"
  815. +                        */
  816. +                       na = strstr(ps, "&");
  817. +                       pv = strstr(ps, "=");
  818. +                       if (pv && (na?(na > pv):true)) {
  819. +                               *pv++ = '\0';
  820. +                               pvalue = pv;
  821. +                               ps = pv;
  822. +                       }
  823. +                       else {
  824. +                               pvalue = NULL;
  825. +                       }
  826. +
  827. +                       if (na) {
  828. +                               *na++ = '\0';
  829. +                       }
  830. +
  831. +                       /* URLDecode parameter name */
  832. +                       urldecodestr(pb, pname, strlen(pname));
  833. +                       uctx->c.parameters[pi].name = pb;
  834. +                       pb += strlen(uctx->c.parameters[pi].name)+1;
  835. +
  836. +                       /* URLDecode parameter value */
  837. +                       if (pvalue) {
  838. +                               urldecodestr(pb, pvalue, strlen(pvalue));
  839. +                               uctx->c.parameters[pi].value = pb;
  840. +                               pb += strlen(uctx->c.parameters[pi].value)+1;
  841. +                       }
  842. +                       else {
  843. +                               uctx->c.parameters[pi].value = NULL;
  844. +                       }
  845. +
  846. +                       /* Next '&' ? */
  847. +                       if (!na)
  848. +                               break;
  849. +
  850. +                       ps = na;
  851. +               }
  852. +
  853. +               uctx->c.num_parameters = pi+1;
  854. +       }
  855. +
  856. +       s = strstr(urlstr, "/");
  857. +       if (s) {
  858. +               /* URL has hostport */
  859. +               slen = s-urlstr;
  860. +               urldecodestr(uctx->c.hostport.hostname, urlstr, slen);
  861. +               urlstr += slen + 1;
  862. +
  863. +               /*
  864. +                * check for addresses within '[' and ']', like
  865. +                * IPv6 addresses
  866. +                */
  867. +               s = uctx->c.hostport.hostname;
  868. +               if (s[0] == '[')
  869. +                       s = strstr(s, "]");
  870. +
  871. +               if (s == NULL) {
  872. +                       D((void)DBG_PUTS("url_parser: Unmatched '[' in hostname\n", stderr));
  873. +                       return -1;
  874. +               }
  875. +
  876. +               s = strstr(s, ":");
  877. +               if (s) {
  878. +                       /* found port number */
  879. +                       uctx->c.hostport.port = atoi(s+1);
  880. +                       *s = '\0';
  881. +               }
  882. +       }
  883. +       else {
  884. +               (void)strcpy(uctx->c.hostport.hostname, urlstr);
  885. +               uctx->c.path = NULL;
  886. +               urlstr = NULL;
  887. +       }
  888. +
  889. +       D(
  890. +               (void)DBG_PRINTF(stdout,
  891. +                       "hostport='%s', port=%d, rest='%s', num_parameters=%d\n",
  892. +                       DBGNULLSTR(uctx->c.hostport.hostname),
  893. +                       uctx->c.hostport.port,
  894. +                       DBGNULLSTR(urlstr),
  895. +                       (int)uctx->c.num_parameters);
  896. +       );
  897. +
  898. +
  899. +       D(
  900. +               ssize_t dpi;
  901. +               for (dpi = 0 ; dpi < uctx->c.num_parameters ; dpi++) {
  902. +                       (void)DBG_PRINTF(stdout,
  903. +                               "param[%d]: name='%s'/value='%s'\n",
  904. +                               (int)dpi,
  905. +                               uctx->c.parameters[dpi].name,
  906. +                               DBGNULLSTR(uctx->c.parameters[dpi].value));
  907. +               }
  908. +       );
  909. +
  910. +       if (!urlstr) {
  911. +               goto done;
  912. +       }
  913. +
  914. +       urldecodestr(uctx->c.path, urlstr, strlen(urlstr));
  915. +       D((void)DBG_PRINTF(stdout, "path='%s'\n", uctx->c.path));
  916. +
  917. +done:
  918. +       return 0;
  919. +}
  920. +
  921. +void url_parser_free_context(url_parser_context *c)
  922. +{
  923. +       free(c);
  924. +}
  925. diff --git a/utils/mount/urlparser1.h b/utils/mount/urlparser1.h
  926. new file mode 100644
  927. index 00000000..515eea9d
  928. --- /dev/null
  929. +++ b/utils/mount/urlparser1.h
  930. @@ -0,0 +1,60 @@
  931. +/*
  932. + * MIT License
  933. + *
  934. + * Copyright (c) 2024 Roland Mainz <roland.mainz@nrubsig.org>
  935. + *
  936. + * Permission is hereby granted, free of charge, to any person obtaining a copy
  937. + * of this software and associated documentation files (the "Software"), to deal
  938. + * in the Software without restriction, including without limitation the rights
  939. + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  940. + * copies of the Software, and to permit persons to whom the Software is
  941. + * furnished to do so, subject to the following conditions:
  942. + *
  943. + * The above copyright notice and this permission notice shall be included in all
  944. + * copies or substantial portions of the Software.
  945. + *
  946. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  947. + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  948. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  949. + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  950. + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  951. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  952. + * SOFTWARE.
  953. + */
  954. +
  955. +/* urlparser1.h - header for simple URL parser */
  956. +
  957. +#ifndef __URLPARSER1_H__
  958. +#define __URLPARSER1_H__ 1
  959. +
  960. +#include <stdlib.h>
  961. +
  962. +typedef struct _url_parser_name_value {
  963. +       char *name;
  964. +       char *value;
  965. +} url_parser_name_value;
  966. +
  967. +typedef struct _url_parser_context {
  968. +       char *in_url;
  969. +
  970. +       char *scheme;
  971. +       struct {
  972. +               char *username;
  973. +               char *passwd;
  974. +       } login;
  975. +       struct {
  976. +               char *hostname;
  977. +               signed int port;
  978. +       } hostport;
  979. +       char *path;
  980. +
  981. +       ssize_t num_parameters;
  982. +       url_parser_name_value *parameters;
  983. +} url_parser_context;
  984. +
  985. +/* Prototypes */
  986. +url_parser_context *url_parser_create_context(const char *in_url, unsigned int flags);
  987. +int url_parser_parse(url_parser_context *uctx);
  988. +void url_parser_free_context(url_parser_context *c);
  989. +
  990. +#endif /* !__URLPARSER1_H__ */
  991. diff --git a/utils/mount/utils.c b/utils/mount/utils.c
  992. index b7562a47..3d55e997 100644
  993. --- a/utils/mount/utils.c
  994. +++ b/utils/mount/utils.c
  995. @@ -28,6 +28,7 @@
  996.  #include <unistd.h>
  997.  #include <sys/types.h>
  998.  #include <sys/stat.h>
  999. +#include <iconv.h>
  1000.  
  1001.  #include "sockaddr.h"
  1002.  #include "nfs_mount.h"
  1003. @@ -173,3 +174,157 @@ int nfs_umount23(const char *devname, char *string)
  1004.         free(dirname);
  1005.         return result;
  1006.  }
  1007. +
  1008. +/* Convert UTF-8 string to multibyte string in the current locale */
  1009. +char *utf8str2mbstr(const char *utf8_str)
  1010. +{
  1011. +       iconv_t cd;
  1012. +
  1013. +       cd = iconv_open("", "UTF-8");
  1014. +       if (cd == (iconv_t)-1) {
  1015. +               perror("utf8str2mbstr: iconv_open failed");
  1016. +               return NULL;
  1017. +       }
  1018. +
  1019. +       size_t inbytesleft = strlen(utf8_str);
  1020. +       char *inbuf = (char *)utf8_str;
  1021. +       size_t outbytesleft = inbytesleft*4+1;
  1022. +       char *outbuf = malloc(outbytesleft);
  1023. +       char *outbuf_orig = outbuf;
  1024. +
  1025. +       if (!outbuf) {
  1026. +               perror("utf8str2mbstr: out of memory");
  1027. +               (void)iconv_close(cd);
  1028. +               return NULL;
  1029. +       }
  1030. +
  1031. +       int ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
  1032. +       if (ret == -1) {
  1033. +               perror("utf8str2mbstr: iconv() failed");
  1034. +               free(outbuf_orig);
  1035. +               (void)iconv_close(cd);
  1036. +               return NULL;
  1037. +       }
  1038. +
  1039. +       *outbuf = '\0';
  1040. +
  1041. +       (void)iconv_close(cd);
  1042. +       return outbuf_orig;
  1043. +}
  1044. +
  1045. +/* fixme: We should use |bool|! */
  1046. +int is_spec_nfs_url(const char *spec)
  1047. +{
  1048. +       return (!strncmp(spec, "nfs://", 6));
  1049. +}
  1050. +
  1051. +int mount_parse_nfs_url(const char *spec, parsed_nfs_url *pnu)
  1052. +{
  1053. +       int result = 1;
  1054. +       url_parser_context *uctx = NULL;
  1055. +
  1056. +       (void)memset(pnu, 0, sizeof(parsed_nfs_url));
  1057. +       pnu->mount_params.read_only = TRIS_BOOL_NOT_SET;
  1058. +
  1059. +       uctx = url_parser_create_context(spec, 0);
  1060. +       if (!uctx) {
  1061. +               nfs_error(_("%s: out of memory"),
  1062. +                       progname);
  1063. +               result = 1;
  1064. +               goto done;
  1065. +       }
  1066. +
  1067. +       if (url_parser_parse(uctx) < 0) {
  1068. +               nfs_error(_("%s: Error parsing nfs://-URL."),
  1069. +                       progname);
  1070. +               result = 1;
  1071. +               goto done;
  1072. +       }
  1073. +       if (uctx->login.username || uctx->login.passwd) {
  1074. +               nfs_error(_("%s: Username/Password are not defined for nfs://-URL."),
  1075. +                       progname);
  1076. +               result = 1;
  1077. +               goto done;
  1078. +       }
  1079. +       if (!uctx->path) {
  1080. +               nfs_error(_("%s: Path missing in nfs://-URL."),
  1081. +                       progname);
  1082. +               result = 1;
  1083. +               goto done;
  1084. +       }
  1085. +       if (uctx->path[0] != '/') {
  1086. +               nfs_error(_("%s: Relative nfs://-URLs are not supported."),
  1087. +                       progname);
  1088. +               result = 1;
  1089. +               goto done;
  1090. +       }
  1091. +
  1092. +       if (uctx->num_parameters > 0) {
  1093. +               int pi;
  1094. +               const char *pname;
  1095. +               const char *pvalue;
  1096. +
  1097. +               /*
  1098. +                * Values added here based on URL parameters
  1099. +                * should be added the front of the list of options,
  1100. +                * so users can override the nfs://-URL given default.
  1101. +                */
  1102. +               for (pi = 0; pi < uctx->num_parameters ; pi++) {
  1103. +                       pname = uctx->parameters[pi].name;
  1104. +                       pvalue = uctx->parameters[pi].value;
  1105. +
  1106. +                       if (!strcmp(pname, "rw")) {
  1107. +                               if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
  1108. +                                       pnu->mount_params.read_only = TRIS_BOOL_FALSE;
  1109. +                               }
  1110. +                               else if (!strcmp(pvalue, "0")) {
  1111. +                                       pnu->mount_params.read_only = TRIS_BOOL_TRUE;
  1112. +                               }
  1113. +                               else {
  1114. +                                       nfs_error(_("%s: Unsupported nfs://-URL "
  1115. +                                               "parameter '%s' value '%s'."),
  1116. +                                               progname, pname, pvalue);
  1117. +                                       result = 1;
  1118. +                                       goto done;
  1119. +                               }
  1120. +                       }
  1121. +                       else if (!strcmp(pname, "ro")) {
  1122. +                               if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
  1123. +                                       pnu->mount_params.read_only = TRIS_BOOL_TRUE;
  1124. +                               }
  1125. +                               else if (!strcmp(pvalue, "0")) {
  1126. +                                       pnu->mount_params.read_only = TRIS_BOOL_FALSE;
  1127. +                               }
  1128. +                               else {
  1129. +                                       nfs_error(_("%s: Unsupported nfs://-URL "
  1130. +                                               "parameter '%s' value '%s'."),
  1131. +                                               progname, pname, pvalue);
  1132. +                                       result = 1;
  1133. +                                       goto done;
  1134. +                               }
  1135. +                       }
  1136. +                       else {
  1137. +                               nfs_error(_("%s: Unsupported nfs://-URL "
  1138. +                                               "parameter '%s'."),
  1139. +                                       progname, pname);
  1140. +                               result = 1;
  1141. +                               goto done;
  1142. +                       }
  1143. +               }
  1144. +       }
  1145. +
  1146. +       result = 0;
  1147. +done:
  1148. +       if (result != 0) {
  1149. +               url_parser_free_context(uctx);
  1150. +               return 0;
  1151. +       }
  1152. +
  1153. +       pnu->uctx = uctx;
  1154. +       return 1;
  1155. +}
  1156. +
  1157. +void mount_free_parse_nfs_url(parsed_nfs_url *pnu)
  1158. +{
  1159. +       url_parser_free_context(pnu->uctx);
  1160. +}
  1161. diff --git a/utils/mount/utils.h b/utils/mount/utils.h
  1162. index 224918ae..465c0a5e 100644
  1163. --- a/utils/mount/utils.h
  1164. +++ b/utils/mount/utils.h
  1165. @@ -24,13 +24,36 @@
  1166.  #define _NFS_UTILS_MOUNT_UTILS_H
  1167.  
  1168.  #include "parse_opt.h"
  1169. +#include "urlparser1.h"
  1170.  
  1171. +/* Boolean with three states: { not_set, false, true */
  1172. +typedef signed char tristate_bool;
  1173. +#define TRIS_BOOL_NOT_SET (-1)
  1174. +#define TRIS_BOOL_TRUE (1)
  1175. +#define TRIS_BOOL_FALSE (0)
  1176. +
  1177. +#define TRIS_BOOL_GET_VAL(tsb, tsb_default) \
  1178. +       (((tsb)!=TRIS_BOOL_NOT_SET)?(tsb):(tsb_default))
  1179. +
  1180. +typedef struct _parsed_nfs_url {
  1181. +       url_parser_context *uctx;
  1182. +       struct {
  1183. +               tristate_bool read_only;
  1184. +       } mount_params;
  1185. +} parsed_nfs_url;
  1186. +
  1187. +/* Prototypes */
  1188.  int discover_nfs_mount_data_version(int *string_ver);
  1189.  void print_one(char *spec, char *node, char *type, char *opts);
  1190.  void mount_usage(void);
  1191.  void umount_usage(void);
  1192.  int chk_mountpoint(const char *mount_point);
  1193. +char *utf8str2mbstr(const char *utf8_str);
  1194. +int is_spec_nfs_url(const char *spec);
  1195.  
  1196.  int nfs_umount23(const char *devname, char *string);
  1197.  
  1198. +int mount_parse_nfs_url(const char *spec, parsed_nfs_url *pnu);
  1199. +void mount_free_parse_nfs_url(parsed_nfs_url *pnu);
  1200. +
  1201.  #endif /* !_NFS_UTILS_MOUNT_UTILS_H */
  1202. --
  1203. 2.30.2

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