feat: (iso9660) directory read support
[lunaix-os.git] / lunaix-os / kernel / fs / iso9660 / mount.c
1 #include <lunaix/block.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 #include <lunaix/mm/cake.h>
8
9 struct cake_pile* drec_cache_pile;
10
11 extern void
12 iso9660_init_inode(struct v_superblock* vsb, struct v_inode* inode);
13
14 uint32_t
15 iso9660_rd_capacity(struct v_superblock* vsb)
16 {
17     struct iso_superblock* isovsb = (struct iso_superblock*)vsb->data;
18     return isovsb->volume_size;
19 }
20
21 int
22 iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
23 {
24     struct device* dev = vsb->dev;
25     struct iso_vol* vdesc = (struct iso_vol*)valloc(ISO9660_BLKSZ);
26     struct iso_vol_primary* vprim = NULL;
27     int errno = 0;
28     do {
29         errno = dev->read(dev, vdesc, ISO9660_BLKSZ * 16, ISO9660_BLKSZ);
30         if (errno < 0) {
31             errno = EIO;
32             goto done;
33         }
34         if (*(u32_t*)vdesc->std_id != ISO_SIGNATURE_LO) {
35             errno = ENODEV;
36             goto done;
37         }
38         if (vdesc->type == ISO_VOLPRIM) {
39             vprim = (struct iso_vol_primary*)vdesc;
40             break;
41         }
42
43     } while (vdesc->type != ISO_VOLTERM);
44
45     if (!vprim) {
46         errno = EINVAL;
47         goto done;
48     }
49
50     struct iso_superblock* isovsb = valloc(sizeof(*isovsb));
51     isovsb->lb_size = vprim->lb_size.le;
52     isovsb->volume_size = vprim->vol_size.le * isovsb->lb_size;
53
54     vsb->data = isovsb;
55     vsb->ops.init_inode = iso9660_init_inode;
56     vsb->ops.read_capacity = iso9660_rd_capacity;
57
58     struct v_inode* rootino = vfs_i_alloc(vsb);
59     struct iso_drecord* dir =
60       iso9660_get_drecord((struct iso_var_mdu*)vprim->root_record);
61
62     if (!dir) {
63         vfree(isovsb);
64         errno = EINVAL;
65         goto done;
66     }
67
68     struct iso_drecache drecache;
69     iso9660_fill_drecache(&drecache, dir);
70
71     if ((errno = iso9660_fill_inode(rootino, &drecache, 0)) < 0) {
72         vfree(isovsb);
73         errno = EINVAL;
74         goto done;
75     }
76
77     if ((errno = iso9660_setup_dnode(mount_point, rootino)) < 0) {
78         vfree(isovsb);
79         errno = EINVAL;
80         goto done;
81     }
82
83     vfs_i_addhash(rootino);
84
85 done:
86     vfree(vdesc);
87     return 0;
88 }
89
90 int
91 iso9660_unmount(struct v_superblock* vsb)
92 {
93     // TODO clean up
94 }
95
96 void
97 iso9660_init()
98 {
99     drec_cache_pile =
100       cake_new_pile("iso_drec", sizeof(struct iso_drecache), 1, 0);
101
102     struct filesystem* fs = fsm_new_fs("iso9660", -1);
103     fs->types |= FSTYPE_ROFS;
104     fs->mount = iso9660_mount;
105     fs->unmount = iso9660_unmount;
106
107     fsm_register(fs);
108 }