OSDN Git Service

Address clusters bitmap using size_t-sized blocks instead of bytes. This should be...
[android-x86/external-exfat.git] / libexfat / exfat.h
index 3ae96ad..4b0ebc9 100644 (file)
@@ -3,11 +3,12 @@
        Definitions of structures and constants used in exFAT file system
        implementation.
 
        Definitions of structures and constants used in exFAT file system
        implementation.
 
-       Copyright (C) 2009, 2010  Andrew Nayenko
+       Free exFAT implementation.
+       Copyright (C) 2010-2013  Andrew Nayenko
 
 
-       This program is free software: you can redistribute it and/or modify
+       This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        it under the terms of the GNU General Public License as published by
-       the Free Software Foundation, either version 3 of the License, or
+       the Free Software Foundation, either version 2 of the License, or
        (at your option) any later version.
 
        This program is distributed in the hope that it will be useful,
        (at your option) any later version.
 
        This program is distributed in the hope that it will be useful,
@@ -15,8 +16,9 @@
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
 
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
 
-       You should have received a copy of the GNU General Public License
-       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       You should have received a copy of the GNU General Public License along
+       with this program; if not, write to the Free Software Foundation, Inc.,
+       51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
 #ifndef EXFAT_H_INCLUDED
 */
 
 #ifndef EXFAT_H_INCLUDED
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include "compiler.h"
 #include "exfatfs.h"
 #include "exfatfs.h"
-
-#define EXFAT_VERSION_MAJOR 0
-#define EXFAT_VERSION_MINOR 5
-#define EXFAT_VERSION_PATCH 0
+#include "version.h"
 
 #define EXFAT_NAME_MAX 256
 #define EXFAT_ATTRIB_CONTIGUOUS 0x10000
 
 #define EXFAT_NAME_MAX 256
 #define EXFAT_ATTRIB_CONTIGUOUS 0x10000
 #define EXFAT_ATTRIB_DIRTY      0x40000
 #define EXFAT_ATTRIB_UNLINKED   0x80000
 #define IS_CONTIGUOUS(node) (((node).flags & EXFAT_ATTRIB_CONTIGUOUS) != 0)
 #define EXFAT_ATTRIB_DIRTY      0x40000
 #define EXFAT_ATTRIB_UNLINKED   0x80000
 #define IS_CONTIGUOUS(node) (((node).flags & EXFAT_ATTRIB_CONTIGUOUS) != 0)
-#define BLOCK_SIZE(sb) (1 << (sb).block_bits)
-#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb).bpc_bits)
-#define CLUSTER_INVALID(c) ((c) == EXFAT_CLUSTER_BAD || (c) == EXFAT_CLUSTER_END)
+#define SECTOR_SIZE(sb) (1 << (sb).sector_bits)
+#define CLUSTER_SIZE(sb) (SECTOR_SIZE(sb) << (sb).spc_bits)
+#define CLUSTER_INVALID(c) \
+       ((c) < EXFAT_FIRST_DATA_CLUSTER || (c) > EXFAT_LAST_DATA_CLUSTER)
 
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
 #define DIV_ROUND_UP(x, d) (((x) + (d) - 1) / (d))
 #define DIV_ROUND_UP(x, d) (((x) + (d) - 1) / (d))
+#define ROUND_UP(x, d) (DIV_ROUND_UP(x, d) * (d))
+#define UTF8_BYTES(c) ((c) * 6) /* UTF-8 character can occupy up to 6 bytes */
+
+typedef size_t bitmap_t;
+#define BMAP_SIZE(count) (ROUND_UP(count, sizeof(bitmap_t) * 8) / 8)
+#define BMAP_BLOCK(index) ((index) / sizeof(bitmap_t) / 8)
+#define BMAP_MASK(index) ((bitmap_t) 1 << ((index) % (sizeof(bitmap_t) * 8)))
+#define BMAP_GET(bitmap, index) \
+       ((bitmap)[BMAP_BLOCK(index)] & BMAP_MASK(index))
+#define BMAP_SET(bitmap, index) \
+       ((bitmap)[BMAP_BLOCK(index)] |= BMAP_MASK(index))
+#define BMAP_CLR(bitmap, index) \
+       ((bitmap)[BMAP_BLOCK(index)] &= ~BMAP_MASK(index))
 
 struct exfat_node
 {
 
 struct exfat_node
 {
@@ -65,10 +81,19 @@ struct exfat_node
        le16_t name[EXFAT_NAME_MAX + 1];
 };
 
        le16_t name[EXFAT_NAME_MAX + 1];
 };
 
+enum exfat_mode
+{
+       EXFAT_MODE_RO,
+       EXFAT_MODE_RW,
+       EXFAT_MODE_ANY,
+};
+
+struct exfat_dev;
+
 struct exfat
 {
 struct exfat
 {
+       struct exfat_dev* dev;
        struct exfat_super_block* sb;
        struct exfat_super_block* sb;
-       int fd;
        le16_t* upcase;
        size_t upcase_chars;
        struct exfat_node* root;
        le16_t* upcase;
        size_t upcase_chars;
        struct exfat_node* root;
@@ -76,17 +101,18 @@ struct exfat
        {
                cluster_t start_cluster;
                uint32_t size;                          /* in bits */
        {
                cluster_t start_cluster;
                uint32_t size;                          /* in bits */
-               uint8_t* chunk;
+               bitmap_t* chunk;
                uint32_t chunk_size;            /* in bits */
                uint32_t chunk_size;            /* in bits */
-               int dirty;
+               bool dirty;
        }
        cmap;
        }
        cmap;
-       void* zero_block;
+       char label[UTF8_BYTES(EXFAT_ENAME_MAX) + 1];
+       void* zero_cluster;
        int dmask, fmask;
        uid_t uid;
        gid_t gid;
        int ro;
        int dmask, fmask;
        uid_t uid;
        gid_t gid;
        int ro;
-       int noatime;
+       bool noatime;
 };
 
 /* in-core nodes iterator */
 };
 
 /* in-core nodes iterator */
@@ -96,22 +122,34 @@ struct exfat_iterator
        struct exfat_node* current;
 };
 
        struct exfat_node* current;
 };
 
+struct exfat_human_bytes
+{
+       uint64_t value;
+       const char* unit;
+};
+
 extern int exfat_errors;
 
 extern int exfat_errors;
 
-void exfat_bug(const char* format, ...)
-       __attribute__((format(printf, 1, 2), noreturn));
-void exfat_error(const char* format, ...)
-       __attribute__((format(printf, 1, 2)));
-void exfat_warn(const char* format, ...)
-       __attribute__((format(printf, 1, 2)));
-void exfat_debug(const char* format, ...)
-       __attribute__((format(printf, 1, 2)));
-
-void exfat_read_raw(void* buffer, size_t size, off_t offset, int fd);
-void exfat_write_raw(const void* buffer, size_t size, off_t offset, int fd);
-ssize_t exfat_read(const struct exfat* ef, struct exfat_node* node,
+void exfat_bug(const char* format, ...) PRINTF NORETURN;
+void exfat_error(const char* format, ...) PRINTF;
+void exfat_warn(const char* format, ...) PRINTF;
+void exfat_debug(const char* format, ...) PRINTF;
+
+struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode);
+int exfat_close(struct exfat_dev* dev);
+int exfat_fsync(struct exfat_dev* dev);
+enum exfat_mode exfat_get_mode(const struct exfat_dev* dev);
+off_t exfat_get_size(const struct exfat_dev* dev);
+off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence);
+ssize_t exfat_read(struct exfat_dev* dev, void* buffer, size_t size);
+ssize_t exfat_write(struct exfat_dev* dev, const void* buffer, size_t size);
+void exfat_pread(struct exfat_dev* dev, void* buffer, size_t size,
+               off_t offset);
+void exfat_pwrite(struct exfat_dev* dev, const void* buffer, size_t size,
+               off_t offset);
+ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node,
                void* buffer, size_t size, off_t offset);
                void* buffer, size_t size, off_t offset);
-ssize_t exfat_write(struct exfat* ef, struct exfat_node* node,
+ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node,
                const void* buffer, size_t size, off_t offset);
 
 int exfat_opendir(struct exfat* ef, struct exfat_node* dir,
                const void* buffer, size_t size, off_t offset);
 
 int exfat_opendir(struct exfat* ef, struct exfat_node* dir,
@@ -120,27 +158,33 @@ void exfat_closedir(struct exfat* ef, struct exfat_iterator* it);
 struct exfat_node* exfat_readdir(struct exfat* ef, struct exfat_iterator* it);
 int exfat_lookup(struct exfat* ef, struct exfat_node** node,
                const char* path);
 struct exfat_node* exfat_readdir(struct exfat* ef, struct exfat_iterator* it);
 int exfat_lookup(struct exfat* ef, struct exfat_node** node,
                const char* path);
-int exfat_split(struct exfat* ef, struct exfat_node** node, le16_t* name,
-               const char* path);
+int exfat_split(struct exfat* ef, struct exfat_node** parent,
+               struct exfat_node** node, le16_t* name, const char* path);
 
 off_t exfat_c2o(const struct exfat* ef, cluster_t cluster);
 cluster_t exfat_next_cluster(const struct exfat* ef,
                const struct exfat_node* node, cluster_t cluster);
 cluster_t exfat_advance_cluster(const struct exfat* ef,
                struct exfat_node* node, uint32_t count);
 
 off_t exfat_c2o(const struct exfat* ef, cluster_t cluster);
 cluster_t exfat_next_cluster(const struct exfat* ef,
                const struct exfat_node* node, cluster_t cluster);
 cluster_t exfat_advance_cluster(const struct exfat* ef,
                struct exfat_node* node, uint32_t count);
-void exfat_flush_cmap(struct exfat* ef);
-int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size);
+void exfat_flush(struct exfat* ef);
+int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size,
+               bool erase);
+uint32_t exfat_count_free_clusters(const struct exfat* ef);
+int exfat_find_used_sectors(const struct exfat* ef, off_t* a, off_t* b);
 
 void exfat_stat(const struct exfat* ef, const struct exfat_node* node,
                struct stat* stbuf);
 
 void exfat_stat(const struct exfat* ef, const struct exfat_node* node,
                struct stat* stbuf);
-time_t exfat_exfat2unix(le16_t date, le16_t time);
-void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time);
 void exfat_get_name(const struct exfat_node* node, char* buffer, size_t n);
 uint16_t exfat_start_checksum(const struct exfat_entry_meta1* entry);
 uint16_t exfat_add_checksum(const void* entry, uint16_t sum);
 le16_t exfat_calc_checksum(const struct exfat_entry_meta1* meta1,
                const struct exfat_entry_meta2* meta2, const le16_t* name);
 void exfat_get_name(const struct exfat_node* node, char* buffer, size_t n);
 uint16_t exfat_start_checksum(const struct exfat_entry_meta1* entry);
 uint16_t exfat_add_checksum(const void* entry, uint16_t sum);
 le16_t exfat_calc_checksum(const struct exfat_entry_meta1* meta1,
                const struct exfat_entry_meta2* meta2, const le16_t* name);
+uint32_t exfat_vbr_start_checksum(const void* sector, size_t size);
+uint32_t exfat_vbr_add_checksum(const void* sector, size_t size, uint32_t sum);
 le16_t exfat_calc_name_hash(const struct exfat* ef, const le16_t* name);
 le16_t exfat_calc_name_hash(const struct exfat* ef, const le16_t* name);
+void exfat_humanize_bytes(uint64_t value, struct exfat_human_bytes* hb);
+void exfat_print_info(const struct exfat_super_block* sb,
+               uint32_t free_clusters);
 
 int utf16_to_utf8(char* output, const le16_t* input, size_t outsize,
                size_t insize);
 
 int utf16_to_utf8(char* output, const le16_t* input, size_t outsize,
                size_t insize);
@@ -161,8 +205,15 @@ int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path);
 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2]);
 void exfat_update_atime(struct exfat_node* node);
 void exfat_update_mtime(struct exfat_node* node);
 void exfat_utimes(struct exfat_node* node, const struct timespec tv[2]);
 void exfat_update_atime(struct exfat_node* node);
 void exfat_update_mtime(struct exfat_node* node);
+const char* exfat_get_label(struct exfat* ef);
+int exfat_set_label(struct exfat* ef, const char* label);
 
 int exfat_mount(struct exfat* ef, const char* spec, const char* options);
 void exfat_unmount(struct exfat* ef);
 
 
 int exfat_mount(struct exfat* ef, const char* spec, const char* options);
 void exfat_unmount(struct exfat* ef);
 
+time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec);
+void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
+               uint8_t* centisec);
+void exfat_tzset(void);
+
 #endif /* ifndef EXFAT_H_INCLUDED */
 #endif /* ifndef EXFAT_H_INCLUDED */