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.
12 #include <sys/types.h>
14 #define __USE_UNIX98 /* for pread() in Linux */
17 #if _FILE_OFFSET_BITS != 64
18 #error You should define _FILE_OFFSET_BITS=64
21 void exfat_read_raw(void* buffer, size_t size, off_t offset, int fd)
23 if (pread(fd, buffer, size, offset) != size)
24 exfat_bug("failed to read %zu bytes from file at %"PRIu64, size,
28 void exfat_write_raw(const void* buffer, size_t size, off_t offset, int fd)
30 if (pwrite(fd, buffer, size, offset) != size)
31 exfat_bug("failed to write %zu bytes to file at %"PRIu64, size,
35 ssize_t exfat_read(const struct exfat* ef, struct exfat_node* node,
36 void* buffer, size_t size, off_t offset)
40 off_t lsize, loffset, remainder;
42 if (offset >= node->size)
47 cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
48 if (CLUSTER_INVALID(cluster))
50 exfat_error("got invalid cluster");
54 loffset = offset % CLUSTER_SIZE(*ef->sb);
55 remainder = MIN(size, node->size - offset);
58 if (CLUSTER_INVALID(cluster))
60 exfat_error("got invalid cluster");
63 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
64 exfat_read_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
68 cluster = exfat_next_cluster(ef, node, cluster);
71 exfat_update_atime(node);
72 return size - remainder;
75 ssize_t exfat_write(struct exfat* ef, struct exfat_node* node,
76 const void* buffer, size_t size, off_t offset)
79 const char* bufp = buffer;
80 off_t lsize, loffset, remainder;
82 if (offset + size > node->size)
84 int rc = exfat_truncate(ef, node, offset + size);
91 cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb));
92 if (CLUSTER_INVALID(cluster))
94 exfat_error("got invalid cluster");
98 loffset = offset % CLUSTER_SIZE(*ef->sb);
100 while (remainder > 0)
102 if (CLUSTER_INVALID(cluster))
104 exfat_error("got invalid cluster");
107 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
108 exfat_write_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
112 cluster = exfat_next_cluster(ef, node, cluster);
114 node->mtime = time(NULL);
115 node->flags |= EXFAT_ATTRIB_DIRTY;
116 return size - remainder;