feat: (iso9660) directory read support
[lunaix-os.git] / lunaix-os / kernel / fs / iso9660 / mount.c
diff --git a/lunaix-os/kernel/fs/iso9660/mount.c b/lunaix-os/kernel/fs/iso9660/mount.c
new file mode 100644 (file)
index 0000000..f6bb2fc
--- /dev/null
@@ -0,0 +1,108 @@
+#include <lunaix/block.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/iso9660.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#include <lunaix/mm/cake.h>
+
+struct cake_pile* drec_cache_pile;
+
+extern void
+iso9660_init_inode(struct v_superblock* vsb, struct v_inode* inode);
+
+uint32_t
+iso9660_rd_capacity(struct v_superblock* vsb)
+{
+    struct iso_superblock* isovsb = (struct iso_superblock*)vsb->data;
+    return isovsb->volume_size;
+}
+
+int
+iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
+{
+    struct device* dev = vsb->dev;
+    struct iso_vol* vdesc = (struct iso_vol*)valloc(ISO9660_BLKSZ);
+    struct iso_vol_primary* vprim = NULL;
+    int errno = 0;
+    do {
+        errno = dev->read(dev, vdesc, ISO9660_BLKSZ * 16, ISO9660_BLKSZ);
+        if (errno < 0) {
+            errno = EIO;
+            goto done;
+        }
+        if (*(u32_t*)vdesc->std_id != ISO_SIGNATURE_LO) {
+            errno = ENODEV;
+            goto done;
+        }
+        if (vdesc->type == ISO_VOLPRIM) {
+            vprim = (struct iso_vol_primary*)vdesc;
+            break;
+        }
+
+    } while (vdesc->type != ISO_VOLTERM);
+
+    if (!vprim) {
+        errno = EINVAL;
+        goto done;
+    }
+
+    struct iso_superblock* isovsb = valloc(sizeof(*isovsb));
+    isovsb->lb_size = vprim->lb_size.le;
+    isovsb->volume_size = vprim->vol_size.le * isovsb->lb_size;
+
+    vsb->data = isovsb;
+    vsb->ops.init_inode = iso9660_init_inode;
+    vsb->ops.read_capacity = iso9660_rd_capacity;
+
+    struct v_inode* rootino = vfs_i_alloc(vsb);
+    struct iso_drecord* dir =
+      iso9660_get_drecord((struct iso_var_mdu*)vprim->root_record);
+
+    if (!dir) {
+        vfree(isovsb);
+        errno = EINVAL;
+        goto done;
+    }
+
+    struct iso_drecache drecache;
+    iso9660_fill_drecache(&drecache, dir);
+
+    if ((errno = iso9660_fill_inode(rootino, &drecache, 0)) < 0) {
+        vfree(isovsb);
+        errno = EINVAL;
+        goto done;
+    }
+
+    if ((errno = iso9660_setup_dnode(mount_point, rootino)) < 0) {
+        vfree(isovsb);
+        errno = EINVAL;
+        goto done;
+    }
+
+    vfs_i_addhash(rootino);
+
+done:
+    vfree(vdesc);
+    return 0;
+}
+
+int
+iso9660_unmount(struct v_superblock* vsb)
+{
+    // TODO clean up
+}
+
+void
+iso9660_init()
+{
+    drec_cache_pile =
+      cake_new_pile("iso_drec", sizeof(struct iso_drecache), 1, 0);
+
+    struct filesystem* fs = fsm_new_fs("iso9660", -1);
+    fs->types |= FSTYPE_ROFS;
+    fs->mount = iso9660_mount;
+    fs->unmount = iso9660_unmount;
+
+    fsm_register(fs);
+}
\ No newline at end of file