Skip to content

Instantly share code, notes, and snippets.

@alexlib
Forked from marcetcheverry/mapread.c
Created August 31, 2019 10:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexlib/bf48c34c3f4a7ebffeee4badbf832ae9 to your computer and use it in GitHub Desktop.
Save alexlib/bf48c34c3f4a7ebffeee4badbf832ae9 to your computer and use it in GitHub Desktop.
mmap and read/write string to file
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
const char *filepath = "/tmp/mmapped.bin";
int fd = open(filepath, O_RDONLY, (mode_t)0600);
if (fd == -1)
{
perror("Error opening file for writing");
exit(EXIT_FAILURE);
}
struct stat fileInfo = {0};
if (fstat(fd, &fileInfo) == -1)
{
perror("Error getting the file size");
exit(EXIT_FAILURE);
}
if (fileInfo.st_size == 0)
{
fprintf(stderr, "Error: File is empty, nothing to do\n");
exit(EXIT_FAILURE);
}
printf("File size is %ji\n", (intmax_t)fileInfo.st_size);
char *map = mmap(0, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED)
{
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
for (off_t i = 0; i < fileInfo.st_size; i++)
{
printf("Found character %c at %ji\n", map[i], (intmax_t)i);
}
// Don't forget to free the mmapped memory
if (munmap(map, fileInfo.st_size) == -1)
{
close(fd);
perror("Error un-mmapping the file");
exit(EXIT_FAILURE);
}
// Un-mmaping doesn't close the file, so we still need to do that.
close(fd);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
int main(int argc, const char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Need at least one argument to write to the file\n");
exit(EXIT_FAILURE);
}
const char *text = argv[1];
printf("Will write text '%s'\n", text);
/* Open a file for writing.
* - Creating the file if it doesn't exist.
* - Truncating it to 0 size if it already exists. (not really needed)
*
* Note: "O_WRONLY" mode is not sufficient when mmaping.
*/
const char *filepath = "/tmp/mmapped.bin";
int fd = open(filepath, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
if (fd == -1)
{
perror("Error opening file for writing");
exit(EXIT_FAILURE);
}
// Stretch the file size to the size of the (mmapped) array of char
size_t textsize = strlen(text) + 1; // + \0 null character
if (lseek(fd, textsize-1, SEEK_SET) == -1)
{
close(fd);
perror("Error calling lseek() to 'stretch' the file");
exit(EXIT_FAILURE);
}
/* Something needs to be written at the end of the file to
* have the file actually have the new size.
* Just writing an empty string at the current file position will do.
*
* Note:
* - The current position in the file is at the end of the stretched
* file due to the call to lseek().
* - An empty string is actually a single '\0' character, so a zero-byte
* will be written at the last byte of the file.
*/
if (write(fd, "", 1) == -1)
{
close(fd);
perror("Error writing last byte of the file");
exit(EXIT_FAILURE);
}
// Now the file is ready to be mmapped.
char *map = mmap(0, textsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED)
{
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
for (size_t i = 0; i < textsize; i++)
{
printf("Writing character %c at %zu\n", text[i], i);
map[i] = text[i];
}
// Write it now to disk
if (msync(map, textsize, MS_SYNC) == -1)
{
perror("Could not sync the file to disk");
}
// Don't forget to free the mmapped memory
if (munmap(map, textsize) == -1)
{
close(fd);
perror("Error un-mmapping the file");
exit(EXIT_FAILURE);
}
// Un-mmaping doesn't close the file, so we still need to do that.
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment