From owner-svn-src-all@freebsd.org Mon Dec 7 11:25:18 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 7E3B447F06A; Mon, 7 Dec 2020 11:25:18 +0000 (UTC) (envelope-from tsoome@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4CqLZk37pmz4gZk; Mon, 7 Dec 2020 11:25:18 +0000 (UTC) (envelope-from tsoome@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 53E212133F; Mon, 7 Dec 2020 11:25:18 +0000 (UTC) (envelope-from tsoome@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0B7BPILG017681; Mon, 7 Dec 2020 11:25:18 GMT (envelope-from tsoome@FreeBSD.org) Received: (from tsoome@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0B7BPIt4017680; Mon, 7 Dec 2020 11:25:18 GMT (envelope-from tsoome@FreeBSD.org) Message-Id: <202012071125.0B7BPIt4017680@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tsoome set sender to tsoome@FreeBSD.org using -f From: Toomas Soome Date: Mon, 7 Dec 2020 11:25:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r368410 - head/stand/libsa/zfs X-SVN-Group: head X-SVN-Commit-Author: tsoome X-SVN-Commit-Paths: head/stand/libsa/zfs X-SVN-Commit-Revision: 368410 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Dec 2020 11:25:18 -0000 Author: tsoome Date: Mon Dec 7 11:25:18 2020 New Revision: 368410 URL: https://svnweb.freebsd.org/changeset/base/368410 Log: loader: xdr_array is missing count The integer arrays are encoded in nvlist as counted array , loader xdr_array() is missing the count. This will affect the pool import when there are hole devices in pool. Also fix the new data add and print functions. Modified: head/stand/libsa/zfs/nvlist.c Modified: head/stand/libsa/zfs/nvlist.c ============================================================================== --- head/stand/libsa/zfs/nvlist.c Mon Dec 7 11:18:51 2020 (r368409) +++ head/stand/libsa/zfs/nvlist.c Mon Dec 7 11:25:18 2020 (r368410) @@ -63,7 +63,7 @@ static int _getint(struct xdr *xdr, int *ip) { *ip = be32dec(xdr->xdr_idx); - return (sizeof (int)); + return (sizeof(int)); } static int @@ -72,14 +72,14 @@ _putint(struct xdr *xdr, int i) int *ip = (int *)xdr->xdr_idx; *ip = htobe32(i); - return (sizeof (int)); + return (sizeof(int)); } static int _getuint(struct xdr *xdr, unsigned *ip) { *ip = be32dec(xdr->xdr_idx); - return (sizeof (unsigned)); + return (sizeof(unsigned)); } static int @@ -88,9 +88,41 @@ _putuint(struct xdr *xdr, unsigned i) unsigned *up = (unsigned *)xdr->xdr_idx; *up = htobe32(i); - return (sizeof (int)); + return (sizeof(int)); } +static int +_getint_mem(struct xdr *xdr, int *ip) +{ + *ip = *(int *)xdr->xdr_idx; + return (sizeof(int)); +} + +static int +_putint_mem(struct xdr *xdr, int i) +{ + int *ip = (int *)xdr->xdr_idx; + + *ip = i; + return (sizeof(int)); +} + +static int +_getuint_mem(struct xdr *xdr, unsigned *ip) +{ + *ip = *(unsigned *)xdr->xdr_idx; + return (sizeof(unsigned)); +} + +static int +_putuint_mem(struct xdr *xdr, unsigned i) +{ + unsigned *up = (unsigned *)xdr->xdr_idx; + + *up = i; + return (sizeof(int)); +} + /* * XDR data translations. */ @@ -131,7 +163,7 @@ xdr_int(xdr_t *xdr, int *ip) bool rv = false; int *i = (int *)xdr->xdr_idx; - if (xdr->xdr_idx + sizeof (int) > xdr->xdr_buf + xdr->xdr_buf_size) + if (xdr->xdr_idx + sizeof(int) > xdr->xdr_buf + xdr->xdr_buf_size) return (rv); switch (xdr->xdr_op) { @@ -160,7 +192,7 @@ xdr_u_int(xdr_t *xdr, unsigned *ip) bool rv = false; unsigned *u = (unsigned *)xdr->xdr_idx; - if (xdr->xdr_idx + sizeof (unsigned) > xdr->xdr_buf + xdr->xdr_buf_size) + if (xdr->xdr_idx + sizeof(unsigned) > xdr->xdr_buf + xdr->xdr_buf_size) return (rv); switch (xdr->xdr_op) { @@ -183,28 +215,29 @@ xdr_u_int(xdr_t *xdr, unsigned *ip) static bool xdr_int64(xdr_t *xdr, int64_t *lp) { - int hi; - unsigned lo; bool rv = false; - if (xdr->xdr_idx + sizeof (int64_t) > xdr->xdr_buf + xdr->xdr_buf_size) + if (xdr->xdr_idx + sizeof(int64_t) > xdr->xdr_buf + xdr->xdr_buf_size) return (rv); switch (xdr->xdr_op) { case XDR_OP_ENCODE: /* Encode value *lp, store to buf */ - hi = *lp >> 32; - lo = *lp & UINT32_MAX; - xdr->xdr_idx += xdr->xdr_putint(xdr, hi); - xdr->xdr_idx += xdr->xdr_putint(xdr, lo); + if (xdr->xdr_putint == _putint) + *(int64_t *)xdr->xdr_idx = htobe64(*lp); + else + *(int64_t *)xdr->xdr_idx = *lp; + xdr->xdr_idx += sizeof(int64_t); rv = true; break; case XDR_OP_DECODE: /* Decode buf, return value to *ip */ - xdr->xdr_idx += xdr->xdr_getint(xdr, &hi); - xdr->xdr_idx += xdr->xdr_getuint(xdr, &lo); - *lp = (((int64_t)hi) << 32) | lo; + if (xdr->xdr_getint == _getint) + *lp = be64toh(*(int64_t *)xdr->xdr_idx); + else + *lp = *(int64_t *)xdr->xdr_idx; + xdr->xdr_idx += sizeof(int64_t); rv = true; } return (rv); @@ -213,27 +246,29 @@ xdr_int64(xdr_t *xdr, int64_t *lp) static bool xdr_uint64(xdr_t *xdr, uint64_t *lp) { - unsigned hi, lo; bool rv = false; - if (xdr->xdr_idx + sizeof (uint64_t) > xdr->xdr_buf + xdr->xdr_buf_size) + if (xdr->xdr_idx + sizeof(uint64_t) > xdr->xdr_buf + xdr->xdr_buf_size) return (rv); switch (xdr->xdr_op) { case XDR_OP_ENCODE: /* Encode value *ip, store to buf */ - hi = *lp >> 32; - lo = *lp & UINT32_MAX; - xdr->xdr_idx += xdr->xdr_putint(xdr, hi); - xdr->xdr_idx += xdr->xdr_putint(xdr, lo); + if (xdr->xdr_putint == _putint) + *(uint64_t *)xdr->xdr_idx = htobe64(*lp); + else + *(uint64_t *)xdr->xdr_idx = *lp; + xdr->xdr_idx += sizeof(uint64_t); rv = true; break; case XDR_OP_DECODE: /* Decode buf, return value to *ip */ - xdr->xdr_idx += xdr->xdr_getuint(xdr, &hi); - xdr->xdr_idx += xdr->xdr_getuint(xdr, &lo); - *lp = (((uint64_t)hi) << 32) | lo; + if (xdr->xdr_getuint == _getuint) + *lp = be64toh(*(uint64_t *)xdr->xdr_idx); + else + *lp = *(uint64_t *)xdr->xdr_idx; + xdr->xdr_idx += sizeof(uint64_t); rv = true; } return (rv); @@ -262,7 +297,7 @@ xdr_string(xdr_t *xdr, nv_string_t *s) switch (xdr->xdr_op) { case XDR_OP_ENCODE: size = s->nv_size; - if (xdr->xdr_idx + sizeof (unsigned) + NV_ALIGN4(size) > + if (xdr->xdr_idx + sizeof(unsigned) + NV_ALIGN4(size) > xdr->xdr_buf + xdr->xdr_buf_size) break; xdr->xdr_idx += xdr->xdr_putuint(xdr, s->nv_size); @@ -271,7 +306,7 @@ xdr_string(xdr_t *xdr, nv_string_t *s) break; case XDR_OP_DECODE: - if (xdr->xdr_idx + sizeof (unsigned) > + if (xdr->xdr_idx + sizeof(unsigned) > xdr->xdr_buf + xdr->xdr_buf_size) break; size = xdr->xdr_getuint(xdr, &s->nv_size); @@ -289,7 +324,11 @@ static bool xdr_array(xdr_t *xdr, const unsigned nelem, const xdrproc_t elproc) { bool rv = true; + unsigned c = nelem; + if (!xdr_u_int(xdr, &c)) + return (false); + for (unsigned i = 0; i < nelem; i++) { if (!elproc(xdr, xdr->xdr_idx)) return (false); @@ -334,14 +373,14 @@ nvlist_create(int flag) nvlist_t *nvl; nvs_data_t *nvs; - nvl = calloc(1, sizeof (*nvl)); + nvl = calloc(1, sizeof(*nvl)); if (nvl == NULL) return (nvl); nvl->nv_header.nvh_encoding = NV_ENCODE_XDR; nvl->nv_header.nvh_endian = _BYTE_ORDER == _LITTLE_ENDIAN; - nvl->nv_asize = nvl->nv_size = sizeof (*nvs); + nvl->nv_asize = nvl->nv_size = sizeof(*nvs); nvs = calloc(1, nvl->nv_asize); if (nvs == NULL) { free(nvl); @@ -378,7 +417,7 @@ nvlist_xdr_nvp(xdr_t *xdr, nvlist_t *nvl) switch (type) { case DATA_TYPE_NVLIST: case DATA_TYPE_NVLIST_ARRAY: - bzero(&nvlist, sizeof (nvlist)); + bzero(&nvlist, sizeof(nvlist)); nvlist.nv_data = xdr->xdr_idx; nvlist.nv_idx = nvlist.nv_data; @@ -514,7 +553,7 @@ nvlist_xdr_nvlist(xdr_t *xdr, nvlist_t *nvl) if (!xdr_u_int(xdr, &nvph->decoded_size)) return (EINVAL); } else { - xdr->xdr_idx += 2 * sizeof (unsigned); + xdr->xdr_idx += 2 * sizeof(unsigned); } rv = 0; @@ -531,7 +570,7 @@ nvlist_xdr_nvlist(xdr_t *xdr, nvlist_t *nvl) if (!xdr_u_int(xdr, &nvph->decoded_size)) return (EINVAL); } else { - xdr->xdr_idx += 2 * sizeof (unsigned); + xdr->xdr_idx += 2 * sizeof(unsigned); } } return (rv); @@ -546,7 +585,7 @@ nvlist_size_xdr(xdr_t *xdr, size_t *size) uint8_t *pair; unsigned encoded_size, decoded_size; - xdr->xdr_idx += 2 * sizeof (unsigned); + xdr->xdr_idx += 2 * sizeof(unsigned); pair = xdr->xdr_idx; if (!xdr_u_int(xdr, &encoded_size) || !xdr_u_int(xdr, &decoded_size)) @@ -578,7 +617,7 @@ nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh) xdr.xdr_idx = nvl->nv_data; xdr.xdr_buf_size = nvl->nv_size; - xdr.xdr_idx += 2 * sizeof (unsigned); + xdr.xdr_idx += 2 * sizeof(unsigned); /* Skip tp current pair */ if (nvh != NULL) { @@ -590,12 +629,12 @@ nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh) return (NULL); encoded_size = *(unsigned *)xdr.xdr_idx; - xdr.xdr_idx += sizeof (unsigned); + xdr.xdr_idx += sizeof(unsigned); if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) return (NULL); decoded_size = *(unsigned *)xdr.xdr_idx; - xdr.xdr_idx += sizeof (unsigned); + xdr.xdr_idx += sizeof(unsigned); if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) return (NULL); @@ -610,11 +649,11 @@ nvlist_next_nvpair(nvlist_t *nvl, nvp_header_t *nvh) return (NULL); encoded_size = *(unsigned *)xdr.xdr_idx; - xdr.xdr_idx += sizeof (unsigned); + xdr.xdr_idx += sizeof(unsigned); if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) return (NULL); decoded_size = *(unsigned *)xdr.xdr_idx; - xdr.xdr_idx += sizeof (unsigned); + xdr.xdr_idx += sizeof(unsigned); if (xdr.xdr_idx > xdr.xdr_buf + xdr.xdr_buf_size) return (NULL); @@ -634,29 +673,29 @@ nvlist_size_native(xdr_t *xdr, size_t *size) uint8_t *pair; unsigned encoded_size, decoded_size; - xdr->xdr_idx += 2 * sizeof (unsigned); + xdr->xdr_idx += 2 * sizeof(unsigned); pair = xdr->xdr_idx; if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) return (false); encoded_size = *(unsigned *)xdr->xdr_idx; - xdr->xdr_idx += sizeof (unsigned); + xdr->xdr_idx += sizeof(unsigned); if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) return (false); decoded_size = *(unsigned *)xdr->xdr_idx; - xdr->xdr_idx += sizeof (unsigned); + xdr->xdr_idx += sizeof(unsigned); while (encoded_size && decoded_size) { xdr->xdr_idx = pair + encoded_size; pair = xdr->xdr_idx; if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) return (false); encoded_size = *(unsigned *)xdr->xdr_idx; - xdr->xdr_idx += sizeof (unsigned); + xdr->xdr_idx += sizeof(unsigned); if (xdr->xdr_idx > xdr->xdr_buf + xdr->xdr_buf_size) return (false); decoded_size = *(unsigned *)xdr->xdr_idx; - xdr->xdr_idx += sizeof (unsigned); + xdr->xdr_idx += sizeof(unsigned); } *size = xdr->xdr_idx - xdr->xdr_buf; @@ -711,7 +750,7 @@ nvlist_import(const char *stream, size_t size) be32toh(*(uint32_t *)(stream + 8)) != NV_UNIQUE_NAME) return (NULL); - nvl = malloc(sizeof (*nvl)); + nvl = malloc(sizeof(*nvl)); if (nvl == NULL) return (nvl); @@ -810,7 +849,7 @@ clone_nvlist(const nvlist_t *nvl, const uint8_t *ptr, { nvlist_t *nv; - nv = calloc(1, sizeof (*nv)); + nv = calloc(1, sizeof(*nv)); if (nv == NULL) return (ENOMEM); @@ -843,7 +882,7 @@ nvlist_next(const uint8_t *ptr) while (nvp->encoded_size != 0 && nvp->decoded_size != 0) { nvp = (nvp_header_t *)((uint8_t *)nvp + nvp->encoded_size); } - return ((uint8_t *)nvp + sizeof (*nvp)); + return ((uint8_t *)nvp + sizeof(*nvp)); } /* @@ -868,7 +907,7 @@ nvlist_find(const nvlist_t *nvl, const char *name, dat nvp = &data->nvl_pair; /* first pair in nvlist */ while (nvp->encoded_size != 0 && nvp->decoded_size != 0) { - nvp_name = (nv_string_t *)((uint8_t *)nvp + sizeof (*nvp)); + nvp_name = (nv_string_t *)((uint8_t *)nvp + sizeof(*nvp)); if (nvl->nv_data + nvl->nv_size < nvp_name->nv_data + nvp_name->nv_size) return (EIO); @@ -885,7 +924,7 @@ nvlist_find(const nvlist_t *nvl, const char *name, dat switch (nvp_data->nv_type) { case DATA_TYPE_UINT64: bcopy(nvp_data->nv_data, valuep, - sizeof (uint64_t)); + sizeof(uint64_t)); return (0); case DATA_TYPE_STRING: nvp_name = (nv_string_t *)nvp_data->nv_data; @@ -906,7 +945,7 @@ nvlist_find(const nvlist_t *nvl, const char *name, dat case DATA_TYPE_NVLIST_ARRAY: nvlist = calloc(nvp_data->nv_nelem, - sizeof (nvlist_t *)); + sizeof(nvlist_t *)); if (nvlist == NULL) return (ENOMEM); ptr = &nvp_data->nv_data[0]; @@ -957,14 +996,14 @@ get_value_size(data_type_t type, const void *data, uin case DATA_TYPE_INT32: case DATA_TYPE_UINT32: /* Our smallest data unit is 32-bit */ - value_sz = sizeof (uint32_t); + value_sz = sizeof(uint32_t); break; case DATA_TYPE_HRTIME: case DATA_TYPE_INT64: - value_sz = sizeof (int64_t); + value_sz = sizeof(int64_t); break; case DATA_TYPE_UINT64: - value_sz = sizeof (uint64_t); + value_sz = sizeof(uint64_t); break; case DATA_TYPE_STRING: if (data == NULL) @@ -973,7 +1012,7 @@ get_value_size(data_type_t type, const void *data, uin value_sz = strlen(data) + 1; break; case DATA_TYPE_BYTE_ARRAY: - value_sz = nelem * sizeof (uint8_t); + value_sz = nelem * sizeof(uint8_t); break; case DATA_TYPE_BOOLEAN_ARRAY: case DATA_TYPE_INT8_ARRAY: @@ -982,16 +1021,16 @@ get_value_size(data_type_t type, const void *data, uin case DATA_TYPE_UINT16_ARRAY: case DATA_TYPE_INT32_ARRAY: case DATA_TYPE_UINT32_ARRAY: - value_sz = (uint64_t)nelem * sizeof (uint32_t); + value_sz = (uint64_t)nelem * sizeof(uint32_t); break; case DATA_TYPE_INT64_ARRAY: - value_sz = (uint64_t)nelem * sizeof (int64_t); + value_sz = (uint64_t)nelem * sizeof(int64_t); break; case DATA_TYPE_UINT64_ARRAY: - value_sz = (uint64_t)nelem * sizeof (uint64_t); + value_sz = (uint64_t)nelem * sizeof(uint64_t); break; case DATA_TYPE_STRING_ARRAY: - value_sz = (uint64_t)nelem * sizeof (uint64_t); + value_sz = (uint64_t)nelem * sizeof(uint64_t); if (data != NULL) { char *const *strs = data; @@ -1011,7 +1050,7 @@ get_value_size(data_type_t type, const void *data, uin value_sz = NV_ALIGN(6 * 4); /* sizeof nvlist_t */ break; case DATA_TYPE_NVLIST_ARRAY: - value_sz = (uint64_t)nelem * sizeof (uint64_t) + + value_sz = (uint64_t)nelem * sizeof(uint64_t) + (uint64_t)nelem * NV_ALIGN(6 * 4); /* sizeof nvlist_t */ break; default: @@ -1041,12 +1080,12 @@ get_nvp_data_size(data_type_t type, const void *data, case DATA_TYPE_INT32: case DATA_TYPE_UINT32: /* Our smallest data unit is 32-bit */ - value_sz = sizeof (uint32_t); + value_sz = sizeof(uint32_t); break; case DATA_TYPE_HRTIME: case DATA_TYPE_INT64: case DATA_TYPE_UINT64: - value_sz = sizeof (uint64_t); + value_sz = sizeof(uint64_t); break; case DATA_TYPE_STRING: value_sz = 4 + NV_ALIGN4(strlen(data)); @@ -1061,11 +1100,11 @@ get_nvp_data_size(data_type_t type, const void *data, case DATA_TYPE_UINT16_ARRAY: case DATA_TYPE_INT32_ARRAY: case DATA_TYPE_UINT32_ARRAY: - value_sz = 4 + (uint64_t)nelem * sizeof (uint32_t); + value_sz = 4 + (uint64_t)nelem * sizeof(uint32_t); break; case DATA_TYPE_INT64_ARRAY: case DATA_TYPE_UINT64_ARRAY: - value_sz = 4 + (uint64_t)nelem * sizeof (uint64_t); + value_sz = 4 + (uint64_t)nelem * sizeof(uint64_t); break; case DATA_TYPE_STRING_ARRAY: if (data != NULL) { @@ -1120,7 +1159,14 @@ nvlist_add_common(nvlist_t *nvl, const char *name, dat uint8_t *ptr; size_t namelen; int decoded_size, encoded_size; - xdr_t xdr; + xdr_t xdr = { + .xdr_op = XDR_OP_ENCODE, + .xdr_putint = _putint_mem, + .xdr_putuint = _putuint_mem, + .xdr_buf = nvl->nv_data, + .xdr_idx = nvl->nv_data, + .xdr_buf_size = nvl->nv_size + }; nvs = (nvs_data_t *)nvl->nv_data; if (nvs->nvl_nvflag & NV_UNIQUE_NAME) @@ -1146,7 +1192,7 @@ nvlist_add_common(nvlist_t *nvl, const char *name, dat * * The decoded size is calculated as: * Note: namelen is with terminating 0. - * NV_ALIGN(sizeof (nvpair_t) (4 * 4) + namelen + 1) + + * NV_ALIGN(sizeof(nvpair_t) (4 * 4) + namelen + 1) + * NV_ALIGN(data_len) */ @@ -1160,88 +1206,133 @@ nvlist_add_common(nvlist_t *nvl, const char *name, dat nvl->nv_data = ptr; nvl->nv_asize += head.encoded_size; } - nvl->nv_idx = nvl->nv_data + nvl->nv_size - sizeof (*hp); + nvl->nv_idx = nvl->nv_data + nvl->nv_size - sizeof(*hp); bzero(nvl->nv_idx, head.encoded_size + 8); hp = (nvp_header_t *)nvl->nv_idx; *hp = head; - nvl->nv_idx += sizeof (*hp); - *(unsigned *)nvl->nv_idx = namelen; - nvl->nv_idx += sizeof (unsigned); - strlcpy((char *)nvl->nv_idx, name, namelen + 1); - nvl->nv_idx += NV_ALIGN4(namelen); - *(unsigned *)nvl->nv_idx = type; - nvl->nv_idx += sizeof (unsigned); - *(unsigned *)nvl->nv_idx = nelem; - nvl->nv_idx += sizeof (unsigned); + nvl->nv_idx += sizeof(*hp); + xdr.xdr_buf = nvl->nv_data; + xdr.xdr_idx = nvl->nv_idx; + + xdr.xdr_idx += xdr.xdr_putuint(&xdr, namelen); + strlcpy((char *)xdr.xdr_idx, name, namelen + 1); + xdr.xdr_idx += NV_ALIGN4(namelen); + xdr.xdr_idx += xdr.xdr_putuint(&xdr, type); + xdr.xdr_idx += xdr.xdr_putuint(&xdr, nelem); + switch (type) { case DATA_TYPE_BOOLEAN: break; + case DATA_TYPE_BYTE_ARRAY: - *(unsigned *)nvl->nv_idx = encoded_size; - nvl->nv_idx += sizeof (unsigned); - bcopy(data, nvl->nv_idx, nelem); - nvl->nv_idx += encoded_size; + xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); + bcopy(data, xdr.xdr_idx, nelem); + xdr.xdr_idx += NV_ALIGN4(encoded_size); break; + case DATA_TYPE_STRING: encoded_size = strlen(data); - *(unsigned *)nvl->nv_idx = encoded_size; - nvl->nv_idx += sizeof (unsigned); - strlcpy((char *)nvl->nv_idx, data, encoded_size + 1); - nvl->nv_idx += NV_ALIGN4(encoded_size); + xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); + strlcpy((char *)xdr.xdr_idx, data, encoded_size + 1); + xdr.xdr_idx += NV_ALIGN4(encoded_size); break; + case DATA_TYPE_STRING_ARRAY: for (uint32_t i = 0; i < nelem; i++) { encoded_size = strlen(((char **)data)[i]); - *(unsigned *)nvl->nv_idx = encoded_size; - nvl->nv_idx += sizeof (unsigned); - strlcpy((char *)nvl->nv_idx, ((char **)data)[i], + xdr.xdr_idx += xdr.xdr_putuint(&xdr, encoded_size); + strlcpy((char *)xdr.xdr_idx, ((char **)data)[i], encoded_size + 1); - nvl->nv_idx += NV_ALIGN4(encoded_size); + xdr.xdr_idx += NV_ALIGN4(encoded_size); } break; + case DATA_TYPE_BYTE: case DATA_TYPE_INT8: case DATA_TYPE_UINT8: + xdr_char(&xdr, (char *)data); + break; + case DATA_TYPE_INT8_ARRAY: case DATA_TYPE_UINT8_ARRAY: - for (uint32_t i = 0; i < nelem; i++) { - *(unsigned *)nvl->nv_idx = ((uint8_t *)data)[i]; - nvl->nv_idx += sizeof (unsigned); - } + xdr_array(&xdr, nelem, (xdrproc_t)xdr_char); break; + case DATA_TYPE_INT16: + xdr_short(&xdr, (short *)data); + break; + case DATA_TYPE_UINT16: + xdr_u_short(&xdr, (unsigned short *)data); + break; + case DATA_TYPE_INT16_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_short); + break; + case DATA_TYPE_UINT16_ARRAY: - for (uint32_t i = 0; i < nelem; i++) { - *(unsigned *)nvl->nv_idx = ((uint16_t *)data)[i]; - nvl->nv_idx += sizeof (unsigned); - } + xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_short); break; + + case DATA_TYPE_BOOLEAN_VALUE: + case DATA_TYPE_INT32: + xdr_int(&xdr, (int *)data); + break; + + case DATA_TYPE_UINT32: + xdr_u_int(&xdr, (unsigned int *)data); + break; + + case DATA_TYPE_BOOLEAN_ARRAY: + case DATA_TYPE_INT32_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_int); + break; + + case DATA_TYPE_UINT32_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_u_int); + break; + + case DATA_TYPE_INT64: + xdr_int64(&xdr, (int64_t *)data); + break; + + case DATA_TYPE_UINT64: + xdr_uint64(&xdr, (uint64_t *)data); + break; + + case DATA_TYPE_INT64_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_int64); + break; + + case DATA_TYPE_UINT64_ARRAY: + xdr_array(&xdr, nelem, (xdrproc_t)xdr_uint64); + break; + case DATA_TYPE_NVLIST: - bcopy(((nvlist_t *)data)->nv_data, nvl->nv_idx, encoded_size); + bcopy(((nvlist_t *)data)->nv_data, xdr.xdr_idx, encoded_size); break; + case DATA_TYPE_NVLIST_ARRAY: { - uint8_t *buf = nvl->nv_idx; size_t size; - xdr_t xdr; + xdr_t xdr_nv; for (uint32_t i = 0; i < nelem; i++) { - xdr.xdr_idx = ((nvlist_t **)data)[i]->nv_data; - xdr.xdr_buf = xdr.xdr_idx; - xdr.xdr_buf_size = ((nvlist_t **)data)[i]->nv_size; + xdr_nv.xdr_idx = ((nvlist_t **)data)[i]->nv_data; + xdr_nv.xdr_buf = xdr_nv.xdr_idx; + xdr_nv.xdr_buf_size = ((nvlist_t **)data)[i]->nv_size; - if (!nvlist_size_native(&xdr, &size)) + if (!nvlist_size_native(&xdr_nv, &size)) return (EINVAL); - bcopy(((nvlist_t **)data)[i]->nv_data, buf, size); - buf += size; + bcopy(((nvlist_t **)data)[i]->nv_data, xdr.xdr_idx, + size); + xdr.xdr_idx += size; } break; } default: - bcopy(data, nvl->nv_idx, encoded_size); + bcopy(data, xdr.xdr_idx, encoded_size); } nvl->nv_size += head.encoded_size; @@ -1465,11 +1556,17 @@ nvpair_print(nvp_header_t *nvp, unsigned int indent) nv_string_t *nvp_name; nv_pair_data_t *nvp_data; nvlist_t nvlist; - xdr_t xdr; - unsigned i, j, u; - uint64_t u64; + unsigned i, j; + xdr_t xdr = { + .xdr_op = XDR_OP_DECODE, + .xdr_getint = _getint_mem, + .xdr_getuint = _getuint_mem, + .xdr_buf = (const uint8_t *)nvp, + .xdr_idx = NULL, + .xdr_buf_size = nvp->encoded_size + }; - nvp_name = (nv_string_t *)((uintptr_t)nvp + sizeof (*nvp)); + nvp_name = (nv_string_t *)((uintptr_t)nvp + sizeof(*nvp)); nvp_data = (nv_pair_data_t *) NV_ALIGN4((uintptr_t)&nvp_name->nv_data[0] + nvp_name->nv_size); @@ -1479,32 +1576,60 @@ nvpair_print(nvp_header_t *nvp, unsigned int indent) printf("%s [%d] %.*s", typenames[nvp_data->nv_type], nvp_data->nv_nelem, nvp_name->nv_size, nvp_name->nv_data); + xdr.xdr_idx = nvp_data->nv_data; switch (nvp_data->nv_type) { case DATA_TYPE_BYTE: case DATA_TYPE_INT8: - case DATA_TYPE_UINT8: - bcopy(nvp_data->nv_data, &u, sizeof (u)); - printf(" = 0x%x\n", (unsigned char)u); + case DATA_TYPE_UINT8: { + char c; + + if (xdr_char(&xdr, &c)) + printf(" = 0x%x\n", c); break; + } case DATA_TYPE_INT16: - case DATA_TYPE_UINT16: - bcopy(nvp_data->nv_data, &u, sizeof (u)); - printf(" = 0x%hx\n", (unsigned short)u); + case DATA_TYPE_UINT16: { + unsigned short u; + + if (xdr_u_short(&xdr, &u)) + printf(" = 0x%hx\n", u); break; + } case DATA_TYPE_BOOLEAN_VALUE: case DATA_TYPE_INT32: - case DATA_TYPE_UINT32: - bcopy(nvp_data->nv_data, &u, sizeof (u)); - printf(" = 0x%x\n", u); + case DATA_TYPE_UINT32: { + unsigned u; + + if (xdr_u_int(&xdr, &u)) + printf(" = 0x%x\n", u); break; + } case DATA_TYPE_INT64: - case DATA_TYPE_UINT64: - bcopy(nvp_data->nv_data, &u64, sizeof (u64)); - printf(" = 0x%jx\n", (uintmax_t)u64); + case DATA_TYPE_UINT64: { + uint64_t u; + + if (xdr_uint64(&xdr, &u)) + printf(" = 0x%jx\n", (uintmax_t)u); break; + } + + case DATA_TYPE_INT64_ARRAY: + case DATA_TYPE_UINT64_ARRAY: { + uint64_t *u; + + if (xdr_array(&xdr, nvp_data->nv_nelem, + (xdrproc_t)xdr_uint64)) { + u = (uint64_t *)(nvp_data->nv_data + sizeof(unsigned)); + for (i = 0; i < nvp_data->nv_nelem; i++) + printf(" [%u] = 0x%jx", i, (uintmax_t)u[i]); + printf("\n"); + } + + break; + } case DATA_TYPE_STRING: case DATA_TYPE_STRING_ARRAY: