?? linux.c
字號:
/* * linux.c * Detection of Linux file systems and boot codes * * Copyright (c) 2003 Christoph Pfisterer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */#include "detect.h"/* * ext2/ext3 file system */int detect_ext23(SECTION *section, DT_Info* info) { unsigned char *buf; char s[256]; U32 blocksize; U64 blockcount; int ret = DT_NO; if (get_buffer(section, 1024, 1024, (void **)&buf) < 1024) return DT_NO; if (get_le_short(buf + 56) == 0xEF53) { if (get_le_long(buf + 96) & 0x0008) { /* JOURNAL_DEV flag */ info->fs.type_version = 3.0; info->fs.type_version_name = _T("Ext3 external journal"); info->fs.type_name = strdup("ext3"); /* print_line(level, "Ext3 external journal"); */ } else if (get_le_long(buf + 92) & 0x0004) { /* HAS_JOURNAL flag */ info->fs.type_version = 3.0; info->fs.type_version_name = _T("Ext3 file system"); info->fs.type_name = strdup("ext3"); /* print_line(level, "Ext3 file system"); */ } else { info->fs.type_version = 2.0; info->fs.type_version_name = _T("Ext2 file system"); info->fs.type_name = strdup("ext2"); /* print_line(level, "Ext2 file system"); */ } info->fs.type = DT_EXT23; ret = DT_YES; get_string(buf + 120, 16, s); if (s[0]) /* print_line(level + 1, "Volume name \"%s\"", s); */ info->fs.volume_name = strdup(s); /* UUID */ memcpy(info->fs.uuid, buf + 104, 16); /* format_uuid(buf + 104, s, uuid_type, uuid_version); */ /* print_line(level + 1, "UUID %s", s); */ /* get_string(buf + 136, 64, s); if (s[0]) print_line(level + 1, "Last mounted at \"%s\"", s);*/ blocksize = 1024 << get_le_long(buf + 24); blockcount = get_le_long(buf + 4); info->fs.volume_blocks = blockcount; info->fs.volume_blocksize = blocksize; info->fs.volume_size = blockcount * blocksize; /* format_blocky_size(s, blockcount, blocksize, "blocks", NULL); print_line(level + 1, "Volume size %s", s); */ /* 76 4 s_rev_level */ /* 62 2 s_minor_rev_level */ /* 72 4 s_creator_os */ /* 92 3x4 s_feature_compat, s_feature_incompat, s_feature_ro_compat */ } else ret = DT_NO; return ret;}/* * ReiserFS file system */int detect_reiser(SECTION *section, DT_Info* info) { unsigned char *buf; int i, at, newformat; int offsets[3] = { 8, 64, -1 }; char s[256]; U64 blockcount; U32 blocksize; for (i = 0; offsets[i] >= 0; i++) { at = offsets[i]; if (get_buffer(section, at * 1024, 1024, (void **)&buf) < 1024) continue; /* check signature */ if (memcmp(buf + 52, "ReIsErFs", 8) == 0) { info->fs.type_version = 3.5; info->fs.type_version_name = _T("ReiserFS file system (old 3.5 format, standard journal)"); /* print_line(level, "ReiserFS file system (old 3.5 format, standard journal, starts at %d KiB)", at); */ newformat = 0; } else if (memcmp(buf + 52, "ReIsEr2Fs", 9) == 0) { info->fs.type_version = 3.6; info->fs.type_version_name = _T("ReiserFS file system (new 3.6 format, standard journal)"); /* print_line(level, "ReiserFS file system (new 3.6 format, standard journal, starts at %d KiB)", at); */ newformat = 1; } else if (memcmp(buf + 52, "ReIsEr3Fs", 9) == 0) { newformat = get_le_short(buf + 72); if (newformat == 0) { info->fs.type_version = 3.5; info->fs.type_version_name = _T("ReiserFS file system (old 3.5 format, non-standard journal)"); /* print_line(level, "ReiserFS file system (old 3.5 format, non-standard journal, starts at %d KiB)", at); */ } else if (newformat == 2) { info->fs.type_version = 3.6; info->fs.type_version_name = _T("ReiserFS file system (new 3.6 format, non-standard journal)"); /* print_line(level, "ReiserFS file system (new 3.6 format, non-standard journal, starts at %d KiB)", at); */ newformat = 1; } else { info->fs.type_version = newformat; info->fs.type_version_name = _T("ReiserFS file system (v3 magic, but unknown version)"); /* print_line(level, "ReiserFS file system (v3 magic, but unknown version %d, starts at %d KiB)", newformat, at); */ continue; } } else continue; info->fs.type = DT_REISER; info->fs.type_name = strdup("reiserfs"); /* get data */ blockcount = get_le_long(buf); blocksize = get_le_short(buf + 44); /* for new format only: hashtype = get_le_long(buf + 64); */ info->fs.volume_size = blockcount * blocksize; info->fs.volume_blocks = blockcount; info->fs.volume_blocksize = blocksize; /* get label */ get_string(buf + 100, 16, s); if (s[0]) info->fs.volume_name = strdup(s); /* print_line(level + 1, "Volume name \"%s\"", s); */ /* UUID */ memcpy(info->fs.uuid, buf + 84, 16); /* format_uuid(buf + 84, s, uuid_type, uuid_version); */ /* print_line(level + 1, "UUID %s", s); */ /* print size */ /* format_blocky_size(s, blockcount, blocksize, "blocks", NULL); print_line(level + 1, "Volume size %s", s); */ /* TODO: print hash code */ } if(info->fs.type == DT_REISER) return DT_YES; return DT_NO;}/* * Linux RAID persistent superblock */static char *levels[] = { "Multipath", "\'HSM\'", "\'translucent\'", "Linear", "RAID0", "RAID1", NULL, NULL, "RAID4(?)", "RAID5" };int detect_linux_raid(SECTION *section, DT_Info* info) { unsigned char *buf; U64 pos; int rlevel, nr_disks, raid_disks, spare; uuid_t uuid; /* don't do this if: * - the size is unknown (0) * - the size is too small for the calculation * - it is inefficient to read from the end of the source */ if (section->size < 65536 || section->source->sequential) return DT_NO; /* get RAID superblock from the end of the device */ pos = (section->size & ~65535) - 65536; if (get_buffer(section, pos, 4096, (void **)&buf) < 4096) return DT_NO; /* signature */ if (get_le_long(buf) != 0xa92b4efc) return DT_NO; /* print_line(level, "Linux RAID disk, version %lu.%lu.%lu", get_le_long(buf + 4), get_le_long(buf + 8), get_le_long(buf + 12)); */ info->fs.type = DT_LINUX_RAID; info->fs.type_name = NULL; info->fs.volume_name = NULL; /* get some data */ rlevel = (int)(long)get_le_long(buf + 28); /* is signed, actually */ nr_disks = get_le_long(buf + 36); raid_disks = get_le_long(buf + 40); spare = nr_disks - raid_disks; /* find the name for the personality in the table */ if (rlevel < -4 || rlevel > 5 || levels[rlevel+4] == NULL) { info->fs.type_version = rlevel; info->fs.type_version_name = _T("Unknown RAID level"); info->fs.volume_size = raid_disks + spare; info->fs.volume_blocks = raid_disks; /* print_line(level + 1, "Unknown RAID level %d using %d regular %d spare disks", rlevel, raid_disks, spare); */ } else { info->fs.type_version = rlevel; info->fs.type_version_name = levels[rlevel+4]; info->fs.volume_size = raid_disks + spare; info->fs.volume_blocks = raid_disks; /* print_line(level + 1, "%s set using %d regular %d spare disks", levels[rlevel+4], raid_disks, spare); */ } /* get the UUID */ memcpy(uuid, buf + 5*4, 4); memcpy(uuid + 4, buf + 13*4, 3*4); memcpy(info->fs.uuid, uuid, 16); /*format_uuid(uuid, s, uuid_type, uuid_version); print_line(level + 1, "RAID set UUID %s", s); */ return DT_YES;}/* * Linux LVM */int detect_linux_lvm(SECTION *section, DT_Info* info) { unsigned char *buf; char s[256]; U64 pe_size, pe_count, pe_start; U16 version; SECTION rs; if (get_buffer(section, 0, 1024, (void **)&buf) < 1024) return DT_NO; /* signature */ if (buf[0] != 'H' || buf[1] != 'M') return DT_NO; /* helpful sanity check... */ if (get_le_long(buf + 36) == 0 || get_le_long(buf + 40) == 0) return DT_NO; version = get_le_short(buf + 2); info->fs.type = DT_LINUX_LVM; info->fs.type_name = NULL; info->fs.type_version = version; /* print_line(level, "Linux LVM volume, version %d", (int)get_le_short(buf + 2)); */ /* volume group name */ get_string(buf + 172, 128, s); info->fs.volume_name = strdup(s); /* print_line(level + 1, "Volume group name \"%s\"", s); */ /* "UUID" of this physical volume */ uuid_unparse(buf + 0x2c, info->fs.uuid); /* get_string(buf + 0x2c, 128, s); format_uuid(uuid, s, uuid_type, uuid_version); print_line(level + 1, "PV \"UUID\" %s", s); */ /* volume size */ pe_size = get_le_long(buf + 452); pe_count = get_le_long(buf + 456); info->fs.volume_size = pe_size * pe_count; info->fs.volume_blocks = pe_size; info->fs.volume_blocksize = pe_size; /* format_blocky_size(s, pe_count, pe_size * 512, "PEs", NULL); print_line(level + 1, "Useable size %s", s); */ /* first PE starts after the declared length of the PE tables */ pe_start = get_le_long(buf + 36) + get_le_long(buf + 40);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -