⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_ext2.c

📁 pocket pc hx4700 bootloader
💻 C
字号:
/* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc. *  Copyright 2006 Pawel Kolodziejski - adopted to linux native bootloader * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "fs_types.h"#include "fs_ext2.h"/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of   the mounted filesystem DATA.  */static grub_err_t grub_ext2_blockgroup(struct grub_ext2_data *data, int group, struct grub_ext2_block_group *blkgrp) {	return grub_disk_read(data->disk, ((grub_le_to_cpu32(data->sblock.first_data_block) + 1) << LOG2_EXT2_BLOCK_SIZE(data)),						group * sizeof(struct grub_ext2_block_group),						sizeof(struct grub_ext2_block_group), (char *)blkgrp);}static int grub_ext2_read_block(grub_fshelp_node_t node, int fileblock) {	struct grub_ext2_data *data = node->data;	struct grub_ext2_inode *inode = &node->inode;	int blknr;	int blksz = EXT2_BLOCK_SIZE(data);	int log2_blksz = LOG2_EXT2_BLOCK_SIZE(data);	grub_uint32_t indir[32768 / 4]; 	/* Direct blocks.  */	if (fileblock < INDIRECT_BLOCKS)		blknr = grub_le_to_cpu32(inode->blocks.dir_blocks[fileblock]);	/* Indirect.  */	else if (fileblock < INDIRECT_BLOCKS + blksz / 4) {		if (grub_disk_read(data->disk, grub_le_to_cpu32(inode->blocks.indir_block) << log2_blksz, 0, blksz, (char *)indir))			return grub_errno;		blknr = grub_le_to_cpu32(indir[fileblock - INDIRECT_BLOCKS]);	}	/* Double indirect.  */	else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz  / 4 + 1)) {		unsigned int perblock = blksz / 4;		unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);		if (grub_disk_read(data->disk, grub_le_to_cpu32(inode->blocks.double_indir_block) << log2_blksz, 0, blksz, (char *)indir))			return grub_errno;		if (grub_disk_read(data->disk, grub_le_to_cpu32(indir[rblock / perblock]) << log2_blksz, 0, blksz, (char *)indir))			return grub_errno;		blknr = grub_le_to_cpu32(indir[rblock % perblock]);	}	/* Tripple indirect.  */	else {		grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "ext2fs doesn't support tripple indirect blocks");		return grub_errno;	}	return blknr;}/* Read LEN bytes from the file described by DATA starting with byte   POS.  Return the amount of read bytes in READ.  */static grub_ssize_t grub_ext2_read_file(grub_fshelp_node_t node,							void (*read_hook)(grub_disk_addr_t sector, unsigned offset, unsigned length),							int pos, unsigned int len, char *buf) {	return grub_fshelp_read_file(node->data->disk, node, read_hook, pos, len, buf, grub_ext2_read_block,								node->inode.size, LOG2_EXT2_BLOCK_SIZE(node->data));}/* Read the inode INO for the file described by DATA into INODE.  */static grub_err_t grub_ext2_read_inode(struct grub_ext2_data *data, int ino,					struct grub_ext2_inode *inode) {	struct grub_ext2_block_group blkgrp;	struct grub_ext2_sblock *sblock = &data->sblock;	int inodes_per_block;	unsigned int blkno;	unsigned int blkoff;	/* It is easier to calculate if the first inode is 0.  */	ino--;	grub_ext2_blockgroup(data, ino / grub_le_to_cpu32 (sblock->inodes_per_group), &blkgrp);	if (grub_errno)		return grub_errno;	inodes_per_block = EXT2_BLOCK_SIZE(data) / 128;	blkno = (ino % grub_le_to_cpu32(sblock->inodes_per_group)) / inodes_per_block;	blkoff = (ino % grub_le_to_cpu32(sblock->inodes_per_group)) % inodes_per_block;	/* Read the inode.  */	if (grub_disk_read(data->disk, ((grub_le_to_cpu32(blkgrp.inode_table_id) + blkno) << LOG2_EXT2_BLOCK_SIZE(data)),						sizeof(struct grub_ext2_inode) * blkoff, sizeof(struct grub_ext2_inode), (char *)inode))		return grub_errno;	return 0;}static struct grub_ext2_data *grub_ext2_mount(grub_disk_t disk) {	struct grub_ext2_data *data;	data = (struct grub_ext2_data *)malloc(sizeof(struct grub_ext2_data));	if (!data)		return 0;	data->disk = disk;	/* Read the superblock.  */	grub_disk_read(disk, 1 * 2, 0, sizeof(struct grub_ext2_sblock), (char *)&data->sblock);	if (grub_errno)		goto fail;	/* Make sure this is an ext2 filesystem.  */	if ((grub_uint16_t)data->sblock.magic != EXT2_MAGIC)		goto fail; 	data->diropen.data = data;	data->diropen.ino = 2;	data->diropen.inode_read = 1;	data->inode = &data->diropen.inode;	grub_ext2_read_inode(data, 2, data->inode);	if (grub_errno)		goto fail; 	return data;fail:	grub_error(GRUB_ERR_BAD_FS, "not an ext2 filesystem");	free(data);	return 0;}char *grub_ext2_read_symlink(grub_fshelp_node_t node) {	char *symlink;	struct grub_fshelp_node *diro = node;	if (!diro->inode_read) {		grub_ext2_read_inode(diro->data, diro->ino, &diro->inode);		if (grub_errno)			return 0;	}	symlink = (char *)malloc(diro->inode.size + 1);	if (!symlink)		return 0;	/* If the filesize of the symlink is bigger than	   60 the symlink is stored in a separate block,	   otherwise it is stored in the inode.  */	if (diro->inode.size <= 60)		strncpy(symlink, diro->inode.symlink, diro->inode.size);	else {		grub_ext2_read_file(diro, 0, 0, diro->inode.size, symlink);		if (grub_errno) {			free(symlink);			return 0;		}	}	symlink[diro->inode.size] = '\0';	return symlink;}static int grub_ext2_iterate_dir(grub_fshelp_node_t dir, int NESTED_FUNC_ATTR						  (*hook)(const char *filename, enum grub_fshelp_filetype filetype,								grub_fshelp_node_t node)) {	unsigned int fpos = 0;	struct grub_fshelp_node *diro = (struct grub_fshelp_node *)dir;	char filename[1024];	int ret;	if (!diro->inode_read) {		grub_ext2_read_inode(diro->data, diro->ino, &diro->inode);		if (grub_errno)			return 0;	}	/* Search the file.  */	while (fpos < diro->inode.size) {		struct ext2_dirent dirent;		grub_ext2_read_file(diro, 0, fpos, sizeof(struct ext2_dirent), (char *)&dirent);		if (grub_errno)			return 0;		if (dirent.namelen != 0) {			struct grub_fshelp_node *fdiro;			enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;			grub_ext2_read_file(diro, 0, fpos + sizeof(struct ext2_dirent), dirent.namelen, filename);			if (grub_errno)				return 0;			fdiro = (struct grub_fshelp_node *)malloc(sizeof(struct grub_fshelp_node));			if (!fdiro)				return 0;			fdiro->data = diro->data;			fdiro->ino = (grub_uint32_t)dirent.inode;			filename[dirent.namelen] = '\0';			if (dirent.filetype != FILETYPE_UNKNOWN) {				fdiro->inode_read = 0;			if (dirent.filetype == FILETYPE_DIRECTORY)				type = GRUB_FSHELP_DIR;			else if (dirent.filetype == FILETYPE_SYMLINK)				type = GRUB_FSHELP_SYMLINK;			else if (dirent.filetype == FILETYPE_REG)				type = GRUB_FSHELP_REG;			} else {				/* The filetype can not be read from the dirent, read				   the inode to get more information.  */				grub_ext2_read_inode(diro->data, dirent.inode, &fdiro->inode);				if (grub_errno) {					free(fdiro);					return 0;				}				fdiro->inode_read = 1;				if (((grub_uint16_t)fdiro->inode.mode & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)					type = GRUB_FSHELP_DIR;				else if (((grub_uint16_t)fdiro->inode.mode & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)					type = GRUB_FSHELP_SYMLINK;				else if (((grub_uint16_t)fdiro->inode.mode & FILETYPE_INO_MASK) == FILETYPE_INO_REG)					type = GRUB_FSHELP_REG;			}			if (hook(filename, type, fdiro))				return 1;		}		fpos += dirent.direntlen;	} 	return 0;}/* Open a file named NAME and initialize FILE.  */grub_err_t grub_ext2_open(struct grub_file *file, const char *name) {	struct grub_ext2_data *data;	struct grub_fshelp_node *fdiro = 0;	data = grub_ext2_mount(file->disk);	if (!data)		goto fail;	grub_fshelp_find_file(name, &data->diropen, &fdiro, grub_ext2_iterate_dir,							grub_ext2_read_symlink, GRUB_FSHELP_REG);	if (grub_errno)		goto fail;	if (!fdiro->inode_read) {		grub_ext2_read_inode(data, fdiro->ino, &fdiro->inode);		if (grub_errno)			goto fail;	}	memcpy(data->inode, &fdiro->inode, sizeof(struct grub_ext2_inode));	free(fdiro);	file->size = data->inode->size;	file->data = data;	file->offset = 0;	return 0;fail:	if (fdiro != &data->diropen)		free (fdiro);	free (data);	return grub_errno;}/* Read LEN bytes data from FILE into BUF.  */grub_ssize_t grub_ext2_read(grub_file_t file, char *buf, grub_size_t len) {	struct grub_ext2_data *data = (struct grub_ext2_data *)file->data;	return grub_ext2_read_file(&data->diropen, file->read_hook, (int)file->offset, len, buf);}grub_err_t grub_ext2_close(grub_file_t file) {	free(file->data);        return GRUB_ERR_NONE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -