dd: fix skip= parse error (spotted by Dirk Clemens <develop@cle-mens.de>)
This commit is contained in:
parent
9ace613406
commit
d1801a4430
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user