aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2021-08-06 12:02:39 +0200
committerKarel Zak <kzak@redhat.com>2021-08-06 12:02:39 +0200
commit9ea47344ca59f1fb9fc5dfb11f223a309c0644e3 (patch)
treec82ffd4e7eecfdb1f4a3d469576aca89783e3d3c
parentf55be401884d651350f15881cb5a9b8a8f120b24 (diff)
downloadutil-linux-9ea47344ca59f1fb9fc5dfb11f223a309c0644e3.tar.gz
lib/buffer: add support for "safe" encoding
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--include/buffer.h9
-rw-r--r--lib/Makemodule.am2
-rw-r--r--lib/buffer.c67
-rw-r--r--libmount/src/optstr.c14
-rw-r--r--misc-utils/lsblk.c4
5 files changed, 80 insertions, 16 deletions
diff --git a/include/buffer.h b/include/buffer.h
index 5c081fb81f..724bcbe90a 100644
--- a/include/buffer.h
+++ b/include/buffer.h
@@ -10,6 +10,9 @@ struct ul_buffer {
size_t sz; /* allocated space for data */
size_t chunksize;
+ char *encoded; /* encoded data (from mbs_safe_encode_to_buffer)) */
+ size_t encoded_sz; /* space allocated for encoded data */
+
char **ptrs; /* saved pointers */
size_t nptrs; /* number of saved poiters */
};
@@ -26,12 +29,16 @@ int ul_buffer_append_data(struct ul_buffer *buf, const char *data, size_t sz);
int ul_buffer_append_string(struct ul_buffer *buf, const char *str);
int ul_buffer_append_ntimes(struct ul_buffer *buf, size_t n, const char *str);
int ul_buffer_set_data(struct ul_buffer *buf, const char *data, size_t sz);
-char *ul_buffer_get_data(struct ul_buffer *buf, size_t *sz);
+
+char *ul_buffer_get_data(struct ul_buffer *buf, size_t *sz, size_t *width);
+char *ul_buffer_get_safe_data(struct ul_buffer *buf, size_t *sz, size_t *width, const char *safechars);
+
size_t ul_buffer_get_bufsiz(struct ul_buffer *buf);
int ul_buffer_save_pointer(struct ul_buffer *buf, unsigned short ptr_idx);
char *ul_buffer_get_pointer(struct ul_buffer *buf, unsigned short ptr_idx);
size_t ul_buffer_get_pointer_length(struct ul_buffer *buf, unsigned short ptr_idx);
+size_t ul_buffer_get_safe_pointer_width(struct ul_buffer *buf, unsigned short ptr_idx);
#endif /* UTIL_LINUX_BUFFER */
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 1cdd1b146c..d32a20a2c4 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -203,7 +203,7 @@ test_pwdutils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM
test_remove_env_SOURCES = lib/env.c
test_remove_env_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM
-test_buffer_SOURCES = lib/buffer.c
+test_buffer_SOURCES = lib/buffer.c lib/mbsalign.c
test_buffer_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_BUFFER
if LINUX
diff --git a/lib/buffer.c b/lib/buffer.c
index 3c112dd9de..b63b3684a9 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -5,6 +5,7 @@
* Written by Karel Zak <kzak@redhat.com>
*/
#include "buffer.h"
+#include "mbsalign.h"
void ul_buffer_reset_data(struct ul_buffer *buf)
{
@@ -26,6 +27,10 @@ void ul_buffer_free_data(struct ul_buffer *buf)
free(buf->ptrs);
buf->ptrs = NULL;
buf->nptrs = 0;
+
+ free(buf->encoded);
+ buf->encoded = NULL;
+ buf->encoded_sz = 0;
}
void ul_buffer_set_chunksize(struct ul_buffer *buf, size_t sz)
@@ -61,15 +66,26 @@ char *ul_buffer_get_pointer(struct ul_buffer *buf, unsigned short ptr_idx)
return NULL;
}
+/* returns length from begin to the pointer */
size_t ul_buffer_get_pointer_length(struct ul_buffer *buf, unsigned short ptr_idx)
{
char *ptr = ul_buffer_get_pointer(buf, ptr_idx);
- if (ptr)
+ if (ptr && ptr > buf->begin)
return ptr - buf->begin;
return 0;
}
+/* returns width of data in safe encoding (from the begin to the pointer) */
+size_t ul_buffer_get_safe_pointer_width(struct ul_buffer *buf, unsigned short ptr_idx)
+{
+ size_t len = ul_buffer_get_pointer_length(buf, ptr_idx);
+
+ if (!len)
+ return 0;
+
+ return mbs_safe_nwidth(buf->begin, len, NULL);
+}
void ul_buffer_refer_string(struct ul_buffer *buf, char *str)
{
@@ -157,10 +173,12 @@ int ul_buffer_set_data(struct ul_buffer *buf, const char *data, size_t sz)
return ul_buffer_append_data(buf, data, sz);
}
-char *ul_buffer_get_data(struct ul_buffer *buf, size_t *sz)
+char *ul_buffer_get_data(struct ul_buffer *buf, size_t *sz, size_t *width)
{
if (sz)
*sz = buf->end - buf->begin;
+ if (width)
+ *width = buf->begin && *buf->begin ? mbs_width(buf->begin) : 0;
return buf->begin;
}
@@ -170,6 +188,42 @@ size_t ul_buffer_get_bufsiz(struct ul_buffer *buf)
return buf->sz;
}
+/* encode data by mbs_safe_encode() to avoid control and non-printable chars */
+char *ul_buffer_get_safe_data(struct ul_buffer *buf, size_t *sz, size_t *width, const char *safechars)
+{
+ char *data = ul_buffer_get_data(buf, NULL, NULL);
+ size_t encsz, wsz = 0;
+ char *res = NULL;
+
+ if (!data)
+ goto nothing;
+
+ encsz = mbs_safe_encode_size(buf->sz) + 1;
+ if (encsz > buf->encoded_sz) {
+ char *tmp = realloc(buf->encoded, encsz);
+ if (!tmp)
+ goto nothing;
+ buf->encoded = tmp;
+ buf->encoded_sz = encsz;
+ }
+
+ res = mbs_safe_encode_to_buffer(data, &wsz, buf->encoded, safechars);
+ if (!res || !wsz || wsz == (size_t) -1)
+ goto nothing;
+
+ if (width)
+ *width = wsz;
+ if (sz)
+ *sz = strlen(res);
+ return res;
+nothing:
+ if (width)
+ *width = 0;
+ if (sz)
+ *sz = 0;
+ return NULL;
+}
+
#ifdef TEST_PROGRAM_BUFFER
@@ -197,18 +251,21 @@ int main(void)
ul_buffer_append_string(&buf, "bbb");
ul_buffer_save_pointer(&buf, PTR_BBB);
- str = ul_buffer_get_data(&buf, &sz);
+ str = ul_buffer_get_data(&buf, &sz, NULL);
printf("data [%zu] '%s'\n", sz, str);
printf(" pointer data len: AAA=%zu, BBB=%zu\n",
ul_buffer_get_pointer_length(&buf, PTR_AAA),
ul_buffer_get_pointer_length(&buf, PTR_BBB));
+ printf(" pointer data width: AAA=%zu, BBB=%zu\n",
+ ul_buffer_get_safe_pointer_width(&buf, PTR_AAA),
+ ul_buffer_get_safe_pointer_width(&buf, PTR_BBB));
ul_buffer_reset_data(&buf);
ul_buffer_append_string(&buf, "This is really long string to test the buffer function.");
ul_buffer_save_pointer(&buf, PTR_AAA);
ul_buffer_append_string(&buf, " YES!");
- str = ul_buffer_get_data(&buf, &sz);
+ str = ul_buffer_get_data(&buf, &sz, NULL);
printf("data [%zu] '%s'\n", sz, str);
printf(" pointer data len: AAA=%zu\n", ul_buffer_get_pointer_length(&buf, PTR_AAA));
@@ -217,7 +274,7 @@ int main(void)
ul_buffer_refer_string(&buf, str);
ul_buffer_append_data(&buf, ",", 1);
ul_buffer_append_string(&buf, "bar");
- str = ul_buffer_get_data(&buf, &sz);
+ str = ul_buffer_get_data(&buf, &sz, NULL);
printf("data [%zu] '%s'\n", sz, str);
ul_buffer_free_data(&buf);
diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c
index d37c7bcd42..21707d1ed3 100644
--- a/libmount/src/optstr.c
+++ b/libmount/src/optstr.c
@@ -224,7 +224,7 @@ int mnt_optstr_append_option(char **optstr, const char *name, const char *value)
rc = __buffer_append_option(&buf, name, nsz, value, vsz);
- *optstr = ul_buffer_get_data(&buf, NULL);
+ *optstr = ul_buffer_get_data(&buf, NULL, NULL);
return rc;
}
/**
@@ -261,7 +261,7 @@ int mnt_optstr_prepend_option(char **optstr, const char *name, const char *value
free(*optstr);
}
- *optstr = ul_buffer_get_data(&buf, NULL);
+ *optstr = ul_buffer_get_data(&buf, NULL, NULL);
return rc;
}
@@ -558,11 +558,11 @@ int mnt_split_optstr(const char *optstr, char **user, char **vfs,
}
if (vfs)
- *vfs = rc ? NULL : ul_buffer_get_data(&xvfs, NULL);
+ *vfs = rc ? NULL : ul_buffer_get_data(&xvfs, NULL, NULL);
if (fs)
- *fs = rc ? NULL : ul_buffer_get_data(&xfs, NULL);
+ *fs = rc ? NULL : ul_buffer_get_data(&xfs, NULL, NULL);
if (user)
- *user = rc ? NULL : ul_buffer_get_data(&xuser, NULL);
+ *user = rc ? NULL : ul_buffer_get_data(&xuser, NULL, NULL);
if (rc) {
ul_buffer_free_data(&xvfs);
ul_buffer_free_data(&xfs);
@@ -626,7 +626,7 @@ int mnt_optstr_get_options(const char *optstr, char **subset,
break;
}
- *subset = rc ? NULL : ul_buffer_get_data(&buf, NULL);
+ *subset = rc ? NULL : ul_buffer_get_data(&buf, NULL, NULL);
if (rc)
ul_buffer_free_data(&buf);
return rc;
@@ -834,7 +834,7 @@ int mnt_optstr_apply_flags(char **optstr, unsigned long flags,
goto err;
}
- *optstr = ul_buffer_get_data(&buf, NULL);
+ *optstr = ul_buffer_get_data(&buf, NULL, NULL);
}
DBG(CXT, ul_debug("new optstr '%s'", *optstr));
diff --git a/misc-utils/lsblk.c b/misc-utils/lsblk.c
index 4a501eda09..100eba0779 100644
--- a/misc-utils/lsblk.c
+++ b/misc-utils/lsblk.c
@@ -820,7 +820,7 @@ static char *device_get_data(
if (i + 1 < n)
ul_buffer_append_data(&buf, "\n", 1);
}
- str = ul_buffer_get_data(&buf, NULL);
+ str = ul_buffer_get_data(&buf, NULL, NULL);
break;
}
case COL_FSROOTS:
@@ -838,7 +838,7 @@ static char *device_get_data(
if (i + 1 < n)
ul_buffer_append_data(&buf, "\n", 1);
}
- str = ul_buffer_get_data(&buf, NULL);
+ str = ul_buffer_get_data(&buf, NULL, NULL);
break;
}
case COL_LABEL: