Commit 19c78dc0 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

Many files:

  Checked in e2fsprogs-1.07
parent 21c84b71
......@@ -71,7 +71,7 @@
00000000 T _ext2fs_update_bb_inode libext2fs bb_inode
00000000 T _ext2fs_read_bb_FILE libext2fs read_bb_file
00000000 T _initialize_ext2_error_table libext2fs ext2_err
00000000 T _ext2_llseek libext2fs llseek
00000000 T _ext2fs_llseek libext2fs llseek
00000000 T _ext2fs_set_inode_callback libext2fs inode
00000000 T _ext2fs_compare_block_bitmap libext2fs cmp_bitmaps
00000000 T _ext2fs_compare_inode_bitmap libext2fs cmp_bitmaps
......@@ -93,3 +93,48 @@
00000000 T _ext2fs_swap_group_desc libext2fs swapfs
00000000 T _ext2fs_get_device_size libext2fs getsize
00000000 T _ext2fs_check_if_mounted libext2fs ismounted
00000000 T _ext2fs_allocate_tables libext2fs alloc_tables
00000000 T _ext2fs_allocate_generic_bitmap libext2fs bitmaps
00000000 T _ext2fs_warn_bitmap2 libext2fs bitops
00000000 T _ext2fs_free_generic_bitmap libext2fs freefs
00000000 T _ext2fs_mark_generic_bitmap libext2fs inline
00000000 T _ext2fs_unmark_generic_bitmap libext2fs inline
00000000 T _ext2fs_test_generic_bitmap libext2fs inline
00000000 T _ext2fs_namei_follow libext2fs namei
00000000 T _ext2fs_follow_link libext2fs namei
00000000 T _ext2fs_native_flag libext2fs native
00000000 T _ext2fs_swap_inode libext2fs swapfs
00000000 T _ext2fs_block_iterate2 libext2fs block
00000000 T _ext2fs_inode_scan_goto_blockgroup libext2fs inode
00000000 T _ext2fs_badblocks_list_create libext2fs badblocks
00000000 T _ext2fs_badblocks_list_add libext2fs badblocks
00000000 T _ext2fs_badblocks_list_test libext2fs badblocks
00000000 T _ext2fs_badblocks_list_iterate_begin libext2fs badblocks
00000000 T _ext2fs_badblocks_list_iterate libext2fs badblocks
00000000 T _ext2fs_badblocks_list_iterate_end libext2fs badblocks
00000000 T _ext2fs_brel_memarray_create libext2fs brel_ma
00000000 T _ext2fs_badblocks_list_free libext2fs closefs
00000000 T _ext2fs_free_dblist libext2fs closefs
00000000 T _ext2fs_get_num_dirs libext2fs dblist
00000000 T _ext2fs_init_dblist libext2fs dblist
00000000 T _ext2fs_add_dir_block libext2fs dblist
00000000 T _ext2fs_dblist_iterate libext2fs dblist
00000000 T _ext2fs_dblist_dir_iterate libext2fs dblist_dir
00000000 T _ext2fs_process_dir_block libext2fs dir_iterate
00000000 T _ext2fs_test_block_bitmap_range libext2fs inline
00000000 T _ext2fs_fast_test_block_bitmap_range libext2fs inline
00000000 T _ext2fs_mark_block_bitmap_range libext2fs inline
00000000 T _ext2fs_fast_mark_block_bitmap_range libext2fs inline
00000000 T _ext2fs_unmark_block_bitmap_range libext2fs inline
00000000 T _ext2fs_fast_unmark_block_bitmap_range libext2fs inline
00000000 T _ext2fs_inode_scan_flags libext2fs inode
00000000 T _ext2fs_irel_memarray_create libext2fs irel_ma
00000000 T _ext2fs_resize_generic_bitmap libext2fs rs_bitmap
00000000 T _ext2fs_inode_has_valid_blocks libext2fs valid_blk
00000000 T _ext2fs_free_icount libext2fs icount
00000000 T _ext2fs_create_icount libext2fs icount
00000000 T _ext2fs_icount_fetch libext2fs icount
00000000 T _ext2fs_icount_increment libext2fs icount
00000000 T _ext2fs_icount_decrement libext2fs icount
00000000 T _ext2fs_icount_store libext2fs icount
00000000 T _ext2fs_get_icount_size libext2fs icount
00000004 D _unix_io_manager libext2fs unix_io
00000004 D _test_io_manager libext2fs test_io
00000004 D _test_io_backing_manager libext2fs test_io
00000004 D _test_io_cb_read_blk libext2fs test_io
00000004 D _test_io_cb_write_blk libext2fs test_io
00000004 D _test_io_cb_set_blksize libext2fs test_io
/*
* expand.c --- expand an ext2fs directory
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......
#
# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. This file may be
# redistributed under the terms of the GNU Public License.
# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
#
# %Begin-Header%
# This file may be redistributed under the terms of the GNU Public
# License.
# %End-Header%
#
error_table ext2
......@@ -37,14 +41,14 @@ ec EXT2_ET_MAGIC_INODE_BITMAP,
ec EXT2_ET_MAGIC_GENERIC_BITMAP,
"Wrong magic number for generic_bitmap structure"
ec EXT2_ET_MAGIC_RESERVED_2,
"Wrong magic number --- RESERVED_2"
ec EXT2_ET_MAGIC_TEST_IO_CHANNEL,
"Wrong magic number for test io_channel structure"
ec EXT2_ET_MAGIC_RESERVED_3,
"Wrong magic number --- RESERVED_3"
ec EXT2_ET_MAGIC_DBLIST,
"Wrong magic number for directory block list structure"
ec EXT2_ET_MAGIC_RESERVED_4,
"Wrong magic number --- RESERVED_4"
ec EXT2_ET_MAGIC_ICOUNT,
"Wrong magic number for icount structure"
ec EXT2_ET_MAGIC_RESERVED_5,
"Wrong magic number --- RESERVED_5"
......@@ -211,4 +215,13 @@ ec EXT2_ET_SYMLINK_LOOP,
ec EXT2_ET_CALLBACK_NOTHANDLED,
"The callback function will not handle this case"
ec EXT2_ET_BAD_BLOCK_IN_INODE_TABLE,
"The inode is from a bad block in the inode table"
ec EXT2_ET_UNSUPP_FEATURE,
"Filesystem has unsupported feature(s)"
ec EXT2_ET_RO_UNSUPP_FEATURE,
"Filesystem has unsupported read-only feature(s)"
end
/*
* ext2fs.h --- ext2fs
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
/*
* Non-GNU C compilers won't necessarily understand inline
*/
#ifndef __GNUC__
#define NO_INLINE_FUNCS
#endif
/*
* Where the master copy of the superblock is located, and how big
* superblocks are supposed to be. We define SUPERBLOCK_SIZE because
......@@ -49,9 +60,7 @@ struct ext2fs_struct_generic_bitmap {
#define EXT2FS_TEST_ERROR 2
typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
#ifdef EXT2_DYNAMIC_REV
......@@ -61,20 +70,47 @@ typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
#endif
/*
* badblocks list definitions
*/
typedef struct ext2_struct_badblocks_list *ext2_badblocks_list;
typedef struct ext2_struct_badblocks_iterate *ext2_badblocks_iterate;
/* old */
typedef struct ext2_struct_badblocks_list *badblocks_list;
typedef struct ext2_struct_badblocks_iterate *badblocks_iterate;
#define BADBLOCKS_FLAG_DIRTY 1
/*
* ext2_dblist structure and abstractions (see dblist.c)
*/
struct ext2_db_entry {
ino_t ino;
blk_t blk;
int blockcnt;
};
typedef struct ext2_struct_dblist *ext2_dblist;
#define DBLIST_ABORT 1
/*
* Flags for the ext2_filsys structure
*/
#define EXT2_FLAG_RW 0x01
#define EXT2_FLAG_CHANGED 0x02
#define EXT2_FLAG_DIRTY 0x04
#define EXT2_FLAG_VALID 0x08
#define EXT2_FLAG_IB_DIRTY 0x10
#define EXT2_FLAG_BB_DIRTY 0x20
#define EXT2_FLAG_RW 0x01
#define EXT2_FLAG_CHANGED 0x02
#define EXT2_FLAG_DIRTY 0x04
#define EXT2_FLAG_VALID 0x08
#define EXT2_FLAG_IB_DIRTY 0x10
#define EXT2_FLAG_BB_DIRTY 0x20
#define EXT2_FLAG_SWAP_BYTES 0x40
#define EXT2_FLAG_SWAP_BYTES_READ 0x80
#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
#define EXT2_FLAG_MASTER_SB_ONLY 0x200
#define EXT2_FLAG_FORCE 0x400
/*
* Special flag in the ext2 inode i_flag field that means that this is
......@@ -103,7 +139,12 @@ struct struct_ext2_filsys {
struct ext2_inode *inode);
errcode_t (*write_inode)(ext2_filsys fs, ino_t ino,
struct ext2_inode *inode);
__u32 reserved[14];
badblocks_list badblocks;
ext2_dblist dblist;
/*
* Reserved for future expansion
*/
__u32 reserved[12];
/*
* Not used by ext2fs library; reserved for the use of the
......@@ -112,32 +153,6 @@ struct struct_ext2_filsys {
void * private;
};
/*
* badblocks list definitions
*/
typedef struct struct_badblocks_list *badblocks_list;
struct struct_badblocks_list {
int magic;
int num;
int size;
blk_t *list;
int badblocks_flags;
int reserved[8];
};
#define BADBLOCKS_FLAG_DIRTY 1
typedef struct struct_badblocks_iterate *badblocks_iterate;
struct struct_badblocks_iterate {
int magic;
badblocks_list bb;
int ptr;
int reserved[8];
};
#include "ext2fs/bitops.h"
/*
......@@ -191,38 +206,30 @@ struct struct_badblocks_iterate {
#define DIRENT_FLAG_INCLUDE_EMPTY 1
#define DIRENT_DOT_FILE 1
#define DIRENT_DOT_DOT_FILE 2
#define DIRENT_OTHER_FILE 3
/*
* Inode scan definitions
*/
typedef struct ext2_struct_inode_scan *ext2_inode_scan;
struct ext2_struct_inode_scan {
int magic;
ext2_filsys fs;
ino_t current_inode;
blk_t current_block;
dgrp_t current_group;
int inodes_left, blocks_left, groups_left;
int inode_buffer_blocks;
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,
void * private);
void * done_group_data;
int reserved[8];
};
/*
* ext2fs_scan flags
*/
#define EXT2_SF_CHK_BADBLOCKS 0x0001
#define EXT2_SF_BAD_INODE_BLK 0x0002
#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
/*
* ext2fs_check_if_mounted flags
*/
#define EXT2_MF_MOUNTED 1
#define EXT2_MF_ISROOT 2
#define EXT2_MF_READONLY 4
#define EXT2_MF_READONLY 4
/*
* Ext2/linux mode flags. We define them here so that we don't need
......@@ -264,6 +271,13 @@ struct ext2_struct_inode_scan {
#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
/*
* ext2_icount_t abstraction
*/
#define EXT2_ICOUNT_OPT_INCREMENT 0x01
typedef struct ext2_icount *ext2_icount_t;
/*
* For checking structure magic numbers...
*/
......@@ -342,7 +356,25 @@ extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
ext2fs_block_bitmap map,
blk_t *ret);
/* allocate_tables.c */
errcode_t ext2fs_allocate_tables(ext2_filsys fs);
/* badblocks.c */
extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
int size);
extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
blk_t blk);
extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
blk_t blk);
extern errcode_t
ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
ext2_badblocks_iterate *ret);
extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
blk_t *blk);
extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
/* bb_compat */
extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
extern void badblocks_list_free(badblocks_list bb);
extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
......@@ -354,7 +386,7 @@ extern void badblocks_list_iterate_end(badblocks_iterate iter);
/* bb_inode.c */
extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
badblocks_list bb_list);
ext2_badblocks_list bb_list);
/* bitmaps.c */
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
......@@ -392,6 +424,18 @@ extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
void *private),
void *private);
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
blk_t ref_blk,
int ref_offset,
void *private),
void *private);
/* check_desc.c */
extern errcode_t ext2fs_check_desc(ext2_filsys fs);
......@@ -405,6 +449,32 @@ extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
ext2fs_inode_bitmap bm2);
/* dblist.c */
errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ino_t *ret_num_dirs);
errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
void ext2fs_free_dblist(ext2_dblist dblist);
errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
int blockcnt);
errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
int (*func)(ext2_filsys fs,
struct ext2_db_entry *db_info,
void *private),
void *private);
/* dblist_dir.c */
extern errcode_t
ext2fs_dblist_dir_iterate(ext2_dblist dblist,
int flags,
char *block_buf,
int (*func)(ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private),
void *private);
/* dirblock.c */
extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
......@@ -412,6 +482,24 @@ extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *buf);
/* dir_iterate.c */
extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
ino_t dir,
int flags,
char *block_buf,
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private),
void *private);
/* private to library */
extern int ext2fs_process_dir_block(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private);
/* expanddir.c */
extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ino_t dir);
......@@ -436,39 +524,42 @@ extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
struct ext2_inode *inode);
void ext2fs_set_inode_callback(ext2_inode_scan scan,
errcode_t (*done_group)(ext2_filsys fs,
ext2_inode_scan scan,
dgrp_t group,
void * private),
void *done_group_data);
void ext2fs_set_inode_callback(ext2_inode_scan scan,
errcode_t (*done_group)(ext2_filsys fs,
ext2_inode_scan scan,
dgrp_t group,
void * private),
void *done_group_data);
extern errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
int group);
extern void ext2fs_set_inode_callback
(ext2_inode_scan scan,
errcode_t (*done_group)(ext2_filsys fs,
ext2_inode_scan scan,
dgrp_t group,
void * private),
void *done_group_data);
extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
int clear_flags);
extern errcode_t ext2fs_read_inode (ext2_filsys fs, ino_t ino,
struct ext2_inode * inode);
extern errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
extern errcode_t ext2fs_write_inode(ext2_filsys fs, ino_t ino,
struct ext2_inode * inode);
extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks);
extern errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino);
/* icount.c */
extern void ext2fs_free_icount(ext2_icount_t icount);
extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
ext2_icount_t *ret);
extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino,
__u16 *ret);
extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
__u16 *ret);
extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
__u16 *ret);
extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
__u16 count);
extern ino_t ext2fs_get_icount_size(ext2_icount_t icount);
/* ismounted.c */
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
/* namei.c */
extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
ino_t dir,
int flags,
char *block_buf,
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private),
void *private);
extern errcode_t ext2fs_lookup(ext2_filsys fs, ino_t dir, const char *name,
int namelen, char *buf, ino_t *inode);
extern errcode_t ext2fs_namei(ext2_filsys fs, ino_t root, ino_t cwd,
......@@ -505,20 +596,32 @@ errcode_t ext2fs_unlink(ext2_filsys fs, ino_t dir, const char *name,
ino_t ino, int flags);
/* read_bb.c */
extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, badblocks_list *bb_list);
extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
ext2_badblocks_list *bb_list);
/* read_bb_file.c */
extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
badblocks_list *bb_list,
ext2_badblocks_list *bb_list,
void (*invalid)(ext2_filsys fs,
blk_t blk));
/* rs_bitmap.c */
extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
__u32 new_real_end,
ext2fs_generic_bitmap bmap);
extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
ext2fs_inode_bitmap bmap);
extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
ext2fs_block_bitmap bmap);
/* swapfs.c */
extern void ext2fs_swap_super(struct ext2_super_block * super);
extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
struct ext2_inode *f, int hostorder);
/* valid_blk.c */
int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
/* inline functions */
extern void ext2fs_mark_super_dirty(ext2_filsys fs);
......
/*
* ext2fsP.h --- private header file for ext2 library
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include "ext2fs.h"
/*
* Badblocks list
*/
struct ext2_struct_badblocks_list {
int magic;
int num;
int size;
blk_t *list;
int badblocks_flags;
};
struct ext2_struct_badblocks_iterate {
int magic;
badblocks_list bb;
int ptr;
};
/*
* Directory block iterator definition
*/
struct ext2_struct_dblist {
int magic;
ext2_filsys fs;
ino_t size;
ino_t count;
int sorted;
struct ext2_db_entry * list;
};
/*
* For directory iterators
*/
struct dir_context {
ino_t dir;
int flags;
char *buf;
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private);
int (*func2)(ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private);
void *private;
errcode_t errcode;
};
/* Function prototypes */
extern int ext2_process_dir_block(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private);
/*
* freefs.c --- free an ext2 filesystem
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......@@ -30,6 +34,16 @@ void ext2fs_free(ext2_filsys fs)
ext2fs_free_block_bitmap(fs->block_map);
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
if (fs->badblocks)
badblocks_list_free(fs->badblocks);
fs->badblocks = 0;
if (fs->dblist)
ext2fs_free_dblist(fs->dblist);
fs->magic = 0;
free(fs);
}
......
/*
* get_pathname.c --- do directry/inode -> name translation
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* ext2fs_get_pathname(fs, dir, ino, name)
*
* This function translates takes two inode numbers into a
* string, placing the result in <name>. <dir> is the containing
* directory inode, and <ino> is the inode number itself. If
* <ino> is zero, then ext2fs_get_pathname will return pathname
* of the the directory <dir>.
*
*/
#include <stdio.h>
......
/*
* getsize.c --- get the size of a partition.
*
* Copyright (C) 1995 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1995, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......@@ -35,7 +39,7 @@ static int valid_offset (int fd, ext2_loff_t offset)
{
char ch;
if (ext2_llseek (fd, offset, 0) < 0)
if (ext2fs_llseek (fd, offset, 0) < 0)
return 0;
if (read (fd, &ch, 1) < 1)
return 0;
......@@ -49,12 +53,13 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize,
blk_t *retblocks)
{
int fd;
int size;
long size;
ext2_loff_t high, low;
#ifdef FDGETPRM
struct floppy_struct this_floppy;
#endif
#ifdef HAVE_SYS_DISKLABEL_H
int part;
struct disklabel lab;
struct partition *pp;
char ch;
......@@ -79,18 +84,18 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize,
}
#endif
#ifdef HAVE_SYS_DISKLABEL_H
size = strlen(file) - 1;
if (size >= 0) {
ch = file[size];
part = strlen(file) - 1;
if (part >= 0) {
ch = file[part];
if (isdigit(ch))
size = 0;
part = 0;
else if (ch >= 'a' && ch <= 'h')
size = ch - 'a';
part = ch - 'a';
else
size = -1;
part = -1;
}
if (size >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
pp = &lab.d_partitions[size];
if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
pp = &lab.d_partitions[part];
if (pp->p_size) {
close(fd);
*retblocks = pp->p_size / (blocksize / 512);
......@@ -101,7 +106,7 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize,
/*
* OK, we couldn't figure it out by using a specialized ioctl,
* which is generally the besy way. So do binary search to
* which is generally the best way. So do binary search to
* find the size of the partition.
*/
low = 0;
......
/*
* icount.c --- an efficient inode count abstraction
*
* Copyright (C) 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <et/com_err.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fs.h"
/*
* The data storage strategy used by icount relies on the observation
* that most inode counts are either zero (for non-allocated inodes),
* one (for most files), and only a few that are two or more
* (directories and files that are linked to more than one directory).
*
* Also, e2fsck tends to load the icount data sequentially.
*
* So, we use an inode bitmap to indicate which inodes have a count of
* one, and then use a sorted list to store the counts for inodes
* which are greater than one.
*
* We also use an optional bitmap to indicate which inodes are already
* in the sorted list, to speed up the use of this abstraction by
* e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
* so this extra bitmap avoids searching the sorted list to see if a
* particular inode is on the sorted list already.
*/
struct ext2_icount_el {
ino_t ino;
__u16 count;
};
struct ext2_icount {
int magic;
ext2fs_inode_bitmap single;
ext2fs_inode_bitmap multiple;
ino_t count;
ino_t size;
ino_t num_inodes;
int cursor;
struct ext2_icount_el *list;
};
void ext2fs_free_icount(ext2_icount_t icount)
{
if (!icount)
return;
icount->magic = 0;
if (icount->list)
free(icount->list);
if (icount->single)
ext2fs_free_inode_bitmap(icount->single);
if (icount->multiple)
ext2fs_free_inode_bitmap(icount->multiple);
free(icount);
}
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
ext2_icount_t *ret)
{
ext2_icount_t icount;
errcode_t retval;
size_t bytes;
icount = malloc(sizeof(struct ext2_icount));
if (!icount)
return ENOMEM;
memset(icount, 0, sizeof(struct ext2_icount));
retval = ext2fs_allocate_inode_bitmap(fs, 0,
&icount->single);
if (retval)
goto errout;
if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
retval = ext2fs_allocate_inode_bitmap(fs, 0,
&icount->multiple);
if (retval)
goto errout;
} else
icount->multiple = 0;
if (size) {
icount->size = size;
} else {
/*
* Figure out how many special case inode counts we will
* have. We know we will need one for each directory;
* we also need to reserve some extra room for file links
*/
retval = ext2fs_get_num_dirs(fs, &icount->size);
if (retval)
goto errout;
icount->size += fs->super->s_inodes_count / 50;
}
bytes = icount->size * sizeof(struct ext2_icount_el);
#if 0
printf("Icount allocated %d entries, %d bytes.\n",
icount->size, bytes);
#endif
icount->list = malloc(bytes);
if (!icount->list)
goto errout;
memset(icount->list, 0, bytes);
icount->magic = EXT2_ET_MAGIC_ICOUNT;
icount->count = 0;
icount->cursor = 0;
icount->num_inodes = fs->super->s_inodes_count;
*ret = icount;
return 0;
errout:
ext2fs_free_icount(icount);
return(retval);
}
/*
* get_icount_el() --- given an inode number, try to find icount
* information in the sorted list. We use a binary search...
*/
static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, ino_t ino)
{
int low, high, mid;
if (!icount || !icount->list || !icount->count)
return 0;
if (icount->multiple &&
!ext2fs_test_inode_bitmap(icount->multiple, ino))
return 0;
low = 0;
high = icount->count-1;
if (ino == icount->list[low].ino) {
icount->cursor = low+1;
return &icount->list[low];
}
if (ino == icount->list[high].ino) {
icount->cursor = 0;
return &icount->list[high];
}
if (icount->cursor >= icount->count)
icount->cursor = 0;
if (ino == icount->list[icount->cursor].ino)
return &icount->list[icount->cursor++];
#if 0
printf("Non-cursor get_icount_el: %u\n", ino);
#endif
while (low < high) {
mid = (low+high)/2;
if (mid == low || mid == high)
break;
if (ino == icount->list[mid].ino) {
icount->cursor = mid;
return &icount->list[mid];
}
if (ino < icount->list[mid].ino)
high = mid;
else
low = mid;
}
return 0;
}
/*
* put_icount_el() --- given an inode number, create a new entry in
* the sorted list. This function is optimized for adding values
* in ascending order.
*/
static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino)
{
struct ext2_icount_el *el, *new_list;
ino_t new_size = 0;
int i, j;
if (icount->count >= icount->size) {
if (icount->count) {
new_size = icount->list[icount->count-1].ino;
new_size = icount->count *
((float) new_size / icount->num_inodes);
}
if (new_size < (icount->size + 100))
new_size = icount->size + 100;
#if 0
printf("Reallocating icount %d entries...\n", new_size);
#endif
new_list = realloc(icount->list,
new_size * sizeof(struct ext2_icount_el));
if (!new_list)
return 0;
icount->size = new_size;
icount->list = new_list;
}
/*
* Normally, get_icount_el is called with each inode in
* sequential order; but once in a while (like when pass 3
* needs to recreate the root directory or lost+found
* directory) it is called out of order.
*/
if (icount->count && icount->list[icount->count-1].ino >= ino) {
for (i = icount->count-1; i > 0; i--)
if (icount->list[i-1].ino < ino)
break;
el = &icount->list[i];
if (el->ino != ino) {
for (j = icount->count++; j > i; j--)
icount->list[j] = icount->list[j-1];
el->count = 0;
}
} else {
el = &icount->list[icount->count++];
el->count = 0;
}
el->ino = ino;
return el;
}
errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret)
{
struct ext2_icount_el *el;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
*ret = 1;
return 0;
}
el = get_icount_el(icount, ino);
if (!el) {
*ret = 0;
return 0;
}
*ret = el->count;
return 0;
}
errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
__u16 *ret)
{
struct ext2_icount_el *el;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
/*
* If the existing count is 1, then we know there is
* no entry in the list, so use put_icount_el().
*/
el = put_icount_el(icount, ino);
if (!el)
return ENOMEM;
} else if (icount->multiple) {
/*
* The count is either zero or greater than 1; if the
* inode is set in icount->multiple, then there should
* be an entry in the list, so find it using
* get_icount_el().
*/
if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
el = get_icount_el(icount, ino);
if (!el) {
/* should never happen */
el = put_icount_el(icount, ino);
if (!el)
return ENOMEM;
}
} else {
/*
* The count was zero; mark the single bitmap
* and return.
*/
zero_count:
ext2fs_mark_inode_bitmap(icount->single, ino);
if (ret)
*ret = 1;
return 0;
}
} else {
/*
* The count is either zero or greater than 1; try to
* find an entry in the list to determine which.
*/
el = get_icount_el(icount, ino);
if (!el) {
/* No entry means the count was zero */
goto zero_count;
}
el = put_icount_el(icount, ino);
if (!el)
return ENOMEM;
}
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
ext2fs_unmark_inode_bitmap(icount->single, ino);
el->count = 2;
} else
el->count++;
if (icount->multiple)
ext2fs_mark_inode_bitmap(icount->multiple, ino);
if (ret)
*ret = el->count;
return 0;
}
errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
__u16 *ret)
{
struct ext2_icount_el *el;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
ext2fs_unmark_inode_bitmap(icount->single, ino);
if (icount->multiple)
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
else {
el = get_icount_el(icount, ino);
if (el)
el->count = 0;
}
if (ret)
*ret = 0;
return 0;
}
el = get_icount_el(icount, ino);
if (!el)
return EINVAL;
el->count--;
if (el->count == 1)
ext2fs_mark_inode_bitmap(icount->single, ino);
if ((el->count == 0) && icount->multiple)
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
if (ret)
*ret = el->count;
return 0;
}
errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
__u16 count)
{
struct ext2_icount_el *el;
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (count == 1) {
ext2fs_mark_inode_bitmap(icount->single, ino);
if (icount->multiple)
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
return 0;
}
if (count == 0) {
ext2fs_unmark_inode_bitmap(icount->single, ino);
if (icount->multiple) {
/*
* If the icount->multiple bitmap is enabled,
* we can just clear both bitmaps and we're done
*/
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
} else {
el = get_icount_el(icount, ino);
if (el)
el->count = 0;
}
return 0;
}
/*
* Get the icount element
*/
el = put_icount_el(icount, ino);
if (!el)
return ENOMEM;
el->count = count;
ext2fs_unmark_inode_bitmap(icount->single, ino);
if (icount->multiple)
ext2fs_mark_inode_bitmap(icount->multiple, ino);
return 0;
}
ino_t ext2fs_get_icount_size(ext2_icount_t icount)
{
if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
return 0;
return icount->size;
}
......@@ -4,8 +4,10 @@
*
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......
......@@ -3,8 +3,12 @@
* files as standalone functions, in case the application program
* is compiled with inlining turned off.
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
......
/*
* inode.c --- utility routines to read and write inodes
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......@@ -17,15 +21,51 @@
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#include "ext2fsP.h"
struct ext2_struct_inode_scan {
int magic;
ext2_filsys fs;
ino_t current_inode;
blk_t current_block;
dgrp_t current_group;
int inodes_left, blocks_left, groups_left;
int inode_buffer_blocks;
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,
void * private);
void * done_group_data;
int bad_block_ptr;
int scan_flags;
int reserved[6];
};
errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
ext2_inode_scan *ret_scan)
{
ext2_inode_scan scan;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
/*
* If fs->badblocks isn't set, then set it --- since the inode
* scanning functions require it.
*/
if (fs->badblocks == 0) {
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
if (retval && fs->badblocks) {
badblocks_list_free(fs->badblocks);
fs->badblocks = 0;
}
}
scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan));
if (!scan)
return ENOMEM;
......@@ -41,6 +81,7 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
scan->inode_buffer = malloc(scan->inode_buffer_blocks * fs->blocksize);
scan->done_group = 0;
scan->done_group_data = 0;
scan->bad_block_ptr = 0;
if (!scan->inode_buffer) {
free(scan);
return ENOMEM;
......@@ -51,6 +92,8 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
free(scan);
return ENOMEM;
}
if (scan->fs->badblocks && scan->fs->badblocks->num)
scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
*ret_scan = scan;
return 0;
}
......@@ -82,11 +125,168 @@ void ext2fs_set_inode_callback(ext2_inode_scan scan,
scan->done_group_data = done_group_data;
}
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)
{
scan->current_group++;
scan->groups_left--;
scan->current_block = scan->fs->
group_desc[scan->current_group].bg_inode_table;
scan->bytes_left = 0;
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
scan->blocks_left = scan->fs->inode_blocks_per_group;
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,
int *num_blocks)
{
blk_t blk = scan->current_block;
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])
*num_blocks = bb->list[scan->bad_block_ptr] - blk;
return 0;
}
/*
* 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)
{
int num_blocks;
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;
}
if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
(scan->current_block == 0)) {
memset(scan->inode_buffer, 0,
num_blocks * scan->fs->blocksize);
} else {
retval = io_channel_read_blk(scan->fs->io,
scan->current_block,
num_blocks, scan->inode_buffer);
if (retval)
return EXT2_ET_NEXT_INODE_READ;
}
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;
return 0;
}
errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
struct ext2_inode *inode)
{
errcode_t retval;
int num_blocks;
int extra_bytes = 0;
EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
......@@ -95,10 +295,10 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
* Do we need to start reading a new block group?
*/
if (scan->inodes_left <= 0) {
retry:
if (scan->done_group) {
retval = (scan->done_group)
(scan->fs, scan,
scan->current_group,
(scan->fs, scan, scan->current_group,
scan->done_group_data);
if (retval)
return retval;
......@@ -107,17 +307,15 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
*ino = 0;
return 0;
}
scan->current_group++;
scan->groups_left--;
scan->current_block = scan->fs->
group_desc[scan->current_group].bg_inode_table;
if (scan->current_block == 0)
return EXT2_ET_MISSING_INODE_TABLE;
scan->bytes_left = 0;
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
scan->blocks_left = scan->fs->inode_blocks_per_group;
retval = get_next_blockgroup(scan);
if (retval)
return retval;
if (scan->current_block == 0) {
if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
goto retry;
} else
return EXT2_ET_MISSING_INODE_TABLE;
}
}
/*
......@@ -127,22 +325,13 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
if (scan->bytes_left < scan->inode_size) {
memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
extra_bytes = scan->bytes_left;
scan->blocks_left -= scan->inode_buffer_blocks;
num_blocks = scan->inode_buffer_blocks;
if (scan->blocks_left < 0)
num_blocks += scan->blocks_left;
retval = io_channel_read_blk(scan->fs->io, scan->current_block,
num_blocks, scan->inode_buffer);
retval = get_next_blocks(scan);
if (retval)
return EXT2_ET_NEXT_INODE_READ;
scan->ptr = scan->inode_buffer;
scan->bytes_left = num_blocks * scan->fs->blocksize;
scan->current_block += scan->inode_buffer_blocks;
return retval;
}
retval = 0;
if (extra_bytes) {
memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
scan->inode_size - extra_bytes);
......@@ -155,6 +344,9 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
(struct ext2_inode *) scan->temp_buffer, 0);
else
*inode = *((struct ext2_inode *) scan->temp_buffer);
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;
} else {
if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
(scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
......@@ -164,12 +356,14 @@ errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
*inode = *((struct ext2_inode *) scan->ptr);
scan->ptr += scan->inode_size;
scan->bytes_left -= scan->inode_size;
if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
}
scan->inodes_left--;
scan->current_inode++;
*ino = scan->current_inode;
return 0;
return retval;
}
/*
......@@ -188,7 +382,7 @@ static struct {
#endif
errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
errcode_t ext2fs_read_inode (ext2_filsys fs, ino_t ino,
struct ext2_inode * inode)
{
unsigned long group, block, block_nr, offset;
......@@ -234,6 +428,8 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
if (!fs->group_desc[group].bg_inode_table)
return EXT2_ET_MISSING_INODE_TABLE;
block_nr = fs->group_desc[group].bg_inode_table + block;
if (block_nr != inode_buffer_block) {
retval = io_channel_read_blk(fs->io, block_nr, 1,
......@@ -280,8 +476,8 @@ errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
return 0;
}
errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
struct ext2_inode * inode)
errcode_t ext2fs_write_inode(ext2_filsys fs, ino_t ino,
struct ext2_inode * inode)
{
unsigned long group, block, block_nr, offset;
errcode_t retval;
......@@ -332,11 +528,14 @@ errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
if (!fs->group_desc[group].bg_inode_table)
return EXT2_ET_MISSING_INODE_TABLE;
block_nr = fs->group_desc[group].bg_inode_table + block;
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
ptr = (char *) inode_buffer + offset;
length = EXT2_INODE_SIZE(fs->super);
clen = length;
if (length > sizeof(struct ext2_inode))
length = sizeof(struct ext2_inode);
......@@ -350,12 +549,11 @@ errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
clen = EXT2_BLOCK_SIZE(fs->super) - offset;
memcpy(ptr, &temp_inode, clen);
length -= clen;
} else {
memcpy(ptr, &temp_inode, length);
length = 0;
}
memcpy(ptr, &temp_inode, clen);
retval = io_channel_write_blk(fs->io, block_nr, 1, inode_buffer);
if (retval)
return retval;
......@@ -419,7 +617,7 @@ errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino)
if (retval)
return retval;
if (!LINUX_S_ISDIR(inode.i_mode))
return ENOTDIR;
return ENOTDIR;
return 0;
}
/*
* io.h --- the I/O manager abstraction
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
/*
......@@ -15,7 +19,7 @@ typedef long ext2_loff_t;
#endif
/* llseek.c */
ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int);
ext2_loff_t ext2fs_llseek (unsigned int, ext2_loff_t, unsigned int);
typedef struct struct_io_manager *io_manager;
typedef struct struct_io_channel *io_channel;
......@@ -68,8 +72,14 @@ struct struct_io_manager {
#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
#define io_channel_flush(c) ((c)->manager->flush((c)))
/* unix_io.c */
extern io_manager unix_io_manager;
/* test_io.c */
extern io_manager test_io_manager, test_io_backing_manager;
extern void (*test_io_cb_read_blk)
(unsigned long block, int count, errcode_t err);
extern void (*test_io_cb_write_blk)
(unsigned long block, int count, errcode_t err);
extern void (*test_io_cb_set_blksize)
(int blksize, errcode_t err);
/*
* irel.h
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
struct ext2_inode_reference {
blk_t block;
__u16 offset;
};
struct ext2_inode_relocate_entry {
ino_t new;
ino_t orig;
__u16 flags;
__u16 max_refs;
};
typedef struct ext2_inode_relocation_table *ext2_irel;
struct ext2_inode_relocation_table {
__u32 magic;
char *name;
ino_t current;
void *private;
/*
* Add an inode relocation entry.
*/
errcode_t (*put)(ext2_irel irel, ino_t old,
struct ext2_inode_relocate_entry *ent);
/*
* Get an inode relocation entry.
*/
errcode_t (*get)(ext2_irel irel, ino_t old,
struct ext2_inode_relocate_entry *ent);
/*
* Get an inode relocation entry by its original inode number
*/
errcode_t (*get_by_orig)(ext2_irel irel, ino_t orig, ino_t *old,
struct ext2_inode_relocate_entry *ent);
/*
* Initialize for iterating over the inode relocation entries.
*/
errcode_t (*start_iter)(ext2_irel irel);
/*
* The iterator function for the inode relocation entries.
* Returns an inode number of 0 when out of entries.
*/
errcode_t (*next)(ext2_irel irel, ino_t *old,
struct ext2_inode_relocate_entry *ent);
/*
* Add an inode reference (i.e., note the fact that a
* particular block/offset contains a reference to an inode)
*/
errcode_t (*add_ref)(ext2_irel irel, ino_t ino,
struct ext2_inode_reference *ref);
/*
* Initialize for iterating over the inode references for a
* particular inode.
*/
errcode_t (*start_iter_ref)(ext2_irel irel, ino_t ino);
/*
* The iterator function for the inode references for an
* inode. The references for only one inode can be interator
* over at a time, as the iterator state is stored in ext2_irel.
*/
errcode_t (*next_ref)(ext2_irel irel,
struct ext2_inode_reference *ref);
/*
* Move the inode relocation table from one inode number to
* another. Note that the inode references also must move.
*/
errcode_t (*move)(ext2_irel irel, ino_t old, ino_t new);
/*
* Remove an inode relocation entry, along with all of the
* inode references.
*/
errcode_t (*delete)(ext2_irel irel, ino_t old);
/*
* Free the inode relocation table.
*/
errcode_t (*free)(ext2_irel irel);
};
errcode_t ext2fs_irel_memarray_create(char *name, ino_t max_inode,
ext2_irel *irel);
#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
((irel)->get_by_orig((irel), orig, old, ent))
#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
#define ext2fs_irel_free(irel) ((irel)->free((irel)))
/*
* irel_ma.c
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#include "irel.h"
static errcode_t ima_put(ext2_irel irel, ino_t old,
struct ext2_inode_relocate_entry *ent);
static errcode_t ima_get(ext2_irel irel, ino_t old,
struct ext2_inode_relocate_entry *ent);
static errcode_t ima_get_by_orig(ext2_irel irel, ino_t orig, ino_t *old,
struct ext2_inode_relocate_entry *ent);
static errcode_t ima_start_iter(ext2_irel irel);
static errcode_t ima_next(ext2_irel irel, ino_t *old,
struct ext2_inode_relocate_entry *ent);
static errcode_t ima_add_ref(ext2_irel irel, ino_t ino,
struct ext2_inode_reference *ref);
static errcode_t ima_start_iter_ref(ext2_irel irel, ino_t ino);
static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
static errcode_t ima_move(ext2_irel irel, ino_t old, ino_t new);
static errcode_t ima_delete(ext2_irel irel, ino_t old);
static errcode_t ima_free(ext2_irel irel);
/*
* This data structure stores the array of inode references; there is
* a structure for each inode.
*/
struct inode_reference_entry {
__u16 num;
struct ext2_inode_reference *refs;
};
struct irel_ma {
__u32 magic;
ino_t max_inode;
ino_t ref_current;
int ref_iter;
ino_t *orig_map;
struct ext2_inode_relocate_entry *entries;
struct inode_reference_entry *ref_entries;
};
errcode_t ext2fs_irel_memarray_create(char *name, ino_t max_inode,
ext2_irel *new_irel)
{
ext2_irel irel = 0;
errcode_t retval;
struct irel_ma *ma = 0;
size_t size;
*new_irel = 0;
/*
* Allocate memory structures
*/
retval = ENOMEM;
irel = malloc(sizeof(struct ext2_inode_relocation_table));
if (!irel)
goto errout;
memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
irel->name = malloc(strlen(name)+1);
if (!irel->name)
goto errout;
strcpy(irel->name, name);
ma = malloc(sizeof(struct irel_ma));
if (!ma)
goto errout;
memset(ma, 0, sizeof(struct irel_ma));
irel->private = ma;
size = sizeof(ino_t) * (max_inode+1);
ma->orig_map = malloc(size);
if (!ma->orig_map)
goto errout;
memset(ma->orig_map, 0, size);
size = sizeof(struct ext2_inode_relocate_entry) * (max_inode+1);
ma->entries = malloc(size);
if (!ma->entries)
goto errout;
memset(ma->entries, 0, size);
size = sizeof(struct inode_reference_entry) * (max_inode+1);
ma->ref_entries = malloc(size);
if (!ma->ref_entries)
goto errout;
memset(ma->ref_entries, 0, size);
ma->max_inode = max_inode;
/*
* Fill in the irel data structure
*/
irel->put = ima_put;
irel->get = ima_get;
irel->get_by_orig = ima_get_by_orig;
irel->start_iter = ima_start_iter;
irel->next = ima_next;
irel->add_ref = ima_add_ref;
irel->start_iter_ref = ima_start_iter_ref;
irel->next_ref = ima_next_ref;
irel->move = ima_move;
irel->delete = ima_delete;
irel->free = ima_free;
*new_irel = irel;
return 0;
errout:
ima_free(irel);
return retval;
}
static errcode_t ima_put(ext2_irel irel, ino_t old,
struct ext2_inode_relocate_entry *ent)
{
struct irel_ma *ma;
struct inode_reference_entry *ref_ent;
struct ext2_inode_reference *new_refs;
int size;
ma = irel->private;
if (old > ma->max_inode)
return EINVAL;
/*
* Force the orig field to the correct value; the application
* program shouldn't be messing with this field.
*/
if (ma->entries[old].new == 0)
ent->orig = old;
else
ent->orig = ma->entries[old].orig;
/*
* If max_refs has changed, reallocate the refs array
*/
ref_ent = ma->ref_entries + old;
if (ref_ent->refs && ent->max_refs != ma->entries[old].max_refs) {
size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
new_refs = realloc(ref_ent->refs, size);
if (!new_refs)
return ENOMEM;
ref_ent->refs = new_refs;
}
ma->entries[old] = *ent;
ma->orig_map[ent->orig] = old;
return 0;
}
static errcode_t ima_get(ext2_irel irel, ino_t old,
struct ext2_inode_relocate_entry *ent)
{
struct irel_ma *ma;
ma = irel->private;
if (old > ma->max_inode)
return EINVAL;
if (ma->entries[old].new == 0)
return ENOENT;
*ent = ma->entries[old];
return 0;
}
static errcode_t ima_get_by_orig(ext2_irel irel, ino_t orig, ino_t *old,
struct ext2_inode_relocate_entry *ent)
{
struct irel_ma *ma;
ino_t ino;
ma = irel->private;
if (orig > ma->max_inode)
return EINVAL;
ino = ma->orig_map[orig];
if (ino == 0)
return ENOENT;
*old = ino;
*ent = ma->entries[ino];
return 0;
}
static errcode_t ima_start_iter(ext2_irel irel)
{
irel->current = 0;
return 0;
}
static errcode_t ima_next(ext2_irel irel, ino_t *old,
struct ext2_inode_relocate_entry *ent)
{
struct irel_ma *ma;
ma = irel->private;
while (++irel->current < ma->max_inode) {
if (ma->entries[irel->current].new == 0)
continue;
*old = irel->current;
*ent = ma->entries[irel->current];
return 0;
}
*old = 0;
return 0;
}
static errcode_t ima_add_ref(ext2_irel irel, ino_t ino,
struct ext2_inode_reference *ref)
{
struct irel_ma *ma;
size_t size;
struct inode_reference_entry *ref_ent;
struct ext2_inode_relocate_entry *ent;
ma = irel->private;
if (ino > ma->max_inode)
return EINVAL;
ref_ent = ma->ref_entries + ino;
ent = ma->entries + ino;
/*
* If the inode reference array doesn't exist, create it.
*/
if (ref_ent->refs == 0) {
size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
ref_ent->refs = malloc(size);
if (ref_ent->refs == 0)
return ENOMEM;
memset(ref_ent->refs, 0, size);
ref_ent->num = 0;
}
if (ref_ent->num >= ent->max_refs)
return ENOSPC;
ref_ent->refs[ref_ent->num++] = *ref;
return 0;
}
static errcode_t ima_start_iter_ref(ext2_irel irel, ino_t ino)
{
struct irel_ma *ma;
ma = irel->private;
if (ino > ma->max_inode)
return EINVAL;
if (ma->entries[ino].new == 0)
return ENOENT;
ma->ref_current = ino;
ma->ref_iter = 0;
return 0;
}
static errcode_t ima_next_ref(ext2_irel irel,
struct ext2_inode_reference *ref)
{
struct irel_ma *ma;
struct inode_reference_entry *ref_ent;
ma = irel->private;
ref_ent = ma->ref_entries + ma->ref_current;
if ((ref_ent->refs == NULL) ||
(ma->ref_iter >= ref_ent->num)) {
ref->block = 0;
ref->offset = 0;
return 0;
}
*ref = ref_ent->refs[ma->ref_iter++];
return 0;
}
static errcode_t ima_move(ext2_irel irel, ino_t old, ino_t new)
{
struct irel_ma *ma;
ma = irel->private;
if ((old > ma->max_inode) || (new > ma->max_inode))
return EINVAL;
if (ma->entries[old].new == 0)
return ENOENT;
ma->entries[new] = ma->entries[old];
if (ma->ref_entries[new].refs)
free(ma->ref_entries[new].refs);
ma->ref_entries[new] = ma->ref_entries[old];
ma->entries[old].new = 0;
ma->ref_entries[old].num = 0;
ma->ref_entries[old].refs = 0;
ma->orig_map[ma->entries[new].orig] = new;
return 0;
}
static errcode_t ima_delete(ext2_irel irel, ino_t old)
{
struct irel_ma *ma;
ma = irel->private;
if (old > ma->max_inode)
return EINVAL;
if (ma->entries[old].new == 0)
return ENOENT;
ma->entries[old].new = 0;
if (ma->ref_entries[old].refs)
free(ma->ref_entries[old].refs);
ma->orig_map[ma->entries[old].orig] = 0;
ma->ref_entries[old].num = 0;
ma->ref_entries[old].refs = 0;
return 0;
}
static errcode_t ima_free(ext2_irel irel)
{
struct irel_ma *ma;
ino_t ino;
if (!irel)
return 0;
ma = irel->private;
if (ma) {
if (ma->orig_map)
free (ma->orig_map);
if (ma->entries)
free (ma->entries);
if (ma->ref_entries) {
for (ino = 0; ino <= ma->max_inode; ino++) {
if (ma->ref_entries[ino].refs)
free(ma->ref_entries[ino].refs);
}
free(ma->ref_entries);
}
free(ma);
}
if (irel->name)
free(irel->name);
free (irel);
return 0;
}
/*
* getsize.c --- get the size of a partition.
* ismounted.c --- Check to see if the filesystem was mounted
*
* Copyright (C) 1995 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......
/*
* link.c --- create or delete links in a ext2fs directory
* link.c --- create links in a ext2fs directory
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
......@@ -104,48 +108,3 @@ errcode_t ext2fs_link(ext2_filsys fs, ino_t dir, const char *name, ino_t ino,
return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
}
static int unlink_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private)
{
struct link_struct *ls = (struct link_struct *) private;
if (ls->name && (dirent->name_len != ls->namelen))
return 0;
if (ls->name && strncmp(ls->name, dirent->name, dirent->name_len))
return 0;
if (ls->inode && (dirent->inode != ls->inode))
return 0;
dirent->inode = 0;
ls->done++;
return DIRENT_ABORT|DIRENT_CHANGED;
}
errcode_t ext2fs_unlink(ext2_filsys fs, ino_t dir, const char *name, ino_t ino,
int flags)
{
errcode_t retval;
struct link_struct ls;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!(fs->flags & EXT2_FLAG_RW))
return EXT2_ET_RO_FILSYS;
ls.name = name;
ls.namelen = name ? strlen(name) : 0;
ls.inode = ino;
ls.flags = 0;
ls.done = 0;
retval = ext2fs_dir_iterate(fs, dir, 0, 0, unlink_proc, &ls);
if (retval)
return retval;
return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
}
/*
* llseek.c -- stub calling the llseek system call
*
* Copyright (C) 1994 Remy Card. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <sys/types.h>
......@@ -55,7 +59,7 @@ static ext2_loff_t llseek (unsigned int fd, ext2_loff_t offset,
#endif /* __alpha__ */
ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset,
ext2_loff_t ext2fs_llseek (unsigned int fd, ext2_loff_t offset,
unsigned int origin)
{
ext2_loff_t result;
......@@ -84,7 +88,7 @@ ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset,
#else /* !linux */
ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset,
ext2_loff_t ext2fs_llseek (unsigned int fd, ext2_loff_t offset,
unsigned int origin)
{
if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
......
/*
* lookup.c --- ext2fs directory lookup operations
*
* Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fs.h"
struct lookup_struct {
const char *name;
int len;
ino_t *inode;
int found;
};
static int lookup_proc(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private)
{
struct lookup_struct *ls = (struct lookup_struct *) private;
if (ls->len != dirent->name_len)
return 0;
if (strncmp(ls->name, dirent->name, dirent->name_len))
return 0;
*ls->inode = dirent->inode;
ls->found++;
return DIRENT_ABORT;
}
errcode_t ext2fs_lookup(ext2_filsys fs, ino_t dir, const char *name,
int namelen, char *buf, ino_t *inode)
{
errcode_t retval;
struct lookup_struct ls;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
ls.name = name;
ls.len = namelen;
ls.inode = inode;
ls.found = 0;
retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
if (retval)
return retval;
return (ls.found) ? 0 : ENOENT;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment