#include #include #include #include #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; }