/*
ext2.c -- generic ext2 stuff
Copyright (C) 1998-2001, 2007, 2009-2010 Free Software Foundation,
Inc.
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#ifndef DISCOVER_ONLY
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ext2.h"
/* ext2 stuff ****************************************************************/
{
return 1;
}
{
int group;
int offset;
int state;
ext2_brelse(bh, 0);
return state;
}
{
int i;
{
blk_t j;
for (j=fs->adminblocks;
j++)
return offset + j;
_("Inconsistent group descriptors!"));
}
_("File system full!"));
return 0;
}
{
int i;
{
ino_t j;
return offset + j;
_("Inconsistent group descriptors!"));
}
_("File system full!"));
return 0;
}
{
unsigned char *buf;
blk_t i;
{
return 1;
}
{
for (i=0;i<num;i++)
return 0;
}
else
{
for (i=num;i>0;i--)
return 0;
}
return 1;
}
{
}
{
int group;
int offset;
if (state)
else
ext2_brelse(bh, 0);
if (updatemetadata)
{
int diff;
}
return 1;
}
{
}
{
unsigned char *buf;
blk_t i;
if (buf)
{
goto error_free_buf;
goto error_free_buf;
return 1;
}
if (buf)
{
for (i=0;i<num;i++)
{
goto error_free_buf;
goto error_free_buf;
}
return 1;
}
for (i=0;i<num;i++)
{
if (!bh)
goto error;
goto error;
}
return 1;
return 0;
}
{
int group;
int offset;
inode--;
* sizeof(struct ext2_inode);
}
{
int group;
int offset;
int ret;
inode--;
ext2_brelse(bh, 0);
return ret;
}
{
if (!bh)
return 0;
ext2_brelse(bh, 0);
return 1;
}
{
int group;
int offset;
inode--;
if (!bh)
return 0;
if (state)
else
ext2_brelse(bh, 0);
if (updatemetadata)
{
int diff;
}
return 1;
}
static void
{
/* i_blocks is in 512 byte blocks */
+ delta * i512perblock);
}
int action)
{
int i;
return -1;
switch (action)
{
case EXT2_ACTION_ADD:
block);
break;
case EXT2_ACTION_DELETE:
block);
break;
case EXT2_ACTION_FIND:
block);
break;
}
/* Direct blocks for first 12 blocks */
for (i = 0; i < EXT2_NDIR_BLOCKS; i++)
{
{
return i;
}
{
if (action == EXT2_ACTION_DELETE)
{
}
return i;
}
if (EXT2_INODE_BLOCK(*inode, i))
count += i512perblock;
}
return -1;
/* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */
for (i = 0; i < u32perblock; i++) {
ext2_brelse(bh, 0);
return EXT2_NDIR_BLOCKS + i;
}
if (action == EXT2_ACTION_DELETE) {
udata[i] = 0;
}
ext2_brelse(bh, 0);
return EXT2_NDIR_BLOCKS + i;
}
if (udata[i])
{
count += i512perblock;
return -1;
}
}
ext2_brelse(bh, 0);
return -1;
/* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */
for (i = 0; i < u32perblock; i++) {
int j;
if (!udata[i]) {
ext2_brelse(bh, 0);
return -1;
}
count += i512perblock;
for (j = 0; j < u32perblock; j++) {
ext2_brelse(bh, 0);
ext2_brelse(bh2, 0);
return EXT2_NDIR_BLOCKS + i * u32perblock + j;
}
if (action == EXT2_ACTION_DELETE) {
udata2[j] = 0;
}
ext2_brelse(bh, 0);
ext2_brelse(bh2, 0);
return EXT2_NDIR_BLOCKS + i * u32perblock + j;
}
if (udata2[j])
{
count += i512perblock;
return -1;
}
}
ext2_brelse(bh2, 0);
}
ext2_brelse(bh, 0);
/* FIXME: we should check for triple-indirect blocks here, but it
* would be nice to have a better routine to traverse blocks, and
* file systems that need triple-indirect blocks for the resize
* inode are too big to worry about yet.
*/
return -1;
}
{
if (!bh)
return 0;
ext2_brelse(bh, 0);
return 1;
}
{
}
/* check whether y is root of x
* (formula grabbed from linux ext2 kernel source) */
static int is_root(int x, int y)
{
if (!x)
return 1;
while (1)
{
if (x == 1)
return 1;
if (x % y)
return 0;
x /= y;
}
}
/* check whether group contains a superblock copy on file systems
* where not all groups have one (sparse superblock feature) */
{
return 1;
return 1;
return 0;
}
{
}
{
int i;
int num;
int sb_block;
/* See if there is even anything to write... */
if (wmeta == EXT2_META_CLEAN)
return 1;
/ 100);
return 0;
} else {
}
{
if (!ext2_is_group_sparse(fs, i))
continue;
if (fs->dynamic_version)
if ((i == 0 && wmeta & EXT2_META_PRIMARY_SB) ||
(i != 0 && wmeta & EXT2_META_SB))
{
return 0;
return 0;
}
if ((i == 0 && wmeta & EXT2_META_PRIMARY_GD) ||
(i != 0 && wmeta & EXT2_META_GD))
{
return 0;
return 0;
}
}
sb_for_io->s_block_group_nr = 0;
/* Clear the flags of the components we just finished writing. */
return 1;
}
{
if (!ext2_bcache_sync(fs)) return 0;
return 1;
}
{
== NULL)
goto error;
{
_("Invalid superblock. Are you sure this is an ext2 "
"file system?"));
goto error_free_fs;
}
fs->opt_verbose = 0;
{
if (ped_exception_throw (
_("File system has errors! You should run e2fsck."))
goto error_free_fs;
}
{
if (ped_exception_throw (
_("File system was not cleanly unmounted! "
"You should run e2fsck. Modifying an unclean "
"file system could cause severe corruption."))
goto error_free_fs;
}
{
_("File system has an incompatible feature enabled. "
"Compatible features are has_journal, dir_index, "
"filetype, sparse_super and large_file. "
"Use tune2fs or debugfs to remove features."));
goto error_free_fs;
}
if (!ext2_bcache_init(fs))
{
_("Error allocating buffer cache."));
goto error_free_fs;
}
* sizeof(struct ext2_group_desc),
* sizeof(struct ext2_inode),
= fs->has_journal
goto error_deinit_bcache;
return fs;
return NULL;
}
#endif /* !DISCOVER_ONLY */