pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


nfs-utils nfs://-URL support patch
Posted by Anonymous on Fri 1st Nov 2024 10:59
raw | new post
view followups (newest first): nfs-utils nfs://-URL support patch by Anonymous
modification of post by Anonymous (view diff)

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

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