I mmap a file into String.
int fd = open(FILE_PATH, O_RDWR);
struct stat s;
int status = fstat(fd, &s);
char *f = (char*) mmap (0, s.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
then I cJSON parse the f
and do some modification.
cJSON *root = cJSON_Parse(f);
//some JSON operation
After finish I regenerated the string from cJSON and try to write it back to disk.
char* rendered = cJSON_Print(root);
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);
There is no error in either mmap or msync.
I checked the file content and found it changes correctly as what I modify using cJSON library.
However, the file is not completed. To be more specific, the size it wrote back to the disk (I check it using Sublime) is not the one I put in the length
parameter of msync
,i.e. strlen(rendered)
, but the original size of the file, i.e. strlen(f)
.
Then I tried to assign the length
hardcodedly by 512
128
or whatever, but I found all of them do not work. The size write back to the file from mmap is still the original size of the mmaped char.
But in the manual of msync
, it says:
The part of the file that corresponds to the memory area starting at addr and having length length is updated.
So I feel puzzled and can anyone tell me how I can assign the length of address I want to flush back to disk?
Thanks for the people inspiring me in the comments, sorry I did a poor reading of the manual.
The msync
cannot extend the size you mapped, you cannot mmap
more size than the file size neither.
So here is the idea:
There for I implemented the resize_remap
function
result_t file_remap_resize(int* fd, char** f, int new_size){
if(ftruncate(*fd, new_size) == -1){
printf("failed to resize\n");
return ERR_CODE;
}
if(munmap(*f, sizeof(*f)) == -1){
printf("failed to unmap\n");
return ERR_CODE;
}
*f = (char*)mmap (0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(!f){
printf("failed to remap\n");
return ERR_CODE;
}
return SUCCESS
}
Then the program is like:
char* rendered = cJSON_Print(root);
file_remap_resize(&fd, &f, strlen(rendered));
memcpy(f, rendered, strlen(rendered));
msync(f, strlen(renderer), MS_SYNC);
and it works!
The modified file can be flushed back into the disk!