summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/hexdecoct.c61
-rw-r--r--src/basic/hexdecoct.h5
-rw-r--r--src/resolve/resolved-dns-rr.c33
-rw-r--r--src/test/test-util.c21
4 files changed, 90 insertions, 30 deletions
diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c
index 1e907de228..f30e028f45 100644
--- a/src/basic/hexdecoct.c
+++ b/src/basic/hexdecoct.c
@@ -514,14 +514,14 @@ int unbase64char(char c) {
return -EINVAL;
}
-char *base64mem(const void *p, size_t l) {
+ssize_t base64mem(const void *p, size_t l, char **out) {
char *r, *z;
const uint8_t *x;
/* three input bytes makes four output bytes, padding is added so we must round up */
z = r = malloc(4 * (l + 2) / 3 + 1);
if (!r)
- return NULL;
+ return -ENOMEM;
for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
@@ -549,9 +549,64 @@ char *base64mem(const void *p, size_t l) {
}
*z = 0;
- return r;
+ *out = r;
+ return z - r;
+}
+
+static int base64_append_width(char **prefix, int plen,
+ const char *sep, int indent,
+ const void *p, size_t l,
+ int width) {
+
+ _cleanup_free_ char *x = NULL;
+ char *t, *s;
+ ssize_t slen, len, avail;
+ int line, lines;
+
+ len = base64mem(p, l, &x);
+ if (len <= 0)
+ return len;
+
+ lines = (len + width - 1) / width;
+
+ slen = sep ? strlen(sep) : 0;
+ t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
+ if (!t)
+ return -ENOMEM;
+
+ memcpy(t + plen, sep, slen);
+
+ for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
+ int act = MIN(width, avail);
+
+ if (line > 0 || sep) {
+ memset(s, ' ', indent);
+ s += indent;
+ }
+
+ memcpy(s, x + width * line, act);
+ s += act;
+ *(s++) = line < lines - 1 ? '\n' : '\0';
+ avail -= act;
+ }
+ assert(avail == 0);
+
+ *prefix = t;
+ return 0;
}
+int base64_append(char **prefix, int plen,
+ const void *p, size_t l,
+ int indent, int width) {
+ if (plen > width / 2 || plen + indent > width)
+ /* leave indent on the left, keep last column free */
+ return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
+ else
+ /* leave plen on the left, keep last column free */
+ return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
+};
+
+
int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
_cleanup_free_ uint8_t *r = NULL;
int a, b, c, d;
diff --git a/src/basic/hexdecoct.h b/src/basic/hexdecoct.h
index d9eb54a8a1..243c5e921e 100644
--- a/src/basic/hexdecoct.h
+++ b/src/basic/hexdecoct.h
@@ -49,7 +49,10 @@ int unbase64char(char c) _const_;
char *base32hexmem(const void *p, size_t l, bool padding);
int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
-char *base64mem(const void *p, size_t l);
+ssize_t base64mem(const void *p, size_t l, char **out);
+int base64_append(char **prefix, int plen,
+ const void *p, size_t l,
+ int margin, int width);
int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
void hexdump(FILE *f, const void *p, size_t s);
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
index 7273ef3825..a3df8d5aff 100644
--- a/src/resolve/resolved-dns-rr.c
+++ b/src/resolve/resolved-dns-rr.c
@@ -30,6 +30,7 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "terminal-util.h"
DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
DnsResourceKey *k;
@@ -958,23 +959,27 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
case DNS_TYPE_DNSKEY: {
_cleanup_free_ char *alg = NULL;
+ int n;
r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
if (r < 0)
return NULL;
- t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
- if (!t)
- return NULL;
-
- r = asprintf(&s, "%s %u %u %s %s",
+ r = asprintf(&s, "%s %u %u %s %n",
k,
rr->dnskey.flags,
rr->dnskey.protocol,
alg,
- t);
+ &n);
if (r < 0)
return NULL;
+
+ r = base64_append(&s, n,
+ rr->dnskey.key, rr->dnskey.key_size,
+ 8, columns());
+ if (r < 0)
+ return NULL;
+
break;
}
@@ -982,6 +987,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
_cleanup_free_ char *alg = NULL;
char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
const char *type;
+ int n;
type = dns_type_to_string(rr->rrsig.type_covered);
@@ -989,10 +995,6 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
if (r < 0)
return NULL;
- t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
- if (!t)
- return NULL;
-
r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
if (r < 0)
return NULL;
@@ -1004,7 +1006,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
/* TYPE?? follows
* http://tools.ietf.org/html/rfc3597#section-5 */
- r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %s",
+ r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n",
k,
type ?: "TYPE",
type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
@@ -1015,9 +1017,16 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
inception,
rr->rrsig.key_tag,
rr->rrsig.signer,
- t);
+ &n);
if (r < 0)
return NULL;
+
+ r = base64_append(&s, n,
+ rr->rrsig.signature, rr->rrsig.signature_size,
+ 8, columns());
+ if (r < 0)
+ return NULL;
+
break;
}
diff --git a/src/test/test-util.c b/src/test/test-util.c
index f6ed55878c..e199497818 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -545,38 +545,31 @@ static void test_unbase32hexmem(void) {
static void test_base64mem(void) {
char *b64;
- b64 = base64mem("", strlen(""));
- assert_se(b64);
+ assert_se(base64mem("", strlen(""), &b64) == 0);
assert_se(streq(b64, ""));
free(b64);
- b64 = base64mem("f", strlen("f"));
- assert_se(b64);
+ assert_se(base64mem("f", strlen("f"), &b64) == 4);
assert_se(streq(b64, "Zg=="));
free(b64);
- b64 = base64mem("fo", strlen("fo"));
- assert_se(b64);
+ assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
assert_se(streq(b64, "Zm8="));
free(b64);
- b64 = base64mem("foo", strlen("foo"));
- assert_se(b64);
+ assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
assert_se(streq(b64, "Zm9v"));
free(b64);
- b64 = base64mem("foob", strlen("foob"));
- assert_se(b64);
+ assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
assert_se(streq(b64, "Zm9vYg=="));
free(b64);
- b64 = base64mem("fooba", strlen("fooba"));
- assert_se(b64);
+ assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmE="));
free(b64);
- b64 = base64mem("foobar", strlen("foobar"));
- assert_se(b64);
+ assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
assert_se(streq(b64, "Zm9vYmFy"));
free(b64);
}