aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/dd.c67
1 files changed, 23 insertions, 44 deletions
diff --git a/toys/pending/dd.c b/toys/pending/dd.c
index 2160e723..aebc90e8 100644
--- a/toys/pending/dd.c
+++ b/toys/pending/dd.c
@@ -7,7 +7,7 @@
*
* todo: ctrl-c doesn't work, the read() is restarting.
-USE_DD(NEWTOY(dd, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+USE_DD(NEWTOY(dd, 0, TOYFLAG_USR|TOYFLAG_BIN))
config DD
bool "dd"
@@ -52,22 +52,10 @@ GLOBALS(
} in, out;
);
-#define C_SYNC 0x0100
-#define C_FSYNC 0x0200
-#define C_NOERROR 0x0400
-#define C_NOTRUNC 0x0800
-
-struct pair {
- char *name;
- unsigned val;
-};
-
-static struct pair clist[] = {
- { "fsync", C_FSYNC },
- { "noerror", C_NOERROR },
- { "notrunc", C_NOTRUNC },
- { "sync", C_SYNC },
-};
+#define C_FSYNC 1
+#define C_NOERROR 2
+#define C_NOTRUNC 4
+#define C_SYNC 8
static void status()
{
@@ -112,24 +100,14 @@ int strstarteq(char **a, char *b)
{
char *aa = *a;
- if (!strstart(&aa, b)) return 0;
- if (*aa != '=') return 0;
- *a = ++aa;
-
- return 1;
-}
-
-static int comp(const void *a, const void *b) //const to shut compiler up
-{
- return strcmp(((struct pair*)a)->name, ((struct pair*)b)->name);
+ return strstart(&aa, b) && *aa == '=' && (*a = aa+1);
}
void dd_main()
{
- struct pair *res, key;
char **args;
unsigned long long bs = 0;
- int trunc = O_TRUNC;
+ int trunc = O_TRUNC, conv = 0;
TT.show_xfer = TT.show_records = 1;
TT.c_count = ULLONG_MAX;
@@ -154,13 +132,14 @@ void dd_main()
else if (!strcmp(arg, "none")) TT.show_xfer = TT.show_records = 0;
else error_exit("unknown status '%s'", arg);
} else if (strstarteq(&arg, "conv")) {
- while (arg) {
- key.name = strsep(&arg, ",");
- if (!(res = bsearch(&key, clist, ARRAY_LEN(clist),
- sizeof(struct pair), comp)))
- error_exit("unknown conversion %s", key.name);
-
- toys.optflags |= res->val;
+ char *ss, *convs[] = {"fsync", "noerror", "notrunc", "sync"};
+ int i, len;
+
+ while ((ss = comma_iterate(&arg, &len))) {
+ for (i = 0; i<ARRAY_LEN(convs); i++)
+ if (len == strlen(convs[i]) && !strncmp(ss, convs[i], len)) break;
+ if (i == ARRAY_LEN(convs)) error_exit("bad conv=%.*s", len, ss);
+ conv |= 1<<i;
}
} else error_exit("bad arg %s", arg);
}
@@ -179,7 +158,7 @@ void dd_main()
if (!TT.in.name) TT.in.name = "stdin";
else TT.in.fd = xopenro(TT.in.name);
- if (toys.optflags&C_NOTRUNC) trunc = 0;
+ if (conv&C_NOTRUNC) trunc = 0;
//setup output
if (!TT.out.name) {
@@ -196,7 +175,7 @@ void dd_main()
if (n < 0) {
perror_msg("%s", TT.in.name);
- if (toys.optflags & C_NOERROR) status();
+ if (conv&C_NOERROR) status();
else return;
} else if (!n) {
xprintf("%s: Can't skip\n", TT.in.name);
@@ -224,16 +203,16 @@ void dd_main()
}
TT.in.bp = TT.in.buff + TT.in.count;
- if (toys.optflags & C_SYNC) memset(TT.in.bp, 0, TT.in.sz);
+ if (conv&C_SYNC) memset(TT.in.bp, 0, TT.in.sz);
if (!(n = read(TT.in.fd, TT.in.bp, TT.in.sz))) break;
if (n < 0) {
if (errno == EINTR) continue;
//read error case.
perror_msg("%s: read error", TT.in.name);
- if (!(toys.optflags & C_NOERROR)) exit(1);
+ if (!(conv&C_NOERROR)) exit(1);
status();
xlseek(TT.in.fd, TT.in.sz, SEEK_CUR);
- if (!(toys.optflags & C_SYNC)) continue;
+ if (!(conv&C_SYNC)) continue;
// if SYNC, then treat as full block of nuls
n = TT.in.sz;
}
@@ -242,7 +221,7 @@ void dd_main()
TT.in.count += n;
} else {
TT.in_part++;
- if (toys.optflags & C_SYNC) TT.in.count += TT.in.sz;
+ if (conv&C_SYNC) TT.in.count += TT.in.sz;
else TT.in.count += n;
}
@@ -259,8 +238,8 @@ void dd_main()
}
}
if (TT.out.count) write_out(1); //write any remaining input blocks
- if (toys.optflags & C_FSYNC && fsync(TT.out.fd) < 0)
- perror_exit("%s: fsync fail", TT.out.name);
+ if ((conv&C_FSYNC) && fsync(TT.out.fd)<0)
+ perror_exit("%s: fsync", TT.out.name);
close(TT.in.fd);
close(TT.out.fd);