With truncate and mmap, it seems like this is possible without having to create a buffer file:
#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
bool file_prepend(int fd, const char *add)
{
struct stat old;
if (fstat(fd, &old) != 0)
return false;
size_t add_len = strlen(add);
// Increase the file size to make space for the string
if (ftruncate(fd, old.st_size + add_len) != 0)
return false;
char *mapped = mmap(NULL, old.st_size + add_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (!mapped)
return false;
// Now we can essentially treat the file as raw memory
memmove(mapped + add_len, mapped, old.st_size);
memcpy(mapped, add, add_len);
munmap(mapped, old.st_size + add_len);
return true;
}
int main(void)
{
int fd = open("foo.txt", O_RDWR);
assert(fd != -1);
bool ok = file_prepend(fd, "Hello ");
assert(ok);
close(fd);
}
Before I run this program foo.txt looks like:
World
And after running the program it looks like:
Hello World
By the way, I'm not an expert in mmap so my prot and flags params might be incorrect (though it works for me), feel free to correct me if I have done something wrong.