diff --git a/README.md b/README.md index a1b29d6..139e719 100644 --- a/README.md +++ b/README.md @@ -63,13 +63,14 @@ small, so using the `--min-size` one can hopefully extract only real MPEG files. -h, --help Print this help message. -q, --quiet Do not print status messages. + -s, --simulate Don't write any output files. -o, --output=DIR Directory where extracted files should be written. (default: ".") -i, --offset=OFFSET Start processing at byte OFFSET. (default: 0) -n, --length=LENGTH Only process LENGTH bytes. - (default and maximum: 8E) + (default and maximum: 8 EB) -m, --min-size=SIZE Minumum size of extracted files (skip smaller). (default: 0) -x, --max-size=SIZE Maximum size of extracted files (skip larger). - (default and maximum: 16E) + (default and maximum: 16 EB) The last character of OFFSET, LENGTH and SIZE may be one of the following: diff --git a/src/audioextract.c b/src/audioextract.c index 810fc78..7f26025 100644 --- a/src/audioextract.c +++ b/src/audioextract.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "audioextract.h" #include "riff.h" @@ -89,6 +90,7 @@ static int usage(int argc, char **argv) "Options:\n" " -h, --help Print this help message.\n" " -q, --quiet Do not print status messages.\n" + " -s, --simulate Don't write any output files.\n" " -o, --output=DIR Directory where extracted files should be written. (default: \".\")\n" " -i, --offset=OFFSET Start processing at byte OFFSET. (default: 0)\n" " -n, --length=LENGTH Only process LENGTH bytes.\n" @@ -203,19 +205,27 @@ const char *basename(const char *path) int write_file(const uint8_t *data, size_t length, const struct extract_options *options, const char *filename, size_t offset, const char *ext, char *pathbuf, size_t pathbuflen) { + double sz = 0; + const char *sz_unit = NULL; snprintf(pathbuf, pathbuflen, EXTRACTED_FILE_FMT, options->outdir, PATH_SEP, filename, offset, ext); if (length < options->minsize) { if (!options->quiet) - fprintf(stderr, "Skipped too small (%"PRIuz ") %s\n", length, pathbuf); + { + sz_unit = format_size(length, &sz); + fprintf(stderr, "Skipped too small (%g %s) %s\n", sz, sz_unit, pathbuf); + } return 0; } else if (length > options->maxsize) { if (!options->quiet) - fprintf(stderr, "Skipped too large (%"PRIuz") %s\n", length, pathbuf); + { + sz_unit = format_size(length, &sz); + fprintf(stderr, "Skipped too large (%g %s) %s\n", sz, sz_unit, pathbuf); + } return 0; } @@ -227,14 +237,18 @@ int write_file(const uint8_t *data, size_t length, const struct extract_options printf("Writing %g %s to %s\n", slice_size, slice_unit, pathbuf); } + if (options->simulate) + return 1; + return write_data(pathbuf, data, length); } -int do_extract(const uint8_t *filedata, size_t filesize, const struct extract_options *options, size_t *numfilesptr) +int do_extract(const uint8_t *filedata, size_t filesize, const struct extract_options *options, size_t *numfilesptr, size_t *sumsizeptr) { const uint8_t *ptr = NULL, *end = NULL; enum fileformat format = NONE; + size_t sumsize = 0; size_t length = 0; int success = 1; int formats = options->formats; @@ -273,6 +287,7 @@ int do_extract(const uint8_t *filedata, size_t filesize, const struct extract_op if (write_file((data), length, options, filename, (size_t)((data) - filedata), (ext), outfilename, namelen)) \ { \ ++ numfiles; \ + sumsize += length; \ } ptr = filedata; @@ -438,6 +453,9 @@ cleanup: if (numfilesptr) *numfilesptr = numfiles; + + if (sumsizeptr) + *sumsizeptr = sumsize; return success; } @@ -751,27 +769,29 @@ const char *format_size(uint64_t in, double *out) } const struct option long_options[] = { - {"formats", required_argument, 0, 'f' }, - {"output", required_argument, 0, 'o' }, - {"help", no_argument, 0, 'h' }, - {"quiet", no_argument, 0, 'q' }, - {"min-size", required_argument, 0, 'm' }, - {"max-size", required_argument, 0, 'x' }, - {"length", required_argument, 0, 'n' }, - {"offset", required_argument, 0, 'i' }, - {0, 0, 0, 0 } + {"formats", required_argument, 0, 'f' }, + {"output", required_argument, 0, 'o' }, + {"help", no_argument, 0, 'h' }, + {"quiet", no_argument, 0, 'q' }, + {"min-size", required_argument, 0, 'm' }, + {"max-size", required_argument, 0, 'x' }, + {"length", required_argument, 0, 'n' }, + {"offset", required_argument, 0, 'i' }, + {"simulate", no_argument, 0, 's' }, + {0, 0, 0, 0 } }; int main(int argc, char **argv) { - struct extract_options options = { NULL, ".", 0, SIZE_MAX, 0, (SIZE_MAX>>1), DEFAULT_FORMATS, 0 }; + struct extract_options options = { NULL, ".", 0, SIZE_MAX, 0, (SIZE_MAX>>1), DEFAULT_FORMATS, 0, 0 }; int i = 0, opt = 0; size_t failures = 0; size_t sumnumfiles = 0; size_t numfiles = 0; size_t size = 0; + size_t sumsize = 0; - while ((opt = getopt_long(argc, argv, "f:o:hqm:x:n:i:", long_options, NULL)) != -1) + while ((opt = getopt_long(argc, argv, "f:o:hqm:x:n:i:s", long_options, NULL)) != -1) { switch (opt) { @@ -824,6 +844,10 @@ int main(int argc, char **argv) } break; + case 's': + options.simulate = 1; + break; + default: fprintf(stderr, SEE_HELP); return 255; @@ -847,9 +871,11 @@ int main(int argc, char **argv) { options.filepath = argv[i]; numfiles = 0; - if (extract(&options, &numfiles)) + size = 0; + if (extract(&options, &numfiles, &size)) { sumnumfiles += numfiles; + sumsize += size; } else { fprintf(stderr, "Error processing file: %s\n", options.filepath); @@ -858,7 +884,14 @@ int main(int argc, char **argv) } if (!options.quiet) - printf("Extracted %"PRIuz" file(s).\n", sumnumfiles); + { + double sz = 0; + const char *sz_unit = format_size(sumsize, &sz); + if (sumnumfiles == 1) + printf("Extracted 1 file of %g %s size.\n", sz, sz_unit); + else + printf("Extracted %"PRIuz" files of %g %s size.\n", sumnumfiles, sz, sz_unit); + } if (failures > 0) { diff --git a/src/audioextract.h b/src/audioextract.h index cecef89..8ebb66b 100644 --- a/src/audioextract.h +++ b/src/audioextract.h @@ -130,12 +130,15 @@ struct extract_options { size_t length; int formats; int quiet; + int simulate; }; int probalby_mod_text(const uint8_t *str, size_t length); -int extract(const struct extract_options *options, size_t *numfilesptr); +int extract(const struct extract_options *options, + size_t *numfilesptr, size_t *sumsizeptr); int do_extract(const uint8_t *filedata, size_t filesize, - const struct extract_options *options, size_t *numfilesptr); + const struct extract_options *options, + size_t *numfilesptr, size_t *sumsizeptr); int write_data(const char *filename, const uint8_t *data, size_t length); #endif /* AUDIOEXTRACT_H__ */ diff --git a/src/audioextract_posix.c b/src/audioextract_posix.c index 15a9b4e..54666f6 100644 --- a/src/audioextract_posix.c +++ b/src/audioextract_posix.c @@ -21,7 +21,7 @@ int write_data(const char *filename, const uint8_t *data, size_t length) return 1; } -int extract(const struct extract_options *options, size_t *numfilesptr) +int extract(const struct extract_options *options, size_t *numfilesptr, size_t *sumsizeptr) { struct stat statdata; size_t length = 0; @@ -76,7 +76,7 @@ int extract(const struct extract_options *options, size_t *numfilesptr) goto error; } - if (do_extract(filedata, length, options, numfilesptr)) + if (do_extract(filedata, length, options, numfilesptr, sumsizeptr)) goto cleanup; error: diff --git a/src/audioextract_windows.c b/src/audioextract_windows.c index 4d59ad4..fe38d58 100644 --- a/src/audioextract_windows.c +++ b/src/audioextract_windows.c @@ -39,7 +39,7 @@ int write_data(const char *filename, const uint8_t *data, size_t length) return 1; } -int extract(const struct extract_options *options, size_t *numfilesptr) +int extract(const struct extract_options *options, size_t *numfilesptr, size_t *sumsizeptr) { LARGE_INTEGER filesize = { .QuadPart = 0 }; int success = 1; @@ -99,7 +99,7 @@ int extract(const struct extract_options *options, size_t *numfilesptr) goto error; } - if (do_extract(filedata, length, options, numfilesptr)) + if (do_extract(filedata, length, options, numfilesptr, sumsizeptr)) { goto cleanup; }