SUMMARY: Restoring partition table, finding superblocks

From: Daniel Kluge (danielk@tibco.com)
Date: Thu Aug 14 1997 - 09:20:21 CDT


Thanx to those who responded, I had my tool ready the same evening, I just
needed a proper Development-Environment (NeXTSTEP 3.3)

Here the whole story

On Tue, 12 Aug 1997, Daniel Kluge wrote:
> This is the usual fuckup, sun-install worked on the wrong HD, it was a 2GB
> Disk with just two data partitions, the disk has now the usual /, /usr,
> /var partition-table, but most of the old data will still be intact.
>
> So, how to get the lost partition table?

David Mitchell <davem@fdgroup.co.uk> wrote:
>There is no direct way of recovering the old partition table, but there
>are some indirect ways >>> as long as suninstall only updated the
>partition table, and did not newfs each partition too<<<. If a newfs has
>been done, then your disk is more or less unrecoverable.

This is the easiest way, just find the superblocks which have a
mountpoint, those are the originals, and they are always on block 16, so
you know the position in the filesystem.

If your original-superblocks have been written over, but you are shure
that you have backups (since the partitioning is different), you can use
'super'.

super gives you almost all size-information of every superblock it finds,
some of it is drive-depended other can be caluclated (by mkfs), but some
redundancy is not bad in this business.

So here is the cookbook for recovering partition-tables:

1. Make a backup of the whole harddisk (dd if=<slice2> of=/dev/nrst)
2. run super on slice 2
        # ./super /dev/rdsk/c0t1d0s2 >disk.log
3. guess your Parameter out of the superblocks, using size, date,
mount-points. Usefull doing is :
        # sed -e 's/^Block [0-9]*: //' disk.log |sort|uniq -c
Easiest is probabely, to go for 'cpfs' value, which gives the number of
cylinders in a filesystem, this value can be put directly into the
partition table using 'format'.
5. Note the blocknumbers of some superblock
6. Change the partition table
7. Print the partition table
8. Recalculate the location of your backup-superblock in the slices
9. Check if it is a superblock with 'newfs -N' and './super
/dev/rdsk/c0t1d0s[0-7] <blocknr>.
10. Take a deep breath
11. fsck -y -o b=<blocknr> /dev/rdsk/c0t1d0s[0-7]
12. fsck again without alternative super-block until the fs is stable
13. Mount & backup the thing
14. clean up ze mess (integrity check on all files if possible)

It worked for me, the second data partition had even an intact superblock
nr. 16, and I had no obvious data-loss (probabely just some corrupted
data), we'll find out.

Thanx to
        Jim Harmon <jharmon@telecnnct.com>
        David Mitchell <davem@fdgroup.co.uk>
for Input, and Marcel Waldvogel <mwa@tik.ee.ethz.ch> for the original
suggestions.

-daniel

-- 
Daniel Kluge / CTS-Engineer                            Tel: +41-1-212-7181
TIBCO                                                  Fax: +41-1-212-7182
Bahnhofstrasse 52          
CH-8001 Zurich                                         danielk@tibco.com
Switzerland                                            http://www.tibco.com

/* super.c - Version 0.2 */
/* Program to find all super-blocks in raw-files *YEACH* */
/* Written by Daniel G. Kluge <daniel@hallus.swill.org> */
/* May be distributed onder the GNU Public Licencse Version 2 or later */

     #include <sys/types.h>
     #include <sys/uio.h>
     #include <unistd.h>
     #include <stdio.h>
     #include <sys/file.h>

     #include <sys/param.h>

     #ifdef sparc
     #include <sys/fs/ufs_fs.h>
     #include <sys/fs/ufs_inode.h>
     #endif
     
     #ifdef NeXT
     #include <sys/fcntl.h>
     #include <sys/vnode.h>
     #include <ufs/fs.h>
     #include <ufs/inode.h>
     #endif

     #include <time.h>
     
     #define BUF_SIZE 8192

int readsblock (int fd, int block)
{
   int s_read, month;
   char buf[BUF_SIZE];

   struct fs *ufs;
   struct tm *tm_ptr;
   
      bzero(&buf, BUF_SIZE);
      lseek(fd, block*512, L_SET);
      s_read=read(fd,&buf,BUF_SIZE);
      if (s_read != BUF_SIZE) {
         fprintf(stderr, "Only read %i bytes\n",s_read);
         if (s_read < sizeof(struct fs)) return 0;
         }

      ufs=(void *)&buf;
      
      if (ufs->fs_magic == FS_MAGIC) {
         printf ("Block %i: ", block);
         tm_ptr =localtime (&(ufs->fs_time));
         month=tm_ptr->tm_mon;month++;
         printf("%i/%i/%i %02i:%02i:%02i", tm_ptr->tm_mday, month, tm_ptr->tm_year,
                                           tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);
        printf(" mnt [%s],",ufs->fs_fsmnt);
        printf(" %li tpc, %li spt, %li spc, %li cpfs,",ufs->fs_ntrak, ufs->fs_nsect, ufs->fs_spc, ufs->fs_ncyl);
        printf(" %li bsize, %li fsize,", ufs->fs_bsize, ufs->fs_fsize);
        printf(" %li blck, %li dblck, %li cgrp,", ufs->fs_size, ufs->fs_dsize, ufs->fs_ncg);
        printf(" %li cpg, %li fpg, %li ipg,", ufs->fs_cpg, ufs->fs_fpg, ufs->fs_ipg);
        printf("\n");
        }
       else {
          return -1;
            }

        return (s_read);
}

int eof_found(fd)
{
   fprintf(stderr, "End of file encountered, closing\n");
   close(fd);
   exit(0);
   return 0; /* Never reached */
}


main (int argc, char *argv[])
{
   int i, fd, blocks, retval;
   int s_read;
   char *path;

   if (BUF_SIZE < sizeof(struct fs)) {
        fprintf(stderr, "BUF_SIZE is smaller than a superblock, please recompile\n");
        exit(1);
        }

   path=argv[1];

   fd=open(path, O_RDONLY, 0);

   if (fd <1) {
      fprintf(stderr, "Cannot open %s\n", path);
      exit(1);
     }

   blocks=0;

   if (argc > 2) {
      for(i=2;i<argc;i++) {
         blocks=atoi(argv[i]);
         retval=readsblock(fd, blocks);
         switch (retval)
            {
            case 0: eof_found(fd);
                     break;
            case -1: printf("Block %i: MAGIC_MISSMATCH\n", blocks);
                     break;
            default: break;
            }
          }
        }
   else {
      while (1) {
         retval=readsblock(fd, blocks);
         if (!retval) eof_found(fd);
         blocks++;
         }
       }
}

  



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:12:00 CDT