📄 rescuept.c
字号:
/* * rescuept - Andries Brouwer - aeb@cwi.nl - 1999 * * This may be distributed under the GPL. * * call: rescuept /dev/xxx * * The output is a proposed partition table, in the * form of input to sfdisk. Typical use: * * ./rescuept /dev/xxx > xxx.pt * now look at xxx.pt to see whether it resembles what * you expected, and possibly edit the partition types; * if you are satisfied, then * sfdisk /dev/xxx < xxx.pt * will restore your partition table. If you are cautious, use * sfdisk /dev/xxx -O xxx.old < xxx.pt * so that the original state can be retrieved using * sfdisk /dev/xxx -I xxx.old * * Here xxx stands for hda or hdb or sda or sdb or ... */#include <stdio.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/ioctl.h>#ifndef BLKGETSIZE#define BLKGETSIZE _IO(0x12,96)#endifchar *progname;char *device;#define MAXPARTITIONS 100#define MAXPAGESZ 65536#define BUFSZ 1024000#define BUFSECS (BUFSZ/512)char buf[BUFSZ];int bufstart = -1;typedef unsigned int uint32;typedef int sint32;typedef unsigned short uint16;typedef short sint16;typedef unsigned char uchar;void read_sectors(int fd, char *buf, int sectornr, int sectorct) { extern long long llseek(); long long offset; int n; offset = sectornr; offset *= 512; if (llseek(fd, offset, SEEK_SET) != offset) { fprintf(stderr, "%s: llseek error\n", progname); exit(1); } n = read(fd, buf, sectorct*512); if (n != sectorct*512) { if (n == -1) perror("read"); fprintf(stderr, "%s: error reading sectors %d-%d\n", progname, sectornr, sectornr+sectorct-1); exit(1); }}/* * Partition table stuff */struct partition { unsigned char bootable; /* 0 or 0x80 */ uchar begin_chs[3]; unsigned char sys_type; uchar end_chs[3]; unsigned int start_sect; /* starting sector counting from 0 */ unsigned int nr_sects; /* nr of sectors in partition */};intis_extended(unsigned char sys_type) { return (sys_type == 0x5 || sys_type == 0xf || sys_type == 0x85);}/* * List of (extended) partition table sectors found */struct epts { int secno; char pt4[64];} epts[MAXPARTITIONS];int eptsct;void addepts(int secno, char *data) { if (eptsct >= MAXPARTITIONS) return; /* ignore */ epts[eptsct].secno = secno; memcpy(epts[eptsct].pt4, data+512-66, 64); eptsct++;}/* * List of guessed partitions */struct pt { int pno; int start; int size; unsigned char type;} pts[MAXPARTITIONS];int partno;void addpart(int start, int size, unsigned char type) { if (partno >= MAXPARTITIONS) return; /* ignore */ pts[partno].start = start; pts[partno].size = size; pts[partno].type = type; partno++;}void outparts() { int i; for(i=0; i<partno; i++) printf("%s%d : start=%9d, size=%8d, Id=%2x\n", device, pts[i].pno, pts[i].start, pts[i].size, pts[i].type);}void outmsg(char *msg, int start, int nextstart, unsigned char type) { printf("# %5d MB %16s (type %2x): sectors %9d-%9d\n", ((nextstart-start)+1024)/2048, msg, type, start, nextstart-1);}intcreate_extended_partition(int fd, int secno, int size) { int sec = secno; int cursec = secno; int pno = partno; /* number of extd partition */ int ei = eptsct-1; unsigned char type = 0x5; int lastseen = secno; int ok = 0; if (epts[ei].secno != secno) { fprintf(stderr, "%s: program bug\n", progname); exit(1); } outmsg("candidate ext pt", secno, secno+1, type); addpart(secno, 1, type); /* size to be filled in later */ while(1) { char buf[512]; struct partition *p1, *p2, *pr, *pe; p1 = (struct partition *)(& epts[ei].pt4[0]); p2 = (struct partition *)(& epts[ei].pt4[16]); /* for the time being we just ignore the rest */ if (is_extended(p1->sys_type)) { pr = p2; pe = p1; } else if (is_extended(p2->sys_type)) { pr = p1; pe = p2; } else if (p1->sys_type == 0) { pr = p2; pe = 0; } else if (p2->sys_type == 0) { pr = p1; pe = 0; } else break; /* first handle the real partition, if any */ if (pr->sys_type != 0) { int ss = cursec + pr->start_sect; int es = ss + pr->nr_sects; outmsg("found in ept", ss, es, pr->sys_type); addpart(ss, pr->nr_sects, pr->sys_type); if (lastseen < es - 1) lastseen = es - 1; if (lastseen >= size) break; } /* then the extended link */ if (!pe) { ok = 1; break; } type = pe->sys_type; cursec = sec + pe->start_sect; if (cursec >= size) break; read_sectors(fd, buf, cursec, 1); addepts(cursec, buf); ei = eptsct-1; } if (!ok || lastseen == secno) { printf("# retracted\n"); partno = pno; return 0; } pts[pno].type = type; pts[pno].size = lastseen+1-secno; outmsg("extended part ok", secno, lastseen+1, type); return lastseen;} /* * Recognize an ext2 superblock */#define EXT2_SUPER_MAGIC 0xEF53struct ext2_super_block { uint32 s_inodes_count; /* 0: Inodes count */ uint32 s_blocks_count; /* 4: Blocks count */ uint32 s_r_blocks_count; /* 8: Reserved blocks count */ uint32 s_free_blocks_count; /* 12: Free blocks count */ uint32 s_free_inodes_count; /* 16: Free inodes count */ uint32 s_first_data_block; /* 20: First Data Block */ uint32 s_log_block_size; /* 24: Block size */ sint32 s_log_frag_size; /* 28: Fragment size */ uint32 s_blocks_per_group; /* 32: # Blocks per group */ uint32 s_frags_per_group; /* 36: # Fragments per group */ uint32 s_inodes_per_group; /* 40: # Inodes per group */ uint32 s_mtime; /* 44: Mount time */ uint32 s_wtime; /* 48: Write time */ uint16 s_mnt_count; /* 52: Mount count */ sint16 s_max_mnt_count; /* 54: Maximal mount count */ uint16 s_magic; /* 56: Magic signature */ uint16 s_state; /* 58: File system state */ uint16 s_errors; /* 60: Behaviour when detecting errors */ uint16 s_minor_rev_level; /* 62: minor revision level */ uint32 s_lastcheck; /* 64: time of last check */ uint32 s_checkinterval; /* 68: max. time between checks */ uint32 s_creator_os; /* 72: OS */ uint32 s_rev_level; /* 76: Revision level */ uint16 s_def_resuid; /* 80: Default uid for reserved blocks */ uint16 s_def_resgid; /* 82: Default gid for reserved blocks */ /* more stuff in later versions - especially s_block_group_nr is useful */ uint32 s_first_ino; /* 84: First non-reserved inode */ uint16 s_inode_size; /* 88: size of inode structure */ uint16 s_block_group_nr; /* 90: block group # of this superblock */ uint32 s_feature_compat; /* 92: compatible feature set */ uint32 s_feature_incompat; /* 96: incompatible feature set */ uint32 s_feature_ro_compat; /* 100: readonly-compatible feature set */ uchar s_uuid[16]; /* 104: 128-bit uuid for volume */ char s_volume_name[16]; /* 120: volume name */ char s_last_mounted[64]; /* 136: directory where last mounted */ uint32 s_algorithm_usage_bitmap;/* 200: For compression */ uchar s_prealloc_blocks; /* 204: Nr of blocks to try to preallocate*/ uchar s_prealloc_dir_blocks; /* 205: Nr to preallocate for dirs */ uchar s_reserved[818]; /* 206-1023 */};/* * Heuristic to weed out false alarms for ext2 superblocks. * Recompile this after 2005, of if you destroy things that * have not been written the past ten years. */#define YEAR (60*60*24*365)#define LOWERLIMIT (1992-1970)*YEAR#define UPPERLIMIT (2005-1970)*YEARintis_time(uint32 t) { return (t >= LOWERLIMIT && t <= UPPERLIMIT);}intis_ztime(uint32 t) { return (t == 0 || (t >= LOWERLIMIT && t <= UPPERLIMIT));}/* * Recognize a FAT filesystem */struct fat_boot_sector_start { uchar jump_code[3]; /* 0: Bootstrap short or near jump */ /* usually jump code (e.g. eb 3e or eb 58) + nop (0x90) */ uchar system_id[8]; /* 3: OEM Name */ /* fat16: MSDOS5.0 or MSWIN4.0 or ... */ /* fat32: MSWIN4.1 (=W95 OSR2) */ /* BIOS Parameter Block (BPB) */ uchar sector_size[2]; /* 11: bytes/sector (usually 512 or 2048) */ uchar cluster_size; /* 13: sectors/cluster (a power of two in 1..128) */ uint16 reserved; /* 14: reserved sectors (I see 1 for FAT16, 17 for FAT32) */ /* The # of sectors preceding the first FAT, including the boot sector, so at least 1 */ uchar fats; /* 16: # of copies of FAT (usually 2) */ uchar dir_entries[2]; /* 17: max # of root directory entries (n/a for FAT32) */ /* (usually 512; 0 for FAT32) */ uchar sectors[2]; /* 19: total # of sectors (in <32MB partn) or 0 */ uchar media; /* 21: media code (0xf8 for hard disks) */ uint16 fat_length; /* 22: sectors/FAT (n/a: 0 for FAT32) */ uint16 secs_track; /* 24: S = # sectors/track (in 1..63) */ uint16 heads; /* 26: H = # of heads (in 1..255) */ uint32 hidden; /* 28: # of hidden sectors in partition, before boot sector */ /* (offset from cyl boundary - often equal to S) */ uint32 total_sect; /* 32: # of sectors (if sectors == 0) */};/* Media descriptor byte: f8 hard disk Floppy types: f0 3.5" 36/2/80 2880k f0 3.5" 18/2/80 1440k f9 3.5" 9/2/80 720k f9 5.25" 15/2/80 1200k fa both 9/1/80 320k fb both 9/2/80 640k fc 5.25" 9/1/40 180k fd 5.25" 9/2/40 360k fe 5.25" 8/1/40 160k ff 5.25" 8/2/40 320k Conclusion: this byte does not differentiate between 3.5" and 5.25", it does not give the capacity or the number of sectors per track. However, maybe C and H can be derived.*/struct fat_boot_sector_middle { /* offset 36-61 for FAT16, 64-89 for FAT32 */ /* Extended BIOS Parameter Block */ uchar drive_number; /* 0: logical drive number of partition */ /* (typically 0 for floppy, 0x80 for each disk) */ uchar current_head; /* Originally: track containing boot record. (Usually 0) For WNT: bit 0: dirty: chkdsk must be run bit 1: also run surface scan */ uchar extd_signature; /* 2: extended signature (0x29) */ /* WNT requires either 0x28 or 0x29 */ uchar serial_nr[4]; /* 3: serial number of partition */ uchar volume_name[11];/* 7: volume name of partition */ /* WNT stores the volume label as a special file in the root directory */ uchar fs_name[8]; /* 18: filesystem name (FAT12, FAT16, FAT32) */};struct fat16_boot_sector { struct fat_boot_sector_start s; /* 0-35 */ struct fat_boot_sector_middle m; /* 36-61 */ uchar boot_code[448]; /* 62-509 */ uchar signature[2]; /* 510-511: aa55 */};struct fat32_boot_sector { struct fat_boot_sector_start s; /* 0-35 */ uint32 fat32_length; /* 36: sectors/FAT */ uint16 flags; /* 40: bit 7: fat mirroring, low 4: active fat */ /* If mirroring is disabled (bit8 set) the FAT info is only written to the active FAT copy. */ uchar version[2]; /* 42: major, minor filesystem version */ uint32 root_cluster; /* 44: first cluster in root directory */ uint16 info_sector; /* 48: filesystem info sector # relative to partition start (usually 1) */ uint16 backup_boot; /* 50: backup boot sector # relat. to part. start */ uint16 reserved2[6]; /* 52-63: Unused */ struct fat_boot_sector_middle m; /* 64-89 */ uchar boot_code[420]; /* 90-509 */ uchar signature[2]; /* 510-511: aa55 */};/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -