feat: (iso9660) implement file read (for both interleaved and non-interleaved mode)
[lunaix-os.git] / lunaix-os / kernel / fs / iso9660 / inode.c
1 #include <klibc/string.h>
2 #include <lunaix/fs.h>
3 #include <lunaix/fs/iso9660.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/spike.h>
6
7 static struct v_inode_ops iso_inode_ops = {
8     .dir_lookup = iso9660_dir_lookup,
9     .open = iso9660_open,
10 };
11
12 static struct v_file_ops iso_file_ops = { .close = iso9660_close,
13                                           .read = iso9660_read,
14                                           .write = iso9660_write,
15                                           .seek = iso9660_seek,
16                                           .readdir = iso9660_readdir };
17
18 void
19 iso9660_init_inode(struct v_superblock* vsb, struct v_inode* inode)
20 {
21     inode->data = vzalloc(sizeof(struct iso_inode));
22 }
23
24 int
25 iso9660_fill_inode(struct v_inode* inode, struct iso_drecache* dir, int ino)
26 {
27     int errno = 0;
28     struct device* dev = inode->sb->dev;
29     struct iso_inode* isoino = (struct iso_inode*)inode->data;
30
31     // In the spec, there is a differentiation in how file section organized
32     // between interleaving and non-interleaving mode. To simplify this, we
33     // treat the non-interleaving as an interleaving with gap size = 0 and fu
34     // size = 1
35     isoino->fu_size = dir->fu_size;
36     isoino->gap_size = dir->gap_size;
37
38     u32_t fu_len = isoino->fu_size * ISO9660_BLKSZ;
39
40     inode->id = ino;
41     inode->lb_addr = dir->extent_addr;
42     inode->ops = &iso_inode_ops;
43     inode->default_fops = &iso_file_ops;
44
45     // xattr_len is in unit of FU. Each FU comprise <fu_sz> block(s).
46     inode->fsize = dir->data_size - dir->xattr_len * fu_len;
47
48     if ((dir->flags & ISO_FDIR)) {
49         inode->itype = VFS_IFDIR;
50     } else {
51         inode->itype = VFS_IFFILE;
52     }
53
54     if (dir->xattr_len) {
55         struct iso_xattr* xattr = (struct iso_xattr*)valloc(ISO9660_BLKSZ);
56         // Only bring in single FU, as we only care about the attributes.
57         errno =
58           dev->read(dev, xattr, ISO9660_BLKSZ * inode->lb_addr, ISO9660_BLKSZ);
59         if (errno < 0) {
60             return EIO;
61         }
62         isoino->record_fmt = xattr->record_fmt;
63         isoino->ctime = iso9660_dt2unix(&xattr->ctime);
64         isoino->mtime = iso9660_dt2unix(&xattr->mtime);
65
66         inode->lb_addr += dir->xattr_len * dir->fu_size;
67
68         vfree(xattr);
69     }
70
71     return 0;
72 }