3 #include <lunaix/mm/cake.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/spike.h>
7 #include <klibc/string.h>
9 #include <usr/lunaix/dirent.h>
11 extern struct cake_pile* drec_cache_pile;
14 iso9660_fill_drecache(struct iso_drecache* cache,
15 struct iso_drecord* drec,
18 *cache = (struct iso_drecache){ .data_size = drec->data_size.le,
19 .extent_addr = drec->extent_addr.le,
21 .fu_size = drec->fu_sz ? drec->fu_sz : 1,
22 .gap_size = drec->gap_sz,
23 .xattr_len = drec->xattr_len };
24 u32_t padding = ((drec->name.len + sizeof(drec->name)) % 2) != 0;
25 u32_t su_offset = drec->name.len + sizeof(struct iso_drecord) + padding;
26 int su_len = drec_len - su_offset - 2, i = 0;
29 struct isosu_base* su_entry =
30 (struct isosu_base*)((void*)drec + su_offset + i);
31 switch (su_entry->signature) {
33 i += isorr_parse_nm(cache, (void*)su_entry);
36 i += isorr_parse_px(cache, (void*)su_entry);
39 i += isorr_parse_tf(cache, (void*)su_entry);
44 i += su_entry->length;
50 if (cache->name.len) {
54 // Load ISO9660 file id if no NM found.
57 char name_val = drec->name.content[0];
58 u32_t l = drec->name.len;
60 if (l == 1 && !name_val) {
61 cache->name = vfs_dot;
65 if(l == 1 && name_val == 1) {
66 cache->name = vfs_ddot;
70 while (l < (u32_t)-1 && drec->name.content[l--] != ';')
73 l = (l + 1) ? l : drec->name.len;
74 l = MIN(l, ISO9660_IDLEN - 1);
76 strncpy(cache->name_val, (const char*)drec->name.content, l);
77 cache->name = HSTR(cache->name_val, l);
78 hstr_rehash(&cache->name, HSTR_FULL_HASH);
82 iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode)
84 if (!check_directory_node(inode)) {
85 vfs_assign_inode(dnode, inode);
89 struct iso_inode* isoino = inode->data;
90 if (!llist_empty(&isoino->drecaches)) {
91 dnode->data = &isoino->drecaches;
92 vfs_assign_inode(dnode, inode);
97 struct device* dev = dnode->super_block->dev;
98 void* records = valloc(ISO9660_BLKSZ);
99 u32_t current_pos = -ISO9660_BLKSZ, max_pos = inode->fsize,
100 blk = inode->lb_addr * ISO9660_BLKSZ, blk_offset = (u32_t)-1;
102 // As per 6.8.1, Directory structure shall NOT recorded in interleave mode.
104 if (blk_offset >= ISO9660_BLKSZ - sizeof(struct iso_drecord)) {
105 current_pos += ISO9660_BLKSZ;
107 dev->ops.read(dev, records, blk + current_pos, ISO9660_BLKSZ);
115 struct iso_drecord* drec;
116 struct iso_var_mdu* mdu = (struct iso_var_mdu*)(records + blk_offset);
118 if (!(drec = iso9660_get_drecord(mdu))) {
122 struct iso_drecache* cache = cake_grab(drec_cache_pile);
124 iso9660_fill_drecache(cache, drec, mdu->len);
125 llist_append(&isoino->drecaches, &cache->caches);
127 blk_offset += mdu->len;
128 } while (current_pos + blk_offset < max_pos);
130 dnode->data = &isoino->drecaches;
132 vfs_assign_inode(dnode, inode);
142 iso9660_dir_lookup(struct v_inode* this, struct v_dnode* dnode)
144 struct iso_inode* isoino = this->data;
145 struct iso_drecache *pos, *n;
147 llist_for_each(pos, n, &isoino->drecaches, caches)
149 if (HSTR_EQ(&dnode->name, &pos->name)) {
156 struct v_inode* inode = vfs_i_find(dnode->super_block, pos->extent_addr);
159 inode = vfs_i_alloc(dnode->super_block);
160 iso9660_fill_inode(inode, pos, pos->extent_addr);
161 vfs_i_addhash(inode);
164 return iso9660_setup_dnode(dnode, inode);
168 __get_dtype(struct iso_drecache* pos)
170 if ((pos->flags & ISO_FDIR)) {
178 iso9660_readdir(struct v_file* file, struct dir_context* dctx)
180 struct llist_header* lead = file->dnode->data;
181 struct iso_drecache *pos, *n;
184 llist_for_each(pos, n, lead, caches)
186 if (counter == file->f_pos && !(pos->flags & ISO_FHIDDEN)) {
187 dctx->read_complete_callback(
188 dctx, HSTR_VAL(pos->name), HSTR_LEN(pos->name), __get_dtype(pos));