Import backup from 2005-06-21
This commit is contained in:
1 parent
da90bcc164
commit
2cefd9441c
15 files changed
+160
-207
No files matched your search
@@ -0,0 +1,37 @@
|
||||
// ext2.cpp
|
||||
// ext2 filesystem driver for HOS
|
||||
// Author: Josh Holtrop
|
||||
// Date: 05/10/05
|
||||
// Modified: 05/10/05
|
||||
|
||||
#define _HOS_CPP_ _HOS_CPP_
|
||||
|
||||
extern "C" {
|
||||
#include "display/kout.h"
|
||||
}
|
||||
|
||||
#include "ext2.h"
|
||||
|
||||
Ext2fs::Ext2fs(device_t dev)
|
||||
{
|
||||
myDevice = dev;
|
||||
if (block_read(DEV_MAJOR(dev), DEV_MINOR(dev), 2, 2, &mySuper) < 1024)
|
||||
{
|
||||
myError = -1;
|
||||
return;
|
||||
}
|
||||
if (mySuper.s_magic != EXT2_MAGIC)
|
||||
{
|
||||
myError = -2;
|
||||
return;
|
||||
}
|
||||
myError = 0;
|
||||
mySuperDirty = 0;
|
||||
kprintf("Device: %d\n", myDevice);
|
||||
}
|
||||
|
||||
Ext2fs::~Ext2fs()
|
||||
{
|
||||
if (mySuperDirty)
|
||||
block_write(DEV_MAJOR(myDevice), DEV_MINOR(myDevice), 2, 2, &mySuper);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// ext2.h
|
||||
// ext2 filesystem driver for HOS
|
||||
// Author: Josh Holtrop
|
||||
// Date: 05/10/05
|
||||
// Modified: 05/23/05
|
||||
|
||||
#ifndef __HOS_EXT2_H__
|
||||
#define __HOS_EXT2_H__ __HOS_EXT2_H__
|
||||
|
||||
#define EXT2_MAGIC 0xEF53
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
#define EXT2_I_MODE_ATTR_MASK 0x0FFF
|
||||
#define EXT2_I_MODE_OX 0x0001
|
||||
#define EXT2_I_MODE_OW 0x0002
|
||||
#define EXT2_I_MODE_OR 0x0004
|
||||
#define EXT2_I_MODE_GX 0x0008
|
||||
#define EXT2_I_MODE_GW 0x0010
|
||||
#define EXT2_I_MODE_GR 0x0020
|
||||
#define EXT2_I_MODE_UX 0x0040
|
||||
#define EXT2_I_MODE_UW 0x0080
|
||||
#define EXT2_I_MODE_UR 0x0100
|
||||
#define EXT2_I_MODE_STICKY 0x0200
|
||||
#define EXT2_I_MODE_SGID 0x0400
|
||||
#define EXT2_I_MODE_SUID 0x0800
|
||||
|
||||
#define EXT2_I_MODE_TYPE_MASK 0xF000
|
||||
#define EXT2_I_MODE_FIFO 0x1000
|
||||
#define EXT2_I_MODE_CHAR 0x2000
|
||||
#define EXT2_I_MODE_DIR 0x4000
|
||||
#define EXT2_I_MODE_BLOCK 0x6000
|
||||
#define EXT2_I_MODE_FILE 0x8000
|
||||
#define EXT2_I_MODE_SYM 0xA000
|
||||
#define EXT2_I_MODE_SOCK 0xC000
|
||||
|
||||
#define EXT2_I_FLAGS_SEC_DEL 0x01
|
||||
#define EXT2_I_FLAGS_UNDELETE 0x02
|
||||
#define EXT2_I_FLAGS_COMPRESS 0x04
|
||||
#define EXT2_I_FLAGS_SYNC 0x08
|
||||
#define EXT2_I_FLAGS_IMMUTABLE 0x10
|
||||
#define EXT2_I_FLAGS_APPEND 0x20
|
||||
#define EXT2_I_FLAGS_NODUMP 0x40
|
||||
|
||||
#define EXT2_INODE_BAD_BLOCKS 1
|
||||
#define EXT2_INODE_ROOT 2
|
||||
#define EXT2_INODE_ACL_INDEX 3
|
||||
#define EXT2_INODE_ACL_DATA 4
|
||||
#define EXT2_INODE_BOOT_LOADER 5
|
||||
#define EXT2_INODE_UNDELETE_DIR 6
|
||||
#define EXT2_INODE_AVAIL 11
|
||||
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHAR 3
|
||||
#define EXT2_FT_BLOCK 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
#include "fs/vfs.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t s_inodes_count; /* Inodes count */
|
||||
u32_t s_blocks_count; /* Blocks count */
|
||||
u32_t s_r_blocks_count; /* Reserved blocks count */
|
||||
u32_t s_free_blocks_count; /* Free blocks count */
|
||||
u32_t s_free_inodes_count; /* Free inodes count */
|
||||
u32_t s_first_data_block; /* First Data Block */
|
||||
u32_t s_log_block_size; /* Block size: 0->1024, 1->2048, 2->4096 */
|
||||
int s_log_frag_size; /* Fragment size */
|
||||
u32_t s_blocks_per_group; /* # Blocks per group */
|
||||
u32_t s_frags_per_group; /* # Fragments per group */
|
||||
u32_t s_inodes_per_group; /* # Inodes per group */
|
||||
u32_t s_mtime; /* Mount time */
|
||||
u32_t s_wtime; /* Write time */
|
||||
u16_t s_mnt_count; /* Mount count */
|
||||
short s_max_mnt_count; /* Maximal mount count */
|
||||
u16_t s_magic; /* Magic signature */
|
||||
u16_t s_state; /* File system state */
|
||||
u16_t s_errors; /* Behaviour when detecting errors */
|
||||
u16_t s_minor_rev_level; /* minor revision level */
|
||||
u32_t s_lastcheck; /* time of last check */
|
||||
u32_t s_checkinterval; /* max. time between checks */
|
||||
u32_t s_creator_os; /* OS */
|
||||
u32_t s_rev_level; /* Revision level */
|
||||
u16_t s_def_resuid; /* Default uid for reserved blocks */
|
||||
u16_t s_def_resgid; /* Default gid for reserved blocks */
|
||||
|
||||
u32_t s_reserved[235];
|
||||
} ext2_super_block_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t bg_block_bitmap; // Blocks bitmap block
|
||||
u32_t bg_inode_bitmap; // Inode bitmap block
|
||||
u32_t bg_inode_table; // Inode table block
|
||||
u16_t bg_free_blocks_count; // Free blocks count
|
||||
u16_t bg_free_inodes_count; // Free Inodes count
|
||||
u16_t bg_used_dirs_count; // Directories count
|
||||
u16_t bg_pad1;
|
||||
u32_t bg_reserved[3];
|
||||
} ext2_group_desc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16_t i_mode; // File mode
|
||||
u16_t i_uid; // Owner UID
|
||||
u32_t i_size; // Size in bytes
|
||||
u32_t i_atime; // Access time
|
||||
u32_t i_ctime; // Creation time
|
||||
u32_t i_mtime; // Modification time
|
||||
u32_t i_dtime; // Deletion time
|
||||
u16_t i_gid; // Group ID
|
||||
u16_t i_links_count; // Links count
|
||||
u32_t i_blocks; // Blocks count
|
||||
u32_t i_flags; // File flags
|
||||
u32_t i_reserved1;
|
||||
u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect)
|
||||
u32_t i_version; // File version (for NFS)
|
||||
u32_t i_file_acl; // File ACL
|
||||
u32_t i_dir_acl; // Directory ACL
|
||||
u32_t i_faddr; // Fragment address
|
||||
u8_t i_frag; // Fragment number
|
||||
u8_t i_fsize; // Fragment size
|
||||
u16_t i_pad1;
|
||||
u32_t i_reserved2[2];
|
||||
} ext2_inode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t inode; // inode number
|
||||
u16_t length; // directory entry length
|
||||
u8_t name_length; // name length
|
||||
u8_t file_type; // File type
|
||||
char name[EXT2_NAME_LEN];
|
||||
} ext2_dir_entry_t;
|
||||
|
||||
#ifdef _HOS_CPP_
|
||||
|
||||
class Ext2fs : public FileSystem
|
||||
{
|
||||
protected:
|
||||
ext2_super_block_t mySuper;
|
||||
int mySuperDirty;
|
||||
public:
|
||||
Ext2fs(device_t dev);
|
||||
~Ext2fs();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,762 @@
|
||||
// ext2.c
|
||||
// Author: Josh Holtrop
|
||||
// Date: 08/22/04
|
||||
// Modified: 12/24/04
|
||||
|
||||
#include "hos_defines.h"
|
||||
#include "fs/devices.h"
|
||||
#include "display/kout.h"
|
||||
#include "ext2.h"
|
||||
#include "mm/vmm.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "lang/lang.h"
|
||||
#include "functions.h"
|
||||
|
||||
/* Turning an inode number into a (group, inode_index) pair:
|
||||
* group = (inode - 1) / s_inodes_per_group
|
||||
* index = (inode - 1) % s_inodes_per_group
|
||||
*/
|
||||
|
||||
vfs_fs_t ext2_driver = {ext2_mount_super, ext2_umount_super, ext2_stat,
|
||||
ext2__get_root_dir_inode, ext2__link_deref,
|
||||
ext2__free_inodes, ext2__total_inodes,
|
||||
ext2__free_blocks, ext2__total_blocks,
|
||||
ext2_alloc_inode, ext2_free_inode, ext2_alloc_block, ext2_free_block,
|
||||
ext2__open_dir, ext2__read_dir, ext2__close_dir,
|
||||
ext2__open_file, ext2__read_file, ext2__close_file,
|
||||
ext2__open_block_file, ext2__read_block_file, ext2__block_file_seek, ext2__close_block_file};
|
||||
|
||||
// initialize the filesystem driver
|
||||
int ext2_init(int fsID)
|
||||
{
|
||||
vfs_fs_t *fs;
|
||||
if (( fs = New(vfs_fs_t) )) // give the VFS our FS structure
|
||||
{
|
||||
*fs = ext2_driver;
|
||||
vfs_register_fs(fsID, fs);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// lookup a file name in a directory and store the directory entry for it
|
||||
int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry)
|
||||
{
|
||||
ext2_open_dir_t *dir = ext2_open_dir(mount, dir_inode);
|
||||
if (!dir)
|
||||
return -1; // bad directory inode number
|
||||
ext2_dir_entry_t dentry;
|
||||
while (!ext2_dir_read_entry(mount, dir, &dentry))
|
||||
{
|
||||
char *dentryName = kcalloc(1, dentry.name_length + 1);
|
||||
memcpy(dentryName, dentry.name, dentry.name_length);
|
||||
int res = strcmp(fileName, dentryName);
|
||||
kfree(dentryName);
|
||||
if (!res)
|
||||
{
|
||||
*direntry = dentry;
|
||||
ext2_close_dir(mount, dir);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ext2_close_dir(mount, dir);
|
||||
return -2;
|
||||
}
|
||||
|
||||
// open a directory by inode number for reading
|
||||
ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number)
|
||||
{
|
||||
ext2_open_dir_t *open_dir = New(ext2_open_dir_t);
|
||||
ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number);
|
||||
if (!open_inode)
|
||||
{
|
||||
kfree(open_dir);
|
||||
return NULL;
|
||||
}
|
||||
if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_DIR)
|
||||
{
|
||||
ext2_close_inode(mount, open_inode);
|
||||
kfree(open_dir);
|
||||
return NULL;
|
||||
}
|
||||
open_dir->open_inode = open_inode;
|
||||
open_dir->position = 0;
|
||||
return open_dir;
|
||||
}
|
||||
|
||||
int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (open_dir->position >= open_dir->open_inode->inode.i_size)
|
||||
return -1; // EOF
|
||||
u32_t dir_block = open_dir->position >> (10 + super->s_log_block_size);
|
||||
char *block = kmalloc(2048 << super->s_log_block_size);
|
||||
ext2_inode_seek(mount, open_dir->open_inode, dir_block);
|
||||
if (ext2_read_inode_block(mount, open_dir->open_inode, block))
|
||||
ext2_read_inode_block(mount, open_dir->open_inode, block + (1024 << super->s_log_block_size));
|
||||
ext2_dir_entry_t *dir_entry = (ext2_dir_entry_t *)(block + open_dir->position % (1024 << super->s_log_block_size));
|
||||
if (!dir_entry->inode)
|
||||
{
|
||||
kfree(block);
|
||||
return -2; // EOF
|
||||
}
|
||||
memcpy(dentry, dir_entry, min(dir_entry->length, sizeof(ext2_dir_entry_t)));
|
||||
open_dir->position += dir_entry->length;
|
||||
kfree(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir)
|
||||
{
|
||||
ext2_close_inode(mount, open_dir->open_inode);
|
||||
kfree(open_dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// open an inode for reading
|
||||
ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number)
|
||||
{
|
||||
ext2_open_inode_t *open_inode = New(ext2_open_inode_t);
|
||||
if ( ext2_read_inode(mount, inode_number, &(open_inode->inode)) )
|
||||
{
|
||||
kfree(open_inode);
|
||||
return NULL;
|
||||
}
|
||||
open_inode->block = 0;
|
||||
open_inode->block_pointers = NULL;
|
||||
open_inode->block_pointers_start = 0;
|
||||
mount->refs++;
|
||||
return open_inode;
|
||||
}
|
||||
|
||||
|
||||
// seek to a certain block of an open inode
|
||||
int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (open_inode->inode.i_size <= (block_number << (10 + super->s_log_block_size)))
|
||||
return -1; // at or past EOF
|
||||
open_inode->block = block_number;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns number of bytes read
|
||||
int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (open_inode->inode.i_size <= (open_inode->block << (10 + super->s_log_block_size)))
|
||||
return 0; // at or past EOF
|
||||
u32_t leftover_bytes = open_inode->inode.i_size - (open_inode->block << (10 + super->s_log_block_size));
|
||||
u32_t block_number = ext2_block_number(mount, open_inode);
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_number, super),
|
||||
2 << super->s_log_block_size, block);
|
||||
open_inode->block++;
|
||||
return min(leftover_bytes, 1024 << super->s_log_block_size);
|
||||
}
|
||||
|
||||
|
||||
// close an open inode
|
||||
int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode)
|
||||
{
|
||||
mount->refs--;
|
||||
if (open_inode->block_pointers)
|
||||
kfree(open_inode->block_pointers); // free the block pointers cache
|
||||
kfree(open_inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// check the status of an inode (1-based inode number)
|
||||
// -1: invalid inode number
|
||||
// 0: free inode
|
||||
// 1: allocated inode
|
||||
int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (inode_number < 1 || inode_number > super->s_inodes_count) // inode number invalid
|
||||
return -1;
|
||||
inode_number--; // turn inode_number into a 0-based index
|
||||
u32_t group = inode_number / super->s_inodes_per_group;
|
||||
u32_t index = inode_number % super->s_inodes_per_group;
|
||||
u32_t inode_bitmap_block = ext2_get_group_desc(mount, group).bg_inode_bitmap + (index >> (13 + super->s_log_block_size));
|
||||
u32_t bitmap_index = index % (8192 << super->s_log_block_size);
|
||||
u8_t *inode_bitmap = kmalloc(1024 << super->s_log_block_size);
|
||||
block_read(mount->major, mount->minor,
|
||||
ext2_FSToDiskBlock(inode_bitmap_block, super), 2 << super->s_log_block_size, inode_bitmap);
|
||||
int inode_status = (inode_bitmap[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1;
|
||||
kfree(inode_bitmap);
|
||||
return inode_status;
|
||||
}
|
||||
|
||||
|
||||
// check the status of a block
|
||||
// -1: invalid block number
|
||||
// 0: free block
|
||||
// 1: allocated block
|
||||
int ext2_block_status(vfs_mount_t *mount, u32_t block_number)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (block_number < super->s_first_data_block || block_number > super->s_blocks_count) // block number invalid
|
||||
return -1;
|
||||
block_number -= super->s_first_data_block;
|
||||
u32_t group = block_number / super->s_blocks_per_group;
|
||||
u32_t index = block_number % super->s_blocks_per_group;
|
||||
u32_t block_bitmap_block = ext2_get_group_desc(mount, group).bg_block_bitmap + (index >> (13 + super->s_log_block_size));
|
||||
u32_t bitmap_index = index % (8192 << super->s_log_block_size);
|
||||
u8_t *block_bitmap = kmalloc(1024 << super->s_log_block_size);
|
||||
block_read(mount->major, mount->minor,
|
||||
ext2_FSToDiskBlock(block_bitmap_block, super), 2 << super->s_log_block_size, block_bitmap);
|
||||
int block_status = (block_bitmap[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1;
|
||||
kfree(block_bitmap);
|
||||
return block_status;
|
||||
}
|
||||
|
||||
|
||||
// transform open_inode->block (a relative block number) to an absolute block number for the filesystem
|
||||
u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode)
|
||||
{
|
||||
if (open_inode->block < 12)
|
||||
return open_inode->inode.i_block[open_inode->block];
|
||||
ext2_super_block_t *super = mount->super;
|
||||
int pointersPerBlock = 256 << super->s_log_block_size;
|
||||
if (open_inode->block_pointers && // there is a block pointers cache block allocated
|
||||
(open_inode->block >= open_inode->block_pointers_start) && // and the block number is in it
|
||||
(open_inode->block < (open_inode->block_pointers_start + pointersPerBlock)))
|
||||
return open_inode->block_pointers[open_inode->block - open_inode->block_pointers_start];
|
||||
u32_t rel_block = open_inode->block - 12;
|
||||
if (!open_inode->block_pointers)
|
||||
open_inode->block_pointers = kmalloc(pointersPerBlock << 2);
|
||||
if (rel_block < pointersPerBlock) // indirect block in i_block[12]
|
||||
{
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[12], super),
|
||||
2 << super->s_log_block_size, open_inode->block_pointers);
|
||||
open_inode->block_pointers_start = 12;
|
||||
return open_inode->block_pointers[rel_block];
|
||||
}
|
||||
rel_block -= pointersPerBlock;
|
||||
if (rel_block < (pointersPerBlock * pointersPerBlock)) // double-indirect block in i_block[13]
|
||||
{
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[13], super),
|
||||
2 << super->s_log_block_size, open_inode->block_pointers);
|
||||
u32_t real_block = open_inode->block_pointers[rel_block / pointersPerBlock];
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(real_block, super),
|
||||
2 << super->s_log_block_size, open_inode->block_pointers);
|
||||
open_inode->block_pointers_start = 12 + pointersPerBlock + rel_block - (rel_block % pointersPerBlock);
|
||||
return open_inode->block_pointers[rel_block % pointersPerBlock];
|
||||
}
|
||||
// this code shouldn't run unless we are dealing with a 65+mb file ...
|
||||
rel_block -= pointersPerBlock * pointersPerBlock;
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[14], super),
|
||||
2 << super->s_log_block_size, open_inode->block_pointers);
|
||||
u32_t index_1 = rel_block / (pointersPerBlock * pointersPerBlock);
|
||||
u32_t leftover_1 = rel_block % (pointersPerBlock * pointersPerBlock);
|
||||
u32_t block_1 = open_inode->block_pointers[index_1];
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_1, super),
|
||||
2 << super->s_log_block_size, open_inode->block_pointers);
|
||||
u32_t index_2 = leftover_1 / pointersPerBlock;
|
||||
u32_t leftover_2 = leftover_1 % pointersPerBlock;
|
||||
u32_t block_2 = open_inode->block_pointers[index_2];
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_2, super),
|
||||
2 << super->s_log_block_size, open_inode->block_pointers);
|
||||
open_inode->block_pointers_start = 12 + (pointersPerBlock + 1) * pointersPerBlock + rel_block - (rel_block % pointersPerBlock);
|
||||
return open_inode->block_pointers[leftover_2];
|
||||
}
|
||||
|
||||
|
||||
// read the inode structure from the device
|
||||
int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat)
|
||||
{
|
||||
if (ext2_inode_status(mount, inode) != 1)
|
||||
return -1; // free or invalid inode number
|
||||
ext2_super_block_t *super = mount->super;
|
||||
inode--; // turn inode into a 0-based index
|
||||
u32_t group = inode / super->s_inodes_per_group;
|
||||
u32_t index = inode % super->s_inodes_per_group;
|
||||
u32_t inodeAddr = (ext2_get_group_desc(mount, group).bg_inode_table <<
|
||||
(10 + super->s_log_block_size)) + (index << 7);
|
||||
void *block = kmalloc(512);
|
||||
block_read(mount->major, mount->minor, inodeAddr >> 9, 1, block);
|
||||
memcpy(dat, (block + (inodeAddr & 0x1FF)), sizeof(ext2_inode_t));
|
||||
kfree(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// write an inode structure to the device
|
||||
int ext2_write_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat)
|
||||
{
|
||||
if (ext2_inode_status(mount, inode) != 1)
|
||||
return -1; // free or invalid inode number
|
||||
ext2_super_block_t *super = mount->super;
|
||||
inode--; // turn inode into a 0-based index
|
||||
u32_t group = inode / super->s_inodes_per_group;
|
||||
u32_t index = inode % super->s_inodes_per_group;
|
||||
u32_t inodeAddr = (ext2_get_group_desc(mount, group).bg_inode_table <<
|
||||
(10 + super->s_log_block_size)) + (index << 7);
|
||||
void *block = kmalloc(512);
|
||||
block_read(mount->major, mount->minor, inodeAddr >> 9, 1, block);
|
||||
memcpy( (block + (inodeAddr & 0x1FF)), dat, sizeof(ext2_inode_t));
|
||||
block_write(mount->major, mount->minor, inodeAddr >> 9, 1, block);
|
||||
kfree(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read the group descriptor structure from the device and return it
|
||||
ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
u32_t groupDescAddr = ((1 + super->s_first_data_block) << (10 + super->s_log_block_size)) + (group << 5);
|
||||
void *block = kmalloc(512);
|
||||
block_read(mount->major, mount->minor, groupDescAddr >> 9, 1, block);
|
||||
ext2_group_desc_t gd = *(ext2_group_desc_t *)(block + (groupDescAddr & 0x1FF));
|
||||
kfree(block);
|
||||
return gd;
|
||||
}
|
||||
|
||||
// write the group descriptor structure to the device
|
||||
void ext2_write_group_desc(vfs_mount_t *mount, u32_t group_num, ext2_group_desc_t *gd)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
u32_t groupDescAddr = ((1 + super->s_first_data_block) << (10 + super->s_log_block_size)) + (group_num << 5);
|
||||
void *block = kmalloc(512);
|
||||
block_read(mount->major, mount->minor, groupDescAddr >> 9, 1, block);
|
||||
memcpy( (block + (groupDescAddr & 0x1FF)), gd, sizeof(ext2_group_desc_t) );
|
||||
block_write(mount->major, mount->minor, groupDescAddr >> 9, 1, block);
|
||||
kfree(block);
|
||||
}
|
||||
|
||||
// allocate an inode and return its number
|
||||
u32_t ext2_alloc_inode(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (!super->s_free_inodes_count)
|
||||
return 0; // no free inodes
|
||||
int bg, bg_max = ext2_num_block_groups(super);
|
||||
for (bg = 0; bg < bg_max; bg++)
|
||||
{
|
||||
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
|
||||
if (group_desc.bg_free_inodes_count)
|
||||
{
|
||||
u32_t node = ext2_reserve_node(mount, group_desc.bg_inode_bitmap, super->s_inodes_per_group);
|
||||
group_desc.bg_free_inodes_count--;
|
||||
ext2_write_group_desc(mount, bg, &group_desc);
|
||||
super->s_free_inodes_count--;
|
||||
return bg * super->s_inodes_per_group + node + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (inode_number < 11 || inode_number > super->s_inodes_count)
|
||||
return -1; // invalid inode number
|
||||
if (ext2_inode_status(mount, inode_number) != 1)
|
||||
return -2; // inode not allocated
|
||||
inode_number--; // now a 0-based inode number
|
||||
int bg = inode_number / super->s_inodes_per_group;
|
||||
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
|
||||
ext2_free_node(mount, group_desc.bg_inode_bitmap, inode_number % super->s_inodes_per_group);
|
||||
group_desc.bg_free_inodes_count++;
|
||||
ext2_write_group_desc(mount, bg, &group_desc);
|
||||
super->s_free_inodes_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allocate a block and return its number
|
||||
u32_t ext2_alloc_block(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (!super->s_free_blocks_count)
|
||||
return 0; // no free blocks
|
||||
int bg, bg_max = ext2_num_block_groups(super);
|
||||
for (bg = 0; bg < bg_max; bg++)
|
||||
{
|
||||
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
|
||||
if (group_desc.bg_free_blocks_count)
|
||||
{
|
||||
u32_t node = ext2_reserve_node(mount, group_desc.bg_block_bitmap, super->s_blocks_per_group);
|
||||
group_desc.bg_free_blocks_count--;
|
||||
ext2_write_group_desc(mount, bg, &group_desc);
|
||||
super->s_free_blocks_count--;
|
||||
return bg * super->s_blocks_per_group + node + super->s_first_data_block;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2_free_block(vfs_mount_t *mount, u32_t block_number)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
if (block_number < super->s_first_data_block || block_number > (super->s_blocks_count + super->s_first_data_block - 1))
|
||||
return -1; // invalid block number
|
||||
if (ext2_block_status(mount, block_number) != 1)
|
||||
return -2; // block not allocated
|
||||
block_number -= super->s_first_data_block; // now a 0-based block number
|
||||
int bg = block_number / super->s_blocks_per_group;
|
||||
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
|
||||
ext2_free_node(mount, group_desc.bg_block_bitmap, block_number % super->s_blocks_per_group);
|
||||
group_desc.bg_free_blocks_count++;
|
||||
ext2_write_group_desc(mount, bg, &group_desc);
|
||||
super->s_free_blocks_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size)
|
||||
{
|
||||
ext2_inode_t inode;
|
||||
if ( ext2_read_inode(mount, inode_number, &inode) )
|
||||
return -1;
|
||||
ext2_super_block_t *super = mount->super;
|
||||
int current_blocks = (inode.i_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size);
|
||||
int new_blocks = (new_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size);
|
||||
if ( new_blocks == current_blocks )
|
||||
return 0;
|
||||
|
||||
// TODO: resize
|
||||
u32_t block_size = 1024 << super->s_log_block_size;
|
||||
u32_t pointers_per_block = block_size >> 2;
|
||||
u32_t *pointer_cache1 = kmalloc(3 * block_size);
|
||||
u32_t *pointer_cache2 = pointer_cache1 + pointers_per_block;
|
||||
u32_t *pointer_cache3 = pointer_cache2 + pointers_per_block;
|
||||
u32_t c1_start, c2_start, c3_start;
|
||||
c1_start = c2_start = c3_start = 0;
|
||||
while (new_blocks < current_blocks) // delete, decrease current_blocks
|
||||
{
|
||||
current_blocks--;
|
||||
// now delete block number current_blocks
|
||||
|
||||
}
|
||||
|
||||
while (current_blocks < new_blocks) // add, increase current_blocks
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// reserve a node of a inode or block bitmap and mark its entry allocated
|
||||
u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
u32_t *bitmap = kmalloc(1024 << super->s_log_block_size);
|
||||
int block, max_block = (bitmap_size - 1) / (8192 << super->s_log_block_size) + 1;
|
||||
for (block = 0; block < max_block; block++)
|
||||
{
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block, super),
|
||||
2 << super->s_log_block_size, bitmap);
|
||||
int num, num_max = 256 << super->s_log_block_size;
|
||||
u32_t *block_pointer = bitmap;
|
||||
int done = 0;
|
||||
for (num = 0; num < num_max && !done; num++)
|
||||
{
|
||||
if (*block_pointer != 0xFFFFFFFF)
|
||||
{
|
||||
done = 1;
|
||||
int bit;
|
||||
for (bit = 0; bit < 32; bit++)
|
||||
{
|
||||
if (!(*block_pointer & (1 << bit)))
|
||||
{
|
||||
u32_t node_number = (block * 8192 << super->s_log_block_size) + (num << 5) + bit;
|
||||
if (node_number < bitmap_size)
|
||||
{
|
||||
// found a node, mark it allocated, write the bitmap, return
|
||||
*block_pointer |= (1 << bit);
|
||||
block_write(mount->major, mount->minor,
|
||||
ext2_FSToDiskBlock(bitmap_block_num + block, super),
|
||||
2 << super->s_log_block_size, bitmap);
|
||||
kfree(bitmap);
|
||||
return node_number;
|
||||
}
|
||||
kfree(bitmap);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
block_pointer++;
|
||||
}
|
||||
}
|
||||
kfree(bitmap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
u32_t block_num = node_number >> (13 + super->s_log_block_size);
|
||||
byte *block = kmalloc(1024 << super->s_log_block_size);
|
||||
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block_num, super),
|
||||
2 << super->s_log_block_size, block);
|
||||
u32_t node_bit_offset = node_number % (8192 << super->s_log_block_size);
|
||||
u32_t node_byte_offset = node_bit_offset >> 3;
|
||||
block[node_byte_offset] &= (0xFF ^ (1 << (node_bit_offset & 0x7)));
|
||||
block_write(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block_num, super),
|
||||
2 << super->s_log_block_size, block);
|
||||
kfree(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return how many block groups are on the filesystem
|
||||
int ext2_num_block_groups(ext2_super_block_t *super)
|
||||
{
|
||||
return (super->s_inodes_count / super->s_inodes_per_group) + 1;
|
||||
}
|
||||
|
||||
void ext2_write_super(vfs_mount_t *mount)
|
||||
{
|
||||
block_write(mount->major, mount->minor, 2, 2, mount->super);
|
||||
}
|
||||
|
||||
|
||||
/***************** VFS INTERFACE FUNCTIONS *******************/
|
||||
|
||||
|
||||
// mount the superblock of the filesystem and return a pointer to it, if valid
|
||||
void *ext2_mount_super(major_t major, minor_t minor)
|
||||
{
|
||||
ext2_super_block_t *super = kmalloc(1024);
|
||||
block_read(major, minor, 2, 2, super);
|
||||
if (super->s_magic != EXT2_MAGIC) // not an ext2 filesystem
|
||||
{
|
||||
kfree(super);
|
||||
return NULL;
|
||||
}
|
||||
return super;
|
||||
}
|
||||
|
||||
|
||||
// called when we are unmounting this filesystem mount
|
||||
int ext2_umount_super(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_write_super(mount);
|
||||
return kfree(mount->super); // free memory that the superblock was taking
|
||||
}
|
||||
|
||||
|
||||
// stat a file, return a structure of info about it
|
||||
int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat)
|
||||
{
|
||||
if (ext2_inode_status(mount, inode_number) != 1)
|
||||
return -1;
|
||||
ext2_inode_t *inode = New(ext2_inode_t);
|
||||
if ( ext2_read_inode(mount, inode_number, inode) )
|
||||
{
|
||||
kfree(inode);
|
||||
return -2;
|
||||
}
|
||||
|
||||
stat->dev = 0;
|
||||
switch(inode->i_mode & EXT2_I_MODE_TYPE_MASK)
|
||||
{
|
||||
case EXT2_I_MODE_FIFO: stat->type = VFS_FT_FIFO; break;
|
||||
case EXT2_I_MODE_CHAR: stat->type = VFS_FT_CHAR; stat->dev = inode->i_block[0]; break;
|
||||
case EXT2_I_MODE_DIR: stat->type = VFS_FT_DIR; break;
|
||||
case EXT2_I_MODE_BLOCK: stat->type = VFS_FT_BLOCK; stat->dev = inode->i_block[0]; break;
|
||||
case EXT2_I_MODE_FILE: stat->type = VFS_FT_FILE; break;
|
||||
case EXT2_I_MODE_SYM: stat->type = VFS_FT_SYMLINK; break;
|
||||
case EXT2_I_MODE_SOCK: stat->type = VFS_FT_SOCK; break;
|
||||
default: stat->type = VFS_FT_UNKNOWN; break;
|
||||
}
|
||||
stat->size = inode->i_size;
|
||||
stat->inode = inode_number;
|
||||
stat->permissions = inode->i_mode & EXT2_I_MODE_ATTR_MASK;
|
||||
stat->uid = inode->i_uid;
|
||||
stat->gid = inode->i_gid;
|
||||
stat->atime = inode->i_atime;
|
||||
stat->mtime = inode->i_mtime;
|
||||
stat->ctime = inode->i_ctime;
|
||||
stat->links = inode->i_links_count;
|
||||
kfree(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// what is the inode of the root directory?
|
||||
u32_t ext2__get_root_dir_inode(vfs_mount_t *mount)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
// VFS interface function to dereference a symbolic link
|
||||
int ext2__link_deref(vfs_mount_t *mount, u32_t link_inode, char *link)
|
||||
{
|
||||
ext2_inode_t inode;
|
||||
if (ext2_read_inode(mount, link_inode, &inode))
|
||||
return -1;
|
||||
if ( (inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_SYM )
|
||||
return -2;
|
||||
if (!inode.i_size)
|
||||
return -4;
|
||||
if (inode.i_size < 61)
|
||||
{
|
||||
memcpy(link, inode.i_block, inode.i_size);
|
||||
link[inode.i_size] = 0;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext2_open_inode_t *open_inode;
|
||||
if (!(open_inode = ext2_open_inode(mount, link_inode)))
|
||||
return -3;
|
||||
ext2_super_block_t *super = mount->super;
|
||||
void *buffer = kmalloc(1024 << super->s_log_block_size);
|
||||
memset(link, 0, 4096);
|
||||
int copied = 0;
|
||||
while (copied < 4096)
|
||||
{
|
||||
int bytes_read = ext2_read_inode_block(mount, open_inode, buffer);
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
memcpy(link + copied, buffer, bytes_read);
|
||||
copied += bytes_read;
|
||||
}
|
||||
ext2_close_inode(mount, open_inode);
|
||||
kfree(buffer);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// VFS interface function to return the number of free inodes
|
||||
int ext2__free_inodes(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
return super->s_free_inodes_count;
|
||||
}
|
||||
|
||||
// VFS interface function to return the total number of inodes
|
||||
int ext2__total_inodes(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
return super->s_inodes_count;
|
||||
}
|
||||
|
||||
// VFS interface function to return the number of free 512-byte blocks
|
||||
int ext2__free_blocks(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
return super->s_free_blocks_count << (1 + super->s_log_block_size);
|
||||
}
|
||||
|
||||
// VFS interface function to return the total number of 512-byte blocks
|
||||
int ext2__total_blocks(vfs_mount_t *mount)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
return super->s_blocks_count << (1 + super->s_log_block_size);
|
||||
}
|
||||
|
||||
// VFS interface function to open a directory
|
||||
int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir)
|
||||
{
|
||||
if (ext2_inode_status(mount, inode_number) != 1)
|
||||
return -1;
|
||||
ext2_open_dir_t *open_dir = ext2_open_dir(mount, inode_number);
|
||||
if (!open_dir)
|
||||
return -2;
|
||||
dir->fs_data = open_dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VFS interface function to read a directory entry from an open directory
|
||||
int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry)
|
||||
{
|
||||
ext2_dir_entry_t t_dentry;
|
||||
int status = ext2_dir_read_entry(mount, dir->fs_data, &t_dentry);
|
||||
if (status)
|
||||
return status;
|
||||
memcpy(dentry->name, t_dentry.name, t_dentry.name_length);
|
||||
dentry->name[t_dentry.name_length] = 0;
|
||||
dentry->inode_number = t_dentry.inode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VFS interface function to close an open directory
|
||||
int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir)
|
||||
{
|
||||
return ext2_close_dir(mount, dir->fs_data);
|
||||
}
|
||||
|
||||
|
||||
// VFS interface function to open a file for reading a byte at a time
|
||||
int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file)
|
||||
{
|
||||
if (ext2_inode_status(mount, inode_number) != 1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VFS interface function to read a byte from an open file
|
||||
int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VFS interface function to close a byte-file
|
||||
int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// VFS interface function to open a file for reading 512-byte blocks at a time
|
||||
int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file)
|
||||
{
|
||||
if (ext2_inode_status(mount, inode_number) != 1)
|
||||
return -1;
|
||||
ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number);
|
||||
if (!open_inode)
|
||||
return -2;
|
||||
if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_FILE)
|
||||
{
|
||||
ext2_close_inode(mount, open_inode);
|
||||
return -3;
|
||||
}
|
||||
ext2__open_block_file_t *open_block_file = New(ext2__open_block_file_t);
|
||||
open_block_file->open_inode = open_inode;
|
||||
open_block_file->block = 0;
|
||||
open_file->fs_data = open_block_file;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// VFS interface function to read a block from an open block file
|
||||
// returns the number of bytes read
|
||||
int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer)
|
||||
{
|
||||
ext2_super_block_t *super = mount->super;
|
||||
ext2__open_block_file_t *open_block_file = open_file->fs_data;
|
||||
if (ext2_inode_seek(mount, open_block_file->open_inode, ext2_diskToFSBlock(open_block_file->block, super)))
|
||||
return 0; // EOF
|
||||
u8_t *block = kmalloc(1024 << super->s_log_block_size);
|
||||
u32_t file_position_read = (1024 << super->s_log_block_size) * open_block_file->open_inode->block;
|
||||
u32_t file_position_want = open_block_file->block << 9;
|
||||
u32_t data_offset = file_position_want - file_position_read;
|
||||
int bytes_read = ext2_read_inode_block(mount, open_block_file->open_inode, block);
|
||||
if (bytes_read <= data_offset)
|
||||
{
|
||||
kfree(block);
|
||||
return 0; // EOF
|
||||
}
|
||||
memcpy(buffer, block + data_offset, min(512, bytes_read - data_offset));
|
||||
kfree(block);
|
||||
open_block_file->block++;
|
||||
return min(512, bytes_read - data_offset);
|
||||
}
|
||||
|
||||
// VFS interface function to seek to a certain block number of an open block file
|
||||
int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number)
|
||||
{
|
||||
ext2__open_block_file_t *open_block_file = open_file->fs_data;
|
||||
return ext2_inode_seek(mount, open_block_file->open_inode, ext2_FSToDiskBlock(block_number, mount->super));
|
||||
}
|
||||
|
||||
// VFS interface function to close an open block file
|
||||
int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
|
||||
{
|
||||
ext2__open_block_file_t *open_block_file = open_file->fs_data;
|
||||
ext2_close_inode(mount, open_block_file->open_inode);
|
||||
kfree(open_block_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
// ext2.h
|
||||
// Author: Josh Holtrop
|
||||
// Date: 08/22/04
|
||||
// Modified: 12/24/04
|
||||
|
||||
#ifndef __HOS_EXT2_H__
|
||||
#define __HOS_EXT2_H__ __HOS_EXT2_H__
|
||||
|
||||
#include "hos_defines.h"
|
||||
#include "fs/devices.h"
|
||||
#include "fs/vfs.h"
|
||||
|
||||
#define EXT2_MAGIC 0xEF53
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
#define EXT2_I_MODE_ATTR_MASK 0x0FFF
|
||||
#define EXT2_I_MODE_OX 0x0001
|
||||
#define EXT2_I_MODE_OW 0x0002
|
||||
#define EXT2_I_MODE_OR 0x0004
|
||||
#define EXT2_I_MODE_GX 0x0008
|
||||
#define EXT2_I_MODE_GW 0x0010
|
||||
#define EXT2_I_MODE_GR 0x0020
|
||||
#define EXT2_I_MODE_UX 0x0040
|
||||
#define EXT2_I_MODE_UW 0x0080
|
||||
#define EXT2_I_MODE_UR 0x0100
|
||||
#define EXT2_I_MODE_STICKY 0x0200
|
||||
#define EXT2_I_MODE_SGID 0x0400
|
||||
#define EXT2_I_MODE_SUID 0x0800
|
||||
|
||||
#define EXT2_I_MODE_TYPE_MASK 0xF000
|
||||
#define EXT2_I_MODE_FIFO 0x1000
|
||||
#define EXT2_I_MODE_CHAR 0x2000
|
||||
#define EXT2_I_MODE_DIR 0x4000
|
||||
#define EXT2_I_MODE_BLOCK 0x6000
|
||||
#define EXT2_I_MODE_FILE 0x8000
|
||||
#define EXT2_I_MODE_SYM 0xA000
|
||||
#define EXT2_I_MODE_SOCK 0xC000
|
||||
|
||||
#define EXT2_I_FLAGS_SEC_DEL 0x01
|
||||
#define EXT2_I_FLAGS_UNDELETE 0x02
|
||||
#define EXT2_I_FLAGS_COMPRESS 0x04
|
||||
#define EXT2_I_FLAGS_SYNC 0x08
|
||||
#define EXT2_I_FLAGS_IMMUTABLE 0x10
|
||||
#define EXT2_I_FLAGS_APPEND 0x20
|
||||
#define EXT2_I_FLAGS_NODUMP 0x40
|
||||
|
||||
#define EXT2_INODE_BAD_BLOCKS 1
|
||||
#define EXT2_INODE_ROOT 2
|
||||
#define EXT2_INODE_ACL_INDEX 3
|
||||
#define EXT2_INODE_ACL_DATA 4
|
||||
#define EXT2_INODE_BOOT_LOADER 5
|
||||
#define EXT2_INODE_UNDELETE_DIR 6
|
||||
#define EXT2_INODE_AVAIL 11
|
||||
|
||||
#define EXT2_FT_UNKNOWN 0
|
||||
#define EXT2_FT_FILE 1
|
||||
#define EXT2_FT_DIR 2
|
||||
#define EXT2_FT_CHAR 3
|
||||
#define EXT2_FT_BLOCK 4
|
||||
#define EXT2_FT_FIFO 5
|
||||
#define EXT2_FT_SOCK 6
|
||||
#define EXT2_FT_SYMLINK 7
|
||||
#define EXT2_FT_MAX 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t s_inodes_count; /* Inodes count */
|
||||
u32_t s_blocks_count; /* Blocks count */
|
||||
u32_t s_r_blocks_count; /* Reserved blocks count */
|
||||
u32_t s_free_blocks_count; /* Free blocks count */
|
||||
u32_t s_free_inodes_count; /* Free inodes count */
|
||||
u32_t s_first_data_block; /* First Data Block */
|
||||
u32_t s_log_block_size; /* Block size: 0->1024, 1->2048, 2->4096 */
|
||||
int s_log_frag_size; /* Fragment size */
|
||||
u32_t s_blocks_per_group; /* # Blocks per group */
|
||||
u32_t s_frags_per_group; /* # Fragments per group */
|
||||
u32_t s_inodes_per_group; /* # Inodes per group */
|
||||
u32_t s_mtime; /* Mount time */
|
||||
u32_t s_wtime; /* Write time */
|
||||
u16_t s_mnt_count; /* Mount count */
|
||||
short s_max_mnt_count; /* Maximal mount count */
|
||||
u16_t s_magic; /* Magic signature */
|
||||
u16_t s_state; /* File system state */
|
||||
u16_t s_errors; /* Behaviour when detecting errors */
|
||||
u16_t s_minor_rev_level; /* minor revision level */
|
||||
u32_t s_lastcheck; /* time of last check */
|
||||
u32_t s_checkinterval; /* max. time between checks */
|
||||
u32_t s_creator_os; /* OS */
|
||||
u32_t s_rev_level; /* Revision level */
|
||||
u16_t s_def_resuid; /* Default uid for reserved blocks */
|
||||
u16_t s_def_resgid; /* Default gid for reserved blocks */
|
||||
|
||||
u32_t s_reserved[235];
|
||||
} ext2_super_block_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t bg_block_bitmap; // Blocks bitmap block
|
||||
u32_t bg_inode_bitmap; // Inode bitmap block
|
||||
u32_t bg_inode_table; // Inode table block
|
||||
u16_t bg_free_blocks_count; // Free blocks count
|
||||
u16_t bg_free_inodes_count; // Free Inodes count
|
||||
u16_t bg_used_dirs_count; // Directories count
|
||||
u16_t bg_pad1;
|
||||
u32_t bg_reserved[3];
|
||||
} ext2_group_desc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16_t i_mode; // File mode
|
||||
u16_t i_uid; // Owner UID
|
||||
u32_t i_size; // Size in bytes
|
||||
u32_t i_atime; // Access time
|
||||
u32_t i_ctime; // Creation time
|
||||
u32_t i_mtime; // Modification time
|
||||
u32_t i_dtime; // Deletion time
|
||||
u16_t i_gid; // Group ID
|
||||
u16_t i_links_count; // Links count
|
||||
u32_t i_blocks; // Blocks count
|
||||
u32_t i_flags; // File flags
|
||||
u32_t i_reserved1;
|
||||
u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect)
|
||||
u32_t i_version; // File version (for NFS)
|
||||
u32_t i_file_acl; // File ACL
|
||||
u32_t i_dir_acl; // Directory ACL
|
||||
u32_t i_faddr; // Fragment address
|
||||
u8_t i_frag; // Fragment number
|
||||
u8_t i_fsize; // Fragment size
|
||||
u16_t i_pad1;
|
||||
u32_t i_reserved2[2];
|
||||
} ext2_inode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t inode; // inode number
|
||||
u16_t length; // directory entry length
|
||||
u8_t name_length; // name length
|
||||
u8_t file_type; // File type
|
||||
char name[EXT2_NAME_LEN];
|
||||
} ext2_dir_entry_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ext2_inode_t inode;
|
||||
u32_t block;
|
||||
u32_t *block_pointers;
|
||||
u32_t block_pointers_start;
|
||||
} ext2_open_inode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ext2_open_inode_t *open_inode;
|
||||
u32_t position;
|
||||
} ext2_open_dir_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ext2_open_inode_t *open_inode;
|
||||
u32_t position;
|
||||
u32_t buffer_start;
|
||||
u32_t buffer_bytes;
|
||||
u8_t *buffer;
|
||||
} ext2__open_file_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ext2_open_inode_t *open_inode;
|
||||
u32_t block;
|
||||
} ext2__open_block_file_t;
|
||||
|
||||
static inline u32_t ext2_diskToFSBlock(u32_t block, ext2_super_block_t *super)
|
||||
{
|
||||
// convert # of disk blocks to # of filesystem blocks
|
||||
return block >> (super->s_log_block_size + 1);
|
||||
}
|
||||
|
||||
static inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super)
|
||||
{
|
||||
// convert # of filesystem blocks to # of disk blocks
|
||||
return block << (super->s_log_block_size + 1);
|
||||
}
|
||||
|
||||
|
||||
int ext2_init(int fsID);
|
||||
int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat);
|
||||
int ext2_write_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat);
|
||||
ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group);
|
||||
void ext2_write_group_desc(vfs_mount_t *mount, u32_t group_num, ext2_group_desc_t *gd);
|
||||
ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number);
|
||||
int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode);
|
||||
int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block);
|
||||
u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode);
|
||||
int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number);
|
||||
|
||||
int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number);
|
||||
int ext2_block_status(vfs_mount_t *mount, u32_t block_number);
|
||||
|
||||
u32_t ext2_alloc_inode(vfs_mount_t *mount);
|
||||
int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number);
|
||||
u32_t ext2_alloc_block(vfs_mount_t *mount);
|
||||
int ext2_free_block(vfs_mount_t *mount, u32_t block_number);
|
||||
|
||||
u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size);
|
||||
int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number);
|
||||
int ext2_num_block_groups(ext2_super_block_t *super);
|
||||
void ext2_write_super(vfs_mount_t *mount);
|
||||
|
||||
int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size);
|
||||
|
||||
ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number);
|
||||
int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry);
|
||||
int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir);
|
||||
int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry);
|
||||
|
||||
|
||||
void *ext2_mount_super(major_t major, minor_t minor);
|
||||
int ext2_umount_super(vfs_mount_t *mount);
|
||||
int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat);
|
||||
u32_t ext2__get_root_dir_inode(vfs_mount_t *mount);
|
||||
int ext2__link_deref(vfs_mount_t *mount, u32_t link_inode, char *link);
|
||||
int ext2__free_inodes(vfs_mount_t *mount);
|
||||
int ext2__total_inodes(vfs_mount_t *mount);
|
||||
int ext2__free_blocks(vfs_mount_t *mount);
|
||||
int ext2__total_blocks(vfs_mount_t *mount);
|
||||
|
||||
|
||||
int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir);
|
||||
int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry);
|
||||
int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir);
|
||||
|
||||
int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
|
||||
int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
|
||||
int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
|
||||
|
||||
int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
|
||||
int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer);
|
||||
int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number);
|
||||
int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user