OSDN Git Service

Add -u option for dumpexfat that prints used sectors.
[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("Sector 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("Sectors 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 sector              %10"PRIu64"\n",
55                         le64_to_cpu(sb->block_start));
56         printf("FAT first sector          %10u\n",
57                         le32_to_cpu(sb->fat_block_start));
58         printf("FAT sectors count         %10u\n",
59                         le32_to_cpu(sb->fat_block_count));
60         printf("First cluster sector      %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 void dump_sectors(struct exfat* ef)
109 {
110         off_t a = 0, b = 0;
111
112         printf("Used sectors ");
113         while (exfat_find_used_blocks(ef, &a, &b) == 0)
114                 printf(" %"PRIu64"-%"PRIu64, a, b);
115         puts("");
116 }
117
118 static int dump_full(const char* spec, int used_sectors)
119 {
120         struct exfat ef;
121         uint32_t free_clusters;
122         uint64_t free_blocks;
123
124         if (exfat_mount(&ef, spec, "ro") != 0)
125                 return 1;
126
127         free_clusters = exfat_count_free_clusters(&ef);
128         free_blocks = (uint64_t) free_clusters << ef.sb->bpc_bits;
129
130         printf("Volume label         %15s\n", exfat_get_label(&ef));
131         print_generic_info(ef.sb);
132         print_block_info(ef.sb);
133         printf("Free sectors              %10"PRIu64"\n", free_blocks);
134         print_cluster_info(ef.sb);
135         printf("Free clusters             %10u\n", free_clusters);
136         print_other_info(ef.sb);
137         if (used_sectors)
138                 dump_sectors(&ef);
139
140         exfat_unmount(&ef);
141         return 0;
142 }
143
144 static void usage(const char* prog)
145 {
146         fprintf(stderr, "Usage: %s [-s] [-u] <device>\n", prog);
147         exit(1);
148 }
149
150 int main(int argc, char* argv[])
151 {
152         char** pp;
153         const char* spec = NULL;
154         int sb_only = 0;
155         int used_sectors = 0;
156
157         for (pp = argv + 1; *pp; pp++)
158         {
159                 if (strcmp(*pp, "-s") == 0)
160                         sb_only = 1;
161                 else if (strcmp(*pp, "-u") == 0)
162                         used_sectors = 1;
163                 else if (spec == NULL)
164                         spec = *pp;
165                 else
166                         usage(argv[0]);
167         }
168         if (spec == NULL)
169                 usage(argv[0]);
170
171         if (sb_only)
172                 return dump_sb(spec);
173
174         return dump_full(spec, used_sectors);
175 }