I have been using similar piece of code since a while.
I have read some issues regarding treating mapped memory as a string. I am not sure about that though.
So I just use strndup(3)
to avoid it anyway. Wanted some reviews on this code:
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct MyFile {
const char *filename;
int fd;
size_t size;
char *contents;
};
int setup_myfile(const char *filename, struct MyFile *file);
void clean_myfile(struct MyFile file);
int
main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
struct MyFile my_file;
char *contents, *line, *to_free;
int err = setup_myfile(argv[1], &my_file);
if (err == -1) {
fprintf(stderr, "setup_myfile() failed\n");
exit(EXIT_FAILURE);
}
to_free = contents = strndup(my_file.contents, my_file.size);
if (to_free == NULL) {
perror("strndup(3)");
exit(EXIT_FAILURE);
}
while ((line = strsep(&contents, "\n")) != NULL) {
// Print line by line or do anything with line
printf("%s", line);
}
free(to_free);
clean_myfile(my_file);
return 0;
}
int
setup_myfile(const char *filename, struct MyFile *file)
{
struct stat st;
file->filename = filename;
file->fd = open(file->filename, O_RDONLY);
if (file->fd == -1) {
perror("open(2)");
return -1;
}
if (fstat(file->fd, &st) == -1) {
perror("fstat(2)");
return -1;
}
file->size = st.st_size;
file->contents = mmap(NULL, file->size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file->fd, 0);
if (file->contents == MAP_FAILED) {
perror("mmap(2)");
return -1;
}
return 0;
}
void
clean_myfile(struct MyFile file)
{
munmap(file.contents, file.size);
close(file.fd);
}