diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2026-02-05 13:36:27 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2026-02-05 13:36:27 +0100 |
| commit | fddd93edbdbf8c5afbfdb3c01d82e082a8a82d1a (patch) | |
| tree | bc67c4cd3acea69333eb7bb4d8d4d904d5d6027a | |
| parent | 3d572a8cc3d71b43877db2776882e91303a0532d (diff) | |
| download | busybox-w32-fddd93edbdbf8c5afbfdb3c01d82e082a8a82d1a.tar.gz busybox-w32-fddd93edbdbf8c5afbfdb3c01d82e082a8a82d1a.tar.bz2 busybox-w32-fddd93edbdbf8c5afbfdb3c01d82e082a8a82d1a.zip | |
libbb: introduce and use xasprintf_inplace()
function old new delta
xasprintf_and_free - 49 +49
watch_main 269 282 +13
singlemount 1313 1315 +2
append_mount_options 157 149 -8
ip_port_str 122 112 -10
lsblk_main 869 858 -11
add_cmd 1178 1167 -11
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/4 up/down: 64/-40) Total: 24 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | editors/sed.c | 5 | ||||
| -rw-r--r-- | include/libbb.h | 2 | ||||
| -rw-r--r-- | libbb/xfuncs_printf.c | 16 | ||||
| -rw-r--r-- | modutils/modprobe-small.c | 4 | ||||
| -rw-r--r-- | networking/ifupdown.c | 5 | ||||
| -rw-r--r-- | networking/netstat.c | 7 | ||||
| -rw-r--r-- | procps/watch.c | 7 | ||||
| -rw-r--r-- | util-linux/lsblk.c | 11 | ||||
| -rw-r--r-- | util-linux/mount.c | 25 |
9 files changed, 48 insertions, 34 deletions
diff --git a/editors/sed.c b/editors/sed.c index 6179c5e80..029e9b8e7 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
| @@ -657,9 +657,8 @@ static void add_cmd(const char *cmdstr) | |||
| 657 | 657 | ||
| 658 | /* Append this line to any unfinished line from last time. */ | 658 | /* Append this line to any unfinished line from last time. */ |
| 659 | if (G.add_cmd_line) { | 659 | if (G.add_cmd_line) { |
| 660 | char *tp = xasprintf("%s\n%s", G.add_cmd_line, cmdstr); | 660 | cmdstr = xasprintf_inplace(G.add_cmd_line, |
| 661 | free(G.add_cmd_line); | 661 | "%s\n%s", G.add_cmd_line, cmdstr); |
| 662 | cmdstr = G.add_cmd_line = tp; | ||
| 663 | } | 662 | } |
| 664 | 663 | ||
| 665 | /* If this line ends with unescaped backslash, request next line. */ | 664 | /* If this line ends with unescaped backslash, request next line. */ |
diff --git a/include/libbb.h b/include/libbb.h index 7cca925b9..6ce01ea94 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -950,6 +950,8 @@ int bb_putchar(int ch) FAST_FUNC; | |||
| 950 | int bb_putchar_stderr(char ch) FAST_FUNC; | 950 | int bb_putchar_stderr(char ch) FAST_FUNC; |
| 951 | int fputs_stdout(const char *s) FAST_FUNC; | 951 | int fputs_stdout(const char *s) FAST_FUNC; |
| 952 | char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) FAST_FUNC RETURNS_MALLOC; | 952 | char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) FAST_FUNC RETURNS_MALLOC; |
| 953 | char *xasprintf_and_free(char *allocated, const char *format, ...) __attribute__ ((format(printf, 2, 3))) FAST_FUNC RETURNS_MALLOC; | ||
| 954 | #define xasprintf_inplace(allocated, ...) ((allocated) = xasprintf_and_free((allocated), __VA_ARGS__)) | ||
| 953 | char *auto_string(char *str) FAST_FUNC; | 955 | char *auto_string(char *str) FAST_FUNC; |
| 954 | // gcc-4.1.1 still isn't good enough at optimizing it | 956 | // gcc-4.1.1 still isn't good enough at optimizing it |
| 955 | // (+200 bytes compared to macro) | 957 | // (+200 bytes compared to macro) |
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 5d26e2bfa..ed10084b3 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
| @@ -349,6 +349,22 @@ char* FAST_FUNC xasprintf(const char *format, ...) | |||
| 349 | return string_ptr; | 349 | return string_ptr; |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | char* FAST_FUNC xasprintf_and_free(char *allocated, const char *format, ...) | ||
| 353 | { | ||
| 354 | va_list p; | ||
| 355 | int r; | ||
| 356 | char *string_ptr; | ||
| 357 | |||
| 358 | va_start(p, format); | ||
| 359 | r = vasprintf(&string_ptr, format, p); | ||
| 360 | va_end(p); | ||
| 361 | |||
| 362 | if (r < 0) | ||
| 363 | bb_die_memory_exhausted(); | ||
| 364 | free(allocated); | ||
| 365 | return string_ptr; | ||
| 366 | } | ||
| 367 | |||
| 352 | void FAST_FUNC xsetenv(const char *key, const char *value) | 368 | void FAST_FUNC xsetenv(const char *key, const char *value) |
| 353 | { | 369 | { |
| 354 | if (setenv(key, value, 1)) | 370 | if (setenv(key, value, 1)) |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 31a215a29..b3c0768ee 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
| @@ -1010,9 +1010,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
| 1010 | char **arg = argv; | 1010 | char **arg = argv; |
| 1011 | while (*++arg) { | 1011 | while (*++arg) { |
| 1012 | /* Enclose options in quotes */ | 1012 | /* Enclose options in quotes */ |
| 1013 | char *s = options; | 1013 | xasprintf_inplace(options, "%s \"%s\"", options ? options : "", *arg); |
| 1014 | options = xasprintf("%s \"%s\"", s ? s : "", *arg); | ||
| 1015 | free(s); | ||
| 1016 | *arg = NULL; | 1014 | *arg = NULL; |
| 1017 | } | 1015 | } |
| 1018 | # else | 1016 | # else |
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 9c3640be7..bc2dca506 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
| @@ -895,16 +895,15 @@ static struct interfaces_file_t *read_interfaces(const char *filename, struct in | |||
| 895 | while ((buf = xmalloc_fgetline(f)) != NULL) { | 895 | while ((buf = xmalloc_fgetline(f)) != NULL) { |
| 896 | #if ENABLE_DESKTOP | 896 | #if ENABLE_DESKTOP |
| 897 | /* Trailing "\" concatenates lines */ | 897 | /* Trailing "\" concatenates lines */ |
| 898 | //TODO: check how to handle "line\\" (double backslashes) | ||
| 898 | char *p; | 899 | char *p; |
| 899 | while ((p = last_char_is(buf, '\\')) != NULL) { | 900 | while ((p = last_char_is(buf, '\\')) != NULL) { |
| 900 | *p = '\0'; | 901 | *p = '\0'; |
| 901 | rest_of_line = xmalloc_fgetline(f); | 902 | rest_of_line = xmalloc_fgetline(f); |
| 902 | if (!rest_of_line) | 903 | if (!rest_of_line) |
| 903 | break; | 904 | break; |
| 904 | p = xasprintf("%s%s", buf, rest_of_line); | 905 | xasprintf_inplace(buf, "%s%s", buf, rest_of_line); |
| 905 | free(buf); | ||
| 906 | free(rest_of_line); | 906 | free(rest_of_line); |
| 907 | buf = p; | ||
| 908 | } | 907 | } |
| 909 | #endif | 908 | #endif |
| 910 | rest_of_line = buf; | 909 | rest_of_line = buf; |
diff --git a/networking/netstat.c b/networking/netstat.c index 807800a62..d7afa8fdd 100644 --- a/networking/netstat.c +++ b/networking/netstat.c | |||
| @@ -391,7 +391,7 @@ static const char *get_sname(int port, const char *proto, int numeric) | |||
| 391 | 391 | ||
| 392 | static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric) | 392 | static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric) |
| 393 | { | 393 | { |
| 394 | char *host, *host_port; | 394 | char *host; |
| 395 | 395 | ||
| 396 | /* Code which used "*" for INADDR_ANY is removed: it's ambiguous | 396 | /* Code which used "*" for INADDR_ANY is removed: it's ambiguous |
| 397 | * in IPv6, while "0.0.0.0" is not. */ | 397 | * in IPv6, while "0.0.0.0" is not. */ |
| @@ -402,9 +402,8 @@ static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int | |||
| 402 | if (!host) | 402 | if (!host) |
| 403 | host = xmalloc_sockaddr2dotted_noport(addr); | 403 | host = xmalloc_sockaddr2dotted_noport(addr); |
| 404 | 404 | ||
| 405 | host_port = xasprintf("%s:%s", host, get_sname(htons(port), proto, numeric)); | 405 | xasprintf_inplace(host, "%s:%s", host, get_sname(htons(port), proto, numeric)); |
| 406 | free(host); | 406 | return host; |
| 407 | return host_port; | ||
| 408 | } | 407 | } |
| 409 | 408 | ||
| 410 | struct inet_params { | 409 | struct inet_params { |
diff --git a/procps/watch.c b/procps/watch.c index b376fdc33..b828079e5 100644 --- a/procps/watch.c +++ b/procps/watch.c | |||
| @@ -76,12 +76,9 @@ int watch_main(int argc UNUSED_PARAM, char **argv) | |||
| 76 | // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param. | 76 | // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param. |
| 77 | argv0 = argv; | 77 | argv0 = argv; |
| 78 | // If -x, cmd is only used for printing header | 78 | // If -x, cmd is only used for printing header |
| 79 | cmd = *argv; | 79 | cmd = xstrdup(*argv); |
| 80 | while (*++argv) | 80 | while (*++argv) |
| 81 | cmd = xasprintf("%s %s", cmd, *argv); | 81 | xasprintf_inplace(cmd, "%s %s", cmd, *argv); |
| 82 | //leaks cmd ^^^ | ||
| 83 | //TODO: create and use xasprintf_inplace(DST, fmt, args_one_of_which_is_DST) | ||
| 84 | //which frees old DST? | ||
| 85 | if (opt & (1 << 3)) | 82 | if (opt & (1 << 3)) |
| 86 | argv = argv0; // If -x, restore argv[0] to !NULL | 83 | argv = argv0; // If -x, restore argv[0] to !NULL |
| 87 | 84 | ||
diff --git a/util-linux/lsblk.c b/util-linux/lsblk.c index a482bfbbc..3bd40bcb4 100644 --- a/util-linux/lsblk.c +++ b/util-linux/lsblk.c | |||
| @@ -101,10 +101,10 @@ static char *get_mountpoints(const char *majmin) | |||
| 101 | 101 | ||
| 102 | mountpoints = NULL; | 102 | mountpoints = NULL; |
| 103 | len = strlen(majmin); | 103 | len = strlen(majmin); |
| 104 | p = G.mountinfo; // "/proc/self/mountinfo" | 104 | p = G.mountinfo; // contents of "/proc/self/mountinfo" |
| 105 | /* lines a-la "63 1 259:3 / /MNTPOINT per-mount_options - ext4 /dev/NAME per-superblock_options" */ | 105 | /* lines a-la "63 1 259:3 / /MNTPOINT per-mount_options - ext4 /dev/NAME per-superblock_options" */ |
| 106 | while (*p) { | 106 | while (*p) { |
| 107 | char *e, *f; | 107 | char *e; |
| 108 | 108 | ||
| 109 | p = skip_non_whitespace(p); | 109 | p = skip_non_whitespace(p); |
| 110 | if (*p != ' ') break; | 110 | if (*p != ' ') break; |
| @@ -127,12 +127,11 @@ static char *get_mountpoints(const char *majmin) | |||
| 127 | // at " /MNTPOINT" | 127 | // at " /MNTPOINT" |
| 128 | e = skip_non_whitespace(p + 1); | 128 | e = skip_non_whitespace(p + 1); |
| 129 | // e is at the end of " /MNTPOINT" | 129 | // e is at the end of " /MNTPOINT" |
| 130 | f = mountpoints; | ||
| 131 | // NO. We return " /MNT1 /MNT2 /MNT3" _with_ leading space! | 130 | // NO. We return " /MNT1 /MNT2 /MNT3" _with_ leading space! |
| 132 | // if (!f) | 131 | // if (!mountpoints) |
| 133 | // p++; | 132 | // p++; |
| 134 | mountpoints = xasprintf("%s%.*s", f ? f : "", (int)(e - p), p); | 133 | xasprintf_inplace(mountpoints, "%s%.*s", |
| 135 | free(f); | 134 | mountpoints ? mountpoints : "", (int)(e - p), p); |
| 136 | } | 135 | } |
| 137 | return mountpoints; | 136 | return mountpoints; |
| 138 | } | 137 | } |
diff --git a/util-linux/mount.c b/util-linux/mount.c index d0f0ae1ad..d0d109c09 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
| @@ -556,27 +556,33 @@ static int verbose_mount(const char *source, const char *target, | |||
| 556 | #endif | 556 | #endif |
| 557 | 557 | ||
| 558 | // Append mount options to string | 558 | // Append mount options to string |
| 559 | // ("merge two comma-separated lists" is a good candidate for libbb!) | ||
| 559 | static void append_mount_options(char **oldopts, const char *newopts) | 560 | static void append_mount_options(char **oldopts, const char *newopts) |
| 560 | { | 561 | { |
| 561 | if (*oldopts && **oldopts) { | 562 | if (*oldopts && **oldopts) { |
| 563 | //TODO: do this unconditionally? | ||
| 564 | //this way, newopts of "opt1,opt2,opt1" | ||
| 565 | //will be de-duped into "opt1,opt2" in _both_ cases | ||
| 566 | //(whether or now old opts are empty) | ||
| 567 | //the only modification needed is to not prepend extra comma | ||
| 568 | //when old opts is "". | ||
| 562 | // Do not insert options which are already there | 569 | // Do not insert options which are already there |
| 563 | while (newopts[0]) { | 570 | while (*newopts) { |
| 564 | char *p; | 571 | char *p; |
| 565 | int len; | 572 | int len; |
| 566 | 573 | ||
| 574 | //if (*newopts == ',') { newopts++; continue; } | ||
| 567 | len = strchrnul(newopts, ',') - newopts; | 575 | len = strchrnul(newopts, ',') - newopts; |
| 568 | p = *oldopts; | 576 | p = *oldopts; |
| 569 | while (1) { | 577 | while (1) { |
| 570 | if (!strncmp(p, newopts, len) | 578 | if (strncmp(p, newopts, len) == 0 |
| 571 | && (p[len] == ',' || p[len] == '\0')) | 579 | && (p[len] == ',' || p[len] == '\0')) |
| 572 | goto skip; | 580 | goto skip; |
| 573 | p = strchr(p,','); | 581 | p = strchr(p, ','); |
| 574 | if (!p) break; | 582 | if (!p) break; |
| 575 | p++; | 583 | p++; |
| 576 | } | 584 | } |
| 577 | p = xasprintf("%s,%.*s", *oldopts, len, newopts); | 585 | xasprintf_inplace(*oldopts, "%s,%.*s", *oldopts, len, newopts); |
| 578 | free(*oldopts); | ||
| 579 | *oldopts = p; | ||
| 580 | skip: | 586 | skip: |
| 581 | newopts += len; | 587 | newopts += len; |
| 582 | while (*newopts == ',') newopts++; | 588 | while (*newopts == ',') newopts++; |
| @@ -2065,12 +2071,11 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
| 2065 | if (!is_prefixed_with(filteropts, ",ip="+1) | 2071 | if (!is_prefixed_with(filteropts, ",ip="+1) |
| 2066 | && !strstr(filteropts, ",ip=") | 2072 | && !strstr(filteropts, ",ip=") |
| 2067 | ) { | 2073 | ) { |
| 2068 | char *dotted, *ip; | 2074 | char *ip; |
| 2069 | // Insert "ip=..." option into options | 2075 | // Insert "ip=..." option into options |
| 2070 | dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); | 2076 | ip = xmalloc_sockaddr2dotted_noport(&lsa->u.sa); |
| 2071 | if (ENABLE_FEATURE_CLEAN_UP) free(lsa); | 2077 | if (ENABLE_FEATURE_CLEAN_UP) free(lsa); |
| 2072 | ip = xasprintf("ip=%s", dotted); | 2078 | xasprintf_inplace(ip, "ip=%s", ip); |
| 2073 | if (ENABLE_FEATURE_CLEAN_UP) free(dotted); | ||
| 2074 | // Note: IPv6 scoped addresses ("host%iface", see RFC 4007) should be | 2079 | // Note: IPv6 scoped addresses ("host%iface", see RFC 4007) should be |
| 2075 | // handled by libc in getnameinfo() (inside xmalloc_sockaddr2dotted_noport()). | 2080 | // handled by libc in getnameinfo() (inside xmalloc_sockaddr2dotted_noport()). |
| 2076 | // Currently, glibc does not support that (has no NI_NUMERICSCOPE), | 2081 | // Currently, glibc does not support that (has no NI_NUMERICSCOPE), |
