]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/buffer: add support for "safe" encoding
authorKarel Zak <kzak@redhat.com>
Fri, 6 Aug 2021 10:02:39 +0000 (12:02 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 6 Aug 2021 10:02:39 +0000 (12:02 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
include/buffer.h
lib/Makemodule.am
lib/buffer.c
libmount/src/optstr.c
misc-utils/lsblk.c

index 5c081fb81f6a55a3d7895926e97762c3c4e23265..724bcbe90a0a1fe95c18a7c54b7cde22d22d176a 100644 (file)
@@ -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 */
index 1cdd1b146c6fe7c0062ae43f5369c83622b67ebb..d32a20a2c40fb9c42e569cfe01424de03b2b21f1 100644 (file)
@@ -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
index 3c112dd9de6174146272dbcd7f24ae684e6eec8c..b63b3684a97f19fde6870bb2541500e94adeb6d3 100644 (file)
@@ -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);
index d37c7bcd42b95b9adaf7803808dc222293c3c50c..21707d1ed30ef00f4a8dc637fe2a7db4ba4fd105 100644 (file)
@@ -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));
index 4a501eda0990112458cd3e754b3e666eeefe0d16..100eba0779f8823086192e7b8aabf9c89219362d 100644 (file)
@@ -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: