gates_of_skeldal/insteng/SETUPCPY.C
2025-01-24 18:27:22 +01:00

165 lines
2.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <memman.h>
#include <string.h>
#include "setupcpy.h"
#define DATASIZE 32768
#define INFOBLOCK 1
#define DATABLOCK 2
#define ERRORBLOCK 3
typedef struct tdatablock
{
void *next;
char block_type;
unsigned short load_size;
char data[DATASIZE];
}TDATABLOCK;
typedef struct tinfoblock
{
void *next;
char block_type;
char pathname[2];
}TINFOBLOCK;
static void *start=NULL;
static void *end=NULL;
static FILE *cpyout=NULL;
static long progress=0;
void (*cpy_error)(int,char *);
void (*mem_error_next)(long);
void (*cpy_progress)(long);
static void *alloc_file(char *target_name)
{
TINFOBLOCK *p;
p=(TINFOBLOCK *)getmem(sizeof(TINFOBLOCK)+strlen(target_name));
strcpy(p->pathname,target_name);
p->next=NULL;
p->block_type=INFOBLOCK;
return p;
}
static void *alloc_data()
{
TDATABLOCK *p;
p=New(TDATABLOCK);
p->next=NULL;
p->load_size=0;
p->block_type=DATABLOCK;
return p;
}
static void *load_data(FILE *f)
{
TDATABLOCK *p;
int rc;
int retry=0;
void *end_line;
p=end_line=alloc_data();
again:
errno=0;
rc=fread(p->data,1,sizeof(p->data),f);
p->load_size=rc;
if (ferror(f) || rc!=sizeof(p->data) && errno!=0)
{
if (retry) retry--;
else cpy_error(CPERR_READ,NULL);
fseek(f,-rc,SEEK_CUR);
errno=0;
goto again;
}
progress+=p->load_size;
cpy_progress(progress);
return end_line;
}
static error_mem(long size)
{
TDATABLOCK *p;
TINFOBLOCK *q;
int rc;
size;
if (start==NULL) mem_error_next(size);
while (start!=NULL)
{
p=start;
q=start;
if (q->block_type==INFOBLOCK)
{
if (cpyout!=NULL) fclose(cpyout);
again:
cpyout=fopen(q->pathname,"wb");
if (cpyout==NULL)
{
cpy_error(CPERR_OPEN,q->pathname);
goto again;
}
start=q->next;
free(q);
}
else if (p->block_type==DATABLOCK)
{
again2:
rc=fwrite(p->data,1,p->load_size,cpyout);
if (rc!=p->load_size)
{
cpy_error(CPERR_WRITE,q->pathname);
fseek(cpyout,-rc,SEEK_CUR);
goto again2;
}
progress+=p->load_size;
cpy_progress(progress);
start=p->next;
free(p);
}
}
end=NULL;
}
void cpy_file(char *source,char *target)
{
FILE *f;
TDATABLOCK *p;
TINFOBLOCK *q;
again:
errno=0;
f=fopen(source,"rb");
if (f==NULL)
{
cpy_error(CPERR_OPEN,source);
goto again;
}
q=alloc_file(target);
if (start==NULL) start=end=q;else end=(((TDATABLOCK *)end)->next=q);
while (!feof(f))
{
p=load_data(f);
if (start==NULL) start=end=p;else end=(((TDATABLOCK *)end)->next=p);
}
fclose(f);
}
void cpy_flush()
{
if (start!=NULL)error_mem(0);
if (cpyout!=NULL)fclose(cpyout);
cpyout=NULL;
}
void install_cpy()
{
mem_error_next=mem_error;
mem_error=error_mem;
}