1. 硬盘镜像中文件系统目录如下:
-
cong@msi:/tmp/minix$ tree
-
.
-
├── bin
-
│ ├── init
-
│ ├── ls
-
│ ├── sh
-
│ └── sh_ok
-
├── dev
-
│ └── tty1
-
├── etc
-
├── usr
-
│ └── bin
-
└── var
-
-
6 directories, 5 files
-
-
cong@msi:/tmp/minix$ ls -l bin/
-
total 548
-
-rwxr-xr-x 1 root root 7293 Oct 5 00:13 init
-
-rwxr-xr-x 1 root root 46084 Jan 15 1992 ls
-
-rwx--x--x 1 root root 250880 Feb 28 2004 sh
-
-rwxr-xr-x 1 root root 250880 Oct 5 00:22 sh_ok
-
-
cong@msi:/tmp/minix$ ls -l dev/
-
total 0
-
crw-r--r-- 1 root root 4, 1 Oct 5 00:13 tty1
2. 代码如下
注重功能的实现,罗嗦点也是值得的。
-
cong@msi:/work/os/11/test$ cat readminix.c
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
#include <string.h>
-
#include "fs.h"
-
-
#define IMG_PATH "./hdc.img"
-
struct partition hd[5];
-
char imap[I_MAP_SLOTS][BLOCK_SIZE];
-
char zmap[Z_MAP_SLOTS][BLOCK_SIZE];
-
struct d_super_block super;
-
struct d_inode root;
-
struct dir_entry root_de[64];
-
//读取mbr,目的是要知道第一个分区的在镜像中的偏移
-
int read_mbr(int fd)
-
{
-
int i;
-
char buf[1024];
-
struct partition * p = NULL;
-
lseek(fd, 0, SEEK_SET);
-
read(fd, buf, 512);
-
if(buf[510]!=0x55 && buf[511]!=0xaa)
-
{
-
printf("not a boot disk\n");
-
return -1;
-
}
-
p =(struct partition*)&buf[0x1be];
-
for(i=1; i<5; i++, p++)
-
{
-
hd[i].start_sect = p->start_sect; //镜像上只有一个minix分区,这个minix分区在磁盘的起始扇区是p->start_sect
-
hd[i].nr_sects = p->nr_sects;
-
printf("%d:start_sect=%d,nr_sects=%d,p->sys_ind=0x%x\n",i, hd[i].start_sect,hd[i].nr_sects, p->sys_ind);
-
}
-
return 0;
-
}
-
//读取minix文件系统中的super block
-
int read_super(int fd)
-
{
-
int i;
-
char buf[1024];
-
//1. go to start of sector
-
lseek(fd, 0, SEEK_SET); //start of hdc.img
-
lseek(fd, hd[1].start_sect*512, SEEK_CUR);
-
//2. skip boot block = 2 sector
-
lseek(fd, 1024, SEEK_CUR);
-
//3. read super block
-
read(fd, buf, 1024); //找到minix文件系统的super_block,大小为1024字节
-
-
super = *(struct d_super_block *) buf;
-
memcpy(&super, buf, sizeof(struct d_super_block));
-
if(super.s_magic != SUPER_MAGIC)
-
{
-
printf("not a super partition\n");
-
return -1;
-
}
-
printf("s_ninodes=0x%x,s_nzones=0x%x,s_imap_blocks=0x%x, \n\
-
s_zmap_blocks=0x%x,s_firstdatazone=0x%x,s_log_zone=0x%x, \n\
-
s_max_size=%ld,s_magic=0x%x\n",super.s_ninodes, super.s_nzones, super.s_imap_blocks, super.s_zmap_blocks,
-
super.s_firstdatazone, super.s_log_zone_size, super.s_max_size, super.s_magic);
-
//4. read imap blocks 这儿没啥用处
-
for(i=0; i<super.s_imap_blocks; i++)
-
{
-
read(fd, buf,1024);
-
memcpy(imap[i], buf, 1024);
-
}
-
//5. read zmap blocks 这儿没啥用处
-
for(i=0; i<super.s_zmap_blocks; i++)
-
{
-
read(fd, buf,1024);
-
memcpy(zmap[i], buf, 1024);
-
}
-
return 0;
-
}
-
-
int dump_inode(struct d_inode node)
-
{
-
int i, j;
-
switch((node.i_mode&S_IFMT)>>12) //0xF000
-
{
-
case 0xA:
-
printf("F_link\n");
-
break;
-
case 0x8:
-
printf("REG\n");
-
break;
-
case 0x6:
-
printf("BLOCK\n");
-
break;
-
case 0x4:
-
printf("DIR\n");
-
break;
-
case 0x2:
-
printf("CHAR\n");
-
break;
-
case 0x1:
-
printf("FIFO\n");
-
break;
-
}
-
if(0 == node.i_nlinks)
-
return 0;
-
printf("i_mode=0x%x,i_uid=0x%x,i_size=0x%lx,i_time=0x%lx,i_gid=0x%x,i_nlinks=0x%x\n",
-
node.i_mode,node.i_uid,node.i_size, node.i_time, node.i_gid, node.i_nlinks);
-
for(i=0; i<9; i++)
-
printf("i_zone[%d]=0x%x ", i, node.i_zone[i]);
-
printf("\n");
-
printf("\n");
-
return 1;
-
}
-
//显示minix文件系统中所有的inodes
-
int show_all_inodes(int fd)
-
{
-
int i,j;
-
int pos;
-
char buf[1024];
-
struct d_inode node[32];
-
//1. go to start of partition
-
lseek(fd, 0, SEEK_SET); //start of hdc.img
-
lseek(fd, hd[1].start_sect*512, SEEK_CUR); //go to start of partition
-
//2. read root inode block
-
pos = (1+1+super.s_imap_blocks+super.s_zmap_blocks)*BLOCK_SIZE; //boot_block super_block imap zmap
-
printf("root data pos=%d(block)\n", pos/BLOCK_SIZE);
-
lseek(fd, pos, SEEK_CUR); //找到inode所在的位置是:它是在minix分区的 boot_block super_block imap zmap 之后
-
for(i=0; i<super.s_imap_blocks-1; i++) //inode的块数记录在s_imap_blocks中的。 这儿减1,是因为第0个块一直标记为1,但不用,所以要减去。
-
{
-
printf("show s_imap_blocks=%d\n", i);
-
read(fd, buf, 1024);
-
memcpy(node, buf, 1024);
-
for(i=0; i<32; i++) //这儿的32=1024/sizeof(struct d_inode),即一个block中含有32个inode
-
{
-
dump_inode(node[i]);
-
}
-
}
-
return 0;
-
}
-
-
int read_inode(int fd, int nr, struct d_inode* inode)
-
{
-
char buf[1024];
-
int blocks = 1+1+super.s_imap_blocks+super.s_zmap_blocks + (nr-1)/INODES_PER_BLOCK; //boot_block super_block imap zmap inode
-
printf("read_inode=%d\n", nr);
-
lseek(fd, hd[1].start_sect*512, SEEK_SET); //go to start of partition
-
lseek(fd, blocks*1024, SEEK_CUR); //go to root_data of partition
-
read(fd, buf, 1024);
-
memcpy(inode, &buf[(nr-1)*sizeof(struct d_inode)], sizeof(struct d_inode));
-
printf("inode.i_zone[0]=0x%x\n", inode->i_zone[0]);
-
return 0;
-
}
-
-
int read_dir_block(int fd, struct d_inode inode, struct dir_entry *de)
-
{
-
int i;
-
char buf[1024];
-
int entries;
-
entries = inode.i_size/(sizeof(struct dir_entry));
-
lseek(fd, hd[1].start_sect*512, SEEK_SET); //go to start of partition
-
lseek(fd, inode.i_zone[0]*1024, SEEK_CUR); //go to root_data of partition
-
printf("inode.i_zone[0]=0x%x=%d\n", inode.i_zone[0], inode.i_zone[0]);
-
read(fd, buf, 1024);
-
memcpy(de, buf, 1024);
-
for(i=0; i<entries; i++)
-
{
-
printf("inode=%d,name=%s\n", de[i].inode, de[i].name);
-
}
-
printf("\n");
-
return 0;
-
}
-
-
int show_root(int fd)
-
{
-
int i;
-
struct dir_entry* de;
-
char buf[1024];
-
int entries;
-
read_inode(fd, 1, &root); //读取root的inode,root的inode=1这是在格式化时就写在磁盘上的
-
if(root.i_zone[0] == 0x0)
-
{
-
printf("no root\n");
-
return -1;
-
}
-
read_dir_block(fd, root, root_de); //根据root的inode读取root的数据块,并打印出来
-
return 0;
-
}
-
//显示minix文件系统中/bin/sh这个inode,这儿模拟了找文件/bin/sh的整个流程
-
int show_bin_sh(int fd)
-
{
-
int i;
-
int entries;
-
struct d_inode inode;
-
struct dir_entry dir_de[64];
-
//第1步先读取root的inode,我这儿己经在show_root函数中保存在root这个全局变量里面了,所以省略。
-
//第2步,通过root这个inode找到bin的inode号
-
entries = root.i_size/(sizeof(struct dir_entry));
-
for(i=0; i<entries; i++)
-
{
-
if(strncmp(root_de[i].name, "bin", strlen("bin")) == 0)
-
break;
-
}
-
if(i>entries)
-
{
-
printf("no dir: bin found\n");
-
return 0;
-
}
-
printf("inode=%d,name=%s\n", root_de[i].inode, root_de[i].name);
-
//第3步,根据bin的inode号从磁盘中读取出bin的inode
-
read_inode(fd, root_de[i].inode, &inode);
-
dump_inode(inode);
-
//第4步,通过bin的inode从磁盘中读取出bin的数据块,因为bin是一个目录,所以bin的数据块里面都是dir_entry
-
read_dir_block(fd, inode, dir_de);
-
printf("next find sh\n");
-
//第5步, 通过bin的数据块判断sh是否在这个目录里面
-
entries = inode.i_size/(sizeof(struct dir_entry));
-
for(i=0; i<entries; i++)
-
{
-
if(strncmp(dir_de[i].name, "sh", strlen("sh")) == 0)
-
break;
-
}
-
if(i>=entries)
-
{
-
printf("no dir: bin found\n");
-
return 0;
-
}
-
//第6步,找到sh的inode号,并在磁盘上把sh的inode读取出来
-
printf("inode=%d,name=%s\n", dir_de[i].inode, dir_de[i].name);
-
read_inode(fd, dir_de[i].inode, &inode);
-
//第7步,sh是一个文件,所以inode->i_zone[0-8]中存的block块号中就是文件sh的数据
-
dump_inode(inode);
-
return 0;
-
}
-
-
int main ( int argc, char *argv[] )
-
{
-
int ret = -1;
-
if(32 != sizeof(struct d_inode))
-
{
-
printf("error: sizeof(d_inode)=%d != 32\n", sizeof(struct d_inode));
-
return -1;
-
}
-
//打开镜像文件,镜像文件的制作方法前面的文章中介绍了
-
int fd = open(IMG_PATH, O_RDWR);
-
if(fd < 0)
-
{
-
perror("open error\n");
-
return -1;
-
}
-
//读取mbr,目的是要知道第一个分区的在镜像中的偏移
-
ret = read_mbr(fd);
-
if(ret < 0)
-
{
-
printf("read_mbr error\n");
-
return -1;
-
}
-
//读取minix文件系统中的super block
-
ret = read_super(fd);
-
if(ret < 0)
-
{
-
printf("read_super error\n");
-
return -1;
-
}
-
//显示minix文件系统中所有的inodes
-
show_all_inodes(fd);
-
//显示minix文件系统中root这个inode
-
show_root(fd);
-
//显示minix文件系统中/bin/sh这个inode
-
show_bin_sh(fd);
-
return EXIT_SUCCESS;
-
}
编译:
gcc -gdwarf-2 -m32 -g3 -O0 -o readminix readminix.c
3.执行结果
-
cong@msi:/work/os/11/test$ ./readminix
-
1:start_sect=2048,nr_sects=63488,p->sys_ind=0x80
-
2:start_sect=0,nr_sects=0,p->sys_ind=0x0
-
3:start_sect=0,nr_sects=0,p->sys_ind=0x0
-
4:start_sect=0,nr_sects=0,p->sys_ind=0x0
-
s_ninodes=0x2a96,s_nzones=0x7fc4,s_imap_blocks=0x2,
-
s_zmap_blocks=0x4,s_firstdatazone=0x15d,s_log_zone=0x0,
-
s_max_size=268966912,s_magic=0x137f
-
<--------------next show_all_inodes------------------>
-
root data pos=8(block)
-
show s_imap_blocks=0
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x70,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x7
-
i_zone[0]=0x15d i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x20,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x2
-
i_zone[0]=0x15e i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x30,i_time=0x57f3d51a,i_gid=0x0,i_nlinks=0x2
-
i_zone[0]=0x15f i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x60,i_time=0x57f7659e,i_gid=0x0,i_nlinks=0x2
-
i_zone[0]=0x160 i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x30,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x3
-
i_zone[0]=0x161 i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x20,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x2
-
i_zone[0]=0x162 i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x20,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x2
-
i_zone[0]=0x163 i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
CHAR
-
i_mode=0x21a4,i_uid=0x0,i_size=0x0,i_time=0x57f3d51a,i_gid=0x0,i_nlinks=0x1
-
i_zone[0]=0x401 i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
REG
-
i_mode=0x81ed,i_uid=0x0,i_size=0x1c7d,i_time=0x57f3d521,i_gid=0x0,i_nlinks=0x1
-
i_zone[0]=0x164 i_zone[1]=0x165 i_zone[2]=0x166 i_zone[3]=0x167 i_zone[4]=0x168 i_zone[5]=0x169 i_zone[6]=0x16a i_zone[7]=0x16b i_zone[8]=0x0
-
-
REG
-
i_mode=0x81ed,i_uid=0x0,i_size=0x3d400,i_time=0x57f3d74e,i_gid=0x0,i_nlinks=0x1
-
i_zone[0]=0x16d i_zone[1]=0x16e i_zone[2]=0x16f i_zone[3]=0x170 i_zone[4]=0x171 i_zone[5]=0x172 i_zone[6]=0x173 i_zone[7]=0x174 i_zone[8]=0x0
-
-
REG
-
i_mode=0x81c9,i_uid=0x0,i_size=0x3d400,i_time=0x403fdc92,i_gid=0x0,i_nlinks=0x1
-
i_zone[0]=0x263 i_zone[1]=0x264 i_zone[2]=0x265 i_zone[3]=0x266 i_zone[4]=0x267 i_zone[5]=0x268 i_zone[6]=0x269 i_zone[7]=0x26a i_zone[8]=0x0
-
-
REG
-
i_mode=0x81ed,i_uid=0x0,i_size=0xb404,i_time=0x29733578,i_gid=0x0,i_nlinks=0x1
-
i_zone[0]=0x359 i_zone[1]=0x35a i_zone[2]=0x35b i_zone[3]=0x35c i_zone[4]=0x35d i_zone[5]=0x35e i_zone[6]=0x35f i_zone[7]=0x360 i_zone[8]=0x0
-
-
<--------------next show_root------------------>
-
next show_root:
-
read_inode=1
-
inode.i_zone[0]=0x15d
-
inode.i_zone[0]=0x15d=349
-
inode=1,name=.
-
inode=1,name=..
-
inode=2,name=etc
-
inode=3,name=dev
-
inode=4,name=bin
-
inode=5,name=usr
-
inode=7,name=var
-
-
<--------------next show_bin_sh------------------>
-
inode=4,name=bin
-
read_inode=4
-
inode.i_zone[0]=0x160
-
DIR
-
i_mode=0x41ed,i_uid=0x0,i_size=0x60,i_time=0x57f7659e,i_gid=0x0,i_nlinks=0x2
-
i_zone[0]=0x160 i_zone[1]=0x0 i_zone[2]=0x0 i_zone[3]=0x0 i_zone[4]=0x0 i_zone[5]=0x0 i_zone[6]=0x0 i_zone[7]=0x0 i_zone[8]=0x0
-
-
inode.i_zone[0]=0x160=352
-
inode=4,name=.
-
inode=1,name=..
-
inode=9,name=init
-
inode=11,name=sh
-
inode=10,name=sh_ok
-
inode=12,name=ls
-
-
next find sh
-
inode=11,name=sh
-
read_inode=11
-
inode.i_zone[0]=0x263
-
REG
-
i_mode=0x81c9,i_uid=0x0,i_size=0x3d400,i_time=0x403fdc92,i_gid=0x0,i_nlinks=0x1
-
i_zone[0]=0x263 i_zone[1]=0x264 i_zone[2]=0x265 i_zone[3]=0x266 i_zone[4]=0x267 i_zone[5]=0x268 i_zone[6]=0x269 i_zone[7]=0x26a i_zone[8]=0x0
下一步读取0x263 0x264 0x265 0x266 0x267 0x268 0x269 的内容
以及0x26a--->所提向的块号的内容,就可以把sh整个文件的内容读取出来
4. 代码下载
readminix.rar(下载后改名为readminix.tar.gz)
代码中包含hdc.img
阅读(1295) | 评论(0) | 转发(0) |