1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* inode.c --- utility routines to read and write inodes
|
2008-08-28 07:07:54 +04:00
|
|
|
*
|
1997-04-29 20:17:09 +04:00
|
|
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
|
|
|
*
|
|
|
|
* %Begin-Header%
|
2010-05-18 05:31:56 +04:00
|
|
|
* This file may be redistributed under the terms of the GNU Library
|
|
|
|
* General Public License, version 2.
|
1997-04-29 20:17:09 +04:00
|
|
|
* %End-Header%
|
1997-04-26 17:21:57 +04:00
|
|
|
*/
|
|
|
|
|
2011-09-19 01:34:37 +04:00
|
|
|
#include "config.h"
|
1997-04-26 17:21:57 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
1997-08-11 03:07:40 +04:00
|
|
|
#if HAVE_UNISTD_H
|
1997-04-26 17:21:57 +04:00
|
|
|
#include <unistd.h>
|
1997-08-11 03:07:40 +04:00
|
|
|
#endif
|
2005-01-26 07:42:56 +03:00
|
|
|
#if HAVE_ERRNO_H
|
|
|
|
#include <errno.h>
|
|
|
|
#endif
|
2008-11-16 18:03:00 +03:00
|
|
|
#include <time.h>
|
1997-10-20 03:00:21 +04:00
|
|
|
#if HAVE_SYS_STAT_H
|
1997-04-26 17:21:57 +04:00
|
|
|
#include <sys/stat.h>
|
1997-10-20 03:00:21 +04:00
|
|
|
#endif
|
|
|
|
#if HAVE_SYS_TYPES_H
|
1997-04-26 17:21:57 +04:00
|
|
|
#include <sys/types.h>
|
1997-10-20 03:00:21 +04:00
|
|
|
#endif
|
1997-04-26 17:21:57 +04:00
|
|
|
|
Many files:
inode.c (ext2fs_open_inode_scan): Initialize the group variables
so that we don't need to call get_next_blockgroup() the first
time around. Saves a bit of time, and prevents us from
needing to assign -1 to current_group (which is an unsigned
value).
icount.c (insert_icount_el): Cast the estimated number of inodes
from a float to an ino_t.
alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, expanddir.c,
ext2fs.h, fileio.c, freefs.c, get_pathname.c, getsize.c,
icount.c, initialize.c, inline.c, inode.c, irel_ma.c,
ismounted.c, link.c, lookup.c, mkdir.c, namei.c, native.c,
newdir.c, openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, valid_blk.c,
version.c: If EXT2_FLAT_INCLUDES is defined, then assume all
of the ext2-specific header files are in a flat directory.
block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
all assignments from void * to be compatible with C++.
closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
make sure the contents of the disk are flushed to disk.
dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
avoid C++ namespace clash.
bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
avoid C++ namespace clash.
ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
unlink.c: Change private to be priv_data (to avoid C++
namespace clash)
1998-01-19 17:47:53 +03:00
|
|
|
#include "ext2_fs.h"
|
1997-04-29 20:17:09 +04:00
|
|
|
#include "ext2fsP.h"
|
2001-05-03 08:02:29 +04:00
|
|
|
#include "e2image.h"
|
1997-04-29 20:17:09 +04:00
|
|
|
|
2014-08-03 06:46:16 +04:00
|
|
|
#define IBLOCK_STATUS_CSUMS_OK 1
|
|
|
|
#define IBLOCK_STATUS_INSANE 2
|
|
|
|
#define SCAN_BLOCK_STATUS(scan) ((scan)->temp_buffer + (scan)->inode_size)
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
struct ext2_struct_inode_scan {
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
errcode_t magic;
|
1997-04-29 20:17:09 +04:00
|
|
|
ext2_filsys fs;
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t current_inode;
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
blk64_t current_block;
|
1997-04-29 20:17:09 +04:00
|
|
|
dgrp_t current_group;
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
ext2_ino_t inodes_left;
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
blk_t blocks_left;
|
|
|
|
dgrp_t groups_left;
|
|
|
|
blk_t inode_buffer_blocks;
|
1997-04-29 20:17:09 +04:00
|
|
|
char * inode_buffer;
|
|
|
|
int inode_size;
|
|
|
|
char * ptr;
|
|
|
|
int bytes_left;
|
|
|
|
char *temp_buffer;
|
|
|
|
errcode_t (*done_group)(ext2_filsys fs,
|
|
|
|
ext2_inode_scan scan,
|
|
|
|
dgrp_t group,
|
Many files:
inode.c (ext2fs_open_inode_scan): Initialize the group variables
so that we don't need to call get_next_blockgroup() the first
time around. Saves a bit of time, and prevents us from
needing to assign -1 to current_group (which is an unsigned
value).
icount.c (insert_icount_el): Cast the estimated number of inodes
from a float to an ino_t.
alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, expanddir.c,
ext2fs.h, fileio.c, freefs.c, get_pathname.c, getsize.c,
icount.c, initialize.c, inline.c, inode.c, irel_ma.c,
ismounted.c, link.c, lookup.c, mkdir.c, namei.c, native.c,
newdir.c, openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, valid_blk.c,
version.c: If EXT2_FLAT_INCLUDES is defined, then assume all
of the ext2-specific header files are in a flat directory.
block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
all assignments from void * to be compatible with C++.
closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
make sure the contents of the disk are flushed to disk.
dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
avoid C++ namespace clash.
bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
avoid C++ namespace clash.
ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
unlink.c: Change private to be priv_data (to avoid C++
namespace clash)
1998-01-19 17:47:53 +03:00
|
|
|
void * priv_data);
|
1997-04-29 20:17:09 +04:00
|
|
|
void * done_group_data;
|
|
|
|
int bad_block_ptr;
|
|
|
|
int scan_flags;
|
|
|
|
int reserved[6];
|
|
|
|
};
|
1997-04-26 17:21:57 +04:00
|
|
|
|
2000-11-12 22:07:06 +03:00
|
|
|
/*
|
|
|
|
* This routine flushes the icache, if it exists.
|
|
|
|
*/
|
|
|
|
errcode_t ext2fs_flush_icache(ext2_filsys fs)
|
|
|
|
{
|
|
|
|
int i;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2000-11-12 22:07:06 +03:00
|
|
|
if (!fs->icache)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i=0; i < fs->icache->cache_size; i++)
|
|
|
|
fs->icache->cache[i].ino = 0;
|
|
|
|
|
2004-12-24 05:49:05 +03:00
|
|
|
fs->icache->buffer_blk = 0;
|
2000-11-12 22:07:06 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-11-30 05:40:21 +04:00
|
|
|
/*
|
|
|
|
* Free the inode cache structure
|
|
|
|
*/
|
|
|
|
void ext2fs_free_inode_cache(struct ext2_inode_cache *icache)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (--icache->refcount)
|
|
|
|
return;
|
|
|
|
if (icache->buffer)
|
|
|
|
ext2fs_free_mem(&icache->buffer);
|
|
|
|
for (i = 0; i < icache->cache_size; i++)
|
|
|
|
ext2fs_free_mem(&icache->cache[i].inode);
|
|
|
|
if (icache->cache)
|
|
|
|
ext2fs_free_mem(&icache->cache);
|
|
|
|
icache->buffer_blk = 0;
|
|
|
|
ext2fs_free_mem(&icache);
|
|
|
|
}
|
|
|
|
|
2014-03-03 10:03:24 +04:00
|
|
|
errcode_t ext2fs_create_inode_cache(ext2_filsys fs, unsigned int cache_size)
|
1997-04-30 01:26:48 +04:00
|
|
|
{
|
2012-07-31 01:42:15 +04:00
|
|
|
int i;
|
1997-10-26 06:41:24 +03:00
|
|
|
errcode_t retval;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-30 01:26:48 +04:00
|
|
|
if (fs->icache)
|
|
|
|
return 0;
|
2003-08-01 17:41:07 +04:00
|
|
|
retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache);
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
|
1997-04-30 01:26:48 +04:00
|
|
|
memset(fs->icache, 0, sizeof(struct ext2_inode_cache));
|
2003-08-01 17:41:07 +04:00
|
|
|
retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer);
|
2012-11-30 05:40:21 +04:00
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
|
1997-04-30 01:26:48 +04:00
|
|
|
fs->icache->buffer_blk = 0;
|
|
|
|
fs->icache->cache_last = -1;
|
2014-03-03 10:03:24 +04:00
|
|
|
fs->icache->cache_size = cache_size;
|
1997-04-30 01:26:48 +04:00
|
|
|
fs->icache->refcount = 1;
|
2007-11-10 03:01:06 +03:00
|
|
|
retval = ext2fs_get_array(fs->icache->cache_size,
|
2012-11-30 05:40:21 +04:00
|
|
|
sizeof(struct ext2_inode_cache_ent),
|
2007-11-10 03:01:06 +03:00
|
|
|
&fs->icache->cache);
|
2012-11-30 05:40:21 +04:00
|
|
|
if (retval)
|
|
|
|
goto errout;
|
2012-07-31 01:42:15 +04:00
|
|
|
|
2012-11-30 05:40:21 +04:00
|
|
|
for (i = 0; i < fs->icache->cache_size; i++) {
|
|
|
|
retval = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super),
|
|
|
|
&fs->icache->cache[i].inode);
|
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
}
|
2012-07-31 01:42:15 +04:00
|
|
|
|
2000-11-12 22:07:06 +03:00
|
|
|
ext2fs_flush_icache(fs);
|
1997-04-30 01:26:48 +04:00
|
|
|
return 0;
|
2012-11-30 05:40:21 +04:00
|
|
|
errout:
|
|
|
|
ext2fs_free_inode_cache(fs->icache);
|
|
|
|
fs->icache = 0;
|
|
|
|
return retval;
|
1997-04-30 01:26:48 +04:00
|
|
|
}
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
|
|
|
|
ext2_inode_scan *ret_scan)
|
|
|
|
{
|
|
|
|
ext2_inode_scan scan;
|
1997-04-29 20:17:09 +04:00
|
|
|
errcode_t retval;
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks);
|
1997-04-26 17:21:57 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
/*
|
|
|
|
* If fs->badblocks isn't set, then set it --- since the inode
|
|
|
|
* scanning functions require it.
|
|
|
|
*/
|
|
|
|
if (fs->badblocks == 0) {
|
1997-04-29 21:48:10 +04:00
|
|
|
/*
|
|
|
|
* Temporarly save fs->get_blocks and set it to zero,
|
|
|
|
* for compatibility with old e2fsck's.
|
|
|
|
*/
|
|
|
|
save_get_blocks = fs->get_blocks;
|
|
|
|
fs->get_blocks = 0;
|
1997-04-29 20:17:09 +04:00
|
|
|
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
|
|
|
|
if (retval && fs->badblocks) {
|
ChangeLog, dumpe2fs.c, mke2fs.c:
dumpe2fs.c: Use WORDS_BIGENDIAN to determine whether or not we're
(not) using i386 byte order.
dumpe2fs.c, mke2fs.c: Stop using the compatibility badblocks function,
and use the ext2fs_badblocks_* functions instead.
ChangeLog, inode.c, tst_iscan.c:
inode.c, tst_iscan.c: Stop using the compatibility badblocks function,
and use the ext2fs_badblocks_* functions instead.
ChangeLog, badblocks.c:
badblocks.c: Stop using the compatibility badblocks function, and use
the ext2fs_badblocks_* functions instead.
2001-06-13 04:12:04 +04:00
|
|
|
ext2fs_badblocks_list_free(fs->badblocks);
|
1997-04-29 20:17:09 +04:00
|
|
|
fs->badblocks = 0;
|
|
|
|
}
|
1997-04-29 21:48:10 +04:00
|
|
|
fs->get_blocks = save_get_blocks;
|
1997-04-29 20:17:09 +04:00
|
|
|
}
|
|
|
|
|
2003-08-01 17:41:07 +04:00
|
|
|
retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan);
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval)
|
|
|
|
return retval;
|
1997-04-26 17:21:57 +04:00
|
|
|
memset(scan, 0, sizeof(struct ext2_struct_inode_scan));
|
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
|
1997-04-26 17:21:57 +04:00
|
|
|
scan->fs = fs;
|
1997-04-26 18:48:50 +04:00
|
|
|
scan->inode_size = EXT2_INODE_SIZE(fs->super);
|
|
|
|
scan->bytes_left = 0;
|
Many files:
inode.c (ext2fs_open_inode_scan): Initialize the group variables
so that we don't need to call get_next_blockgroup() the first
time around. Saves a bit of time, and prevents us from
needing to assign -1 to current_group (which is an unsigned
value).
icount.c (insert_icount_el): Cast the estimated number of inodes
from a float to an ino_t.
alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, expanddir.c,
ext2fs.h, fileio.c, freefs.c, get_pathname.c, getsize.c,
icount.c, initialize.c, inline.c, inode.c, irel_ma.c,
ismounted.c, link.c, lookup.c, mkdir.c, namei.c, native.c,
newdir.c, openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, valid_blk.c,
version.c: If EXT2_FLAT_INCLUDES is defined, then assume all
of the ext2-specific header files are in a flat directory.
block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
all assignments from void * to be compatible with C++.
closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
make sure the contents of the disk are flushed to disk.
dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
avoid C++ namespace clash.
bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
avoid C++ namespace clash.
ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
unlink.c: Change private to be priv_data (to avoid C++
namespace clash)
1998-01-19 17:47:53 +03:00
|
|
|
scan->current_group = 0;
|
|
|
|
scan->groups_left = fs->group_desc_count - 1;
|
1997-04-26 17:21:57 +04:00
|
|
|
scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
scan->current_block = ext2fs_inode_table_loc(scan->fs,
|
|
|
|
scan->current_group);
|
Many files:
inode.c (ext2fs_open_inode_scan): Initialize the group variables
so that we don't need to call get_next_blockgroup() the first
time around. Saves a bit of time, and prevents us from
needing to assign -1 to current_group (which is an unsigned
value).
icount.c (insert_icount_el): Cast the estimated number of inodes
from a float to an ino_t.
alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, expanddir.c,
ext2fs.h, fileio.c, freefs.c, get_pathname.c, getsize.c,
icount.c, initialize.c, inline.c, inode.c, irel_ma.c,
ismounted.c, link.c, lookup.c, mkdir.c, namei.c, native.c,
newdir.c, openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, valid_blk.c,
version.c: If EXT2_FLAT_INCLUDES is defined, then assume all
of the ext2-specific header files are in a flat directory.
block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
all assignments from void * to be compatible with C++.
closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
make sure the contents of the disk are flushed to disk.
dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
avoid C++ namespace clash.
bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
avoid C++ namespace clash.
ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
unlink.c: Change private to be priv_data (to avoid C++
namespace clash)
1998-01-19 17:47:53 +03:00
|
|
|
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
|
|
|
|
scan->blocks_left = scan->fs->inode_blocks_per_group;
|
2012-08-03 04:47:45 +04:00
|
|
|
if (ext2fs_has_group_desc_csum(fs)) {
|
2008-04-23 07:22:17 +04:00
|
|
|
scan->inodes_left -=
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
ext2fs_bg_itable_unused(fs, scan->current_group);
|
2008-04-23 07:22:17 +04:00
|
|
|
scan->blocks_left =
|
|
|
|
(scan->inodes_left +
|
|
|
|
(fs->blocksize / scan->inode_size - 1)) *
|
|
|
|
scan->inode_size / fs->blocksize;
|
|
|
|
}
|
2012-05-07 22:41:49 +04:00
|
|
|
retval = io_channel_alloc_buf(fs->io, scan->inode_buffer_blocks,
|
|
|
|
&scan->inode_buffer);
|
1997-04-26 17:34:30 +04:00
|
|
|
scan->done_group = 0;
|
|
|
|
scan->done_group_data = 0;
|
1997-04-29 20:17:09 +04:00
|
|
|
scan->bad_block_ptr = 0;
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval) {
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&scan);
|
1997-10-26 06:41:24 +03:00
|
|
|
return retval;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2014-08-03 06:46:16 +04:00
|
|
|
retval = ext2fs_get_mem(scan->inode_size + scan->inode_buffer_blocks,
|
|
|
|
&scan->temp_buffer);
|
1997-10-26 06:41:24 +03:00
|
|
|
if (retval) {
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&scan->inode_buffer);
|
|
|
|
ext2fs_free_mem(&scan);
|
1997-10-26 06:41:24 +03:00
|
|
|
return retval;
|
1997-04-26 18:48:50 +04:00
|
|
|
}
|
2014-08-03 06:46:16 +04:00
|
|
|
memset(SCAN_BLOCK_STATUS(scan), 0, scan->inode_buffer_blocks);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (scan->fs->badblocks && scan->fs->badblocks->num)
|
|
|
|
scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
|
2012-08-03 04:47:45 +04:00
|
|
|
if (ext2fs_has_group_desc_csum(fs))
|
2007-10-22 06:03:25 +04:00
|
|
|
scan->scan_flags |= EXT2_SF_DO_LAZY;
|
1997-04-26 17:21:57 +04:00
|
|
|
*ret_scan = scan;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ext2fs_close_inode_scan(ext2_inode_scan scan)
|
|
|
|
{
|
1997-04-26 17:34:30 +04:00
|
|
|
if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
|
|
|
|
return;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&scan->inode_buffer);
|
1997-04-26 17:21:57 +04:00
|
|
|
scan->inode_buffer = NULL;
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&scan->temp_buffer);
|
1997-04-26 18:48:50 +04:00
|
|
|
scan->temp_buffer = NULL;
|
2003-08-01 17:41:07 +04:00
|
|
|
ext2fs_free_mem(&scan);
|
1997-04-26 17:21:57 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
void ext2fs_set_inode_callback(ext2_inode_scan scan,
|
|
|
|
errcode_t (*done_group)(ext2_filsys fs,
|
|
|
|
ext2_inode_scan scan,
|
|
|
|
dgrp_t group,
|
Many files:
inode.c (ext2fs_open_inode_scan): Initialize the group variables
so that we don't need to call get_next_blockgroup() the first
time around. Saves a bit of time, and prevents us from
needing to assign -1 to current_group (which is an unsigned
value).
icount.c (insert_icount_el): Cast the estimated number of inodes
from a float to an ino_t.
alloc.c, alloc_tables.c, badlbocks.c, bb_compat.c, bb_inode.c,
bitmaps.c, bitops.c, block.c, bmap.c, bmove.c, brel_ma.c,
check_desc.c, closefs.c, cmp_bitmaps.c, dblist.c,
dblist_dir.c, dir_iterate.c, dirblock.c, dupfs.c, expanddir.c,
ext2fs.h, fileio.c, freefs.c, get_pathname.c, getsize.c,
icount.c, initialize.c, inline.c, inode.c, irel_ma.c,
ismounted.c, link.c, lookup.c, mkdir.c, namei.c, native.c,
newdir.c, openfs.c, read_bb.c, read_bb_file.c, rs_bitmap.c,
rw_bitmaps.c, swapfs.c, test_io.c, tst_badblocks.c,
tst_getsize.c, tst_iscan.c, unix_io.c, unlink.c, valid_blk.c,
version.c: If EXT2_FLAT_INCLUDES is defined, then assume all
of the ext2-specific header files are in a flat directory.
block.c, bmove.c, dirblock.c, fileio.c: Explicitly cast
all assignments from void * to be compatible with C++.
closefs.c (ext2fs_flush): Add a call to io_channel_flush() to
make sure the contents of the disk are flushed to disk.
dblist.c (ext2fs_add_dir_block): Change new to be new_entry to
avoid C++ namespace clash.
bitmaps.c (ext2fs_copy_bitmap): Change new to be new_map to
avoid C++ namespace clash.
ext2fs.h, bb_inode.c, block.c, bmove.c, brel.h, brel_ma.c,
irel.h, irel_ma.c, dblist.c, dblist_dir.c, dir_iterate.c,
ext2fsP.h, expanddir.c, get_pathname.c, inode.c, link.c,
unlink.c: Change private to be priv_data (to avoid C++
namespace clash)
1998-01-19 17:47:53 +03:00
|
|
|
void * priv_data),
|
1997-04-26 17:34:30 +04:00
|
|
|
void *done_group_data)
|
|
|
|
{
|
|
|
|
if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
|
|
|
|
return;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
scan->done_group = done_group;
|
|
|
|
scan->done_group_data = done_group_data;
|
|
|
|
}
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
|
|
|
|
int clear_flags)
|
|
|
|
{
|
|
|
|
int old_flags;
|
|
|
|
|
|
|
|
if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
old_flags = scan->scan_flags;
|
|
|
|
scan->scan_flags &= ~clear_flags;
|
|
|
|
scan->scan_flags |= set_flags;
|
|
|
|
return old_flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is called by ext2fs_get_next_inode when it needs to
|
|
|
|
* get ready to read in a new blockgroup.
|
|
|
|
*/
|
|
|
|
static errcode_t get_next_blockgroup(ext2_inode_scan scan)
|
|
|
|
{
|
2007-10-22 06:03:25 +04:00
|
|
|
ext2_filsys fs = scan->fs;
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
scan->current_group++;
|
|
|
|
scan->groups_left--;
|
2007-10-22 06:03:25 +04:00
|
|
|
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
scan->current_block = ext2fs_inode_table_loc(scan->fs,
|
|
|
|
scan->current_group);
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
scan->current_inode = scan->current_group *
|
2007-10-22 06:03:25 +04:00
|
|
|
EXT2_INODES_PER_GROUP(fs->super);
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
scan->bytes_left = 0;
|
2007-10-22 06:03:25 +04:00
|
|
|
scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super);
|
|
|
|
scan->blocks_left = fs->inode_blocks_per_group;
|
2012-08-03 04:47:45 +04:00
|
|
|
if (ext2fs_has_group_desc_csum(fs)) {
|
2007-10-22 06:03:25 +04:00
|
|
|
scan->inodes_left -=
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
ext2fs_bg_itable_unused(fs, scan->current_group);
|
2007-10-22 06:03:25 +04:00
|
|
|
scan->blocks_left =
|
2008-03-31 18:57:38 +04:00
|
|
|
(scan->inodes_left +
|
|
|
|
(fs->blocksize / scan->inode_size - 1)) *
|
2007-10-22 06:03:25 +04:00
|
|
|
scan->inode_size / fs->blocksize;
|
|
|
|
}
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
|
|
|
|
int group)
|
|
|
|
{
|
|
|
|
scan->current_group = group - 1;
|
|
|
|
scan->groups_left = scan->fs->group_desc_count - group;
|
|
|
|
return get_next_blockgroup(scan);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function is called by get_next_blocks() to check for bad
|
|
|
|
* blocks in the inode table.
|
|
|
|
*
|
|
|
|
* This function assumes that badblocks_list->list is sorted in
|
|
|
|
* increasing order.
|
|
|
|
*/
|
|
|
|
static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
|
2013-10-07 17:51:48 +04:00
|
|
|
blk64_t *num_blocks)
|
1997-04-29 20:17:09 +04:00
|
|
|
{
|
2013-10-07 17:51:48 +04:00
|
|
|
blk64_t blk = scan->current_block;
|
1997-04-29 20:17:09 +04:00
|
|
|
badblocks_list bb = scan->fs->badblocks;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the inode table is missing, then obviously there are no
|
|
|
|
* bad blocks. :-)
|
|
|
|
*/
|
|
|
|
if (blk == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the current block is greater than the bad block listed
|
|
|
|
* in the bad block list, then advance the pointer until this
|
|
|
|
* is no longer the case. If we run out of bad blocks, then
|
|
|
|
* we don't need to do any more checking!
|
|
|
|
*/
|
|
|
|
while (blk > bb->list[scan->bad_block_ptr]) {
|
|
|
|
if (++scan->bad_block_ptr >= bb->num) {
|
|
|
|
scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the current block is equal to the bad block listed in
|
|
|
|
* the bad block list, then handle that one block specially.
|
|
|
|
* (We could try to handle runs of bad blocks, but that
|
|
|
|
* only increases CPU efficiency by a small amount, at the
|
|
|
|
* expense of a huge expense of code complexity, and for an
|
|
|
|
* uncommon case at that.)
|
|
|
|
*/
|
|
|
|
if (blk == bb->list[scan->bad_block_ptr]) {
|
|
|
|
scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
|
|
|
|
*num_blocks = 1;
|
|
|
|
if (++scan->bad_block_ptr >= bb->num)
|
|
|
|
scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there is a bad block in the range that we're about to
|
|
|
|
* read in, adjust the number of blocks to read so that we we
|
|
|
|
* don't read in the bad block. (Then the next block to read
|
|
|
|
* will be the bad block, which is handled in the above case.)
|
|
|
|
*/
|
|
|
|
if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
*num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk);
|
1997-04-29 20:17:09 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-03 06:46:16 +04:00
|
|
|
static int block_map_looks_insane(ext2_filsys fs,
|
|
|
|
struct ext2_inode_large *inode)
|
|
|
|
{
|
|
|
|
unsigned int i, bad;
|
|
|
|
|
|
|
|
/* We're only interested in block mapped files, dirs, and symlinks */
|
|
|
|
if ((inode->i_flags & EXT4_INLINE_DATA_FL) ||
|
|
|
|
(inode->i_flags & EXT4_EXTENTS_FL))
|
|
|
|
return 0;
|
|
|
|
if (!LINUX_S_ISREG(inode->i_mode) &&
|
|
|
|
!LINUX_S_ISLNK(inode->i_mode) &&
|
|
|
|
!LINUX_S_ISDIR(inode->i_mode))
|
|
|
|
return 0;
|
|
|
|
if (LINUX_S_ISLNK(inode->i_mode) &&
|
|
|
|
EXT2_I_SIZE(inode) <= sizeof(inode->i_block))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Unused inodes probably aren't insane */
|
|
|
|
if (inode->i_links_count == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* See if more than half the block maps are insane */
|
|
|
|
for (i = 0, bad = 0; i < EXT2_N_BLOCKS; i++)
|
|
|
|
if (inode->i_block[i] != 0 &&
|
|
|
|
(inode->i_block[i] < fs->super->s_first_data_block ||
|
|
|
|
inode->i_block[i] >= ext2fs_blocks_count(fs->super)))
|
|
|
|
bad++;
|
|
|
|
return bad > EXT2_N_BLOCKS / 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extent_head_looks_insane(struct ext2_inode_large *inode)
|
|
|
|
{
|
|
|
|
if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
|
|
|
|
ext2fs_extent_header_verify(inode->i_block,
|
|
|
|
sizeof(inode->i_block)) == 0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check all the inodes that we just read into the buffer. Record what we
|
|
|
|
* find here -- currently, we can observe that all checksums are ok; more
|
|
|
|
* than half the inodes are insane; or no conclusions at all.
|
|
|
|
*/
|
|
|
|
static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks)
|
|
|
|
{
|
|
|
|
ext2_ino_t ino, inodes_to_scan;
|
|
|
|
unsigned int badness, checksum_failures;
|
|
|
|
unsigned int inodes_in_buf, inodes_per_block;
|
|
|
|
void *p;
|
|
|
|
struct ext2_inode_large *inode;
|
|
|
|
char *block_status;
|
2014-08-25 06:00:56 +04:00
|
|
|
unsigned int blk, bad_csum;
|
2014-08-03 06:46:16 +04:00
|
|
|
|
|
|
|
if (!(scan->scan_flags & EXT2_SF_WARN_GARBAGE_INODES))
|
|
|
|
return;
|
|
|
|
|
|
|
|
inodes_to_scan = scan->inodes_left;
|
|
|
|
inodes_in_buf = num_blocks * scan->fs->blocksize / scan->inode_size;
|
|
|
|
if (inodes_to_scan > inodes_in_buf)
|
|
|
|
inodes_to_scan = inodes_in_buf;
|
|
|
|
|
|
|
|
p = scan->inode_buffer;
|
|
|
|
ino = scan->current_inode + 1;
|
|
|
|
checksum_failures = badness = 0;
|
|
|
|
block_status = SCAN_BLOCK_STATUS(scan);
|
|
|
|
memset(block_status, 0, scan->inode_buffer_blocks);
|
|
|
|
inodes_per_block = EXT2_INODES_PER_BLOCK(scan->fs->super);
|
|
|
|
|
2014-12-03 06:17:10 +03:00
|
|
|
if (inodes_per_block < 2)
|
|
|
|
return;
|
|
|
|
|
2014-08-25 06:00:56 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
if (ext2fs_get_mem(EXT2_INODE_SIZE(scan->fs->super), &inode))
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
2014-08-03 06:46:16 +04:00
|
|
|
while (inodes_to_scan > 0) {
|
|
|
|
blk = (p - (void *)scan->inode_buffer) / scan->fs->blocksize;
|
2014-08-25 06:00:56 +04:00
|
|
|
bad_csum = ext2fs_inode_csum_verify(scan->fs, ino, p) == 0;
|
|
|
|
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
ext2fs_swap_inode_full(scan->fs,
|
|
|
|
(struct ext2_inode_large *) inode,
|
|
|
|
(struct ext2_inode_large *) p,
|
|
|
|
0, EXT2_INODE_SIZE(scan->fs->super));
|
|
|
|
#else
|
2014-08-03 06:46:16 +04:00
|
|
|
inode = p;
|
2014-08-25 06:00:56 +04:00
|
|
|
#endif
|
2014-08-03 06:46:16 +04:00
|
|
|
|
|
|
|
/* Is this inode insane? */
|
2014-08-25 06:00:56 +04:00
|
|
|
if (bad_csum) {
|
2014-08-03 06:46:16 +04:00
|
|
|
checksum_failures++;
|
|
|
|
badness++;
|
|
|
|
} else if (extent_head_looks_insane(inode) ||
|
|
|
|
block_map_looks_insane(scan->fs, inode))
|
|
|
|
badness++;
|
|
|
|
|
|
|
|
/* If more than half are insane, declare the whole block bad */
|
|
|
|
if (badness > inodes_per_block / 2) {
|
|
|
|
unsigned int ino_adj;
|
|
|
|
|
|
|
|
block_status[blk] |= IBLOCK_STATUS_INSANE;
|
|
|
|
ino_adj = inodes_per_block -
|
|
|
|
((ino - 1) % inodes_per_block);
|
|
|
|
if (ino_adj > inodes_to_scan)
|
|
|
|
ino_adj = inodes_to_scan;
|
|
|
|
inodes_to_scan -= ino_adj;
|
|
|
|
p += scan->inode_size * ino_adj;
|
|
|
|
ino += ino_adj;
|
|
|
|
checksum_failures = badness = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ino % inodes_per_block) == 0) {
|
|
|
|
if (checksum_failures == 0)
|
|
|
|
block_status[blk] |= IBLOCK_STATUS_CSUMS_OK;
|
|
|
|
checksum_failures = badness = 0;
|
|
|
|
}
|
|
|
|
inodes_to_scan--;
|
|
|
|
p += scan->inode_size;
|
|
|
|
ino++;
|
|
|
|
};
|
2014-08-25 06:00:56 +04:00
|
|
|
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
ext2fs_free_mem(&inode);
|
|
|
|
#endif
|
2014-08-03 06:46:16 +04:00
|
|
|
}
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
/*
|
|
|
|
* This function is called by ext2fs_get_next_inode when it needs to
|
|
|
|
* read in more blocks from the current blockgroup's inode table.
|
|
|
|
*/
|
|
|
|
static errcode_t get_next_blocks(ext2_inode_scan scan)
|
|
|
|
{
|
2013-10-07 17:51:48 +04:00
|
|
|
blk64_t num_blocks;
|
1997-04-29 20:17:09 +04:00
|
|
|
errcode_t retval;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Figure out how many blocks to read; we read at most
|
|
|
|
* inode_buffer_blocks, and perhaps less if there aren't that
|
|
|
|
* many blocks left to read.
|
|
|
|
*/
|
|
|
|
num_blocks = scan->inode_buffer_blocks;
|
|
|
|
if (num_blocks > scan->blocks_left)
|
|
|
|
num_blocks = scan->blocks_left;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the past block "read" was a bad block, then mark the
|
|
|
|
* left-over extra bytes as also being bad.
|
|
|
|
*/
|
|
|
|
if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
|
|
|
|
if (scan->bytes_left)
|
|
|
|
scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
|
|
|
|
scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do inode bad block processing, if necessary.
|
|
|
|
*/
|
|
|
|
if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
|
|
|
|
retval = check_for_inode_bad_blocks(scan, &num_blocks);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
|
|
|
|
(scan->current_block == 0)) {
|
|
|
|
memset(scan->inode_buffer, 0,
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
(size_t) num_blocks * scan->fs->blocksize);
|
1997-04-29 20:17:09 +04:00
|
|
|
} else {
|
2009-09-08 05:14:24 +04:00
|
|
|
retval = io_channel_read_blk64(scan->fs->io,
|
1997-04-29 20:17:09 +04:00
|
|
|
scan->current_block,
|
Many files:
dosio.c: New file to do DOS/BIOS disk accesses.
namei.c (open_namei): Make pathlen be of type size_t.
llseek.c: Always #include stdlib.h since it's need to define
size_t.
io.h: Use errcode_t for magic numbers.
icount.c (get_icount_el), dupfs.c (ext2fs_dup_handle), dblist.c
(dir_block_cmp): Use size_t where appropriate.
read_bb.c (ext2fs_read_bb_inode), cmp_bitmaps.c
(ext2fs_compare_inode_bitmap): Use blk_t, ino_t and size_t
where appropriate.
closefs.c (ext2fs_flush): Use dgrp_t instead of int where
appropriate.
openfs.c (ext2fs_open), check_desc.c (ext2fs_check_desc): Use blk_t
instead of int where appropriate.
rw_bitmaps.c (read_bitmaps), irel_ma.c, inode.c (ext2fs_write_inode),
initialize.c (ext2fs_initialize): brel_ma.c: Fix to make be
16-bit safe.
link.c (ext2fs_link), unlink.c (ext2fs_unlink), lookup.c (lookup_proc),
ismounted.c (ext2fs_check_if_mounted), block.c (xlate_func):
Add #pragma argsused for Turbo C.
1997-08-12 00:29:22 +04:00
|
|
|
(int) num_blocks,
|
|
|
|
scan->inode_buffer);
|
1997-04-29 20:17:09 +04:00
|
|
|
if (retval)
|
|
|
|
return EXT2_ET_NEXT_INODE_READ;
|
|
|
|
}
|
2014-08-03 06:46:16 +04:00
|
|
|
check_inode_block_sanity(scan, num_blocks);
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
scan->ptr = scan->inode_buffer;
|
|
|
|
scan->bytes_left = num_blocks * scan->fs->blocksize;
|
|
|
|
|
|
|
|
scan->blocks_left -= num_blocks;
|
|
|
|
if (scan->current_block)
|
|
|
|
scan->current_block += num_blocks;
|
2014-08-03 06:46:16 +04:00
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* Returns 1 if the entire inode_buffer has a non-zero size and
|
|
|
|
* contains all zeros. (Not just deleted inodes, since that means
|
|
|
|
* that part of the inode table was used at one point; we want all
|
|
|
|
* zeros, which means that the inode table is pristine.)
|
|
|
|
*/
|
|
|
|
static inline int is_empty_scan(ext2_inode_scan scan)
|
|
|
|
{
|
|
|
|
int i;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
if (scan->bytes_left == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i=0; i < scan->bytes_left; i++)
|
|
|
|
if (scan->ptr[i])
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-01-26 07:42:56 +03:00
|
|
|
errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino,
|
|
|
|
struct ext2_inode *inode, int bufsize)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
errcode_t retval;
|
1997-04-26 18:48:50 +04:00
|
|
|
int extra_bytes = 0;
|
2014-08-03 06:46:16 +04:00
|
|
|
int length;
|
2012-07-31 02:46:04 +04:00
|
|
|
struct ext2_inode_large *iptr = (struct ext2_inode_large *)inode;
|
2014-08-03 06:46:16 +04:00
|
|
|
char *iblock_status;
|
|
|
|
unsigned int iblk;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
|
2014-08-03 06:46:16 +04:00
|
|
|
length = EXT2_INODE_SIZE(scan->fs->super);
|
|
|
|
iblock_status = SCAN_BLOCK_STATUS(scan);
|
1997-04-26 17:34:30 +04:00
|
|
|
|
1997-04-26 18:48:50 +04:00
|
|
|
/*
|
|
|
|
* Do we need to start reading a new block group?
|
|
|
|
*/
|
1997-04-26 17:21:57 +04:00
|
|
|
if (scan->inodes_left <= 0) {
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
force_new_group:
|
1997-04-26 18:48:50 +04:00
|
|
|
if (scan->done_group) {
|
|
|
|
retval = (scan->done_group)
|
1997-04-29 20:17:09 +04:00
|
|
|
(scan->fs, scan, scan->current_group,
|
1997-04-26 18:48:50 +04:00
|
|
|
scan->done_group_data);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
if (scan->groups_left <= 0) {
|
|
|
|
*ino = 0;
|
|
|
|
return 0;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
1997-04-29 20:17:09 +04:00
|
|
|
retval = get_next_blockgroup(scan);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
1997-04-26 18:48:50 +04:00
|
|
|
}
|
1998-02-21 04:41:39 +03:00
|
|
|
/*
|
2008-08-28 07:07:54 +04:00
|
|
|
* These checks are done outside the above if statement so
|
2006-05-09 04:17:26 +04:00
|
|
|
* they can be done for block group #0.
|
1998-02-21 04:41:39 +03:00
|
|
|
*/
|
2006-05-09 04:17:26 +04:00
|
|
|
if ((scan->scan_flags & EXT2_SF_DO_LAZY) &&
|
2009-10-26 04:42:12 +03:00
|
|
|
(ext2fs_bg_flags_test(scan->fs, scan->current_group, EXT2_BG_INODE_UNINIT)
|
2009-09-08 05:15:12 +04:00
|
|
|
))
|
2006-05-09 04:17:26 +04:00
|
|
|
goto force_new_group;
|
2007-10-22 06:03:25 +04:00
|
|
|
if (scan->inodes_left == 0)
|
|
|
|
goto force_new_group;
|
1998-02-21 04:41:39 +03:00
|
|
|
if (scan->current_block == 0) {
|
|
|
|
if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
goto force_new_group;
|
1998-02-21 04:41:39 +03:00
|
|
|
} else
|
|
|
|
return EXT2_ET_MISSING_INODE_TABLE;
|
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 18:48:50 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Have we run out of space in the inode buffer? If so, we
|
|
|
|
* need to read in more blocks.
|
|
|
|
*/
|
|
|
|
if (scan->bytes_left < scan->inode_size) {
|
|
|
|
memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
|
|
|
|
extra_bytes = scan->bytes_left;
|
1997-04-29 20:17:09 +04:00
|
|
|
|
|
|
|
retval = get_next_blocks(scan);
|
1997-04-26 17:21:57 +04:00
|
|
|
if (retval)
|
1997-04-29 20:17:09 +04:00
|
|
|
return retval;
|
ChangeLog, debugfs.8.in, debugfs.c:
Add a -V option which displays the current version.
ChangeLog, unix.c:
unix.c (e2fsck_update_progress): Remove unused variables.
ChangeLog, inode.c:
inode.c (get_next_blockgroup): Fix bug where if get_next_blockgroup()
is called early because of a missing inode table in a block group, the
current_inode counter wasn't incremented correctly.
ChangeLog, tst_uuid.c:
tst_uuid.c (main): Fixed bogus declaration of the main's argv parameter.
ChangeLog, test_icount.c:
test_icount.c (main): Fix main() declaration so that it returns int,
not void.
Many files:
fsck.c (ignore): Remove unused variable cp.
chattr.c (fatal_error):
tune2fs.c (usage):
lsattr.c (usage):
dumpe2fs.c (usage):
badblocks.c (usage): Remove volatile from declaration.
fsck.c: Change use of strdup to be string_copy, since we don't trust
what glibc is doing with strdup. (Whatever it is, it isn't pretty.)
1998-06-27 09:11:14 +04:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* XXX test Need check for used inode somehow.
|
|
|
|
* (Note: this is hard.)
|
|
|
|
*/
|
|
|
|
if (is_empty_scan(scan))
|
|
|
|
goto force_new_group;
|
|
|
|
#endif
|
1997-04-26 18:48:50 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 01:42:15 +04:00
|
|
|
if (bufsize < length) {
|
|
|
|
retval = ext2fs_get_mem(length, &iptr);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
1997-04-29 20:17:09 +04:00
|
|
|
retval = 0;
|
2014-08-03 06:46:16 +04:00
|
|
|
iblk = scan->current_inode % EXT2_INODES_PER_GROUP(scan->fs->super) /
|
|
|
|
EXT2_INODES_PER_BLOCK(scan->fs->super) %
|
|
|
|
scan->inode_buffer_blocks;
|
1997-04-26 18:48:50 +04:00
|
|
|
if (extra_bytes) {
|
|
|
|
memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
|
|
|
|
scan->inode_size - extra_bytes);
|
|
|
|
scan->ptr += scan->inode_size - extra_bytes;
|
|
|
|
scan->bytes_left -= scan->inode_size - extra_bytes;
|
|
|
|
|
2012-07-31 02:46:04 +04:00
|
|
|
/* Verify the inode checksum. */
|
2014-08-03 06:46:16 +04:00
|
|
|
if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) &&
|
|
|
|
!(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
|
2012-07-31 02:46:04 +04:00
|
|
|
!ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
|
|
|
|
(struct ext2_inode_large *)scan->temp_buffer))
|
|
|
|
retval = EXT2_ET_INODE_CSUM_INVALID;
|
|
|
|
|
2007-08-11 09:56:48 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2012-07-31 01:42:15 +04:00
|
|
|
memset(iptr, 0, length);
|
2008-08-28 07:07:54 +04:00
|
|
|
ext2fs_swap_inode_full(scan->fs,
|
2012-07-31 01:42:15 +04:00
|
|
|
(struct ext2_inode_large *) iptr,
|
2008-08-28 07:07:54 +04:00
|
|
|
(struct ext2_inode_large *) scan->temp_buffer,
|
2012-07-31 01:42:15 +04:00
|
|
|
0, length);
|
2007-08-11 09:56:48 +04:00
|
|
|
#else
|
2012-07-31 01:42:15 +04:00
|
|
|
memcpy(iptr, scan->temp_buffer, length);
|
ChangeLog, Makefile.in, swapfs.c, unix.c:
Makefile.in: Add message.c and swapfs.c to the list of source files to
build the make depend.
swapfs.c, unix.c: Only support the -s and -S options to e2fsck if
ENABLE_SWAPFS is defined.
Many files:
ext2fs.h, bitops.h, block.c, bmap.c, closefs.c, dirblock.c, inode.c,
native.c, openfs.c, rw_bitmaps.c, swapfs.c: Only include the
byte-swapping logic if ENABLE_SWAPFS is turned on or if we're on a
big-endian machine.
initialize.c (ext2fs_initialize):Use WORDS_BIGENDIAN directly to set
EXT2_FLAG_SWAP_BYTES, instead of using ext2fs_native_flag.
native.c (ext2fs_native_flag): Use WORDS_BIGENDIAN provided by
autoconf to determine whether or not return EXT2_FLAG_SWAP_BYTES.
2001-06-11 11:00:04 +04:00
|
|
|
#endif
|
1997-04-29 20:17:09 +04:00
|
|
|
if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
|
|
|
|
retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
|
|
|
|
scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
|
1997-04-26 18:48:50 +04:00
|
|
|
} else {
|
2012-07-31 02:46:04 +04:00
|
|
|
/* Verify the inode checksum. */
|
2014-08-03 06:46:16 +04:00
|
|
|
if (!(iblock_status[iblk] & IBLOCK_STATUS_CSUMS_OK) &&
|
|
|
|
!(scan->fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
|
2012-07-31 02:46:04 +04:00
|
|
|
!ext2fs_inode_csum_verify(scan->fs, scan->current_inode + 1,
|
|
|
|
(struct ext2_inode_large *)scan->ptr))
|
|
|
|
retval = EXT2_ET_INODE_CSUM_INVALID;
|
|
|
|
|
2007-08-11 09:56:48 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2012-07-31 01:42:15 +04:00
|
|
|
memset(iptr, 0, length);
|
2008-08-28 07:07:54 +04:00
|
|
|
ext2fs_swap_inode_full(scan->fs,
|
2012-07-31 01:42:15 +04:00
|
|
|
(struct ext2_inode_large *) iptr,
|
2005-01-26 07:42:56 +03:00
|
|
|
(struct ext2_inode_large *) scan->ptr,
|
2012-07-31 01:42:15 +04:00
|
|
|
0, length);
|
2007-08-11 09:56:48 +04:00
|
|
|
#else
|
2012-07-31 01:42:15 +04:00
|
|
|
memcpy(iptr, scan->ptr, length);
|
ChangeLog, Makefile.in, swapfs.c, unix.c:
Makefile.in: Add message.c and swapfs.c to the list of source files to
build the make depend.
swapfs.c, unix.c: Only support the -s and -S options to e2fsck if
ENABLE_SWAPFS is defined.
Many files:
ext2fs.h, bitops.h, block.c, bmap.c, closefs.c, dirblock.c, inode.c,
native.c, openfs.c, rw_bitmaps.c, swapfs.c: Only include the
byte-swapping logic if ENABLE_SWAPFS is turned on or if we're on a
big-endian machine.
initialize.c (ext2fs_initialize):Use WORDS_BIGENDIAN directly to set
EXT2_FLAG_SWAP_BYTES, instead of using ext2fs_native_flag.
native.c (ext2fs_native_flag): Use WORDS_BIGENDIAN provided by
autoconf to determine whether or not return EXT2_FLAG_SWAP_BYTES.
2001-06-11 11:00:04 +04:00
|
|
|
#endif
|
1997-04-26 18:48:50 +04:00
|
|
|
scan->ptr += scan->inode_size;
|
|
|
|
scan->bytes_left -= scan->inode_size;
|
1997-04-29 20:17:09 +04:00
|
|
|
if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
|
|
|
|
retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
2014-08-03 06:46:16 +04:00
|
|
|
if ((iblock_status[iblk] & IBLOCK_STATUS_INSANE) &&
|
|
|
|
(retval == 0 || retval == EXT2_ET_INODE_CSUM_INVALID))
|
|
|
|
retval = EXT2_ET_INODE_IS_GARBAGE;
|
1997-04-26 17:58:21 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
scan->inodes_left--;
|
|
|
|
scan->current_inode++;
|
|
|
|
*ino = scan->current_inode;
|
2012-07-31 02:46:04 +04:00
|
|
|
if (iptr != (struct ext2_inode_large *)inode) {
|
2012-07-31 01:42:15 +04:00
|
|
|
memcpy(inode, iptr, bufsize);
|
|
|
|
ext2fs_free_mem(&iptr);
|
|
|
|
}
|
1997-04-29 20:17:09 +04:00
|
|
|
return retval;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2005-01-26 07:42:56 +03:00
|
|
|
errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino,
|
|
|
|
struct ext2_inode *inode)
|
|
|
|
{
|
|
|
|
return ext2fs_get_next_inode_full(scan, ino, inode,
|
|
|
|
sizeof(struct ext2_inode));
|
|
|
|
}
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Functions to read and write a single inode.
|
|
|
|
*/
|
2005-01-26 07:42:56 +03:00
|
|
|
errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
|
|
|
struct ext2_inode * inode, int bufsize)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2011-07-06 04:02:27 +04:00
|
|
|
blk64_t block_nr;
|
|
|
|
unsigned long group, block, offset;
|
1997-04-26 18:48:50 +04:00
|
|
|
char *ptr;
|
1997-04-26 17:21:57 +04:00
|
|
|
errcode_t retval;
|
2012-07-31 01:42:15 +04:00
|
|
|
int clen, i, inodes_per_block;
|
2004-07-29 05:11:48 +04:00
|
|
|
io_channel io;
|
2012-07-31 01:42:15 +04:00
|
|
|
int length = EXT2_INODE_SIZE(fs->super);
|
2012-07-31 02:46:04 +04:00
|
|
|
struct ext2_inode_large *iptr;
|
2014-08-03 06:49:12 +04:00
|
|
|
int cache_slot, fail_csum;
|
1997-04-26 17:21:57 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
|
|
|
|
1997-04-29 18:53:37 +04:00
|
|
|
/* Check to see if user has an override function */
|
2013-04-22 07:53:26 +04:00
|
|
|
if (fs->read_inode &&
|
|
|
|
((bufsize == sizeof(struct ext2_inode)) ||
|
|
|
|
(EXT2_INODE_SIZE(fs->super) == sizeof(struct ext2_inode)))) {
|
1997-04-29 18:53:37 +04:00
|
|
|
retval = (fs->read_inode)(fs, ino, inode);
|
|
|
|
if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
|
|
|
|
return retval;
|
|
|
|
}
|
2008-07-15 19:10:19 +04:00
|
|
|
if ((ino == 0) || (ino > fs->super->s_inodes_count))
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
1997-04-30 01:26:48 +04:00
|
|
|
/* Create inode cache if not present */
|
|
|
|
if (!fs->icache) {
|
2014-03-03 10:03:24 +04:00
|
|
|
retval = ext2fs_create_inode_cache(fs, 4);
|
1997-04-30 01:26:48 +04:00
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
}
|
1997-04-29 18:53:37 +04:00
|
|
|
/* Check to see if it's in the inode cache */
|
2012-07-31 01:42:15 +04:00
|
|
|
for (i = 0; i < fs->icache->cache_size; i++) {
|
|
|
|
if (fs->icache->cache[i].ino == ino) {
|
2012-11-17 22:37:45 +04:00
|
|
|
memcpy(inode, fs->icache->cache[i].inode,
|
|
|
|
(bufsize > length) ? length : bufsize);
|
2012-07-31 01:42:15 +04:00
|
|
|
return 0;
|
1997-04-29 18:53:37 +04:00
|
|
|
}
|
|
|
|
}
|
2001-05-03 08:02:29 +04:00
|
|
|
if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
|
|
|
|
inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
|
|
|
|
block_nr = fs->image_header->offset_inode / fs->blocksize;
|
|
|
|
block_nr += (ino - 1) / inodes_per_block;
|
|
|
|
offset = ((ino - 1) % inodes_per_block) *
|
|
|
|
EXT2_INODE_SIZE(fs->super);
|
2004-07-29 05:11:48 +04:00
|
|
|
io = fs->image_io;
|
2001-05-03 08:02:29 +04:00
|
|
|
} else {
|
|
|
|
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
|
2009-01-20 07:09:37 +03:00
|
|
|
if (group > fs->group_desc_count)
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
2001-05-03 08:02:29 +04:00
|
|
|
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
|
|
|
|
EXT2_INODE_SIZE(fs->super);
|
|
|
|
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
if (!ext2fs_inode_table_loc(fs, (unsigned) group))
|
2001-05-03 08:02:29 +04:00
|
|
|
return EXT2_ET_MISSING_INODE_TABLE;
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
block_nr = ext2fs_inode_table_loc(fs, group) +
|
2001-05-03 08:02:29 +04:00
|
|
|
block;
|
2004-07-29 05:11:48 +04:00
|
|
|
io = fs->io;
|
2001-05-03 08:02:29 +04:00
|
|
|
}
|
1997-04-26 18:48:50 +04:00
|
|
|
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
|
|
|
|
|
2012-07-31 01:42:15 +04:00
|
|
|
cache_slot = (fs->icache->cache_last + 1) % fs->icache->cache_size;
|
2012-07-31 02:46:04 +04:00
|
|
|
iptr = (struct ext2_inode_large *)fs->icache->cache[cache_slot].inode;
|
2005-01-26 07:42:56 +03:00
|
|
|
|
2012-07-31 01:42:15 +04:00
|
|
|
ptr = (char *) iptr;
|
2005-01-26 07:42:56 +03:00
|
|
|
while (length) {
|
|
|
|
clen = length;
|
|
|
|
if ((offset + length) > fs->blocksize)
|
|
|
|
clen = fs->blocksize - offset;
|
|
|
|
|
|
|
|
if (block_nr != fs->icache->buffer_blk) {
|
2009-09-08 05:14:24 +04:00
|
|
|
retval = io_channel_read_blk64(io, block_nr, 1,
|
2005-01-26 07:42:56 +03:00
|
|
|
fs->icache->buffer);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
fs->icache->buffer_blk = block_nr;
|
1997-04-30 01:26:48 +04:00
|
|
|
}
|
2005-01-26 07:42:56 +03:00
|
|
|
|
|
|
|
memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset,
|
|
|
|
clen);
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
length -= clen;
|
|
|
|
ptr += clen;
|
|
|
|
block_nr++;
|
|
|
|
}
|
2012-07-31 01:42:15 +04:00
|
|
|
length = EXT2_INODE_SIZE(fs->super);
|
2005-01-26 07:42:56 +03:00
|
|
|
|
2012-07-31 02:46:04 +04:00
|
|
|
/* Verify the inode checksum. */
|
2014-08-03 06:49:12 +04:00
|
|
|
fail_csum = !ext2fs_inode_csum_verify(fs, ino, iptr);
|
2012-07-31 02:46:04 +04:00
|
|
|
|
2007-08-11 09:56:48 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2012-07-31 01:42:15 +04:00
|
|
|
ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) iptr,
|
|
|
|
(struct ext2_inode_large *) iptr,
|
|
|
|
0, length);
|
ChangeLog, Makefile.in, swapfs.c, unix.c:
Makefile.in: Add message.c and swapfs.c to the list of source files to
build the make depend.
swapfs.c, unix.c: Only support the -s and -S options to e2fsck if
ENABLE_SWAPFS is defined.
Many files:
ext2fs.h, bitops.h, block.c, bmap.c, closefs.c, dirblock.c, inode.c,
native.c, openfs.c, rw_bitmaps.c, swapfs.c: Only include the
byte-swapping logic if ENABLE_SWAPFS is turned on or if we're on a
big-endian machine.
initialize.c (ext2fs_initialize):Use WORDS_BIGENDIAN directly to set
EXT2_FLAG_SWAP_BYTES, instead of using ext2fs_native_flag.
native.c (ext2fs_native_flag): Use WORDS_BIGENDIAN provided by
autoconf to determine whether or not return EXT2_FLAG_SWAP_BYTES.
2001-06-11 11:00:04 +04:00
|
|
|
#endif
|
1997-04-29 18:53:37 +04:00
|
|
|
|
2012-07-31 01:42:15 +04:00
|
|
|
/* Update the inode cache bookkeeping */
|
2014-08-03 06:49:12 +04:00
|
|
|
if (!fail_csum) {
|
|
|
|
fs->icache->cache_last = cache_slot;
|
|
|
|
fs->icache->cache[cache_slot].ino = ino;
|
|
|
|
}
|
2012-11-17 22:37:45 +04:00
|
|
|
memcpy(inode, iptr, (bufsize > length) ? length : bufsize);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2014-08-03 06:49:12 +04:00
|
|
|
if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && fail_csum)
|
|
|
|
return EXT2_ET_INODE_CSUM_INVALID;
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-01-26 07:42:56 +03:00
|
|
|
errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
|
|
|
|
struct ext2_inode * inode)
|
|
|
|
{
|
|
|
|
return ext2fs_read_inode_full(fs, ino, inode,
|
|
|
|
sizeof(struct ext2_inode));
|
|
|
|
}
|
|
|
|
|
|
|
|
errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
|
|
|
|
struct ext2_inode * inode, int bufsize)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2011-07-06 04:02:27 +04:00
|
|
|
blk64_t block_nr;
|
|
|
|
unsigned long group, block, offset;
|
2005-01-26 07:42:56 +03:00
|
|
|
errcode_t retval = 0;
|
2012-07-31 01:42:15 +04:00
|
|
|
struct ext2_inode_large *w_inode;
|
1997-04-26 18:48:50 +04:00
|
|
|
char *ptr;
|
2012-07-31 01:42:15 +04:00
|
|
|
int clen, i;
|
|
|
|
int length = EXT2_INODE_SIZE(fs->super);
|
1997-04-26 17:21:57 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
|
|
|
|
1997-04-29 18:53:37 +04:00
|
|
|
/* Check to see if user provided an override function */
|
|
|
|
if (fs->write_inode) {
|
|
|
|
retval = (fs->write_inode)(fs, ino, inode);
|
|
|
|
if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
|
|
|
|
return retval;
|
|
|
|
}
|
1997-04-30 01:26:48 +04:00
|
|
|
|
2012-07-31 01:42:15 +04:00
|
|
|
if ((ino == 0) || (ino > fs->super->s_inodes_count))
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
|
|
|
|
|
|
|
/* Prepare our shadow buffer for read/modify/byteswap/write */
|
|
|
|
retval = ext2fs_get_mem(length, &w_inode);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
2012-07-31 02:46:04 +04:00
|
|
|
|
|
|
|
if (bufsize < length) {
|
|
|
|
int old_flags = fs->flags;
|
|
|
|
fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
2012-07-31 01:42:15 +04:00
|
|
|
retval = ext2fs_read_inode_full(fs, ino,
|
|
|
|
(struct ext2_inode *)w_inode,
|
|
|
|
length);
|
e2fsck: correctly preserve fs flags when modifying ignore-csum-error flag
When we need to modify the "ignore checksum error" behavior flag to
get us past a library call, it's possible that the library call can
result in other flag bits being changed. Therefore, it is not correct
to restore unconditionally the previous flags value, since this will
have unintended side effects on the other fs->flags; nor is it correct
to assume that we can unconditionally set (or clear) the "ignore csum
error" flag bit. Therefore, we must merge the previous value of the
"ignore csum error" flag with the value of flags after the call.
Note that we want to leave checksum verification on as much as
possible because doing so exposes e2fsck bugs where two metadata
blocks are "sharing" the same disk block, and attempting to fix one
before relocating the other causes major filesystem damage. The
damage is much more obvious when a previously checked piece of
metadata suddenly fails in a subsequent pass.
The modifications to the pass 2, 3, and 3A code are justified as
follows: When e2fsck encounters a block of directory entries and
cannot find the placeholder entry at the end that contains the
checksum, it will try to insert the placeholder. If that fails, it
will schedule the directory for a pass 3A reconstruction. Until that
happens, we don't want directory block writing (pass 2), block
iteration (pass 3), or block reading (pass 3A) to fail due to checksum
errors, because failing to find the placeholder is itself a checksum
verification error, which causes e2fsck to abort without fixing
anything.
The e2fsck call to ext2fs_read_bitmaps must never fail due to a
checksum error because e2fsck subsequently (a) verifies the bitmaps
itself; or (b) decides that they don't match what has been observed,
and rewrites them.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
2014-08-03 06:48:21 +04:00
|
|
|
fs->flags = (old_flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) |
|
|
|
|
(fs->flags & ~EXT2_FLAG_IGNORE_CSUM_ERRORS);
|
2012-07-31 02:46:04 +04:00
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
}
|
2012-07-31 01:42:15 +04:00
|
|
|
|
1997-04-29 18:53:37 +04:00
|
|
|
/* Check to see if the inode cache needs to be updated */
|
1997-04-30 01:26:48 +04:00
|
|
|
if (fs->icache) {
|
|
|
|
for (i=0; i < fs->icache->cache_size; i++) {
|
|
|
|
if (fs->icache->cache[i].ino == ino) {
|
2012-07-31 01:42:15 +04:00
|
|
|
memcpy(fs->icache->cache[i].inode, inode,
|
2012-11-17 22:37:45 +04:00
|
|
|
(bufsize > length) ? length : bufsize);
|
1997-04-30 01:26:48 +04:00
|
|
|
break;
|
|
|
|
}
|
1997-04-29 18:53:37 +04:00
|
|
|
}
|
1997-04-30 01:26:48 +04:00
|
|
|
} else {
|
2014-03-03 10:03:24 +04:00
|
|
|
retval = ext2fs_create_inode_cache(fs, 4);
|
1997-04-30 01:26:48 +04:00
|
|
|
if (retval)
|
2012-07-31 01:42:15 +04:00
|
|
|
goto errout;
|
1997-04-29 18:53:37 +04:00
|
|
|
}
|
2012-07-31 01:42:15 +04:00
|
|
|
memcpy(w_inode, inode, (bufsize > length) ? length : bufsize);
|
2008-08-28 07:07:54 +04:00
|
|
|
|
2012-07-31 01:42:15 +04:00
|
|
|
if (!(fs->flags & EXT2_FLAG_RW)) {
|
|
|
|
retval = EXT2_ET_RO_FILSYS;
|
|
|
|
goto errout;
|
|
|
|
}
|
2005-01-26 07:42:56 +03:00
|
|
|
|
2007-08-11 09:56:48 +04:00
|
|
|
#ifdef WORDS_BIGENDIAN
|
2012-07-31 01:42:15 +04:00
|
|
|
ext2fs_swap_inode_full(fs, w_inode, w_inode, 1, length);
|
ChangeLog, Makefile.in, swapfs.c, unix.c:
Makefile.in: Add message.c and swapfs.c to the list of source files to
build the make depend.
swapfs.c, unix.c: Only support the -s and -S options to e2fsck if
ENABLE_SWAPFS is defined.
Many files:
ext2fs.h, bitops.h, block.c, bmap.c, closefs.c, dirblock.c, inode.c,
native.c, openfs.c, rw_bitmaps.c, swapfs.c: Only include the
byte-swapping logic if ENABLE_SWAPFS is turned on or if we're on a
big-endian machine.
initialize.c (ext2fs_initialize):Use WORDS_BIGENDIAN directly to set
EXT2_FLAG_SWAP_BYTES, instead of using ext2fs_native_flag.
native.c (ext2fs_native_flag): Use WORDS_BIGENDIAN provided by
autoconf to determine whether or not return EXT2_FLAG_SWAP_BYTES.
2001-06-11 11:00:04 +04:00
|
|
|
#endif
|
2007-08-11 09:56:48 +04:00
|
|
|
|
2012-07-31 02:46:04 +04:00
|
|
|
retval = ext2fs_inode_csum_set(fs, ino, w_inode);
|
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
|
1997-04-26 18:48:50 +04:00
|
|
|
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
|
|
|
|
EXT2_INODE_SIZE(fs->super);
|
|
|
|
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
if (!ext2fs_inode_table_loc(fs, (unsigned) group)) {
|
2007-03-22 00:38:47 +03:00
|
|
|
retval = EXT2_ET_MISSING_INODE_TABLE;
|
|
|
|
goto errout;
|
|
|
|
}
|
Convert to use block group accessor functions
Convert direct accesses to use the following block group accessor
functions: ext2fs_block_bitmap_loc(), ext2fs_inode_bitmap_loc(),
ext2fs_inode_table_loc(), ext2fs_bg_itable_unused(),
ext2fs_block_bitmap_loc_set(), ext2fs_inode_bitmap_loc_set(),
ext2fs_inode_table_loc_set(), ext2fs_bg_free_inodes_count(),
ext2fs_ext2fs_bg_used_dirs_count(), ext2fs_bg_free_inodes_count_set(),
ext2fs_bg_free_blocks_count_set(), ext2fs_bg_used_dirs_count_set()
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Signed-off-by: Nick Dokos <nicholas.dokos@hp.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
2009-10-26 04:43:47 +03:00
|
|
|
block_nr = ext2fs_inode_table_loc(fs, (unsigned) group) + block;
|
2005-01-26 07:42:56 +03:00
|
|
|
|
1997-04-26 18:48:50 +04:00
|
|
|
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
|
|
|
|
|
2005-01-26 07:42:56 +03:00
|
|
|
ptr = (char *) w_inode;
|
|
|
|
|
|
|
|
while (length) {
|
|
|
|
clen = length;
|
|
|
|
if ((offset + length) > fs->blocksize)
|
|
|
|
clen = fs->blocksize - offset;
|
|
|
|
|
|
|
|
if (fs->icache->buffer_blk != block_nr) {
|
2009-09-08 05:14:24 +04:00
|
|
|
retval = io_channel_read_blk64(fs->io, block_nr, 1,
|
2005-01-26 07:42:56 +03:00
|
|
|
fs->icache->buffer);
|
|
|
|
if (retval)
|
|
|
|
goto errout;
|
|
|
|
fs->icache->buffer_blk = block_nr;
|
1997-04-26 18:48:50 +04:00
|
|
|
}
|
|
|
|
|
2008-08-28 07:07:54 +04:00
|
|
|
|
|
|
|
memcpy((char *) fs->icache->buffer + (unsigned) offset,
|
2005-01-26 07:42:56 +03:00
|
|
|
ptr, clen);
|
|
|
|
|
2009-09-08 05:14:24 +04:00
|
|
|
retval = io_channel_write_blk64(fs->io, block_nr, 1,
|
1997-04-30 01:26:48 +04:00
|
|
|
fs->icache->buffer);
|
1997-04-26 18:48:50 +04:00
|
|
|
if (retval)
|
2005-01-26 07:42:56 +03:00
|
|
|
goto errout;
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
ptr += clen;
|
|
|
|
length -= clen;
|
|
|
|
block_nr++;
|
1997-04-26 18:48:50 +04:00
|
|
|
}
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
fs->flags |= EXT2_FLAG_CHANGED;
|
2005-01-26 07:42:56 +03:00
|
|
|
errout:
|
2012-07-31 01:42:15 +04:00
|
|
|
ext2fs_free_mem(&w_inode);
|
2005-01-26 07:42:56 +03:00
|
|
|
return retval;
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2005-01-26 07:42:56 +03:00
|
|
|
errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
|
|
|
|
struct ext2_inode *inode)
|
|
|
|
{
|
|
|
|
return ext2fs_write_inode_full(fs, ino, inode,
|
|
|
|
sizeof(struct ext2_inode));
|
|
|
|
}
|
2005-03-21 04:05:22 +03:00
|
|
|
|
2008-08-28 07:07:54 +04:00
|
|
|
/*
|
2005-03-21 04:05:22 +03:00
|
|
|
* This function should be called when writing a new inode. It makes
|
2005-03-21 09:02:53 +03:00
|
|
|
* sure that extra part of large inodes is initialized properly.
|
2005-03-21 04:05:22 +03:00
|
|
|
*/
|
|
|
|
errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
|
|
|
|
struct ext2_inode *inode)
|
|
|
|
{
|
|
|
|
struct ext2_inode *buf;
|
|
|
|
int size = EXT2_INODE_SIZE(fs->super);
|
2005-03-21 09:02:53 +03:00
|
|
|
struct ext2_inode_large *large_inode;
|
2007-04-06 16:50:15 +04:00
|
|
|
errcode_t retval;
|
2008-08-14 22:30:05 +04:00
|
|
|
__u32 t = fs->now ? fs->now : time(NULL);
|
|
|
|
|
|
|
|
if (!inode->i_ctime)
|
|
|
|
inode->i_ctime = t;
|
|
|
|
if (!inode->i_mtime)
|
|
|
|
inode->i_mtime = t;
|
|
|
|
if (!inode->i_atime)
|
|
|
|
inode->i_atime = t;
|
2005-03-21 04:05:22 +03:00
|
|
|
|
|
|
|
if (size == sizeof(struct ext2_inode))
|
|
|
|
return ext2fs_write_inode_full(fs, ino, inode,
|
|
|
|
sizeof(struct ext2_inode));
|
|
|
|
|
|
|
|
buf = malloc(size);
|
|
|
|
if (!buf)
|
|
|
|
return ENOMEM;
|
|
|
|
|
|
|
|
memset(buf, 0, size);
|
|
|
|
*buf = *inode;
|
|
|
|
|
2005-03-21 09:02:53 +03:00
|
|
|
large_inode = (struct ext2_inode_large *) buf;
|
2008-08-28 07:07:54 +04:00
|
|
|
large_inode->i_extra_isize = sizeof(struct ext2_inode_large) -
|
2005-03-21 09:02:53 +03:00
|
|
|
EXT2_GOOD_OLD_INODE_SIZE;
|
2008-08-14 22:30:05 +04:00
|
|
|
if (!large_inode->i_crtime)
|
|
|
|
large_inode->i_crtime = t;
|
2005-03-21 09:02:53 +03:00
|
|
|
|
2007-04-06 16:50:15 +04:00
|
|
|
retval = ext2fs_write_inode_full(fs, ino, buf, size);
|
|
|
|
free(buf);
|
|
|
|
return retval;
|
2005-03-21 04:05:22 +03:00
|
|
|
}
|
|
|
|
|
2008-08-28 07:07:54 +04:00
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
struct ext2_inode inode;
|
|
|
|
int i;
|
|
|
|
errcode_t retval;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
if (ino > fs->super->s_inodes_count)
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
|
|
|
|
|
|
|
if (fs->get_blocks) {
|
|
|
|
if (!(*fs->get_blocks)(fs, ino, blocks))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
retval = ext2fs_read_inode(fs, ino, &inode);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
|
|
|
for (i=0; i < EXT2_N_BLOCKS; i++)
|
|
|
|
blocks[i] = inode.i_block[i];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Many files:
alloc.c, bb_inode.c, bitmaps.c, bitops.h, block.c, bmap.c, bmove.c,
brel.h, cmp_bitmaps.c, dblist.c, dblist_dir.c, dir_iterate.c,
expanddir.c, ext2fs.h, ext2fsP.h, fileio.c, finddev.c, get_pathname.c,
icount.c, inode.c, irel.h, irel_ma.c, ismounted.c, link.c, lookup.c,
mkdir.c, mkjournal.c, namei.c, newdir.c, read_bb_file.c, test_io.c,
tst_iscan.c, unix_io.c, unlink.c: Change use of ino_t to ext2_ino_t,
to protect applications that attempt to compile
-D_FILE_OFFSET_BITS=64, since this inexplicably changes ino_t(!?). So
we use ext2_ino_t to avoid an unexpected ABI change.
2001-01-11 07:54:39 +03:00
|
|
|
errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
struct ext2_inode inode;
|
|
|
|
errcode_t retval;
|
2008-08-28 07:07:54 +04:00
|
|
|
|
1997-04-26 17:34:30 +04:00
|
|
|
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
if (ino > fs->super->s_inodes_count)
|
|
|
|
return EXT2_ET_BAD_INODE_NUM;
|
|
|
|
|
1997-10-03 21:42:28 +04:00
|
|
|
if (fs->check_directory) {
|
|
|
|
retval = (fs->check_directory)(fs, ino);
|
|
|
|
if (retval != EXT2_ET_CALLBACK_NOTHANDLED)
|
|
|
|
return retval;
|
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
retval = ext2fs_read_inode(fs, ino, &inode);
|
|
|
|
if (retval)
|
|
|
|
return retval;
|
1997-04-26 17:58:21 +04:00
|
|
|
if (!LINUX_S_ISDIR(inode.i_mode))
|
1997-10-31 09:07:47 +03:00
|
|
|
return EXT2_ET_NO_DIRECTORY;
|
1997-04-26 17:21:57 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|