Code:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4096
// Error function for outputting error
void Error(char *output)
{
MessageBox(NULL, output, "Error", MB_OK);
//PostQuitMessage(1);
exit(1);
}
// Functions to obtain file information
long int GetFileSize(char *fileName)
{
long int fileSize;
FILE *fp = fopen(fileName, "rb");
fseek(fp, 0, SEEK_END);
fileSize = ftell(fp);
fclose(fp);
return fileSize;
}
int min3(size_t a, size_t b, size_t c)
{
if (a < b)
return a < c ? a : c;
else
return b < c ? b : c;
}
FILE *OpenVolumeFile(char *archiveName, int volume)
{
char volumeName[256];
FILE *fArchive;
if (volume > 0)
sprintf(volumeName, "%s-%d", archiveName, 0);
else
sprintf(volumeName, "%s", archiveName);
if (!(fArchive = fopen(volumeName, "wb"))) Error("No file handle\n");
return fArchive;
}
size_t ReadBuffer(FILE *fin, char *buffer, size_t bytesToRead)
{
size_t bytesRead;
bytesRead = fread(buffer, 1, bytesToRead, fin);
if(bytesRead < bytesToRead) Error("fread failure");
return bytesRead;
}
// Write file header
void WriteArchiveHeaderRecord(FILE* out, char fileName[][256], int fileNameLen, int fileSize)
{
// write filesize to bin
if( fwrite(&fileSize, sizeof(fileSize), 1, out) != 1) Error("Could not write filesize header\n");
// write filename length to bin
if( fwrite(&fileNameLen, sizeof(fileNameLen), 1, out) != 1) Error("Could not write filename length to header\n");
// write filename to header
if( fwrite(fileName, 1, fileNameLen, out) != fileNameLen) Error("Could not write filename to header\n");
}
size_t WriteArchiveHeader(FILE *fArchive, size_t volSize, int numFiles,
char fileNames[][256], size_t *fileSizes)
{
size_t headerSize = sizeof numFiles + sizeof volSize +
numFiles * (sizeof *fileSizes + sizeof (size_t));
int i;
if( fwrite(&numFiles, sizeof(numFiles), 1, fArchive) != 1) Error("Error writing number of files to bin\n");
if( fwrite(&volSize, sizeof(volSize), 1, fArchive) != 1) Error("Error writing volume size to bin\n");
for(i = 0; i < numFiles; i++)
{
size_t fileNameLen = strlen(fileNames[i]);
WriteArchiveHeaderRecord(fArchive, &fileNames[i], fileNameLen, fileSizes[i]);
printf("Filename: %s\tSize: %i\tFilename Length: %i\n", &fileNames[i], fileSizes[i], fileNameLen);
headerSize += fileNameLen;
}
printf("Wrote file header -> Size: %d\n\n", headerSize);
return headerSize;
}
// Write file to bin
void WriteBuffer(FILE* out, char *buffer, size_t size)
{
// write data to outfile
if( fwrite(buffer, 1, size, out) != size) Error("Error writing file to bin\n");
}
void CreateArchive(char *archiveName, size_t volSize, int numFiles, char fileNames[][256])
{
FILE *fArchive;
size_t volBytesLeft;
size_t headerSize;
size_t fileSizes[numFiles]; // I got rid of the "file" struct
int i;
int volume = 0;
for(i = 0; i < numFiles; i++)
fileSizes[i] = GetFileSize(fileNames[i]);
fArchive = OpenVolumeFile(archiveName, volSize>0 ? ++volume : 0);
headerSize = WriteArchiveHeader(fArchive, volSize, numFiles, fileNames, fileSizes);
if (volSize > 0)
volBytesLeft = volSize - headerSize;
else
volBytesLeft = BUFFER_SIZE + 1; // ensure that it's greater than buffer size
volume = 0;
for(i = 0; i < numFiles; i++)
{
size_t fileBytesLeft = fileSizes[i];
FILE *fData = fopen(fileNames[i], "rb");
if(fData == NULL) Error("Error opening file\n");
printf("File %i: %.2f MB\n", i + 1, (double)fileSizes[i] / 1024 / 1024);
do
{
char buffer[BUFFER_SIZE];
size_t bytesToRead, bytesRead;
if(volBytesLeft == 0)
{
fclose(fArchive);
volume++;
fArchive = OpenVolumeFile(archiveName, volume);
volBytesLeft = volSize;
}
bytesToRead = min3(sizeof buffer, fileBytesLeft, volBytesLeft);
bytesRead = ReadBuffer(fData, buffer, bytesToRead);
WriteBuffer(fArchive, buffer, bytesRead);
fileBytesLeft -= bytesRead;
volBytesLeft -= bytesRead;
}
while(fileBytesLeft > 0);
fclose(fData);
printf("Wrote file %i: %s\n\n", i + 1, &fileNames[i]);
}
fclose(fArchive);
printf("Success!");
}
int main()
{
char fileNames[][256] = {"Test1.zip", "Test2.rar"};
int volSize = 5;
int numFiles = 2;
//CreateArchive(char *archiveName, size_t volSize, int numFiles, char *fileNames);
CreateArchive("ArchiveName.bin", (size_t)volSize*1024*1024, numFiles, fileNames);
return 0;
}