1. 概述
在 Linux系統的機器上檢視MBR資料 一文中,通過指令的方式給出了Linux下面MBR的資料示例,其中對MBR中每個資料結構的讀取&解析也是人工方式的。本文繼續該内容,但通過代碼自動分析MBR各個字段的内容。
本文編碼所在的環境和上篇不同,是以MBR資料和上文存在差異。
2. 疊代1:讀MBR所在第一個扇區的資料
本文采用靈活開發的模式,一步步給出問題的最終解決方案。
作為第一步,要能夠讀取到硬碟的第一個扇區,即MBR資料。至于資料解析,我們留到下一個疊代。
2.1 代碼
下面是讀取MBR的代碼:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = -1;
const unsigned int SECTOR_SIZE = 512;
unsigned char buf[SECTOR_SIZE];
ssize_t read_count;
const char* DEV_NAME = "/dev/sda";
fd = open(DEV_NAME, O_RDONLY);
if (fd == -1) {
printf("Open file failed.\n");
return -1;
}
read_count = read(fd, buf, SECTOR_SIZE);
if (read_count != SECTOR_SIZE) {
printf("Read error: %d\n", read_count);
close(fd);
return -1;
}
printf("\n\n Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
for (ssize_t i = 0; i < SECTOR_SIZE; i++) {
if (i % 16 == 0) {
printf("\n0x%04X ", i);
}
printf("%02X ", buf[i]);
}
printf("\n");
close(fd);
return 0;
}
2.2 運作
[email protected]:~/examples/cpp/read_mbr$ gcc -std=c99 main.c
[email protected]:~/examples/cpp/read_mbr$ sudo ./a.out
Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0x0000 EB 63 90 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E
0x0010 DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A
0x0020 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4
0x0030 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00
0x0040 B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC
0x0050 0A C0 74 FA B4 0E BB 07 00 CD 00 80 01 00 00 00
0x0060 00 00 00 00 FF FA 90 90 F6 C2 80 74 05 F6 C2 70
0x0070 74 02 B2 80 EA 79 7C 00 00 31 C0 8E D8 8E D0 BC
0x0080 00 20 FB A0 64 7C 3C FF 74 02 88 C2 52 BB 17 04
0x0090 80 27 03 74 06 BE 88 7D E8 17 01 BE 05 7C B4 41
0x00A0 BB AA 55 CD 13 5A 52 72 3D 81 FB 55 AA 75 37 83
0x00B0 E1 01 74 32 31 C0 89 44 04 40 88 44 FF 89 44 02
0x00C0 C7 04 10 00 66 8B 1E 5C 7C 66 89 5C 08 66 8B 1E
0x00D0 60 7C 66 89 5C 0C C7 44 06 00 70 B4 42 CD 13 72
0x00E0 05 BB 00 70 EB 76 B4 08 CD 13 73 0D F6 C2 80 0F
0x00F0 84 D0 00 BE 93 7D E9 82 00 66 0F B6 C6 88 64 FF
0x0100 40 66 89 44 04 0F B6 D1 C1 E2 02 88 E8 88 F4 40
0x0110 89 44 08 0F B6 C2 C0 E8 02 66 89 04 66 A1 60 7C
0x0120 66 09 C0 75 4E 66 A1 5C 7C 66 31 D2 66 F7 34 88
0x0130 D1 31 D2 66 F7 74 04 3B 44 08 7D 37 FE C1 88 C5
0x0140 30 C0 C1 E8 02 08 C1 88 D0 5A 88 C6 BB 00 70 8E
0x0150 C3 31 DB B8 01 02 CD 13 72 1E 8C C3 60 1E B9 00
0x0160 01 8E DB 31 F6 BF 00 80 8E C6 FC F3 A5 1F 61 FF
0x0170 26 5A 7C BE 8E 7D EB 03 BE 9D 7D E8 34 00 BE A2
0x0180 7D E8 2E 00 CD 18 EB FE 47 52 55 42 20 00 47 65
0x0190 6F 6D 00 48 61 72 64 20 44 69 73 6B 00 52 65 61
0x01A0 64 00 20 45 72 72 6F 72 0D 0A 00 BB 01 00 B4 0E
0x01B0 CD 10 AC 3C 00 75 F4 C3 32 F2 49 15 00 00 80 01
0x01C0 01 00 07 EF FF FF 3F 00 00 00 D0 88 81 1D 00 FE
0x01D0 FF FF 05 FE FF FF FE 8F 81 1D 02 60 07 1C 00 EF
0x01E0 FF FF 07 EF FF FF 10 F1 88 39 80 57 AF 00 00 00
0x01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
[email protected]:~/examples/cpp/read_mbr$
初步地分析這個碼流,我們知道已成功讀取MBR的資料,比如最後的55 AA;再倒數的每16個位元組一組的MBR Partition Record。進一步地,可以用上一節的指令做對比:
[email protected]:~/examples/cpp/read_mbr$ sudo dd if=/dev/sda ibs=512 count=1 | hexdump -C
00000000 eb 63 90 00 02 8e d7 bc 00 7a bb a0 07 8b ce 8e |.c.......z......|
00000010 db 8e c3 f3 a4 ea 5d 00 a0 07 10 00 01 00 00 7a |......]........z|
00000020 00 00 00 00 00 00 00 00 00 00 07 66 8b 55 08 b4 |...........f.U..|
00000030 42 c6 06 1f 00 7c 32 c0 66 89 16 22 00 be 1a 00 |B....|2.f.."....|
00000040 b2 80 cd 13 0f 82 cd 00 81 3e fe 03 55 aa c3 ac |.........>..U...|
00000050 0a c0 74 fa b4 0e bb 07 00 cd 00 80 01 00 00 00 |..t.............|
00000060 00 00 00 00 ff fa 90 90 f6 c2 80 74 05 f6 c2 70 |...........t...p|
00000070 74 02 b2 80 ea 79 7c 00 00 31 c0 8e d8 8e d0 bc |t....y|..1......|
00000080 00 20 fb a0 64 7c 3c ff 74 02 88 c2 52 bb 17 04 |. ..d|<.t...R...|
00000090 80 27 03 74 06 be 88 7d e8 17 01 be 05 7c b4 41 |.'.t...}.....|.A|
000000a0 bb aa 55 cd 13 5a 52 72 3d 81 fb 55 aa 75 37 83 |..U..ZRr=..U.u7.|
000000b0 e1 01 74 32 31 c0 89 44 04 40 88 44 ff 89 44 02 |[email protected].|
000000c0 c7 04 10 00 66 8b 1e 5c 7c 66 89 5c 08 66 8b 1e |....f..\|f.\.f..|
000000d0 60 7c 66 89 5c 0c c7 44 06 00 70 b4 42 cd 13 72 |`|f.\..D..p.B..r|
000000e0 05 bb 00 70 eb 76 b4 08 cd 13 73 0d f6 c2 80 0f |...p.v....s.....|
000000f0 84 d0 00 be 93 7d e9 82 00 66 0f b6 c6 88 64 ff |.....}...f....d.|
00000100 40 66 89 44 04 0f b6 d1 c1 e2 02 88 e8 88 f4 40 |@f.D...........@|
00000110 89 44 08 0f b6 c2 c0 e8 02 66 89 04 66 a1 60 7c |.D.......f..f.`||
00000120 66 09 c0 75 4e 66 a1 5c 7c 66 31 d2 66 f7 34 88 |f..uNf.\|f1.f.4.|
00000130 d1 31 d2 66 f7 74 04 3b 44 08 7d 37 fe c1 88 c5 |.1.f.t.;D.}7....|
00000140 30 c0 c1 e8 02 08 c1 88 d0 5a 88 c6 bb 00 70 8e |0........Z....p.|
00000150 c3 31 db b8 01 02 cd 13 72 1e 8c c3 60 1e b9 00 |.1......r...`...|
00000160 01 8e db 31 f6 bf 00 80 8e c6 fc f3 a5 1f 61 ff |...1..........a.|
00000170 26 5a 7c be 8e 7d eb 03 be 9d 7d e8 34 00 be a2 |&Z|..}....}.4...|
00000180 7d e8 2e 00 cd 18 eb fe 47 52 55 42 20 00 47 65 |}.......GRUB .Ge|
00000190 6f 6d 00 48 61 72 64 20 44 69 73 6b 00 52 65 61 |om.Hard Disk.Rea|
000001a0 64 00 20 45 72 72 6f 72 0d 0a 00 bb 01 00 b4 0e |d. Error........|
000001b0 cd 10 ac 3c 00 75 f4 c3 32 f2 49 15 00 00 80 01 |...<.u..2.I.....|
000001c0 01 00 07 ef ff ff 3f 00 00 00 d0 88 81 1d 00 fe |......?.........|
000001d0 ff ff 05 fe ff ff fe 8f 81 1d 02 60 07 1c 00 ef |...........`....|
000001e0 ff ff 07 ef ff ff 10 f1 88 39 80 57 af 00 00 00 |.........9.W....|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
記錄了1+0 的讀入
記錄了1+0 的寫出
512位元組(512 B)已複制,0.00250075 秒,205 kB/秒
00000200
[email protected]:~/examples/cpp/read_mbr$
2.3 幾個問題分析
1. 在上面的代碼中,有一大段是輸出碼流的代碼,而且這個功能也相對獨立。是以需要把這一部分代碼重構到一個獨立的函數中。
2. 再者,對裝置檔案是寫死的,是以如果能夠參數化,則更加靈活。再進一步,如果能夠自動識别MBR所在的裝置名稱,代碼就更具有可移植性。
3. MBR中每一個組成部分還沒有自動分析出來,是以需要增加結構化分析。
接下來就是通過每一個疊代來實作上述功能。
3. 疊代2:領域無關代碼的重構
這一步,我們把和讀取&解析MBR無關的代碼分離出去,也就是把輸出二進制碼流部分的代碼利用Extract Method手法提取出去。
另外從現在開始,我們從C切換到C++。此時代碼包括如下幾個檔案:
- main.cpp:領域代碼;
- file-utils.h:提取出來的列印二進制碼流的實用小函數,頭檔案;
- file-tuils.cpp:使用小函數的實作檔案。
3.1 main.cpp
#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <file-utils.h>
int main()
{
int fd = -1;
const unsigned int SECTOR_SIZE = 512;
unsigned char buf[SECTOR_SIZE];
ssize_t read_count;
const char* DEV_NAME = "/dev/sda";
fd = open(DEV_NAME, O_RDONLY);
if (fd == -1) {
printf("Open file failed.\n");
return -1;
}
read_count = read(fd, buf, SECTOR_SIZE);
if (read_count != SECTOR_SIZE) {
printf("Read error: %d\n", read_count);
close(fd);
return -1;
}
dump_binary(buf, SECTOR_SIZE);
close(fd);
return 0;
}
3.2 file-utils.h
/*
* File utilities.
*
*/
#ifndef __FILE_UTILS_H
#define __FILE_UTILS_H
/*
* Dump the binary stream.
* 16 bytes each line.
*/
void dump_binary(unsigned char *buf, unsigned int len);
#endif //__FILE_UTILS_H
3.3 file-utils.cpp
#include <file-utils.h>
#include <cstdio>
void dump_binary(unsigned char *buf, unsigned int len)
{
printf("\n\n Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
for (unsigned int i = 0; i < len; i++) {
if (i % 16 == 0) {
printf("\n0x%04X ", i);
}
printf("%02X ", buf[i]);
}
printf("\n\n");
}
3.4 編譯&運作
[email protected]:~/examples/cpp/read_mbr$ g++ main.cpp file-utils.cpp -I.
[email protected]:~/examples/cpp/read_mbr$ sudo ./a.out
Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0x0000 EB 63 90 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E
0x0010 DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A
0x0020 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4
0x0030 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00
0x0040 B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC
0x0050 0A C0 74 FA B4 0E BB 07 00 CD 00 80 01 00 00 00
0x0060 00 00 00 00 FF FA 90 90 F6 C2 80 74 05 F6 C2 70
0x0070 74 02 B2 80 EA 79 7C 00 00 31 C0 8E D8 8E D0 BC
0x0080 00 20 FB A0 64 7C 3C FF 74 02 88 C2 52 BB 17 04
0x0090 80 27 03 74 06 BE 88 7D E8 17 01 BE 05 7C B4 41
0x00A0 BB AA 55 CD 13 5A 52 72 3D 81 FB 55 AA 75 37 83
0x00B0 E1 01 74 32 31 C0 89 44 04 40 88 44 FF 89 44 02
0x00C0 C7 04 10 00 66 8B 1E 5C 7C 66 89 5C 08 66 8B 1E
0x00D0 60 7C 66 89 5C 0C C7 44 06 00 70 B4 42 CD 13 72
0x00E0 05 BB 00 70 EB 76 B4 08 CD 13 73 0D F6 C2 80 0F
0x00F0 84 D0 00 BE 93 7D E9 82 00 66 0F B6 C6 88 64 FF
0x0100 40 66 89 44 04 0F B6 D1 C1 E2 02 88 E8 88 F4 40
0x0110 89 44 08 0F B6 C2 C0 E8 02 66 89 04 66 A1 60 7C
0x0120 66 09 C0 75 4E 66 A1 5C 7C 66 31 D2 66 F7 34 88
0x0130 D1 31 D2 66 F7 74 04 3B 44 08 7D 37 FE C1 88 C5
0x0140 30 C0 C1 E8 02 08 C1 88 D0 5A 88 C6 BB 00 70 8E
0x0150 C3 31 DB B8 01 02 CD 13 72 1E 8C C3 60 1E B9 00
0x0160 01 8E DB 31 F6 BF 00 80 8E C6 FC F3 A5 1F 61 FF
0x0170 26 5A 7C BE 8E 7D EB 03 BE 9D 7D E8 34 00 BE A2
0x0180 7D E8 2E 00 CD 18 EB FE 47 52 55 42 20 00 47 65
0x0190 6F 6D 00 48 61 72 64 20 44 69 73 6B 00 52 65 61
0x01A0 64 00 20 45 72 72 6F 72 0D 0A 00 BB 01 00 B4 0E
0x01B0 CD 10 AC 3C 00 75 F4 C3 32 F2 49 15 00 00 80 01
0x01C0 01 00 07 EF FF FF 3F 00 00 00 D0 88 81 1D 00 FE
0x01D0 FF FF 05 FE FF FF FE 8F 81 1D 02 60 07 1C 00 EF
0x01E0 FF FF 07 EF FF FF 10 F1 88 39 80 57 AF 00 00 00
0x01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA
[email protected]:~/examples/cpp/read_mbr$
4. 疊代3:MBR領域模組化
前面的示範,僅列印了第一個扇區的碼流,具體内容是我們根據MBR格式,去查找對應位置的二進制資料。接下來我們對MBR模組化,即對MBR所在第一個扇區的内容重構到對應的資料結構中。
此時新增了mbr.h,.cpp,并對main.cpp進行了重構。同時,我們重用了 Windows上面讀磁盤分區表 一文中的代碼。
4.1 mbr.h
#ifndef __MBR_H
#define __MBR_H
struct CHS {
unsigned int header;
unsigned int sector;
unsigned int cylinder;
};
struct partition_record {
unsigned char boot_indicator;
unsigned char os_type;
struct CHS starting_chs;
struct CHS ending_chs;
unsigned int starting_LBA;
unsigned int size_in_LBA;
};
const unsigned int BOOT_LOADER_CODE_SIZE = 446;
struct mbr {
unsigned char boot_loader_code[BOOT_LOADER_CODE_SIZE];
struct partition_record partition_records[4];
};
/*
buffer: the 512-bytes of first sector.
The caller ensure that it is the right data.
return: 0 - SUCCESS.
-1: invalid mbr, i.e. the signature is not 0xaa55.
*/
int get_mbr(unsigned char buffer[], struct mbr &mbr);
#endif //__MBR_H
4.2 mbr.cpp
#include "mbr.h"
#include <cstdio>
#include <cstring> //memcpy
#include "file-utils.h"
static void dump_partition_record(const partition_record& record)
{
const double DISK_SECTOR_SIZE = 512.0;
const size_t GB = 1024 * 1024 * 1024;
printf(
"\tboot indicator: 0x%02x\n"
"\tOS Type: 0x%02x\n"
"\tStarting CHS: (%d, %d, %d)\n"
"\tEnding_CHS: (%d, %d, %d)\n"
"\tSize in LBA: %d\n"
"\tSize:%.2f\n\n",
record.boot_indicator,
record.os_type,
record.starting_chs.cylinder,
record.starting_chs.header,
record.starting_chs.sector,
record.ending_chs.cylinder,
record.ending_chs.header,
record.ending_chs.sector,
record.size_in_LBA,
record.size_in_LBA * DISK_SECTOR_SIZE / GB);
}
// transform the 16-bytes buffer to partition record
static void get_partition_record(unsigned char buffer[], struct partition_record& record)
{
record.boot_indicator = buffer[0];
record.starting_chs.header = buffer[1];
record.starting_chs.sector = buffer[2] & 0x3f;
record.starting_chs.cylinder = (((buffer[2] & 0xff) >> 6) << 8) + buffer[3];
record.os_type = buffer[4];
record.ending_chs.header = buffer[5];
record.ending_chs.sector = buffer[6] & 0x3f;
record.ending_chs.cylinder = (((buffer[6] & 0xff) >> 6) << 8) + buffer[7];
record.size_in_LBA = *(unsigned int*)(buffer + 12);
}
int get_mbr(unsigned char buffer[], struct mbr &mbr)
{
// check the signature, it must be 0xaa55
const unsigned int SIGNATURE_OFFSET = 510;
if (buffer[SIGNATURE_OFFSET] != 0x55 && buffer[SIGNATURE_OFFSET + 1] != 0xaa) {
printf("ERROR: invalid mbr!\n");
return -1;
}
memcpy(mbr.boot_loader_code, buffer, BOOT_LOADER_CODE_SIZE);
printf("boot loader:");
dump_binary(mbr.boot_loader_code, BOOT_LOADER_CODE_SIZE);
unsigned char *partition_record = buffer + BOOT_LOADER_CODE_SIZE;
const unsigned int PARTITION_RECORD_SIZE = 16;
for (unsigned int i = 0; i < 4; i++) {
get_partition_record(
buffer + BOOT_LOADER_CODE_SIZE + i * PARTITION_RECORD_SIZE,
mbr.partition_records[0]);
dump_partition_record(mbr.partition_records[0]);
}
return 0;
}
4.3 main.cpp
#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "mbr.h"
int main()
{
int fd = -1;
const unsigned int SECTOR_SIZE = 512;
unsigned char buf[SECTOR_SIZE];
ssize_t read_count;
const char* DEV_NAME = "/dev/sda";
fd = open(DEV_NAME, O_RDONLY);
if (fd == -1) {
printf("Open file failed.\n");
return -1;
}
read_count = read(fd, buf, SECTOR_SIZE);
if (read_count != SECTOR_SIZE) {
printf("Read error: %d\n", read_count);
close(fd);
return -1;
}
struct mbr mbr = {0};
get_mbr(buf, mbr);
close(fd);
return 0;
}
4.4 運作結果
[email protected]:~/examples/cpp/read_mbr$ g++ main.cpp file-utils.cpp mbr.cpp -I.
[email protected]:~/examples/cpp/read_mbr$ sudo ./a.out
boot loader:
Addr 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0x0000 EB 63 90 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E
0x0010 DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A
0x0020 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4
0x0030 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00
0x0040 B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC
0x0050 0A C0 74 FA B4 0E BB 07 00 CD 00 80 01 00 00 00
0x0060 00 00 00 00 FF FA 90 90 F6 C2 80 74 05 F6 C2 70
0x0070 74 02 B2 80 EA 79 7C 00 00 31 C0 8E D8 8E D0 BC
0x0080 00 20 FB A0 64 7C 3C FF 74 02 88 C2 52 BB 17 04
0x0090 80 27 03 74 06 BE 88 7D E8 17 01 BE 05 7C B4 41
0x00A0 BB AA 55 CD 13 5A 52 72 3D 81 FB 55 AA 75 37 83
0x00B0 E1 01 74 32 31 C0 89 44 04 40 88 44 FF 89 44 02
0x00C0 C7 04 10 00 66 8B 1E 5C 7C 66 89 5C 08 66 8B 1E
0x00D0 60 7C 66 89 5C 0C C7 44 06 00 70 B4 42 CD 13 72
0x00E0 05 BB 00 70 EB 76 B4 08 CD 13 73 0D F6 C2 80 0F
0x00F0 84 D0 00 BE 93 7D E9 82 00 66 0F B6 C6 88 64 FF
0x0100 40 66 89 44 04 0F B6 D1 C1 E2 02 88 E8 88 F4 40
0x0110 89 44 08 0F B6 C2 C0 E8 02 66 89 04 66 A1 60 7C
0x0120 66 09 C0 75 4E 66 A1 5C 7C 66 31 D2 66 F7 34 88
0x0130 D1 31 D2 66 F7 74 04 3B 44 08 7D 37 FE C1 88 C5
0x0140 30 C0 C1 E8 02 08 C1 88 D0 5A 88 C6 BB 00 70 8E
0x0150 C3 31 DB B8 01 02 CD 13 72 1E 8C C3 60 1E B9 00
0x0160 01 8E DB 31 F6 BF 00 80 8E C6 FC F3 A5 1F 61 FF
0x0170 26 5A 7C BE 8E 7D EB 03 BE 9D 7D E8 34 00 BE A2
0x0180 7D E8 2E 00 CD 18 EB FE 47 52 55 42 20 00 47 65
0x0190 6F 6D 00 48 61 72 64 20 44 69 73 6B 00 52 65 61
0x01A0 64 00 20 45 72 72 6F 72 0D 0A 00 BB 01 00 B4 0E
0x01B0 CD 10 AC 3C 00 75 F4 C3 32 F2 49 15 00 00
boot indicator: 0x80
OS Type: 0x07
Starting CHS: (0, 1, 1)
Ending_CHS: (1023, 239, 63)
Size in LBA: 495028432
Size:236.05
boot indicator: 0x00
OS Type: 0x05
Starting CHS: (1023, 254, 63)
Ending_CHS: (1023, 254, 63)
Size in LBA: 470245378
Size:224.23
boot indicator: 0x00
OS Type: 0x07
Starting CHS: (1023, 239, 63)
Ending_CHS: (1023, 239, 63)
Size in LBA: 11491200
Size:5.48
boot indicator: 0x00
OS Type: 0x00
Starting CHS: (0, 0, 0)
Ending_CHS: (0, 0, 0)
Size in LBA: 0
Size:0.00
[email protected]:~/examples/cpp/read_mbr$
可以看到,和 Windows上面讀磁盤分區表 一文的partition record資料一樣,但boot loader不一樣。這是因為在windows系統上,後來裝成了雙系統,是以更新了boot loader。
5. 疊代4:自動分析裝置名稱
前面的代碼中,裝置名稱是hard code成/dev/sda。但不同的環境可能并不都是這個裝置名稱,比如雙硬碟的情況,還可能MBR在sdb上面。為此,可否自動分析出MBR所在裝置名稱呢?接下來就實作這個功能。