dd: support conv=fsync dd: support "dd --" if CONFIG_DESKTOP=y
No binary (build failed)
—
(log yok)
| @@ -79,23 +79,31 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, | |
| #endif | |
| int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| - | int dd_main(int argc, char **argv) |
| + | int dd_main(int argc ATTRIBUTE_UNUSED, char **argv) |
| { | |
| enum { | |
| - | FLAG_SYNC = 1 << 0, |
| - | FLAG_NOERROR = 1 << 1, |
| - | FLAG_NOTRUNC = 1 << 2, |
| - | FLAG_TWOBUFS = 1 << 3, |
| - | FLAG_COUNT = 1 << 4, |
| + | /* Must be in the same order as OP_conv_XXX! */ |
| + | /* (see "flags |= (1 << what)" below) */ |
| + | FLAG_NOTRUNC = 1 << 0, |
| + | FLAG_SYNC = 1 << 1, |
| + | FLAG_NOERROR = 1 << 2, |
| + | FLAG_FSYNC = 1 << 3, |
| + | /* end of conv flags */ |
| + | FLAG_TWOBUFS = 1 << 4, |
| + | FLAG_COUNT = 1 << 5, |
| }; | |
| static const char keywords[] ALIGN1 = | |
| "bs=\0""count=\0""seek=\0""skip=\0""if=\0""of=\0" | |
| #if ENABLE_FEATURE_DD_IBS_OBS | |
| - | "ibs=\0""obs=\0""conv=\0""notrunc\0""sync\0""noerror\0" |
| + | "ibs=\0""obs=\0""conv=\0" |
| #endif | |
| ; | |
| + | #if ENABLE_FEATURE_DD_IBS_OBS |
| + | static const char conv_words[] ALIGN1 = |
| + | "notrunc\0""sync\0""noerror\0""fsync\0"; |
| + | #endif |
| enum { | |
| - | OP_bs = 1, |
| + | OP_bs = 0, |
| OP_count, | |
| OP_seek, | |
| OP_skip, | |
| @@ -105,9 +113,23 @@ int dd_main(int argc, char **argv) | |
| OP_ibs, | |
| OP_obs, | |
| OP_conv, | |
| - | OP_conv_notrunc, |
| + | /* Must be in the same order as FLAG_XXX! */ |
| + | OP_conv_notrunc = 0, |
| OP_conv_sync, | |
| OP_conv_noerror, | |
| + | OP_conv_fsync, |
| + | /* Unimplemented conv=XXX: */ |
| + | //nocreat do not create the output file |
| + | //excl fail if the output file already exists |
| + | //fdatasync physically write output file data before finishing |
| + | //swab swap every pair of input bytes |
| + | //lcase change upper case to lower case |
| + | //ucase change lower case to upper case |
| + | //block pad newline-terminated records with spaces to cbs-size |
| + | //unblock replace trailing spaces in cbs-size records with newline |
| + | //ascii from EBCDIC to ASCII |
| + | //ebcdic from ASCII to EBCDIC |
| + | //ibm from ASCII to alternate EBCDIC |
| #endif | |
| }; | |
| int exitcode = EXIT_FAILURE; | |
| @@ -138,85 +160,85 @@ int dd_main(int argc, char **argv) | |
| signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status); | |
| #endif | |
| - | for (n = 1; n < argc; n++) { |
| - | smalluint key_len; |
| - | smalluint what; |
| - | char *key; |
| + | for (n = 1; argv[n]; n++) { |
| + | int what; |
| + | char *val; |
| char *arg = argv[n]; | |
| - | //XXX:FIXME: we reject plain "dd --" This would cost ~20 bytes, so.. |
| - | //if (*arg == '-' && *++arg == '-' && !*++arg) continue; |
| - | key = strstr(arg, "="); |
| - | if (key == NULL) |
| + | #if ENABLE_DESKTOP |
| + | /* "dd --". NB: coreutils 6.9 will complain if they see |
| + | * more than one of them. We wouldn't. */ |
| + | if (arg[0] == '-' && arg[1] == '-' && arg[2] == '\0') |
| + | continue; |
| + | #endif |
| + | val = strchr(arg, '='); |
| + | if (val == NULL) |
| bb_show_usage(); | |
| - | key_len = key - arg + 1; |
| - | key = xstrndup(arg, key_len); |
| - | what = index_in_strings(keywords, key) + 1; |
| - | if (ENABLE_FEATURE_CLEAN_UP) |
| - | free(key); |
| - | if (what == 0) |
| + | *val = '\0'; |
| + | what = index_in_strings(keywords, arg); |
| + | if (what < 0) |
| bb_show_usage(); | |
| - | arg += key_len; |
| + | /* *val = '='; - to preserve ps listing? */ |
| + | val++; |
| #if ENABLE_FEATURE_DD_IBS_OBS | |
| if (what == OP_ibs) { | |
| /* Must fit into positive ssize_t */ | |
| - | ibs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); |
| - | continue; |
| + | ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); |
| + | /*continue;*/ |
| } | |
| if (what == OP_obs) { | |
| - | obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); |
| - | continue; |
| + | obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); |
| + | /*continue;*/ |
| } | |
| if (what == OP_conv) { | |
| while (1) { | |
| - | /* find ',', replace them with NUL so we can use arg for |
| + | /* find ',', replace them with NUL so we can use val for |
| * index_in_strings() without copying. | |
| - | * We rely on arg being non-null, else strchr would fault. |
| + | * We rely on val being non-null, else strchr would fault. |
| */ | |
| - | key = strchr(arg, ','); |
| - | if (key) |
| - | *key = '\0'; |
| - | what = index_in_strings(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 |= FLAG_NOTRUNC; |
| - | if (what == OP_conv_sync) |
| - | flags |= FLAG_SYNC; |
| - | if (what == OP_conv_noerror) |
| - | flags |= FLAG_NOERROR; |
| - | if (!key) /* no ',' left, so this was the last specifier */ |
| + | arg = strchr(val, ','); |
| + | if (arg) |
| + | *arg = '\0'; |
| + | what = index_in_strings(conv_words, val); |
| + | if (what < 0) |
| + | bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); |
| + | flags |= (1 << what); |
| + | if (!arg) /* no ',' left, so this was the last specifier */ |
| break; | |
| - | arg = key + 1; /* skip this keyword and ',' */ |
| + | /* *arg = ','; - to preserve ps listing? */ |
| + | val = arg + 1; /* skip this keyword and ',' */ |
| } | |
| - | continue; |
| + | continue; /* we trashed 'what', can't fall through */ |
| } | |
| #endif | |
| if (what == OP_bs) { | |
| - | ibs = obs = xatoul_range_sfx(arg, 1, ((size_t)-1L)/2, dd_suffixes); |
| - | continue; |
| + | ibs = obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); |
| + | /*continue;*/ |
| } | |
| /* These can be large: */ | |
| if (what == OP_count) { | |
| flags |= FLAG_COUNT; | |
| - | count = XATOU_SFX(arg, dd_suffixes); |
| - | continue; |
| + | count = XATOU_SFX(val, dd_suffixes); |
| + | /*continue;*/ |
| } | |
| if (what == OP_seek) { | |
| - | seek = XATOU_SFX(arg, dd_suffixes); |
| - | continue; |
| + | seek = XATOU_SFX(val, dd_suffixes); |
| + | /*continue;*/ |
| } | |
| if (what == OP_skip) { | |
| - | skip = XATOU_SFX(arg, dd_suffixes); |
| - | continue; |
| + | skip = XATOU_SFX(val, dd_suffixes); |
| + | /*continue;*/ |
| } | |
| if (what == OP_if) { | |
| - | infile = arg; |
| - | continue; |
| + | infile = val; |
| + | /*continue;*/ |
| } | |
| - | if (what == OP_of) |
| - | outfile = arg; |
| - | } |
| + | if (what == OP_of) { |
| + | outfile = val; |
| + | /*continue;*/ |
| + | } |
| + | } /* end of "for (argv[n])" */ |
| + | |
| //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | |
| ibuf = obuf = xmalloc(ibs); | |
| if (ibs != obs) { | |
| @@ -304,13 +326,17 @@ int dd_main(int argc, char **argv) | |
| } | |
| } else if (write_and_stats(ibuf, n, obs, outfile)) | |
| goto out_status; | |
| + | |
| + | if (flags & FLAG_FSYNC) { |
| + | if (fsync(ofd) < 0) |
| + | goto die_outfile; |
| + | } |
| } | |
| if (ENABLE_FEATURE_DD_IBS_OBS && oc) { | |
| w = full_write_or_warn(obuf, oc, outfile); | |
| if (w < 0) goto out_status; | |
| - | if (w > 0) |
| - | G.out_part++; |
| + | if (w > 0) G.out_part++; |
| } | |
| if (close(ifd) < 0) { | |
| die_infile: | |