📄 e2fs.c
字号:
__FUNCTION__, name, namelen, dir_ino);
#endif
if (!e2fs_get_inode(e2fs, dir_ino, &inode)) {
#if DEBUG_E2FS > 0
diag_printf("%s: e2fs_get_inode [%d] failed\n", __FUNCTION__, dir_ino);
#endif
return NULL;
}
nbytes = SWAB_LE32(inode.size);
nblocks = (nbytes + e2fs->blocksize - 1) / e2fs->blocksize;
last_block_size = nbytes % e2fs->blocksize;
if (last_block_size == 0)
last_block_size = e2fs->blocksize;
for (i = 0; i < nblocks; i++) {
if (!e2fs_inode_block(e2fs, &inode, i, &block_nr))
return NULL;
if (block_nr) {
if (!__READ_BLOCK(block_nr))
return NULL;
} else
memset(blockbuf, 0, e2fs->blocksize);
dir = search_dir_block(e2fs, blockbuf, name, namelen);
if (dir != NULL)
return dir;
}
return NULL;
}
typedef struct ino_info {
cyg_uint32 ino;
cyg_uint32 parent_ino;
cyg_uint8 filetype;
} ino_info_t;
static int e2fs_inode_lookup(e2fs_desc_t *e2fs, cyg_uint32 dir_ino,
const char *pathname, ino_info_t *info);
// Starting from the given directory, find the inode number, filetype, and
// parent inode for the file pointed to by the given symbolic link inode.
// If successful, fills out ino_info_t and return true.
//
static int
e2fs_follow_symlink(e2fs_desc_t *e2fs, cyg_uint32 dir_ino, cyg_uint32 sym_ino, ino_info_t *info)
{
#define MAX_SYMLINK_NAME 255
char symlink[MAX_SYMLINK_NAME+1];
int pathlen;
cyg_uint32 block_nr;
e2fs_inode_t inode;
if (!e2fs_get_inode(e2fs, sym_ino, &inode)) {
#if DEBUG_E2FS > 0
diag_printf("%s: e2fs_get_inode [%d] failed\n", __FUNCTION__, sym_ino);
#endif
return 0;
}
pathlen = SWAB_LE32(inode.size);
if (pathlen > MAX_SYMLINK_NAME)
return 0;
if (inode.blocks) {
if (!e2fs_inode_block(e2fs, &inode, 0, &block_nr))
return 0;
if (block_nr) {
if (!PARTITION_READ(e2fs->part, E2FS_BLOCK_TO_SECTOR(e2fs, block_nr),
blockbuf, e2fs->blocksize/SECTOR_SIZE))
return 0;
memcpy(symlink, blockbuf, pathlen);
} else
return 0;
} else {
// small enough path to fit in inode struct
memcpy(symlink, (char *)&inode.block[0], pathlen);
}
symlink[pathlen] = 0;
return e2fs_inode_lookup(e2fs, dir_ino, symlink, info);
}
// Starting from the given directory, find the inode number, filetype, and
// parent inode for the given file pathname.
// If successful, fills out ino_info_t and return true.
//
static int
e2fs_inode_lookup(e2fs_desc_t *e2fs, cyg_uint32 dir_ino, const char *pathname, ino_info_t *info)
{
int len, pathlen;
const char *p;
e2fs_dir_entry_t *dir = NULL;
if (!pathname || (pathlen = strlen(pathname)) == 0)
return 0;
if (*pathname == '/') {
if (--pathlen == 0) {
info->ino = info->parent_ino = E2FS_ROOT_INO;
info->filetype = E2FS_FTYPE_DIR;
return 1;
}
++pathname;
dir_ino = E2FS_ROOT_INO;
}
while (pathlen) {
// find next delimiter in path.
for (p = pathname, len = 0; len < pathlen; len++, p++) {
// skip delimiter if found.
if (*p == '/') {
++p;
--pathlen;
break;
}
}
dir = e2fs_dir_lookup(e2fs, dir_ino, pathname, len);
if (dir == NULL)
return 0;
pathlen -= len;
pathname = p;
switch (dir->filetype) {
case E2FS_FTYPE_SYMLINK:
// follow the symbolic link (this will cause recursion)
if (!e2fs_follow_symlink(e2fs, dir_ino, SWAB_LE32(dir->inode), info))
return 0;
if (pathlen == 0)
return 1;
// must be a dir if we want to continue
if (info->filetype != E2FS_FTYPE_DIR)
return 0;
dir_ino = info->ino;
break;
case E2FS_FTYPE_DIR:
if (pathlen)
dir_ino = SWAB_LE32(dir->inode);
break;
case E2FS_FTYPE_REG_FILE:
if (pathlen)
return 0; // regular file embedded in middle of path
break;
case E2FS_FTYPE_UNKNOWN:
case E2FS_FTYPE_CHRDEV:
case E2FS_FTYPE_BLKDEV:
case E2FS_FTYPE_FIFO:
case E2FS_FTYPE_SOCK:
default:
return 0;
}
}
info->ino = SWAB_LE32(dir->inode);
info->parent_ino = dir_ino;
info->filetype = dir->filetype;
return 1;
}
struct read_info {
e2fs_desc_t e2fs_desc;
e2fs_inode_t inode;
cyg_uint32 fsize;
cyg_uint32 fpos;
};
static void *
e2fs_open(partition_t *p, const char *filepath)
{
static struct read_info rinfo;
ino_info_t ino_info;
// mount partition
if (e2fs_mount(p, &rinfo.e2fs_desc) != 0) {
diag_printf("mount failed.\n");
return NULL;
}
// find file inode
if (!e2fs_inode_lookup(&rinfo.e2fs_desc, E2FS_ROOT_INO, filepath, &ino_info)) {
diag_printf("%s: e2fs_inode_lookup failed\n", __FUNCTION__);
return NULL;
}
// read inode
if (!e2fs_get_inode(&rinfo.e2fs_desc, ino_info.ino, &rinfo.inode)) {
diag_printf("%s: e2fs_get_inode failed for ino[%d]\n", __FUNCTION__, ino_info.ino);
return NULL;
}
rinfo.fsize = SWAB_LE32(rinfo.inode.size);
rinfo.fpos = 0;
return &rinfo;
}
static int
e2fs_read(void *fp, char *buf, cyg_uint32 nbytes)
{
struct read_info *info = fp;
e2fs_desc_t *e2fs;
cyg_uint32 nread = 0, rem, block_nr, bindex, to_read;
if ((info->fpos + nbytes) > info->fsize)
nbytes = info->fsize - info->fpos;
e2fs = &info->e2fs_desc;
// see if we need to copy leftover data from last read call
rem = e2fs->blocksize - (info->fpos % e2fs->blocksize);
if (rem != e2fs->blocksize) {
char *p = (char *)blockbuf + e2fs->blocksize - rem;
if (rem > nbytes)
rem = nbytes;
memcpy(buf, p, rem);
nread += rem;
buf += rem;
info->fpos += rem;
}
// now loop through blocks if we're not done
bindex = info->fpos / e2fs->blocksize;
while (nread < nbytes) {
if (!e2fs_inode_block(e2fs, &info->inode, bindex, &block_nr))
return -1;
if (block_nr) {
if (!PARTITION_READ(e2fs->part, E2FS_BLOCK_TO_SECTOR(e2fs, block_nr),
blockbuf, e2fs->blocksize/SECTOR_SIZE))
return 0;
} else
memset(blockbuf, 0, e2fs->blocksize);
to_read = nbytes - nread;
if (to_read > e2fs->blocksize)
to_read = e2fs->blocksize;
memcpy(buf, blockbuf, to_read);
nread += to_read;
buf += to_read;
info->fpos += to_read;
++bindex;
}
return nread;
}
#if DEBUG_E2FS > 4
static void dump_sb(struct e2fs_super_block *s)
{
diag_printf("inode_count: %d\n", SWAB_LE32(s->inodes_count));
diag_printf("blocks_count: %d\n", SWAB_LE32(s->blocks_count));
diag_printf("r_blocks_count: %d\n", SWAB_LE32(s->r_blocks_count));
diag_printf("free_blocks_count: %d\n", SWAB_LE32(s->free_blocks_count));
diag_printf("free_inodes_count: %d\n", SWAB_LE32(s->free_inodes_count));
diag_printf("first_data_block: %d\n", SWAB_LE32(s->first_data_block));
diag_printf("log_block_size: %d\n", SWAB_LE32(s->log_block_size));
diag_printf("log_frag_size: %d\n", SWAB_LE32(s->log_frag_size));
diag_printf("blocks_per_group: %d\n", SWAB_LE32(s->blocks_per_group));
diag_printf("frags_per_group: %d\n", SWAB_LE32(s->frags_per_group));
diag_printf("inodes_per_group: %d\n", SWAB_LE32(s->inodes_per_group));
diag_printf("mnt_count: %d\n", SWAB_LE16(s->mnt_count));
diag_printf("max_mnt_count: %d\n", SWAB_LE16(s->max_mnt_count));
diag_printf("magic: %d\n", SWAB_LE16(s->magic));
diag_printf("state: %d\n", SWAB_LE16(s->state));
diag_printf("errors: %d\n", SWAB_LE16(s->errors));
diag_printf("minor_rev_level: %d\n", SWAB_LE16(s->minor_rev_level));
diag_printf("lastcheck: %d\n", SWAB_LE32(s->lastcheck));
diag_printf("checkinterval: %d\n", SWAB_LE32(s->checkinterval));
diag_printf("creator_os: %d\n", SWAB_LE32(s->creator_os));
diag_printf("rev_level: %d\n", SWAB_LE32(s->rev_level));
}
static void dump_inode(struct e2fs_inode *i)
{
int j, n;
diag_printf("mode: %o\n", SWAB_LE16(i->mode));
diag_printf("uid: %o\n", SWAB_LE16(i->uid));
diag_printf("size: %d\n", SWAB_LE32(i->size));
diag_printf("gid: %o\n", SWAB_LE16(i->gid));
diag_printf("links: %d\n", SWAB_LE16(i->links_count));
diag_printf("blocks: %d\n", SWAB_LE32(i->blocks));
n = i->blocks;
if (n > E2FS_N_BLOCKS)
n = E2FS_N_BLOCKS;
for (j = 0; j < n; j++)
diag_printf(" block: %d\n", SWAB_LE32(i->block[j]));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -