X-Git-Url: http://git.sven.stormbind.net/?p=sven%2Fexfat-utils.git;a=blobdiff_plain;f=dump%2Fmain.c;h=fda5b9b35b5ca125463659d86eade510486259b1;hp=71711c1623bccb279302ce95145c6652385b22ec;hb=0e295d91bb7f18afee1a0b0d587e5a0cf58bf2fb;hpb=f77812e8b678b8bf620bfbf33882139997ccda34 diff --git a/dump/main.c b/dump/main.c index 71711c1..fda5b9b 100644 --- a/dump/main.c +++ b/dump/main.c @@ -3,7 +3,7 @@ Prints detailed information about exFAT volume. Free exFAT implementation. - Copyright (C) 2011-2014 Andrew Nayenko + Copyright (C) 2011-2016 Andrew Nayenko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,12 +20,12 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include #include #include #include #include -#include static void print_generic_info(const struct exfat_super_block* sb) { @@ -140,9 +140,66 @@ static int dump_full(const char* spec, bool used_sectors) return 0; } +static int dump_file_fragments(const char* spec, const char* path) +{ + struct exfat ef; + struct exfat_node* node; + cluster_t cluster; + cluster_t next_cluster; + cluster_t fragment_start_cluster; + off_t remainder; + off_t fragment_size = 0; + int rc = 0; + + if (exfat_mount(&ef, spec, "ro") != 0) + return 1; + + rc = exfat_lookup(&ef, &node, path); + if (rc != 0) + { + exfat_unmount(&ef); + exfat_error("'%s': %s", path, strerror(-rc)); + return 1; + } + + cluster = fragment_start_cluster = node->start_cluster; + remainder = node->size; + while (remainder > 0) + { + off_t lsize; + + if (CLUSTER_INVALID(cluster)) + { + exfat_error("'%s' has invalid cluster %#x", path, cluster); + rc = 1; + break; + } + + lsize = MIN(CLUSTER_SIZE(*ef.sb), remainder); + fragment_size += lsize; + remainder -= lsize; + + next_cluster = exfat_next_cluster(&ef, node, cluster); + if (next_cluster != cluster + 1 || remainder == 0) + { + /* next cluster is not contiguous or this is EOF */ + printf("%"PRIu64" %"PRIu64"\n", + exfat_c2o(&ef, fragment_start_cluster), fragment_size); + /* start a new fragment */ + fragment_start_cluster = next_cluster; + fragment_size = 0; + } + cluster = next_cluster; + } + + exfat_put_node(&ef, node); + exfat_unmount(&ef); + return rc; +} + static void usage(const char* prog) { - fprintf(stderr, "Usage: %s [-s] [-u] [-V] \n", prog); + fprintf(stderr, "Usage: %s [-s] [-u] [-f file] [-V] \n", prog); exit(1); } @@ -152,11 +209,9 @@ int main(int argc, char* argv[]) const char* spec = NULL; bool sb_only = false; bool used_sectors = false; + const char* file_path = NULL; - printf("dumpexfat %u.%u.%u\n", - EXFAT_VERSION_MAJOR, EXFAT_VERSION_MINOR, EXFAT_VERSION_PATCH); - - while ((opt = getopt(argc, argv, "suV")) != -1) + while ((opt = getopt(argc, argv, "suf:V")) != -1) { switch (opt) { @@ -166,8 +221,12 @@ int main(int argc, char* argv[]) case 'u': used_sectors = true; break; + case 'f': + file_path = optarg; + break; case 'V': - puts("Copyright (C) 2011-2014 Andrew Nayenko"); + printf("dumpexfat %s\n", VERSION); + puts("Copyright (C) 2011-2016 Andrew Nayenko"); return 0; default: usage(argv[0]); @@ -177,6 +236,9 @@ int main(int argc, char* argv[]) usage(argv[0]); spec = argv[optind]; + if (file_path) + return dump_file_fragments(spec, file_path); + if (sb_only) return dump_sb(spec);