Code-base clean-up and refactoring (#47)
[lunaix-os.git] / lunaix-os / kernel / fs / iso9660 / mount.c
1 #include <lunaix/block.h>
2 #include <lunaix/fs/api.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/mm/cake.h>
5 #include <lunaix/spike.h>
6
7 #include "iso9660.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 static size_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 static void
22 __vsb_release(struct v_superblock* vsb)
23 {
24     vfree(vsb->data);
25 }
26
27 int
28 iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
29 {
30     struct device* dev = vsb->dev;
31     struct iso_vol* vdesc = (struct iso_vol*)valloc(ISO9660_BLKSZ);
32     struct iso_vol_primary* vprim = NULL;
33     u32_t lba = 16;
34     int errno = 0;
35     do {
36         errno = dev->ops.read(dev, vdesc, ISO9660_BLKSZ * lba, ISO9660_BLKSZ);
37         if (errno < 0) {
38             errno = EIO;
39             goto done;
40         }
41         if (*(u32_t*)vdesc->std_id != ISO_SIGNATURE_LO) {
42             errno = ENODEV;
43             goto done;
44         }
45         if (vdesc->type == ISO_VOLPRIM) {
46             vprim = (struct iso_vol_primary*)vdesc;
47             break;
48         }
49         lba++;
50     } while (vdesc->type != ISO_VOLTERM);
51
52     if (!vprim) {
53         errno = EINVAL;
54         goto done;
55     }
56
57     struct iso_superblock* isovsb = valloc(sizeof(*isovsb));
58     isovsb->lb_size = vprim->lb_size.le;
59     isovsb->volume_size = vprim->vol_size.le * isovsb->lb_size;
60
61     vsb->data = isovsb;
62     vsb->ops.init_inode = iso9660_init_inode;
63     vsb->ops.read_capacity = __iso9660_rd_capacity;
64     vsb->ops.release = __vsb_release;
65     vsb->blksize = ISO9660_BLKSZ;
66
67     struct v_inode* rootino = vfs_i_alloc(vsb);
68     struct iso_var_mdu* mdu = (struct iso_var_mdu*)vprim->root_record;
69     struct iso_drecord* dir = iso9660_get_drecord(mdu);
70
71     if (!dir) {
72         vfree(isovsb);
73         errno = EINVAL;
74         goto done;
75     }
76
77     struct iso_drecache drecache;
78     iso9660_fill_drecache(&drecache, dir, mdu->len);
79
80     if ((errno = iso9660_fill_inode(rootino, &drecache, 0)) < 0) {
81         vfree(isovsb);
82         errno = EINVAL;
83         goto done;
84     }
85
86     if ((errno = iso9660_setup_dnode(mount_point, rootino)) < 0) {
87         vfree(isovsb);
88         errno = EINVAL;
89         goto done;
90     }
91
92     vfs_i_addhash(rootino);
93     return 0;
94
95 done:
96     vfree(vdesc);
97     return errno;
98 }
99
100
101
102 int
103 iso9660_unmount(struct v_superblock* vsb)
104 {
105     return 0;
106 }
107
108 void
109 iso9660_init()
110 {
111     struct filesystem* fs;
112     fs = fsapi_fs_declare("iso9660", FSTYPE_ROFS);
113     
114     fsapi_fs_set_mntops(fs, iso9660_mount, iso9660_unmount);
115     fsapi_fs_finalise(fs);
116  
117     drec_cache_pile =
118       cake_new_pile("iso_drec", sizeof(struct iso_drecache), 1, 0);
119 }
120 EXPORT_FILE_SYSTEM(iso9660, iso9660_init);