/*
 * ext2fs.h --- ext2fs
 */

#define SUPERBLOCK_NR	1
#define SUPERBLOCK_SIZE 1024

typedef unsigned long	blk_t;
typedef unsigned int	dgrp_t;

#include "et/com_err.h"
#include "io.h"
#include "ext2_err.h"

/*
 * 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

typedef struct struct_ext2_filsys *ext2_filsys;

struct struct_ext2_filsys {
	io_channel			io;
	int				flags;
	char *				device_name;
	struct ext2_super_block	* 	super;
	int				blocksize;
	unsigned long			group_desc_count;
	unsigned long			desc_blocks;
	struct ext2_group_desc *	group_desc;
	int				inode_blocks_per_group;
	char *				inode_map;
	char *				block_map;
	errcode_t (*get_blocks)(ext2_filsys fs, ino_t ino, blk_t *blocks);
	errcode_t (*check_directory)(ext2_filsys fs, ino_t ino);
};

#include "bitops.h"

/*
 * Return flags for the block iterator functions
 */
#define BLOCK_CHANGED	1
#define BLOCK_ABORT	2
#define BLOCK_ERROR	4

/*
 * Block interate flags
 */
#define BLOCK_FLAG_APPEND	1

/*
 * Return flags for the directory iterator functions
 */
#define DIRENT_CHANGED	1
#define DIRENT_ABORT	2
#define DIRENT_ERROR	3

/*
 * Directory iterator flags
 */

#define DIRENT_FLAG_INCLUDE_EMPTY	1

/*
 * Inode scan definitions
 */
struct struct_inode_scan {
	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;
	struct ext2_inode *	inode_scan_ptr;
};

typedef struct struct_inode_scan *inode_scan;

/*
 * function prototypes
 */

/* openfs.c */
extern inline void ext2fs_mark_super_dirty(ext2_filsys fs)
{
	fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED;
}
extern inline void ext2fs_mark_changed(ext2_filsys fs)
{
	fs->flags |= EXT2_FLAG_CHANGED;
}
extern inline int ext2fs_test_changed(ext2_filsys fs)
{
	return (fs->flags & EXT2_FLAG_CHANGED);
}
extern inline void ext2fs_mark_valid(ext2_filsys fs)
{
	fs->flags |= EXT2_FLAG_VALID;
}
extern inline void ext2fs_unmark_valid(ext2_filsys fs)
{
	fs->flags &= ~EXT2_FLAG_VALID;
}
extern inline int ext2fs_test_valid(ext2_filsys fs)
{
	return (fs->flags & EXT2_FLAG_VALID);
}
extern inline void ext2fs_mark_ib_dirty(ext2_filsys fs)
{
	fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED;
}
extern inline void ext2fs_mark_bb_dirty(ext2_filsys fs)
{
	fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED;
}
extern inline int ext2fs_test_ib_dirty(ext2_filsys fs)
{
	return (fs->flags & EXT2_FLAG_IB_DIRTY);
}
extern inline int ext2fs_test_bb_dirty(ext2_filsys fs)
{
	return (fs->flags & EXT2_FLAG_BB_DIRTY);
}

extern void ext2fs_free(ext2_filsys fs);
extern errcode_t ext2fs_open(char *name, int flags, int superblock,
			     int block_size, io_manager manager,
			     ext2_filsys *ret_fs);
extern errcode_t ext2fs_close(ext2_filsys fs);
extern errcode_t ext2_check_desc(ext2_filsys fs);

/* alloc.c */
extern errcode_t ext2fs_new_inode(ext2_filsys fs, ino_t dir, int mode,
				  char *map, ino_t *ret);
extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
				  char *map, blk_t *ret);

/* bitmaps.c */
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, char **ret);
extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, char **ret);

/* block.c */
errcode_t ext2fs_block_iterate(ext2_filsys fs,
			       ino_t	ino,
			       int	flags,
			       char *block_buf,
			       int (*func)(ext2_filsys fs,
					   blk_t	*blocknr,
					   int	blockcnt,
					   void	*private),
			       void *private);

/* expanddir.c */
extern int ext2fs_expand_dir(ext2_filsys fs, ino_t dir);

/* inode.c */
extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
				  inode_scan *ret_scan);
extern void ext2fs_close_inode_scan(inode_scan scan);
extern errcode_t ext2fs_get_next_inode(inode_scan scan, ino_t *ino,
			       struct ext2_inode *inode);
extern errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
			    struct ext2_inode * inode);
extern errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long 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);

/* 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, char *name,
			 int namelen, char *buf, ino_t *inode);
extern errcode_t ext2fs_namei(ext2_filsys fs, ino_t root, ino_t cwd,
			char *name, ino_t *inode);
extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ino_t dir_ino,
				ino_t parent_ino, char **block);

/* get_pathname.c */
extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ino_t dir, ino_t ino,
			       char **name);

/* link.c */
errcode_t ext2fs_link(ext2_filsys fs, ino_t dir, char *name,
		      ino_t ino, int flags);
errcode_t ext2fs_unlink(ext2_filsys fs, ino_t dir, char *name,
			ino_t ino, int flags);

