From caaf4f94a5ae2c866416d83ef50f1ba47ebc365d Mon Sep 17 00:00:00 2001 From: mintsuki Date: Wed, 15 Feb 2023 10:43:15 +0100 Subject: [PATCH] fs: Drop ext* support --- GNUmakefile.in | 23 -- README.md | 1 - common/fs/ext2.h | 13 - common/fs/ext2.s2.c | 685 -------------------------------------------- common/fs/file.s2.c | 13 +- 5 files changed, 2 insertions(+), 733 deletions(-) delete mode 100644 common/fs/ext2.h delete mode 100644 common/fs/ext2.s2.c diff --git a/GNUmakefile.in b/GNUmakefile.in index cd62ab6a..38daf2ba 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -385,29 +385,6 @@ mbrtest.hdd: dd if=/dev/zero bs=1M count=0 seek=64 of=mbrtest.hdd echo -e "o\nn\np\n1\n2048\n\nt\n6\na\nw\n" | fdisk mbrtest.hdd -H 16 -S 63 -.PHONY: ext2-test -ext2-test: - $(MAKE) test-clean - $(MAKE) test.hdd - $(MAKE) limine-bios - $(MAKE) limine-deploy - $(MAKE) -C test CROSS_FILE='$(call SHESCAPE,$(BUILDDIR))/cross-files/x86_64-elf-toolchain.mk' - rm -rf test_image/ - mkdir test_image - sudo losetup -Pf --show test.hdd > loopback_dev - sudo partprobe `cat loopback_dev` - sudo mkfs.ext2 `cat loopback_dev`p1 - sudo mount `cat loopback_dev`p1 test_image - sudo mkdir test_image/boot - sudo cp -rv $(BINDIR)/* test_image/boot/ - sudo cp -rv test/* test_image/boot/ - sync - sudo umount test_image/ - sudo losetup -d `cat loopback_dev` - rm -rf test_image loopback_dev - $(BINDIR)/limine-deploy test.hdd - qemu-system-x86_64 -net none -smp 4 -hda test.hdd -debugcon stdio - .PHONY: fat12-test fat12-test: $(MAKE) test-clean diff --git a/README.md b/README.md index fbc27c37..03351979 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ as the reference implementation for the [Limine boot protocol](/PROTOCOL.md). * Unpartitioned media ### Supported filesystems -* ext2/3/4 * FAT12/16/32 * ISO9660 (CDs/DVDs) diff --git a/common/fs/ext2.h b/common/fs/ext2.h deleted file mode 100644 index 22f787ac..00000000 --- a/common/fs/ext2.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __FS__EXT2_H__ -#define __FS__EXT2_H__ - -#include -#include -#include - -bool ext2_get_guid(struct guid *guid, struct volume *part); -char *ext2_get_label(struct volume *part); - -struct file_handle *ext2_open(struct volume *part, const char *path); - -#endif diff --git a/common/fs/ext2.s2.c b/common/fs/ext2.s2.c deleted file mode 100644 index 9b56d615..00000000 --- a/common/fs/ext2.s2.c +++ /dev/null @@ -1,685 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Superblock Fields */ -struct ext2_superblock { - uint32_t s_inodes_count; - uint32_t s_blocks_count; - uint32_t s_r_blocks_count; - uint32_t s_free_blocks_count; - uint32_t s_free_inodes_count; - uint32_t s_first_data_block; - uint32_t s_log_block_size; - uint32_t s_log_frag_size; - uint32_t s_blocks_per_group; - uint32_t s_frags_per_group; - uint32_t s_inodes_per_group; - uint32_t s_mtime; - uint32_t s_wtime; - - uint16_t s_mnt_count; - uint16_t s_max_mnt_count; - uint16_t s_magic; - uint16_t s_state; - uint16_t s_errors; - uint16_t s_minor_rev_level; - - uint32_t s_lastcheck; - uint32_t s_checkinterval; - uint32_t s_creator_os; - uint32_t s_rev_level; - uint16_t s_def_resuid; - uint16_t s_def_gid; - - // if version number >= 1, we have to use the ext2 extended superblock as well - - /* Extended Superblock */ - uint32_t s_first_ino; - - uint16_t s_inode_size; - uint16_t s_block_group_nr; - - uint32_t s_feature_compat; - uint32_t s_feature_incompat; - uint32_t s_feature_ro_compat; - - uint64_t s_uuid[2]; - uint8_t s_volume_name[16]; - - uint64_t s_last_mounted[8]; - - uint32_t compression_info; - uint8_t prealloc_blocks; - uint8_t prealloc_dir_blocks; - uint16_t reserved_gdt_blocks; - uint8_t journal_uuid[16]; - uint32_t journal_inum; - uint32_t journal_dev; - uint32_t last_orphan; - uint32_t hash_seed[4]; - uint8_t def_hash_version; - uint8_t jnl_backup_type; - uint16_t group_desc_size; - uint32_t default_mount_opts; - uint32_t first_meta_bg; - uint32_t mkfs_time; - uint32_t jnl_blocks[17]; -} __attribute__((packed)); - -struct ext2_linux { - uint8_t frag_num; - uint8_t frag_size; - - uint16_t reserved_16; - uint16_t user_id_high; - uint16_t group_id_high; - - uint32_t reserved_32; -} __attribute__((packed)); - -struct ext2_inode { - uint16_t i_mode; - uint16_t i_uid; - - uint32_t i_size; - uint32_t i_atime; - uint32_t i_ctime; - uint32_t i_mtime; - uint32_t i_dtime; - - uint16_t i_gid; - uint16_t i_links_count; - - uint32_t i_blocks_count; - uint32_t i_flags; - uint32_t i_osd1; - uint32_t i_blocks[15]; - uint32_t i_generation; - - /* EXT2 v >= 1.0 */ - uint32_t i_eab; - uint32_t i_maj; - - /* EXT2 vAll */ - uint32_t i_frag_block; - - struct ext2_linux i_osd2; -} __attribute__((packed)); - -struct ext2_file_handle { - struct volume *part; - struct ext2_superblock sb; - int size; - struct ext2_inode root_inode; - struct ext2_inode inode; - uint64_t block_size; - uint32_t *alloc_map; -}; - -/* Inode types */ -#define S_IFIFO 0x1000 -#define S_IFCHR 0x2000 -#define S_IFDIR 0x4000 -#define S_IFBLK 0x6000 -#define S_IFREG 0x8000 -#define S_IFLNK 0xa000 -#define S_IFSOCK 0xc000 - -#define FMT_MASK 0xf000 - -/* EXT2 Filesystem States */ -#define EXT2_FS_UNRECOVERABLE_ERRORS 3 - -/* Ext2 incompatible features */ -#define EXT2_IF_COMPRESSION 0x01 -#define EXT2_IF_EXTENTS 0x40 -#define EXT2_IF_64BIT 0x80 -#define EXT2_IF_INLINE_DATA 0x8000 -#define EXT2_IF_ENCRYPT 0x10000 -#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 - -/* Ext4 flags */ -#define EXT4_EXTENTS_FLAG 0x80000 - -#define EXT2_S_MAGIC 0xEF53 - -/* EXT2 Block Group Descriptor */ -struct ext2_bgd { - uint32_t bg_block_bitmap; - uint32_t bg_inode_bitmap; - uint32_t bg_inode_table; - - uint16_t bg_free_blocks_count; - uint16_t bg_free_inodes_count; - uint16_t bg_dirs_count; - - uint16_t reserved[7]; -} __attribute__((packed)); - -struct ext4_bgd { - uint32_t bg_block_bitmap; - uint32_t bg_inode_bitmap; - uint32_t bg_inode_table; - - uint16_t bg_free_blocks_count; - uint16_t bg_free_inodes_count; - uint16_t bg_dirs_count; - - uint16_t pad; - uint32_t reserved[3]; - uint32_t block_id_hi; - uint32_t inode_id_hi; - uint32_t inode_table_id_hi; - uint16_t free_blocks_hi; - uint16_t free_inodes_hi; - uint16_t used_dirs_hi; - uint16_t pad2; - uint32_t reserved2[3]; -} __attribute__((packed)); - -/* EXT2 Inode Types */ -#define EXT2_INO_DIRECTORY 0x4000 - -/* EXT2 Directory Entry */ -struct ext2_dir_entry { - uint32_t inode; - uint16_t rec_len; - uint8_t name_len; - uint8_t type; -} __attribute__((packed)); - -struct ext4_extent_header { - uint16_t magic; - uint16_t entries; - uint16_t max; - uint16_t depth; - uint16_t generation; -} __attribute__((packed)); - -struct ext4_extent { - uint32_t block; - uint16_t len; - uint16_t start_hi; - uint32_t start; -} __attribute__((packed)); - -struct ext4_extent_idx { - uint32_t block; - uint32_t leaf; - uint16_t leaf_hi; - uint16_t empty; -} __attribute__((packed)); - -static int inode_read(void *buf, uint64_t loc, uint64_t count, - struct ext2_inode *inode, struct ext2_file_handle *fd, - uint32_t *alloc_map); -static bool ext2_parse_dirent(struct ext2_dir_entry *dir, struct ext2_file_handle *fd, const char *path); - -// parse an inode given the partition base and inode number -static bool ext2_get_inode(struct ext2_inode *ret, - struct ext2_file_handle *fd, uint64_t inode) { - if (inode == 0) - return false; - - struct ext2_superblock *sb = &fd->sb; - - //determine if we need to use 64 bit inode ids - bool bit64 = false; - if (sb->s_rev_level != 0 - && (sb->s_feature_incompat & (EXT2_IF_64BIT)) - && sb->group_desc_size != 0 - && ((sb->group_desc_size & (sb->group_desc_size - 1)) == 0)) { - if(sb->group_desc_size > 32) { - bit64 = true; - } - } - - const uint64_t ino_blk_grp = (inode - 1) / sb->s_inodes_per_group; - const uint64_t ino_tbl_idx = (inode - 1) % sb->s_inodes_per_group; - - const uint64_t block_size = ((uint64_t)1024 << sb->s_log_block_size); - uint64_t ino_offset; - const uint64_t bgd_start_offset = block_size >= 2048 ? block_size : block_size * 2; - const uint64_t ino_size = sb->s_rev_level == 0 ? sizeof(struct ext2_inode) : sb->s_inode_size; - - if (!bit64) { - struct ext2_bgd target_descriptor; - const uint64_t bgd_offset = bgd_start_offset + (sizeof(struct ext2_bgd) * ino_blk_grp); - - volume_read(fd->part, &target_descriptor, bgd_offset, sizeof(struct ext2_bgd)); - - ino_offset = ((target_descriptor.bg_inode_table) * block_size) + - (ino_size * ino_tbl_idx); - } else { - struct ext4_bgd target_descriptor; - const uint64_t bgd_offset = bgd_start_offset + (sizeof(struct ext4_bgd) * ino_blk_grp); - - volume_read(fd->part, &target_descriptor, bgd_offset, sizeof(struct ext4_bgd)); - - ino_offset = ((target_descriptor.bg_inode_table | (bit64 ? ((uint64_t)target_descriptor.inode_id_hi << 32) : 0)) * block_size) + - (ino_size * ino_tbl_idx); - } - - volume_read(fd->part, ret, ino_offset, sizeof(struct ext2_inode)); - - return true; -} - -static uint32_t *create_alloc_map(struct ext2_file_handle *fd, - struct ext2_inode *inode) { - if (inode->i_flags & EXT4_EXTENTS_FLAG) - return NULL; - - size_t entries_per_block = fd->block_size / sizeof(uint32_t); - - // Cache the map of blocks - uint32_t *alloc_map = ext_mem_alloc(inode->i_blocks_count * sizeof(uint32_t)); - for (uint32_t i = 0; i < inode->i_blocks_count; i++) { - uint32_t block = i; - if (block < 12) { - // Direct block - alloc_map[i] = inode->i_blocks[block]; - } else { - // Indirect block - block -= 12; - if (block >= entries_per_block) { - // Double indirect block - block -= entries_per_block; - uint32_t index = block / entries_per_block; - uint32_t indirect_block; - if (index >= entries_per_block) { - uint32_t first_index = index / entries_per_block; - uint32_t first_indirect_block; - volume_read( - fd->part, &first_indirect_block, - inode->i_blocks[14] * fd->block_size + first_index * sizeof(uint32_t), - sizeof(uint32_t) - ); - uint32_t second_index = index % entries_per_block; - volume_read( - fd->part, &indirect_block, - first_indirect_block * fd->block_size + second_index * sizeof(uint32_t), - sizeof(uint32_t) - ); - } else { - volume_read( - fd->part, &indirect_block, - inode->i_blocks[13] * fd->block_size + index * sizeof(uint32_t), - sizeof(uint32_t) - ); - } - for (uint32_t j = 0; j < entries_per_block; j++) { - if (i + j >= inode->i_blocks_count) - return alloc_map; - volume_read( - fd->part, &alloc_map[i + j], - indirect_block * fd->block_size + j * sizeof(uint32_t), - sizeof(uint32_t) - ); - } - i += entries_per_block - 1; - } else { - // Single indirect block - volume_read( - fd->part, &alloc_map[i], - inode->i_blocks[12] * fd->block_size + block * sizeof(uint32_t), - sizeof(uint32_t) - ); - } - } - } - - return alloc_map; -} - -static bool symlink_to_inode(struct ext2_inode *inode, struct ext2_file_handle *fd, - const char *cwd, size_t cwd_len) { - // I cannot find whether this is 0-terminated or not, so I'm gonna take the - // safe route here and assume it is not. - if (inode->i_size < 59) { - struct ext2_dir_entry dir; - char *symlink = (char *)inode->i_blocks; - symlink[59] = 0; - - char *abs = ext_mem_alloc(4096); - char *cwd_copy = ext_mem_alloc(cwd_len + 1); - memcpy(cwd_copy, cwd, cwd_len); - get_absolute_path(abs, symlink, cwd_copy); - - pmm_free(cwd_copy, cwd_len + 1); - - if (!ext2_parse_dirent(&dir, fd, abs)) { - pmm_free(abs, 4096); - return false; - } - pmm_free(abs, 4096); - - ext2_get_inode(inode, fd, dir.inode); - return true; - } else { - print("ext2: Symlinks with destination paths longer than 60 chars unsupported\n"); - return false; - } -} - -static bool ext2_parse_dirent(struct ext2_dir_entry *dir, struct ext2_file_handle *fd, const char *path) { - if (*path != '/') { - panic(true, "ext2: Path does not start in /"); - } - - path++; - - struct ext2_inode current_inode = fd->root_inode; - - bool escape = false; - static char token[256]; - - bool ret; - - const char *cwd = path - 1; // because / - size_t cwd_len = 1; - size_t next_cwd_len = cwd_len; - -next: - memset(token, 0, 256); - - for (size_t i = 0; i < 255 && *path != '/' && *path != '\0'; i++, path++, next_cwd_len++) - token[i] = *path; - - if (*path == '\0') - escape = true; - else - path++, next_cwd_len++; - - uint32_t *alloc_map = create_alloc_map(fd, ¤t_inode); - - for (uint32_t i = 0; i < current_inode.i_size; ) { - // preliminary read - inode_read(dir, i, sizeof(struct ext2_dir_entry), - ¤t_inode, fd, alloc_map); - - // name read - char *name = ext_mem_alloc(dir->name_len + 1); - - memset(name, 0, dir->name_len + 1); - inode_read(name, i + sizeof(struct ext2_dir_entry), dir->name_len, - ¤t_inode, fd, alloc_map); - - int (*strcmpfn)(const char *, const char *) = case_insensitive_fopen ? strcasecmp : strcmp; - - int test = strcmpfn(token, name); - pmm_free(name, dir->name_len + 1); - - if (test == 0) { - if (escape) { - ret = true; - goto out; - } else { - // update the current inode - ext2_get_inode(¤t_inode, fd, dir->inode); - while ((current_inode.i_mode & FMT_MASK) != S_IFDIR) { - if ((current_inode.i_mode & FMT_MASK) == S_IFLNK) { - if (!symlink_to_inode(¤t_inode, fd, cwd, cwd_len)) { - ret = false; - goto out; - } - } else { - print("ext2: Part of path is not directory nor symlink\n"); - ret = false; - goto out; - } - } - pmm_free(alloc_map, current_inode.i_blocks_count * sizeof(uint32_t)); - cwd_len = next_cwd_len; - goto next; - } - } - - i += dir->rec_len; - } - - ret = false; - -out: - pmm_free(alloc_map, current_inode.i_blocks_count * sizeof(uint32_t)); - return ret; -} - -static void ext2_read(struct file_handle *handle, void *buf, uint64_t loc, uint64_t count); -static void ext2_close(struct file_handle *file); - -struct file_handle *ext2_open(struct volume *part, const char *path) { - struct ext2_file_handle *ret = ext_mem_alloc(sizeof(struct ext2_file_handle)); - - ret->part = part; - - volume_read(ret->part, &ret->sb, 1024, sizeof(struct ext2_superblock)); - - struct ext2_superblock *sb = &ret->sb; - - if (sb->s_magic != EXT2_S_MAGIC) { - pmm_free(ret, sizeof(struct ext2_file_handle)); - return NULL; - } - - if (sb->s_rev_level != 0 && - (sb->s_feature_incompat & EXT2_IF_COMPRESSION || - sb->s_feature_incompat & EXT2_IF_INLINE_DATA || - sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)) { - print("ext2: filesystem has unsupported features %x\n", sb->s_feature_incompat); - pmm_free(ret, sizeof(struct ext2_file_handle)); - return NULL; - } - - if (sb->s_rev_level != 0 && sb->s_feature_incompat & EXT2_IF_ENCRYPT) { - print("ext2: WARNING: File system has encryption feature on, stuff may misbehave\n"); - } - - if (sb->s_state == EXT2_FS_UNRECOVERABLE_ERRORS) { - print("ext2: unrecoverable errors found\n"); - pmm_free(ret, sizeof(struct ext2_file_handle)); - return NULL; - } - - ret->block_size = ((uint64_t)1024 << ret->sb.s_log_block_size); - - ext2_get_inode(&ret->root_inode, ret, 2); - - struct ext2_dir_entry entry; - - size_t cwd_len = 0; - char *cwd = ext_mem_alloc(4096); - for (int i = strlen(path) - 1; i > 0; i--) { - if (path[i] == '/' || path[i] == 0) { - cwd_len = i; - break; - } - } - memcpy(cwd, path, cwd_len); - - if (!ext2_parse_dirent(&entry, ret, path)) { - pmm_free(cwd, 4096); - pmm_free(ret, sizeof(struct ext2_file_handle)); - return NULL; - } - - ext2_get_inode(&ret->inode, ret, entry.inode); - - while ((ret->inode.i_mode & FMT_MASK) != S_IFREG) { - if ((ret->inode.i_mode & FMT_MASK) == S_IFLNK) { - if (!symlink_to_inode(&ret->inode, ret, cwd, cwd_len)) { - pmm_free(cwd, 4096); - pmm_free(ret, sizeof(struct ext2_file_handle)); - return NULL; - } - } else { - print("ext2: Entity is not regular file nor symlink\n"); - pmm_free(cwd, 4096); - pmm_free(ret, sizeof(struct ext2_file_handle)); - return NULL; - } - } - - pmm_free(cwd, 4096); - - ret->size = ret->inode.i_size; - - ret->alloc_map = create_alloc_map(ret, &ret->inode); - - struct file_handle *handle = ext_mem_alloc(sizeof(struct file_handle)); - - handle->fd = ret; - handle->read = (void *)ext2_read; - handle->close = (void *)ext2_close; - handle->size = ret->size; - handle->vol = part; -#if defined (UEFI) - handle->efi_part_handle = part->efi_part_handle; -#endif - - return handle; -} - -static void ext2_close(struct file_handle *file) { - struct ext2_file_handle *f = file->fd; - if (f->alloc_map != NULL) { - pmm_free(f->alloc_map, f->inode.i_blocks_count * sizeof(uint32_t)); - } - pmm_free(f, sizeof(struct ext2_file_handle)); -} - -static void ext2_read(struct file_handle *file, void *buf, uint64_t loc, uint64_t count) { - struct ext2_file_handle *f = file->fd; - inode_read(buf, loc, count, &f->inode, f, f->alloc_map); -} - -static struct ext4_extent_header *ext4_find_leaf(struct ext4_extent_header *ext_block, uint32_t read_block, uint64_t block_size, struct volume *part) { - struct ext4_extent_idx *index; - - void *buf = ext_mem_alloc(block_size); - memcpy(buf, ext_block, block_size); - ext_block = buf; - - for (;;) { - index = (struct ext4_extent_idx *)((size_t)ext_block + 12); - - #define EXT4_EXT_MAGIC 0xf30a - if (ext_block->magic != EXT4_EXT_MAGIC) - panic(false, "invalid extent magic"); - - if (ext_block->depth == 0) { - return ext_block; - } - - int i; - for (i = 0; i < ext_block->entries; i++) { - if (read_block < index[i].block) - break; - } - - if (--i < 0) - panic(false, "extent not found"); - - uint64_t block = ((uint64_t)index[i].leaf_hi << 32) | index[i].leaf; - - volume_read(part, buf, (block * block_size), block_size); - ext_block = buf; - } -} - -static int inode_read(void *buf, uint64_t loc, uint64_t count, - struct ext2_inode *inode, struct ext2_file_handle *fd, - uint32_t *alloc_map) { - for (uint64_t progress = 0; progress < count;) { - uint64_t block = (loc + progress) / fd->block_size; - - uint64_t chunk = count - progress; - uint64_t offset = (loc + progress) % fd->block_size; - if (chunk > fd->block_size - offset) - chunk = fd->block_size - offset; - - uint32_t block_index; - - if (inode->i_flags & EXT4_EXTENTS_FLAG) { - struct ext4_extent_header *leaf; - struct ext4_extent *ext; - int i; - - leaf = ext4_find_leaf((struct ext4_extent_header *)inode->i_blocks, block, fd->block_size, fd->part); - - if (!leaf) - panic(false, "invalid extent"); - ext = (struct ext4_extent*)((size_t)leaf + 12); - - for (i = 0; i < leaf->entries; i++) { - if (block < ext[i].block) { - break; - } - } - - if (--i >= 0) { - block -= ext[i].block; - if (block >= ext[i].len) { - panic(false, "block longer than extent"); - } else { - uint64_t start = ((uint64_t)ext[i].start_hi << 32) + ext[i].start; - block_index = start + block; - } - } else { - panic(false, "extent for block not found"); - } - - pmm_free(leaf, fd->block_size); - } else { - block_index = alloc_map[block]; - } - - volume_read(fd->part, buf + progress, (block_index * fd->block_size) + offset, chunk); - - progress += chunk; - } - - return 0; -} - -bool ext2_get_guid(struct guid *guid, struct volume *part) { - struct ext2_superblock sb; - volume_read(part, &sb, 1024, sizeof(struct ext2_superblock)); - - if (sb.s_magic != EXT2_S_MAGIC) - return false; - - ((uint64_t *)guid)[0] = sb.s_uuid[0]; - ((uint64_t *)guid)[1] = sb.s_uuid[1]; - - return true; -} - -char *ext2_get_label(struct volume *part) { - struct ext2_superblock sb; - volume_read(part, &sb, 1024, sizeof(struct ext2_superblock)); - - if (sb.s_magic != EXT2_S_MAGIC) { - return NULL; - } - - if (sb.s_rev_level < 1) { - return NULL; - } - - size_t label_len = strlen((char *)sb.s_volume_name); - if (label_len == 0) { - return NULL; - } - char *ret = ext_mem_alloc(label_len + 1); - strcpy(ret, (char *)sb.s_volume_name); - - return ret; -} diff --git a/common/fs/file.s2.c b/common/fs/file.s2.c index aa603e6f..643f19c3 100644 --- a/common/fs/file.s2.c +++ b/common/fs/file.s2.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -17,18 +16,13 @@ char *fs_get_label(struct volume *part) { if ((ret = fat32_get_label(part)) != NULL) { return ret; } - if ((ret = ext2_get_label(part)) != NULL) { - return ret; - } return NULL; } bool fs_get_guid(struct guid *guid, struct volume *part) { - if (ext2_get_guid(guid, part) == true) { - return true; - } - + (void)guid; + (void)part; return false; } @@ -56,9 +50,6 @@ struct file_handle *fopen(struct volume *part, const char *filename) { return ret; } - if ((ret = ext2_open(part, filename)) != NULL) { - goto success; - } if ((ret = iso9660_open(part, filename)) != NULL) { goto success; }