1 #include <lunaix/dirent.h>
3 #include <lunaix/fs/iso9660.h>
4 #include <lunaix/mm/cake.h>
5 #include <lunaix/mm/valloc.h>
6 #include <lunaix/spike.h>
8 #include <klibc/string.h>
10 extern struct cake_pile* drec_cache_pile;
13 iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec)
15 *cache = (struct iso_drecache){ .data_size = drec->data_size.le,
16 .extent_addr = drec->extent_addr.le,
18 .fu_size = drec->fu_sz ? drec->fu_sz : 1,
19 .gap_size = drec->gap_sz,
20 .xattr_len = drec->xattr_len };
21 u32_t l = drec->name.len;
22 while (l < (u32_t)-1 && drec->name.content[l--] != ';')
25 l = l ? l : drec->name.len;
26 l = MIN(l, ISO9660_IDLEN - 1);
28 strncpy(cache->name_val, drec->name.content, l);
29 cache->name = HSTR(cache->name_val, l);
30 hstr_rehash(&cache->name, HSTR_FULL_HASH);
34 iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode)
36 if (!(inode->itype & VFS_IFDIR)) {
37 vfs_assign_inode(dnode, inode);
42 struct device* dev = dnode->super_block->dev;
43 struct iso_inode* isoino = inode->data;
44 struct llist_header* lead = valloc(sizeof(*lead));
45 void* records = valloc(ISO9660_BLKSZ);
46 u32_t current_pos = -ISO9660_BLKSZ, max_pos = inode->fsize,
47 blk = inode->lb_addr * ISO9660_BLKSZ, blk_offset = (u32_t)-1;
49 llist_init_head(lead);
51 // As per 6.8.1, Directory structure shall NOT recorded in interleave mode.
53 if (blk_offset >= ISO9660_BLKSZ - sizeof(struct iso_drecord)) {
54 current_pos += ISO9660_BLKSZ;
55 errno = dev->read(dev, records, blk + current_pos, ISO9660_BLKSZ);
63 struct iso_drecord* drec;
64 struct iso_var_mdu* mdu = (struct iso_var_mdu*)(records + blk_offset);
66 if (!(drec = iso9660_get_drecord(mdu))) {
70 // ignore the '.', '..' as we have built-in support
71 if (drec->name.len == 1) {
75 struct iso_drecache* cache = cake_grab(drec_cache_pile);
77 iso9660_fill_drecache(cache, drec);
78 llist_append(lead, &cache->caches);
80 blk_offset += mdu->len;
81 } while (current_pos + blk_offset < max_pos);
84 isoino->drecaches = lead;
86 vfs_assign_inode(dnode, inode);
96 iso9660_dir_lookup(struct v_inode* this, struct v_dnode* dnode)
98 struct iso_inode* isoino = this->data;
99 struct llist_header* lead = isoino->drecaches;
100 struct iso_drecache *pos, *n;
102 llist_for_each(pos, n, lead, caches)
104 if (HSTR_EQ(&dnode->name, &pos->name)) {
111 struct v_inode* inode = vfs_i_find(dnode->super_block, pos->extent_addr);
114 inode = vfs_i_alloc(dnode->super_block);
115 iso9660_fill_inode(inode, pos, pos->extent_addr);
116 vfs_i_addhash(inode);
119 return iso9660_setup_dnode(dnode, inode);
123 __get_dtype(struct iso_drecache* pos)
125 if ((pos->flags & ISO_FDIR)) {
133 iso9660_readdir(struct v_file* file, struct dir_context* dctx)
135 struct llist_header* lead = file->dnode->data;
136 struct iso_drecache *pos, *n;
137 u32_t counter = dctx->index - 1;
139 llist_for_each(pos, n, lead, caches)
141 if (counter == (u32_t)-1 && !(pos->flags & ISO_FHIDDEN)) {
142 dctx->read_complete_callback(
143 dctx, pos->name_val, pos->name.len, __get_dtype(pos));