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 <exfat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <string.h>
-#include <exfat.h>
 
 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] <device>\n", prog);
+	fprintf(stderr, "Usage: %s [-s] [-u] [-f file] [-V] <device>\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);