On Mon, 2007-07-23 10:15:21 +0200, Rene Herman <[email protected]> wrote: > /* > * Public Domain 2007, Rene Herman > */ > > #define _LARGEFILE64_SOURCE > > #include <stdlib.h> > #include <stdio.h> > #include <stdint.h> > #include <string.h> > > #include <sys/types.h> > #include <sys/stat.h> > #include <sys/ioctl.h> > #include <unistd.h> > #include <fcntl.h> > > enum { > DOS_EXTENDED = 0x05, > WIN98_EXTENDED = 0x0f, > LINUX_EXTENDED = 0x85, > }; > > struct partition { > uint8_t boot_ind; > uint8_t head; Different indention. > uint8_t sector; > uint8_t cyl; > uint8_t sys_ind; > uint8_t end_head; > uint8_t end_sector; > uint8_t end_cyl; > uint32_t start; > uint32_t size; As multibyte on-disk variables, these will need LE/BE conversion. > } __attribute__((packed)); > > struct entry { > uint8_t flags; > uint8_t type; > uint16_t __1; > uint64_t start; > uint32_t size; Dito. > } __attribute__((packed)); > > enum { > ENTRY_FLAG_PRIMARY = 0x01, > ENTRY_FLAG_BOOTABLE = 0x80, > }; > > struct backup { > uint8_t signature[8]; > uint16_t type; > uint8_t heads; > uint8_t sectors; > uint8_t count; > uint8_t __1[3]; > struct entry table[31]; > } __attribute__((packed)); > > #define BACKUP_SIGNATURE "PARTBAK1" > > enum { > BACKUP_TYPE_MBR = 1, > }; > > struct backup backup = { > .signature = BACKUP_SIGNATURE, > .type = BACKUP_TYPE_MBR, > }; > > #define ARRAY_SIZE(arr) (sizeof arr / sizeof arr[0]) > > int is_extended(struct partition *partition) > { > int ret = 0; > > switch (partition->sys_ind) { > case DOS_EXTENDED: > case WIN98_EXTENDED: > case LINUX_EXTENDED: > ret = 1; > } > return ret; > } > > unsigned char *get_sector(int fd, uint64_t n) > { > unsigned char *sector; > > if (lseek64(fd, n << 9, SEEK_SET) < 0) { > perror("lseek64"); > return NULL; > } > sector = malloc(512); > if (!sector) { > fprintf(stderr, "malloc: out of memory\n"); > return NULL; > } > if (read(fd, sector, 512) != 512) { > perror("read"); > free(sector); > return NULL; > } > return sector; > } > > void put_sector(unsigned char *sector) > { > free(sector); > } > > #define TABLE_OFFSET (512 - 2 - 4 * sizeof(struct partition)) > > inline struct partition *table(unsigned char *sector) > { > return (struct partition *)(sector + TABLE_OFFSET); > } > > int do_sector(int fd, uint32_t offset, uint32_t start) > { > unsigned char *sector; > struct partition *cur; > struct partition *ext = NULL; > int ret = 0; > > sector = get_sector(fd, offset + start); > if (!sector) > return -1; > > if (sector[510] != 0x55 || sector[511] != 0xaa) { > ret = -1; > goto out; > } > for (cur = table(sector); cur < table(sector) + 4; cur++) { > struct entry *entry; > > if (!cur->size) > continue; > > cur->end_head += 1; > if (backup.heads < cur->end_head) > backup.heads = cur->end_head; > > cur->end_sector &= 0x3f; > if (backup.sectors < cur->end_sector) > backup.sectors = cur->end_sector; > > if (is_extended(cur)) { > if (!offset) { > ret = do_sector(fd, cur->start, 0); > if (ret < 0) > goto out; > } else if (!ext) > ext = cur; > continue; > } > if (backup.count == ARRAY_SIZE(backup.table)) { > fprintf(stderr, "do_sector: out of space!\n"); > ret = -1; > goto out; > } > entry = backup.table + backup.count++; > > entry->flags = cur->boot_ind; > if (!offset) > entry->flags |= ENTRY_FLAG_PRIMARY; > > entry->type = cur->sys_ind; > entry->start = cur->start + start; > entry->size = cur->size; LE/BE issues here... > } > if (ext) > ret = do_sector(fd, offset, ext->start); > out: > put_sector(sector); > return ret; > } > > void show_backup(void) > { > #ifdef DEBUG > > int i; > > fprintf(stderr, "signature: "); > for (i = 0; i < 8; i++) > fprintf(stderr, "%c", backup.signature[i]); > fprintf(stderr, "\n"); > > fprintf(stderr, " type: %d\n", backup.type); > fprintf(stderr, " heads: %d\n", backup.heads); > fprintf(stderr, " sectors: %d\n", backup.sectors); > fprintf(stderr, " count: %d\n", backup.count); > > for (i = 0; i < backup.count; i++) { > fprintf(stderr, "\n"); > fprintf(stderr, "%2d: flags: %02x\n", i, backup.table[i].flags); > fprintf(stderr, "%2d: type: %02x\n", i, backup.table[i].type); > fprintf(stderr, "%2d: start: %llu\n", i, backup.table[i].start); > fprintf(stderr, "%2d: size: %u\n", i, backup.table[i].size); You'll output wrong values here, depending on your host system. > } > #endif > } > > int main(int argc, char *argv[]) > { > int fd; > struct stat buf; > > if (argc != 2) { > printf("%s <blkdev>\n", argv[0]); > return EXIT_FAILURE; > } > fd = open(argv[1], O_RDONLY); > if (fd < 0) { > perror("open"); > return EXIT_FAILURE; > } > if (fstat(fd, &buf) < 0) { > perror("stat"); > return EXIT_FAILURE; > } > if (!S_ISBLK(buf.st_mode)) > fprintf(stderr, "warning: not a block device\n"); > > if (do_sector(fd, 0, 0) < 0) > return EXIT_FAILURE; > > if (close(fd) < 0) { > perror("close"); > return EXIT_FAILURE; > } > if (write(STDOUT_FILENO, &backup, sizeof backup) != sizeof backup) { > perror("write"); > return EXIT_FAILURE; > } > > show_backup(); > > return EXIT_SUCCESS; > } Looks like a useful program, but you'd definively fix the LE/BE issues. If you do that, it'll be able to even run on BE machines, too. MfG, JBG -- Jan-Benedict Glaw [email protected] +49-172-7608481 Signature of: Träume nicht von Dein Leben: Lebe Deinen Traum! the second :
Attachment:
signature.asc
Description: Digital signature
- Follow-Ups:
- Re: [RFH] Partition table recovery
- From: Rene Herman <[email protected]>
- Re: [RFH] Partition table recovery
- References:
- [RFH] Partion table recovery
- From: Al Boldi <[email protected]>
- Re: [RFH] Partition table recovery
- From: Rene Herman <[email protected]>
- Re: [RFH] Partition table recovery
- From: Al Boldi <[email protected]>
- Re: [RFH] Partition table recovery
- From: Theodore Tso <[email protected]>
- Re: [RFH] Partition table recovery
- From: Rene Herman <[email protected]>
- [RFH] Partion table recovery
- Prev by Date: Re: 2.6.22-git17 boot failure
- Next by Date: Re: 2.6.20->2.6.21 - networking dies after random time
- Previous by thread: Re: [RFH] Partition table recovery
- Next by thread: Re: [RFH] Partition table recovery
- Index(es):