OSDN Git Service

Moved mount and unmount functions into separate file.
[android-x86/external-exfat.git] / libexfat / mount.c
1 /*
2  *  mount.c
3  *  exFAT file system implementation library.
4  *
5  *  Created by Andrew Nayenko on 22.10.09.
6  *  This software is distributed under the GNU General Public License 
7  *  version 3 or any later.
8  */
9
10 #include "exfat.h"
11 #include <string.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #define _XOPEN_SOURCE /* for tzset() in Linux */
16 #include <time.h>
17
18 static uint64_t rootdir_size(const struct exfat* ef)
19 {
20         uint64_t clusters = 0;
21         cluster_t rootdir_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
22
23         while (!CLUSTER_INVALID(rootdir_cluster))
24         {
25                 clusters++;
26                 /* root directory cannot be contiguous because there is no flag
27                    to indicate this */
28                 rootdir_cluster = exfat_next_cluster(ef, rootdir_cluster, 0);
29         }
30         return clusters * CLUSTER_SIZE(*ef->sb);
31 }
32
33 int exfat_mount(struct exfat* ef, const char* spec)
34 {
35         tzset();
36
37         ef->sb = malloc(sizeof(struct exfat_super_block));
38         if (ef->sb == NULL)
39         {
40                 exfat_error("memory allocation failed");
41                 return -ENOMEM;
42         }
43
44         ef->fd = open(spec, O_RDONLY); /* currently read only */
45         if (ef->fd < 0)
46         {
47                 free(ef->sb);
48                 exfat_error("failed to open `%s'", spec);
49                 return -EIO;
50         }
51
52         exfat_read_raw(ef->sb, sizeof(struct exfat_super_block), 0, ef->fd);
53         if (memcmp(ef->sb->oem_name, "EXFAT   ", 8) != 0)
54         {
55                 close(ef->fd);
56                 free(ef->sb);
57                 exfat_error("exFAT file system is not found");
58                 return -EIO;
59         }
60
61         ef->upcase = NULL;
62         ef->upcase_chars = 0;
63         ef->rootdir_size = rootdir_size(ef);
64
65         ef->root = malloc(sizeof(struct exfat_node));
66         if (ef->root == NULL)
67         {
68                 close(ef->fd);
69                 free(ef->sb);
70                 exfat_error("failed to allocate root node");
71                 return -ENOMEM;
72         }
73         memset(ef->root, 0, sizeof(struct exfat_node));
74         ef->root->flags = EXFAT_ATTRIB_DIR;
75         ef->root->size = ef->rootdir_size;
76         ef->root->start_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
77         ef->root->name[0] = cpu_to_le16('\0');
78         /* exFAT does not have time attributes for the root directory */
79         ef->root->mtime = 0;
80         ef->root->atime = 0;
81         /* always keep at least 1 reference to the root node */
82         exfat_get_node(ef->root);
83
84         return 0;
85 }
86
87 void exfat_unmount(struct exfat* ef)
88 {
89         exfat_put_node(ef->root);
90         exfat_reset_cache(ef);
91         ef->root = NULL;
92         close(ef->fd);
93         ef->fd = 0;
94         free(ef->sb);
95         ef->sb = NULL;
96         free(ef->upcase);
97         ef->upcase = NULL;
98         ef->upcase_chars = 0;
99 }