aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2026-02-05 13:36:27 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2026-02-05 13:36:27 +0100
commitfddd93edbdbf8c5afbfdb3c01d82e082a8a82d1a (patch)
treebc67c4cd3acea69333eb7bb4d8d4d904d5d6027a
parent3d572a8cc3d71b43877db2776882e91303a0532d (diff)
downloadbusybox-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.c5
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/xfuncs_printf.c16
-rw-r--r--modutils/modprobe-small.c4
-rw-r--r--networking/ifupdown.c5
-rw-r--r--networking/netstat.c7
-rw-r--r--procps/watch.c7
-rw-r--r--util-linux/lsblk.c11
-rw-r--r--util-linux/mount.c25
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;
950int bb_putchar_stderr(char ch) FAST_FUNC; 950int bb_putchar_stderr(char ch) FAST_FUNC;
951int fputs_stdout(const char *s) FAST_FUNC; 951int fputs_stdout(const char *s) FAST_FUNC;
952char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) FAST_FUNC RETURNS_MALLOC; 952char *xasprintf(const char *format, ...) __attribute__ ((format(printf, 1, 2))) FAST_FUNC RETURNS_MALLOC;
953char *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__))
953char *auto_string(char *str) FAST_FUNC; 955char *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
352char* 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
352void FAST_FUNC xsetenv(const char *key, const char *value) 368void 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
392static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int numeric) 392static 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
410struct inet_params { 409struct 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!)
559static void append_mount_options(char **oldopts, const char *newopts) 560static 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),