mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-16 00:15:08 +01:00
0f17471b27
*Added sources of the custom libs to the branches *Fixed crash when switching from list layout to grid/carousel layout *Removed 1:1 copy option because its meaningless and almost the same as installing all partitions *Fixed install partition selection. This option needs a reset. Go to settings and reselect your option for this. *Fixed schinese and tchinese language modes (filename bugs. has to be schinese.lang and tchinese.lang like on SVN) *Fixed bug in sound buffer circle *Fixed incorrect behaviour of x-flip when selecting system like (thx Cyan for the patch) *Accept ios revision 65535 for Waninkokos IOSes (thx to PPSainity for pointing it out) *Merged the new theming style branch into trunk. Just as a reminder: ALL old themes will not work until the themers did port it to the new style! *Removed old theme style completely Theme example: The example file of the theme is the Default.them file. It can be found in the SVN trunk. Change in loading of themes: When selecting a theme now a list of all .them files in a folder is displayed. The image folder of that theme has to be in the same folder as the .them file. The image path is defined in the head of the .them file in the line with "Image-Folder: Example\n".
412 lines
11 KiB
C
412 lines
11 KiB
C
/*
|
|
* openfs.c --- open an ext2 filesystem
|
|
*
|
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
|
*
|
|
* %Begin-Header%
|
|
* This file may be redistributed under the terms of the GNU Library
|
|
* General Public License, version 2.
|
|
* %End-Header%
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#if HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#if HAVE_SYS_STAT_H
|
|
#include <sys/stat.h>
|
|
#endif
|
|
#if HAVE_SYS_TYPES_H
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
#include "ext2_fs.h"
|
|
|
|
|
|
#include "ext2fs.h"
|
|
#include "e2image.h"
|
|
|
|
blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block,
|
|
dgrp_t i)
|
|
{
|
|
int bg;
|
|
int has_super = 0;
|
|
blk64_t ret_blk;
|
|
|
|
if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) ||
|
|
(i < fs->super->s_first_meta_bg))
|
|
return (group_block + i + 1);
|
|
|
|
bg = EXT2_DESC_PER_BLOCK(fs->super) * i;
|
|
if (ext2fs_bg_has_super(fs, bg))
|
|
has_super = 1;
|
|
ret_blk = ext2fs_group_first_block2(fs, bg) + has_super;
|
|
/*
|
|
* If group_block is not the normal value, we're trying to use
|
|
* the backup group descriptors and superblock --- so use the
|
|
* alternate location of the second block group in the
|
|
* metablock group. Ideally we should be testing each bg
|
|
* descriptor block individually for correctness, but we don't
|
|
* have the infrastructure in place to do that.
|
|
*/
|
|
if (group_block != fs->super->s_first_data_block &&
|
|
((ret_blk + fs->super->s_blocks_per_group) <
|
|
ext2fs_blocks_count(fs->super)))
|
|
ret_blk += fs->super->s_blocks_per_group;
|
|
return ret_blk;
|
|
}
|
|
|
|
blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i)
|
|
{
|
|
return ext2fs_descriptor_block_loc2(fs, group_block, i);
|
|
}
|
|
|
|
errcode_t ext2fs_open(const char *name, int flags, int superblock,
|
|
unsigned int block_size, io_channel * io,
|
|
ext2_filsys *ret_fs)
|
|
{
|
|
return ext2fs_open2(name, 0, flags, superblock, block_size,
|
|
io, ret_fs);
|
|
}
|
|
|
|
/*
|
|
* Note: if superblock is non-zero, block-size must also be non-zero.
|
|
* Superblock and block_size can be zero to use the default size.
|
|
*
|
|
* Valid flags for ext2fs_open()
|
|
*
|
|
* EXT2_FLAG_RW - Open the filesystem for read/write.
|
|
* EXT2_FLAG_FORCE - Open the filesystem even if some of the
|
|
* features aren't supported.
|
|
* EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device
|
|
*/
|
|
errcode_t ext2fs_open2(const char *name, const char *io_options,
|
|
int flags, int superblock,
|
|
unsigned int block_size, io_channel * io,
|
|
ext2_filsys *ret_fs)
|
|
{
|
|
ext2_filsys fs;
|
|
io_manager manager = (*io)->manager;
|
|
errcode_t retval;
|
|
unsigned long i, first_meta_bg;
|
|
__u32 features;
|
|
int groups_per_block, blocks_per_group, io_flags;
|
|
blk64_t group_block, blk;
|
|
char *dest, *cp;
|
|
#ifdef WORDS_BIGENDIAN
|
|
struct ext2_group_desc *gdp;
|
|
int j;
|
|
#endif
|
|
|
|
EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
|
|
|
|
retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs);
|
|
if (retval)
|
|
return retval;
|
|
|
|
memset(fs, 0, sizeof(struct struct_ext2_filsys));
|
|
fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
|
|
fs->io = *io;
|
|
fs->flags = flags;
|
|
/* don't overwrite sb backups unless flag is explicitly cleared */
|
|
fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
|
|
fs->umask = 022;
|
|
retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name);
|
|
if (retval)
|
|
goto cleanup;
|
|
strcpy(fs->device_name, name);
|
|
cp = strchr(fs->device_name, '?');
|
|
if (!io_options && cp) {
|
|
*cp++ = 0;
|
|
io_options = cp;
|
|
}
|
|
|
|
io_flags = 0;
|
|
if (flags & EXT2_FLAG_RW)
|
|
io_flags |= IO_FLAG_RW;
|
|
if (flags & EXT2_FLAG_EXCLUSIVE)
|
|
io_flags |= IO_FLAG_EXCLUSIVE;
|
|
if (flags & EXT2_FLAG_DIRECT_IO)
|
|
io_flags |= IO_FLAG_DIRECT_IO;
|
|
retval = manager->open(fs->device_name, io_flags, &fs->io);
|
|
if (retval)
|
|
goto cleanup;
|
|
if (io_options &&
|
|
(retval = io_channel_set_options(fs->io, io_options)))
|
|
goto cleanup;
|
|
fs->image_io = fs->io;
|
|
fs->io->app_data = fs;
|
|
retval = ext2fs_get_memalign(SUPERBLOCK_SIZE, 512, &fs->super);
|
|
if (retval)
|
|
goto cleanup;
|
|
if (flags & EXT2_FLAG_IMAGE_FILE) {
|
|
retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr),
|
|
&fs->image_header);
|
|
if (retval)
|
|
goto cleanup;
|
|
retval = io_channel_read_blk(fs->io, 0,
|
|
-(int)sizeof(struct ext2_image_hdr),
|
|
fs->image_header);
|
|
if (retval)
|
|
goto cleanup;
|
|
if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE)
|
|
return EXT2_ET_MAGIC_E2IMAGE;
|
|
superblock = 1;
|
|
block_size = fs->image_header->fs_blocksize;
|
|
}
|
|
|
|
/*
|
|
* If the user specifies a specific block # for the
|
|
* superblock, then he/she must also specify the block size!
|
|
* Otherwise, read the master superblock located at offset
|
|
* SUPERBLOCK_OFFSET from the start of the partition.
|
|
*
|
|
* Note: we only save a backup copy of the superblock if we
|
|
* are reading the superblock from the primary superblock location.
|
|
*/
|
|
if (superblock) {
|
|
if (!block_size) {
|
|
retval = EXT2_ET_INVALID_ARGUMENT;
|
|
goto cleanup;
|
|
}
|
|
io_channel_set_blksize(fs->io, block_size);
|
|
group_block = superblock;
|
|
fs->orig_super = 0;
|
|
} else {
|
|
io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET);
|
|
superblock = 1;
|
|
group_block = 0;
|
|
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super);
|
|
if (retval)
|
|
goto cleanup;
|
|
}
|
|
retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE,
|
|
fs->super);
|
|
if (retval)
|
|
goto cleanup;
|
|
if (fs->orig_super)
|
|
memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE);
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
fs->flags |= EXT2_FLAG_SWAP_BYTES;
|
|
ext2fs_swap_super(fs->super);
|
|
#else
|
|
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
|
|
retval = EXT2_ET_UNIMPLEMENTED;
|
|
goto cleanup;
|
|
}
|
|
#endif
|
|
|
|
if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
|
|
retval = EXT2_ET_BAD_MAGIC;
|
|
goto cleanup;
|
|
}
|
|
if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
|
|
retval = EXT2_ET_REV_TOO_HIGH;
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* Check for feature set incompatibility
|
|
*/
|
|
if (!(flags & EXT2_FLAG_FORCE)) {
|
|
features = fs->super->s_feature_incompat;
|
|
#ifdef EXT2_LIB_SOFTSUPP_INCOMPAT
|
|
if (flags & EXT2_FLAG_SOFTSUPP_FEATURES)
|
|
features &= !EXT2_LIB_SOFTSUPP_INCOMPAT;
|
|
#endif
|
|
if (features & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
|
|
retval = EXT2_ET_UNSUPP_FEATURE;
|
|
goto cleanup;
|
|
}
|
|
|
|
features = fs->super->s_feature_ro_compat;
|
|
#ifdef EXT2_LIB_SOFTSUPP_RO_COMPAT
|
|
if (flags & EXT2_FLAG_SOFTSUPP_FEATURES)
|
|
features &= !EXT2_LIB_SOFTSUPP_RO_COMPAT;
|
|
#endif
|
|
if ((flags & EXT2_FLAG_RW) &&
|
|
(features & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
|
|
retval = EXT2_ET_RO_UNSUPP_FEATURE;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
|
|
(fs->super->s_feature_incompat &
|
|
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
|
|
retval = EXT2_ET_UNSUPP_FEATURE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if ((fs->super->s_log_block_size + EXT2_MIN_BLOCK_LOG_SIZE) >
|
|
EXT2_MAX_BLOCK_LOG_SIZE) {
|
|
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
goto cleanup;
|
|
}
|
|
fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
|
|
if (EXT2_INODE_SIZE(fs->super) < EXT2_GOOD_OLD_INODE_SIZE) {
|
|
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
goto cleanup;
|
|
}
|
|
fs->fragsize = EXT2_FRAG_SIZE(fs->super);
|
|
fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) *
|
|
EXT2_INODE_SIZE(fs->super) +
|
|
EXT2_BLOCK_SIZE(fs->super) - 1) /
|
|
EXT2_BLOCK_SIZE(fs->super));
|
|
if (block_size) {
|
|
if (block_size != fs->blocksize) {
|
|
retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
/*
|
|
* Set the blocksize to the filesystem's blocksize.
|
|
*/
|
|
io_channel_set_blksize(fs->io, fs->blocksize);
|
|
|
|
/*
|
|
* If this is an external journal device, don't try to read
|
|
* the group descriptors, because they're not there.
|
|
*/
|
|
if (fs->super->s_feature_incompat &
|
|
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
|
|
fs->group_desc_count = 0;
|
|
*ret_fs = fs;
|
|
return 0;
|
|
}
|
|
|
|
if (EXT2_INODES_PER_GROUP(fs->super) == 0) {
|
|
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
goto cleanup;
|
|
}
|
|
|
|
/*
|
|
* Read group descriptors
|
|
*/
|
|
blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super);
|
|
if (blocks_per_group == 0 ||
|
|
blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) ||
|
|
fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super) ||
|
|
EXT2_DESC_PER_BLOCK(fs->super) == 0 ||
|
|
fs->super->s_first_data_block >= ext2fs_blocks_count(fs->super)) {
|
|
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
goto cleanup;
|
|
}
|
|
fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) -
|
|
fs->super->s_first_data_block,
|
|
blocks_per_group);
|
|
if (fs->group_desc_count * EXT2_INODES_PER_GROUP(fs->super) !=
|
|
fs->super->s_inodes_count) {
|
|
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
|
|
goto cleanup;
|
|
}
|
|
fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
|
|
EXT2_DESC_PER_BLOCK(fs->super));
|
|
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
|
|
&fs->group_desc);
|
|
if (retval)
|
|
goto cleanup;
|
|
if (!group_block)
|
|
group_block = fs->super->s_first_data_block;
|
|
dest = (char *) fs->group_desc;
|
|
groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
|
|
if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
|
|
first_meta_bg = fs->super->s_first_meta_bg;
|
|
else
|
|
first_meta_bg = fs->desc_blocks;
|
|
if (first_meta_bg) {
|
|
retval = io_channel_read_blk(fs->io, group_block+1,
|
|
first_meta_bg, dest);
|
|
if (retval)
|
|
goto cleanup;
|
|
#ifdef WORDS_BIGENDIAN
|
|
gdp = (struct ext2_group_desc *) dest;
|
|
for (j=0; j < groups_per_block*first_meta_bg; j++) {
|
|
gdp = ext2fs_group_desc(fs, fs->group_desc, j);
|
|
ext2fs_swap_group_desc2(fs, gdp);
|
|
}
|
|
#endif
|
|
dest += fs->blocksize*first_meta_bg;
|
|
}
|
|
for (i=first_meta_bg ; i < fs->desc_blocks; i++) {
|
|
blk = ext2fs_descriptor_block_loc2(fs, group_block, i);
|
|
retval = io_channel_read_blk64(fs->io, blk, 1, dest);
|
|
if (retval)
|
|
goto cleanup;
|
|
#ifdef WORDS_BIGENDIAN
|
|
for (j=0; j < groups_per_block; j++) {
|
|
/* The below happens to work... be careful. */
|
|
gdp = ext2fs_group_desc(fs, fs->group_desc, j);
|
|
ext2fs_swap_group_desc2(fs, gdp);
|
|
}
|
|
#endif
|
|
dest += fs->blocksize;
|
|
}
|
|
|
|
fs->stride = fs->super->s_raid_stride;
|
|
|
|
/*
|
|
* If recovery is from backup superblock, Clear _UNININT flags &
|
|
* reset bg_itable_unused to zero
|
|
*/
|
|
if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
|
|
EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
|
|
dgrp_t group;
|
|
|
|
for (group = 0; group < fs->group_desc_count; group++) {
|
|
ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
|
|
ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
|
|
ext2fs_bg_itable_unused_set(fs, group, 0);
|
|
}
|
|
ext2fs_mark_super_dirty(fs);
|
|
}
|
|
|
|
fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR;
|
|
*ret_fs = fs;
|
|
return 0;
|
|
cleanup:
|
|
if (flags & EXT2_FLAG_NOFREE_ON_ERROR)
|
|
*ret_fs = fs;
|
|
else
|
|
ext2fs_free(fs);
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* Set/get the filesystem data I/O channel.
|
|
*
|
|
* These functions are only valid if EXT2_FLAG_IMAGE_FILE is true.
|
|
*/
|
|
errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io)
|
|
{
|
|
if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
|
|
return EXT2_ET_NOT_IMAGE_FILE;
|
|
if (old_io) {
|
|
*old_io = (fs->image_io == fs->io) ? 0 : fs->io;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io)
|
|
{
|
|
if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
|
|
return EXT2_ET_NOT_IMAGE_FILE;
|
|
fs->io = new_io ? new_io : fs->image_io;
|
|
return 0;
|
|
}
|
|
|
|
errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io)
|
|
{
|
|
if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0)
|
|
return EXT2_ET_NOT_IMAGE_FILE;
|
|
fs->io = fs->image_io = new_io;
|
|
fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW |
|
|
EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
|
|
fs->flags &= ~EXT2_FLAG_IMAGE_FILE;
|
|
return 0;
|
|
}
|