X-Git-Url: http://git.sven.stormbind.net/?p=sven%2Fexfat-utils.git;a=blobdiff_plain;f=dump%2Fmain.c;h=fda5b9b35b5ca125463659d86eade510486259b1;hp=fa80903b8a0c07a32c20d3a6daee67c50ce52e2b;hb=refs%2Ftags%2Fupstream%2F1.2.5;hpb=4efb596cee7f7cc961990f8dffc3b210e579e49c diff --git a/dump/main.c b/dump/main.c index fa80903..fda5b9b 100644 --- a/dump/main.c +++ b/dump/main.c @@ -2,11 +2,12 @@ main.c (08.11.10) Prints detailed information about exFAT volume. - Copyright (C) 2011-2013 Andrew Nayenko + Free exFAT implementation. + Copyright (C) 2011-2016 Andrew Nayenko - This program is free software: you can redistribute it and/or modify + 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 - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,16 +15,17 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 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) { @@ -83,13 +85,13 @@ static int dump_sb(const char* spec) if (exfat_read(dev, &sb, sizeof(struct exfat_super_block)) < 0) { exfat_close(dev); - exfat_error("failed to read from `%s'", spec); + exfat_error("failed to read from '%s'", spec); return 1; } if (memcmp(sb.oem_name, "EXFAT ", sizeof(sb.oem_name)) != 0) { exfat_close(dev); - exfat_error("exFAT file system is not found on `%s'", spec); + exfat_error("exFAT file system is not found on '%s'", spec); return 1; } @@ -138,40 +140,104 @@ 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); } int main(int argc, char* argv[]) { - char** pp; + int opt; 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); - - for (pp = argv + 1; *pp; pp++) + while ((opt = getopt(argc, argv, "suf:V")) != -1) { - if (strcmp(*pp, "-s") == 0) + switch (opt) + { + case 's': sb_only = true; - else if (strcmp(*pp, "-u") == 0) + break; + case 'u': used_sectors = true; - else if (strcmp(*pp, "-v") == 0) - { - puts("Copyright (C) 2011-2013 Andrew Nayenko"); + break; + case 'f': + file_path = optarg; + break; + case 'V': + printf("dumpexfat %s\n", VERSION); + puts("Copyright (C) 2011-2016 Andrew Nayenko"); return 0; - } - else if (spec == NULL) - spec = *pp; - else + default: usage(argv[0]); + } } - if (spec == NULL) + if (argc - optind != 1) usage(argv[0]); + spec = argv[optind]; + + if (file_path) + return dump_file_fragments(spec, file_path); if (sb_only) return dump_sb(spec);