-
-
Save lynnporu/0cb091a71a8e1574dcae3e39a3952b9a to your computer and use it in GitHub Desktop.
Linux file mapping
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Does not supposed to be compiled as main. | |
Contains methods for dealing with Linux file mappings. | |
*/ | |
#include "io.h" | |
extern int errno; | |
char IO_CUT_EOF = 1; | |
/* | |
* Read `stream` to `msg` and write bytes read to `size`. | |
* This function is kinda dirty, just delete it if you won't need | |
* any stdin reading. */ | |
void readstream(char** msg, size_t* size, FILE* stream){ | |
// one more bit for \0 | |
char buffer[IO_MAX_FGETS_SIZE + 1]; | |
*size = (size_t)0; | |
*msg = malloc(1024); | |
if(*msg == NULL){ | |
EMERGENCY("Memory error") | |
exit(EXIT_FAILURE); | |
} | |
*msg[0] = '\0'; | |
// Here we going to read IO_MAX_FGETS_SIZE to the buffer and copy it to the | |
// message. | |
while(fgets(buffer, IO_MAX_FGETS_SIZE, stream)){ | |
char** old = msg; | |
// WARNING: this code suppose cut_eof only takes 0 or 1 | |
*size += strlen(buffer) - IO_CUT_EOF; | |
*msg = realloc(*msg, sizeof(char) * *size); | |
if(*msg == NULL){ | |
EMERGENCY("Cannot reallocate") | |
free(old); | |
exit(EXIT_FAILURE); | |
} | |
memcpy(*msg, buffer, sizeof(char) * *size); | |
} | |
} | |
/* | |
* Create mapping to given `dest` of the file with given `addr`. | |
* For common tasks use o_flags = O_RDONLY and map_flags = PROT_READ. | |
* Size of the fill will be written to `fsize`. | |
* If map_flags contains PROT_WRITE file will be truncated to | |
* `desired_length` size. */ | |
void openfmap( | |
mapstream_t* dest, char* addr, | |
int o_flags, mode_t o_mode, int map_flags, | |
off_t desired_length | |
){ | |
int handle; | |
struct stat filestat; | |
if((handle = open(addr, o_flags, o_mode)) < 0){ | |
EMERGENCY("Cannot open '%s'", addr); | |
exit(EXIT_FAILURE); | |
} | |
if(map_flags & PROT_WRITE) | |
if(ftruncate(handle, desired_length) < 0){ | |
EMERGENCY("Cannot resize '%s'", addr); | |
exit(EXIT_FAILURE); | |
} | |
fstat(handle, &filestat); | |
dest->fsize = filestat.st_size; | |
if( | |
(dest->map = mmap( | |
0, dest->fsize, | |
map_flags, MAP_SHARED, | |
handle, 0 | |
)) == MAP_FAILED | |
){ | |
EMERGENCY("Cannot map '%s'", addr); | |
exit(EXIT_FAILURE); | |
} | |
close(handle); | |
dest->cursor = 0; | |
} | |
/*Close file mappings but do not free *src. */ | |
void closefmap(mapstream_t* src){ | |
if(munmap(src->map, src->fsize) < 0){ | |
EMERGENCY("Cannot unmap file at %p", src->map); | |
exit(EXIT_FAILURE); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef H_IO | |
#define H_IO | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdint.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#define IO_MAX_FGETS_SIZE 0xffff | |
// Prints text to the fout variable or stdout if | |
// print_to_file evaluates to 0. | |
#define IO_PRINT(format, ...) \ | |
fprintf( \ | |
print_to_file ? fout : stdout, \ | |
format, __VA_ARGS__); | |
// If cut_eof == 1, the very last symbol of the message (EOF or \0) will | |
// be erased. | |
extern char IO_CUT_EOF; | |
extern int errno; | |
/*Print fail message with errno to stderr, can be | |
* used for debugging. */ | |
#define EMERGENCY(msg, ...) \ | |
fprintf( \ | |
stderr, \ | |
"FAIL: " msg "; errno: %d\n", \ | |
__VA_ARGS__ __VA_OPT__(,) errno \ | |
); | |
/*This structure was desired to handle file mapping. */ | |
typedef struct { | |
// In my opinion, it is convenient to handle file mapping as uint8_t*, | |
// because it's just a set of 8-bit bytes after all. But you can change | |
// it to void* in case it's more preferable for you. | |
uint8_t* map; | |
// True length of the file. | |
off_t fsize; | |
// Current cursor of reading/writing process. You're free to change this | |
// value. | |
off_t cursor; | |
// This variable may be used in algorithms that calculates new length of the | |
// file only once and want it to be stored somewhere globally (like MD5 or | |
// RC5). | |
off_t sizeslot1; | |
} mapstream_t; | |
// See for function description in io.c file. | |
void openfmap( | |
mapstream_t* dest, char* addr, | |
int o_flags, mode_t o_mode, int map_flags, | |
off_t desired_length | |
); | |
void closefmap(mapstream_t* src); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment