blob: 009a0c08188e9a42dc6e0611c8557a60b313ee00 [file] [log] [blame]
bigbiff bigbiff9c754052013-01-09 09:09:08 -05001/*
2 exfat.h (29.08.09)
3 Definitions of structures and constants used in exFAT file system
4 implementation.
5
bigbiff bigbiff61cdc022013-08-08 08:35:06 -04006 Free exFAT implementation.
Matt Mower09ef1e42015-12-13 11:29:45 -06007 Copyright (C) 2010-2015 Andrew Nayenko
bigbiff bigbiff9c754052013-01-09 09:09:08 -05008
bigbiff bigbiff61cdc022013-08-08 08:35:06 -04009 This program is free software; you can redistribute it and/or modify
bigbiff bigbiff9c754052013-01-09 09:09:08 -050010 it under the terms of the GNU General Public License as published by
bigbiff bigbiff61cdc022013-08-08 08:35:06 -040011 the Free Software Foundation, either version 2 of the License, or
bigbiff bigbiff9c754052013-01-09 09:09:08 -050012 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
bigbiff bigbiff61cdc022013-08-08 08:35:06 -040019 You should have received a copy of the GNU General Public License along
20 with this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
bigbiff bigbiff9c754052013-01-09 09:09:08 -050022*/
23
24#ifndef EXFAT_H_INCLUDED
25#define EXFAT_H_INCLUDED
26
Matt Mower09ef1e42015-12-13 11:29:45 -060027#if defined(__ANDROID__)
28#include "android_config.h"
29#else
30#include "config.h"
31#endif
32#include "compiler.h"
33#include "exfatfs.h"
bigbiff bigbiff9c754052013-01-09 09:09:08 -050034#include <stdio.h>
35#include <stdlib.h>
36#include <time.h>
37#include <stdbool.h>
38#include <sys/stat.h>
39#include <sys/types.h>
bigbiff bigbiff9c754052013-01-09 09:09:08 -050040
41#define EXFAT_NAME_MAX 256
42#define EXFAT_ATTRIB_CONTIGUOUS 0x10000
43#define EXFAT_ATTRIB_CACHED 0x20000
44#define EXFAT_ATTRIB_DIRTY 0x40000
45#define EXFAT_ATTRIB_UNLINKED 0x80000
46#define IS_CONTIGUOUS(node) (((node).flags & EXFAT_ATTRIB_CONTIGUOUS) != 0)
47#define SECTOR_SIZE(sb) (1 << (sb).sector_bits)
48#define CLUSTER_SIZE(sb) (SECTOR_SIZE(sb) << (sb).spc_bits)
49#define CLUSTER_INVALID(c) \
50 ((c) < EXFAT_FIRST_DATA_CLUSTER || (c) > EXFAT_LAST_DATA_CLUSTER)
51
52#define MIN(a, b) ((a) < (b) ? (a) : (b))
53#define MAX(a, b) ((a) > (b) ? (a) : (b))
54#define DIV_ROUND_UP(x, d) (((x) + (d) - 1) / (d))
55#define ROUND_UP(x, d) (DIV_ROUND_UP(x, d) * (d))
bigbiff bigbiff004e2df2013-07-03 14:52:12 -040056#define UTF8_BYTES(c) ((c) * 6) /* UTF-8 character can occupy up to 6 bytes */
bigbiff bigbiff9c754052013-01-09 09:09:08 -050057
bigbiff bigbiff61cdc022013-08-08 08:35:06 -040058#define BMAP_SIZE(count) (ROUND_UP(count, sizeof(bitmap_t) * 8) / 8)
59#define BMAP_BLOCK(index) ((index) / sizeof(bitmap_t) / 8)
60#define BMAP_MASK(index) ((bitmap_t) 1 << ((index) % (sizeof(bitmap_t) * 8)))
bigbiff bigbiff9c754052013-01-09 09:09:08 -050061#define BMAP_GET(bitmap, index) \
bigbiff bigbiff61cdc022013-08-08 08:35:06 -040062 ((bitmap)[BMAP_BLOCK(index)] & BMAP_MASK(index))
bigbiff bigbiff9c754052013-01-09 09:09:08 -050063#define BMAP_SET(bitmap, index) \
bigbiff bigbiff61cdc022013-08-08 08:35:06 -040064 ((bitmap)[BMAP_BLOCK(index)] |= BMAP_MASK(index))
bigbiff bigbiff9c754052013-01-09 09:09:08 -050065#define BMAP_CLR(bitmap, index) \
bigbiff bigbiff61cdc022013-08-08 08:35:06 -040066 ((bitmap)[BMAP_BLOCK(index)] &= ~BMAP_MASK(index))
bigbiff bigbiff9c754052013-01-09 09:09:08 -050067
Matt Mower09ef1e42015-12-13 11:29:45 -060068/* The size of off_t type must be 64 bits. File systems larger than 2 GB will
Spegeliusd69ac2b2014-11-23 15:15:06 +020069 be corrupted with 32-bit off_t. So, we use loff_t here.*/
70STATIC_ASSERT(sizeof(loff_t) == 8);
Matt Mower09ef1e42015-12-13 11:29:45 -060071
bigbiff bigbiff9c754052013-01-09 09:09:08 -050072struct exfat_node
73{
74 struct exfat_node* parent;
75 struct exfat_node* child;
76 struct exfat_node* next;
77 struct exfat_node* prev;
78
79 int references;
80 uint32_t fptr_index;
81 cluster_t fptr_cluster;
82 cluster_t entry_cluster;
Spegeliusd69ac2b2014-11-23 15:15:06 +020083 loff_t entry_offset;
bigbiff bigbiff9c754052013-01-09 09:09:08 -050084 cluster_t start_cluster;
85 int flags;
86 uint64_t size;
87 time_t mtime, atime;
88 le16_t name[EXFAT_NAME_MAX + 1];
89};
90
91enum exfat_mode
92{
93 EXFAT_MODE_RO,
94 EXFAT_MODE_RW,
95 EXFAT_MODE_ANY,
96};
97
98struct exfat_dev;
99
100struct exfat
101{
102 struct exfat_dev* dev;
103 struct exfat_super_block* sb;
104 le16_t* upcase;
105 size_t upcase_chars;
106 struct exfat_node* root;
107 struct
108 {
109 cluster_t start_cluster;
110 uint32_t size; /* in bits */
bigbiff bigbiff61cdc022013-08-08 08:35:06 -0400111 bitmap_t* chunk;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500112 uint32_t chunk_size; /* in bits */
113 bool dirty;
114 }
115 cmap;
bigbiff bigbiff004e2df2013-07-03 14:52:12 -0400116 char label[UTF8_BYTES(EXFAT_ENAME_MAX) + 1];
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500117 void* zero_cluster;
118 int dmask, fmask;
119 uid_t uid;
120 gid_t gid;
121 int ro;
122 bool noatime;
123};
124
125/* in-core nodes iterator */
126struct exfat_iterator
127{
128 struct exfat_node* parent;
129 struct exfat_node* current;
130};
131
132struct exfat_human_bytes
133{
134 uint64_t value;
135 const char* unit;
136};
137
138extern int exfat_errors;
139
bigbiff bigbiff61cdc022013-08-08 08:35:06 -0400140void exfat_bug(const char* format, ...) PRINTF NORETURN;
141void exfat_error(const char* format, ...) PRINTF;
142void exfat_warn(const char* format, ...) PRINTF;
143void exfat_debug(const char* format, ...) PRINTF;
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500144
145struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode);
146int exfat_close(struct exfat_dev* dev);
147int exfat_fsync(struct exfat_dev* dev);
148enum exfat_mode exfat_get_mode(const struct exfat_dev* dev);
Spegeliusd69ac2b2014-11-23 15:15:06 +0200149loff_t exfat_get_size(const struct exfat_dev* dev);
150loff_t exfat_seek(struct exfat_dev* dev, loff_t offset, int whence);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500151ssize_t exfat_read(struct exfat_dev* dev, void* buffer, size_t size);
152ssize_t exfat_write(struct exfat_dev* dev, const void* buffer, size_t size);
bigbiff bigbiff61cdc022013-08-08 08:35:06 -0400153ssize_t exfat_pread(struct exfat_dev* dev, void* buffer, size_t size,
Spegeliusd69ac2b2014-11-23 15:15:06 +0200154 loff_t offset);
bigbiff bigbiff61cdc022013-08-08 08:35:06 -0400155ssize_t exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size,
Spegeliusd69ac2b2014-11-23 15:15:06 +0200156 loff_t offset);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500157ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node,
Spegeliusd69ac2b2014-11-23 15:15:06 +0200158 void* buffer, size_t size, loff_t offset);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500159ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
Spegeliusd69ac2b2014-11-23 15:15:06 +0200160 const void* buffer, size_t size, loff_t offset);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500161
162int exfat_opendir(struct exfat* ef, struct exfat_node* dir,
163 struct exfat_iterator* it);
164void exfat_closedir(struct exfat* ef, struct exfat_iterator* it);
165struct exfat_node* exfat_readdir(struct exfat* ef, struct exfat_iterator* it);
166int exfat_lookup(struct exfat* ef, struct exfat_node** node,
167 const char* path);
168int exfat_split(struct exfat* ef, struct exfat_node** parent,
169 struct exfat_node** node, le16_t* name, const char* path);
170
Spegeliusd69ac2b2014-11-23 15:15:06 +0200171loff_t exfat_c2o(const struct exfat* ef, cluster_t cluster);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500172cluster_t exfat_next_cluster(const struct exfat* ef,
173 const struct exfat_node* node, cluster_t cluster);
174cluster_t exfat_advance_cluster(const struct exfat* ef,
175 struct exfat_node* node, uint32_t count);
Matt Mower09ef1e42015-12-13 11:29:45 -0600176int exfat_flush_nodes(struct exfat* ef);
bigbiff bigbiff61cdc022013-08-08 08:35:06 -0400177int exfat_flush(struct exfat* ef);
bigbiff bigbiff998716f2013-03-07 09:59:37 -0500178int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size,
179 bool erase);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500180uint32_t exfat_count_free_clusters(const struct exfat* ef);
Spegeliusd69ac2b2014-11-23 15:15:06 +0200181int exfat_find_used_sectors(const struct exfat* ef, loff_t* a, loff_t* b);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500182
183void exfat_stat(const struct exfat* ef, const struct exfat_node* node,
184 struct stat* stbuf);
185void exfat_get_name(const struct exfat_node* node, char* buffer, size_t n);
186uint16_t exfat_start_checksum(const struct exfat_entry_meta1* entry);
187uint16_t exfat_add_checksum(const void* entry, uint16_t sum);
188le16_t exfat_calc_checksum(const struct exfat_entry_meta1* meta1,
189 const struct exfat_entry_meta2* meta2, const le16_t* name);
190uint32_t exfat_vbr_start_checksum(const void* sector, size_t size);
191uint32_t exfat_vbr_add_checksum(const void* sector, size_t size, uint32_t sum);
192le16_t exfat_calc_name_hash(const struct exfat* ef, const le16_t* name);
193void exfat_humanize_bytes(uint64_t value, struct exfat_human_bytes* hb);
194void exfat_print_info(const struct exfat_super_block* sb,
195 uint32_t free_clusters);
196
197int utf16_to_utf8(char* output, const le16_t* input, size_t outsize,
198 size_t insize);
199int utf8_to_utf16(le16_t* output, const char* input, size_t outsize,
200 size_t insize);
201size_t utf16_length(const le16_t* str);
202
203struct exfat_node* exfat_get_node(struct exfat_node* node);
204void exfat_put_node(struct exfat* ef, struct exfat_node* node);
Matt Mower09ef1e42015-12-13 11:29:45 -0600205int exfat_cleanup_node(struct exfat* ef, struct exfat_node* node);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500206int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir);
207void exfat_reset_cache(struct exfat* ef);
bigbiff bigbiff61cdc022013-08-08 08:35:06 -0400208int exfat_flush_node(struct exfat* ef, struct exfat_node* node);
bigbiff bigbiff9c754052013-01-09 09:09:08 -0500209int exfat_unlink(struct exfat* ef, struct exfat_node* node);
210int exfat_rmdir(struct exfat* ef, struct exfat_node* node);
211int exfat_mknod(struct exfat* ef, const char* path);
212int exfat_mkdir(struct exfat* ef, const char* path);
213int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path);
214void exfat_utimes(struct exfat_node* node, const struct timespec tv[2]);
215void exfat_update_atime(struct exfat_node* node);
216void exfat_update_mtime(struct exfat_node* node);
217const char* exfat_get_label(struct exfat* ef);
218int exfat_set_label(struct exfat* ef, const char* label);
219
220int exfat_mount(struct exfat* ef, const char* spec, const char* options);
221void exfat_unmount(struct exfat* ef);
222
223time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec);
224void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
225 uint8_t* centisec);
226void exfat_tzset(void);
227
228#endif /* ifndef EXFAT_H_INCLUDED */