#include "merger.h"
#define TestBit(A,k) ( A[(k/32)] & (1 << (k%32)) )
int fhImage;
int fhCow;
off_t *filePointers;
uint64_t imageBlockCount;
uint64_t size;
bool merger(char *imageFilePath, char *cowFilePath){
if(!loadFiles(imageFilePath, cowFilePath)){
return false;
}
if (merge()){
printf("File Merged");
return true;
}
return false;
}
bool loadFiles(char *imageFilePath, char *cowFilePath){
if((fhImage = open (imageFilePath, O_RDWR))==-1){
printf( "Could not open Image.\n" );
return false;
}
if((fhCow = open (cowFilePath, O_RDONLY))==-1){
printf( "Could not open Cow File.\n" );
close(fhImage);
return false;
}
unsigned int version ;
read(fhCow,&version,sizeof(unsigned int));
read(fhCow,&size,sizeof(uint64_t));
int l;
read(fhCow,&l,sizeof(int));
char *buffer = malloc(sizeof(char)*(l+1));
read(fhCow,buffer,l*sizeof(char));
buffer[l]='\0';
int pageSize;
read(fhCow,&pageSize,sizeof(int));
printf("Version: %u\n",version);
printf("länge: %i \n",l);
printf("Image Name: %s\n",buffer);
printf("Size: %ld\n", (long)size);
printf("pageSize: %i\n", (pageSize));
free(buffer);
//TODO Image Validation
imageBlockCount = ( size + (4096*256)-1 ) / (4096*256);
off_t mmapStart = lseek(fhCow, 0L, SEEK_CUR);
int maxPageSize = 8192;
mmapStart= ((mmapStart+maxPageSize-1)/maxPageSize)*maxPageSize;
filePointers = mmap(NULL,imageBlockCount*sizeof(off_t), PROT_READ, MAP_SHARED,fhCow, mmapStart);
if(filePointers == MAP_FAILED ){
printf("Error creating mmap in COW File.\n%s\nBye.\n ", strerror(errno));
close(fhCow);
close(fhImage);
return false;
}
return true;
}
bool merge(){
uint64_t mergedBlocks = 0;
for(uint64_t i = 0; i < imageBlockCount;i++){
printf("Merged %llu of %llu Blocks \n",i,imageBlockCount);
off_t pointer =(off_t)filePointers[i];
if(pointer !=0){
int blockState[8];
lseek(fhCow,filePointers[i],SEEK_SET);
read(fhCow,&blockState,sizeof(int)*8);
for(int j = 0; j < 256;j++){
if(TestBit(blockState,j)){
lseek(fhCow,filePointers[i]+(4096*(j+1)),SEEK_SET);
char buff[4096] = {0};
if(read(fhCow, &buff, 4096) < 0){
printf("Error on reading Cow File. BigBlock: %llu\n",i);
return false;
}
lseek(fhImage,(i*4096*256)+(4096*j),SEEK_SET);
if(write(fhImage, &buff, 4096) < 0){
printf("Error on writing to File. BigBlock: %llu\n",i);
return false;
}
}
}
mergedBlocks++;
}
}
printf("Merged %llu Blocks\n",mergedBlocks);
ftruncate(fhImage, size);
return true;
}