X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/c6de44b989e9d7286337e4cbf4d82d919f9120e6..0eabc11fcf240415e39f3873dfce7cd9384b3042:/lunaix-os/kernel/fs/iso9660/file.c diff --git a/lunaix-os/kernel/fs/iso9660/file.c b/lunaix-os/kernel/fs/iso9660/file.c index 6813c22..34d3b47 100644 --- a/lunaix-os/kernel/fs/iso9660/file.c +++ b/lunaix-os/kernel/fs/iso9660/file.c @@ -1,5 +1,9 @@ #include #include +#include +#include + +#include int iso9660_open(struct v_inode* this, struct v_file* file) @@ -18,15 +22,68 @@ iso9660_close(struct v_file* file) int iso9660_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos) { - // TODO - return 0; + // This read implementation handle both interleaved and non-interleaved + // structuring + + struct iso_inode* isoino = inode->data; + struct device* bdev = inode->sb->dev; + + len = MIN(fpos + len, inode->fsize); + if (len <= fpos) { + return 0; + } + + len -= fpos; + + size_t fu_len = isoino->fu_size * ISO9660_BLKSZ; + // if fpos is not FU aligned, then we must do an extra read. + size_t fu_to_read = + ICEIL(len, fu_len) + (fpos > fu_len && (fpos % fu_len) != 0); + size_t sec = (fpos % fu_len) / ISO9660_BLKSZ; + size_t wd_start = fpos % ISO9660_BLKSZ, + wd_len = MIN(len, ISO9660_BLKSZ - wd_start), i = 0; + + // how many blocks (file unit + gaps) before of our current read position + size_t true_offset = (fpos / fu_len); + true_offset = true_offset * (isoino->fu_size + isoino->gap_size); + + void* rd_buffer = valloc(ISO9660_BLKSZ); + + true_offset += sec + inode->lb_addr; + + int errno = 0; + while (fu_to_read) { + for (; sec < isoino->fu_size && i < len; sec++) { + errno = bdev->read( + bdev, rd_buffer, true_offset * ISO9660_BLKSZ, ISO9660_BLKSZ); + + if (errno < 0) { + errno = EIO; + goto done; + } + + memcpy(buffer + i, rd_buffer + wd_start, wd_len); + + i += wd_len; + true_offset++; + wd_start = 0; + wd_len = MIN(len - i, ISO9660_BLKSZ); + } + sec = 0; + fu_to_read--; + } + errno = i; + +done: + vfree(rd_buffer); + return errno; } int iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos) { // TODO - return EROFS; + return ENOTSUP; } int