OSDN Git Service

Implemented existing files writing in libexfat.
[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, ef->root, rootdir_cluster);
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         memset(ef->sb, 0, sizeof(struct exfat_super_block));
44
45         ef->fd = open(spec, O_RDWR);
46         if (ef->fd < 0)
47         {
48                 free(ef->sb);
49                 exfat_error("failed to open `%s'", spec);
50                 return -EIO;
51         }
52
53         exfat_read_raw(ef->sb, sizeof(struct exfat_super_block), 0, ef->fd);
54         if (memcmp(ef->sb->oem_name, "EXFAT   ", 8) != 0)
55         {
56                 close(ef->fd);
57                 free(ef->sb);
58                 exfat_error("exFAT file system is not found");
59                 return -EIO;
60         }
61
62         ef->zero_block = malloc(BLOCK_SIZE(*ef->sb));
63         if (ef->zero_block == NULL)
64         {
65                 close(ef->fd);
66                 free(ef->sb);
67                 exfat_error("failed to allocate zero block");
68                 return -ENOMEM;
69         }
70         memset(ef->zero_block, 0, BLOCK_SIZE(*ef->sb));
71
72         ef->root = malloc(sizeof(struct exfat_node));
73         if (ef->root == NULL)
74         {
75                 free(ef->zero_block);
76                 close(ef->fd);
77                 free(ef->sb);
78                 exfat_error("failed to allocate root node");
79                 return -ENOMEM;
80         }
81         memset(ef->root, 0, sizeof(struct exfat_node));
82         ef->root->flags = EXFAT_ATTRIB_DIR;
83         ef->root->start_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
84         ef->root->name[0] = cpu_to_le16('\0');
85         ef->root->size = rootdir_size(ef);
86         /* exFAT does not have time attributes for the root directory */
87         ef->root->mtime = 0;
88         ef->root->atime = 0;
89         /* always keep at least 1 reference to the root node */
90         exfat_get_node(ef->root);
91
92         return 0;
93 }
94
95 void exfat_unmount(struct exfat* ef)
96 {
97         exfat_put_node(ef->root);
98         exfat_reset_cache(ef);
99         ef->root = NULL;
100         free(ef->zero_block);
101         ef->zero_block = NULL;
102         free(ef->cmap.chunk);
103         ef->cmap.chunk = NULL;
104         close(ef->fd);
105         ef->fd = 0;
106         free(ef->sb);
107         ef->sb = NULL;
108         free(ef->upcase);
109         ef->upcase = NULL;
110         ef->upcase_chars = 0;
111 }