usbloadergx/libcustomext2fs/source/fileio.c
dimok321 0f17471b27 *Removed ntfs/fat source and added them as custom libs (makes them easier to update later)
*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".
2010-12-26 17:02:14 +00:00

413 lines
8.8 KiB
C

/*
* fileio.c --- Simple file I/O routines
*
* Copyright (C) 1997 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 "ext2_fs.h"
#include "ext2fs.h"
struct ext2_file {
errcode_t magic;
ext2_filsys fs;
ext2_ino_t ino;
struct ext2_inode inode;
int flags;
__u64 pos;
blk64_t blockno;
blk64_t physblock;
char *buf;
};
#define BMAP_BUFFER (file->buf + fs->blocksize)
errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode,
int flags, ext2_file_t *ret)
{
ext2_file_t file;
errcode_t retval;
/*
* Don't let caller create or open a file for writing if the
* filesystem is read-only.
*/
if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
if (retval)
return retval;
memset(file, 0, sizeof(struct ext2_file));
file->magic = EXT2_ET_MAGIC_EXT2_FILE;
file->fs = fs;
file->ino = ino;
file->flags = flags & EXT2_FILE_MASK;
if (inode) {
memcpy(&file->inode, inode, sizeof(struct ext2_inode));
} else {
retval = ext2fs_read_inode(fs, ino, &file->inode);
if (retval)
goto fail;
}
retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
if (retval)
goto fail;
*ret = file;
return 0;
fail:
if (file->buf)
ext2fs_free_mem(&file->buf);
ext2fs_free_mem(&file);
return retval;
}
errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
int flags, ext2_file_t *ret)
{
return ext2fs_file_open2(fs, ino, NULL, flags, ret);
}
/*
* This function returns the filesystem handle of a file from the structure
*/
ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return 0;
return file->fs;
}
/*
* This function returns the pointer to the inode of a file from the structure
*/
struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return NULL;
return &file->inode;
}
/*
* This function flushes the dirty block buffer out to disk if
* necessary.
*/
errcode_t ext2fs_file_flush(ext2_file_t file)
{
errcode_t retval;
ext2_filsys fs;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
if (!(file->flags & EXT2_FILE_BUF_VALID) ||
!(file->flags & EXT2_FILE_BUF_DIRTY))
return 0;
// Flushing out the new size - Dimok
ext2fs_write_inode(file->fs, file->ino, &file->inode);
/*
* OK, the physical block hasn't been allocated yet.
* Allocate it.
*/
if (!file->physblock) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
file->blockno, 0, &file->physblock);
if (retval)
return retval;
}
retval = io_channel_write_blk(fs->io, file->physblock,
1, file->buf);
if (retval)
return retval;
file->flags &= ~EXT2_FILE_BUF_DIRTY;
return retval;
}
/*
* This function synchronizes the file's block buffer and the current
* file position, possibly invalidating block buffer if necessary
*/
static errcode_t sync_buffer_position(ext2_file_t file)
{
blk_t b;
errcode_t retval;
b = file->pos / file->fs->blocksize;
if (b != file->blockno) {
retval = ext2fs_file_flush(file);
if (retval)
return retval;
file->flags &= ~EXT2_FILE_BUF_VALID;
}
file->blockno = b;
return 0;
}
/*
* This function loads the file's block buffer with valid data from
* the disk as necessary.
*
* If dontfill is true, then skip initializing the buffer since we're
* going to be replacing its entire contents anyway. If set, then the
* function basically only sets file->physblock and EXT2_FILE_BUF_VALID
*/
#define DONTFILL 1
static errcode_t load_buffer(ext2_file_t file, int dontfill)
{
ext2_filsys fs = file->fs;
errcode_t retval;
if (!(file->flags & EXT2_FILE_BUF_VALID)) {
retval = ext2fs_bmap2(fs, file->ino, &file->inode,
BMAP_BUFFER, 0, file->blockno, 0,
&file->physblock);
if (retval)
return retval;
if (!dontfill) {
if (file->physblock) {
retval = io_channel_read_blk(fs->io,
file->physblock,
1, file->buf);
if (retval)
return retval;
} else
memset(file->buf, 0, fs->blocksize);
}
file->flags |= EXT2_FILE_BUF_VALID;
}
return 0;
}
errcode_t ext2fs_file_close(ext2_file_t file)
{
errcode_t retval;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
retval = ext2fs_file_flush(file);
if (file->buf)
ext2fs_free_mem(&file->buf);
ext2fs_free_mem(&file);
return retval;
}
errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
unsigned int wanted, unsigned int *got)
{
ext2_filsys fs;
errcode_t retval = 0;
unsigned int start, c, count = 0;
__u64 left;
char *ptr = (char *) buf;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
retval = sync_buffer_position(file);
if (retval)
goto fail;
retval = load_buffer(file, 0);
if (retval)
goto fail;
start = file->pos % fs->blocksize;
c = fs->blocksize - start;
if (c > wanted)
c = wanted;
left = EXT2_I_SIZE(&file->inode) - file->pos ;
if (c > left)
c = left;
memcpy(ptr, file->buf+start, c);
file->pos += c;
ptr += c;
count += c;
wanted -= c;
}
fail:
if (got)
*got = count;
return retval;
}
errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
unsigned int nbytes, unsigned int *written)
{
ext2_filsys fs;
errcode_t retval = 0;
unsigned int start, c, count = 0;
const char *ptr = (const char *) buf;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
fs = file->fs;
if (!(file->flags & EXT2_FILE_WRITE))
return EXT2_ET_FILE_RO;
while (nbytes > 0) {
retval = sync_buffer_position(file);
if (retval)
goto fail;
start = file->pos % fs->blocksize;
c = fs->blocksize - start;
if (c > nbytes)
c = nbytes;
/*
* We only need to do a read-modify-update cycle if
* we're doing a partial write.
*/
retval = load_buffer(file, (c == fs->blocksize));
if (retval)
goto fail;
file->flags |= EXT2_FILE_BUF_DIRTY;
memcpy(file->buf+start, ptr, c);
file->pos += c;
ptr += c;
count += c;
nbytes -= c;
}
// I don't see why changing size is my duty - Dimok
if(EXT2_I_SIZE(&file->inode) < file->pos)
{
file->inode.i_size = file->pos & 0xFFFFFFFF;
file->inode.i_size_high = (file->pos >> 32) & 0xFFFFFFFF;
}
fail:
if (written)
*written = count;
return retval;
}
errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
int whence, __u64 *ret_pos)
{
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
if (whence == EXT2_SEEK_SET)
file->pos = offset;
else if (whence == EXT2_SEEK_CUR)
file->pos += offset;
else if (whence == EXT2_SEEK_END)
file->pos = EXT2_I_SIZE(&file->inode) + offset;
else
return EXT2_ET_INVALID_ARGUMENT;
if (ret_pos)
*ret_pos = file->pos;
return 0;
}
errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
int whence, ext2_off_t *ret_pos)
{
__u64 loffset, ret_loffset = 0;
errcode_t retval;
loffset = offset;
retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
if (ret_pos)
*ret_pos = (ext2_off_t) ret_loffset;
return retval;
}
/*
* This function returns the size of the file, according to the inode
*/
errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
{
if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
return EXT2_ET_MAGIC_EXT2_FILE;
*ret_size = EXT2_I_SIZE(&file->inode);
return 0;
}
/*
* This function returns the size of the file, according to the inode
*/
ext2_off_t ext2fs_file_get_size(ext2_file_t file)
{
__u64 size;
if (ext2fs_file_get_lsize(file, &size))
return 0;
if ((size >> 32) != 0)
return 0;
return size;
}
/*
* This function sets the size of the file, truncating it if necessary
*
*/
errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size)
{
ext2_off64_t old_size;
errcode_t retval;
blk64_t old_truncate, truncate_block;
EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
truncate_block = ((size + file->fs->blocksize - 1) >>
EXT2_BLOCK_SIZE_BITS(file->fs->super)) + 1;
old_size = file->inode.i_size +
(((blk64_t) file->inode.i_size_high) << 32);
old_truncate = ((old_size + file->fs->blocksize - 1) >>
EXT2_BLOCK_SIZE_BITS(file->fs->super)) + 1;
file->inode.i_size = size & 0xffffffff;
file->inode.i_size_high = (size >> 32);
if (file->ino) {
retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
if (retval)
return retval;
}
if (truncate_block <= old_truncate)
return 0;
return ext2fs_punch(file->fs, file->ino, &file->inode, 0,
truncate_block, ~0ULL);
}
errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
{
return ext2fs_file_set_size2(file, size);
}