[PATCH] mount.nfs4: Add support for nfs://-URLs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add support for RFC 2224-style nfs://-URLs as alternative to the
traditional hostname:/path+-o port=<tcp-port> notation,
providing standardised, extensible, single-string, crossplatform,
portable, Character-Encoding independent (e.g. mount point with
Japanese, Chinese, French etc. characters) and ASCII-compatible
descriptions of NFSv4 server resources (exports).

Reviewed-by: Martin Wege <martin.l.wege@xxxxxxxxx>
Signed-off-by: Marvin Wenzel <marvin.wenzel@xxxxxxxxx>
Signed-off-by: Cedric Blancher <cedric.blancher@xxxxxxxxx>
---
 utils/mount/Makefile.am  |   3 +-
 utils/mount/mount.c      |   3 +
 utils/mount/nfs4mount.c  |  69 +++++++-
 utils/mount/nfsmount.c   |  93 ++++++++--
 utils/mount/parse_dev.c  |  67 ++++++--
 utils/mount/stropts.c    |  96 ++++++++++-
 utils/mount/urlparser1.c | 358 +++++++++++++++++++++++++++++++++++++++
 utils/mount/urlparser1.h |  60 +++++++
 utils/mount/utils.c      | 155 +++++++++++++++++
 utils/mount/utils.h      |  23 +++
 10 files changed, 890 insertions(+), 37 deletions(-)
 create mode 100644 utils/mount/urlparser1.c
 create mode 100644 utils/mount/urlparser1.h

diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am
index 83a8ee1c..0e4cab3e 100644
--- a/utils/mount/Makefile.am
+++ b/utils/mount/Makefile.am
@@ -13,7 +13,8 @@ sbin_PROGRAMS = mount.nfs
 EXTRA_DIST = nfsmount.conf $(man8_MANS) $(man5_MANS)
 mount_common = error.c network.c token.c \
      parse_opt.c parse_dev.c \
-     nfsmount.c nfs4mount.c stropts.c\
+     nfsmount.c nfs4mount.c \
+     urlparser1.c urlparser1.h stropts.c \
      mount_constants.h error.h network.h token.h \
      parse_opt.h parse_dev.h \
      nfs4_mount.h stropts.h version.h \
diff --git a/utils/mount/mount.c b/utils/mount/mount.c
index b98f9e00..2ce6209d 100644
--- a/utils/mount/mount.c
+++ b/utils/mount/mount.c
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <locale.h>
 #include <sys/mount.h>
 #include <getopt.h>
 #include <mntent.h>
@@ -386,6 +387,8 @@ int main(int argc, char *argv[])
  char *extra_opts = NULL, *mount_opts = NULL;
  uid_t uid = getuid();

+ (void)setlocale(LC_ALL, "");
+
  progname = basename(argv[0]);

  nfs_mount_data_version = discover_nfs_mount_data_version(&string);
diff --git a/utils/mount/nfs4mount.c b/utils/mount/nfs4mount.c
index 0fe142a7..8e4fbf30 100644
--- a/utils/mount/nfs4mount.c
+++ b/utils/mount/nfs4mount.c
@@ -50,8 +50,10 @@
 #include "mount_constants.h"
 #include "nfs4_mount.h"
 #include "nfs_mount.h"
+#include "urlparser1.h"
 #include "error.h"
 #include "network.h"
+#include "utils.h"

 #if defined(VAR_LOCK_DIR)
 #define DEFAULT_DIR VAR_LOCK_DIR
@@ -182,7 +184,7 @@ int nfs4mount(const char *spec, const char *node, int flags,
  int num_flavour = 0;
  int ip_addr_in_opts = 0;

- char *hostname, *dirname, *old_opts;
+ char *hostname, *dirname, *mb_dirname = NULL, *old_opts;
  char new_opts[1024];
  char *opt, *opteq;
  char *s;
@@ -192,15 +194,66 @@ int nfs4mount(const char *spec, const char
*node, int flags,
  int retry;
  int retval = EX_FAIL;
  time_t timeout, t;
+ int nfs_port = NFS_PORT;
+ parsed_nfs_url pnu;
+
+ (void)memset(&pnu, 0, sizeof(parsed_nfs_url));

  if (strlen(spec) >= sizeof(hostdir)) {
  nfs_error(_("%s: excessively long host:dir argument\n"),
  progname);
  goto fail;
  }
- strcpy(hostdir, spec);
- if (parse_devname(hostdir, &hostname, &dirname))
- goto fail;
+
+ /*
+ * Support nfs://-URLS per RFC 2224 ("NFS URL
+ * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
+ * including custom port (nfs://hostname@port/path/...)
+ * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
+ * support
+ */
+ if (is_spec_nfs_url(spec)) {
+ if (!mount_parse_nfs_url(spec, &pnu)) {
+ goto fail;
+ }
+
+ /*
+ * |pnu.uctx->path| is in UTF-8, but we need the data
+ * in the current local locale's encoding, as mount(2)
+ * does not have something like a |MS_UTF8_SPEC| flag
+ * to indicate that the input path is in UTF-8,
+ * independently of the current locale
+ */
+ hostname = pnu.uctx->hostport.hostname;
+ dirname = mb_dirname = utf8str2mbstr(pnu.uctx->path);
+
+ (void)snprintf(hostdir, sizeof(hostdir), "%s:/%s",
+ hostname, dirname);
+ spec = hostdir;
+
+ if (pnu.uctx->hostport.port != -1) {
+ nfs_port = pnu.uctx->hostport.port;
+ }
+
+ /*
+ * Values added here based on URL parameters
+ * should be added the front of the list of options,
+ * so users can override the nfs://-URL given default.
+ *
+ * FIXME: We do not do that here for |MS_RDONLY|!
+ */
+ if (pnu.mount_params.read_only != TRIS_BOOL_NOT_SET) {
+ if (pnu.mount_params.read_only)
+ flags |= MS_RDONLY;
+ else
+ flags &= ~MS_RDONLY;
+ }
+        } else {
+ (void)strcpy(hostdir, spec);
+
+ if (parse_devname(hostdir, &hostname, &dirname))
+ goto fail;
+ }

  if (fill_ipv4_sockaddr(hostname, &server_addr))
  goto fail;
@@ -247,7 +300,7 @@ int nfs4mount(const char *spec, const char *node, int flags,
  /*
  * NFSv4 specifies that the default port should be 2049
  */
- server_addr.sin_port = htons(NFS_PORT);
+ server_addr.sin_port = htons(nfs_port);

  /* parse options */

@@ -474,8 +527,14 @@ int nfs4mount(const char *spec, const char *node,
int flags,
  }
  }

+ mount_free_parse_nfs_url(&pnu);
+ free(mb_dirname);
+
  return EX_SUCCESS;

 fail:
+ mount_free_parse_nfs_url(&pnu);
+ free(mb_dirname);
+
  return retval;
 }
diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c
index a1c92fe8..e61d718a 100644
--- a/utils/mount/nfsmount.c
+++ b/utils/mount/nfsmount.c
@@ -63,11 +63,13 @@
 #include "xcommon.h"
 #include "mount.h"
 #include "nfs_mount.h"
+#include "urlparser1.h"
 #include "mount_constants.h"
 #include "nls.h"
 #include "error.h"
 #include "network.h"
 #include "version.h"
+#include "utils.h"

 #ifdef HAVE_RPCSVC_NFS_PROT_H
 #include <rpcsvc/nfs_prot.h>
@@ -493,7 +495,7 @@ nfsmount(const char *spec, const char *node, int flags,
  char **extra_opts, int fake, int running_bg)
 {
  char hostdir[1024];
- char *hostname, *dirname, *old_opts, *mounthost = NULL;
+ char *hostname, *dirname, *mb_dirname = NULL, *old_opts, *mounthost = NULL;
  char new_opts[1024], cbuf[1024];
  static struct nfs_mount_data data;
  int val;
@@ -521,29 +523,79 @@ nfsmount(const char *spec, const char *node, int flags,
  time_t t;
  time_t prevt;
  time_t timeout;
+ int nfsurl_port = -1;
+ parsed_nfs_url pnu;
+
+ (void)memset(&pnu, 0, sizeof(parsed_nfs_url));

  if (strlen(spec) >= sizeof(hostdir)) {
  nfs_error(_("%s: excessively long host:dir argument"),
  progname);
  goto fail;
  }
- strcpy(hostdir, spec);
- if ((s = strchr(hostdir, ':'))) {
- hostname = hostdir;
- dirname = s + 1;
- *s = '\0';
- /* Ignore all but first hostname in replicated mounts
-    until they can be fully supported. (mack@xxxxxxx) */
- if ((s = strchr(hostdir, ','))) {
+
+ /*
+ * Support nfs://-URLS per RFC 2224 ("NFS URL
+ * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
+ * including custom port (nfs://hostname@port/path/...)
+ * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
+ * support
+ */
+ if (is_spec_nfs_url(spec)) {
+ if (!mount_parse_nfs_url(spec, &pnu)) {
+ goto fail;
+ }
+
+ /*
+ * |pnu.uctx->path| is in UTF-8, but we need the data
+ * in the current local locale's encoding, as mount(2)
+ * does not have something like a |MS_UTF8_SPEC| flag
+ * to indicate that the input path is in UTF-8,
+ * independently of the current locale
+ */
+ hostname = pnu.uctx->hostport.hostname;
+ dirname = mb_dirname = utf8str2mbstr(pnu.uctx->path);
+
+ (void)snprintf(hostdir, sizeof(hostdir), "%s:/%s",
+ hostname, dirname);
+ spec = hostdir;
+
+ if (pnu.uctx->hostport.port != -1) {
+ nfsurl_port = pnu.uctx->hostport.port;
+ }
+
+ /*
+ * Values added here based on URL parameters
+ * should be added the front of the list of options,
+ * so users can override the nfs://-URL given default.
+ *
+ * FIXME: We do not do that here for |MS_RDONLY|!
+ */
+ if (pnu.mount_params.read_only != TRIS_BOOL_NOT_SET) {
+ if (pnu.mount_params.read_only)
+ flags |= MS_RDONLY;
+ else
+ flags &= ~MS_RDONLY;
+ }
+        } else {
+ (void)strcpy(hostdir, spec);
+ if ((s = strchr(hostdir, ':'))) {
+ hostname = hostdir;
+ dirname = s + 1;
  *s = '\0';
- nfs_error(_("%s: warning: "
-   "multiple hostnames not supported"),
+ /* Ignore all but first hostname in replicated mounts
+    until they can be fully supported. (mack@xxxxxxx) */
+ if ((s = strchr(hostdir, ','))) {
+ *s = '\0';
+ nfs_error(_("%s: warning: "
+ "multiple hostnames not supported"),
  progname);
- }
- } else {
- nfs_error(_("%s: directory to mount not in host:dir format"),
+ }
+ } else {
+ nfs_error(_("%s: directory to mount not in host:dir format"),
  progname);
- goto fail;
+ goto fail;
+ }
  }

  if (!nfs_gethostbyname(hostname, nfs_saddr))
@@ -579,6 +631,14 @@ nfsmount(const char *spec, const char *node, int flags,
  memset(nfs_pmap, 0, sizeof(*nfs_pmap));
  nfs_pmap->pm_prog = NFS_PROGRAM;

+ if (nfsurl_port != -1) {
+ /*
+ * Set custom TCP port defined by a nfs://-URL here,
+ * so $ mount -o port ... # can be used to override
+ */
+ nfs_pmap->pm_port = nfsurl_port;
+ }
+
  /* parse options */
  new_opts[0] = 0;
  if (!parse_options(old_opts, &data, &bg, &retry, &mnt_server, &nfs_server,
@@ -863,10 +923,13 @@ noauth_flavors:
  }
  }

+ mount_free_parse_nfs_url(&pnu);
+
  return EX_SUCCESS;

  /* abort */
  fail:
+ mount_free_parse_nfs_url(&pnu);
  if (fsock != -1)
  close(fsock);
  return retval;
diff --git a/utils/mount/parse_dev.c b/utils/mount/parse_dev.c
index 2ade5d5d..d9f8cf59 100644
--- a/utils/mount/parse_dev.c
+++ b/utils/mount/parse_dev.c
@@ -27,6 +27,8 @@
 #include "xcommon.h"
 #include "nls.h"
 #include "parse_dev.h"
+#include "urlparser1.h"
+#include "utils.h"

 #ifndef NFS_MAXHOSTNAME
 #define NFS_MAXHOSTNAME (255)
@@ -179,17 +181,62 @@ static int nfs_parse_square_bracket(const char *dev,
 }

 /*
- * RFC 2224 says an NFS client must grok "public file handles" to
- * support NFS URLs.  Linux doesn't do that yet.  Print a somewhat
- * helpful error message in this case instead of pressing forward
- * with the mount request and failing with a cryptic error message
- * later.
+ * Support nfs://-URLS per RFC 2224 ("NFS URL
+ * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
+ * including port support (nfs://hostname@port/path/...)
  */
-static int nfs_parse_nfs_url(__attribute__((unused)) const char *dev,
-      __attribute__((unused)) char **hostname,
-      __attribute__((unused)) char **pathname)
+static int nfs_parse_nfs_url(const char *dev,
+      char **out_hostname,
+      char **out_pathname)
 {
- nfs_error(_("%s: NFS URLs are not supported"), progname);
+ parsed_nfs_url pnu;
+
+ if (out_hostname)
+ *out_hostname = NULL;
+ if (out_pathname)
+ *out_pathname = NULL;
+
+ /*
+ * Support nfs://-URLS per RFC 2224 ("NFS URL
+ * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
+ * including custom port (nfs://hostname@port/path/...)
+ * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
+ * support
+ */
+ if (!mount_parse_nfs_url(dev, &pnu)) {
+ goto fail;
+ }
+
+ if (pnu.uctx->hostport.port != -1) {
+ /* NOP here, unless we switch from hostname to hostport */
+ }
+
+ if (out_hostname)
+ *out_hostname = strdup(pnu.uctx->hostport.hostname);
+ if (out_pathname)
+ *out_pathname = utf8str2mbstr(pnu.uctx->path);
+
+ if (((out_hostname)?(*out_hostname == NULL):0) ||
+ ((out_pathname)?(*out_pathname == NULL):0)) {
+ nfs_error(_("%s: out of memory"),
+ progname);
+ goto fail;
+ }
+
+ mount_free_parse_nfs_url(&pnu);
+
+ return 1;
+
+fail:
+ mount_free_parse_nfs_url(&pnu);
+ if (out_hostname) {
+ free(*out_hostname);
+ *out_hostname = NULL;
+ }
+ if (out_pathname) {
+ free(*out_pathname);
+ *out_pathname = NULL;
+ }
  return 0;
 }

@@ -223,7 +270,7 @@ int nfs_parse_devname(const char *devname,
  return nfs_pdn_nomem_err();
  if (*dev == '[')
  result = nfs_parse_square_bracket(dev, hostname, pathname);
- else if (strncmp(dev, "nfs://", 6) == 0)
+ else if (is_spec_nfs_url(dev))
  result = nfs_parse_nfs_url(dev, hostname, pathname);
  else
  result = nfs_parse_simple_hostname(dev, hostname, pathname);
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 23f0a8c0..ad92ab78 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -42,6 +42,7 @@
 #include "nls.h"
 #include "nfsrpc.h"
 #include "mount_constants.h"
+#include "urlparser1.h"
 #include "stropts.h"
 #include "error.h"
 #include "network.h"
@@ -50,6 +51,7 @@
 #include "parse_dev.h"
 #include "conffile.h"
 #include "misc.h"
+#include "utils.h"

 #ifndef NFS_PROGRAM
 #define NFS_PROGRAM (100003)
@@ -643,24 +645,106 @@ static int nfs_sys_mount(struct nfsmount_info
*mi, struct mount_options *opts)
 {
  char *options = NULL;
  int result;
+ int nfs_port = 2049;

  if (mi->fake)
  return 1;

- if (po_join(opts, &options) == PO_FAILED) {
- errno = EIO;
- return 0;
- }
+ /*
+ * Support nfs://-URLS per RFC 2224 ("NFS URL
+ * SCHEME", see https://www.rfc-editor.org/rfc/rfc2224.html),
+ * including custom port (nfs://hostname@port/path/...)
+ * and URL parameter (e.g. nfs://.../?param1=val1&param2=val2
+ * support
+ */
+ if (is_spec_nfs_url(mi->spec)) {
+ parsed_nfs_url pnu;
+ char *mb_path;
+ char mount_source[1024];
+
+ if (!mount_parse_nfs_url(mi->spec, &pnu)) {
+ result = 1;
+ errno = EINVAL;
+ goto done;
+ }
+
+ /*
+ * |pnu.uctx->path| is in UTF-8, but we need the data
+ * in the current local locale's encoding, as mount(2)
+ * does not have something like a |MS_UTF8_SPEC| flag
+ * to indicate that the input path is in UTF-8,
+ * independently of the current locale
+ */
+ mb_path = utf8str2mbstr(pnu.uctx->path);
+ if (!mb_path) {
+ nfs_error(_("%s: Could not convert path to local encoding."),
+ progname);
+ mount_free_parse_nfs_url(&pnu);
+ result = 1;
+ errno = EINVAL;
+ goto done;
+ }
+
+ (void)snprintf(mount_source, sizeof(mount_source),
+ "%s:/%s",
+ pnu.uctx->hostport.hostname,
+ mb_path);
+ free(mb_path);
+
+ if (pnu.uctx->hostport.port != -1) {
+ nfs_port = pnu.uctx->hostport.port;
+ }

- result = mount(mi->spec, mi->node, mi->type,
+ /*
+ * Insert "port=" option with the value from the nfs://
+ * URL at the beginning of the list of options, so
+ * users can override it with $ mount.nfs4 -o port= #,
+ * e.g.
+ * $ mount.nfs4 -o port=1234 nfs://10.49.202.230:400//bigdisk /mnt4 #
+ * should use port 1234, and not port 400 as specified
+ * in the URL.
+ */
+ char portoptbuf[5+32+1];
+ (void)snprintf(portoptbuf, sizeof(portoptbuf), "port=%d", nfs_port);
+ (void)po_insert(opts, portoptbuf);
+
+ if (pnu.mount_params.read_only != TRIS_BOOL_NOT_SET) {
+ if (pnu.mount_params.read_only)
+ mi->flags |= MS_RDONLY;
+ else
+ mi->flags &= ~MS_RDONLY;
+ }
+
+ mount_free_parse_nfs_url(&pnu);
+
+ if (po_join(opts, &options) == PO_FAILED) {
+ errno = EIO;
+ result = 1;
+ goto done;
+ }
+
+ result = mount(mount_source, mi->node, mi->type,
+ mi->flags & ~(MS_USER|MS_USERS), options);
+ free(options);
+ } else {
+ if (po_join(opts, &options) == PO_FAILED) {
+ errno = EIO;
+ result = 1;
+ goto done;
+ }
+
+ result = mount(mi->spec, mi->node, mi->type,
  mi->flags & ~(MS_USER|MS_USERS), options);
- free(options);
+ free(options);
+ }

  if (verbose && result) {
  int save = errno;
  nfs_error(_("%s: mount(2): %s"), progname, strerror(save));
  errno = save;
  }
+
+done:
  return !result;
 }

diff --git a/utils/mount/urlparser1.c b/utils/mount/urlparser1.c
new file mode 100644
index 00000000..d4c6f339
--- /dev/null
+++ b/utils/mount/urlparser1.c
@@ -0,0 +1,358 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024 Roland Mainz <roland.mainz@xxxxxxxxxxx>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* urlparser1.c - simple URL parser */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#ifdef DBG_USE_WIDECHAR
+#include <wchar.h>
+#include <locale.h>
+#include <io.h>
+#include <fcntl.h>
+#endif /* DBG_USE_WIDECHAR */
+
+#include "urlparser1.h"
+
+typedef struct _url_parser_context_private {
+ url_parser_context c;
+
+ /* Private data */
+ char *parameter_string_buff;
+} url_parser_context_private;
+
+#define MAX_URL_PARAMETERS 256
+
+/*
+ * Original extended regular expression:
+ *
+ * "^"
+ * "(.+?)" // scheme
+ * "://" // '://'
+ * "(" // login
+ * "(?:"
+ * "(.+?)" // user (optional)
+ * "(?::(.+))?" // password (optional)
+ * "@"
+ * ")?"
+ * "(" // hostport
+ * "(.+?)" // host
+ * "(?::([[:digit:]]+))?" // port (optional)
+ * ")"
+ * ")"
+ * "(?:/(.*?))?" // path (optional)
+ * "(?:\?(.*?))?" // URL parameters (optional)
+ * "$"
+ */
+
+#define DBGNULLSTR(s) (((s)!=NULL)?(s):"<NULL>")
+#if 0 || defined(TEST_URLPARSER)
+#define D(x) x
+#else
+#define D(x)
+#endif
+
+#ifdef DBG_USE_WIDECHAR
+/*
+ * Use wide-char APIs on WIN32, otherwise we cannot output
+ * Japanese/Chinese/etc correctly
+ */
+#define DBG_PUTS(str, fp) fputws(L"" str, (fp))
+#define DBG_PUTC(c, fp) fputwc(btowc(c), (fp))
+#define DBG_PRINTF(fp, fmt, ...) fwprintf((fp), L"" fmt, __VA_ARGS__)
+#else
+#define DBG_PUTS(str, fp) fputs((str), (fp))
+#define DBG_PUTC(c, fp) fputc((c), (fp))
+#define DBG_PRINTF(fp, fmt, ...) fprintf((fp), fmt, __VA_ARGS__)
+#endif /* DBG_USE_WIDECHAR */
+
+static
+void urldecodestr(char *outbuff, const char *buffer, size_t len)
+{
+ size_t i, j;
+
+ for (i = j = 0 ; i < len ; ) {
+ switch (buffer[i]) {
+ case '%':
+ if ((i + 2) < len) {
+ if (isxdigit((int)buffer[i+1]) && isxdigit((int)buffer[i+2])) {
+ const char hexstr[3] = {
+ buffer[i+1],
+ buffer[i+2],
+ '\0'
+ };
+ outbuff[j++] = (unsigned char)strtol(hexstr, NULL, 16);
+ i += 3;
+ } else {
+ /* invalid hex digit */
+ outbuff[j++] = buffer[i];
+ i++;
+ }
+ } else {
+ /* incomplete hex digit */
+ outbuff[j++] = buffer[i];
+ i++;
+ }
+ break;
+ case '+':
+ outbuff[j++] = ' ';
+ i++;
+ break;
+ default:
+ outbuff[j++] = buffer[i++];
+ break;
+ }
+ }
+
+ outbuff[j] = '\0';
+}
+
+url_parser_context *url_parser_create_context(const char *in_url,
unsigned int flags)
+{
+ url_parser_context_private *uctx;
+ char *s;
+ size_t in_url_len;
+ size_t context_len;
+
+ /* |flags| is for future extensions */
+ (void)flags;
+
+ if (!in_url)
+ return NULL;
+
+ in_url_len = strlen(in_url);
+
+ context_len = sizeof(url_parser_context_private) +
+ ((in_url_len+1)*6) +
+ (sizeof(url_parser_name_value)*MAX_URL_PARAMETERS)+sizeof(void*);
+ uctx = malloc(context_len);
+ if (!uctx)
+ return NULL;
+
+ s = (void *)(uctx+1);
+ uctx->c.in_url = s; s+= in_url_len+1;
+ (void)strcpy(uctx->c.in_url, in_url);
+ uctx->c.scheme = s; s+= in_url_len+1;
+ uctx->c.login.username = s; s+= in_url_len+1;
+ uctx->c.hostport.hostname = s; s+= in_url_len+1;
+ uctx->c.path = s; s+= in_url_len+1;
+ uctx->c.hostport.port = -1;
+ uctx->c.num_parameters = -1;
+ uctx->c.parameters = (void *)s; s+=
(sizeof(url_parser_name_value)*MAX_URL_PARAMETERS)+sizeof(void*);
+ uctx->parameter_string_buff = s; s+= in_url_len+1;
+
+ return &uctx->c;
+}
+
+int url_parser_parse(url_parser_context *ctx)
+{
+ url_parser_context_private *uctx = (url_parser_context_private *)ctx;
+
+ D((void)DBG_PRINTF(stderr, "## parser in_url='%s'\n", uctx->c.in_url));
+
+ char *s;
+ const char *urlstr = uctx->c.in_url;
+ size_t slen;
+
+ s = strstr(urlstr, "://");
+ if (!s) {
+ D((void)DBG_PUTS("url_parser: Not an URL\n", stderr));
+ return -1;
+ }
+
+ slen = s-urlstr;
+ (void)memcpy(uctx->c.scheme, urlstr, slen);
+ uctx->c.scheme[slen] = '\0';
+ urlstr += slen + 3;
+
+ D((void)DBG_PRINTF(stdout, "scheme='%s', rest='%s'\n",
uctx->c.scheme, urlstr));
+
+ s = strstr(urlstr, "@");
+ if (s) {
+ /* URL has user/password */
+ slen = s-urlstr;
+ urldecodestr(uctx->c.login.username, urlstr, slen);
+ urlstr += slen + 1;
+
+ s = strstr(uctx->c.login.username, ":");
+ if (s) {
+ /* found passwd */
+ uctx->c.login.passwd = s+1;
+ *s = '\0';
+ }
+ else {
+ uctx->c.login.passwd = NULL;
+ }
+
+ /* catch password-only URLs */
+ if (uctx->c.login.username[0] == '\0')
+ uctx->c.login.username = NULL;
+ }
+ else {
+ uctx->c.login.username = NULL;
+ uctx->c.login.passwd = NULL;
+ }
+
+ D((void)DBG_PRINTF(stdout, "login='%s', passwd='%s', rest='%s'\n",
+ DBGNULLSTR(uctx->c.login.username),
+ DBGNULLSTR(uctx->c.login.passwd),
+ DBGNULLSTR(urlstr)));
+
+ char *raw_parameters;
+
+ uctx->c.num_parameters = 0;
+ raw_parameters = strstr(urlstr, "?");
+ /* Do we have a non-empty parameter string ? */
+ if (raw_parameters && (raw_parameters[1] != '\0')) {
+ *raw_parameters++ = '\0';
+ D((void)DBG_PRINTF(stdout, "raw parameters = '%s'\n", raw_parameters));
+
+ char *ps = raw_parameters;
+ char *pv; /* parameter value */
+ char *na; /* next '&' */
+ char *pb = uctx->parameter_string_buff;
+ char *pname;
+ char *pvalue;
+ ssize_t pi;
+
+ for (pi = 0; pi < MAX_URL_PARAMETERS ; pi++) {
+ pname = ps;
+
+ /*
+ * Handle parameters without value,
+ * e.g. "path?name1&name2=value2"
+ */
+ na = strstr(ps, "&");
+ pv = strstr(ps, "=");
+ if (pv && (na?(na > pv):true)) {
+ *pv++ = '\0';
+ pvalue = pv;
+ ps = pv;
+ }
+ else {
+ pvalue = NULL;
+ }
+
+ if (na) {
+ *na++ = '\0';
+ }
+
+ /* URLDecode parameter name */
+ urldecodestr(pb, pname, strlen(pname));
+ uctx->c.parameters[pi].name = pb;
+ pb += strlen(uctx->c.parameters[pi].name)+1;
+
+ /* URLDecode parameter value */
+ if (pvalue) {
+ urldecodestr(pb, pvalue, strlen(pvalue));
+ uctx->c.parameters[pi].value = pb;
+ pb += strlen(uctx->c.parameters[pi].value)+1;
+ }
+ else {
+ uctx->c.parameters[pi].value = NULL;
+ }
+
+ /* Next '&' ? */
+ if (!na)
+ break;
+
+ ps = na;
+ }
+
+ uctx->c.num_parameters = pi+1;
+ }
+
+ s = strstr(urlstr, "/");
+ if (s) {
+ /* URL has hostport */
+ slen = s-urlstr;
+ urldecodestr(uctx->c.hostport.hostname, urlstr, slen);
+ urlstr += slen + 1;
+
+ /*
+ * check for addresses within '[' and ']', like
+ * IPv6 addresses
+ */
+ s = uctx->c.hostport.hostname;
+ if (s[0] == '[')
+ s = strstr(s, "]");
+
+ if (s == NULL) {
+ D((void)DBG_PUTS("url_parser: Unmatched '[' in hostname\n", stderr));
+ return -1;
+ }
+
+ s = strstr(s, ":");
+ if (s) {
+ /* found port number */
+ uctx->c.hostport.port = atoi(s+1);
+ *s = '\0';
+ }
+ }
+ else {
+ (void)strcpy(uctx->c.hostport.hostname, urlstr);
+ uctx->c.path = NULL;
+ urlstr = NULL;
+ }
+
+ D(
+ (void)DBG_PRINTF(stdout,
+ "hostport='%s', port=%d, rest='%s', num_parameters=%d\n",
+ DBGNULLSTR(uctx->c.hostport.hostname),
+ uctx->c.hostport.port,
+ DBGNULLSTR(urlstr),
+ (int)uctx->c.num_parameters);
+ );
+
+
+ D(
+ ssize_t dpi;
+ for (dpi = 0 ; dpi < uctx->c.num_parameters ; dpi++) {
+ (void)DBG_PRINTF(stdout,
+ "param[%d]: name='%s'/value='%s'\n",
+ (int)dpi,
+ uctx->c.parameters[dpi].name,
+ DBGNULLSTR(uctx->c.parameters[dpi].value));
+ }
+ );
+
+ if (!urlstr) {
+ goto done;
+ }
+
+ urldecodestr(uctx->c.path, urlstr, strlen(urlstr));
+ D((void)DBG_PRINTF(stdout, "path='%s'\n", uctx->c.path));
+
+done:
+ return 0;
+}
+
+void url_parser_free_context(url_parser_context *c)
+{
+ free(c);
+}
diff --git a/utils/mount/urlparser1.h b/utils/mount/urlparser1.h
new file mode 100644
index 00000000..515eea9d
--- /dev/null
+++ b/utils/mount/urlparser1.h
@@ -0,0 +1,60 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2024 Roland Mainz <roland.mainz@xxxxxxxxxxx>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* urlparser1.h - header for simple URL parser */
+
+#ifndef __URLPARSER1_H__
+#define __URLPARSER1_H__ 1
+
+#include <stdlib.h>
+
+typedef struct _url_parser_name_value {
+ char *name;
+ char *value;
+} url_parser_name_value;
+
+typedef struct _url_parser_context {
+ char *in_url;
+
+ char *scheme;
+ struct {
+ char *username;
+ char *passwd;
+ } login;
+ struct {
+ char *hostname;
+ signed int port;
+ } hostport;
+ char *path;
+
+ ssize_t num_parameters;
+ url_parser_name_value *parameters;
+} url_parser_context;
+
+/* Prototypes */
+url_parser_context *url_parser_create_context(const char *in_url,
unsigned int flags);
+int url_parser_parse(url_parser_context *uctx);
+void url_parser_free_context(url_parser_context *c);
+
+#endif /* !__URLPARSER1_H__ */
diff --git a/utils/mount/utils.c b/utils/mount/utils.c
index b7562a47..3d55e997 100644
--- a/utils/mount/utils.c
+++ b/utils/mount/utils.c
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <iconv.h>

 #include "sockaddr.h"
 #include "nfs_mount.h"
@@ -173,3 +174,157 @@ int nfs_umount23(const char *devname, char *string)
  free(dirname);
  return result;
 }
+
+/* Convert UTF-8 string to multibyte string in the current locale */
+char *utf8str2mbstr(const char *utf8_str)
+{
+ iconv_t cd;
+
+ cd = iconv_open("", "UTF-8");
+ if (cd == (iconv_t)-1) {
+ perror("utf8str2mbstr: iconv_open failed");
+ return NULL;
+ }
+
+ size_t inbytesleft = strlen(utf8_str);
+ char *inbuf = (char *)utf8_str;
+ size_t outbytesleft = inbytesleft*4+1;
+ char *outbuf = malloc(outbytesleft);
+ char *outbuf_orig = outbuf;
+
+ if (!outbuf) {
+ perror("utf8str2mbstr: out of memory");
+ (void)iconv_close(cd);
+ return NULL;
+ }
+
+ int ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ if (ret == -1) {
+ perror("utf8str2mbstr: iconv() failed");
+ free(outbuf_orig);
+ (void)iconv_close(cd);
+ return NULL;
+ }
+
+ *outbuf = '\0';
+
+ (void)iconv_close(cd);
+ return outbuf_orig;
+}
+
+/* fixme: We should use |bool|! */
+int is_spec_nfs_url(const char *spec)
+{
+ return (!strncmp(spec, "nfs://", 6));
+}
+
+int mount_parse_nfs_url(const char *spec, parsed_nfs_url *pnu)
+{
+ int result = 1;
+ url_parser_context *uctx = NULL;
+
+ (void)memset(pnu, 0, sizeof(parsed_nfs_url));
+ pnu->mount_params.read_only = TRIS_BOOL_NOT_SET;
+
+ uctx = url_parser_create_context(spec, 0);
+ if (!uctx) {
+ nfs_error(_("%s: out of memory"),
+ progname);
+ result = 1;
+ goto done;
+ }
+
+ if (url_parser_parse(uctx) < 0) {
+ nfs_error(_("%s: Error parsing nfs://-URL."),
+ progname);
+ result = 1;
+ goto done;
+ }
+ if (uctx->login.username || uctx->login.passwd) {
+ nfs_error(_("%s: Username/Password are not defined for nfs://-URL."),
+ progname);
+ result = 1;
+ goto done;
+ }
+ if (!uctx->path) {
+ nfs_error(_("%s: Path missing in nfs://-URL."),
+ progname);
+ result = 1;
+ goto done;
+ }
+ if (uctx->path[0] != '/') {
+ nfs_error(_("%s: Relative nfs://-URLs are not supported."),
+ progname);
+ result = 1;
+ goto done;
+ }
+
+ if (uctx->num_parameters > 0) {
+ int pi;
+ const char *pname;
+ const char *pvalue;
+
+ /*
+ * Values added here based on URL parameters
+ * should be added the front of the list of options,
+ * so users can override the nfs://-URL given default.
+ */
+ for (pi = 0; pi < uctx->num_parameters ; pi++) {
+ pname = uctx->parameters[pi].name;
+ pvalue = uctx->parameters[pi].value;
+
+ if (!strcmp(pname, "rw")) {
+ if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
+ pnu->mount_params.read_only = TRIS_BOOL_FALSE;
+ }
+ else if (!strcmp(pvalue, "0")) {
+ pnu->mount_params.read_only = TRIS_BOOL_TRUE;
+ }
+ else {
+ nfs_error(_("%s: Unsupported nfs://-URL "
+ "parameter '%s' value '%s'."),
+ progname, pname, pvalue);
+ result = 1;
+ goto done;
+ }
+ }
+ else if (!strcmp(pname, "ro")) {
+ if ((pvalue == NULL) || (!strcmp(pvalue, "1"))) {
+ pnu->mount_params.read_only = TRIS_BOOL_TRUE;
+ }
+ else if (!strcmp(pvalue, "0")) {
+ pnu->mount_params.read_only = TRIS_BOOL_FALSE;
+ }
+ else {
+ nfs_error(_("%s: Unsupported nfs://-URL "
+ "parameter '%s' value '%s'."),
+ progname, pname, pvalue);
+ result = 1;
+ goto done;
+ }
+ }
+ else {
+ nfs_error(_("%s: Unsupported nfs://-URL "
+ "parameter '%s'."),
+ progname, pname);
+ result = 1;
+ goto done;
+ }
+ }
+ }
+
+ result = 0;
+done:
+ if (result != 0) {
+ url_parser_free_context(uctx);
+ return 0;
+ }
+
+ pnu->uctx = uctx;
+ return 1;
+}
+
+void mount_free_parse_nfs_url(parsed_nfs_url *pnu)
+{
+ url_parser_free_context(pnu->uctx);
+}
diff --git a/utils/mount/utils.h b/utils/mount/utils.h
index 224918ae..465c0a5e 100644
--- a/utils/mount/utils.h
+++ b/utils/mount/utils.h
@@ -24,13 +24,36 @@
 #define _NFS_UTILS_MOUNT_UTILS_H

 #include "parse_opt.h"
+#include "urlparser1.h"

+/* Boolean with three states: { not_set, false, true */
+typedef signed char tristate_bool;
+#define TRIS_BOOL_NOT_SET (-1)
+#define TRIS_BOOL_TRUE (1)
+#define TRIS_BOOL_FALSE (0)
+
+#define TRIS_BOOL_GET_VAL(tsb, tsb_default) \
+ (((tsb)!=TRIS_BOOL_NOT_SET)?(tsb):(tsb_default))
+
+typedef struct _parsed_nfs_url {
+ url_parser_context *uctx;
+ struct {
+ tristate_bool read_only;
+ } mount_params;
+} parsed_nfs_url;
+
+/* Prototypes */
 int discover_nfs_mount_data_version(int *string_ver);
 void print_one(char *spec, char *node, char *type, char *opts);
 void mount_usage(void);
 void umount_usage(void);
 int chk_mountpoint(const char *mount_point);
+char *utf8str2mbstr(const char *utf8_str);
+int is_spec_nfs_url(const char *spec);

 int nfs_umount23(const char *devname, char *string);

+int mount_parse_nfs_url(const char *spec, parsed_nfs_url *pnu);
+void mount_free_parse_nfs_url(parsed_nfs_url *pnu);
+
 #endif /* !_NFS_UTILS_MOUNT_UTILS_H */
-- 
2.30.2
---- snip ----

----

Bye,
Roland
-- 
  __ .  . __
 (o.\ \/ /.o) roland.mainz@xxxxxxxxxxx
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)

--000000000000ccb28f0628a0fd7d
Content-Type: application/octet-stream; 
	name="0001-mount.nfs4-Add-support-for-nfs-URLs_v2.patch"
Content-Disposition: attachment; 
	filename="0001-mount.nfs4-Add-support-for-nfs-URLs_v2.patch"
Content-Transfer-Encoding: base64
Content-ID: <f_m4da24re0>
X-Attachment-Id: f_m4da24re0

RnJvbSA3NjdlMWFhMDk2YmFjZDRkZDYwMGQ0NmNjYWFlZmJjNDdiYTg2M2JmIE1vbiBTZXAgMTcg
MDA6MDA6MDAgMjAwMQpGcm9tOiBSb2xhbmQgTWFpbnogPHJvbGFuZC5tYWluekBucnVic2lnLm9y
Zz4KRGF0ZTogRnJpLCA2IERlYyAyMDI0IDE1OjIyOjIzICswMTAwClN1YmplY3Q6IFtQQVRDSF0g
bW91bnQubmZzNDogQWRkIHN1cHBvcnQgZm9yIG5mczovLy1VUkxzCgpBZGQgc3VwcG9ydCBmb3Ig
UkZDIDIyMjQtc3R5bGUgbmZzOi8vLVVSTHMgYXMgYWx0ZXJuYXRpdmUgdG8gdGhlCnRyYWRpdGlv
bmFsIGhvc3RuYW1lOi9wYXRoKy1vIHBvcnQ9PHRjcC1wb3J0PiBub3RhdGlvbiwKcHJvdmlkaW5n
IHN0YW5kYXJkaXNlZCwgZXh0ZW5zaWJsZSwgc2luZ2xlLXN0cmluZywgY3Jvc3NwbGF0Zm9ybSwK
cG9ydGFibGUsIENoYXJhY3Rlci1FbmNvZGluZyBpbmRlcGVuZGVudCAoZS5nLiBtb3VudCBwb2lu
dCB3aXRoCkphcGFuZXNlLCBDaGluZXNlLCBGcmVuY2ggZXRjLiBjaGFyYWN0ZXJzKSBhbmQgQVND
SUktY29tcGF0aWJsZQpkZXNjcmlwdGlvbnMgb2YgTkZTdjQgc2VydmVyIHJlc291cmNlcyAoZXhw
b3J0cykuCgpSZXZpZXdlZC1ieTogTWFydGluIFdlZ2UgPG1hcnRpbi5sLndlZ2VAZ21haWwuY29t
PgpTaWduZWQtb2ZmLWJ5OiBNYXJ2aW4gV2VuemVsIDxtYXJ2aW4ud2VuemVsQHJvdmVtYS5kZT4K
U2lnbmVkLW9mZi1ieTogQ2VkcmljIEJsYW5jaGVyIDxjZWRyaWMuYmxhbmNoZXJAZ21haWwuY29t
PgotLS0KIHV0aWxzL21vdW50L01ha2VmaWxlLmFtICB8ICAgMyArLQogdXRpbHMvbW91bnQvbW91
bnQuYyAgICAgIHwgICAzICsKIHV0aWxzL21vdW50L25mczRtb3VudC5jICB8ICA2OSArKysrKysr
LQogdXRpbHMvbW91bnQvbmZzbW91bnQuYyAgIHwgIDkzICsrKysrKysrLS0KIHV0aWxzL21vdW50
L3BhcnNlX2Rldi5jICB8ICA2NyArKysrKystLQogdXRpbHMvbW91bnQvc3Ryb3B0cy5jICAgIHwg
IDk2ICsrKysrKysrKystCiB1dGlscy9tb3VudC91cmxwYXJzZXIxLmMgfCAzNTggKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiB1dGlscy9tb3VudC91cmxwYXJzZXIxLmgg
fCAgNjAgKysrKysrKwogdXRpbHMvbW91bnQvdXRpbHMuYyAgICAgIHwgMTU1ICsrKysrKysrKysr
KysrKysrCiB1dGlscy9tb3VudC91dGlscy5oICAgICAgfCAgMjMgKysrCiAxMCBmaWxlcyBjaGFu
Z2VkLCA4OTAgaW5zZXJ0aW9ucygrKSwgMzcgZGVsZXRpb25zKC0pCiBjcmVhdGUgbW9kZSAxMDA2
NDQgdXRpbHMvbW91bnQvdXJscGFyc2VyMS5jCiBjcmVhdGUgbW9kZSAxMDA2NDQgdXRpbHMvbW91
bnQvdXJscGFyc2VyMS5oCgpkaWZmIC0tZ2l0IGEvdXRpbHMvbW91bnQvTWFrZWZpbGUuYW0gYi91
dGlscy9tb3VudC9NYWtlZmlsZS5hbQppbmRleCA4M2E4ZWUxYy4uMGU0Y2FiM2UgMTAwNjQ0Ci0t
LSBhL3V0aWxzL21vdW50L01ha2VmaWxlLmFtCisrKyBiL3V0aWxzL21vdW50L01ha2VmaWxlLmFt
CkBAIC0xMyw3ICsxMyw4IEBAIHNiaW5fUFJPR1JBTVMJPSBtb3VudC5uZnMKIEVYVFJBX0RJU1Qg
PSBuZnNtb3VudC5jb25mICQobWFuOF9NQU5TKSAkKG1hbjVfTUFOUykKIG1vdW50X2NvbW1vbiA9
IGVycm9yLmMgbmV0d29yay5jIHRva2VuLmMgXAogCQkgICAgcGFyc2Vfb3B0LmMgcGFyc2VfZGV2
LmMgXAotCQkgICAgbmZzbW91bnQuYyBuZnM0bW91bnQuYyBzdHJvcHRzLmNcCisJCSAgICBuZnNt
b3VudC5jIG5mczRtb3VudC5jIFwKKwkJICAgIHVybHBhcnNlcjEuYyB1cmxwYXJzZXIxLmggc3Ry
b3B0cy5jIFwKIAkJICAgIG1vdW50X2NvbnN0YW50cy5oIGVycm9yLmggbmV0d29yay5oIHRva2Vu
LmggXAogCQkgICAgcGFyc2Vfb3B0LmggcGFyc2VfZGV2LmggXAogCQkgICAgbmZzNF9tb3VudC5o
IHN0cm9wdHMuaCB2ZXJzaW9uLmggXApkaWZmIC0tZ2l0IGEvdXRpbHMvbW91bnQvbW91bnQuYyBi
L3V0aWxzL21vdW50L21vdW50LmMKaW5kZXggYjk4ZjllMDAuLjJjZTYyMDlkIDEwMDY0NAotLS0g
YS91dGlscy9tb3VudC9tb3VudC5jCisrKyBiL3V0aWxzL21vdW50L21vdW50LmMKQEAgLTI5LDYg
KzI5LDcgQEAKICNpbmNsdWRlIDxzdHJpbmcuaD4KICNpbmNsdWRlIDxlcnJuby5oPgogI2luY2x1
ZGUgPGZjbnRsLmg+CisjaW5jbHVkZSA8bG9jYWxlLmg+CiAjaW5jbHVkZSA8c3lzL21vdW50Lmg+
CiAjaW5jbHVkZSA8Z2V0b3B0Lmg+CiAjaW5jbHVkZSA8bW50ZW50Lmg+CkBAIC0zODYsNiArMzg3
LDggQEAgaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkKIAljaGFyICpleHRyYV9vcHRz
ID0gTlVMTCwgKm1vdW50X29wdHMgPSBOVUxMOwogCXVpZF90IHVpZCA9IGdldHVpZCgpOwogCisJ
KHZvaWQpc2V0bG9jYWxlKExDX0FMTCwgIiIpOworCiAJcHJvZ25hbWUgPSBiYXNlbmFtZShhcmd2
WzBdKTsKIAogCW5mc19tb3VudF9kYXRhX3ZlcnNpb24gPSBkaXNjb3Zlcl9uZnNfbW91bnRfZGF0
YV92ZXJzaW9uKCZzdHJpbmcpOwpkaWZmIC0tZ2l0IGEvdXRpbHMvbW91bnQvbmZzNG1vdW50LmMg
Yi91dGlscy9tb3VudC9uZnM0bW91bnQuYwppbmRleCAwZmUxNDJhNy4uOGU0ZmJmMzAgMTAwNjQ0
Ci0tLSBhL3V0aWxzL21vdW50L25mczRtb3VudC5jCisrKyBiL3V0aWxzL21vdW50L25mczRtb3Vu
dC5jCkBAIC01MCw4ICs1MCwxMCBAQAogI2luY2x1ZGUgIm1vdW50X2NvbnN0YW50cy5oIgogI2lu
Y2x1ZGUgIm5mczRfbW91bnQuaCIKICNpbmNsdWRlICJuZnNfbW91bnQuaCIKKyNpbmNsdWRlICJ1
cmxwYXJzZXIxLmgiCiAjaW5jbHVkZSAiZXJyb3IuaCIKICNpbmNsdWRlICJuZXR3b3JrLmgiCisj
aW5jbHVkZSAidXRpbHMuaCIKIAogI2lmIGRlZmluZWQoVkFSX0xPQ0tfRElSKQogI2RlZmluZSBE
RUZBVUxUX0RJUiBWQVJfTE9DS19ESVIKQEAgLTE4Miw3ICsxODQsNyBAQCBpbnQgbmZzNG1vdW50
KGNvbnN0IGNoYXIgKnNwZWMsIGNvbnN0IGNoYXIgKm5vZGUsIGludCBmbGFncywKIAlpbnQgbnVt
X2ZsYXZvdXIgPSAwOwogCWludCBpcF9hZGRyX2luX29wdHMgPSAwOwogCi0JY2hhciAqaG9zdG5h
bWUsICpkaXJuYW1lLCAqb2xkX29wdHM7CisJY2hhciAqaG9zdG5hbWUsICpkaXJuYW1lLCAqbWJf
ZGlybmFtZSA9IE5VTEwsICpvbGRfb3B0czsKIAljaGFyIG5ld19vcHRzWzEwMjRdOwogCWNoYXIg
Km9wdCwgKm9wdGVxOwogCWNoYXIgKnM7CkBAIC0xOTIsMTUgKzE5NCw2NiBAQCBpbnQgbmZzNG1v
dW50KGNvbnN0IGNoYXIgKnNwZWMsIGNvbnN0IGNoYXIgKm5vZGUsIGludCBmbGFncywKIAlpbnQg
cmV0cnk7CiAJaW50IHJldHZhbCA9IEVYX0ZBSUw7CiAJdGltZV90IHRpbWVvdXQsIHQ7CisJaW50
IG5mc19wb3J0ID0gTkZTX1BPUlQ7CisJcGFyc2VkX25mc191cmwgcG51OworCisJKHZvaWQpbWVt
c2V0KCZwbnUsIDAsIHNpemVvZihwYXJzZWRfbmZzX3VybCkpOwogCiAJaWYgKHN0cmxlbihzcGVj
KSA+PSBzaXplb2YoaG9zdGRpcikpIHsKIAkJbmZzX2Vycm9yKF8oIiVzOiBleGNlc3NpdmVseSBs
b25nIGhvc3Q6ZGlyIGFyZ3VtZW50XG4iKSwKIAkJCQlwcm9nbmFtZSk7CiAJCWdvdG8gZmFpbDsK
IAl9Ci0Jc3RyY3B5KGhvc3RkaXIsIHNwZWMpOwotCWlmIChwYXJzZV9kZXZuYW1lKGhvc3RkaXIs
ICZob3N0bmFtZSwgJmRpcm5hbWUpKQotCQlnb3RvIGZhaWw7CisKKwkvKgorCSAqIFN1cHBvcnQg
bmZzOi8vLVVSTFMgcGVyIFJGQyAyMjI0ICgiTkZTIFVSTAorCSAqIFNDSEVNRSIsIHNlZSBodHRw
czovL3d3dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjMjIyNC5odG1sKSwKKwkgKiBpbmNsdWRpbmcg
Y3VzdG9tIHBvcnQgKG5mczovL2hvc3RuYW1lQHBvcnQvcGF0aC8uLi4pCisJICogYW5kIFVSTCBw
YXJhbWV0ZXIgKGUuZy4gbmZzOi8vLi4uLz9wYXJhbTE9dmFsMSZwYXJhbTI9dmFsMgorCSAqIHN1
cHBvcnQKKwkgKi8KKwlpZiAoaXNfc3BlY19uZnNfdXJsKHNwZWMpKSB7CisJCWlmICghbW91bnRf
cGFyc2VfbmZzX3VybChzcGVjLCAmcG51KSkgeworCQkJZ290byBmYWlsOworCQl9CisKKwkJLyoK
KwkJICogfHBudS51Y3R4LT5wYXRofCBpcyBpbiBVVEYtOCwgYnV0IHdlIG5lZWQgdGhlIGRhdGEK
KwkJICogaW4gdGhlIGN1cnJlbnQgbG9jYWwgbG9jYWxlJ3MgZW5jb2RpbmcsIGFzIG1vdW50KDIp
CisJCSAqIGRvZXMgbm90IGhhdmUgc29tZXRoaW5nIGxpa2UgYSB8TVNfVVRGOF9TUEVDfCBmbGFn
CisJCSAqIHRvIGluZGljYXRlIHRoYXQgdGhlIGlucHV0IHBhdGggaXMgaW4gVVRGLTgsCisJCSAq
IGluZGVwZW5kZW50bHkgb2YgdGhlIGN1cnJlbnQgbG9jYWxlCisJCSAqLworCQlob3N0bmFtZSA9
IHBudS51Y3R4LT5ob3N0cG9ydC5ob3N0bmFtZTsKKwkJZGlybmFtZSA9IG1iX2Rpcm5hbWUgPSB1
dGY4c3RyMm1ic3RyKHBudS51Y3R4LT5wYXRoKTsKKworCQkodm9pZClzbnByaW50Zihob3N0ZGly
LCBzaXplb2YoaG9zdGRpciksICIlczovJXMiLAorCQkJaG9zdG5hbWUsIGRpcm5hbWUpOworCQlz
cGVjID0gaG9zdGRpcjsKKworCQlpZiAocG51LnVjdHgtPmhvc3Rwb3J0LnBvcnQgIT0gLTEpIHsK
KwkJCW5mc19wb3J0ID0gcG51LnVjdHgtPmhvc3Rwb3J0LnBvcnQ7CisJCX0KKworCQkvKgorCQkg
KiBWYWx1ZXMgYWRkZWQgaGVyZSBiYXNlZCBvbiBVUkwgcGFyYW1ldGVycworCQkgKiBzaG91bGQg
YmUgYWRkZWQgdGhlIGZyb250IG9mIHRoZSBsaXN0IG9mIG9wdGlvbnMsCisJCSAqIHNvIHVzZXJz
IGNhbiBvdmVycmlkZSB0aGUgbmZzOi8vLVVSTCBnaXZlbiBkZWZhdWx0LgorCQkgKgorCQkgKiBG
SVhNRTogV2UgZG8gbm90IGRvIHRoYXQgaGVyZSBmb3IgfE1TX1JET05MWXwhCisJCSAqLworCQlp
ZiAocG51Lm1vdW50X3BhcmFtcy5yZWFkX29ubHkgIT0gVFJJU19CT09MX05PVF9TRVQpIHsKKwkJ
CWlmIChwbnUubW91bnRfcGFyYW1zLnJlYWRfb25seSkKKwkJCQlmbGFncyB8PSBNU19SRE9OTFk7
CisJCQllbHNlCisJCQkJZmxhZ3MgJj0gfk1TX1JET05MWTsKKwkJfQorICAgICAgICB9IGVsc2Ug
eworCQkodm9pZClzdHJjcHkoaG9zdGRpciwgc3BlYyk7CisKKwkJaWYgKHBhcnNlX2Rldm5hbWUo
aG9zdGRpciwgJmhvc3RuYW1lLCAmZGlybmFtZSkpCisJCQlnb3RvIGZhaWw7CisJfQogCiAJaWYg
KGZpbGxfaXB2NF9zb2NrYWRkcihob3N0bmFtZSwgJnNlcnZlcl9hZGRyKSkKIAkJZ290byBmYWls
OwpAQCAtMjQ3LDcgKzMwMCw3IEBAIGludCBuZnM0bW91bnQoY29uc3QgY2hhciAqc3BlYywgY29u
c3QgY2hhciAqbm9kZSwgaW50IGZsYWdzLAogCS8qCiAJICogTkZTdjQgc3BlY2lmaWVzIHRoYXQg
dGhlIGRlZmF1bHQgcG9ydCBzaG91bGQgYmUgMjA0OQogCSAqLwotCXNlcnZlcl9hZGRyLnNpbl9w
b3J0ID0gaHRvbnMoTkZTX1BPUlQpOworCXNlcnZlcl9hZGRyLnNpbl9wb3J0ID0gaHRvbnMobmZz
X3BvcnQpOwogCiAJLyogcGFyc2Ugb3B0aW9ucyAqLwogCkBAIC00NzQsOCArNTI3LDE0IEBAIGlu
dCBuZnM0bW91bnQoY29uc3QgY2hhciAqc3BlYywgY29uc3QgY2hhciAqbm9kZSwgaW50IGZsYWdz
LAogCQl9CiAJfQogCisJbW91bnRfZnJlZV9wYXJzZV9uZnNfdXJsKCZwbnUpOworCWZyZWUobWJf
ZGlybmFtZSk7CisKIAlyZXR1cm4gRVhfU1VDQ0VTUzsKIAogZmFpbDoKKwltb3VudF9mcmVlX3Bh
cnNlX25mc191cmwoJnBudSk7CisJZnJlZShtYl9kaXJuYW1lKTsKKwogCXJldHVybiByZXR2YWw7
CiB9CmRpZmYgLS1naXQgYS91dGlscy9tb3VudC9uZnNtb3VudC5jIGIvdXRpbHMvbW91bnQvbmZz
bW91bnQuYwppbmRleCBhMWM5MmZlOC4uZTYxZDcxOGEgMTAwNjQ0Ci0tLSBhL3V0aWxzL21vdW50
L25mc21vdW50LmMKKysrIGIvdXRpbHMvbW91bnQvbmZzbW91bnQuYwpAQCAtNjMsMTEgKzYzLDEz
IEBACiAjaW5jbHVkZSAieGNvbW1vbi5oIgogI2luY2x1ZGUgIm1vdW50LmgiCiAjaW5jbHVkZSAi
bmZzX21vdW50LmgiCisjaW5jbHVkZSAidXJscGFyc2VyMS5oIgogI2luY2x1ZGUgIm1vdW50X2Nv
bnN0YW50cy5oIgogI2luY2x1ZGUgIm5scy5oIgogI2luY2x1ZGUgImVycm9yLmgiCiAjaW5jbHVk
ZSAibmV0d29yay5oIgogI2luY2x1ZGUgInZlcnNpb24uaCIKKyNpbmNsdWRlICJ1dGlscy5oIgog
CiAjaWZkZWYgSEFWRV9SUENTVkNfTkZTX1BST1RfSAogI2luY2x1ZGUgPHJwY3N2Yy9uZnNfcHJv
dC5oPgpAQCAtNDkzLDcgKzQ5NSw3IEBAIG5mc21vdW50KGNvbnN0IGNoYXIgKnNwZWMsIGNvbnN0
IGNoYXIgKm5vZGUsIGludCBmbGFncywKIAkgY2hhciAqKmV4dHJhX29wdHMsIGludCBmYWtlLCBp
bnQgcnVubmluZ19iZykKIHsKIAljaGFyIGhvc3RkaXJbMTAyNF07Ci0JY2hhciAqaG9zdG5hbWUs
ICpkaXJuYW1lLCAqb2xkX29wdHMsICptb3VudGhvc3QgPSBOVUxMOworCWNoYXIgKmhvc3RuYW1l
LCAqZGlybmFtZSwgKm1iX2Rpcm5hbWUgPSBOVUxMLCAqb2xkX29wdHMsICptb3VudGhvc3QgPSBO
VUxMOwogCWNoYXIgbmV3X29wdHNbMTAyNF0sIGNidWZbMTAyNF07CiAJc3RhdGljIHN0cnVjdCBu
ZnNfbW91bnRfZGF0YSBkYXRhOwogCWludCB2YWw7CkBAIC01MjEsMjkgKzUyMyw3OSBAQCBuZnNt
b3VudChjb25zdCBjaGFyICpzcGVjLCBjb25zdCBjaGFyICpub2RlLCBpbnQgZmxhZ3MsCiAJdGlt
ZV90IHQ7CiAJdGltZV90IHByZXZ0OwogCXRpbWVfdCB0aW1lb3V0OworCWludCBuZnN1cmxfcG9y
dCA9IC0xOworCXBhcnNlZF9uZnNfdXJsIHBudTsKKworCSh2b2lkKW1lbXNldCgmcG51LCAwLCBz
aXplb2YocGFyc2VkX25mc191cmwpKTsKIAogCWlmIChzdHJsZW4oc3BlYykgPj0gc2l6ZW9mKGhv
c3RkaXIpKSB7CiAJCW5mc19lcnJvcihfKCIlczogZXhjZXNzaXZlbHkgbG9uZyBob3N0OmRpciBh
cmd1bWVudCIpLAogCQkJCXByb2duYW1lKTsKIAkJZ290byBmYWlsOwogCX0KLQlzdHJjcHkoaG9z
dGRpciwgc3BlYyk7Ci0JaWYgKChzID0gc3RyY2hyKGhvc3RkaXIsICc6JykpKSB7Ci0JCWhvc3Ru
YW1lID0gaG9zdGRpcjsKLQkJZGlybmFtZSA9IHMgKyAxOwotCQkqcyA9ICdcMCc7Ci0JCS8qIEln
bm9yZSBhbGwgYnV0IGZpcnN0IGhvc3RuYW1lIGluIHJlcGxpY2F0ZWQgbW91bnRzCi0JCSAgIHVu
dGlsIHRoZXkgY2FuIGJlIGZ1bGx5IHN1cHBvcnRlZC4gKG1hY2tAc2dpLmNvbSkgKi8KLQkJaWYg
KChzID0gc3RyY2hyKGhvc3RkaXIsICcsJykpKSB7CisKKwkvKgorCSAqIFN1cHBvcnQgbmZzOi8v
LVVSTFMgcGVyIFJGQyAyMjI0ICgiTkZTIFVSTAorCSAqIFNDSEVNRSIsIHNlZSBodHRwczovL3d3
dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjMjIyNC5odG1sKSwKKwkgKiBpbmNsdWRpbmcgY3VzdG9t
IHBvcnQgKG5mczovL2hvc3RuYW1lQHBvcnQvcGF0aC8uLi4pCisJICogYW5kIFVSTCBwYXJhbWV0
ZXIgKGUuZy4gbmZzOi8vLi4uLz9wYXJhbTE9dmFsMSZwYXJhbTI9dmFsMgorCSAqIHN1cHBvcnQK
KwkgKi8KKwlpZiAoaXNfc3BlY19uZnNfdXJsKHNwZWMpKSB7CisJCWlmICghbW91bnRfcGFyc2Vf
bmZzX3VybChzcGVjLCAmcG51KSkgeworCQkJZ290byBmYWlsOworCQl9CisKKwkJLyoKKwkJICog
fHBudS51Y3R4LT5wYXRofCBpcyBpbiBVVEYtOCwgYnV0IHdlIG5lZWQgdGhlIGRhdGEKKwkJICog
aW4gdGhlIGN1cnJlbnQgbG9jYWwgbG9jYWxlJ3MgZW5jb2RpbmcsIGFzIG1vdW50KDIpCisJCSAq
IGRvZXMgbm90IGhhdmUgc29tZXRoaW5nIGxpa2UgYSB8TVNfVVRGOF9TUEVDfCBmbGFnCisJCSAq
IHRvIGluZGljYXRlIHRoYXQgdGhlIGlucHV0IHBhdGggaXMgaW4gVVRGLTgsCisJCSAqIGluZGVw
ZW5kZW50bHkgb2YgdGhlIGN1cnJlbnQgbG9jYWxlCisJCSAqLworCQlob3N0bmFtZSA9IHBudS51
Y3R4LT5ob3N0cG9ydC5ob3N0bmFtZTsKKwkJZGlybmFtZSA9IG1iX2Rpcm5hbWUgPSB1dGY4c3Ry
Mm1ic3RyKHBudS51Y3R4LT5wYXRoKTsKKworCQkodm9pZClzbnByaW50Zihob3N0ZGlyLCBzaXpl
b2YoaG9zdGRpciksICIlczovJXMiLAorCQkJaG9zdG5hbWUsIGRpcm5hbWUpOworCQlzcGVjID0g
aG9zdGRpcjsKKworCQlpZiAocG51LnVjdHgtPmhvc3Rwb3J0LnBvcnQgIT0gLTEpIHsKKwkJCW5m
c3VybF9wb3J0ID0gcG51LnVjdHgtPmhvc3Rwb3J0LnBvcnQ7CisJCX0KKworCQkvKgorCQkgKiBW
YWx1ZXMgYWRkZWQgaGVyZSBiYXNlZCBvbiBVUkwgcGFyYW1ldGVycworCQkgKiBzaG91bGQgYmUg
YWRkZWQgdGhlIGZyb250IG9mIHRoZSBsaXN0IG9mIG9wdGlvbnMsCisJCSAqIHNvIHVzZXJzIGNh
biBvdmVycmlkZSB0aGUgbmZzOi8vLVVSTCBnaXZlbiBkZWZhdWx0LgorCQkgKgorCQkgKiBGSVhN
RTogV2UgZG8gbm90IGRvIHRoYXQgaGVyZSBmb3IgfE1TX1JET05MWXwhCisJCSAqLworCQlpZiAo
cG51Lm1vdW50X3BhcmFtcy5yZWFkX29ubHkgIT0gVFJJU19CT09MX05PVF9TRVQpIHsKKwkJCWlm
IChwbnUubW91bnRfcGFyYW1zLnJlYWRfb25seSkKKwkJCQlmbGFncyB8PSBNU19SRE9OTFk7CisJ
CQllbHNlCisJCQkJZmxhZ3MgJj0gfk1TX1JET05MWTsKKwkJfQorICAgICAgICB9IGVsc2Ugewor
CQkodm9pZClzdHJjcHkoaG9zdGRpciwgc3BlYyk7CisJCWlmICgocyA9IHN0cmNocihob3N0ZGly
LCAnOicpKSkgeworCQkJaG9zdG5hbWUgPSBob3N0ZGlyOworCQkJZGlybmFtZSA9IHMgKyAxOwog
CQkJKnMgPSAnXDAnOwotCQkJbmZzX2Vycm9yKF8oIiVzOiB3YXJuaW5nOiAiCi0JCQkJICAibXVs
dGlwbGUgaG9zdG5hbWVzIG5vdCBzdXBwb3J0ZWQiKSwKKwkJCS8qIElnbm9yZSBhbGwgYnV0IGZp
cnN0IGhvc3RuYW1lIGluIHJlcGxpY2F0ZWQgbW91bnRzCisJCQkgICB1bnRpbCB0aGV5IGNhbiBi
ZSBmdWxseSBzdXBwb3J0ZWQuIChtYWNrQHNnaS5jb20pICovCisJCQlpZiAoKHMgPSBzdHJjaHIo
aG9zdGRpciwgJywnKSkpIHsKKwkJCQkqcyA9ICdcMCc7CisJCQkJbmZzX2Vycm9yKF8oIiVzOiB3
YXJuaW5nOiAiCisJCQkJCSJtdWx0aXBsZSBob3N0bmFtZXMgbm90IHN1cHBvcnRlZCIpLAogCQkJ
CQlwcm9nbmFtZSk7Ci0JCX0KLQl9IGVsc2UgewotCQluZnNfZXJyb3IoXygiJXM6IGRpcmVjdG9y
eSB0byBtb3VudCBub3QgaW4gaG9zdDpkaXIgZm9ybWF0IiksCisJCQl9CisJCX0gZWxzZSB7CisJ
CQluZnNfZXJyb3IoXygiJXM6IGRpcmVjdG9yeSB0byBtb3VudCBub3QgaW4gaG9zdDpkaXIgZm9y
bWF0IiksCiAJCQkJcHJvZ25hbWUpOwotCQlnb3RvIGZhaWw7CisJCQlnb3RvIGZhaWw7CisJCX0K
IAl9CiAKIAlpZiAoIW5mc19nZXRob3N0YnluYW1lKGhvc3RuYW1lLCBuZnNfc2FkZHIpKQpAQCAt
NTc5LDYgKzYzMSwxNCBAQCBuZnNtb3VudChjb25zdCBjaGFyICpzcGVjLCBjb25zdCBjaGFyICpu
b2RlLCBpbnQgZmxhZ3MsCiAJbWVtc2V0KG5mc19wbWFwLCAwLCBzaXplb2YoKm5mc19wbWFwKSk7
CiAJbmZzX3BtYXAtPnBtX3Byb2cgPSBORlNfUFJPR1JBTTsKIAorCWlmIChuZnN1cmxfcG9ydCAh
PSAtMSkgeworCQkvKgorCQkgKiBTZXQgY3VzdG9tIFRDUCBwb3J0IGRlZmluZWQgYnkgYSBuZnM6
Ly8tVVJMIGhlcmUsCisJCSAqIHNvICQgbW91bnQgLW8gcG9ydCAuLi4gIyBjYW4gYmUgdXNlZCB0
byBvdmVycmlkZQorCQkgKi8KKwkJbmZzX3BtYXAtPnBtX3BvcnQgPSBuZnN1cmxfcG9ydDsKKwl9
CisKIAkvKiBwYXJzZSBvcHRpb25zICovCiAJbmV3X29wdHNbMF0gPSAwOwogCWlmICghcGFyc2Vf
b3B0aW9ucyhvbGRfb3B0cywgJmRhdGEsICZiZywgJnJldHJ5LCAmbW50X3NlcnZlciwgJm5mc19z
ZXJ2ZXIsCkBAIC04NjMsMTAgKzkyMywxMyBAQCBub2F1dGhfZmxhdm9yczoKIAkJfQogCX0KIAor
CW1vdW50X2ZyZWVfcGFyc2VfbmZzX3VybCgmcG51KTsKKwogCXJldHVybiBFWF9TVUNDRVNTOwog
CiAJLyogYWJvcnQgKi8KICBmYWlsOgorCW1vdW50X2ZyZWVfcGFyc2VfbmZzX3VybCgmcG51KTsK
IAlpZiAoZnNvY2sgIT0gLTEpCiAJCWNsb3NlKGZzb2NrKTsKIAlyZXR1cm4gcmV0dmFsOwpkaWZm
IC0tZ2l0IGEvdXRpbHMvbW91bnQvcGFyc2VfZGV2LmMgYi91dGlscy9tb3VudC9wYXJzZV9kZXYu
YwppbmRleCAyYWRlNWQ1ZC4uZDlmOGNmNTkgMTAwNjQ0Ci0tLSBhL3V0aWxzL21vdW50L3BhcnNl
X2Rldi5jCisrKyBiL3V0aWxzL21vdW50L3BhcnNlX2Rldi5jCkBAIC0yNyw2ICsyNyw4IEBACiAj
aW5jbHVkZSAieGNvbW1vbi5oIgogI2luY2x1ZGUgIm5scy5oIgogI2luY2x1ZGUgInBhcnNlX2Rl
di5oIgorI2luY2x1ZGUgInVybHBhcnNlcjEuaCIKKyNpbmNsdWRlICJ1dGlscy5oIgogCiAjaWZu
ZGVmIE5GU19NQVhIT1NUTkFNRQogI2RlZmluZSBORlNfTUFYSE9TVE5BTUUJCSgyNTUpCkBAIC0x
NzksMTcgKzE4MSw2MiBAQCBzdGF0aWMgaW50IG5mc19wYXJzZV9zcXVhcmVfYnJhY2tldChjb25z
dCBjaGFyICpkZXYsCiB9CiAKIC8qCi0gKiBSRkMgMjIyNCBzYXlzIGFuIE5GUyBjbGllbnQgbXVz
dCBncm9rICJwdWJsaWMgZmlsZSBoYW5kbGVzIiB0bwotICogc3VwcG9ydCBORlMgVVJMcy4gIExp
bnV4IGRvZXNuJ3QgZG8gdGhhdCB5ZXQuICBQcmludCBhIHNvbWV3aGF0Ci0gKiBoZWxwZnVsIGVy
cm9yIG1lc3NhZ2UgaW4gdGhpcyBjYXNlIGluc3RlYWQgb2YgcHJlc3NpbmcgZm9yd2FyZAotICog
d2l0aCB0aGUgbW91bnQgcmVxdWVzdCBhbmQgZmFpbGluZyB3aXRoIGEgY3J5cHRpYyBlcnJvciBt
ZXNzYWdlCi0gKiBsYXRlci4KKyAqIFN1cHBvcnQgbmZzOi8vLVVSTFMgcGVyIFJGQyAyMjI0ICgi
TkZTIFVSTAorICogU0NIRU1FIiwgc2VlIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9y
ZmMyMjI0Lmh0bWwpLAorICogaW5jbHVkaW5nIHBvcnQgc3VwcG9ydCAobmZzOi8vaG9zdG5hbWVA
cG9ydC9wYXRoLy4uLikKICAqLwotc3RhdGljIGludCBuZnNfcGFyc2VfbmZzX3VybChfX2F0dHJp
YnV0ZV9fKCh1bnVzZWQpKSBjb25zdCBjaGFyICpkZXYsCi0JCQkgICAgIF9fYXR0cmlidXRlX18o
KHVudXNlZCkpIGNoYXIgKipob3N0bmFtZSwKLQkJCSAgICAgX19hdHRyaWJ1dGVfXygodW51c2Vk
KSkgY2hhciAqKnBhdGhuYW1lKQorc3RhdGljIGludCBuZnNfcGFyc2VfbmZzX3VybChjb25zdCBj
aGFyICpkZXYsCisJCQkgICAgIGNoYXIgKipvdXRfaG9zdG5hbWUsCisJCQkgICAgIGNoYXIgKipv
dXRfcGF0aG5hbWUpCiB7Ci0JbmZzX2Vycm9yKF8oIiVzOiBORlMgVVJMcyBhcmUgbm90IHN1cHBv
cnRlZCIpLCBwcm9nbmFtZSk7CisJcGFyc2VkX25mc191cmwgcG51OworCisJaWYgKG91dF9ob3N0
bmFtZSkKKwkJKm91dF9ob3N0bmFtZSA9IE5VTEw7CisJaWYgKG91dF9wYXRobmFtZSkKKwkJKm91
dF9wYXRobmFtZSA9IE5VTEw7CisKKwkvKgorCSAqIFN1cHBvcnQgbmZzOi8vLVVSTFMgcGVyIFJG
QyAyMjI0ICgiTkZTIFVSTAorCSAqIFNDSEVNRSIsIHNlZSBodHRwczovL3d3dy5yZmMtZWRpdG9y
Lm9yZy9yZmMvcmZjMjIyNC5odG1sKSwKKwkgKiBpbmNsdWRpbmcgY3VzdG9tIHBvcnQgKG5mczov
L2hvc3RuYW1lQHBvcnQvcGF0aC8uLi4pCisJICogYW5kIFVSTCBwYXJhbWV0ZXIgKGUuZy4gbmZz
Oi8vLi4uLz9wYXJhbTE9dmFsMSZwYXJhbTI9dmFsMgorCSAqIHN1cHBvcnQKKwkgKi8KKwlpZiAo
IW1vdW50X3BhcnNlX25mc191cmwoZGV2LCAmcG51KSkgeworCQlnb3RvIGZhaWw7CisJfQorCisJ
aWYgKHBudS51Y3R4LT5ob3N0cG9ydC5wb3J0ICE9IC0xKSB7CisJCS8qIE5PUCBoZXJlLCB1bmxl
c3Mgd2Ugc3dpdGNoIGZyb20gaG9zdG5hbWUgdG8gaG9zdHBvcnQgKi8KKwl9CisKKwlpZiAob3V0
X2hvc3RuYW1lKQorCQkqb3V0X2hvc3RuYW1lID0gc3RyZHVwKHBudS51Y3R4LT5ob3N0cG9ydC5o
b3N0bmFtZSk7CisJaWYgKG91dF9wYXRobmFtZSkKKwkJKm91dF9wYXRobmFtZSA9IHV0ZjhzdHIy
bWJzdHIocG51LnVjdHgtPnBhdGgpOworCisJaWYgKCgob3V0X2hvc3RuYW1lKT8oKm91dF9ob3N0
bmFtZSA9PSBOVUxMKTowKSB8fAorCQkoKG91dF9wYXRobmFtZSk/KCpvdXRfcGF0aG5hbWUgPT0g
TlVMTCk6MCkpIHsKKwkJbmZzX2Vycm9yKF8oIiVzOiBvdXQgb2YgbWVtb3J5IiksCisJCQlwcm9n
bmFtZSk7CisJCWdvdG8gZmFpbDsKKwl9CisKKwltb3VudF9mcmVlX3BhcnNlX25mc191cmwoJnBu
dSk7CisKKwlyZXR1cm4gMTsKKworZmFpbDoKKwltb3VudF9mcmVlX3BhcnNlX25mc191cmwoJnBu
dSk7CisJaWYgKG91dF9ob3N0bmFtZSkgeworCQlmcmVlKCpvdXRfaG9zdG5hbWUpOworCQkqb3V0
X2hvc3RuYW1lID0gTlVMTDsKKwl9CisJaWYgKG91dF9wYXRobmFtZSkgeworCQlmcmVlKCpvdXRf
cGF0aG5hbWUpOworCQkqb3V0X3BhdGhuYW1lID0gTlVMTDsKKwl9CiAJcmV0dXJuIDA7CiB9CiAK
QEAgLTIyMyw3ICsyNzAsNyBAQCBpbnQgbmZzX3BhcnNlX2Rldm5hbWUoY29uc3QgY2hhciAqZGV2
bmFtZSwKIAkJcmV0dXJuIG5mc19wZG5fbm9tZW1fZXJyKCk7CiAJaWYgKCpkZXYgPT0gJ1snKQog
CQlyZXN1bHQgPSBuZnNfcGFyc2Vfc3F1YXJlX2JyYWNrZXQoZGV2LCBob3N0bmFtZSwgcGF0aG5h
bWUpOwotCWVsc2UgaWYgKHN0cm5jbXAoZGV2LCAibmZzOi8vIiwgNikgPT0gMCkKKwllbHNlIGlm
IChpc19zcGVjX25mc191cmwoZGV2KSkKIAkJcmVzdWx0ID0gbmZzX3BhcnNlX25mc191cmwoZGV2
LCBob3N0bmFtZSwgcGF0aG5hbWUpOwogCWVsc2UKIAkJcmVzdWx0ID0gbmZzX3BhcnNlX3NpbXBs
ZV9ob3N0bmFtZShkZXYsIGhvc3RuYW1lLCBwYXRobmFtZSk7CmRpZmYgLS1naXQgYS91dGlscy9t
b3VudC9zdHJvcHRzLmMgYi91dGlscy9tb3VudC9zdHJvcHRzLmMKaW5kZXggMjNmMGE4YzAuLmFk
OTJhYjc4IDEwMDY0NAotLS0gYS91dGlscy9tb3VudC9zdHJvcHRzLmMKKysrIGIvdXRpbHMvbW91
bnQvc3Ryb3B0cy5jCkBAIC00Miw2ICs0Miw3IEBACiAjaW5jbHVkZSAibmxzLmgiCiAjaW5jbHVk
ZSAibmZzcnBjLmgiCiAjaW5jbHVkZSAibW91bnRfY29uc3RhbnRzLmgiCisjaW5jbHVkZSAidXJs
cGFyc2VyMS5oIgogI2luY2x1ZGUgInN0cm9wdHMuaCIKICNpbmNsdWRlICJlcnJvci5oIgogI2lu
Y2x1ZGUgIm5ldHdvcmsuaCIKQEAgLTUwLDYgKzUxLDcgQEAKICNpbmNsdWRlICJwYXJzZV9kZXYu
aCIKICNpbmNsdWRlICJjb25mZmlsZS5oIgogI2luY2x1ZGUgIm1pc2MuaCIKKyNpbmNsdWRlICJ1
dGlscy5oIgogCiAjaWZuZGVmIE5GU19QUk9HUkFNCiAjZGVmaW5lIE5GU19QUk9HUkFNCSgxMDAw
MDMpCkBAIC02NDMsMjQgKzY0NSwxMDYgQEAgc3RhdGljIGludCBuZnNfc3lzX21vdW50KHN0cnVj
dCBuZnNtb3VudF9pbmZvICptaSwgc3RydWN0IG1vdW50X29wdGlvbnMgKm9wdHMpCiB7CiAJY2hh
ciAqb3B0aW9ucyA9IE5VTEw7CiAJaW50IHJlc3VsdDsKKwlpbnQgbmZzX3BvcnQgPSAyMDQ5Owog
CiAJaWYgKG1pLT5mYWtlKQogCQlyZXR1cm4gMTsKIAotCWlmIChwb19qb2luKG9wdHMsICZvcHRp
b25zKSA9PSBQT19GQUlMRUQpIHsKLQkJZXJybm8gPSBFSU87Ci0JCXJldHVybiAwOwotCX0KKwkv
KgorCSAqIFN1cHBvcnQgbmZzOi8vLVVSTFMgcGVyIFJGQyAyMjI0ICgiTkZTIFVSTAorCSAqIFND
SEVNRSIsIHNlZSBodHRwczovL3d3dy5yZmMtZWRpdG9yLm9yZy9yZmMvcmZjMjIyNC5odG1sKSwK
KwkgKiBpbmNsdWRpbmcgY3VzdG9tIHBvcnQgKG5mczovL2hvc3RuYW1lQHBvcnQvcGF0aC8uLi4p
CisJICogYW5kIFVSTCBwYXJhbWV0ZXIgKGUuZy4gbmZzOi8vLi4uLz9wYXJhbTE9dmFsMSZwYXJh
bTI9dmFsMgorCSAqIHN1cHBvcnQKKwkgKi8KKwlpZiAoaXNfc3BlY19uZnNfdXJsKG1pLT5zcGVj
KSkgeworCQlwYXJzZWRfbmZzX3VybCBwbnU7CisJCWNoYXIgKm1iX3BhdGg7CisJCWNoYXIgbW91
bnRfc291cmNlWzEwMjRdOworCisJCWlmICghbW91bnRfcGFyc2VfbmZzX3VybChtaS0+c3BlYywg
JnBudSkpIHsKKwkJCXJlc3VsdCA9IDE7CisJCQllcnJubyA9IEVJTlZBTDsKKwkJCWdvdG8gZG9u
ZTsKKwkJfQorCisJCS8qCisJCSAqIHxwbnUudWN0eC0+cGF0aHwgaXMgaW4gVVRGLTgsIGJ1dCB3
ZSBuZWVkIHRoZSBkYXRhCisJCSAqIGluIHRoZSBjdXJyZW50IGxvY2FsIGxvY2FsZSdzIGVuY29k
aW5nLCBhcyBtb3VudCgyKQorCQkgKiBkb2VzIG5vdCBoYXZlIHNvbWV0aGluZyBsaWtlIGEgfE1T
X1VURjhfU1BFQ3wgZmxhZworCQkgKiB0byBpbmRpY2F0ZSB0aGF0IHRoZSBpbnB1dCBwYXRoIGlz
IGluIFVURi04LAorCQkgKiBpbmRlcGVuZGVudGx5IG9mIHRoZSBjdXJyZW50IGxvY2FsZQorCQkg
Ki8KKwkJbWJfcGF0aCA9IHV0ZjhzdHIybWJzdHIocG51LnVjdHgtPnBhdGgpOworCQlpZiAoIW1i
X3BhdGgpIHsKKwkJCW5mc19lcnJvcihfKCIlczogQ291bGQgbm90IGNvbnZlcnQgcGF0aCB0byBs
b2NhbCBlbmNvZGluZy4iKSwKKwkJCQlwcm9nbmFtZSk7CisJCQltb3VudF9mcmVlX3BhcnNlX25m
c191cmwoJnBudSk7CisJCQlyZXN1bHQgPSAxOworCQkJZXJybm8gPSBFSU5WQUw7CisJCQlnb3Rv
IGRvbmU7CisJCX0KKworCQkodm9pZClzbnByaW50Zihtb3VudF9zb3VyY2UsIHNpemVvZihtb3Vu
dF9zb3VyY2UpLAorCQkJIiVzOi8lcyIsCisJCQlwbnUudWN0eC0+aG9zdHBvcnQuaG9zdG5hbWUs
CisJCQltYl9wYXRoKTsKKwkJZnJlZShtYl9wYXRoKTsKKworCQlpZiAocG51LnVjdHgtPmhvc3Rw
b3J0LnBvcnQgIT0gLTEpIHsKKwkJCW5mc19wb3J0ID0gcG51LnVjdHgtPmhvc3Rwb3J0LnBvcnQ7
CisJCX0KIAotCXJlc3VsdCA9IG1vdW50KG1pLT5zcGVjLCBtaS0+bm9kZSwgbWktPnR5cGUsCisJ
CS8qCisJCSAqIEluc2VydCAicG9ydD0iIG9wdGlvbiB3aXRoIHRoZSB2YWx1ZSBmcm9tIHRoZSBu
ZnM6Ly8KKwkJICogVVJMIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpc3Qgb2Ygb3B0aW9ucywg
c28KKwkJICogdXNlcnMgY2FuIG92ZXJyaWRlIGl0IHdpdGggJCBtb3VudC5uZnM0IC1vIHBvcnQ9
ICMsCisJCSAqIGUuZy4KKwkJICogJCBtb3VudC5uZnM0IC1vIHBvcnQ9MTIzNCBuZnM6Ly8xMC40
OS4yMDIuMjMwOjQwMC8vYmlnZGlzayAvbW50NCAjCisJCSAqIHNob3VsZCB1c2UgcG9ydCAxMjM0
LCBhbmQgbm90IHBvcnQgNDAwIGFzIHNwZWNpZmllZAorCQkgKiBpbiB0aGUgVVJMLgorCQkgKi8K
KwkJY2hhciBwb3J0b3B0YnVmWzUrMzIrMV07CisJCSh2b2lkKXNucHJpbnRmKHBvcnRvcHRidWYs
IHNpemVvZihwb3J0b3B0YnVmKSwgInBvcnQ9JWQiLCBuZnNfcG9ydCk7CisJCSh2b2lkKXBvX2lu
c2VydChvcHRzLCBwb3J0b3B0YnVmKTsKKworCQlpZiAocG51Lm1vdW50X3BhcmFtcy5yZWFkX29u
bHkgIT0gVFJJU19CT09MX05PVF9TRVQpIHsKKwkJCWlmIChwbnUubW91bnRfcGFyYW1zLnJlYWRf
b25seSkKKwkJCQltaS0+ZmxhZ3MgfD0gTVNfUkRPTkxZOworCQkJZWxzZQorCQkJCW1pLT5mbGFn
cyAmPSB+TVNfUkRPTkxZOworCQl9CisKKwkJbW91bnRfZnJlZV9wYXJzZV9uZnNfdXJsKCZwbnUp
OworCisJCWlmIChwb19qb2luKG9wdHMsICZvcHRpb25zKSA9PSBQT19GQUlMRUQpIHsKKwkJCWVy
cm5vID0gRUlPOworCQkJcmVzdWx0ID0gMTsKKwkJCWdvdG8gZG9uZTsKKwkJfQorCisJCXJlc3Vs
dCA9IG1vdW50KG1vdW50X3NvdXJjZSwgbWktPm5vZGUsIG1pLT50eXBlLAorCQkJbWktPmZsYWdz
ICYgfihNU19VU0VSfE1TX1VTRVJTKSwgb3B0aW9ucyk7CisJCWZyZWUob3B0aW9ucyk7CisJfSBl
bHNlIHsKKwkJaWYgKHBvX2pvaW4ob3B0cywgJm9wdGlvbnMpID09IFBPX0ZBSUxFRCkgeworCQkJ
ZXJybm8gPSBFSU87CisJCQlyZXN1bHQgPSAxOworCQkJZ290byBkb25lOworCQl9CisKKwkJcmVz
dWx0ID0gbW91bnQobWktPnNwZWMsIG1pLT5ub2RlLCBtaS0+dHlwZSwKIAkJCW1pLT5mbGFncyAm
IH4oTVNfVVNFUnxNU19VU0VSUyksIG9wdGlvbnMpOwotCWZyZWUob3B0aW9ucyk7CisJCWZyZWUo
b3B0aW9ucyk7CisJfQogCiAJaWYgKHZlcmJvc2UgJiYgcmVzdWx0KSB7CiAJCWludCBzYXZlID0g
ZXJybm87CiAJCW5mc19lcnJvcihfKCIlczogbW91bnQoMik6ICVzIiksIHByb2duYW1lLCBzdHJl
cnJvcihzYXZlKSk7CiAJCWVycm5vID0gc2F2ZTsKIAl9CisKK2RvbmU6CiAJcmV0dXJuICFyZXN1
bHQ7CiB9CiAKZGlmZiAtLWdpdCBhL3V0aWxzL21vdW50L3VybHBhcnNlcjEuYyBiL3V0aWxzL21v
dW50L3VybHBhcnNlcjEuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMC4uZDRj
NmYzMzkKLS0tIC9kZXYvbnVsbAorKysgYi91dGlscy9tb3VudC91cmxwYXJzZXIxLmMKQEAgLTAs
MCArMSwzNTggQEAKKy8qCisgKiBNSVQgTGljZW5zZQorICoKKyAqIENvcHlyaWdodCAoYykgMjAy
NCBSb2xhbmQgTWFpbnogPHJvbGFuZC5tYWluekBucnVic2lnLm9yZz4KKyAqCisgKiBQZXJtaXNz
aW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRh
aW5pbmcgYSBjb3B5CisgKiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50
YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUiKSwgdG8gZGVhbAorICogaW4gdGhlIFNvZnR3YXJl
IHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJp
Z2h0cworICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRl
LCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbAorICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5k
IHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQg
dG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRo
ZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxs
IGJlIGluY2x1ZGVkIGluIGFsbAorICogY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9m
IHRoZSBTb2Z0d2FyZS4KKyAqCisgKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwg
V0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5D
TFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJ
VFksCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VN
RU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUKKyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERF
UlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElU
WSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBB
UklTSU5HIEZST00sCisgKiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FS
RSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRQorICogU09GVFdBUkUuCisgKi8K
KworLyogdXJscGFyc2VyMS5jIC0gc2ltcGxlIFVSTCBwYXJzZXIgKi8KKworI2luY2x1ZGUgPHN0
ZGxpYi5oPgorI2luY2x1ZGUgPHN0ZGJvb2wuaD4KKyNpbmNsdWRlIDxzdHJpbmcuaD4KKyNpbmNs
dWRlIDxjdHlwZS5oPgorI2luY2x1ZGUgPHN0ZGlvLmg+CisKKyNpZmRlZiBEQkdfVVNFX1dJREVD
SEFSCisjaW5jbHVkZSA8d2NoYXIuaD4KKyNpbmNsdWRlIDxsb2NhbGUuaD4KKyNpbmNsdWRlIDxp
by5oPgorI2luY2x1ZGUgPGZjbnRsLmg+CisjZW5kaWYgLyogREJHX1VTRV9XSURFQ0hBUiAqLwor
CisjaW5jbHVkZSAidXJscGFyc2VyMS5oIgorCit0eXBlZGVmIHN0cnVjdCBfdXJsX3BhcnNlcl9j
b250ZXh0X3ByaXZhdGUgeworCXVybF9wYXJzZXJfY29udGV4dCBjOworCisJLyogUHJpdmF0ZSBk
YXRhICovCisJY2hhciAqcGFyYW1ldGVyX3N0cmluZ19idWZmOworfSB1cmxfcGFyc2VyX2NvbnRl
eHRfcHJpdmF0ZTsKKworI2RlZmluZSBNQVhfVVJMX1BBUkFNRVRFUlMgMjU2CisKKy8qCisgKiBP
cmlnaW5hbCBleHRlbmRlZCByZWd1bGFyIGV4cHJlc3Npb246CisgKgorICogIl4iCisgKiAiKC4r
PykiCQkJCS8vIHNjaGVtZQorICogIjovLyIJCQkJLy8gJzovLycKKyAqICIoIgkJCQkJLy8gbG9n
aW4KKyAqCSIoPzoiCisgKgkiKC4rPykiCQkJCS8vIHVzZXIgKG9wdGlvbmFsKQorICoJCSIoPzo6
KC4rKSk/IgkJLy8gcGFzc3dvcmQgKG9wdGlvbmFsKQorICoJCSJAIgorICoJIik/IgorICoJIigi
CQkJCS8vIGhvc3Rwb3J0CisgKgkJIiguKz8pIgkJCS8vIGhvc3QKKyAqCQkiKD86OihbWzpkaWdp
dDpdXSspKT8iCS8vIHBvcnQgKG9wdGlvbmFsKQorICoJIikiCisgKiAiKSIKKyAqICIoPzovKC4q
PykpPyIJCQkvLyBwYXRoIChvcHRpb25hbCkKKyAqICIoPzpcPyguKj8pKT8iCQkJLy8gVVJMIHBh
cmFtZXRlcnMgKG9wdGlvbmFsKQorICogIiQiCisgKi8KKworI2RlZmluZSBEQkdOVUxMU1RSKHMp
ICgoKHMpIT1OVUxMKT8ocyk6IjxOVUxMPiIpCisjaWYgMCB8fCBkZWZpbmVkKFRFU1RfVVJMUEFS
U0VSKQorI2RlZmluZSBEKHgpIHgKKyNlbHNlCisjZGVmaW5lIEQoeCkKKyNlbmRpZgorCisjaWZk
ZWYgREJHX1VTRV9XSURFQ0hBUgorLyoKKyAqIFVzZSB3aWRlLWNoYXIgQVBJcyBvbiBXSU4zMiwg
b3RoZXJ3aXNlIHdlIGNhbm5vdCBvdXRwdXQKKyAqIEphcGFuZXNlL0NoaW5lc2UvZXRjIGNvcnJl
Y3RseQorICovCisjZGVmaW5lIERCR19QVVRTKHN0ciwgZnApCQlmcHV0d3MoTCIiIHN0ciwgKGZw
KSkKKyNkZWZpbmUgREJHX1BVVEMoYywgZnApCQkJZnB1dHdjKGJ0b3djKGMpLCAoZnApKQorI2Rl
ZmluZSBEQkdfUFJJTlRGKGZwLCBmbXQsIC4uLikJZndwcmludGYoKGZwKSwgTCIiIGZtdCwgX19W
QV9BUkdTX18pCisjZWxzZQorI2RlZmluZSBEQkdfUFVUUyhzdHIsIGZwKQkJZnB1dHMoKHN0ciks
IChmcCkpCisjZGVmaW5lIERCR19QVVRDKGMsIGZwKQkJCWZwdXRjKChjKSwgKGZwKSkKKyNkZWZp
bmUgREJHX1BSSU5URihmcCwgZm10LCAuLi4pCWZwcmludGYoKGZwKSwgZm10LCBfX1ZBX0FSR1Nf
XykKKyNlbmRpZiAvKiBEQkdfVVNFX1dJREVDSEFSICovCisKK3N0YXRpYwordm9pZCB1cmxkZWNv
ZGVzdHIoY2hhciAqb3V0YnVmZiwgY29uc3QgY2hhciAqYnVmZmVyLCBzaXplX3QgbGVuKQorewor
CXNpemVfdCBpLCBqOworCisJZm9yIChpID0gaiA9IDAgOyBpIDwgbGVuIDsgKSB7CisJCXN3aXRj
aCAoYnVmZmVyW2ldKSB7CisJCQljYXNlICclJzoKKwkJCQlpZiAoKGkgKyAyKSA8IGxlbikgewor
CQkJCQlpZiAoaXN4ZGlnaXQoKGludClidWZmZXJbaSsxXSkgJiYgaXN4ZGlnaXQoKGludClidWZm
ZXJbaSsyXSkpIHsKKwkJCQkJCWNvbnN0IGNoYXIgaGV4c3RyWzNdID0geworCQkJCQkJCWJ1ZmZl
cltpKzFdLAorCQkJCQkJCWJ1ZmZlcltpKzJdLAorCQkJCQkJCSdcMCcKKwkJCQkJCX07CisJCQkJ
CQlvdXRidWZmW2orK10gPSAodW5zaWduZWQgY2hhcilzdHJ0b2woaGV4c3RyLCBOVUxMLCAxNik7
CisJCQkJCQlpICs9IDM7CisJCQkJCX0gZWxzZSB7CisJCQkJCQkvKiBpbnZhbGlkIGhleCBkaWdp
dCAqLworCQkJCQkJb3V0YnVmZltqKytdID0gYnVmZmVyW2ldOworCQkJCQkJaSsrOworCQkJCQl9
CisJCQkJfSBlbHNlIHsKKwkJCQkJLyogaW5jb21wbGV0ZSBoZXggZGlnaXQgKi8KKwkJCQkJb3V0
YnVmZltqKytdID0gYnVmZmVyW2ldOworCQkJCQlpKys7CisJCQkJfQorCQkJCWJyZWFrOworCQkJ
Y2FzZSAnKyc6CisJCQkJb3V0YnVmZltqKytdID0gJyAnOworCQkJCWkrKzsKKwkJCQlicmVhazsK
KwkJCWRlZmF1bHQ6CisJCQkJb3V0YnVmZltqKytdID0gYnVmZmVyW2krK107CisJCQkJYnJlYWs7
CisJCX0KKwl9CisKKwlvdXRidWZmW2pdID0gJ1wwJzsKK30KKwordXJsX3BhcnNlcl9jb250ZXh0
ICp1cmxfcGFyc2VyX2NyZWF0ZV9jb250ZXh0KGNvbnN0IGNoYXIgKmluX3VybCwgdW5zaWduZWQg
aW50IGZsYWdzKQoreworCXVybF9wYXJzZXJfY29udGV4dF9wcml2YXRlICp1Y3R4OworCWNoYXIg
KnM7CisJc2l6ZV90IGluX3VybF9sZW47CisJc2l6ZV90IGNvbnRleHRfbGVuOworCisJLyogfGZs
YWdzfCBpcyBmb3IgZnV0dXJlIGV4dGVuc2lvbnMgKi8KKwkodm9pZClmbGFnczsKKworCWlmICgh
aW5fdXJsKQorCQlyZXR1cm4gTlVMTDsKKworCWluX3VybF9sZW4gPSBzdHJsZW4oaW5fdXJsKTsK
KworCWNvbnRleHRfbGVuID0gc2l6ZW9mKHVybF9wYXJzZXJfY29udGV4dF9wcml2YXRlKSArCisJ
CSgoaW5fdXJsX2xlbisxKSo2KSArCisJCShzaXplb2YodXJsX3BhcnNlcl9uYW1lX3ZhbHVlKSpN
QVhfVVJMX1BBUkFNRVRFUlMpK3NpemVvZih2b2lkKik7CisJdWN0eCA9IG1hbGxvYyhjb250ZXh0
X2xlbik7CisJaWYgKCF1Y3R4KQorCQlyZXR1cm4gTlVMTDsKKworCXMgPSAodm9pZCAqKSh1Y3R4
KzEpOworCXVjdHgtPmMuaW5fdXJsID0gczsJCXMrPSBpbl91cmxfbGVuKzE7CisJKHZvaWQpc3Ry
Y3B5KHVjdHgtPmMuaW5fdXJsLCBpbl91cmwpOworCXVjdHgtPmMuc2NoZW1lID0gczsJCXMrPSBp
bl91cmxfbGVuKzE7CisJdWN0eC0+Yy5sb2dpbi51c2VybmFtZSA9IHM7CXMrPSBpbl91cmxfbGVu
KzE7CisJdWN0eC0+Yy5ob3N0cG9ydC5ob3N0bmFtZSA9IHM7CXMrPSBpbl91cmxfbGVuKzE7CisJ
dWN0eC0+Yy5wYXRoID0gczsJCXMrPSBpbl91cmxfbGVuKzE7CisJdWN0eC0+Yy5ob3N0cG9ydC5w
b3J0ID0gLTE7CisJdWN0eC0+Yy5udW1fcGFyYW1ldGVycyA9IC0xOworCXVjdHgtPmMucGFyYW1l
dGVycyA9ICh2b2lkICopczsJCXMrPSAoc2l6ZW9mKHVybF9wYXJzZXJfbmFtZV92YWx1ZSkqTUFY
X1VSTF9QQVJBTUVURVJTKStzaXplb2Yodm9pZCopOworCXVjdHgtPnBhcmFtZXRlcl9zdHJpbmdf
YnVmZiA9IHM7CXMrPSBpbl91cmxfbGVuKzE7CisKKwlyZXR1cm4gJnVjdHgtPmM7Cit9CisKK2lu
dCB1cmxfcGFyc2VyX3BhcnNlKHVybF9wYXJzZXJfY29udGV4dCAqY3R4KQoreworCXVybF9wYXJz
ZXJfY29udGV4dF9wcml2YXRlICp1Y3R4ID0gKHVybF9wYXJzZXJfY29udGV4dF9wcml2YXRlICop
Y3R4OworCisJRCgodm9pZClEQkdfUFJJTlRGKHN0ZGVyciwgIiMjIHBhcnNlciBpbl91cmw9JyVz
J1xuIiwgdWN0eC0+Yy5pbl91cmwpKTsKKworCWNoYXIgKnM7CisJY29uc3QgY2hhciAqdXJsc3Ry
ID0gdWN0eC0+Yy5pbl91cmw7CisJc2l6ZV90IHNsZW47CisKKwlzID0gc3Ryc3RyKHVybHN0ciwg
IjovLyIpOworCWlmICghcykgeworCQlEKCh2b2lkKURCR19QVVRTKCJ1cmxfcGFyc2VyOiBOb3Qg
YW4gVVJMXG4iLCBzdGRlcnIpKTsKKwkJcmV0dXJuIC0xOworCX0KKworCXNsZW4gPSBzLXVybHN0
cjsKKwkodm9pZCltZW1jcHkodWN0eC0+Yy5zY2hlbWUsIHVybHN0ciwgc2xlbik7CisJdWN0eC0+
Yy5zY2hlbWVbc2xlbl0gPSAnXDAnOworCXVybHN0ciArPSBzbGVuICsgMzsKKworCUQoKHZvaWQp
REJHX1BSSU5URihzdGRvdXQsICJzY2hlbWU9JyVzJywgcmVzdD0nJXMnXG4iLCB1Y3R4LT5jLnNj
aGVtZSwgdXJsc3RyKSk7CisKKwlzID0gc3Ryc3RyKHVybHN0ciwgIkAiKTsKKwlpZiAocykgewor
CQkvKiBVUkwgaGFzIHVzZXIvcGFzc3dvcmQgKi8KKwkJc2xlbiA9IHMtdXJsc3RyOworCQl1cmxk
ZWNvZGVzdHIodWN0eC0+Yy5sb2dpbi51c2VybmFtZSwgdXJsc3RyLCBzbGVuKTsKKwkJdXJsc3Ry
ICs9IHNsZW4gKyAxOworCisJCXMgPSBzdHJzdHIodWN0eC0+Yy5sb2dpbi51c2VybmFtZSwgIjoi
KTsKKwkJaWYgKHMpIHsKKwkJCS8qIGZvdW5kIHBhc3N3ZCAqLworCQkJdWN0eC0+Yy5sb2dpbi5w
YXNzd2QgPSBzKzE7CisJCQkqcyA9ICdcMCc7CisJCX0KKwkJZWxzZSB7CisJCQl1Y3R4LT5jLmxv
Z2luLnBhc3N3ZCA9IE5VTEw7CisJCX0KKworCQkvKiBjYXRjaCBwYXNzd29yZC1vbmx5IFVSTHMg
Ki8KKwkJaWYgKHVjdHgtPmMubG9naW4udXNlcm5hbWVbMF0gPT0gJ1wwJykKKwkJCXVjdHgtPmMu
bG9naW4udXNlcm5hbWUgPSBOVUxMOworCX0KKwllbHNlIHsKKwkJdWN0eC0+Yy5sb2dpbi51c2Vy
bmFtZSA9IE5VTEw7CisJCXVjdHgtPmMubG9naW4ucGFzc3dkID0gTlVMTDsKKwl9CisKKwlEKCh2
b2lkKURCR19QUklOVEYoc3Rkb3V0LCAibG9naW49JyVzJywgcGFzc3dkPSclcycsIHJlc3Q9JyVz
J1xuIiwKKwkJREJHTlVMTFNUUih1Y3R4LT5jLmxvZ2luLnVzZXJuYW1lKSwKKwkJREJHTlVMTFNU
Uih1Y3R4LT5jLmxvZ2luLnBhc3N3ZCksCisJCURCR05VTExTVFIodXJsc3RyKSkpOworCisJY2hh
ciAqcmF3X3BhcmFtZXRlcnM7CisKKwl1Y3R4LT5jLm51bV9wYXJhbWV0ZXJzID0gMDsKKwlyYXdf
cGFyYW1ldGVycyA9IHN0cnN0cih1cmxzdHIsICI/Iik7CisJLyogRG8gd2UgaGF2ZSBhIG5vbi1l
bXB0eSBwYXJhbWV0ZXIgc3RyaW5nID8gKi8KKwlpZiAocmF3X3BhcmFtZXRlcnMgJiYgKHJhd19w
YXJhbWV0ZXJzWzFdICE9ICdcMCcpKSB7CisJCSpyYXdfcGFyYW1ldGVycysrID0gJ1wwJzsKKwkJ
RCgodm9pZClEQkdfUFJJTlRGKHN0ZG91dCwgInJhdyBwYXJhbWV0ZXJzID0gJyVzJ1xuIiwgcmF3
X3BhcmFtZXRlcnMpKTsKKworCQljaGFyICpwcyA9IHJhd19wYXJhbWV0ZXJzOworCQljaGFyICpw
djsgLyogcGFyYW1ldGVyIHZhbHVlICovCisJCWNoYXIgKm5hOyAvKiBuZXh0ICcmJyAqLworCQlj
aGFyICpwYiA9IHVjdHgtPnBhcmFtZXRlcl9zdHJpbmdfYnVmZjsKKwkJY2hhciAqcG5hbWU7CisJ
CWNoYXIgKnB2YWx1ZTsKKwkJc3NpemVfdCBwaTsKKworCQlmb3IgKHBpID0gMDsgcGkgPCBNQVhf
VVJMX1BBUkFNRVRFUlMgOyBwaSsrKSB7CisJCQlwbmFtZSA9IHBzOworCisJCQkvKgorCQkJICog
SGFuZGxlIHBhcmFtZXRlcnMgd2l0aG91dCB2YWx1ZSwKKwkJCSAqIGUuZy4gInBhdGg/bmFtZTEm
bmFtZTI9dmFsdWUyIgorCQkJICovCisJCQluYSA9IHN0cnN0cihwcywgIiYiKTsKKwkJCXB2ID0g
c3Ryc3RyKHBzLCAiPSIpOworCQkJaWYgKHB2ICYmIChuYT8obmEgPiBwdik6dHJ1ZSkpIHsKKwkJ
CQkqcHYrKyA9ICdcMCc7CisJCQkJcHZhbHVlID0gcHY7CisJCQkJcHMgPSBwdjsKKwkJCX0KKwkJ
CWVsc2UgeworCQkJCXB2YWx1ZSA9IE5VTEw7CisJCQl9CisKKwkJCWlmIChuYSkgeworCQkJCSpu
YSsrID0gJ1wwJzsKKwkJCX0KKworCQkJLyogVVJMRGVjb2RlIHBhcmFtZXRlciBuYW1lICovCisJ
CQl1cmxkZWNvZGVzdHIocGIsIHBuYW1lLCBzdHJsZW4ocG5hbWUpKTsKKwkJCXVjdHgtPmMucGFy
YW1ldGVyc1twaV0ubmFtZSA9IHBiOworCQkJcGIgKz0gc3RybGVuKHVjdHgtPmMucGFyYW1ldGVy
c1twaV0ubmFtZSkrMTsKKworCQkJLyogVVJMRGVjb2RlIHBhcmFtZXRlciB2YWx1ZSAqLworCQkJ
aWYgKHB2YWx1ZSkgeworCQkJCXVybGRlY29kZXN0cihwYiwgcHZhbHVlLCBzdHJsZW4ocHZhbHVl
KSk7CisJCQkJdWN0eC0+Yy5wYXJhbWV0ZXJzW3BpXS52YWx1ZSA9IHBiOworCQkJCXBiICs9IHN0
cmxlbih1Y3R4LT5jLnBhcmFtZXRlcnNbcGldLnZhbHVlKSsxOworCQkJfQorCQkJZWxzZSB7CisJ
CQkJdWN0eC0+Yy5wYXJhbWV0ZXJzW3BpXS52YWx1ZSA9IE5VTEw7CisJCQl9CisKKwkJCS8qIE5l
eHQgJyYnID8gKi8KKwkJCWlmICghbmEpCisJCQkJYnJlYWs7CisKKwkJCXBzID0gbmE7CisJCX0K
KworCQl1Y3R4LT5jLm51bV9wYXJhbWV0ZXJzID0gcGkrMTsKKwl9CisKKwlzID0gc3Ryc3RyKHVy
bHN0ciwgIi8iKTsKKwlpZiAocykgeworCQkvKiBVUkwgaGFzIGhvc3Rwb3J0ICovCisJCXNsZW4g
PSBzLXVybHN0cjsKKwkJdXJsZGVjb2Rlc3RyKHVjdHgtPmMuaG9zdHBvcnQuaG9zdG5hbWUsIHVy
bHN0ciwgc2xlbik7CisJCXVybHN0ciArPSBzbGVuICsgMTsKKworCQkvKgorCQkgKiBjaGVjayBm
b3IgYWRkcmVzc2VzIHdpdGhpbiAnWycgYW5kICddJywgbGlrZQorCQkgKiBJUHY2IGFkZHJlc3Nl
cworCQkgKi8KKwkJcyA9IHVjdHgtPmMuaG9zdHBvcnQuaG9zdG5hbWU7CisJCWlmIChzWzBdID09
ICdbJykKKwkJCXMgPSBzdHJzdHIocywgIl0iKTsKKworCQlpZiAocyA9PSBOVUxMKSB7CisJCQlE
KCh2b2lkKURCR19QVVRTKCJ1cmxfcGFyc2VyOiBVbm1hdGNoZWQgJ1snIGluIGhvc3RuYW1lXG4i
LCBzdGRlcnIpKTsKKwkJCXJldHVybiAtMTsKKwkJfQorCisJCXMgPSBzdHJzdHIocywgIjoiKTsK
KwkJaWYgKHMpIHsKKwkJCS8qIGZvdW5kIHBvcnQgbnVtYmVyICovCisJCQl1Y3R4LT5jLmhvc3Rw
b3J0LnBvcnQgPSBhdG9pKHMrMSk7CisJCQkqcyA9ICdcMCc7CisJCX0KKwl9CisJZWxzZSB7CisJ
CSh2b2lkKXN0cmNweSh1Y3R4LT5jLmhvc3Rwb3J0Lmhvc3RuYW1lLCB1cmxzdHIpOworCQl1Y3R4
LT5jLnBhdGggPSBOVUxMOworCQl1cmxzdHIgPSBOVUxMOworCX0KKworCUQoCisJCSh2b2lkKURC
R19QUklOVEYoc3Rkb3V0LAorCQkJImhvc3Rwb3J0PSclcycsIHBvcnQ9JWQsIHJlc3Q9JyVzJywg
bnVtX3BhcmFtZXRlcnM9JWRcbiIsCisJCQlEQkdOVUxMU1RSKHVjdHgtPmMuaG9zdHBvcnQuaG9z
dG5hbWUpLAorCQkJdWN0eC0+Yy5ob3N0cG9ydC5wb3J0LAorCQkJREJHTlVMTFNUUih1cmxzdHIp
LAorCQkJKGludCl1Y3R4LT5jLm51bV9wYXJhbWV0ZXJzKTsKKwkpOworCisKKwlEKAorCQlzc2l6
ZV90IGRwaTsKKwkJZm9yIChkcGkgPSAwIDsgZHBpIDwgdWN0eC0+Yy5udW1fcGFyYW1ldGVycyA7
IGRwaSsrKSB7CisJCQkodm9pZClEQkdfUFJJTlRGKHN0ZG91dCwKKwkJCQkicGFyYW1bJWRdOiBu
YW1lPSclcycvdmFsdWU9JyVzJ1xuIiwKKwkJCQkoaW50KWRwaSwKKwkJCQl1Y3R4LT5jLnBhcmFt
ZXRlcnNbZHBpXS5uYW1lLAorCQkJCURCR05VTExTVFIodWN0eC0+Yy5wYXJhbWV0ZXJzW2RwaV0u
dmFsdWUpKTsKKwkJfQorCSk7CisKKwlpZiAoIXVybHN0cikgeworCQlnb3RvIGRvbmU7CisJfQor
CisJdXJsZGVjb2Rlc3RyKHVjdHgtPmMucGF0aCwgdXJsc3RyLCBzdHJsZW4odXJsc3RyKSk7CisJ
RCgodm9pZClEQkdfUFJJTlRGKHN0ZG91dCwgInBhdGg9JyVzJ1xuIiwgdWN0eC0+Yy5wYXRoKSk7
CisKK2RvbmU6CisJcmV0dXJuIDA7Cit9CisKK3ZvaWQgdXJsX3BhcnNlcl9mcmVlX2NvbnRleHQo
dXJsX3BhcnNlcl9jb250ZXh0ICpjKQoreworCWZyZWUoYyk7Cit9CmRpZmYgLS1naXQgYS91dGls
cy9tb3VudC91cmxwYXJzZXIxLmggYi91dGlscy9tb3VudC91cmxwYXJzZXIxLmgKbmV3IGZpbGUg
bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAuLjUxNWVlYTlkCi0tLSAvZGV2L251bGwKKysrIGIv
dXRpbHMvbW91bnQvdXJscGFyc2VyMS5oCkBAIC0wLDAgKzEsNjAgQEAKKy8qCisgKiBNSVQgTGlj
ZW5zZQorICoKKyAqIENvcHlyaWdodCAoYykgMjAyNCBSb2xhbmQgTWFpbnogPHJvbGFuZC5tYWlu
ekBucnVic2lnLm9yZz4KKyAqCisgKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVl
IG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5CisgKiBvZiB0aGlzIHNv
ZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAiU29mdHdhcmUi
KSwgdG8gZGVhbAorICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1
ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cworICogdG8gdXNlLCBjb3B5LCBtb2Rp
ZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbAor
ICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20g
dGhlIFNvZnR3YXJlIGlzCisgKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZv
bGxvd2luZyBjb25kaXRpb25zOgorICoKKyAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFu
ZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbAorICogY29w
aWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4KKyAqCisgKiBUSEUg
U09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lO
RCwgRVhQUkVTUyBPUgorICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBU
SEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksCisgKiBGSVRORVNTIEZPUiBBIFBBUlRJ
Q1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUK
KyAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0s
IERBTUFHRVMgT1IgT1RIRVIKKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0Yg
Q09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sCisgKiBPVVQgT0YgT1Ig
SU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJ
TkdTIElOIFRIRQorICogU09GVFdBUkUuCisgKi8KKworLyogdXJscGFyc2VyMS5oIC0gaGVhZGVy
IGZvciBzaW1wbGUgVVJMIHBhcnNlciAqLworCisjaWZuZGVmIF9fVVJMUEFSU0VSMV9IX18KKyNk
ZWZpbmUgX19VUkxQQVJTRVIxX0hfXyAxCisKKyNpbmNsdWRlIDxzdGRsaWIuaD4KKwordHlwZWRl
ZiBzdHJ1Y3QgX3VybF9wYXJzZXJfbmFtZV92YWx1ZSB7CisJY2hhciAqbmFtZTsKKwljaGFyICp2
YWx1ZTsKK30gdXJsX3BhcnNlcl9uYW1lX3ZhbHVlOworCit0eXBlZGVmIHN0cnVjdCBfdXJsX3Bh
cnNlcl9jb250ZXh0IHsKKwljaGFyICppbl91cmw7CisKKwljaGFyICpzY2hlbWU7CisJc3RydWN0
IHsKKwkJY2hhciAqdXNlcm5hbWU7CisJCWNoYXIgKnBhc3N3ZDsKKwl9IGxvZ2luOworCXN0cnVj
dCB7CisJCWNoYXIgKmhvc3RuYW1lOworCQlzaWduZWQgaW50IHBvcnQ7CisJfSBob3N0cG9ydDsK
KwljaGFyICpwYXRoOworCisJc3NpemVfdCBudW1fcGFyYW1ldGVyczsKKwl1cmxfcGFyc2VyX25h
bWVfdmFsdWUgKnBhcmFtZXRlcnM7Cit9IHVybF9wYXJzZXJfY29udGV4dDsKKworLyogUHJvdG90
eXBlcyAqLwordXJsX3BhcnNlcl9jb250ZXh0ICp1cmxfcGFyc2VyX2NyZWF0ZV9jb250ZXh0KGNv
bnN0IGNoYXIgKmluX3VybCwgdW5zaWduZWQgaW50IGZsYWdzKTsKK2ludCB1cmxfcGFyc2VyX3Bh
cnNlKHVybF9wYXJzZXJfY29udGV4dCAqdWN0eCk7Cit2b2lkIHVybF9wYXJzZXJfZnJlZV9jb250
ZXh0KHVybF9wYXJzZXJfY29udGV4dCAqYyk7CisKKyNlbmRpZiAvKiAhX19VUkxQQVJTRVIxX0hf
XyAqLwpkaWZmIC0tZ2l0IGEvdXRpbHMvbW91bnQvdXRpbHMuYyBiL3V0aWxzL21vdW50L3V0aWxz
LmMKaW5kZXggYjc1NjJhNDcuLjNkNTVlOTk3IDEwMDY0NAotLS0gYS91dGlscy9tb3VudC91dGls
cy5jCisrKyBiL3V0aWxzL21vdW50L3V0aWxzLmMKQEAgLTI4LDYgKzI4LDcgQEAKICNpbmNsdWRl
IDx1bmlzdGQuaD4KICNpbmNsdWRlIDxzeXMvdHlwZXMuaD4KICNpbmNsdWRlIDxzeXMvc3RhdC5o
PgorI2luY2x1ZGUgPGljb252Lmg+CiAKICNpbmNsdWRlICJzb2NrYWRkci5oIgogI2luY2x1ZGUg
Im5mc19tb3VudC5oIgpAQCAtMTczLDMgKzE3NCwxNTcgQEAgaW50IG5mc191bW91bnQyMyhjb25z
dCBjaGFyICpkZXZuYW1lLCBjaGFyICpzdHJpbmcpCiAJZnJlZShkaXJuYW1lKTsKIAlyZXR1cm4g
cmVzdWx0OwogfQorCisvKiBDb252ZXJ0IFVURi04IHN0cmluZyB0byBtdWx0aWJ5dGUgc3RyaW5n
IGluIHRoZSBjdXJyZW50IGxvY2FsZSAqLworY2hhciAqdXRmOHN0cjJtYnN0cihjb25zdCBjaGFy
ICp1dGY4X3N0cikKK3sKKwlpY29udl90IGNkOworCisJY2QgPSBpY29udl9vcGVuKCIiLCAiVVRG
LTgiKTsKKwlpZiAoY2QgPT0gKGljb252X3QpLTEpIHsKKwkJcGVycm9yKCJ1dGY4c3RyMm1ic3Ry
OiBpY29udl9vcGVuIGZhaWxlZCIpOworCQlyZXR1cm4gTlVMTDsKKwl9CisKKwlzaXplX3QgaW5i
eXRlc2xlZnQgPSBzdHJsZW4odXRmOF9zdHIpOworCWNoYXIgKmluYnVmID0gKGNoYXIgKil1dGY4
X3N0cjsKKwlzaXplX3Qgb3V0Ynl0ZXNsZWZ0ID0gaW5ieXRlc2xlZnQqNCsxOworCWNoYXIgKm91
dGJ1ZiA9IG1hbGxvYyhvdXRieXRlc2xlZnQpOworCWNoYXIgKm91dGJ1Zl9vcmlnID0gb3V0YnVm
OworCisJaWYgKCFvdXRidWYpIHsKKwkJcGVycm9yKCJ1dGY4c3RyMm1ic3RyOiBvdXQgb2YgbWVt
b3J5Iik7CisJCSh2b2lkKWljb252X2Nsb3NlKGNkKTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJ
aW50IHJldCA9IGljb252KGNkLCAmaW5idWYsICZpbmJ5dGVzbGVmdCwgJm91dGJ1ZiwgJm91dGJ5
dGVzbGVmdCk7CisJaWYgKHJldCA9PSAtMSkgeworCQlwZXJyb3IoInV0ZjhzdHIybWJzdHI6IGlj
b252KCkgZmFpbGVkIik7CisJCWZyZWUob3V0YnVmX29yaWcpOworCQkodm9pZClpY29udl9jbG9z
ZShjZCk7CisJCXJldHVybiBOVUxMOworCX0KKworCSpvdXRidWYgPSAnXDAnOworCisJKHZvaWQp
aWNvbnZfY2xvc2UoY2QpOworCXJldHVybiBvdXRidWZfb3JpZzsKK30KKworLyogZml4bWU6IFdl
IHNob3VsZCB1c2UgfGJvb2x8ISAqLworaW50IGlzX3NwZWNfbmZzX3VybChjb25zdCBjaGFyICpz
cGVjKQoreworCXJldHVybiAoIXN0cm5jbXAoc3BlYywgIm5mczovLyIsIDYpKTsKK30KKworaW50
IG1vdW50X3BhcnNlX25mc191cmwoY29uc3QgY2hhciAqc3BlYywgcGFyc2VkX25mc191cmwgKnBu
dSkKK3sKKwlpbnQgcmVzdWx0ID0gMTsKKwl1cmxfcGFyc2VyX2NvbnRleHQgKnVjdHggPSBOVUxM
OworCisJKHZvaWQpbWVtc2V0KHBudSwgMCwgc2l6ZW9mKHBhcnNlZF9uZnNfdXJsKSk7CisJcG51
LT5tb3VudF9wYXJhbXMucmVhZF9vbmx5ID0gVFJJU19CT09MX05PVF9TRVQ7CisKKwl1Y3R4ID0g
dXJsX3BhcnNlcl9jcmVhdGVfY29udGV4dChzcGVjLCAwKTsKKwlpZiAoIXVjdHgpIHsKKwkJbmZz
X2Vycm9yKF8oIiVzOiBvdXQgb2YgbWVtb3J5IiksCisJCQlwcm9nbmFtZSk7CisJCXJlc3VsdCA9
IDE7CisJCWdvdG8gZG9uZTsKKwl9CisKKwlpZiAodXJsX3BhcnNlcl9wYXJzZSh1Y3R4KSA8IDAp
IHsKKwkJbmZzX2Vycm9yKF8oIiVzOiBFcnJvciBwYXJzaW5nIG5mczovLy1VUkwuIiksCisJCQlw
cm9nbmFtZSk7CisJCXJlc3VsdCA9IDE7CisJCWdvdG8gZG9uZTsKKwl9CisJaWYgKHVjdHgtPmxv
Z2luLnVzZXJuYW1lIHx8IHVjdHgtPmxvZ2luLnBhc3N3ZCkgeworCQluZnNfZXJyb3IoXygiJXM6
IFVzZXJuYW1lL1Bhc3N3b3JkIGFyZSBub3QgZGVmaW5lZCBmb3IgbmZzOi8vLVVSTC4iKSwKKwkJ
CXByb2duYW1lKTsKKwkJcmVzdWx0ID0gMTsKKwkJZ290byBkb25lOworCX0KKwlpZiAoIXVjdHgt
PnBhdGgpIHsKKwkJbmZzX2Vycm9yKF8oIiVzOiBQYXRoIG1pc3NpbmcgaW4gbmZzOi8vLVVSTC4i
KSwKKwkJCXByb2duYW1lKTsKKwkJcmVzdWx0ID0gMTsKKwkJZ290byBkb25lOworCX0KKwlpZiAo
dWN0eC0+cGF0aFswXSAhPSAnLycpIHsKKwkJbmZzX2Vycm9yKF8oIiVzOiBSZWxhdGl2ZSBuZnM6
Ly8tVVJMcyBhcmUgbm90IHN1cHBvcnRlZC4iKSwKKwkJCXByb2duYW1lKTsKKwkJcmVzdWx0ID0g
MTsKKwkJZ290byBkb25lOworCX0KKworCWlmICh1Y3R4LT5udW1fcGFyYW1ldGVycyA+IDApIHsK
KwkJaW50IHBpOworCQljb25zdCBjaGFyICpwbmFtZTsKKwkJY29uc3QgY2hhciAqcHZhbHVlOwor
CisJCS8qCisJCSAqIFZhbHVlcyBhZGRlZCBoZXJlIGJhc2VkIG9uIFVSTCBwYXJhbWV0ZXJzCisJ
CSAqIHNob3VsZCBiZSBhZGRlZCB0aGUgZnJvbnQgb2YgdGhlIGxpc3Qgb2Ygb3B0aW9ucywKKwkJ
ICogc28gdXNlcnMgY2FuIG92ZXJyaWRlIHRoZSBuZnM6Ly8tVVJMIGdpdmVuIGRlZmF1bHQuCisJ
CSAqLworCQlmb3IgKHBpID0gMDsgcGkgPCB1Y3R4LT5udW1fcGFyYW1ldGVycyA7IHBpKyspIHsK
KwkJCXBuYW1lID0gdWN0eC0+cGFyYW1ldGVyc1twaV0ubmFtZTsKKwkJCXB2YWx1ZSA9IHVjdHgt
PnBhcmFtZXRlcnNbcGldLnZhbHVlOworCisJCQlpZiAoIXN0cmNtcChwbmFtZSwgInJ3IikpIHsK
KwkJCQlpZiAoKHB2YWx1ZSA9PSBOVUxMKSB8fCAoIXN0cmNtcChwdmFsdWUsICIxIikpKSB7CisJ
CQkJCXBudS0+bW91bnRfcGFyYW1zLnJlYWRfb25seSA9IFRSSVNfQk9PTF9GQUxTRTsKKwkJCQl9
CisJCQkJZWxzZSBpZiAoIXN0cmNtcChwdmFsdWUsICIwIikpIHsKKwkJCQkJcG51LT5tb3VudF9w
YXJhbXMucmVhZF9vbmx5ID0gVFJJU19CT09MX1RSVUU7CisJCQkJfQorCQkJCWVsc2UgeworCQkJ
CQluZnNfZXJyb3IoXygiJXM6IFVuc3VwcG9ydGVkIG5mczovLy1VUkwgIgorCQkJCQkJInBhcmFt
ZXRlciAnJXMnIHZhbHVlICclcycuIiksCisJCQkJCQlwcm9nbmFtZSwgcG5hbWUsIHB2YWx1ZSk7
CisJCQkJCXJlc3VsdCA9IDE7CisJCQkJCWdvdG8gZG9uZTsKKwkJCQl9CisJCQl9CisJCQllbHNl
IGlmICghc3RyY21wKHBuYW1lLCAicm8iKSkgeworCQkJCWlmICgocHZhbHVlID09IE5VTEwpIHx8
ICghc3RyY21wKHB2YWx1ZSwgIjEiKSkpIHsKKwkJCQkJcG51LT5tb3VudF9wYXJhbXMucmVhZF9v
bmx5ID0gVFJJU19CT09MX1RSVUU7CisJCQkJfQorCQkJCWVsc2UgaWYgKCFzdHJjbXAocHZhbHVl
LCAiMCIpKSB7CisJCQkJCXBudS0+bW91bnRfcGFyYW1zLnJlYWRfb25seSA9IFRSSVNfQk9PTF9G
QUxTRTsKKwkJCQl9CisJCQkJZWxzZSB7CisJCQkJCW5mc19lcnJvcihfKCIlczogVW5zdXBwb3J0
ZWQgbmZzOi8vLVVSTCAiCisJCQkJCQkicGFyYW1ldGVyICclcycgdmFsdWUgJyVzJy4iKSwKKwkJ
CQkJCXByb2duYW1lLCBwbmFtZSwgcHZhbHVlKTsKKwkJCQkJcmVzdWx0ID0gMTsKKwkJCQkJZ290
byBkb25lOworCQkJCX0KKwkJCX0KKwkJCWVsc2UgeworCQkJCW5mc19lcnJvcihfKCIlczogVW5z
dXBwb3J0ZWQgbmZzOi8vLVVSTCAiCisJCQkJCQkicGFyYW1ldGVyICclcycuIiksCisJCQkJCXBy
b2duYW1lLCBwbmFtZSk7CisJCQkJcmVzdWx0ID0gMTsKKwkJCQlnb3RvIGRvbmU7CisJCQl9CisJ
CX0KKwl9CisKKwlyZXN1bHQgPSAwOworZG9uZToKKwlpZiAocmVzdWx0ICE9IDApIHsKKwkJdXJs
X3BhcnNlcl9mcmVlX2NvbnRleHQodWN0eCk7CisJCXJldHVybiAwOworCX0KKworCXBudS0+dWN0
eCA9IHVjdHg7CisJcmV0dXJuIDE7Cit9CisKK3ZvaWQgbW91bnRfZnJlZV9wYXJzZV9uZnNfdXJs
KHBhcnNlZF9uZnNfdXJsICpwbnUpCit7CisJdXJsX3BhcnNlcl9mcmVlX2NvbnRleHQocG51LT51
Y3R4KTsKK30KZGlmZiAtLWdpdCBhL3V0aWxzL21vdW50L3V0aWxzLmggYi91dGlscy9tb3VudC91
dGlscy5oCmluZGV4IDIyNDkxOGFlLi40NjVjMGE1ZSAxMDA2NDQKLS0tIGEvdXRpbHMvbW91bnQv
dXRpbHMuaAorKysgYi91dGlscy9tb3VudC91dGlscy5oCkBAIC0yNCwxMyArMjQsMzYgQEAKICNk
ZWZpbmUgX05GU19VVElMU19NT1VOVF9VVElMU19ICiAKICNpbmNsdWRlICJwYXJzZV9vcHQuaCIK
KyNpbmNsdWRlICJ1cmxwYXJzZXIxLmgiCiAKKy8qIEJvb2xlYW4gd2l0aCB0aHJlZSBzdGF0ZXM6
IHsgbm90X3NldCwgZmFsc2UsIHRydWUgKi8KK3R5cGVkZWYgc2lnbmVkIGNoYXIgdHJpc3RhdGVf
Ym9vbDsKKyNkZWZpbmUgVFJJU19CT09MX05PVF9TRVQgKC0xKQorI2RlZmluZSBUUklTX0JPT0xf
VFJVRSAoMSkKKyNkZWZpbmUgVFJJU19CT09MX0ZBTFNFICgwKQorCisjZGVmaW5lIFRSSVNfQk9P
TF9HRVRfVkFMKHRzYiwgdHNiX2RlZmF1bHQpIFwKKwkoKCh0c2IpIT1UUklTX0JPT0xfTk9UX1NF
VCk/KHRzYik6KHRzYl9kZWZhdWx0KSkKKwordHlwZWRlZiBzdHJ1Y3QgX3BhcnNlZF9uZnNfdXJs
IHsKKwl1cmxfcGFyc2VyX2NvbnRleHQgKnVjdHg7CisJc3RydWN0IHsKKwkJdHJpc3RhdGVfYm9v
bCByZWFkX29ubHk7CisJfSBtb3VudF9wYXJhbXM7Cit9IHBhcnNlZF9uZnNfdXJsOworCisvKiBQ
cm90b3R5cGVzICovCiBpbnQgZGlzY292ZXJfbmZzX21vdW50X2RhdGFfdmVyc2lvbihpbnQgKnN0
cmluZ192ZXIpOwogdm9pZCBwcmludF9vbmUoY2hhciAqc3BlYywgY2hhciAqbm9kZSwgY2hhciAq
dHlwZSwgY2hhciAqb3B0cyk7CiB2b2lkIG1vdW50X3VzYWdlKHZvaWQpOwogdm9pZCB1bW91bnRf
dXNhZ2Uodm9pZCk7CiBpbnQgY2hrX21vdW50cG9pbnQoY29uc3QgY2hhciAqbW91bnRfcG9pbnQp
OworY2hhciAqdXRmOHN0cjJtYnN0cihjb25zdCBjaGFyICp1dGY4X3N0cik7CitpbnQgaXNfc3Bl
Y19uZnNfdXJsKGNvbnN0IGNoYXIgKnNwZWMpOwogCiBpbnQgbmZzX3Vtb3VudDIzKGNvbnN0IGNo
YXIgKmRldm5hbWUsIGNoYXIgKnN0cmluZyk7CiAKK2ludCBtb3VudF9wYXJzZV9uZnNfdXJsKGNv
bnN0IGNoYXIgKnNwZWMsIHBhcnNlZF9uZnNfdXJsICpwbnUpOwordm9pZCBtb3VudF9mcmVlX3Bh
cnNlX25mc191cmwocGFyc2VkX25mc191cmwgKnBudSk7CisKICNlbmRpZgkvKiAhX05GU19VVElM
U19NT1VOVF9VVElMU19IICovCi0tIAoyLjMwLjIKCg==
--000000000000ccb28f0628a0fd7d--




[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux