X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/c6de44b989e9d7286337e4cbf4d82d919f9120e6..2a49908006b177c4d6354309333d06b1b96e4887:/lunaix-os/kernel/fs/iso9660/directory.c diff --git a/lunaix-os/kernel/fs/iso9660/directory.c b/lunaix-os/kernel/fs/iso9660/directory.c index d240e1f..5a06fc8 100644 --- a/lunaix-os/kernel/fs/iso9660/directory.c +++ b/lunaix-os/kernel/fs/iso9660/directory.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,10 +6,14 @@ #include +#include + extern struct cake_pile* drec_cache_pile; void -iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec) +iso9660_fill_drecache(struct iso_drecache* cache, + struct iso_drecord* drec, + u32_t drec_len) { *cache = (struct iso_drecache){ .data_size = drec->data_size.le, .extent_addr = drec->extent_addr.le, @@ -18,33 +21,69 @@ iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec) .fu_size = drec->fu_sz ? drec->fu_sz : 1, .gap_size = drec->gap_sz, .xattr_len = drec->xattr_len }; - u32_t l = drec->name.len; - while (l < (u32_t)-1 && drec->name.content[l--] != ';') - ; - l = (l + 1) ? l : drec->name.len; - l = MIN(l, ISO9660_IDLEN); - strncpy(cache->name_val, drec->name.content, l); - cache->name = HSTR(cache->name_val, l); - hstr_rehash(&cache->name, HSTR_FULL_HASH); + u32_t padding = ((drec->name.len + sizeof(drec->name)) % 2) != 0; + u32_t su_offset = drec->name.len + sizeof(struct iso_drecord) + padding; + int su_len = drec_len - su_offset - 2, i = 0; + + while (i < su_len) { + struct isosu_base* su_entry = + (struct isosu_base*)((void*)drec + su_offset + i); + switch (su_entry->signature) { + case ISORR_NM: + i += isorr_parse_nm(cache, (void*)su_entry); + break; + case ISORR_PX: + i += isorr_parse_px(cache, (void*)su_entry); + break; + case ISORR_TF: + i += isorr_parse_tf(cache, (void*)su_entry); + break; + case ISOSU_ST: + goto done; + default: + i += su_entry->length; + break; + } + } + +done: + if (!cache->name.len) { + // Load ISO9660 file id if no NM found. + u32_t l = drec->name.len; + while (l < (u32_t)-1 && drec->name.content[l--] != ';') + ; + + l = (l + 1) ? l : drec->name.len; + l = MIN(l, ISO9660_IDLEN - 1); + + strncpy(cache->name_val, (const char*)drec->name.content, l); + + cache->name = HSTR(cache->name_val, l); + hstr_rehash(&cache->name, HSTR_FULL_HASH); + } } int iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode) { if (!(inode->itype & VFS_IFDIR)) { - return; + vfs_assign_inode(dnode, inode); + return 0; + } + + struct iso_inode* isoino = inode->data; + if (!llist_empty(&isoino->drecaches)) { + dnode->data = &isoino->drecaches; + vfs_assign_inode(dnode, inode); + return 0; } int errno = 0; struct device* dev = dnode->super_block->dev; - struct iso_inode* isoino = inode->data; - struct llist_header* lead = valloc(sizeof(*lead)); void* records = valloc(ISO9660_BLKSZ); u32_t current_pos = -ISO9660_BLKSZ, max_pos = inode->fsize, blk = inode->lb_addr * ISO9660_BLKSZ, blk_offset = (u32_t)-1; - llist_init_head(lead); - // As per 6.8.1, Directory structure shall NOT recorded in interleave mode. do { if (blk_offset >= ISO9660_BLKSZ - sizeof(struct iso_drecord)) { @@ -71,14 +110,13 @@ iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode) struct iso_drecache* cache = cake_grab(drec_cache_pile); - iso9660_fill_drecache(cache, drec); - llist_append(lead, &cache->caches); + iso9660_fill_drecache(cache, drec, mdu->len); + llist_append(&isoino->drecaches, &cache->caches); cont: blk_offset += mdu->len; } while (current_pos + blk_offset < max_pos); - dnode->data = lead; - isoino->drecaches = lead; + dnode->data = &isoino->drecaches; vfs_assign_inode(dnode, inode); @@ -93,10 +131,9 @@ int iso9660_dir_lookup(struct v_inode* this, struct v_dnode* dnode) { struct iso_inode* isoino = this->data; - struct llist_header* lead = isoino->drecaches; struct iso_drecache *pos, *n; - llist_for_each(pos, n, lead, caches) + llist_for_each(pos, n, &isoino->drecaches, caches) { if (HSTR_EQ(&dnode->name, &pos->name)) { goto found; @@ -113,9 +150,7 @@ found: vfs_i_addhash(inode); } - iso9660_setup_dnode(dnode, inode); - - return 0; + return iso9660_setup_dnode(dnode, inode); } static int