Re: [Toybox] [PATCH] Add ftruncate logic to handle non-regular files
IIUC, ftruncate will fail with `EISDIR` if its input is a directory. And I don't know of any use-cases where we'd want or should be able to `dd` a directory. Unless I'm missing something, the S_ISDIR could be removed, since ftruncate ought to fail if a directory is given. Thanks! +Chris On Wed, Sep 23, 2020 at 4:38 AM Rob Landley wrote: > On 9/15/20 12:10 PM, Chris Sarra via Toybox wrote: > > -if (trunc && ftruncate(TT.out.fd, bs)) perror_exit("ftruncate"); > > +if (trunc && ftruncate(TT.out.fd, bs)) { > > + struct stat st; > > + if (fstat(TT.out.fd, ) < 0 || S_ISREG(st.st_mode) || > S_ISDIR(st.st_mode)) { > > +perror_exit("unexpected ftruncate failure"); > > + } > > +} > > What does truncating a directory do? Is there a valid use case where dd's > target > can be a directory? (How would that work?) > > Rob > ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] [PATCH] Add fflush to lib/password; remove print from stty
Hey Rob, I removed that xprintf in stty from our copy a long time ago to get rid of a log we didn't really need, but that change can be ignored if others find it useful. Thanks, +Chris On Wed, Sep 16, 2020 at 1:27 AM Rob Landley wrote: > > > On 9/15/20 11:39 AM, Chris Sarra via Toybox wrote: > > toybox logins were displaying the "password:" prompt after > > the user entered a password. This patch fixes the issue so the > > password prompt shows *before* password is entered. > > --- > > lib/password.c | 1 + > > toys/pending/stty.c | 2 +- > > 2 files changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/lib/password.c b/lib/password.c > > index 432905cc..2f5997ff 100644 > > --- a/lib/password.c > > +++ b/lib/password.c > > @@ -63,6 +63,7 @@ int read_password(char *buf, int buflen, char *mesg) > >xset_terminal(0, 1, 0, ); > > > >xprintf("%s", mesg); > > + fflush(NULL); > > This is why xprintf() had the x. This is literally why, but actually > flushing > before checking for error was too slow. (And then Elliott wanted to enable > line > buffering for everything, which breaks tee...) > > Sigh, ok I'm replacing it with dprintf() to avoid the borked stdio > buffering > entirely, which raises the question should the prompt go to stdout or > stderr? > > $ sudo /bin/bash > [sudo] password for landley: > $ sudo /bin/bash 2>/dev/null > [sudo] password for landley: > $ sudo /bin/bash >/dev/null > [sudo] password for landley: > > Answer: it goes to /dev/tty. Right, stop, BIG HAMMER time. ("There's never > time > to do it right, there's always time to do it over" meets "it is better to > light > a flamethrower than to curse the darkness", as usual for this project.) > > >for (i=0; i < buflen-1; i++) { > > if ((ret = read(0, buf+i, 1)) < 0 || (!ret && !i)) { > > diff --git a/toys/pending/stty.c b/toys/pending/stty.c > > index 8c937696..fe8f5c8d 100644 > > --- a/toys/pending/stty.c > > +++ b/toys/pending/stty.c > > @@ -271,7 +271,7 @@ static int set_special_character(struct termios > *new, int *i, char *char_name) > >else if (arg[0] == '^' && arg[2] == 0) ch = (toupper(arg[1])-'@'); > >else if (!arg[1]) ch = arg[0]; > >else error_exit("invalid arg: %s", arg); > > - xprintf("setting %s to %s (%02x)\n", char_name, arg, ch); > > + //xprintf("setting %s to %s (%02x)\n", char_name, arg, ch); > > What's this one about? (It's pending, which usually means I'm not as > familiar > with the guts of the command...) > > Rob > ___ > Toybox mailing list > Toybox@lists.landley.net > http://lists.landley.net/listinfo.cgi/toybox-landley.net > ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
[Toybox] [PATCH] Add ftruncate logic to handle non-regular files
ftruncate was failing on device files, leading to whole dd.c failures. This patch allows us to dump device files. --- toys/pending/dd.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/toys/pending/dd.c b/toys/pending/dd.c index 7de91825..a7b7f5fd 100644 --- a/toys/pending/dd.c +++ b/toys/pending/dd.c @@ -224,7 +224,12 @@ void dd_main() if (!(TT.oflag & _DD_oflag_seek_bytes)) bs *= TT.out.sz; if (bs) { xlseek(TT.out.fd, bs, SEEK_CUR); -if (trunc && ftruncate(TT.out.fd, bs)) perror_exit("ftruncate"); +if (trunc && ftruncate(TT.out.fd, bs)) { + struct stat st; + if (fstat(TT.out.fd, ) < 0 || S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { +perror_exit("unexpected ftruncate failure"); + } +} } unsigned long long bytes_left = TT.c_count; -- 2.28.0.618.gf4bc123cb7-goog ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
[Toybox] [PATCH] Add fflush to lib/password; remove print from stty
toybox logins were displaying the "password:" prompt after the user entered a password. This patch fixes the issue so the password prompt shows *before* password is entered. --- lib/password.c | 1 + toys/pending/stty.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/password.c b/lib/password.c index 432905cc..2f5997ff 100644 --- a/lib/password.c +++ b/lib/password.c @@ -63,6 +63,7 @@ int read_password(char *buf, int buflen, char *mesg) xset_terminal(0, 1, 0, ); xprintf("%s", mesg); + fflush(NULL); for (i=0; i < buflen-1; i++) { if ((ret = read(0, buf+i, 1)) < 0 || (!ret && !i)) { diff --git a/toys/pending/stty.c b/toys/pending/stty.c index 8c937696..fe8f5c8d 100644 --- a/toys/pending/stty.c +++ b/toys/pending/stty.c @@ -271,7 +271,7 @@ static int set_special_character(struct termios *new, int *i, char *char_name) else if (arg[0] == '^' && arg[2] == 0) ch = (toupper(arg[1])-'@'); else if (!arg[1]) ch = arg[0]; else error_exit("invalid arg: %s", arg); - xprintf("setting %s to %s (%02x)\n", char_name, arg, ch); + //xprintf("setting %s to %s (%02x)\n", char_name, arg, ch); new->c_cc[chars[j].value] = ch; return 1; } -- 2.28.0.618.gf4bc123cb7-goog ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
[Toybox] [PATCH] Add ipv6 support to wget.c
--- toys/pending/wget.c | 48 + 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/toys/pending/wget.c b/toys/pending/wget.c index 75fad3f4..5c85889a 100644 --- a/toys/pending/wget.c +++ b/toys/pending/wget.c @@ -25,11 +25,11 @@ GLOBALS( char *filename; ) -// extract hostname from url +// extract hostname and port from url static unsigned get_hn(const char *url, char *hostname) { unsigned i; - for (i = 0; url[i] != '\0' && url[i] != ':' && url[i] != '/'; i++) { + for (i = 0; url[i] != '\0' && url[i] != '/'; i++) { if(i >= 1024) error_exit("too long hostname in URL"); hostname[i] = url[i]; } @@ -41,7 +41,6 @@ static unsigned get_hn(const char *url, char *hostname) { // extract port number static unsigned get_port(const char *url, char *port, unsigned url_i) { unsigned i; - for (i = 0; url[i] != '\0' && url[i] != '/'; i++, url_i++) { if('0' <= url[i] && url[i] <= '9') port[i] = url[i]; else error_exit("wrong decimal port number"); @@ -52,6 +51,20 @@ static unsigned get_port(const char *url, char *port, unsigned url_i) { return url_i; } +static void strip_v6_brackets(char* hostname) { + size_t len = strlen(hostname); + if (len > 1023) { +error_exit("hostname too long, %d bytes\n", len); + } + char * closing_bracket = strchr(hostname, ']'); + if (closing_bracket && closing_bracket == hostname + len - 1) { +if (strchr(hostname, '[') == hostname) { + hostname[len-1] = 0; + memmove(hostname, hostname + 1, len - 1); +} + } +} + // get http infos in URL static void get_info(const char *url, char* hostname, char *port, char *path) { unsigned i = 7, len; @@ -62,11 +75,30 @@ static void get_info(const char *url, char* hostname, char *port, char *path) { len = get_hn(url+i, hostname); i += len; - // get port if exists - if (url[i] == ':') { -i++; -i = get_port(url+i, port, i); - } else strcpy(port, "80"); + // `hostname` now contains `host:port`, where host can be any of: a raw IPv4 + // address; a bracketed, raw IPv6 address, or a hostname. Extract port, if it exists, + // by searching for the last ':' in the hostname string. + char *port_delim = strrchr(hostname, ':'); + char use_default_port = 1; + if (port_delim) { +// Found a colon; is there a closing bracket after it? If so, +// then this colon was in the middle of a bracketed IPv6 address +if (!strchr(port_delim, ']')) { + // No closing bracket; this is a real port + use_default_port = 0; + get_port(port_delim + 1, port, 0); + + // Mark the new end of the hostname string + *port_delim = 0; +} + } + + if (use_default_port) { +strcpy(port, "80"); + } + + // This is a NOP if hostname is not a bracketed IPv6 address + strip_v6_brackets(hostname); // get uri in URL if (url[i] == '\0') strcpy(path, "/"); -- 2.28.0.526.ge36021eeef-goog ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] [PATCH] logger.c was failing to properly log local0-local6 facilities, due to a string parsing error. This patch enables proper local facility handling.
Just ran it through a short suite of tests on my end and all looks good here. Thanks for the cleanup! +Chris On Wed, Sep 9, 2020 at 12:57 AM Rob Landley wrote: > > > On 9/9/20 12:30 AM, Rob Landley wrote: > > On 9/8/20 2:16 PM, Chris Sarra via Toybox wrote: > >> --- > >> toys/posix/logger.c | 7 --- > >> 1 file changed, 4 insertions(+), 3 deletions(-) > >> > >> diff --git a/toys/posix/logger.c b/toys/posix/logger.c > >> index 3bcfb174..d1cc7291 100644 > >> --- a/toys/posix/logger.c > >> +++ b/toys/posix/logger.c > >> @@ -64,9 +64,10 @@ void logger_main(void) > >> else { > >>*s1++ = len = 0; > >>facility = arrayfind(TT.p, facilities, ARRAY_LEN(facilities)); > >> - if (facility == -1 && strncasecmp(TT.p, "local", 5)) { > >> -facility = s1[5]-'0'; > >> -if (facility>7 || s1[6]) facility = -1; > >> + if (facility == -1 && strncasecmp(TT.p, "local", 5) == 0) { > >> +s2 = TT.p; > >> +facility = s2[5]-'0'; > >> +if (facility>7 || s2[6]) facility = -1; > > > > Sigh, why did I promote this out of pending? arrayfind() initializes > matchlen to > > 0 and then never sets it to anything ELSE, so it ONLY returns exact > matches not > > longest unambiguous match (which is the point of the function I think?) > > > > Applied your patch, but I have some cleanup to do to this command... > > I did the cleanup but I have no tests/logger.test, so I dunno if I broke > it. (It > survived obvious smoketesting, but...?) > > Could you try the attached and see if it works for you? > > Thanks, > > Rob > ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
[Toybox] [PATCH] logger.c was failing to properly log local0-local6 facilities, due to a string parsing error. This patch enables proper local facility handling.
--- toys/posix/logger.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/toys/posix/logger.c b/toys/posix/logger.c index 3bcfb174..d1cc7291 100644 --- a/toys/posix/logger.c +++ b/toys/posix/logger.c @@ -64,9 +64,10 @@ void logger_main(void) else { *s1++ = len = 0; facility = arrayfind(TT.p, facilities, ARRAY_LEN(facilities)); - if (facility == -1 && strncasecmp(TT.p, "local", 5)) { -facility = s1[5]-'0'; -if (facility>7 || s1[6]) facility = -1; + if (facility == -1 && strncasecmp(TT.p, "local", 5) == 0) { +s2 = TT.p; +facility = s2[5]-'0'; +if (facility>7 || s2[6]) facility = -1; if (facility>=0) facility += 16; } if (facility<0) error_exit("bad facility: %s", TT.p); -- 2.28.0.526.ge36021eeef-goog ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] [PATCH] SIGHUP to init.c triggers inittab reload
Thanks Rob, and no worries- I've been able to use the init.c for a few months now, with only that patch. So hopefully cleanup won't be so bad! :) +Chris On Tue, Sep 1, 2020 at 11:16 PM Rob Landley wrote: > On 9/1/20 9:22 PM, Chris Sarra via Toybox wrote: > > --- > > toys/pending/init.c | 25 - > > 1 file changed, 24 insertions(+), 1 deletion(-) > > Applied, but this command is in pending. Caviar Emperor and all that... > > https://github.com/landley/toybox/blob/master/toys/pending/README#L6 > > (Yes, I should https://landley.net/toybox/cleanup.html all the pending > stuff, > alas this is still not my day job, doing what I can...) > > Thanks for the patch, > > Rob > ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
[Toybox] [PATCH] SIGHUP to init.c triggers inittab reload
--- toys/pending/init.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/toys/pending/init.c b/toys/pending/init.c index 64b61481..b147911f 100644 --- a/toys/pending/init.c +++ b/toys/pending/init.c @@ -188,6 +188,25 @@ static void inittab_parsing(void) } } +static void reload_inittab(void) +{ + // Remove all inactive actions, then reload /etc/inittab + struct action_list_seed **y; + y = _list_pointer; + while (*y) { +if (!(*y)->pid) { + struct action_list_seed *x = *y; + free(x->terminal_name); + free(x->command); + *y = (*y)->next; + free(x); + continue; +} +y = &(*y)->next; + } + inittab_parsing(); +} + static void run_command(char *command) { char *final_command[128]; @@ -405,7 +424,7 @@ static void restart_init_handler(int sig_no) static void catch_signal(int sig_no) { caught_signal = sig_no; - error_msg("signal seen"); + error_msg("signal seen: %d", sig_no); } static void pause_handler(int sig_no) @@ -439,6 +458,10 @@ static int check_if_pending_signals(void) caught_signal = 0; signal_caught = 1; if (sig == SIGINT) run_action_from_list(CTRLALTDEL); +else if (sig == SIGHUP) { + error_msg("reloading inittab"); + reload_inittab(); +} } } -- 2.28.0.402.g5ffc5be6b7-goog ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
Re: [Toybox] [PATCH] Introducing toys/pending/watchdog.c
+Chris On Mon, Aug 24, 2020 at 9:56 AM enh wrote: > > > On Sun, Aug 23, 2020 at 11:59 PM Rob Landley wrote: > >> On 8/22/20 3:05 PM, enh via Toybox wrote: >> > On Sat, Aug 22, 2020 at 11:22 AM Chris Sarra via Toybox >> > mailto:toybox@lists.landley.net>> wrote: >> > >> > This patch introduces a simple watchdog implementation for toybox. >> We >> > send the appropriate ioctls to set the relevant timeouts, and >> intercept >> > signals to safely shut down if required. >> > --- >> > toys/pending/watchdog.c | 128 >> >> > 1 file changed, 128 insertions(+) >> > create mode 100644 toys/pending/watchdog.c >> > >> > diff --git a/toys/pending/watchdog.c b/toys/pending/watchdog.c >> > new file mode 100644 >> > index ..0813fe69 >> > --- /dev/null >> > +++ b/toys/pending/watchdog.c >> > @@ -0,0 +1,128 @@ >> > +/* watchdog - start a watchdog timer with configurable kick >> frequencies >> > + >> > + Author: Chris Sarra, chrissa...@google.com > chrissa...@google.com> >> > >> > not sure why we're both working on a Saturday, but... >> >> Only reason I didn't get to it yesterday is I took a day off like you >> suggested. :) >> >> > + Date: 25 July 2019 >> > + Ref: kernel.org/doc/Documentation/watchdog/watchdog-api.txt >> > <http://kernel.org/doc/Documentation/watchdog/watchdog-api.txt> >> > >> > use the " * " indent from the other source files? >> >> I already cleaned this up before spotting this email. :) >> >> > also mention that there's precedent in a busybox "watchdog", which this >> is >> > command-line compatible with? >> >> Not a clue. Last system I dealt with using watchdog stuff had a 5 line >> function >> in the main loop of the app poking the watchdog so if the app went down >> the >> system rebooted. I've always been mildly confused by standalone watchdog >> binaries: what do they prove exactly? >> >> > +USE_WATCHDOG(NEWTOY(watchdog, "Ft#T#", >> TOYFLAG_NEEDROOT|TOYFLAG_BIN)) >> > >> > huh. i didn't realize that USE_ worked _inside_ the comment! probably >> best to >> > move it below the comment as is the convention though. >> >> It's a grep pulling NEWTOY()/OLDTOY() lines with no leading whitespace >> out of >> toys/*/*.c and running them through sort to make generated/newtoys.h. >> >> > +config WATCHDOG >> > + bool "watchdog" >> > + default y >> > + help >> > +usage: watchdog [-F] [-t SW_TIMER_S] [-T HW_TIMER_S] DEV >> > + >> > +Start the watchdog timer at DEV with optional timeout >> parameters. >> > >> > (blank line here.) >> > >> > +-F run in the foreground (do not daemonize) >> > +-t software timer (in seconds) >> > +-T hardware timer (in seconds) >> > >> > >> > say what the defaults are? >> >> Ooh, good suggestion. >> >> > the busybox help implies that it's possible to use more precision than >> seconds? >> > afaik from the kernel source and kernel docs, though, that's a lie? >> >> You can for the sleep, not for this watchdog ioctl. Might be a newer >> ioctl with >> more precision though... Not spotting an obvious candidate in the current >> kernel >> source though. (What's a PRETIMEOUT?) >> > > strace says they're using the same ioctl, so maybe just over-enthusiastic > copy & paste in the help text... > > >> > i think it would help to explain that -T is what you set the hardware >> watchdog >> > to, and -t is how often you kick it. i didn't get that from either your >> --help >> > or the busybox --help. >> > >> > so something like: >> > >> > -T N Set hardware watchdog to N seconds (default 60). >> > -t N Kick watchdog every N seconds (default 30). >> >> Is kick the official term for this? >> > > it's the one i'm familiar with, and wikipedia says it's not just me, but > `busybox watchdog --help` says "reset" and wikipedia calls the section > "restart" but then _don't_ use the verb "restart" but do use both "kick" > (the most) and "reset": > https://en.wikiped
[Toybox] [PATCH] Introducing toys/pending/watchdog.c
This patch introduces a simple watchdog implementation for toybox. We send the appropriate ioctls to set the relevant timeouts, and intercept signals to safely shut down if required. --- toys/pending/watchdog.c | 128 1 file changed, 128 insertions(+) create mode 100644 toys/pending/watchdog.c diff --git a/toys/pending/watchdog.c b/toys/pending/watchdog.c new file mode 100644 index ..0813fe69 --- /dev/null +++ b/toys/pending/watchdog.c @@ -0,0 +1,128 @@ +/* watchdog - start a watchdog timer with configurable kick frequencies + + Author: Chris Sarra, chrissa...@google.com + Date: 25 July 2019 + Ref: kernel.org/doc/Documentation/watchdog/watchdog-api.txt + +USE_WATCHDOG(NEWTOY(watchdog, "Ft#T#", TOYFLAG_NEEDROOT|TOYFLAG_BIN)) + +config WATCHDOG + bool "watchdog" + default y + help +usage: watchdog [-F] [-t SW_TIMER_S] [-T HW_TIMER_S] DEV + +Start the watchdog timer at DEV with optional timeout parameters. +-F run in the foreground (do not daemonize) +-t software timer (in seconds) +-T hardware timer (in seconds) +*/ +#define FOR_watchdog +#include "toys.h" +#include "linux/watchdog.h" + +// Make sure no DEBUG variable is set; change this if you need debug prints! +#undef WATCHDOG_DEBUG + +// Default timeout values in seconds. +#define WATCHDOG_SW_TIMER_S_DEFAULT (4) +#define WATCHDOG_HW_TIMER_S_DEFAULT (60) + +GLOBALS( + long hw_timer_s; + long sw_timer_s; + int fd; +) + +static int intercept_signals(void (*fn)(int)) { + int rc = 0; + struct sigaction sigact; + memset(, 0, sizeof(sigact)); + sigact.sa_handler = fn; + + rc = sigaction(SIGTERM, , NULL); +#if defined(WATCHDOG_DEBUG) + if ( rc ) { +printf("failed to create new sigaction for SIGTERM: %d\n", rc); + } +#endif + return rc; +} + +void safe_shutdown(int __attribute__((unused))ignored) { + write(TT.fd, "V", 1); + close(TT.fd); + TT.fd = -1; + error_exit("safely exited watchdog."); +} + +void watchdog_main(void) { + int rc = 0; + long hw_timer_sec = 0; + char *watchdog_dev = NULL; + + if ( toys.optc > 0 ) { +watchdog_dev = toys.optargs[0]; +#if defined(WATCHDOG_DEBUG) +printf("using dev @ '%s'\n", watchdog_dev); +#endif + } else { +error_exit("watchdog dev required"); + } + + // Set default values for timeouts if no flags + if (!(toys.optflags & FLAG_t)) { +TT.sw_timer_s = WATCHDOG_SW_TIMER_S_DEFAULT; +#if defined(WATCHDOG_DEBUG) +printf("using default sw_timer_s.\n"); +#endif + } + + if (!(toys.optflags & FLAG_T)) { +TT.hw_timer_s = WATCHDOG_HW_TIMER_S_DEFAULT; +#if defined(WATCHDOG_DEBUG) +printf("using default hw_timer_s.\n"); +#endif + } + +#if defined(WATCHDOG_DEBUG) +printf("hw timer: %ld seconds\n", TT.hw_timer_s); +printf("sw timer: %ld seconds\n", TT.sw_timer_s); +#endif + + if (!(toys.optflags & FLAG_F)) { +#if defined(WATCHDOG_DEBUG) + printf("daemonizing. so long, foreground!\n"); +#endif +// Attempt to daemonize +rc = daemon(1, 1); +if ( rc ) { + perror_exit("failed to daemonize: %d", rc); +} + } + + // Intercept terminating signals so we can call our shutdown routine first. + if ( intercept_signals(safe_shutdown) ) { +perror_exit("failed to intercept desired signals: %d", rc); + } +#if defined(WATCHDOG_DEBUG) +printf("Successfully intercepted signals.\n"); +#endif + + TT.fd = open(watchdog_dev, O_WRONLY); + if ( TT.fd == -1 ) { +perror_exit("failed to open '%s'", watchdog_dev); + } + +#if defined(WDIOC_SETTIMEOUT) + // SETTIMEOUT takes time value in seconds: s = ms / (1000 ms/s) + hw_timer_sec = TT.hw_timer_s; + xioctl(TT.fd, WDIOC_SETTIMEOUT, (void *)_timer_sec); +#endif // WDIOC_SETTIMEOUT + + // Now that we've got the watchdog device open, kick it periodically. + while (1) { +write(TT.fd, "\0", 1); +usleep(TT.sw_timer_s * 1000 * 1000); + } +} -- 2.28.0.297.g1956fa8f8d-goog ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net
[Toybox] Patch memory leak in tar.c
Hi Rob and toybox Users, I'm a newcomer to this email list, so if I'm using incorrect patch formats or should be emailing in a different way, please let me know. In looking at tar.c, I noticed that, while parsing files, for the symlink case there are two calls to xreadlink(). Both calls allocate a new char*, but only one is ever freed. I've attached a git diff to fix this. Please let me know if there's anything else I should do to patch this. Thanks! +Chris 0001-Patch-out-memory-leak-in-tar.c.patch Description: Binary data ___ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net