From: Jan-Benedict Glaw <jbglaw@lug-owl.de>
To: Rene Herman <rene.herman@gmail.com>
Cc: Theodore Tso <tytso@mit.edu>,
linux-fsdevel@vger.kernel.org, Al Boldi <a1426z@gawab.com>,
linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [RFH] Partition table recovery
Date: Mon, 23 Jul 2007 10:41:46 +0200 [thread overview]
Message-ID: <20070723084146.GP22998@lug-owl.de> (raw)
In-Reply-To: <46A46399.5090406@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5916 bytes --]
On Mon, 2007-07-23 10:15:21 +0200, Rene Herman <rene.herman@gmail.com> 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 jbglaw@lug-owl.de +49-172-7608481
Signature of: Träume nicht von Dein Leben: Lebe Deinen Traum!
the second :
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
next prev parent reply other threads:[~2007-07-23 8:41 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-20 5:13 [RFH] Partion table recovery Al Boldi
2007-07-20 5:20 ` Dave Young
2007-07-20 5:57 ` Dave Young
2007-07-20 11:29 ` [RFH] Partition " Al Boldi
2007-07-20 5:25 ` [RFH] Partion " James Lamanna
2007-07-20 7:00 ` Jan-Benedict Glaw
2007-07-20 11:29 ` [RFH] Partition " Al Boldi
2007-07-20 11:53 ` Anton Altaparmakov
2007-07-20 5:35 ` [RFH] Partion " Willy Tarreau
2007-07-20 5:44 ` Dave Young
2007-07-20 7:03 ` Jan Engelhardt
2007-07-20 11:29 ` [RFH] Partition " Al Boldi
2007-07-20 11:39 ` Jan-Benedict Glaw
2007-07-20 12:22 ` Al Boldi
2007-07-20 12:29 ` Rene Herman
2007-07-20 16:06 ` Theodore Tso
2007-07-21 17:54 ` Rene Herman
[not found] ` <20070722011141.GJ26752@thunk.org>
2007-07-22 4:10 ` Al Boldi
2007-07-22 16:28 ` Theodore Tso
2007-07-22 19:05 ` Al Boldi
2007-07-22 21:23 ` Indan Zupancic
2007-07-23 8:15 ` Rene Herman
2007-07-23 8:41 ` Jan-Benedict Glaw [this message]
2007-07-23 10:54 ` Rene Herman
2007-07-23 12:39 ` Rene Herman
2007-07-23 13:15 ` Jan-Benedict Glaw
2007-07-23 13:32 ` Rene Herman
2007-07-23 20:22 ` Bill Davidsen
2007-07-23 13:58 ` Theodore Tso
2007-07-24 4:08 ` Rene Herman
2007-07-22 9:11 ` Rene Herman
[not found] ` <20070722163934.GB20174@thunk.org>
[not found] ` <46A45A01.5050709@gmail.com>
2007-07-23 13:48 ` Theodore Tso
2007-07-24 3:41 ` Rene Herman
2007-07-20 6:47 ` [RFH] Partion " Jeffrey V. Merkey
2007-07-20 11:29 ` [RFH] Partition " Al Boldi
2007-07-20 7:35 ` [RFH] Partion " Anton Altaparmakov
2007-07-21 19:40 ` Willy Tarreau
2007-07-23 20:08 ` Bill Davidsen
2007-07-24 3:45 ` Rene Herman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070723084146.GP22998@lug-owl.de \
--to=jbglaw@lug-owl.de \
--cc=a1426z@gawab.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=rene.herman@gmail.com \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.