3 * exFAT file system implementation library.
5 * Created by Andrew Nayenko on 02.09.09.
6 * This software is distributed under the GNU General Public License
7 * version 3 or any later.
11 #include <sys/types.h>
13 #define __USE_UNIX98 /* for pread() in Linux */
16 #if _FILE_OFFSET_BITS != 64
17 #error You should define _FILE_OFFSET_BITS=64
20 void exfat_read_raw(void* buffer, size_t size, off_t offset, int fd)
22 if (pread(fd, buffer, size, offset) != size)
23 exfat_bug("failed to read %zu bytes from file at %llu", size, offset);
26 void exfat_write_raw(const void* buffer, size_t size, off_t offset, int fd)
28 if (pwrite(fd, buffer, size, offset) != size)
29 exfat_bug("failed to write %zu bytes to file at %llu", size, offset);
32 ssize_t exfat_read(const struct exfat* ef, const struct exfat_node* node,
33 void* buffer, size_t size, off_t offset)
37 off_t lsize, loffset, remainder;
39 if (offset >= node->size)
44 cluster = exfat_advance_cluster(ef, node, node->start_cluster,
45 offset / CLUSTER_SIZE(*ef->sb));
46 if (CLUSTER_INVALID(cluster))
48 exfat_error("got invalid cluster");
52 loffset = offset % CLUSTER_SIZE(*ef->sb);
53 remainder = MIN(size, node->size - offset);
56 if (CLUSTER_INVALID(cluster))
58 exfat_error("got invalid cluster");
61 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
62 exfat_read_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
66 cluster = exfat_next_cluster(ef, node, cluster);
68 return size - remainder;
71 ssize_t exfat_write(struct exfat* ef, struct exfat_node* node,
72 const void* buffer, size_t size, off_t offset)
75 const char* bufp = buffer;
76 off_t lsize, loffset, remainder;
78 if (offset + size > node->size)
79 exfat_truncate(ef, node, offset + size);
83 cluster = exfat_advance_cluster(ef, node, node->start_cluster,
84 offset / CLUSTER_SIZE(*ef->sb));
85 if (CLUSTER_INVALID(cluster))
87 exfat_error("got invalid cluster");
91 loffset = offset % CLUSTER_SIZE(*ef->sb);
95 if (CLUSTER_INVALID(cluster))
97 exfat_error("got invalid cluster");
100 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
101 exfat_write_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
105 cluster = exfat_next_cluster(ef, node, cluster);
107 /* FIXME update modification time */
108 /* FIXME no need to flush immediately */
109 exfat_flush_node(ef, node);
110 return size - remainder;