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, 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, offset / CLUSTER_SIZE(*ef->sb));
45 if (CLUSTER_INVALID(cluster))
47 exfat_error("got invalid cluster");
51 loffset = offset % CLUSTER_SIZE(*ef->sb);
52 remainder = MIN(size, node->size - offset);
55 if (CLUSTER_INVALID(cluster))
57 exfat_error("got invalid cluster");
60 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
61 exfat_read_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
65 cluster = exfat_next_cluster(ef, node, cluster);
67 return size - remainder;
70 ssize_t exfat_write(struct exfat* ef, struct exfat_node* node,
71 const void* buffer, size_t size, off_t offset)
74 const char* bufp = buffer;
75 off_t lsize, loffset, remainder;
77 if (offset + size > node->size)
78 exfat_truncate(ef, node, offset + size);
82 cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
83 if (CLUSTER_INVALID(cluster))
85 exfat_error("got invalid cluster");
89 loffset = offset % CLUSTER_SIZE(*ef->sb);
93 if (CLUSTER_INVALID(cluster))
95 exfat_error("got invalid cluster");
98 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
99 exfat_write_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
103 cluster = exfat_next_cluster(ef, node, cluster);
105 node->mtime = time(NULL);
106 node->flags |= EXFAT_ATTRIB_DIRTY;
107 return size - remainder;