📄 ext2fs.c
字号:
/*----------------------------------------------------------------------* search_dir_block*----------------------------------------------------------------------*/static EXT2_DIR_T *search_dir_block(EXT2_DESC_T *ext2fs, UINT32 *blkbuf, char *name, int namelen, int type){ EXT2_DIR_T *dir; UINT16 reclen, len; UINT32 offset; UINT8 filename[60+1]; offset = 0; while (offset < ext2fs->blocksize) { dir = (EXT2_DIR_T *)((char *)blkbuf + offset); reclen = SWAB_LE16(dir->reclen); offset += reclen; len = dir->namelen; // terminate on anything which doesn't make sense if (reclen < 8 || (len + 8) > reclen || offset > (ext2fs->blocksize + 1)) return NULL; if (type == 0) { if (dir->inode && len == namelen && !strncmp(dir->name, name, len)) return dir; } else { switch(dir->filetype) { case EXT2_FTYPE_REG_FILE: printf(" [FILE] "); break; case EXT2_FTYPE_DIR: printf(" [DIR] "); break; case EXT2_FTYPE_CHRDEV: printf(" [ChrDev] "); break; case EXT2_FTYPE_BLKDEV: printf(" [BlkDev] "); break; case EXT2_FTYPE_FIFO: printf(" [FIFO] "); break; case EXT2_FTYPE_SOCK: printf(" [SOCK] "); break; case EXT2_FTYPE_SYMLINK: printf(" [SYM] "); break; case EXT2_FTYPE_UNKNOWN: default: printf(" [Unknown] "); break; } if (len > 60) len = 60; memcpy(filename, dir->name, len); filename[len] = 0x00; printf(filename); printf("\n"); } } return NULL;}/*----------------------------------------------------------------------* ext2fs_dir_lookup *----------------------------------------------------------------------*/static EXT2_DIR_T * ext2fs_dir_lookup(EXT2_DESC_T *ext2fs, UINT32 dir_ino, char *name, int namelen, int type){ EXT2_INODE_T inode; EXT2_DIR_T *dir; UINT32 nblocks, last_block_size, i, block_nr, nbytes; if (!ext2fs_get_inode(ext2fs, dir_ino, &inode)) return NULL; nbytes = SWAB_LE32(inode.size); nblocks = (nbytes + ext2fs->blocksize - 1) / ext2fs->blocksize; last_block_size = nbytes % ext2fs->blocksize; if (last_block_size == 0) last_block_size = ext2fs->blocksize; for (i = 0; i < nblocks; i++) { if (!ext2fs_inode_block(ext2fs, &inode, i, &block_nr)) return NULL; if (block_nr) { if (!__READ_BLOCK(block_nr)) return NULL; } else memset(blockbuf, 0, ext2fs->blocksize); dir = search_dir_block(ext2fs, blockbuf, name, namelen, type); if (dir != NULL) return dir; } return NULL;}/*----------------------------------------------------------------------* ext2fs_follow_symlink * Starting from the given directory, find the inode number, * filetype, and parent inode for the file pointed to by the * given symbolic link inode.* f successful, fills out INODE_INFO_T and return true.*----------------------------------------------------------------------*/static int ext2fs_follow_symlink(EXT2_DESC_T *ext2fs, UINT32 dir_ino, UINT32 sym_ino, INODE_INFO_T *info){ #define MAX_SYMLINK_NAME 255 char symlink[MAX_SYMLINK_NAME+1]; int pathlen; UINT32 block_nr; EXT2_INODE_T inode; if (!ext2fs_get_inode(ext2fs, sym_ino, &inode)) return 0; pathlen = SWAB_LE32(inode.size); if (pathlen > MAX_SYMLINK_NAME) return 0; if (inode.blocks) { if (!ext2fs_inode_block(ext2fs, &inode, 0, &block_nr)) return 0; if (block_nr) { if (!PARTITION_READ(ext2fs->part, EXT2_BLOCK_TO_SECTOR(ext2fs, block_nr), ext2fs->blocksize/IDE_SECTOR_SIZE, blockbuf)) 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 ext2fs_inode_lookup(ext2fs, dir_ino, symlink, info, 0);}/*----------------------------------------------------------------------* ext2fs_inode_lookup*----------------------------------------------------------------------*/static int ext2fs_inode_lookup(EXT2_DESC_T *ext2fs, UINT32 dir_ino, char *pathname, INODE_INFO_T *info, int type){ int len, pathlen; char *p; EXT2_DIR_T *dir = NULL; if (!pathname || (pathlen = strlen(pathname)) == 0) return 0; if (*pathname == '/') { if (--pathlen == 0) { info->ino = info->parent_ino = EXT2_ROOT_INO; info->filetype = EXT2_FTYPE_DIR; return 1; } ++pathname; dir_ino = EXT2_ROOT_INO; } while (pathlen) { int is_file = 1; // find next delimiter in path. for (p = pathname, len = 0; len < pathlen; len++, p++) { // skip delimiter if found. if (*p == '/') { ++p; --pathlen; is_file = 0; break; } } if (type == 0) dir = ext2fs_dir_lookup(ext2fs, dir_ino, pathname, len, type); else dir = ext2fs_dir_lookup(ext2fs, dir_ino, pathname, len, is_file); if (dir == NULL) return 0; pathlen -= len; pathname = p; switch (dir->filetype) { case EXT2_FTYPE_SYMLINK: // follow the symbolic link (this will cause recursion) if (!ext2fs_follow_symlink(ext2fs, 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 != EXT2_FTYPE_DIR) return 0; dir_ino = info->ino; break; case EXT2_FTYPE_DIR: if (pathlen) dir_ino = SWAB_LE32(dir->inode); break; case EXT2_FTYPE_REG_FILE: if (pathlen) return 0; // regular file embedded in middle of path break; case EXT2_FTYPE_UNKNOWN: case EXT2_FTYPE_CHRDEV: case EXT2_FTYPE_BLKDEV: case EXT2_FTYPE_FIFO: case EXT2_FTYPE_SOCK: default: return 0; } } info->ino = SWAB_LE32(dir->inode); info->parent_ino = dir_ino; info->filetype = dir->filetype; return 1;}/*----------------------------------------------------------------------* ext2fs_read*----------------------------------------------------------------------*/int ext2fs_read(void *fp, char *buf, UINT32 nbytes){ FILE_T *info = fp; EXT2_DESC_T *ext2fs; UINT32 nread = 0, rem, block_nr, bindex, to_read; if ((info->file_pos + nbytes) > info->file_size) nbytes = info->file_size - info->file_pos; ext2fs = info->ext2fs_desc; // see if we need to copy leftover data from last read call rem = ext2fs->blocksize - (info->file_pos % ext2fs->blocksize); if (rem != ext2fs->blocksize) { char *p = (char *)blockbuf + ext2fs->blocksize - rem; if (rem > nbytes) rem = nbytes; memcpy(buf, p, rem); nread += rem; buf += rem; info->file_pos += rem; } // now loop through blocks if we're not done bindex = info->file_pos / ext2fs->blocksize; while (nread < nbytes) { if (!ext2fs_inode_block(ext2fs, &info->inode, bindex, &block_nr)) return -1; if (block_nr) { if (!PARTITION_READ(ext2fs->part, EXT2_BLOCK_TO_SECTOR(ext2fs, block_nr), ext2fs->blocksize/IDE_SECTOR_SIZE, blockbuf)) return 0; } else memset(blockbuf, 0, ext2fs->blocksize); to_read = nbytes - nread; if (to_read > ext2fs->blocksize) to_read = ext2fs->blocksize; memcpy(buf, blockbuf, to_read); nread += to_read; buf += to_read; info->file_pos += to_read; ++bindex; } return nread;}/*----------------------------------------------------------------------* ext2fs_close*----------------------------------------------------------------------*/int ext2fs_close(void *fp){ FILE_T *info = fp; info->opened = 0;} /*----------------------------------------------------------------------* ext2fs_file_size*----------------------------------------------------------------------*/int ext2fs_file_size(void *fp){ FILE_T *info = fp; return info->file_size;}/*----------------------------------------------------------------------* ext2fs_ls* List file*----------------------------------------------------------------------*/void ext2fs_ls(char *pathname){ INODE_INFO_T inode_info; ext2fs_inode_lookup(&ext2fs_desc, EXT2_ROOT_INO, pathname, &inode_info, 1);}/*----------------------------------------------------------------------* ext2fs_ls_cmd* CLI command to list file*----------------------------------------------------------------------*/void ext2fs_ls_cmd(char argc, char *argv[]){ char pathname[81]; #if 1 if (argc <= 1) strcpy(pathname, "/*"); else if (strlen(argv[1]) <= 80) sprintf(pathname, "%s/*", argv[1]); else printf("Pathname is too long! (>= 80)\n");#else strcpy(pathname, "/*");#endif ide_init(); ext2fs_init(); ext2fs_ls(pathname); }#endif // BOARD_SUPPORT_IDE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -