This is really a quick hack to read AmiBack backups - I don't know if it works with floppy based backups - but probably the source below is most useful for understanding the format.
I used it succesfully to restore all of my backups that were stored on QIC Tape (45/150mb).
/*---------------------------------------------------------------------------
*
* Title: AmiBack extraction utility
*
* File: amiread.cpp
*
* Date: May 2005
*
* Description:
* Reads/extracts files from a dumped amibackup format archive.
*
* Rev By Description Date
* 1.0 R.J.Harrison Implement 05-05-2005
*
* Copyright © 2005 R.J.Harrison
*---------------------------------------------------------------------------*/
#pragma warning(disable : 4786)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <io.h>
#include <fcntl.h>
#include <vector>
#include <string>
#pragma pack(1)
typedef struct {
char header[4]; // FHDR
char name[108];// fname
long aa; //???
long filesize;
long ee;
long ff;
long gg;
long hh;
char depth;
char type;
// content follows. (unless filesize 0);
}AmiHeader;
void check_path(const char *path)
{
FILE *q;
static char *ptr,*name, *end, tmp [200];
strcpy (tmp,path);
end = ptr = tmp+strlen(tmp);
while (*--ptr && *ptr != '/');
if(*ptr)
{
*++ptr = 0; /* Remove file name */
name = ptr = tmp;
do
{
while (*ptr && *ptr != '/') ptr++;
if(*ptr)
{
*ptr = 0;
if(!(q=fopen(name,"r")))
{
mkdir (name);
}
else
{
fclose (q);
}
*ptr++ = '/';
}
}while (*ptr && ptr < end);
}
}
main()
{
FILE *f = fopen("N:/Users/Richard/tape/Tapes/amiga_wb_work.amiback","rb");
std::vector<std::string> dirz(100);
#define BUFFER_SIZE 1000 /* k */
int buffer_size = BUFFER_SIZE;
buffer_size *= 1024;
void *file_buffer = malloc(buffer_size + 10);
if (!f)
{
fprintf (stderr, "Not found\n");
exit(-1);
}
char hdr[512];
#define SWAP_LONG(v) (((v & 0xff000000) >> 24) | ((v & 0xff0000) >> 8) | ((v & 0xff00) << 8) | ((v & 0xff) << 24))
fread(hdr,1,sizeof(hdr),f);
printf ("%d\n",sizeof(AmiHeader));
int fc=0;
std::string fname;
chdir("C:/temp/amiga/");
while(!feof(f))
{
AmiHeader fhdr;
fread (&fhdr, 1, sizeof(fhdr),f);
fhdr.filesize = SWAP_LONG(fhdr.filesize);
if (fc == 9175)
printf("%x\n", ftell(f));
//? Colon in name is new device...
if (strncmp(fhdr.header, "FHDR", 4))
printf ("???Header???");
printf ("%5d: %10d - ",fc++,fhdr.filesize);
fname = std::string();
switch (fhdr.type)
{
case 0x2:
{
char *s = strchr(fhdr.name, ':');
if (s)
*s = 0; // zoink colon from devname
dirz[0] = fhdr.name;
}
break;
case 0x0:
dirz[fhdr.depth] = fhdr.name;
break;
default:
for (size_t i = 0; i < fhdr.depth; i++)
{
// printf ("%s/",dirz[i].c_str());
fname = fname + dirz[i] + "/";
}
break;
}
fname = fname + fhdr.name;
printf ("%s\n",fname.c_str());
if (fhdr.filesize)
{
bool list = false;
int size = fhdr.filesize;
int of;
if(!list)
{
check_path(fname.c_str());
of = open(fname.c_str(), O_BINARY | O_CREAT | O_WRONLY | O_TRUNC, 0x666);// need mode..hdr.mode);
if(!of) fprintf(stderr,"unable to open %s\n", fname.c_str());
}
while(size >= buffer_size)
{
fread(file_buffer, 1, buffer_size, f);
if(!list)
write(of, file_buffer, buffer_size);
size -= buffer_size;
}
if(size > 0)
{
fread(file_buffer, 1, size, f);
if(!list )
write(of, file_buffer, size);
}
if (!list )
close(of);
// if (fseek(f, fhdr.filesize, SEEK_CUR))
// {
// fprintf (stderr,"Seek failed\n");
// exit(-1);
// }
}
else
{
printf ("Directory\n");
if (fhdr.type)
printf ("Type %d\n", fhdr.type);
}
//ii[0] - 0x2 = device;
//ii[0] - 0x0 = dir;
//ii[0] - 0x1 = file?
}
}