To learn some low level C magic, I tried to implement different methods to copy the content of one file to another.
The following method uses a buffer, where I save chunks of data, e.g. 512 bytes. Then I write FROM this buffer into my destination file. Allegedly this is more efficient than copying the whole file directly.
When I use a small buffer, e.g. 512 Bytes, this works fine. If I use a big buffer, e.g. 10000000 Bytes, roughly 10MB, I get a segmentation fault.
I am running on Ubuntu.
I tried stuff with malloc
, but nothing really seams to work for me. I guess the fix will be easy, once I know it.
According to my debbuger the error is in this line:
if (stat(to, &statBuffer) == -1)
I left in a lot of the error checking I am doing. Here is the code I run:
void copyUsingBuffer(char from[], char to[], long unsigned int bufferSize)
{
struct stat statBuffer;
int sourceFD, destFD;
char buffer[bufferSize / sizeof(char)];
int EndOfFileErreicht = 0;
// Dateien pruefen
if (stat(to, &statBuffer) == -1)
{
if (errno != ENOENT)
{
perror("Fehler beim Pruefen der Zieldatei");
exit(EXIT_FAILURE);
}
}
else
{
if (!(S_ISREG(statBuffer.st_mode)))
{
printf("Die Zieldatei ist keine regulaere Datei\n");
exit(EXIT_FAILURE);
}
}
// Dateien oeffnen
sourceFD = open(from, O_RDONLY);
if (sourceFD == -1)
{
perror("Fehler beim Oeffnen der Quelldatei");
exit(EXIT_FAILURE);
}
if (fstat(sourceFD, &statBuffer) == -1)
{
perror("Fehler beim Pruefen der Quelldatei");
exit(EXIT_FAILURE);
}
if (!(S_ISREG(statBuffer.st_mode)))
{
printf("Die Quelldatei ist keine regulaere Datei\n");
exit(EXIT_FAILURE);
}
destFD = open(to, O_WRONLY | O_CREAT | O_TRUNC, statBuffer.st_mode);
if (destFD == -1)
{
perror("Fehler beim Oeffnen der Zieldatei");
exit(EXIT_FAILURE);
}
while (EndOfFileErreicht == 0)
{
int geleseneBytes = read(sourceFD, buffer, sizeof(buffer));
if (geleseneBytes == -1)
{
perror("Fehler beim Lesen aus der Quelldatei");
exit(EXIT_FAILURE);
}
if (geleseneBytes < bufferSize)
{
// EOF wurde erreicht, also Flag setzen
EndOfFileErreicht = 1;
}
if (write(destFD, buffer, geleseneBytes) == -1)
{
perror("Fehler beim Schreiben in die Zieldatei");
exit(EXIT_FAILURE);
}
}
close(sourceFD);
close(destFD);
}
I would expect that if I enter a 500MB text file, that my program copies this file to its destination.
I realise that there are different ways to implement file copying. I already implemented some of those. In this case I am restricted to using write, read, and the buffer. Also bufferSize NEEDS to be a variable. The naive way i have using malloc would be:
char* buffer = malloc(bufferSize);
But when i use this the file will be corrupted.