OSDN Git Service

Pass node to exfat_next_cluster() and exfat_advance_cluster().
[android-x86/external-exfat.git] / libexfat / io.c
1 /*
2  *  io.c
3  *  exFAT file system implementation library.
4  *
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.
8  */
9
10 #include "exfat.h"
11 #include <sys/types.h>
12 #include <sys/uio.h>
13 #define __USE_UNIX98 /* for pread() in Linux */
14 #include <unistd.h>
15
16 #if _FILE_OFFSET_BITS != 64
17         #error You should define _FILE_OFFSET_BITS=64
18 #endif
19
20 #define MIN(a, b) ((a) < (b) ? (a) : (b))
21
22 void exfat_read_raw(void* buffer, size_t size, off_t offset, int fd)
23 {
24         if (pread(fd, buffer, size, offset) != size)
25                 exfat_bug("failed to read %zu bytes from file at %llu", size, offset);
26 }
27
28 ssize_t exfat_read(const struct exfat* ef, const struct exfat_node* node,
29                 void* buffer, size_t size, off_t offset)
30 {
31         cluster_t cluster;
32         char* bufp = buffer;
33         off_t lsize, loffset, remainder;
34
35         if (offset >= node->size)
36                 return 0;
37         if (size == 0)
38                 return 0;
39
40         cluster = exfat_advance_cluster(ef, node, node->start_cluster,
41                         offset / CLUSTER_SIZE(*ef->sb));
42         if (CLUSTER_INVALID(cluster))
43         {
44                 exfat_error("got invalid cluster");
45                 return -1;
46         }
47
48         loffset = offset % CLUSTER_SIZE(*ef->sb);
49         remainder = MIN(size, node->size - offset);
50         while (remainder > 0)
51         {
52                 lsize = MIN(CLUSTER_SIZE(*ef->sb) - loffset, remainder);
53                 exfat_read_raw(bufp, lsize, exfat_c2o(ef, cluster) + loffset, ef->fd);
54                 bufp += lsize;
55                 loffset = 0;
56                 remainder -= lsize;
57                 cluster = exfat_next_cluster(ef, node, cluster);
58                 if (CLUSTER_INVALID(cluster))
59                 {
60                         exfat_error("got invalid cluster");
61                         return -1;
62                 }
63         }
64         return size - remainder;
65 }