OSDN Git Service

Improved dumpexfat: now it also prints volume label, free sectors and free clusters...
[android-x86/external-exfat.git] / dump / main.c
1 /*
2         main.c (08.11.10)
3         Prints detailed information about exFAT volume.
4
5         Copyright (C) 2010  Andrew Nayenko
6
7         This program is free software: you can redistribute it and/or modify
8         it under the terms of the GNU General Public License as published by
9         the Free Software Foundation, either version 3 of the License, or
10         (at your option) any later version.
11
12         This program is distributed in the hope that it will be useful,
13         but WITHOUT ANY WARRANTY; without even the implied warranty of
14         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15         GNU General Public License for more details.
16
17         You should have received a copy of the GNU General Public License
18         along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <inttypes.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <exfat.h>
27
28 static void print_generic_info(const struct exfat_super_block* sb)
29 {
30         printf("Volume serial number      0x%08x\n",
31                         le32_to_cpu(sb->volume_serial));
32         printf("FS version                       %hhu.%hhu\n",
33                         sb->version.major, sb->version.minor);
34         printf("Block size                %10u\n",
35                         BLOCK_SIZE(*sb));
36         printf("Cluster size              %10u\n",
37                         CLUSTER_SIZE(*sb));
38 }
39
40 static void print_block_info(const struct exfat_super_block* sb)
41 {
42         printf("Blocks count              %10"PRIu64"\n",
43                         le64_to_cpu(sb->block_count));
44 }
45
46 static void print_cluster_info(const struct exfat_super_block* sb)
47 {
48         printf("Clusters count            %10u\n",
49                         le32_to_cpu(sb->cluster_count));
50 }
51
52 static void print_other_info(const struct exfat_super_block* sb)
53 {
54         printf("First block               %10"PRIu64"\n",
55                         le64_to_cpu(sb->block_start));
56         printf("FAT first block           %10u\n",
57                         le32_to_cpu(sb->fat_block_start));
58         printf("FAT blocks count          %10u\n",
59                         le32_to_cpu(sb->fat_block_count));
60         printf("First cluster block       %10u\n",
61                         le32_to_cpu(sb->cluster_block_start));
62         printf("Root directory cluster    %10u\n",
63                         le32_to_cpu(sb->rootdir_cluster));
64         printf("Volume state                  0x%04hx\n",
65                         le16_to_cpu(sb->volume_state));
66         printf("FATs count                %10hhu\n",
67                         sb->fat_count);
68         printf("Drive number                    0x%02hhx\n",
69                         sb->drive_no);
70         printf("Allocated space           %9hhu%%\n",
71                         sb->allocated_percent);
72 }
73
74 static int dump_sb(const char* spec)
75 {
76         int fd;
77         struct exfat_super_block sb;
78
79         fd = open(spec, O_RDONLY);
80         if (fd < 0)
81         {
82                 exfat_error("failed to open `%s'", spec);
83                 return 1;
84         }
85         if (read(fd, &sb, sizeof(struct exfat_super_block))
86                         != sizeof(struct exfat_super_block))
87         {
88                 close(fd);
89                 exfat_error("failed to read from `%s'", spec);
90                 return 1;
91         }
92         if (memcmp(sb.oem_name, "EXFAT   ", sizeof(sb.oem_name)) != 0)
93         {
94                 close(fd);
95                 exfat_error("exFAT file system is not found on `%s'", spec);
96                 return 1;
97         }
98
99         print_generic_info(&sb);
100         print_block_info(&sb);
101         print_cluster_info(&sb);
102         print_other_info(&sb);
103
104         close(fd);
105         return 0;
106 }
107
108 static int dump_full(const char* spec)
109 {
110         struct exfat ef;
111         uint32_t free_clusters;
112         uint64_t free_blocks;
113
114         if (exfat_mount(&ef, spec, "ro") != 0)
115                 return 1;
116
117         free_clusters = exfat_count_free_clusters(&ef);
118         free_blocks = (uint64_t) free_clusters << ef.sb->bpc_bits;
119
120         printf("Volume label         %15s\n", exfat_get_label(&ef));
121         print_generic_info(ef.sb);
122         print_block_info(ef.sb);
123         printf("Free blocks               %10"PRIu64"\n", free_blocks);
124         print_cluster_info(ef.sb);
125         printf("Free clusters             %10u\n", free_clusters);
126         print_other_info(ef.sb);
127
128         exfat_unmount(&ef);
129         return 0;
130 }
131
132 static void usage(const char* prog)
133 {
134         fprintf(stderr, "Usage: %s [-s] <device>\n", prog);
135         exit(1);
136 }
137
138 int main(int argc, char* argv[])
139 {
140         char** pp;
141         const char* spec = NULL;
142         int sb_only = 0;
143
144         for (pp = argv + 1; *pp; pp++)
145         {
146                 if (strcmp(*pp, "-s") == 0)
147                         sb_only = 1;
148                 else if (spec == NULL)
149                         spec = *pp;
150                 else
151                         usage(argv[0]);
152         }
153         if (spec == NULL)
154                 usage(argv[0]);
155
156         if (sb_only)
157                 return dump_sb(spec);
158         else
159                 return dump_full(spec);
160 }