]> git.sven.stormbind.net Git - sven/fuse-exfat.git/blob - libexfat/mount.c
New upstream version 1.3.0+git20220115
[sven/fuse-exfat.git] / libexfat / mount.c
1 /*
2         mount.c (22.10.09)
3         exFAT file system implementation library.
4
5         Free exFAT implementation.
6         Copyright (C) 2010-2018  Andrew Nayenko
7
8         This program is free software; you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 2 of the License, or
11         (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
18         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.
21 */
22
23 #include "exfat.h"
24 #include <string.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <inttypes.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30
31 static uint64_t rootdir_size(const struct exfat* ef)
32 {
33         uint32_t clusters = 0;
34         uint32_t clusters_max = le32_to_cpu(ef->sb->cluster_count);
35         cluster_t rootdir_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
36
37         /* Iterate all clusters of the root directory to calculate its size.
38            It can't be contiguous because there is no flag to indicate this. */
39         do
40         {
41                 if (clusters == clusters_max) /* infinite loop detected */
42                 {
43                         exfat_error("root directory cannot occupy all %d clusters",
44                                         clusters);
45                         return 0;
46                 }
47                 if (CLUSTER_INVALID(*ef->sb, rootdir_cluster))
48                 {
49                         exfat_error("bad cluster %#x while reading root directory",
50                                         rootdir_cluster);
51                         return 0;
52                 }
53                 rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster);
54                 clusters++;
55         }
56         while (rootdir_cluster != EXFAT_CLUSTER_END);
57
58         return (uint64_t) clusters * CLUSTER_SIZE(*ef->sb);
59 }
60
61 static const char* get_option(const char* options, const char* option_name)
62 {
63         const char* p;
64         size_t length = strlen(option_name);
65
66         for (p = strstr(options, option_name); p; p = strstr(p + 1, option_name))
67                 if ((p == options || p[-1] == ',') && p[length] == '=')
68                         return p + length + 1;
69         return NULL;
70 }
71
72 static int get_int_option(const char* options, const char* option_name,
73                 int base, int default_value)
74 {
75         const char* p = get_option(options, option_name);
76
77         if (p == NULL)
78                 return default_value;
79         return strtol(p, NULL, base);
80 }
81
82 static void parse_options(struct exfat* ef, const char* options)
83 {
84         int opt_umask;
85
86         opt_umask = get_int_option(options, "umask", 8, 0);
87         ef->dmask = get_int_option(options, "dmask", 8, opt_umask);
88         ef->fmask = get_int_option(options, "fmask", 8, opt_umask);
89
90         ef->uid = get_int_option(options, "uid", 10, geteuid());
91         ef->gid = get_int_option(options, "gid", 10, getegid());
92
93         ef->noatime = exfat_match_option(options, "noatime");
94
95         switch (get_int_option(options, "repair", 10, 0))
96         {
97         case 1:
98                 ef->repair = EXFAT_REPAIR_ASK;
99                 break;
100         case 2:
101                 ef->repair = EXFAT_REPAIR_YES;
102                 break;
103         default:
104                 ef->repair = EXFAT_REPAIR_NO;
105                 break;
106         }
107 }
108
109 static bool verify_vbr_checksum(const struct exfat* ef, void* sector)
110 {
111         off_t sector_size = SECTOR_SIZE(*ef->sb);
112         uint32_t vbr_checksum;
113         size_t i;
114
115         if (exfat_pread(ef->dev, sector, sector_size, 0) < 0)
116         {
117                 exfat_error("failed to read boot sector");
118                 return false;
119         }
120         vbr_checksum = exfat_vbr_start_checksum(sector, sector_size);
121         for (i = 1; i < 11; i++)
122         {
123                 if (exfat_pread(ef->dev, sector, sector_size, i * sector_size) < 0)
124                 {
125                         exfat_error("failed to read VBR sector");
126                         return false;
127                 }
128                 vbr_checksum = exfat_vbr_add_checksum(sector, sector_size,
129                                 vbr_checksum);
130         }
131         if (exfat_pread(ef->dev, sector, sector_size, i * sector_size) < 0)
132         {
133                 exfat_error("failed to read VBR checksum sector");
134                 return false;
135         }
136         for (i = 0; i < sector_size / sizeof(vbr_checksum); i++)
137                 if (le32_to_cpu(((const le32_t*) sector)[i]) != vbr_checksum)
138                 {
139                         exfat_error("invalid VBR checksum 0x%x (expected 0x%x)",
140                                         le32_to_cpu(((const le32_t*) sector)[i]), vbr_checksum);
141                         if (!EXFAT_REPAIR(invalid_vbr_checksum, ef, sector, vbr_checksum))
142                                 return false;
143                 }
144         return true;
145 }
146
147 static int commit_super_block(const struct exfat* ef)
148 {
149         if (exfat_pwrite(ef->dev, ef->sb, sizeof(struct exfat_super_block), 0) < 0)
150         {
151                 exfat_error("failed to write super block");
152                 return 1;
153         }
154         return exfat_fsync(ef->dev);
155 }
156
157 int exfat_soil_super_block(const struct exfat* ef)
158 {
159         if (ef->ro)
160                 return 0;
161
162         ef->sb->volume_state = cpu_to_le16(
163                         le16_to_cpu(ef->sb->volume_state) | EXFAT_STATE_MOUNTED);
164         return commit_super_block(ef);
165 }
166
167 static void exfat_free(struct exfat* ef)
168 {
169         exfat_close(ef->dev);   /* first of all, close the descriptor */
170         ef->dev = NULL;                 /* struct exfat_dev is freed by exfat_close() */
171         free(ef->root);
172         ef->root = NULL;
173         free(ef->zero_cluster);
174         ef->zero_cluster = NULL;
175         free(ef->cmap.chunk);
176         ef->cmap.chunk = NULL;
177         free(ef->upcase);
178         ef->upcase = NULL;
179         free(ef->sb);
180         ef->sb = NULL;
181 }
182
183 int exfat_mount(struct exfat* ef, const char* spec, const char* options)
184 {
185         int rc;
186         enum exfat_mode mode;
187
188         exfat_tzset();
189         memset(ef, 0, sizeof(struct exfat));
190
191         parse_options(ef, options);
192
193         if (exfat_match_option(options, "ro"))
194                 mode = EXFAT_MODE_RO;
195         else if (exfat_match_option(options, "ro_fallback"))
196                 mode = EXFAT_MODE_ANY;
197         else
198                 mode = EXFAT_MODE_RW;
199         ef->dev = exfat_open(spec, mode);
200         if (ef->dev == NULL)
201                 return -EIO;
202         if (exfat_get_mode(ef->dev) == EXFAT_MODE_RO)
203         {
204                 if (mode == EXFAT_MODE_ANY)
205                         ef->ro = -1;
206                 else
207                         ef->ro = 1;
208         }
209
210         ef->sb = malloc(sizeof(struct exfat_super_block));
211         if (ef->sb == NULL)
212         {
213                 exfat_error("failed to allocate memory for the super block");
214                 exfat_free(ef);
215                 return -ENOMEM;
216         }
217         memset(ef->sb, 0, sizeof(struct exfat_super_block));
218
219         if (exfat_pread(ef->dev, ef->sb, sizeof(struct exfat_super_block), 0) < 0)
220         {
221                 exfat_error("failed to read boot sector");
222                 exfat_free(ef);
223                 return -EIO;
224         }
225         if (memcmp(ef->sb->oem_name, "EXFAT   ", 8) != 0)
226         {
227                 exfat_error("exFAT file system is not found");
228                 exfat_free(ef);
229                 return -EIO;
230         }
231         /* sector cannot be smaller than 512 bytes */
232         if (ef->sb->sector_bits < 9)
233         {
234                 exfat_error("too small sector size: 2^%hhd", ef->sb->sector_bits);
235                 exfat_free(ef);
236                 return -EIO;
237         }
238         /* officially exFAT supports cluster size up to 32 MB */
239         if ((int) ef->sb->sector_bits + (int) ef->sb->spc_bits > 25)
240         {
241                 exfat_error("too big cluster size: 2^(%hhd+%hhd)",
242                                 ef->sb->sector_bits, ef->sb->spc_bits);
243                 exfat_free(ef);
244                 return -EIO;
245         }
246         ef->zero_cluster = malloc(CLUSTER_SIZE(*ef->sb));
247         if (ef->zero_cluster == NULL)
248         {
249                 exfat_error("failed to allocate zero sector");
250                 exfat_free(ef);
251                 return -ENOMEM;
252         }
253         /* use zero_cluster as a temporary buffer for VBR checksum verification */
254         if (!verify_vbr_checksum(ef, ef->zero_cluster))
255         {
256                 exfat_free(ef);
257                 return -EIO;
258         }
259         memset(ef->zero_cluster, 0, CLUSTER_SIZE(*ef->sb));
260         if (ef->sb->version.major != 1 || ef->sb->version.minor != 0)
261         {
262                 exfat_error("unsupported exFAT version: %hhu.%hhu",
263                                 ef->sb->version.major, ef->sb->version.minor);
264                 exfat_free(ef);
265                 return -EIO;
266         }
267         if (ef->sb->fat_count != 1)
268         {
269                 exfat_error("unsupported FAT count: %hhu", ef->sb->fat_count);
270                 exfat_free(ef);
271                 return -EIO;
272         }
273         if (le64_to_cpu(ef->sb->sector_count) * SECTOR_SIZE(*ef->sb) >
274                         (uint64_t) exfat_get_size(ef->dev))
275         {
276                 /* this can cause I/O errors later but we don't fail mounting to let
277                    user rescue data */
278                 exfat_warn("file system in sectors is larger than device: "
279                                 "%"PRIu64" * %d > %"PRIu64,
280                                 le64_to_cpu(ef->sb->sector_count), SECTOR_SIZE(*ef->sb),
281                                 exfat_get_size(ef->dev));
282         }
283         if ((off_t) le32_to_cpu(ef->sb->cluster_count) * CLUSTER_SIZE(*ef->sb) >
284                         exfat_get_size(ef->dev))
285         {
286                 exfat_error("file system in clusters is larger than device: "
287                                 "%u * %d > %"PRIu64,
288                                 le32_to_cpu(ef->sb->cluster_count), CLUSTER_SIZE(*ef->sb),
289                                 exfat_get_size(ef->dev));
290                 exfat_free(ef);
291                 return -EIO;
292         }
293         if (le16_to_cpu(ef->sb->volume_state) & EXFAT_STATE_MOUNTED)
294                 exfat_warn("volume was not unmounted cleanly");
295
296         ef->root = malloc(sizeof(struct exfat_node));
297         if (ef->root == NULL)
298         {
299                 exfat_error("failed to allocate root node");
300                 exfat_free(ef);
301                 return -ENOMEM;
302         }
303         memset(ef->root, 0, sizeof(struct exfat_node));
304         ef->root->attrib = EXFAT_ATTRIB_DIR;
305         ef->root->start_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
306         ef->root->fptr_cluster = ef->root->start_cluster;
307         ef->root->name[0] = cpu_to_le16('\0');
308         ef->root->size = rootdir_size(ef);
309         if (ef->root->size == 0)
310         {
311                 exfat_free(ef);
312                 return -EIO;
313         }
314         /* exFAT does not have time attributes for the root directory */
315         ef->root->mtime = 0;
316         ef->root->atime = 0;
317         /* always keep at least 1 reference to the root node */
318         exfat_get_node(ef->root);
319
320         rc = exfat_cache_directory(ef, ef->root);
321         if (rc != 0)
322                 goto error;
323         if (ef->upcase == NULL)
324         {
325                 exfat_error("upcase table is not found");
326                 goto error;
327         }
328         if (ef->cmap.chunk == NULL)
329         {
330                 exfat_error("clusters bitmap is not found");
331                 goto error;
332         }
333
334         return 0;
335
336 error:
337         exfat_put_node(ef, ef->root);
338         exfat_reset_cache(ef);
339         exfat_free(ef);
340         return -EIO;
341 }
342
343 static void finalize_super_block(struct exfat* ef)
344 {
345         if (ef->ro)
346                 return;
347
348         ef->sb->volume_state = cpu_to_le16(
349                         le16_to_cpu(ef->sb->volume_state) & ~EXFAT_STATE_MOUNTED);
350
351         /* Some implementations set the percentage of allocated space to 0xff
352            on FS creation and never update it. In this case leave it as is. */
353         if (ef->sb->allocated_percent != 0xff)
354         {
355                 uint32_t free, total;
356
357                 free = exfat_count_free_clusters(ef);
358                 total = le32_to_cpu(ef->sb->cluster_count);
359                 ef->sb->allocated_percent = ((total - free) * 100 + total / 2) / total;
360         }
361
362         commit_super_block(ef); /* ignore return code */
363 }
364
365 void exfat_unmount(struct exfat* ef)
366 {
367         exfat_flush_nodes(ef);  /* ignore return code */
368         exfat_flush(ef);                /* ignore return code */
369         exfat_put_node(ef, ef->root);
370         exfat_reset_cache(ef);
371         finalize_super_block(ef);
372         exfat_free(ef);                 /* will close the descriptor */
373 }