dd: fix skip= parse error (spotted by Dirk Clemens
No binary (build failed)
—
(log yok)
| @@ -58,7 +58,7 @@ static bool write_and_stats(int fd, const void *buf, size_t len, size_t obs, | |
| return 1; | |
| if (n == obs) | |
| G.out_full++; | |
| - | else if (n > 0) |
| + | else if (n) /* > 0 */ |
| G.out_part++; | |
| return 0; | |
| } | |
| @@ -73,10 +73,10 @@ int dd_main(int argc, char **argv); | |
| int dd_main(int argc, char **argv) | |
| { | |
| enum { | |
| - | sync_flag = 1 << 0, |
| - | noerror = 1 << 1, |
| - | trunc_flag = 1 << 2, |
| - | twobufs_flag = 1 << 3, |
| + | SYNC_FLAG = 1 << 0, |
| + | NOERROR = 1 << 1, |
| + | TRUNC_FLAG = 1 << 2, |
| + | TWOBUFS_FLAG = 1 << 3, |
| }; | |
| static const char * const keywords[] = { | |
| "bs=", "count=", "seek=", "skip=", "if=", "of=", | |
| @@ -98,10 +98,10 @@ int dd_main(int argc, char **argv) | |
| OP_conv, | |
| OP_conv_notrunc, | |
| OP_conv_sync, | |
| - | OP_conv_noerror, |
| + | OP_conv_NOERROR, |
| #endif | |
| }; | |
| - | int flags = trunc_flag; |
| + | int flags = TRUNC_FLAG; |
| size_t oc = 0, ibs = 512, obs = 512; | |
| ssize_t n, w; | |
| off_t seek = 0, skip = 0, count = OFF_T_MAX; | |
| @@ -152,23 +152,23 @@ int dd_main(int argc, char **argv) | |
| while (1) { | |
| /* find ',', replace them with nil so we can use arg for | |
| * index_in_str_array without copying. | |
| - | * We rely on arg being non-null, else strstr would fault. |
| + | * We rely on arg being non-null, else strchr would fault. |
| */ | |
| - | key = strstr(arg, ","); |
| + | key = strchr(arg, ','); |
| if (key) | |
| *key = '\0'; | |
| what = index_in_str_array(keywords, arg) + 1; | |
| if (what < OP_conv_notrunc) | |
| bb_error_msg_and_die(bb_msg_invalid_arg, arg, "conv"); | |
| if (what == OP_conv_notrunc) | |
| - | flags &= ~trunc_flag; |
| + | flags &= ~TRUNC_FLAG; |
| if (what == OP_conv_sync) | |
| - | flags |= sync_flag; |
| - | if (what == OP_conv_noerror) |
| - | flags |= noerror; |
| + | flags |= SYNC_FLAG; |
| + | if (what == OP_conv_NOERROR) |
| + | flags |= NOERROR; |
| if (!key) /* no ',' left, so this was the last specifier */ | |
| break; | |
| - | arg += key - arg + 1; /* skip this keyword plus ',' */ |
| + | arg = key + 1; /* skip this keyword and ',' */ |
| } | |
| continue; | |
| } | |
| @@ -186,7 +186,7 @@ int dd_main(int argc, char **argv) | |
| seek = XATOU_SFX(arg, dd_suffixes); | |
| continue; | |
| } | |
| - | if (what == skip) { |
| + | if (what == OP_skip) { |
| skip = XATOU_SFX(arg, dd_suffixes); | |
| continue; | |
| } | |
| @@ -200,7 +200,7 @@ int dd_main(int argc, char **argv) | |
| //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | |
| ibuf = obuf = xmalloc(ibs); | |
| if (ibs != obs) { | |
| - | flags |= twobufs_flag; |
| + | flags |= TWOBUFS_FLAG; |
| obuf = xmalloc(obs); | |
| } | |
| if (infile != NULL) | |
| @@ -212,12 +212,12 @@ int dd_main(int argc, char **argv) | |
| if (outfile != NULL) { | |
| int oflag = O_WRONLY | O_CREAT; | |
| - | if (!seek && (flags & trunc_flag)) |
| + | if (!seek && (flags & TRUNC_FLAG)) |
| oflag |= O_TRUNC; | |
| ofd = xopen(outfile, oflag); | |
| - | if (seek && (flags & trunc_flag)) { |
| + | if (seek && (flags & TRUNC_FLAG)) { |
| if (ftruncate(ofd, seek * obs) < 0) { | |
| struct stat st; | |
| @@ -247,13 +247,13 @@ int dd_main(int argc, char **argv) | |
| } | |
| while (G.in_full + G.in_part != count) { | |
| - | if (flags & noerror) /* Pre-zero the buffer when for noerror */ |
| + | if (flags & NOERROR) /* Pre-zero the buffer when for NOERROR */ |
| memset(ibuf, '\0', ibs); | |
| n = safe_read(ifd, ibuf, ibs); | |
| if (n == 0) | |
| break; | |
| if (n < 0) { | |
| - | if (flags & noerror) { |
| + | if (flags & NOERROR) { |
| n = ibs; | |
| bb_perror_msg("%s", infile); | |
| } else | |
| @@ -263,12 +263,12 @@ int dd_main(int argc, char **argv) | |
| G.in_full++; | |
| else { | |
| G.in_part++; | |
| - | if (flags & sync_flag) { |
| + | if (flags & SYNC_FLAG) { |
| memset(ibuf + n, '\0', ibs - n); | |
| n = ibs; | |
| } | |
| } | |
| - | if (flags & twobufs_flag) { |
| + | if (flags & TWOBUFS_FLAG) { |
| char *tmp = ibuf; | |
| while (n) { | |
| size_t d = obs - oc; | |
| @@ -285,9 +285,8 @@ int dd_main(int argc, char **argv) | |
| oc = 0; | |
| } | |
| } | |
| - | } else |
| - | if (write_and_stats(ofd, ibuf, n, obs, outfile)) |
| - | goto out_status; |
| + | } else if (write_and_stats(ofd, ibuf, n, obs, outfile)) |
| + | goto out_status; |
| } | |
| if (ENABLE_FEATURE_DD_IBS_OBS && oc) { | |
| @@ -2,8 +2,12 @@ strace of "sleep 1 | sleep 2" being run from interactive bash 3.0 | |
| Synopsis: | |
| + | open /dev/tty [, if fails, open ttyname(0)]; close /* helps re-establish ctty */ |
| get current signal mask | |
| - | install default handlers for GHLD QUIT TERM |
| + | TCGETS on fd# 0 |
| + | TCGETS on fd# 2 /* NB: if returns ENOTTY (2>/dev/null), sh seems to disable job control, |
| + | does not show prompt, but still executes cmds from fd# 0 */ |
| + | install default handlers for CHLD QUIT TERM |
| install common handler for HUP INT ILL TRAP ABRT FPE BUS SEGV SYS PIPE ALRM TERM XCPU XFSZ VTALRM USR1 USR2 | |
| ignore QUIT | |
| install handler for INT | |
| @@ -34,11 +38,73 @@ get our pprocess group | |
| signal followed by a SIGCONT signal will be sent to each process | |
| in the newly-orphaned process group. | |
| ... | |
| - | |
| + | dup stderr to fd# 255 |
| + | move ourself to our own process group |
| + | block CHLD TSTP TTIN TTOU |
| + | set tty's (255, stderr's) foreground process group to our group |
| + | allow all signals |
| + | mark 255 CLOEXEC |
| + | set CHLD handler |
| + | get signal mask |
| + | get fd#0 flags |
| + | get signal mask |
| + | set INT handler |
| + | block CHLD TSTP TTIN TTOU |
| + | set fd #255 foreground process group to our group |
| + | allow all signals |
| + | set INT handler |
| + | block all signals |
| + | allow all signals |
| + | block INT |
| + | allow all signals |
| + | lotsa sigactions: set INT,ALRM,WINCH handlers, ignore TERM,QUIT,TSTP,TTOU,TTIN |
| + | block all signals |
| + | allow all signals |
| + | block all signals |
| + | allow all signals |
| + | block all signals |
| + | allow all signals |
| + | read "sleep 1 | sleep 2\n" |
| + | block INT |
| + | TCSETSW on fd# 0 |
| + | allow all signals |
| + | lotsa sigactions: set INT,ALRM,WINCH handlers, ignore TERM,QUIT,TSTP,TTOU,TTIN |
| + | block CHLD |
| + | pipe([4, 5]) /* oops seems I lost another pipe() in editing... */ |
| + | fork child #1 |
| + | put child in it's own process group |
| + | block only CHLD |
| + | close(5) |
| + | block only INT CHLD |
| + | fork child #2 |
| + | put child in the same process group as first one |
| + | block only CHLD |
| + | close(4) |
| + | block only CHLD |
| + | block only CHLD TSTP TTIN TTOU |
| + | set fd# 255 foreground process group to first child's one |
| + | block only CHLD |
| + | block only CHLD |
| + | block only CHLD |
| + | wait4 for children to die or stop - first child exits |
| + | wait4 for children to die or stop - second child exits |
| + | block CHLD TSTP TTIN TTOU |
| + | set fd# 255 foreground process group to our own one |
| + | block only CHLD |
| + | block only CHLD |
| + | block nothing |
| + | --- SIGCHLD (Child exited) @ 0 (0) --- |
| + | wait for it - no child (already waited for) |
| + | sigreturn() |
| + | read signal mask |
| + | lotsa sigactions... |
| + | read next command |
| execve("/bin/sh", ["sh"], [/* 34 vars */]) = 0 | |
| rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 | |
| + | ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 |
| + | ioctl(2, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0 |
| rt_sigaction(SIGCHLD, {SIG_DFL}, {SIG_DFL}, 8) = 0 | |
| rt_sigaction(SIGQUIT, {SIG_DFL}, {SIG_DFL}, 8) = 0 | |
| rt_sigaction(SIGTERM, {SIG_DFL}, {SIG_DFL}, 8) = 0 | |