I recently realized that my C skills got a bit rusty and decided to play a bit. I just ended up with a weird behavior though - the file-mapped memory I requested doesn't seem to flush the variable ifs.free_space
. The result is that if you don't comment out the two //root
lines, the program always starts with ifs.free_space
equal to zero. However, commenting it out leads to the counter being saved. What's happening here?
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#define FILE_LENGTH 0x10000
void* offset_to_pointer(uint64_t offset, void* file_memory) {
return (void *)((uint64_t)file_memory + offset);
}
uint64_t pointer_to_offset(void* pointer, void* file_memory) {
return ((uint64_t)pointer - (uint64_t)file_memory);
}
void* allocate(uint64_t size, uint64_t* free_space, void* file_memory) {
void* ret = offset_to_pointer(*free_space, file_memory);
*free_space += size;
return ret;
}
typedef struct dirent {
uint64_t prev_offset;
uint64_t next_offset;
uint64_t size;
} dirent;
typedef struct idiotfs {
void* file_memory;
uint64_t* free_space;
dirent* root;
} idiotfs;
int main (int argc, char* const argv[])
{
int fd = open("file.bin", O_RDWR | O_DSYNC, S_IRUSR | S_IWUSR);
if (fd == -1)
return 2;
idiotfs ifs;
ifs.file_memory = mmap(0, FILE_LENGTH,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
ifs.free_space = (uint64_t *)offset_to_pointer(0, ifs.file_memory);
dirent* root = (dirent *)allocate(sizeof(struct dirent) + strlen("hi") + 1,
ifs.free_space, ifs.file_memory);
//root = (dirent *)allocate(sizeof(struct dirent) + strlen("hi") + 1,
// ifs.free_space, ifs.file_memory);
root->prev_offset = 0;
root->next_offset = 0;
root->size = 3;
char* text = (char *)((uint64_t)root + sizeof(dirent));
strcpy(text, "hi");
close(fd);
}
The location of the ifs
struct overlaps the location of the first root
struct. This is because you started free_space
at 0, so the first root
struct will be allocated at offset 0 exactly where the ifs
struct is at.
Before you allocate the first root
struct, you should set free_space
to sizeof(ifs)
.