Imported Upstream version 0.9.5
[sven/exfat-utils.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                         SECTOR_SIZE(*sb));
36         printf("Cluster size              %10u\n",
37                         CLUSTER_SIZE(*sb));
38 }
39
40 static void print_sector_info(const struct exfat_super_block* sb)
41 {
42         printf("Sectors count             %10"PRIu64"\n",
43                         le64_to_cpu(sb->sector_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->sector_start));
56         printf("FAT first sector          %10u\n",
57                         le32_to_cpu(sb->fat_sector_start));
58         printf("FAT sectors count         %10u\n",
59                         le32_to_cpu(sb->fat_sector_count));
60         printf("First cluster sector      %10u\n",
61                         le32_to_cpu(sb->cluster_sector_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 = exfat_open(spec, 1);
80         if (fd < 0)
81                 return 1;
82
83         if (read(fd, &sb, sizeof(struct exfat_super_block))
84                         != sizeof(struct exfat_super_block))
85         {
86                 close(fd);
87                 exfat_error("failed to read from `%s'", spec);
88                 return 1;
89         }
90         if (memcmp(sb.oem_name, "EXFAT   ", sizeof(sb.oem_name)) != 0)
91         {
92                 close(fd);
93                 exfat_error("exFAT file system is not found on `%s'", spec);
94                 return 1;
95         }
96
97         print_generic_info(&sb);
98         print_sector_info(&sb);
99         print_cluster_info(&sb);
100         print_other_info(&sb);
101
102         close(fd);
103         return 0;
104 }
105
106 static void dump_sectors(struct exfat* ef)
107 {
108         off_t a = 0, b = 0;
109
110         printf("Used sectors ");
111         while (exfat_find_used_sectors(ef, &a, &b) == 0)
112                 printf(" %"PRIu64"-%"PRIu64, a, b);
113         puts("");
114 }
115
116 static int dump_full(const char* spec, int used_sectors)
117 {
118         struct exfat ef;
119         uint32_t free_clusters;
120         uint64_t free_sectors;
121
122         if (exfat_mount(&ef, spec, "ro") != 0)
123                 return 1;
124
125         free_clusters = exfat_count_free_clusters(&ef);
126         free_sectors = (uint64_t) free_clusters << ef.sb->spc_bits;
127
128         printf("Volume label         %15s\n", exfat_get_label(&ef));
129         print_generic_info(ef.sb);
130         print_sector_info(ef.sb);
131         printf("Free sectors              %10"PRIu64"\n", free_sectors);
132         print_cluster_info(ef.sb);
133         printf("Free clusters             %10u\n", free_clusters);
134         print_other_info(ef.sb);
135         if (used_sectors)
136                 dump_sectors(&ef);
137
138         exfat_unmount(&ef);
139         return 0;
140 }
141
142 static void usage(const char* prog)
143 {
144         fprintf(stderr, "Usage: %s [-s] [-u] [-v] <device>\n", prog);
145         exit(1);
146 }
147
148 int main(int argc, char* argv[])
149 {
150         char** pp;
151         const char* spec = NULL;
152         int sb_only = 0;
153         int used_sectors = 0;
154
155         printf("dumpexfat %u.%u.%u\n",
156                         EXFAT_VERSION_MAJOR, EXFAT_VERSION_MINOR, EXFAT_VERSION_PATCH);
157
158         for (pp = argv + 1; *pp; pp++)
159         {
160                 if (strcmp(*pp, "-s") == 0)
161                         sb_only = 1;
162                 else if (strcmp(*pp, "-u") == 0)
163                         used_sectors = 1;
164                 else if (strcmp(*pp, "-v") == 0)
165                 {
166                         puts("Copyright (C) 2010  Andrew Nayenko");
167                         return 0;
168                 }
169                 else if (spec == NULL)
170                         spec = *pp;
171                 else
172                         usage(argv[0]);
173         }
174         if (spec == NULL)
175                 usage(argv[0]);
176
177         if (sb_only)
178                 return dump_sb(spec);
179
180         return dump_full(spec, used_sectors);
181 }