Subject: Re: Any disklabel experts out there?
To: None <port-i386@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: port-i386
Date: 05/23/2002 18:47:18
> I was moving disks and using partition magic, and I deleted my
> partition table.  And my disk label.

Ouch.

> The data, I'm pretty sure, is still there.  There's a win98 partition
> still alive, and the netbsd stuff is hidden behind it.  [...]  Anyone
> have any hints for me?

[in another message, same person]

> Can I search through the data still physically on the disk for
> something that identifies the start of a partition?

Yes, loosely speaking.

I have a program that reads through a raw disk device looking for
blocks that might be valid superblocks.  It's fairly old and it may
have bitrotted a little.  But it may be worth trying anyway.

Since it's small (under 6K, including auxiliary files), I'm just
including it here.  Feel free to write me back (preferably off-list) if
you have any problems with it.

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse@rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B

#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Thu May 23 18:46:05 2002
# Run this through sh to create:
#	findsb.c
#	acc.h
#	acc.c
echo x - findsb.c \(4818 characters\)
sed 's/^X//' > findsb.c << \EOF
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <unistd.h>
X#include <stdlib.h>
X#include <stdarg.h>
X#include <strings.h>
X#include <ufs/ffs/fs.h>
X
X#include "acc.h"
X
Xextern const char *__progname;
X
X#define NBLOCKS 128
X
Xstatic int fd;
Xstatic char sbbuf[SBSIZE] __attribute__((__aligned__(__alignof__(struct fs))));
Xstatic struct fs *sb;
Xstatic char blocks[NBLOCKS*DEV_BSIZE];
Xstatic int firstblock;
Xstatic unsigned int diskend;
Xstatic int npsb;
Xstatic int *psb;
Xstatic void **sbs;
Xstatic int sboff;
Xstatic ACC *pref;
X
Xstatic int getblock(int n, void *where)
X{
X if ((n < firstblock) || (n >= firstblock+NBLOCKS))
X  { int nr;
X    firstblock = n;
X    if (lseek(fd,DEV_BSIZE*(off_t)n,L_SET) < 0)
X     { fprintf(stderr,"%s: lseek for block %d: %s\n",__progname,n,strerror(errno));
X       exit(1);
X     }
X    nr = read(fd,&blocks[0],NBLOCKS*DEV_BSIZE);
X    if (nr < 0)
X     { if (errno == EINVAL)
X	{ nr = 0;
X	}
X       else
X	{ fprintf(stderr,"%s: read for block %d: %s\n",__progname,n,strerror(errno));
X	  exit(1);
X	}
X     }
X    if (nr % DEV_BSIZE)
X     { printf("strange block read value: %d %% %d != 0\n",nr,DEV_BSIZE);
X       exit(1);
X     }
X    nr /= DEV_BSIZE;
X    if (nr < NBLOCKS) diskend = n + nr;
X  }
X if (n >= diskend) return(1);
X bcopy(&blocks[(n-firstblock)*DEV_BSIZE],where,DEV_BSIZE);
X return(0);
X}
X
Xstatic int getsb(int off)
X{
X int i;
X
X sboff = off;
X for (i=0;i<SBSIZE/DEV_BSIZE;i++)
X  { if (getblock(off+i,&sbbuf[i*DEV_BSIZE])) return(1);
X  }
X sb = (struct fs *) &sbbuf[0];
X return(0);
X}
X
Xstatic int sanesb(void)
X{
X if (sb->fs_magic != FS_MAGIC) return(0);
X return(1);
X}
X
Xstatic void printsbhead(void)
X{
X printf("possible sb at block %d\n",sboff);
X}
X
Xstatic void setpref(const char *, ...) __attribute__((__format__(__printf__,1,2)));
Xstatic void setpref(const char *fmt, ...)
X{
X FILE *f;
X va_list ap;
X
X if (pref) acc_close(pref);
X pref = acc_open();
X f = fwopen(pref,acc_fwrite);
X va_start(ap,fmt);
X vfprintf(f,fmt,ap);
X va_end(ap);
X fclose(f);
X}
X
Xstatic void msg(const char *, ...) __attribute__((__format__(__printf__,1,2)));
Xstatic void msg(const char *fmt, ...)
X{
X va_list ap;
X
X if (pref) fwrite(acc_buf(pref),1,acc_len(pref),stdout);
X va_start(ap,fmt);
X vprintf(fmt,ap);
X va_end(ap);
X printf("\n");
X}
X
Xstatic int badsb(void)
X{
X if ((sb->fs_optim != FS_OPTTIME) && (sb->fs_optim != FS_OPTSPACE))
X  { msg("undefined optimization");
X    return(1);
X  }
X if ((sb->fs_minfree < 0) || (sb->fs_minfree > 100))
X  { msg("minimum free-space set to %d%%",sb->fs_minfree);
X    return(1);
X  }
X if ((sb->fs_bshift < 0) || (sb->fs_bshift > 31))
X  { msg("ludicrous bshift %d",sb->fs_bshift);
X    return(1);
X  }
X if ((sb->fs_fshift < 0) || (sb->fs_fshift > 31))
X  { msg("ludicrous fshift %d",sb->fs_fshift);
X    return(1);
X  }
X if (sb->fs_bmask != ((~(unsigned int)0)<<sb->fs_bshift))
X  { msg("bmask (0x%08x) doesn't match bshift (%d)",sb->fs_bmask,sb->fs_bshift);
X    return(1);
X  }
X if (sb->fs_fmask != ((~(unsigned int)0)<<sb->fs_fshift))
X  { msg("fmask (0x%08x) doesn't match fshift (%d)",sb->fs_fmask,sb->fs_fshift);
X    return(1);
X  }
X if (sb->fs_bsize & (sb->fs_bsize-1))
X  { msg("bsize (%d) not a power of two",sb->fs_bsize);
X    return(1);
X  }
X if (sb->fs_fsize & (sb->fs_fsize-1))
X  { msg("fsize (%d) not a power of two",sb->fs_fsize);
X    return(1);
X  }
X if (sb->fs_fsize != (1 << sb->fs_fshift))
X  { msg("fsize (%d) doesn't match fshift (%d)",sb->fs_fsize,sb->fs_fshift);
X    return(1);
X  }
X if (sb->fs_bsize != (1 << sb->fs_bshift))
X  { msg("bsize (%d) doesn't match bshift (%d)",sb->fs_bsize,sb->fs_bshift);
X    return(1);
X  }
X if ((sb->fs_size<<(sb->fs_fshift-9)) > diskend)
X  { msg("size (%d) too large for disk (%d)",sb->fs_size,diskend);
X    return(1);
X  }
X return(0);
X}
X
Xint main(int, char **);
Xint main(int ac, char **av)
X{
X int i;
X
X if (ac != 2)
X  { fprintf(stderr,"Usage: %s partition\n",__progname);
X    exit(1);
X  }
X fd = open(av[1],O_RDONLY,0);
X if (fd < 0)
X  { fprintf(stderr,"%s: %s: %s\n",__progname,av[1],strerror(errno));
X    exit(1);
X  }
X firstblock = - NBLOCKS;
X diskend = ~0;
X npsb = 0;
X psb = malloc(sizeof(int));
X for (i=0;;i+=(SBSIZE/DEV_BSIZE))
X  { if (getsb(i)) break;
X    if (sanesb())
X     { printsbhead();
X       fflush(stdout);
X       npsb ++;
X       psb = realloc(psb,npsb*sizeof(int));
X       psb[npsb-1] = i;
X     }
X  }
X sbs = malloc(npsb*sizeof(void *));
X sbs[0] = malloc(npsb*SBSIZE);
X for (i=1;i<npsb;i++) sbs[i] = SBSIZE + (char *)sbs[i-1];
X for (i=0;i<npsb;i++)
X  { getsb(psb[i]);
X    bcopy(&sbbuf[0],sbs[i],SBSIZE);
X  }
X for (i=0;i<npsb;i++)
X  { if (sbs[i])
X     { sb = (struct fs *) sbs[i];
X       setpref("at %d: ",psb[i]);
X       if (badsb()) sbs[i] = 0;
X     }
X  }
X for (i=0;i<npsb;i++) if (sbs[i]) printf("plausible sb at %d (fs beginning at %d)\n",psb[i],psb[i]-SBLOCK);
X /* XXX should check each sb's idea of alternative sb locations */
X exit(0);
X}
EOF
if test 4818 -ne "`wc -c < findsb.c`"
then
echo shar: error transmitting findsb.c \(should have been 4818 characters\)
fi
echo x - acc.h \(388 characters\)
sed 's/^X//' > acc.h << \EOF
X#ifndef _ACC_H_36e776f4_
X#define _ACC_H_36e776f4_
X
Xtypedef struct acc ACC;
X
Xextern ACC *acc_open(void);
Xextern void acc_write(ACC *, const void *, int);
Xextern int acc_fwrite(void *, const char *, int); /* for funopen(3) */
Xextern int acc_len(ACC *);
Xextern const void *acc_buf(ACC *);
Xextern void acc_clear(ACC *);
Xextern void acc_drop(ACC *, int);
Xextern void acc_close(ACC *);
X
X#endif
EOF
if test 388 -ne "`wc -c < acc.h`"
then
echo shar: error transmitting acc.h \(should have been 388 characters\)
fi
echo x - acc.c \(814 characters\)
sed 's/^X//' > acc.c << \EOF
X#include <stdlib.h>
X#include <strings.h>
X
X#include "acc.h"
X
Xstruct acc {
X  char *buf;
X  int len;
X  int have;
X  } ;
X
XACC *acc_open(void)
X{
X ACC *a;
X
X a = malloc(sizeof(ACC));
X a->buf = 0;
X a->len = 0;
X a->have = 0;
X return(a);
X}
X
Xvoid acc_write(ACC *a, const void *buf, int len)
X{
X if (len < 1) return;
X if (a->len+len > a->have) a->buf = realloc(a->buf,a->have=a->len+len);
X bcopy(buf,a->buf+a->len,len);
X a->len += len;
X}
X
Xint acc_fwrite(void *avp, const char *buf, int len)
X{
X acc_write(avp,buf,len);
X return(len);
X}
X
Xint acc_len(ACC *a)
X{
X return(a->len);
X}
X
Xconst void *acc_buf(ACC *a)
X{
X return(a->buf);
X}
X
Xvoid acc_clear(ACC *a)
X{
X a->len = 0;
X}
X
Xvoid acc_drop(ACC *a, int n)
X{
X if (n > a->len)
X  { a->len = 0;
X  }
X else if (n > 0)
X  { a->len -= n;
X  }
X}
X
Xvoid acc_close(ACC *a)
X{
X free(a->buf);
X free(a);
X}
EOF
if test 814 -ne "`wc -c < acc.c`"
then
echo shar: error transmitting acc.c \(should have been 814 characters\)
fi
exit 0
# end of shell archive