ext2.c revision 7e7bd3dccbfe8f79e25e5c1554b5bc3a9aaca321
/*
ext2.c -- generic ext2 stuff
Copyright (C) 1998, 1999, 2000, 2001, 2007 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;
}
{
struct ext2_buffer_head *bh;
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;
}
{
}
{
struct ext2_buffer_head *bh;
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++)
{
struct ext2_buffer_head *bh;
if (!bh)
goto error;
goto error;
}
return 1;
return 0;
}
{
int group;
int offset;
inode--;
* sizeof(struct ext2_inode);
}
{
struct ext2_buffer_head *bh;
int group;
int offset;
int ret;
inode--;
ext2_brelse(bh, 0);
return ret;
}
{
struct ext2_buffer_head *bh;
if (!bh)
return 0;
ext2_brelse(bh, 0);
return 1;
}
{
struct ext2_buffer_head *bh;
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)
{
struct ext2_buffer_head *bh;
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++) {
struct ext2_buffer_head *bh2;
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;
}
{
struct ext2_buffer_head *bh;
if (!bh)
return 0;
ext2_brelse(bh, 0);
return 1;
}
{
struct ext2_inode buf;
}
/* 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;
struct ext2_super_block *sb_for_io;
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."));
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 */