📄 unix.c
字号:
/* * unix.c * Detection of general Unix file systems * * 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"/* * JFS (for Linux) */void detect_jfs(SECTION *section, int level) { unsigned char *buf; int version; char s[256]; U32 blocksize; U64 blockcount; if (get_buffer(section, 32768, 512, (void **)&buf) < 512) return; /* check signature */ if (memcmp(buf, "JFS1", 4) != 0) return; /* tell the user */ version = get_le_long(buf + 4); print_line(level, "JFS file system, version %d", version); get_string(buf + 101, 11, s); print_line(level + 1, "Volume name \"%s\"", s); blocksize = get_le_long(buf + 24); blockcount = get_le_quad(buf + 8); format_blocky_size(s, blockcount, blocksize, "h/w blocks", NULL); print_line(level + 1, "Volume size %s", s);}/* * XFS */void detect_xfs(SECTION *section, int level) { unsigned char *buf; U32 raw_version, blocksize; U64 blockcount; int version; char s[256]; if (get_buffer(section, 0, 512, (void **)&buf) < 512) return; /* check signature */ if (get_be_long(buf) != 0x58465342) return; /* tell the user */ raw_version = get_be_short(buf + 0x64); version = raw_version & 0x000f; print_line(level, "XFS file system, version %d", version); get_string(buf + 0x6c, 12, s); print_line(level + 1, "Volume name \"%s\"", s); format_uuid(buf + 32, s); print_line(level + 1, "UUID %s", s); blocksize = get_be_long(buf + 4); blockcount = get_be_quad(buf + 8); format_blocky_size(s, blockcount, blocksize, "blocks", NULL); print_line(level + 1, "Volume size %s", s);}/* * UFS file system from various BSD strains */void detect_ufs(SECTION *section, int level) { unsigned char *buf; int i, at, en, namelen, offsets[5] = { 0, 8, 64, 256, -1 }; U32 magic; char s[256]; /* NextStep/OpenStep apparently can move the superblock further into the device. Linux uses steps of 8 blocks (of the applicable block size) to scan for it. We only scan at the canonical location for now. */ /* Possible block sizes: 512 (old formats), 1024 (most), 2048 (CD media) */ for (i = 0; offsets[i] >= 0; i++) { at = offsets[i]; if (get_buffer(section, at * 1024, 1536, (void **)&buf) < 1536) break; for (en = 0; en < 2; en++) { magic = get_ve_long(en, buf + 1372); if (magic == 0x00011954) { print_line(level, "UFS file system, %d KiB offset, %s", at, get_ve_name(en)); } else if (magic == 0x00095014) { print_line(level, "UFS file system, %d KiB offset, long file names, %s", at, get_ve_name(en)); } else if (magic == 0x00195612) { print_line(level, "UFS file system, %d KiB offset, fs_featurebits, %s", at, get_ve_name(en)); } else if (magic == 0x05231994) { print_line(level, "UFS file system, %d KiB offset, fs_featurebits, >4GB support, %s", at, get_ve_name(en)); } else if (magic == 0x19540119) { print_line(level, "UFS2 file system, %d KiB offset, %s", at, get_ve_name(en)); } else continue; /* volume name by FreeBSD convention */ get_string(buf + 680, 32, s); if (s[0]) print_line(level + 1, "Volume name \"%s\" (in superblock)", s); /* last mount point */ get_string(buf + 212, 255, s); /* actually longer, but varies */ if (s[0]) print_line(level + 1, "Last mounted at \"%s\"", s); /* volume name by Darwin convention */ if (get_buffer(section, 7 * 1024, 1024, (void **)&buf) == 1024) { if (get_ve_long(en, buf) == 0x4c41424c && /* "LABL" */ get_ve_long(en, buf + 8) == 1) { /* version 1 */ namelen = get_ve_short(en, buf + 16); get_string(buf + 18, namelen, s); /* automatically limits to 255 */ print_line(level + 1, "Volume name \"%s\" (in label v%lu)", s, get_ve_long(en, buf + 8)); } } return; } }}/* * System V file system */void detect_sysv(SECTION *section, int level) { unsigned char *buf; int i, at, en, offsets[5] = { 512, 1024, -1 }; S32 blocksize_code; char s[256]; for (i = 0; offsets[i] >= 0; i++) { at = offsets[i]; if (get_buffer(section, at, 1024, (void **)&buf) < 1024) break; for (en = 0; en < 2; en++) { if (get_ve_long(en, buf + 1016) == 0x2b5544) { blocksize_code = get_ve_long(en, buf + 1020); s[0] = 0; if (blocksize_code == 1) strcpy(s, "512 byte blocks"); else if (blocksize_code == 2) strcpy(s, "1 KiB blocks"); else if (blocksize_code == 3) strcpy(s, "2 KiB blocks"); else snprintf(s, 255, "unknown block size code %d", (int)blocksize_code); print_line(level, "XENIX file system (SysV variant), %s, %s", get_ve_name(en), s); return; } if (get_ve_long(en, buf + 504) == 0xfd187e20) { blocksize_code = get_ve_long(en, buf + 508); s[0] = 0; if (blocksize_code == 1) strcpy(s, "512 byte blocks"); else if (blocksize_code == 2) strcpy(s, "1 KiB blocks"); else snprintf(s, 255, "unknown block size code %d", (int)blocksize_code); print_line(level, "SysV file system, %s, %s", get_ve_name(en), s); return; } } }}/* * BSD disklabel */static char * bsdtype_names[] = { "Unused", "swap", "Sixth Edition", "Seventh Edition", "System V", "V7 with 1 KiB blocks", "Eighth Edition, 4 KiB blocks", "4.2BSD fast file system", "ext2 or MS-DOS", "4.4BSD log-structured file system", "\"Other\"", "HPFS", "ISO9660", "bootstrap", "AmigaDOS fast file system", "Macintosh HFS", "Digital Unix AdvFS", };static char * get_name_for_bsdtype(int type) { if (type >= 0 && type <= 16) return bsdtype_names[type]; return "Unknown";}void detect_bsd_disklabel(SECTION *section, int level) { unsigned char *buf; int i, off, partcount, types[16], min_offset_valid, did_recurse; U32 starts[16], sizes[16]; U32 sectsize, nsectors, ntracks, ncylinders, secpercyl, secperunit; U64 offset, min_offset, base_offset; char s[256], append[64], pn; if (section->flags & FLAG_IN_DISKLABEL) return; if (get_buffer(section, 512, 512, (void **)&buf) < 512) return; if (get_le_long(buf) != 0x82564557 || get_le_long(buf + 132) != 0x82564557) return; sectsize = get_le_long(buf + 40); nsectors = get_le_long(buf + 44); ntracks = get_le_long(buf + 48); ncylinders = get_le_long(buf + 52); secpercyl = get_le_long(buf + 56); secperunit = get_le_long(buf + 60); partcount = get_le_short(buf + 138); if (partcount <= 8) { print_line(level, "BSD disklabel (at sector 1), %d partitions", partcount); } else if (partcount > 8 && partcount <= 16) { print_line(level, "BSD disklabel (at sector 1), %d partitions (more than usual, but valid)", partcount); } else if (partcount > 16) { print_line(level, "BSD disklabel (at sector 1), %d partitions (broken, limiting to 16)", partcount); partcount = 16; } if (sectsize != 512) { print_line(level + 1, "Unusual sector size %d bytes, your mileage may vary"); } min_offset = 0; min_offset_valid = 0; for (i = 0, off = 148; i < partcount; i++, off += 16) { starts[i] = get_le_long(buf + off + 4); sizes[i] = get_le_long(buf + off); types[i] = buf[off + 12];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -