blob: 75f7ff19c3680b24fe7c46c36c84176f58573238 [file] [log] [blame]
relanfc88c472010-11-08 17:01:44 +00001/*
2 main.c (08.11.10)
relana271c7c2011-01-22 10:35:33 +00003 Prints detailed information about exFAT volume.
relanfc88c472010-11-08 17:01:44 +00004
relan48573ff2013-07-08 07:30:45 +00005 Free exFAT implementation.
reland2a4dd42016-06-03 08:20:53 +03006 Copyright (C) 2011-2016 Andrew Nayenko
relanfc88c472010-11-08 17:01:44 +00007
relan48573ff2013-07-08 07:30:45 +00008 This program is free software; you can redistribute it and/or modify
relanfc88c472010-11-08 17:01:44 +00009 it under the terms of the GNU General Public License as published by
relan48573ff2013-07-08 07:30:45 +000010 the Free Software Foundation, either version 2 of the License, or
relanfc88c472010-11-08 17:01:44 +000011 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
relan48573ff2013-07-08 07:30:45 +000018 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
relanfc88c472010-11-08 17:01:44 +000021*/
22
relanc05a94a2015-06-29 15:25:00 +030023#include <exfat.h>
relanfc88c472010-11-08 17:01:44 +000024#include <fcntl.h>
25#include <unistd.h>
26#include <inttypes.h>
27#include <stdio.h>
28#include <string.h>
relanfc88c472010-11-08 17:01:44 +000029
relan35f9a6e2011-01-24 17:57:38 +000030static void print_generic_info(const struct exfat_super_block* sb)
31{
32 printf("Volume serial number 0x%08x\n",
33 le32_to_cpu(sb->volume_serial));
34 printf("FS version %hhu.%hhu\n",
35 sb->version.major, sb->version.minor);
relanac418ad2011-01-24 18:13:41 +000036 printf("Sector size %10u\n",
relana39bcd22011-02-23 08:38:53 +000037 SECTOR_SIZE(*sb));
relan35f9a6e2011-01-24 17:57:38 +000038 printf("Cluster size %10u\n",
39 CLUSTER_SIZE(*sb));
40}
41
relana39bcd22011-02-23 08:38:53 +000042static void print_sector_info(const struct exfat_super_block* sb)
relan35f9a6e2011-01-24 17:57:38 +000043{
relanac418ad2011-01-24 18:13:41 +000044 printf("Sectors count %10"PRIu64"\n",
relana39bcd22011-02-23 08:38:53 +000045 le64_to_cpu(sb->sector_count));
relan35f9a6e2011-01-24 17:57:38 +000046}
47
48static void print_cluster_info(const struct exfat_super_block* sb)
49{
50 printf("Clusters count %10u\n",
51 le32_to_cpu(sb->cluster_count));
52}
53
54static void print_other_info(const struct exfat_super_block* sb)
relanfc88c472010-11-08 17:01:44 +000055{
relanac418ad2011-01-24 18:13:41 +000056 printf("First sector %10"PRIu64"\n",
relana39bcd22011-02-23 08:38:53 +000057 le64_to_cpu(sb->sector_start));
relanac418ad2011-01-24 18:13:41 +000058 printf("FAT first sector %10u\n",
relana39bcd22011-02-23 08:38:53 +000059 le32_to_cpu(sb->fat_sector_start));
relanac418ad2011-01-24 18:13:41 +000060 printf("FAT sectors count %10u\n",
relana39bcd22011-02-23 08:38:53 +000061 le32_to_cpu(sb->fat_sector_count));
relanac418ad2011-01-24 18:13:41 +000062 printf("First cluster sector %10u\n",
relana39bcd22011-02-23 08:38:53 +000063 le32_to_cpu(sb->cluster_sector_start));
relan8b265cf2011-01-22 18:51:17 +000064 printf("Root directory cluster %10u\n",
relanfc88c472010-11-08 17:01:44 +000065 le32_to_cpu(sb->rootdir_cluster));
relan8b265cf2011-01-22 18:51:17 +000066 printf("Volume state 0x%04hx\n",
relanfc88c472010-11-08 17:01:44 +000067 le16_to_cpu(sb->volume_state));
relan8b265cf2011-01-22 18:51:17 +000068 printf("FATs count %10hhu\n",
relanfc88c472010-11-08 17:01:44 +000069 sb->fat_count);
relan8b265cf2011-01-22 18:51:17 +000070 printf("Drive number 0x%02hhx\n",
relanfc88c472010-11-08 17:01:44 +000071 sb->drive_no);
relan8b265cf2011-01-22 18:51:17 +000072 printf("Allocated space %9hhu%%\n",
relanfc88c472010-11-08 17:01:44 +000073 sb->allocated_percent);
74}
75
relan35f9a6e2011-01-24 17:57:38 +000076static int dump_sb(const char* spec)
relanfc88c472010-11-08 17:01:44 +000077{
relanad3c8452012-03-03 07:39:07 +000078 struct exfat_dev* dev;
relanfc88c472010-11-08 17:01:44 +000079 struct exfat_super_block sb;
80
relan84e2bcb2012-12-04 18:34:01 +000081 dev = exfat_open(spec, EXFAT_MODE_RO);
relanad3c8452012-03-03 07:39:07 +000082 if (dev == NULL)
relanfc88c472010-11-08 17:01:44 +000083 return 1;
relan49aecac2011-04-22 19:27:00 +000084
relanad3c8452012-03-03 07:39:07 +000085 if (exfat_read(dev, &sb, sizeof(struct exfat_super_block)) < 0)
relanfc88c472010-11-08 17:01:44 +000086 {
relanad3c8452012-03-03 07:39:07 +000087 exfat_close(dev);
relaneca4ae82014-06-01 19:53:48 +000088 exfat_error("failed to read from '%s'", spec);
relanfc88c472010-11-08 17:01:44 +000089 return 1;
90 }
91 if (memcmp(sb.oem_name, "EXFAT ", sizeof(sb.oem_name)) != 0)
92 {
relanad3c8452012-03-03 07:39:07 +000093 exfat_close(dev);
relaneca4ae82014-06-01 19:53:48 +000094 exfat_error("exFAT file system is not found on '%s'", spec);
relanfc88c472010-11-08 17:01:44 +000095 return 1;
96 }
relan35f9a6e2011-01-24 17:57:38 +000097
98 print_generic_info(&sb);
relana39bcd22011-02-23 08:38:53 +000099 print_sector_info(&sb);
relan35f9a6e2011-01-24 17:57:38 +0000100 print_cluster_info(&sb);
101 print_other_info(&sb);
102
relanad3c8452012-03-03 07:39:07 +0000103 exfat_close(dev);
relanfc88c472010-11-08 17:01:44 +0000104 return 0;
105}
relan35f9a6e2011-01-24 17:57:38 +0000106
relan17f43542011-02-05 14:36:45 +0000107static void dump_sectors(struct exfat* ef)
108{
109 off_t a = 0, b = 0;
110
111 printf("Used sectors ");
relana39bcd22011-02-23 08:38:53 +0000112 while (exfat_find_used_sectors(ef, &a, &b) == 0)
relan17f43542011-02-05 14:36:45 +0000113 printf(" %"PRIu64"-%"PRIu64, a, b);
114 puts("");
115}
116
relan572ac772012-12-12 19:16:42 +0000117static int dump_full(const char* spec, bool used_sectors)
relan35f9a6e2011-01-24 17:57:38 +0000118{
119 struct exfat ef;
120 uint32_t free_clusters;
relana39bcd22011-02-23 08:38:53 +0000121 uint64_t free_sectors;
relan35f9a6e2011-01-24 17:57:38 +0000122
123 if (exfat_mount(&ef, spec, "ro") != 0)
124 return 1;
125
126 free_clusters = exfat_count_free_clusters(&ef);
relana39bcd22011-02-23 08:38:53 +0000127 free_sectors = (uint64_t) free_clusters << ef.sb->spc_bits;
relan35f9a6e2011-01-24 17:57:38 +0000128
129 printf("Volume label %15s\n", exfat_get_label(&ef));
130 print_generic_info(ef.sb);
relana39bcd22011-02-23 08:38:53 +0000131 print_sector_info(ef.sb);
132 printf("Free sectors %10"PRIu64"\n", free_sectors);
relan35f9a6e2011-01-24 17:57:38 +0000133 print_cluster_info(ef.sb);
134 printf("Free clusters %10u\n", free_clusters);
135 print_other_info(ef.sb);
relan17f43542011-02-05 14:36:45 +0000136 if (used_sectors)
137 dump_sectors(&ef);
relan35f9a6e2011-01-24 17:57:38 +0000138
139 exfat_unmount(&ef);
140 return 0;
141}
142
143static void usage(const char* prog)
144{
relan8ba82142013-03-28 16:51:12 +0000145 fprintf(stderr, "Usage: %s [-s] [-u] [-V] <device>\n", prog);
relan35f9a6e2011-01-24 17:57:38 +0000146 exit(1);
147}
148
149int main(int argc, char* argv[])
150{
relan31b12322013-03-29 06:29:10 +0000151 int opt;
relan35f9a6e2011-01-24 17:57:38 +0000152 const char* spec = NULL;
relan572ac772012-12-12 19:16:42 +0000153 bool sb_only = false;
154 bool used_sectors = false;
relan35f9a6e2011-01-24 17:57:38 +0000155
relanc50537e2015-06-29 15:32:49 +0300156 printf("dumpexfat %s\n", VERSION);
relan9c76a442011-03-01 05:35:14 +0000157
relan31b12322013-03-29 06:29:10 +0000158 while ((opt = getopt(argc, argv, "suV")) != -1)
relan35f9a6e2011-01-24 17:57:38 +0000159 {
relan31b12322013-03-29 06:29:10 +0000160 switch (opt)
relan9c76a442011-03-01 05:35:14 +0000161 {
relan31b12322013-03-29 06:29:10 +0000162 case 's':
163 sb_only = true;
164 break;
165 case 'u':
166 used_sectors = true;
167 break;
168 case 'V':
reland2a4dd42016-06-03 08:20:53 +0300169 puts("Copyright (C) 2011-2016 Andrew Nayenko");
relan9c76a442011-03-01 05:35:14 +0000170 return 0;
relan31b12322013-03-29 06:29:10 +0000171 default:
relan35f9a6e2011-01-24 17:57:38 +0000172 usage(argv[0]);
relan31b12322013-03-29 06:29:10 +0000173 }
relan35f9a6e2011-01-24 17:57:38 +0000174 }
relan31b12322013-03-29 06:29:10 +0000175 if (argc - optind != 1)
relan35f9a6e2011-01-24 17:57:38 +0000176 usage(argv[0]);
relan31b12322013-03-29 06:29:10 +0000177 spec = argv[optind];
relan35f9a6e2011-01-24 17:57:38 +0000178
179 if (sb_only)
180 return dump_sb(spec);
relan17f43542011-02-05 14:36:45 +0000181
182 return dump_full(spec, used_sectors);
relan35f9a6e2011-01-24 17:57:38 +0000183}