Merge branch 'master' into prog-loader
[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
8 int
9 iso9660_open(struct v_inode* this, struct v_file* file)
10 {
11     // TODO
12     return 0;
13 }
14
15 int
16 iso9660_close(struct v_file* file)
17 {
18     // TODO
19     return 0;
20 }
21
22 int
23 iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
24 {
25     // This read implementation handle both interleaved and non-interleaved
26     // structuring
27
28     struct iso_inode* isoino = inode->data;
29     struct device* bdev = inode->sb->dev;
30
31     len = MIN(fpos + len, inode->fsize);
32     if (len <= fpos) {
33         return 0;
34     }
35
36     len -= fpos;
37
38     size_t fu_len = isoino->fu_size * ISO9660_BLKSZ;
39     // if fpos is not FU aligned, then we must do an extra read.
40     size_t fu_to_read =
41       ICEIL(len, fu_len) + (fpos > fu_len && (fpos % fu_len) != 0);
42     size_t sec = (fpos % fu_len) / ISO9660_BLKSZ;
43     size_t wd_start = fpos % ISO9660_BLKSZ,
44            wd_len = MIN(len, ISO9660_BLKSZ - wd_start), i = 0;
45
46     // how many blocks (file unit + gaps) before of our current read position
47     size_t true_offset = (fpos / fu_len);
48     true_offset = true_offset * (isoino->fu_size + isoino->gap_size);
49
50     void* rd_buffer = valloc(ISO9660_BLKSZ);
51
52     true_offset += sec + inode->lb_addr;
53
54     int errno = 0;
55     while (fu_to_read) {
56         for (; sec < isoino->fu_size && i < len; sec++) {
57             errno = bdev->read(
58               bdev, rd_buffer, true_offset * ISO9660_BLKSZ, ISO9660_BLKSZ);
59
60             if (errno < 0) {
61                 errno = EIO;
62                 goto done;
63             }
64
65             memcpy(buffer + i, rd_buffer + wd_start, wd_len);
66
67             i += wd_len;
68             true_offset++;
69             wd_start = 0;
70             wd_len = MIN(len - i, ISO9660_BLKSZ);
71         }
72         sec = 0;
73         fu_to_read--;
74     }
75     errno = i;
76
77 done:
78     vfree(rd_buffer);
79     return errno;
80 }
81
82 int
83 iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
84 {
85     // TODO
86     return ENOTSUP;
87 }
88
89 int
90 iso9660_seek(struct v_inode* inode, size_t offset)
91 {
92     // TODO
93     return 0;
94 }