I just completed a lot of recovery from losing all the bin/* part of
psql version 6.4.2, and had to install 6.5.3.  The disk file format
changed, so, I had to translate the disk files into sql commands.`

Most of the tables I had were text, char, etc.  So, I used the
standatd unix tools, like string, sed, awk, sort, uniq, etc. to
recover the data.

I did have to write some code.  It is below.  Build it with 
  cc -o xxxx xxxx.c -lm

This code is for a specific file.  I only had a few data files to deal
with, so, I did not create a general tool.  sorry about the lack of comments, etc.

To adapt this to a given data file, look through the file with 
   'hd aaaaa | more'

Note: A date is an offset from 1/1/2000.

tomdean


/*
 * read_db_file.c - read a psql 6.4.2 disk file and output all the data.
 *
 * books
 */
#include <stdio.h>
#include <math.h>
#include <time.h>

#define BUF_SIZE 100*1024
#define IN_FILE "../tomdean/books"

void usage(char *name) {
  printf("usage: %s\n", name);
  return;
}

/*
 | JulToCal.c - convert the julian data to calendar date.
 | arguments:
 |  jd  - julian date
 |  yr  - int return the year
 |  mo  - int return the month
 |  da  - int return the day
 |  tm  - double return the time
 */
void JulToCalDate(double jd, struct tm *time) {
  double a, b, c, d, e, f, g, i, tm, d_tmp;
  
  f = modf(jd+0.5,&i);
  if (i > 2299160.0) {
    a = floor((i - 1867216.25)/36524.25);
    b = floor(i + 1.0 + a - floor(a/4.0));
  }
  else {
    a = i;
    b = 0;
  }
  
  c = b + 1524.0;
  d = floor((c-122.1)/365.25);
  e = floor(365.25*d);
  g = floor((c-e)/30.6001);
  
  tm = 24.0*modf(c - e + f - floor(30.6001*g), &b); /* b is day */
  tm = modf(tm, &d_tmp);
  time->tm_hour = (int)d_tmp;
  tm *= 60.0;
  tm = modf(tm, &d_tmp);
  time->tm_min = (int)d_tmp;
  time->tm_sec = (int)floor(tm*60.0);
  
  time->tm_mday = (int)b;

  if (g < 13.5) {
    time->tm_mon = (int)(g - 1);
  }
  else {
    time->tm_mon = (int)(g - 13);
  }
  
  if (time->tm_mon > 2) {
    time->tm_year = (int) (d - 4716);
  }
  else {
    time->tm_year = (int) (d - 4715);
  }

}

void copy_lstring(char *dst, char *src, int len) {
  char *p = dst, *q = src;
  int idx;
  
  for (idx=0; idx<len; idx++) *p++ = *q++;
  
  *p = '\0';
  
  return;
}

int main(int argc, char **argv) {
  FILE *fp;
  int bytes_read;
  char buffer[BUF_SIZE];  /* work buffer */
  char *p;
  int len;
  char author[100], isbn[100], title[100], series[100], publisher[100];
  int date;
  double *temp, jd;
  struct tm when;

  if (argc != 1) {
        usage(argv[0]);
        return -1;
  }

  if ((fp = fopen(IN_FILE, "r")) == NULL) {
        perror(IN_FILE);
        return -2;
  }

  bytes_read = fread(buffer, 1, BUF_SIZE, fp);
  printf("Read %d bytes from %s\n",bytes_read, IN_FILE);

  buffer[bytes_read] = '\0';

  p = &buffer[0x630];

  while (*p != '\0') {
        temp = (double *)p;
        /* author */
        len=*(int *)p;
        copy_lstring(author, p+4, len-4);
        printf("INSERT INTO books values( \'%s\',", author);
        p += 4*((len+3)/4);
        /* isbn */
        len=*(int *)p ;
        copy_lstring(isbn, p+4, len-4);
        printf("\'%s\',", isbn);
        p += 4*((len+3)/4);
        /* title */
        len=*(int *)p ;
        copy_lstring(title, p+4, len-4);
        printf("\'%s\',", title);
        p += 4*((len+3)/4);
        /* date */
        date = *(int *)p;
        jd = 2451545.0 + (double)date;
        JulToCalDate(jd, &when);
        /*  int tm_mday;    day of month (1 - 31)  */
        /*  int tm_mon;     month of year (0 - 11) */
        /*  int tm_year;    year - 1900            */
        printf("\'%02d/%02d/%04d\',",
                   when.tm_mon+1, when.tm_mday, when.tm_year);
        p += 4;  /* already mod 4 */
        /* series */
        len=*(int *)p ;
        copy_lstring(series, p+4, len-4);
        printf("\'%s\',", series);
        p += 4*((len+3)/4);
        /* publisher */
        len=*(int *)p ;
        copy_lstring(publisher, p+4, len-4);
        printf("\'%s\' );\n", publisher);
        p += len;
        /* round to lword and skip some db ints */
        while ((int)temp < (int)p) temp++;
        p = (char *)((int)temp + 40);

  }

  fclose(fp);
}
  

Reply via email to