a48da33845d737d2bea57eb3a73fea41ac9b66cb
[lunaix-os.git] / lunaix-os / kernel / fs / iso9660 / file.c
1 #include <lunaix/fs.h>
2 #include <lunaix/fs/iso9660.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/spike.h>
5
6 #include <klibc/string.h>
7 #include <sys/mm/mempart.h>
8
9 int
10 iso9660_open(struct v_inode* this, struct v_file* file)
11 {
12     // TODO
13     return 0;
14 }
15
16 int
17 iso9660_close(struct v_file* file)
18 {
19     // TODO
20     return 0;
21 }
22
23 int
24 iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
25 {
26     // This read implementation handle both interleaved and non-interleaved
27     // structuring
28
29     struct iso_inode* isoino = inode->data;
30     struct device* bdev = inode->sb->dev;
31
32     len = MIN(fpos + len, inode->fsize);
33     if (len <= fpos) {
34         return 0;
35     }
36
37     len -= fpos;
38
39     size_t fu_len = isoino->fu_size * ISO9660_BLKSZ;
40     // if fpos is not FU aligned, then we must do an extra read.
41     size_t fu_to_read =
42       ICEIL(len, fu_len) + (fpos > fu_len && (fpos % fu_len) != 0);
43     size_t sec = (fpos % fu_len) / ISO9660_BLKSZ;
44     size_t wd_start = fpos % ISO9660_BLKSZ,
45            wd_len = MIN(len, ISO9660_BLKSZ - wd_start), i = 0;
46
47     // how many blocks (file unit + gaps) before of our current read position
48     size_t true_offset = (fpos / fu_len);
49     true_offset = true_offset * (isoino->fu_size + isoino->gap_size);
50
51     void* rd_buffer = valloc(ISO9660_BLKSZ);
52
53     true_offset += sec + inode->lb_addr;
54
55     int errno = 0;
56     while (fu_to_read) {
57         for (; sec < isoino->fu_size && i < len; sec++) {
58             errno = bdev->ops.read(
59               bdev, rd_buffer, true_offset * ISO9660_BLKSZ, ISO9660_BLKSZ);
60
61             if (errno < 0) {
62                 errno = EIO;
63                 goto done;
64             }
65
66             memcpy(buffer + i, rd_buffer + wd_start, wd_len);
67
68             i += wd_len;
69             true_offset++;
70             wd_start = 0;
71             wd_len = MIN(len - i, ISO9660_BLKSZ);
72         }
73         sec = 0;
74         fu_to_read--;
75     }
76     errno = i;
77
78 done:
79     vfree(rd_buffer);
80     return errno;
81 }
82
83 int
84 iso9660_read_page(struct v_inode* inode, void* buffer, size_t fpos)
85 {
86     return iso9660_read(inode, buffer, MEM_PAGE, fpos);
87 }
88
89 int
90 iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
91 {
92     // TODO
93     return ENOTSUP;
94 }
95
96 int
97 iso9660_write_page(struct v_inode* inode, void* buffer, size_t fpos)
98 {
99     // TODO
100     return ENOTSUP;
101 }
102
103 int
104 iso9660_seek(struct v_inode* inode, size_t offset)
105 {
106     // TODO
107     return 0;
108 }