diff options
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/core/fs/ext2/ext2.c')
-rw-r--r-- | contrib/syslinux/syslinux-4.03/core/fs/ext2/ext2.c | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/contrib/syslinux/syslinux-4.03/core/fs/ext2/ext2.c b/contrib/syslinux/syslinux-4.03/core/fs/ext2/ext2.c deleted file mode 100644 index 716670c..0000000 --- a/contrib/syslinux/syslinux-4.03/core/fs/ext2/ext2.c +++ /dev/null @@ -1,335 +0,0 @@ -#include <dprintf.h> -#include <stdio.h> -#include <string.h> -#include <sys/dirent.h> -#include <minmax.h> -#include "cache.h" -#include "core.h" -#include "disk.h" -#include "fs.h" -#include "ext2_fs.h" - -/* - * Convert an ext2 file type to the global values - */ -static enum dirent_type ext2_cvt_type(unsigned int d_file_type) -{ - static const enum dirent_type inode_type[] = { - DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, - DT_BLK, DT_FIFO, DT_SOCK, DT_LNK, - }; - - if (d_file_type > sizeof inode_type / sizeof *inode_type) - return DT_UNKNOWN; - else - return inode_type[d_file_type]; -} - -/* - * get the group's descriptor of group_num - */ -static const struct ext2_group_desc * -ext2_get_group_desc(struct fs_info *fs, uint32_t group_num) -{ - struct ext2_sb_info *sbi = EXT2_SB(fs); - uint32_t desc_block, desc_index; - const struct ext2_group_desc *desc_data_block; - - if (group_num >= sbi->s_groups_count) { - printf ("ext2_get_group_desc" - "block_group >= groups_count - " - "block_group = %d, groups_count = %d", - group_num, sbi->s_groups_count); - - return NULL; - } - - desc_block = group_num / sbi->s_desc_per_block; - desc_index = group_num % sbi->s_desc_per_block; - - desc_block += sbi->s_first_data_block + 1; - - desc_data_block = get_cache(fs->fs_dev, desc_block); - return &desc_data_block[desc_index]; -} - -/* - * Unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure. - */ -static inline bool ext2_match_entry(const char *name, size_t len, - const struct ext2_dir_entry * de) -{ - if (!de->d_inode) - return false; - if (len != de->d_name_len) - return false; - return !memcmp(name, de->d_name, len); -} - - -/* - * p is at least 6 bytes before the end of page - */ -static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p) -{ - return (struct ext2_dir_entry *)((char*)p + p->d_rec_len); -} - -/* - * Map a logical sector and load it into the cache - */ -static const void * -ext2_get_cache(struct inode *inode, block_t lblock) -{ - block_t pblock = ext2_bmap(inode, lblock, NULL); - return get_cache(inode->fs->fs_dev, pblock); -} - -/* - * find a dir entry, return it if found, or return NULL. - */ -static const struct ext2_dir_entry * -ext2_find_entry(struct fs_info *fs, struct inode *inode, const char *dname) -{ - block_t index = 0; - uint32_t i = 0, offset, maxoffset; - const struct ext2_dir_entry *de; - const char *data; - size_t dname_len = strlen(dname); - - while (i < inode->size) { - data = ext2_get_cache(inode, index++); - offset = 0; - maxoffset = min(BLOCK_SIZE(fs), i-inode->size); - - /* The smallest possible size is 9 bytes */ - while (offset < maxoffset-8) { - de = (const struct ext2_dir_entry *)(data + offset); - if (de->d_rec_len > maxoffset - offset) - break; - - if (ext2_match_entry(dname, dname_len, de)) - return de; - - offset += de->d_rec_len; - } - i += BLOCK_SIZE(fs); - } - - return NULL; -} - -static const struct ext2_inode * -ext2_get_inode(struct fs_info *fs, int inr) -{ - const struct ext2_group_desc *desc; - const char *data; - uint32_t inode_group, inode_offset; - uint32_t block_num, block_off; - - inr--; - inode_group = inr / EXT2_INODES_PER_GROUP(fs); - inode_offset = inr % EXT2_INODES_PER_GROUP(fs); - desc = ext2_get_group_desc(fs, inode_group); - if (!desc) - return NULL; - - block_num = desc->bg_inode_table + - inode_offset / EXT2_INODES_PER_BLOCK(fs); - block_off = inode_offset % EXT2_INODES_PER_BLOCK(fs); - - data = get_cache(fs->fs_dev, block_num); - - return (const struct ext2_inode *) - (data + block_off * EXT2_SB(fs)->s_inode_size); -} - -static void fill_inode(struct inode *inode, const struct ext2_inode *e_inode) -{ - inode->mode = IFTODT(e_inode->i_mode); - inode->size = e_inode->i_size; - inode->atime = e_inode->i_atime; - inode->ctime = e_inode->i_ctime; - inode->mtime = e_inode->i_mtime; - inode->dtime = e_inode->i_dtime; - inode->blocks = e_inode->i_blocks; - inode->flags = e_inode->i_flags; - inode->file_acl = e_inode->i_file_acl; - memcpy(PVT(inode)->i_block, e_inode->i_block, sizeof PVT(inode)->i_block); -} - -static struct inode *ext2_iget_by_inr(struct fs_info *fs, uint32_t inr) -{ - const struct ext2_inode *e_inode; - struct inode *inode; - - e_inode = ext2_get_inode(fs, inr); - if (!(inode = alloc_inode(fs, inr, sizeof(struct ext2_pvt_inode)))) - return NULL; - fill_inode(inode, e_inode); - - return inode; -} - -static struct inode *ext2_iget_root(struct fs_info *fs) -{ - return ext2_iget_by_inr(fs, EXT2_ROOT_INO); -} - -static struct inode *ext2_iget(const char *dname, struct inode *parent) -{ - const struct ext2_dir_entry *de; - struct fs_info *fs = parent->fs; - - de = ext2_find_entry(fs, parent, dname); - if (!de) - return NULL; - - return ext2_iget_by_inr(fs, de->d_inode); -} - -/* - * Read the entire contents of an inode into a memory buffer - */ -static int cache_get_file(struct inode *inode, void *buf, size_t bytes) -{ - struct fs_info *fs = inode->fs; - size_t block_size = BLOCK_SIZE(fs); - uint32_t index = 0; /* Logical block number */ - size_t chunk; - const char *data; - char *p = buf; - - if (inode->size > bytes) - bytes = inode->size; - - while (bytes) { - chunk = min(bytes, block_size); - data = ext2_get_cache(inode, index++); - memcpy(p, data, chunk); - - bytes -= chunk; - p += chunk; - } - - return 0; -} - -static int ext2_readlink(struct inode *inode, char *buf) -{ - struct fs_info *fs = inode->fs; - int sec_per_block = 1 << (fs->block_shift - fs->sector_shift); - bool fast_symlink; - - if (inode->size > BLOCK_SIZE(fs)) - return -1; /* Error! */ - - fast_symlink = (inode->file_acl ? sec_per_block : 0) == inode->blocks; - if (fast_symlink) - memcpy(buf, PVT(inode)->i_block, inode->size); - else - cache_get_file(inode, buf, inode->size); - - return inode->size; -} - -/* - * Read one directory entry at a time - */ -static int ext2_readdir(struct file *file, struct dirent *dirent) -{ - struct fs_info *fs = file->fs; - struct inode *inode = file->inode; - const struct ext2_dir_entry *de; - const char *data; - block_t index = file->offset >> fs->block_shift; - - if (file->offset >= inode->size) - return -1; /* End of file */ - - data = ext2_get_cache(inode, index); - de = (const struct ext2_dir_entry *) - (data + (file->offset & (BLOCK_SIZE(fs) - 1))); - - dirent->d_ino = de->d_inode; - dirent->d_off = file->offset; - dirent->d_reclen = offsetof(struct dirent, d_name) + de->d_name_len + 1; - dirent->d_type = ext2_cvt_type(de->d_file_type); - memcpy(dirent->d_name, de->d_name, de->d_name_len); - dirent->d_name[de->d_name_len] = '\0'; - - file->offset += de->d_rec_len; /* Update for next reading */ - - return 0; -} - -/* - * init. the fs meta data, return the block size bits. - */ -static int ext2_fs_init(struct fs_info *fs) -{ - struct disk *disk = fs->fs_dev->disk; - struct ext2_sb_info *sbi; - struct ext2_super_block sb; - struct cache *cs; - - /* read the super block */ - disk->rdwr_sectors(disk, &sb, 2, 2, 0); - - /* check if it is ext2, since we also support btrfs now */ - if (sb.s_magic != EXT2_SUPER_MAGIC) - return -1; - - sbi = malloc(sizeof(*sbi)); - if (!sbi) { - malloc_error("ext2_sb_info structure"); - return -1; - } - fs->fs_info = sbi; - - if (sb.s_magic != EXT2_SUPER_MAGIC) { - printf("ext2 mount error: it's not a EXT2/3/4 file system!\n"); - return 0; - } - - fs->sector_shift = disk->sector_shift; - fs->block_shift = sb.s_log_block_size + 10; - fs->sector_size = 1 << fs->sector_shift; - fs->block_size = 1 << fs->block_shift; - - sbi->s_inodes_per_group = sb.s_inodes_per_group; - sbi->s_blocks_per_group = sb.s_blocks_per_group; - sbi->s_inodes_per_block = BLOCK_SIZE(fs) / sb.s_inode_size; - if (sb.s_desc_size < sizeof(struct ext2_group_desc)) - sb.s_desc_size = sizeof(struct ext2_group_desc); - sbi->s_desc_per_block = BLOCK_SIZE(fs) / sb.s_desc_size; - sbi->s_groups_count = (sb.s_blocks_count - sb.s_first_data_block - + EXT2_BLOCKS_PER_GROUP(fs) - 1) - / EXT2_BLOCKS_PER_GROUP(fs); - sbi->s_first_data_block = sb.s_first_data_block; - sbi->s_inode_size = sb.s_inode_size; - - /* Initialize the cache, and force block zero to all zero */ - cache_init(fs->fs_dev, fs->block_shift); - cs = _get_cache_block(fs->fs_dev, 0); - memset(cs->data, 0, fs->block_size); - cache_lock_block(cs); - - return fs->block_shift; -} - -const struct fs_ops ext2_fs_ops = { - .fs_name = "ext2", - .fs_flags = FS_THISIND | FS_USEMEM, - .fs_init = ext2_fs_init, - .searchdir = NULL, - .getfssec = generic_getfssec, - .close_file = generic_close_file, - .mangle_name = generic_mangle_name, - .load_config = generic_load_config, - .iget_root = ext2_iget_root, - .iget = ext2_iget, - .readlink = ext2_readlink, - .readdir = ext2_readdir, - .next_extent = ext2_next_extent, -}; |