3 * exFAT file system implementation library.
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.
16 #include <sys/types.h>
18 #define _XOPEN_SOURCE /* for tzset() in Linux */
21 static uint64_t rootdir_size(const struct exfat* ef)
23 uint64_t clusters = 0;
24 cluster_t rootdir_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
26 while (!CLUSTER_INVALID(rootdir_cluster))
29 /* root directory cannot be contiguous because there is no flag
31 rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster);
33 return clusters * CLUSTER_SIZE(*ef->sb);
36 static const char* get_option(const char* options, const char* option_name)
38 const char* p = strstr(options, option_name);
39 size_t length = strlen(option_name);
43 if ((p != options && p[-1] != ',') || p[length] != '=')
45 return p + length + 1;
48 static int get_int_option(const char* options, const char* option_name,
49 int base, int default_value)
51 const char* p = get_option(options, option_name);
55 return strtol(p, NULL, base);
58 static void parse_options(struct exfat* ef, const char* options)
60 int sys_umask = umask(0);
63 umask(sys_umask); /* restore umask */
64 opt_umask = get_int_option(options, "umask", 8, sys_umask);
65 ef->dmask = get_int_option(options, "dmask", 8, opt_umask) & 0777;
66 ef->fmask = get_int_option(options, "fmask", 8, opt_umask) & 0777;
69 int exfat_mount(struct exfat* ef, const char* spec, const char* options)
72 memset(ef, 0, sizeof(struct exfat));
74 ef->sb = malloc(sizeof(struct exfat_super_block));
77 exfat_error("memory allocation failed");
80 memset(ef->sb, 0, sizeof(struct exfat_super_block));
82 parse_options(ef, options);
84 ef->fd = open(spec, O_RDWR);
88 exfat_error("failed to open `%s'", spec);
92 exfat_read_raw(ef->sb, sizeof(struct exfat_super_block), 0, ef->fd);
93 if (memcmp(ef->sb->oem_name, "EXFAT ", 8) != 0)
97 exfat_error("exFAT file system is not found");
101 ef->zero_block = malloc(BLOCK_SIZE(*ef->sb));
102 if (ef->zero_block == NULL)
106 exfat_error("failed to allocate zero block");
109 memset(ef->zero_block, 0, BLOCK_SIZE(*ef->sb));
111 ef->root = malloc(sizeof(struct exfat_node));
112 if (ef->root == NULL)
114 free(ef->zero_block);
117 exfat_error("failed to allocate root node");
120 memset(ef->root, 0, sizeof(struct exfat_node));
121 ef->root->flags = EXFAT_ATTRIB_DIR;
122 ef->root->start_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
123 ef->root->fptr_cluster = ef->root->start_cluster;
124 ef->root->name[0] = cpu_to_le16('\0');
125 ef->root->size = rootdir_size(ef);
126 /* exFAT does not have time attributes for the root directory */
129 /* always keep at least 1 reference to the root node */
130 exfat_get_node(ef->root);
135 void exfat_unmount(struct exfat* ef)
137 exfat_put_node(ef, ef->root);
138 exfat_reset_cache(ef);
141 free(ef->zero_block);
142 ef->zero_block = NULL;
143 free(ef->cmap.chunk);
144 ef->cmap.chunk = NULL;
151 ef->upcase_chars = 0;