#include <fs.h>
#include "ext2_fs.h"
-#define MAX_SYMLINKS 64
-#define SYMLINK_SECTORS 2
-static char SymlinkBuf[SYMLINK_SECTORS * SECTOR_SIZE + 64];
-
-/*
- * File structure, This holds the information for each currently open file
- */
-struct open_file_t {
- uint32_t file_bytesleft; /* Number of bytes left (0 = free) */
- uint32_t file_sector; /* Next linear sector to read */
- sector_t file_in_sec; /* Sector where inode lives */
- uint16_t file_in_off;
- uint16_t file_mode;
- uint32_t pad[3]; /* pad to 2^5 == 0x20 bytes */
-};
-static struct open_file_t Files[MAX_OPEN];
-
-static struct ext2_inode this_inode;
-static struct ext2_super_block sb;
-
-static uint16_t ClustByteShift, ClustShift;
-static uint32_t SecPerClust, ClustSize, ClustMask;
-static uint32_t PtrsPerBlock1, PtrsPerBlock2, PtrsPerBlock3;
-static int DescPerBlock, InodePerBlock;
-
/*
* just like the function strcpy(), except it returns non-zero if overflow.
*
*/
-static int strecpy(char *dst, char *src, char *end)
+static int strecpy(char *dst, const char *src, char *end)
{
while (*src != '\0')
*dst++ = *src++;
return 0;
}
-
-/*
- * Allocate a file structure, if successful return the file pointer, or NULL.
- *
- */
-static struct open_file_t *allocate_file(void)
-{
- struct open_file_t *file = Files;
- int i;
-
- for (i = 0; i < MAX_OPEN; i++) {
- if (file->file_bytesleft == 0) /* found it */
- return file;
- file++;
- }
-
- return NULL; /* not found */
-}
-
-
-/**
- * ext2_close_file:
- *
- * Deallocates a file structure point by FILE
- *
- * @param: file, the file structure we want deallocate
- *
- */
-static inline void close_pvt(struct open_file_t *of)
-{
- of->file_bytesleft = 0;
-}
-
static void ext2_close_file(struct file *file)
{
- close_pvt(file->open_file);
+ if (file->u1.inode) {
+ file->u2.offset = 0;
+ free_inode(file->u1.inode);
+ }
}
-/**
+/*
* get the group's descriptor of group_num
- *
- * @param: group_num, the group number;
- *
- * @return: the pointer of the group's descriptor
- *
- */
-static struct ext2_group_desc *
-get_group_desc(struct fs_info *fs, uint32_t group_num)
-{
- block_t block_num;
- uint32_t offset;
- struct ext2_group_desc *desc;
- struct cache_struct *cs;
-
- block_num = group_num / DescPerBlock;
- offset = group_num % DescPerBlock;
-
- block_num += sb.s_first_data_block + 1;
- cs = get_cache_block(fs->fs_dev, block_num);
- desc = (struct ext2_group_desc *)cs->data + offset;
-
- return desc;
-}
-
-
-/**
- * read the right inode structure to _dst_.
- *
- * @param: inode_offset, the inode offset within a group;
- * @prarm: dst, wher we will store the inode structure;
- * @param: desc, the pointer to the group's descriptor
- * @param: block, a pointer used for retruning the blk number for file structure
- * @param: offset, same as block
- *
- */
-static void read_inode(struct fs_info *fs, uint32_t inode_offset,
- struct ext2_inode *dst, struct ext2_group_desc *desc,
- block_t *block, uint32_t *offset)
-{
- struct cache_struct *cs;
- struct ext2_inode *inode;
-
- *block = inode_offset / InodePerBlock + desc->bg_inode_table;
- *offset = inode_offset % InodePerBlock;
-
- cs = get_cache_block(fs->fs_dev, *block);
-
- /* well, in EXT4, the inode structure usually be 256 */
- inode = (struct ext2_inode *)(cs->data + (*offset * (sb.s_inode_size)));
- memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE);
-
- /* for file structure */
- *offset = (inode_offset * sb.s_inode_size) % ClustSize;
-}
-
-
-/**
- * open a file indicated by an inode number in INR
- *
- * @param : inr, the inode number
- * @return: a open_file_t structure pointer
- * file length in bytes
- * the first 128 bytes of the inode, stores in ThisInode
- *
*/
-static struct open_file_t *
-open_inode(struct fs_info *fs, uint32_t inr, uint32_t *file_len)
-{
- struct open_file_t *file;
- struct ext2_group_desc *desc;
-
- uint32_t inode_group, inode_offset;
- block_t block_num;
- uint32_t block_off;
-
- file = allocate_file();
- if (!file)
- return NULL;
-
- file->file_sector = 0;
-
- inr --;
- inode_group = inr / sb.s_inodes_per_group;
-
- /* get the group desc */
- desc = get_group_desc(fs, inode_group);
-
- inode_offset = inr % sb.s_inodes_per_group;
- read_inode(fs, inode_offset, &this_inode, desc, &block_num, &block_off);
-
- /* Finally, we need to convet it to sector for now */
- file->file_in_sec = (block_num<<ClustShift) + (block_off>>SECTOR_SHIFT);
- file->file_in_off = block_off & (SECTOR_SIZE - 1);
- file->file_mode = this_inode.i_mode;
- *file_len = file->file_bytesleft = this_inode.i_size;
-
- if (*file_len == 0)
- return NULL;
-
- return file;
-}
-
-
-
-static struct ext4_extent_header *
-ext4_find_leaf(struct fs_info *fs, struct ext4_extent_header *eh, block_t block)
-{
- struct ext4_extent_idx *index;
- struct cache_struct *cs;
- block_t blk;
- int i;
-
- while (1) {
- if (eh->eh_magic != EXT4_EXT_MAGIC)
- return NULL;
-
- /* got it */
- if (eh->eh_depth == 0)
- return eh;
-
- index = EXT4_FIRST_INDEX(eh);
- for (i = 0; i < eh->eh_entries; i++) {
- if (block < index[i].ei_block)
- break;
- }
- if (--i < 0)
- return NULL;
-
- blk = index[i].ei_leaf_hi;
- blk = (blk << 32) + index[i].ei_leaf_lo;
-
- /* read the blk to memeory */
- cs = get_cache_block(fs->fs_dev, blk);
- eh = (struct ext4_extent_header *)(cs->data);
- }
-}
-
-/* handle the ext4 extents to get the phsical block number */
-static block_t linsector_extent(struct fs_info *fs, block_t block,
- struct ext2_inode *inode)
+struct ext2_group_desc * ext2_get_group_desc(uint32_t group_num)
{
- struct ext4_extent_header *leaf;
- struct ext4_extent *ext;
- int i;
- block_t start;
-
- leaf = ext4_find_leaf(fs, (struct ext4_extent_header*)inode->i_block, block);
- if (!leaf) {
- printf("ERROR, extent leaf not found\n");
- return 0;
- }
-
- ext = EXT4_FIRST_EXTENT(leaf);
- for (i = 0; i < leaf->eh_entries; i++) {
- if (block < ext[i].ee_block)
- break;
- }
- if (--i < 0) {
- printf("ERROR, not find the right block\n");
- return 0;
- }
-
- /* got it */
- block -= ext[i].ee_block;
- if (block >= ext[i].ee_len)
- return 0;
-
- start = ext[i].ee_start_hi;
- start = (start << 32) + ext[i].ee_start_lo;
-
- return start + block;
+ struct ext2_sb_info *sbi = EXT2_SB(this_fs);
+
+ if (group_num >= sbi->s_groups_count) {
+ printf ("ext2_get_group_desc"
+ "block_group >= groups_count - "
+ "block_group = %d, groups_count = %d",
+ group_num, sbi->s_groups_count);
+
+ return NULL;
+ }
+
+ return sbi->s_group_desc[group_num];
}
-/**
- * linsector_direct:
- *
- * @param: block, the block index
- * @param: inode, the inode structure
- *
- * @return: the physic block number
- */
-static block_t linsector_direct(struct fs_info *fs, uint32_t block, struct ext2_inode *inode)
-{
- struct cache_struct *cs;
-
- /* direct blocks */
- if (block < EXT2_NDIR_BLOCKS)
- return inode->i_block[block];
-
-
- /* indirect blocks */
- block -= EXT2_NDIR_BLOCKS;
- if (block < PtrsPerBlock1) {
- block_t ind_block = inode->i_block[EXT2_IND_BLOCK];
- cs = get_cache_block(fs->fs_dev, ind_block);
-
- return ((uint32_t *)cs->data)[block];
- }
-
- /* double indirect blocks */
- block -= PtrsPerBlock1;
- if (block < PtrsPerBlock2) {
- block_t dou_block = inode->i_block[EXT2_DIND_BLOCK];
- cs = get_cache_block(fs->fs_dev, dou_block);
-
- dou_block = ((uint32_t *)cs->data)[block / PtrsPerBlock1];
- cs = get_cache_block(fs->fs_dev, dou_block);
-
- return ((uint32_t*)cs->data)[block % PtrsPerBlock1];
- }
-
- /* triple indirect block */
- block -= PtrsPerBlock2;
- if (block < PtrsPerBlock3) {
- block_t tri_block = inode->i_block[EXT2_TIND_BLOCK];
- cs = get_cache_block(fs->fs_dev, tri_block);
-
- tri_block = ((uint32_t *)cs->data)[block / PtrsPerBlock2];
- cs = get_cache_block(fs->fs_dev, tri_block);
-
- tri_block = ((uint32_t *)cs->data)[block % PtrsPerBlock2];
- cs = get_cache_block(fs->fs_dev, tri_block);
-
- return ((uint32_t*)cs->data)[block % PtrsPerBlock1];
- }
-
- /* File too big, can not handle */
- printf("ERROR, file too big\n");
- return 0;
-}
-
/**
* linsector:
*
* @return: physic sector number
*/
-static sector_t linsector(struct fs_info *fs, uint32_t lin_sector)
+static sector_t linsector(struct fs_info *fs,
+ struct inode *inode,
+ uint32_t lin_sector)
{
- uint32_t block = lin_sector >> ClustShift;
- block_t ret;
- struct ext2_inode *inode;
-
- /* well, this is what I think the variable this_inode used for */
- inode = &this_inode;
-
- if (inode->i_flags & EXT4_EXTENTS_FLAG)
- ret = linsector_extent(fs, block, inode);
- else
- ret = linsector_direct(fs, block, inode);
-
- if (!ret) {
- printf("ERROR: something error happend at linsector..\n");
- return 0;
- }
+ block_t block = bmap(fs, inode, lin_sector >> fs->blk_bits);
- /* finally convert it to sector */
- return ((ret << ClustShift) + (lin_sector & ClustMask));
-}
-
-
-/*
- * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure.
- *
- * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller.
- */
-static inline int ext2_match_entry (const char * const name,
- struct ext2_dir_entry * de)
-{
- if (!de->d_inode)
- return 0;
- return !strncmp(name, de->d_name, de->d_name_len);
+ return (block << fs->blk_bits) + (lin_sector & ((1 << fs->blk_bits) - 1));
}
-/*
- * p is at least 6 bytes before the end of page
- */
-static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p)
-{
- return (struct ext2_dir_entry *)((char*)p + p->d_rec_len);
-}
-
/**
* getlinsec_ext:
*
*
*/
static void getlinsec_ext(struct fs_info *fs, char *buf,
- sector_t sector, int sector_cnt)
+ sector_t sector, int sector_cnt)
{
int ext_cnt = 0;
+ int sec_per_block = 1 << fs->blk_bits;
struct disk *disk = fs->fs_dev->disk;
- if (sector < SecPerClust) {
- ext_cnt = SecPerClust - sector;
+ if (sector < sec_per_block) {
+ ext_cnt = sec_per_block - sector;
memset(buf, 0, ext_cnt << SECTOR_SHIFT);
buf += ext_cnt << SECTOR_SHIFT;
}
* do. So, let it be based on sectors.
*
*/
-static uint32_t ext2_getfssec(struct file *gfile, char *buf,
+static uint32_t ext2_getfssec(struct file *file, char *buf,
int sectors, bool *have_more)
{
int sector_left, next_sector, sector_idx;
int frag_start, con_sec_cnt;
int bytes_read = sectors << SECTOR_SHIFT;
- struct open_file_t *file = gfile->open_file;
- struct fs_info *fs = gfile->fs;
+ struct inode *inode = file->u1.inode;
+ struct fs_info *fs = file->fs;
+ uint32_t bytesleft = inode->size - file->u2.offset;
- sector_left = (file->file_bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
+ sector_left = (bytesleft + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
if (sectors > sector_left)
sectors = sector_left;
+ sector_idx = file->u2.offset >> SECTOR_SHIFT;
while (sectors) {
/*
* get the frament
*/
- sector_idx = file->file_sector;
- next_sector = frag_start = linsector(fs, sector_idx);
+ next_sector = frag_start = linsector(fs, inode, sector_idx);
con_sec_cnt = 0;
/* get the consective sectors count */
sector_idx ++;
next_sector ++;
- } while (next_sector == linsector(fs, sector_idx));
+ } while (next_sector == linsector(fs, inode, sector_idx));
-#if 0
+#if 0
printf("You are reading data stored at sector --0x%x--0x%x\n",
frag_start, frag_start + con_sec_cnt -1);
#endif
getlinsec_ext(fs, buf, frag_start, con_sec_cnt);
- buf += con_sec_cnt << 9;
- file->file_sector += con_sec_cnt; /* next sector index */
+ buf += con_sec_cnt << SECTOR_SHIFT;
} while(sectors);
- if (bytes_read >= file->file_bytesleft) {
- bytes_read = file->file_bytesleft;
+ if (bytes_read >= bytesleft) {
+ bytes_read = bytesleft;
*have_more = 0;
} else {
*have_more = 1;
}
- file->file_bytesleft -= bytes_read;
-
+ file->u2.offset += bytes_read;
+
return bytes_read;
}
-
+/*
+ * Unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure.
+ */
+static inline int ext2_match_entry (const char * const name,
+ struct ext2_dir_entry * de)
+{
+ if (!de->d_inode)
+ return 0;
+ if (strlen(name) != de->d_name_len)
+ return 0;
+ return !strncmp(name, de->d_name, de->d_name_len);
+}
+
+
+/*
+ * p is at least 6 bytes before the end of page
+ */
+static inline struct ext2_dir_entry *ext2_next_entry(struct ext2_dir_entry *p)
+{
+ return (struct ext2_dir_entry *)((char*)p + p->d_rec_len);
+}
/*
* find a dir entry, return it if found, or return NULL.
- *
*/
-static struct ext2_dir_entry*
-find_dir_entry(struct fs_info *fs, struct open_file_t *file, char *filename)
+static struct ext2_dir_entry *
+ext2_find_entry(struct fs_info *fs, struct inode *inode, char *dname)
{
- bool have_more;
- char *EndBlock = trackbuf + (SecPerClust << SECTOR_SHIFT);;
+ int index = 0;
+ block_t block;
+ uint32_t i = 0;
struct ext2_dir_entry *de;
- struct file xfile;
-
- /* Fake out a VFS file structure */
- xfile.fs = fs;
- xfile.open_file = file;
+ struct cache_struct *cs;
- /* read a clust at a time */
- ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more);
- de = (struct ext2_dir_entry *)trackbuf;
+ if (!(block = bmap(fs, inode, index++)))
+ return NULL;
+ cs = get_cache_block(fs->fs_dev, block);
+ de = (struct ext2_dir_entry *)cs->data;
+
+ while(i < (int)inode->size) {
+ if (ext2_match_entry(dname, de))
+ return de;
+ i += de->d_rec_len;
+ if (i >= (int)inode->size)
+ break;
+ if ((char *)de >= (char *)cs->data + inode->blksize) {
+ if (!(block = bmap(fs, inode, index++)))
+ break;
+ cs = get_cache_block(fs->fs_dev, block);
+ de = (struct ext2_dir_entry *)cs->data;
+ continue;
+ }
+
+ de = ext2_next_entry(de);
+ }
- while (1) {
- if ((char *)de >= (char *)EndBlock) {
- if (!have_more)
- return NULL;
- ext2_getfssec(&xfile, trackbuf, SecPerClust, &have_more);
- de = (struct ext2_dir_entry *)trackbuf;
- }
-
- /* Zero inode == void entry */
- if (de->d_inode == 0) {
- de = ext2_next_entry(de);
- continue;
- }
-
- if (ext2_match_entry (filename, de)) {
- filename += de->d_name_len;
- if ((*filename == 0) || (*filename == '/'))
- return de; /* got it */
-
- /* not match, restore the filename then try next */
- filename -= de->d_name_len;
- }
-
- de = ext2_next_entry(de);
- }
+ return NULL;
}
-
-static char *do_symlink(struct fs_info *fs, struct open_file_t *file,
- uint32_t file_len, char *filename)
+static struct ext2_inode * get_inode(int inr)
{
- int flag;
- bool have_more;
-
- char *SymlinkTmpBuf = trackbuf;
- char *lnk_end;
- char *SymlinkTmpBufEnd = trackbuf + SYMLINK_SECTORS * SECTOR_SIZE+64;
- struct file xfile;
- xfile.fs = fs;
- xfile.open_file = file;
-
- flag = this_inode.i_file_acl ? SecPerClust : 0;
- if (this_inode.i_blocks == flag) {
- /* fast symlink */
- close_pvt(file); /* we've got all we need */
- memcpy(SymlinkTmpBuf, this_inode.i_block, file_len);
- lnk_end = SymlinkTmpBuf + file_len;
-
- } else {
- /* slow symlink */
- ext2_getfssec(&xfile, SymlinkTmpBuf, SYMLINK_SECTORS, &have_more);
- lnk_end = SymlinkTmpBuf + file_len;
- }
+ struct ext2_group_desc *desc;
+ struct cache_struct *cs;
+ uint32_t inode_group, inode_offset;
+ uint32_t block_num, block_off;
- if (*filename != 0)
- *lnk_end++ = '/';
+ inr--;
+ inode_group = inr / EXT2_INODES_PER_GROUP(this_fs);
+ inode_offset = inr % EXT2_INODES_PER_GROUP(this_fs);
+ desc = ext2_get_group_desc (inode_group);
+ if (!desc)
+ return NULL;
- if (strecpy(lnk_end, filename, SymlinkTmpBufEnd))
- return NULL; /* buffer overflow */
+ block_num = desc->bg_inode_table +
+ inode_offset / EXT2_INODES_PER_BLOCK(this_fs);
+ block_off = inode_offset % EXT2_INODES_PER_BLOCK(this_fs);
- /*
- * now copy it to the "real" buffer; we need to have
- * two buffers so we avoid overwriting the tail on
- * the next copy.
- */
- strcpy(SymlinkBuf, SymlinkTmpBuf);
+ cs = get_cache_block(this_fs->fs_dev, block_num);
- /* return the new path */
- return SymlinkBuf;
+ return cs->data + block_off * EXT2_SB(this_fs)->s_inode_size;
}
+static inline int get_inode_mode(int mode)
+{
+ mode >>= S_IFSHIFT;
+ if (mode == T_IFDIR)
+ mode = I_DIR;
+ else if (mode == T_IFLNK)
+ mode = I_SYMLINK;
+ else
+ mode = I_FILE; /* we treat others as FILE */
+ return mode;
+}
+static void fill_inode(struct inode *inode, struct ext2_inode *e_inode)
+{
+ inode->mode = get_inode_mode(e_inode->i_mode);
+ inode->size = e_inode->i_size;
+ inode->atime = e_inode->i_atime;
+ inode->ctime = e_inode->i_ctime;
+ inode->mtime = e_inode->i_mtime;
+ inode->dtime = e_inode->i_dtime;
+ inode->blocks = e_inode->i_blocks;
+ inode->flags = e_inode->i_flags;
+ inode->blksize = 1 << (SECTOR_SHIFT + this_fs->blk_bits);
+ inode->file_acl = e_inode->i_file_acl;
+
+ inode->data = malloc(EXT2_N_BLOCKS * sizeof(uint32_t *));
+ if (!inode->data) {
+ malloc_error("inode data filed");
+ return ;
+ }
+ memcpy(inode->data, e_inode->i_block, EXT2_N_BLOCKS * sizeof(uint32_t *));
+}
+static struct inode *ext2_iget_by_inr(uint32_t inr)
+{
+ struct ext2_inode *e_inode;
+ struct inode *inode;
+
+ e_inode = get_inode(inr);
+ if (!(inode = malloc(sizeof(*inode))))
+ return NULL;
+ fill_inode(inode, e_inode);
+ inode->ino = inr;
+
+ return inode;
+}
-/**
- * Search the root directory for a pre-mangle filename in FILENAME.
- *
- * @param: filename, the filename we want to search.
- *
- * @out : a open_file_t structure pointer, stores in file->open_file
- * @out : file lenght in bytes, stores in file->file_len
- *
- */
-static void ext2_searchdir(char *filename, struct file *file)
+static struct inode *ext2_iget_root()
+{
+ return ext2_iget_by_inr(EXT2_ROOT_INO);
+}
+
+static struct inode *ext2_iget_current()
{
extern int CurrentDir;
- struct open_file_t *open_file;
- struct ext2_dir_entry *de;
- uint8_t file_mode;
- uint8_t SymlinkCtr = MAX_SYMLINKS;
- uint32_t inr = CurrentDir;
- uint32_t ThisDir = CurrentDir;
- uint32_t file_len;
-
- begin_path:
- while (*filename == '/') { /* Absolute filename */
- inr = EXT2_ROOT_INO;
- filename ++;
- }
- open:
- if ((open_file = open_inode(file->fs, inr, &file_len)) == NULL)
- goto err_noclose;
-
- file_mode = open_file->file_mode >> S_IFSHIFT;
-
- /* It's a file */
- if (file_mode == T_IFREG) {
- if (*filename == '\0')
- goto done;
- else
- goto err;
- }
-
-
- /* It's a directory */
- if (file_mode == T_IFDIR) {
- ThisDir = inr;
-
- if (*filename == 0)
- goto err;
- while (*filename == '/')
- filename ++;
+ if (CurrentDir)
+ return ext2_iget_by_inr(CurrentDir);
+}
+
+static struct inode *ext2_iget(char *dname, struct inode *parent)
+{
+ struct ext2_dir_entry *de;
- de = find_dir_entry(file->fs, open_file, filename);
- if (!de)
- goto err;
+ de = ext2_find_entry(this_fs, parent, dname);
+ if (!de)
+ return NULL;
- inr = de->d_inode;
- filename += de->d_name_len;
- close_pvt(open_file);
- goto open;
- }
+ return ext2_iget_by_inr(de->d_inode);
+}
+
+
+static char * ext2_follow_symlink(struct inode *inode, const char *name_left)
+{
+ int sec_per_block = 1 << this_fs->blk_bits;
+ int fast_symlink;
+ char *symlink_buf;
+ char *p;
+ struct cache_struct *cs;
-
- /*
- * It's a symlink. We have to determine if it's a fast symlink
- * (data stored in the inode) or not (data stored as a regular
- * file.) Either which way, we start from the directory
- * which we just visited if relative, or from the root directory
- * if absolute, and append any remaining part of the path.
- */
- if (file_mode == T_IFLNK) {
- if (--SymlinkCtr==0 || file_len>=SYMLINK_SECTORS*SECTOR_SIZE)
- goto err; /* too many links or symlink too long */
-
- filename = do_symlink(file->fs, open_file, file_len, filename);
- if (!filename)
- goto err_noclose;/* buffer overflow */
-
- inr = ThisDir;
- goto begin_path; /* we got a new path, so search it again */
+ symlink_buf = malloc(inode->blksize);
+ if (!symlink_buf) {
+ malloc_error("symlink buffer");
+ return NULL;
}
+ fast_symlink = (inode->file_acl ? sec_per_block : 0) == inode->blocks;
+ if (fast_symlink) {
+ memcpy(symlink_buf, inode->data, inode->size);
+ } else {
+ cs = get_cache_block(this_fs->fs_dev, *(uint32_t *)inode->data);
+ memcpy(symlink_buf, cs->data, inode->size);
+ }
+ p = symlink_buf + inode->size;
- /* Otherwise, something bad ... */
- err:
- close_pvt(open_file);
- err_noclose:
- file_len = 0;
- open_file = NULL;
- done:
-
- file->file_len = file_len;
- file->open_file = (void*)open_file;
-
-#if 0
- if (open_file) {
- printf("file bytesleft: %d\n", open_file->file_bytesleft);
- printf("file sector : %d\n", open_file->file_sector);
- printf("file in sector: %d\n", open_file->file_in_sec);
- printf("file offsector: %d\n", open_file->file_in_off);
+ if (*name_left)
+ *p++ = '/';
+ if (strecpy(p, name_left, symlink_buf + inode->blksize)) {
+ free(symlink_buf);
+ return NULL;
}
-#endif
-
+ if(!(p = strdup(symlink_buf)))
+ return symlink_buf;
+
+ free(symlink_buf);
+ return p;
}
+
/* Load the config file, return 1 if failed, or 0 */
static int ext2_load_config(void)
{
static int ext2_fs_init(struct fs_info *fs)
{
struct disk *disk = fs->fs_dev->disk;
-
- /* read the super block */
- disk->rdwr_sectors(disk, &sb, 2, 2, 0);
+ struct ext2_sb_info *sbi;
+ struct ext2_super_block *esb;
+ int block_size;
+ int block_shift;
+ int db_count;
+ int i;
+ int desc_block;
+ char *desc_buffer;
- ClustByteShift = sb.s_log_block_size + 10;
- ClustSize = 1 << ClustByteShift;
- ClustShift = ClustByteShift - SECTOR_SHIFT;
+ esb = malloc(sizeof(struct ext2_super_block));
+ if (!esb) {
+ malloc_error("ext2_super_block structure");
+ return -1;
+ }
- DescPerBlock = ClustSize >> ext2_group_desc_lg2size;
- InodePerBlock = ClustSize / sb.s_inode_size;
+ /* read the super block */
+ disk->rdwr_sectors(disk, esb, 2, 2, 0);
+
- SecPerClust = ClustSize >> SECTOR_SHIFT;
- ClustMask = SecPerClust - 1;
+ sbi = malloc(sizeof(*sbi));
+ if (!sbi) {
+ malloc_error("ext2_sb_info structure");
+ return -1;
+ }
+ fs->fs_info = sbi;
+ sbi->s_es = esb;
- PtrsPerBlock1 = 1 << (ClustByteShift - 2);
- PtrsPerBlock2 = 1 << ((ClustByteShift - 2) * 2);
- PtrsPerBlock3 = 1 << ((ClustByteShift - 2) * 3);
+ if (esb->s_magic != EXT2_SUPER_MAGIC) {
+ printf("ext2 mount error: can't found ext2 file system!\n");
+ return 0;
+ }
+
+ block_shift = esb->s_log_block_size + 10;
+ block_size = 1 << block_shift;
+ fs->blk_bits = block_shift - SECTOR_SHIFT;
+
+ sbi->s_inodes_per_group = esb->s_inodes_per_group;
+ sbi->s_blocks_per_group = esb->s_blocks_per_group;
+ sbi->s_inodes_per_block = block_size / esb->s_inode_size;
+ sbi->s_itb_per_group = sbi->s_inodes_per_group /
+ sbi->s_inodes_per_block;
+ if (esb->s_desc_size < sizeof(struct ext2_group_desc))
+ esb->s_desc_size = sizeof(struct ext2_group_desc);
+ sbi->s_desc_per_block = block_size / esb->s_desc_size;
+ sbi->s_groups_count = (esb->s_blocks_count - esb->s_first_data_block
+ + EXT2_BLOCKS_PER_GROUP(fs) - 1)
+ / EXT2_BLOCKS_PER_GROUP(fs);
+ db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) /
+ EXT2_DESC_PER_BLOCK(fs);
+ sbi->s_gdb_count = db_count;
+ sbi->s_inode_size = esb->s_inode_size;
+
+ /* read the descpritors */
+ desc_block = esb->s_first_data_block + 1;
+ desc_buffer = malloc(db_count * block_size);
+ if (!desc_buffer) {
+ malloc_error("desc_buffer");
+ return -1;
+ }
+ disk->rdwr_sectors(disk, desc_buffer, desc_block << fs->blk_bits,
+ db_count << fs->blk_bits, 0);
+ sbi->s_group_desc = malloc(sizeof(struct ext2_group_desc *)
+ * sbi->s_groups_count);
+ if (!sbi->s_group_desc) {
+ malloc_error("sbi->s_group_desc");
+ return -1;
+ }
+ for (i = 0; i < (int)sbi->s_groups_count; i++) {
+ sbi->s_group_desc[i] = (struct ext2_group_desc *)desc_buffer;
+ desc_buffer += esb->s_desc_size;
+ }
- return ClustByteShift;
+ return block_shift;
}
const struct fs_ops ext2_fs_ops = {
.fs_name = "ext2",
.fs_flags = 0,
.fs_init = ext2_fs_init,
- .searchdir = ext2_searchdir,
+ .searchdir = NULL,
.getfssec = ext2_getfssec,
.close_file = ext2_close_file,
.mangle_name = generic_mangle_name,
.unmangle_name = generic_unmangle_name,
- .load_config = ext2_load_config
+ .load_config = ext2_load_config,
+ .iget_root = ext2_iget_root,
+ .iget_current = ext2_iget_current,
+ .iget = ext2_iget,
+ .follow_symlink = ext2_follow_symlink
};