Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150811
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2016-10-09 17:01:52

1. 硬盘镜像中文件系统目录如下:
  1. cong@msi:/tmp/minix$ tree 
  2. .
  3. ├── bin
  4. │   ├── init
  5. │   ├── ls
  6. │   ├── sh
  7. │   └── sh_ok
  8. ├── dev
  9. │   └── tty1
  10. ├── etc
  11. ├── usr
  12. │   └── bin
  13. └── var

  14. 6 directories, 5 files

  15. cong@msi:/tmp/minix$ ls -l bin/
  16. total 548
  17. -rwxr-xr-x 1 root root 7293 Oct 5 00:13 init
  18. -rwxr-xr-x 1 root root 46084 Jan 15 1992 ls
  19. -rwx--x--x 1 root root 250880 Feb 28 2004 sh
  20. -rwxr-xr-x 1 root root 250880 Oct 5 00:22 sh_ok

  21. cong@msi:/tmp/minix$ ls -l dev/
  22. total 0
  23. crw-r--r-- 1 root root 4, 1 Oct 5 00:13 tty1

2. 代码如下
注重功能的实现,罗嗦点也是值得的。
  1. cong@msi:/work/os/11/test$ cat readminix.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <string.h>
  8. #include "fs.h"

  9. #define IMG_PATH "./hdc.img"
  10. struct partition hd[5];
  11. char imap[I_MAP_SLOTS][BLOCK_SIZE];
  12. char zmap[Z_MAP_SLOTS][BLOCK_SIZE];
  13. struct d_super_block super;
  14. struct d_inode root;
  15. struct dir_entry root_de[64];
  16. //读取mbr,目的是要知道第一个分区的在镜像中的偏移
  17. int read_mbr(int fd)
  18. {
  19.     int i;
  20.     char buf[1024];
  21.     struct partition * p = NULL;
  22.     lseek(fd, 0, SEEK_SET);
  23.     read(fd, buf, 512);
  24.     if(buf[510]!=0x55 && buf[511]!=0xaa)
  25.     {
  26.         printf("not a boot disk\n");
  27.         return -1;
  28.     }
  29.     p =(struct partition*)&buf[0x1be];
  30.     for(i=1; i<5; i++, p++)
  31.     {
  32.         hd[i].start_sect = p->start_sect;      //镜像上只有一个minix分区,这个minix分区在磁盘的起始扇区是p->start_sect
  33.         hd[i].nr_sects = p->nr_sects;
  34.         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);
  35.     }
  36.     return 0;
  37. }
  38. //读取minix文件系统中的super block
  39. int read_super(int fd)
  40. {
  41.     int i;
  42.     char buf[1024];
  43.     //1. go to start of sector
  44.     lseek(fd, 0, SEEK_SET); //start of hdc.img
  45.     lseek(fd, hd[1].start_sect*512, SEEK_CUR);
  46.     //2. skip boot block = 2 sector
  47.     lseek(fd, 1024, SEEK_CUR);
  48.     //3. read super block
  49.     read(fd, buf, 1024);               //找到minix文件系统的super_block,大小为1024字节

  50.     super = *(struct d_super_block *) buf;
  51.     memcpy(&super, buf, sizeof(struct d_super_block));
  52.     if(super.s_magic != SUPER_MAGIC)
  53.     {
  54.         printf("not a super partition\n");
  55.         return -1;
  56.     }
  57.     printf("s_ninodes=0x%x,s_nzones=0x%x,s_imap_blocks=0x%x, \n\
  58.             s_zmap_blocks=0x%x,s_firstdatazone=0x%x,s_log_zone=0x%x, \n\
  59.             s_max_size=%ld,s_magic=0x%x\n",super.s_ninodes, super.s_nzones, super.s_imap_blocks, super.s_zmap_blocks,
  60.             super.s_firstdatazone, super.s_log_zone_size, super.s_max_size, super.s_magic);
  61.     //4. read imap blocks   这儿没啥用处
  62.     for(i=0; i<super.s_imap_blocks; i++)
  63.     {
  64.         read(fd, buf,1024);
  65.         memcpy(imap[i], buf, 1024);
  66.     }
  67.     //5. read zmap blocks 这儿没啥用处
  68.     for(i=0; i<super.s_zmap_blocks; i++)
  69.     {
  70.         read(fd, buf,1024);
  71.         memcpy(zmap[i], buf, 1024);
  72.     }
  73.     return 0;
  74. }

  75. int dump_inode(struct d_inode node)
  76. {
  77.     int i, j;
  78.     switch((node.i_mode&S_IFMT)>>12) //0xF000
  79.     {
  80.         case 0xA:
  81.             printf("F_link\n");
  82.             break;
  83.         case 0x8:
  84.             printf("REG\n");
  85.             break;
  86.         case 0x6:
  87.             printf("BLOCK\n");
  88.             break;
  89.         case 0x4:
  90.             printf("DIR\n");
  91.             break;
  92.         case 0x2:
  93.             printf("CHAR\n");
  94.             break;
  95.         case 0x1:
  96.             printf("FIFO\n");
  97.             break;
  98.     }
  99.     if(0 == node.i_nlinks)
  100.         return 0;
  101.     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",
  102.             node.i_mode,node.i_uid,node.i_size, node.i_time, node.i_gid, node.i_nlinks);
  103.     for(i=0; i<9; i++)
  104.         printf("i_zone[%d]=0x%x ", i, node.i_zone[i]);
  105.     printf("\n");
  106.     printf("\n");
  107.     return 1;
  108. }
  109. //显示minix文件系统中所有的inodes
  110. int show_all_inodes(int fd)
  111. {
  112.     int i,j;
  113.     int pos;
  114.     char buf[1024];
  115.     struct d_inode node[32];
  116.     //1. go to start of partition
  117.     lseek(fd, 0, SEEK_SET); //start of hdc.img
  118.     lseek(fd, hd[1].start_sect*512, SEEK_CUR); //go to start of partition
  119.     //2. read root inode block
  120.     pos = (1+1+super.s_imap_blocks+super.s_zmap_blocks)*BLOCK_SIZE; //boot_block super_block imap zmap
  121.     printf("root data pos=%d(block)\n", pos/BLOCK_SIZE);
  122.     lseek(fd, pos, SEEK_CUR);                    //找到inode所在的位置是:它是在minix分区的 boot_block super_block imap zmap 之后
  123.     for(i=0; i<super.s_imap_blocks-1; i++)       //inode的块数记录在s_imap_blocks中的。 这儿减1,是因为第0个块一直标记为1,但不用,所以要减去。
  124.     {
  125.         printf("show s_imap_blocks=%d\n", i);
  126.         read(fd, buf, 1024);
  127.         memcpy(node, buf, 1024);
  128.         for(i=0; i<32; i++)                     //这儿的32=1024/sizeof(struct d_inode),即一个block中含有32个inode
  129.         {
  130.             dump_inode(node[i]);
  131.         }
  132.     }
  133.     return 0;
  134. }

  135. int read_inode(int fd, int nr, struct d_inode* inode)
  136. {
  137.     char buf[1024];
  138.     int blocks = 1+1+super.s_imap_blocks+super.s_zmap_blocks + (nr-1)/INODES_PER_BLOCK; //boot_block super_block imap zmap inode
  139.     printf("read_inode=%d\n", nr);
  140.     lseek(fd, hd[1].start_sect*512, SEEK_SET); //go to start of partition
  141.     lseek(fd, blocks*1024, SEEK_CUR); //go to root_data of partition
  142.     read(fd, buf, 1024);
  143.     memcpy(inode, &buf[(nr-1)*sizeof(struct d_inode)], sizeof(struct d_inode));
  144.     printf("inode.i_zone[0]=0x%x\n", inode->i_zone[0]);
  145.     return 0;
  146. }

  147. int read_dir_block(int fd, struct d_inode inode, struct dir_entry *de)
  148. {
  149.     int i;
  150.     char buf[1024];
  151.     int entries;
  152.     entries = inode.i_size/(sizeof(struct dir_entry));
  153.     lseek(fd, hd[1].start_sect*512, SEEK_SET); //go to start of partition
  154.     lseek(fd, inode.i_zone[0]*1024, SEEK_CUR); //go to root_data of partition
  155.     printf("inode.i_zone[0]=0x%x=%d\n", inode.i_zone[0], inode.i_zone[0]);
  156.     read(fd, buf, 1024);
  157.     memcpy(de, buf, 1024);
  158.     for(i=0; i<entries; i++)
  159.     {
  160.         printf("inode=%d,name=%s\n", de[i].inode, de[i].name);
  161.     }
  162.     printf("\n");
  163.     return 0;
  164. }

  165. int show_root(int fd)
  166. {
  167.     int i;
  168.     struct dir_entry* de;
  169.     char buf[1024];
  170.     int entries;
  171.     read_inode(fd, 1, &root);     //读取root的inode,root的inode=1这是在格式化时就写在磁盘上的
  172.     if(root.i_zone[0] == 0x0)
  173.     {
  174.         printf("no root\n");
  175.         return -1;
  176.     }
  177.     read_dir_block(fd, root, root_de);    //根据root的inode读取root的数据块,并打印出来
  178.     return 0;
  179. }
  180. //显示minix文件系统中/bin/sh这个inode,这儿模拟了找文件/bin/sh的整个流程
  181. int show_bin_sh(int fd)
  182. {
  183.     int i;
  184.     int entries;
  185.     struct d_inode inode;
  186.     struct dir_entry dir_de[64];
  187. //第1步先读取root的inode,我这儿己经在show_root函数中保存在root这个全局变量里面了,所以省略。
  188. //第2步,通过root这个inode找到bin的inode号
  189.     entries = root.i_size/(sizeof(struct dir_entry));
  190.     for(i=0; i<entries; i++)
  191.     {
  192.         if(strncmp(root_de[i].name, "bin", strlen("bin")) == 0)
  193.             break;
  194.     }
  195.     if(i>entries)
  196.     {
  197.         printf("no dir: bin found\n");
  198.         return 0;
  199.     }
  200.     printf("inode=%d,name=%s\n", root_de[i].inode, root_de[i].name);
  201. //第3步,根据bin的inode号从磁盘中读取出bin的inode
  202.     read_inode(fd, root_de[i].inode, &inode);
  203.     dump_inode(inode);
  204. //第4步,通过bin的inode从磁盘中读取出bin的数据块,因为bin是一个目录,所以bin的数据块里面都是dir_entry
  205.     read_dir_block(fd, inode, dir_de);
  206.     printf("next find sh\n");
  207. //第5步, 通过bin的数据块判断sh是否在这个目录里面
  208.     entries = inode.i_size/(sizeof(struct dir_entry));
  209.     for(i=0; i<entries; i++)
  210.     {
  211.         if(strncmp(dir_de[i].name, "sh", strlen("sh")) == 0)
  212.             break;
  213.     }
  214.     if(i>=entries)
  215.     {
  216.         printf("no dir: bin found\n");
  217.         return 0;
  218.     }
  219. //第6步,找到sh的inode号,并在磁盘上把sh的inode读取出来
  220.     printf("inode=%d,name=%s\n", dir_de[i].inode, dir_de[i].name);
  221.     read_inode(fd, dir_de[i].inode, &inode);
  222. //第7步,sh是一个文件,所以inode->i_zone[0-8]中存的block块号中就是文件sh数据
  223.     dump_inode(inode);
  224.     return 0;
  225. }

  226. int main ( int argc, char *argv[] )
  227. {
  228.     int ret = -1;
  229.     if(32 != sizeof(struct d_inode))
  230.     {
  231.         printf("error: sizeof(d_inode)=%d != 32\n", sizeof(struct d_inode));
  232.         return -1;
  233.     }
  234. //打开镜像文件,镜像文件的制作方法前面的文章中介绍了
  235.     int fd = open(IMG_PATH, O_RDWR);    
  236.     if(fd < 0)
  237.     {
  238.         perror("open error\n");
  239.         return -1;
  240.     }
  241. //读取mbr,目的是要知道第一个分区的在镜像中的偏移
  242.     ret = read_mbr(fd);
  243.     if(ret < 0)
  244.     {
  245.         printf("read_mbr error\n");
  246.         return -1;
  247.     }
  248. //读取minix文件系统中的super block
  249.     ret = read_super(fd);
  250.     if(ret < 0)
  251.     {
  252.         printf("read_super error\n");
  253.         return -1;
  254.     }
  255. //显示minix文件系统中所有的inodes
  256.     show_all_inodes(fd);
  257. //显示minix文件系统中root这个inode
  258.     show_root(fd);
  259. //显示minix文件系统中/bin/sh这个inode
  260.     show_bin_sh(fd);
  261.     return EXIT_SUCCESS;
  262. }
编译:
gcc -gdwarf-2  -m32 -g3 -O0 -o readminix readminix.c



3.执行结果
  1. cong@msi:/work/os/11/test$ ./readminix
  2. 1:start_sect=2048,nr_sects=63488,p->sys_ind=0x80
  3. 2:start_sect=0,nr_sects=0,p->sys_ind=0x0
  4. 3:start_sect=0,nr_sects=0,p->sys_ind=0x0
  5. 4:start_sect=0,nr_sects=0,p->sys_ind=0x0
  6. s_ninodes=0x2a96,s_nzones=0x7fc4,s_imap_blocks=0x2,
  7.         s_zmap_blocks=0x4,s_firstdatazone=0x15d,s_log_zone=0x0,
  8.         s_max_size=268966912,s_magic=0x137f
  9. <--------------next show_all_inodes------------------>
  10. root data pos=8(block)
  11. show s_imap_blocks=0
  12. DIR
  13. i_mode=0x41ed,i_uid=0x0,i_size=0x70,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x7
  14. 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

  15. DIR
  16. i_mode=0x41ed,i_uid=0x0,i_size=0x20,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x2
  17. 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

  18. DIR
  19. i_mode=0x41ed,i_uid=0x0,i_size=0x30,i_time=0x57f3d51a,i_gid=0x0,i_nlinks=0x2
  20. 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

  21. DIR
  22. i_mode=0x41ed,i_uid=0x0,i_size=0x60,i_time=0x57f7659e,i_gid=0x0,i_nlinks=0x2
  23. 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

  24. DIR
  25. i_mode=0x41ed,i_uid=0x0,i_size=0x30,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x3
  26. 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

  27. DIR
  28. i_mode=0x41ed,i_uid=0x0,i_size=0x20,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x2
  29. 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

  30. DIR
  31. i_mode=0x41ed,i_uid=0x0,i_size=0x20,i_time=0x57f3d511,i_gid=0x0,i_nlinks=0x2
  32. 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

  33. CHAR
  34. i_mode=0x21a4,i_uid=0x0,i_size=0x0,i_time=0x57f3d51a,i_gid=0x0,i_nlinks=0x1
  35. 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

  36. REG
  37. i_mode=0x81ed,i_uid=0x0,i_size=0x1c7d,i_time=0x57f3d521,i_gid=0x0,i_nlinks=0x1
  38. 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

  39. REG
  40. i_mode=0x81ed,i_uid=0x0,i_size=0x3d400,i_time=0x57f3d74e,i_gid=0x0,i_nlinks=0x1
  41. 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

  42. REG
  43. i_mode=0x81c9,i_uid=0x0,i_size=0x3d400,i_time=0x403fdc92,i_gid=0x0,i_nlinks=0x1
  44. 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

  45. REG
  46. i_mode=0x81ed,i_uid=0x0,i_size=0xb404,i_time=0x29733578,i_gid=0x0,i_nlinks=0x1
  47. 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

  48. <--------------next show_root------------------>
  49. next show_root:
  50. read_inode=1
  51. inode.i_zone[0]=0x15d
  52. inode.i_zone[0]=0x15d=349
  53. inode=1,name=.
  54. inode=1,name=..
  55. inode=2,name=etc
  56. inode=3,name=dev
  57. inode=4,name=bin
  58. inode=5,name=usr
  59. inode=7,name=var

  60. <--------------next show_bin_sh------------------>
  61. inode=4,name=bin
  62. read_inode=4
  63. inode.i_zone[0]=0x160
  64. DIR
  65. i_mode=0x41ed,i_uid=0x0,i_size=0x60,i_time=0x57f7659e,i_gid=0x0,i_nlinks=0x2
  66. 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

  67. inode.i_zone[0]=0x160=352
  68. inode=4,name=.
  69. inode=1,name=..
  70. inode=9,name=init
  71. inode=11,name=sh
  72. inode=10,name=sh_ok
  73. inode=12,name=ls

  74. next find sh
  75. inode=11,name=sh
  76. read_inode=11
  77. inode.i_zone[0]=0x263
  78. REG
  79. i_mode=0x81c9,i_uid=0x0,i_size=0x3d400,i_time=0x403fdc92,i_gid=0x0,i_nlinks=0x1
  80. 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) |
给主人留下些什么吧!~~