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);
}