mmap file not syncing - file

Hello I am trying to back up a vector by mmap.
However, I have tried msync then munmap but it doesn't work. After I write to the (char *) then munmap the file, the file has no content. The mmap file is also created with flag MAP_SHARED. Would really appreciate it if anyone can help.
//update file descriptor
if ((fd = open(filename.c_str(), O_RDWR | S_IRWXU)) < 0) { //| O_CREAT
printf("ERROR opening file %s for writing", filename.c_str());
exit(1);
}
//lseek create a file large enough
off_t i = lseek(fd, frontier_size * URL_MAX_SIZE, SEEK_SET);
if (i != frontier_size * URL_MAX_SIZE) {
cout << "failed to seek";
}
//reposition and write 3 bytes to the file else will failed to read
char buff[3] = "ta";
ssize_t kk = lseek(fd, 0, SEEK_SET);
if (kk < 0) {
cout << "failed to reposition";
}
ssize_t temp_write = write(fd, (void *)& buff, 2);
if (temp_write < 0) {
cout << "failed to write";
cout << temp_write;
}
//reposition to begining
ssize_t k = lseek(fd, 0, SEEK_SET);
if (k < 0) {
cout << "failed to reposition";
}
char * map = (char *)mmap(0, frontier_size * URL_MAX_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
printf("failed mmap");
exit(1);
}
mmap_frontier = map;
//write to frontier
for (int i = 0; i < frontier.size(); ++i) {
strcpy(mmap_frontier, frontier[i].c_str());
mmap_frontier += URL_MAX_SIZE;
}
mmap_frontier -= frontier.size() * URL_MAX_SIZE;
ssize_t k = lseek(fd, 0, SEEK_SET);
if (k < 0) {
cout << "failed to reposition";
}
int sync = msync((void *)0, frontier.size() * URL_MAX_SIZE, MS_ASYNC);
if (sync < 0 ) {
cout << "failed to sync";
}
int unmap = munmap((void *)0, frontier.size() * URL_MAX_SIZE);
if (unmap < 0) {
cout << "failed to unmap";
}

There are quite a few problems with your code, and with the question:
S_IRWXU is the 3rd argument to open(), not a flag for the 2nd parameter.
mmap() won't work correctly if the file is too small. You can use ftruncte() to set the file size correctly. You tried to seek past the total size of the mapping and write a couple of bytes ("ta"), but before doing that you issued the seek lseek(fd, 0, SEEK_SET) which means the file size was set to 3 rather than mapping_size+3.
You're not backing the vector with an mmapped file, the vector has nothing to do with it, the vector uses its own memory that isn't related in any way to this mapping (please edit your question...).
You called msync() with the address (void *)0, so the actual address which needs to be synced, map, is not being synced.
Likewise, you called munmap() with the address (void *)0, so the actual address which needs to be unmapped is not being unmapped.
You called msync() with MS_ASYNC, which means there's no guarantee that the sync happens before you read the file's contents.
Here's what's working for me (error handling omitted for brevity):
unsigned frontier_size = 2;
const unsigned URL_MAX_SIZE = 100;
int fd = open("data", O_RDWR);
loff_t size = frontier_size * URL_MAX_SIZE;
ftruncate(fd, size);
char *map = (char *)mmap(0, size, PROT_WRITE, MAP_SHARED, fd, 0);
strcpy(map, "hello there");
msync(map, size, MS_SYNC);
munmap(map, size);
close(fd);

Related

Pipe does not give the same result every time in C

I am trying to read a file by the parent process, send the content to two child processes and child processes write content to a shared memory segment. However, at each run, I get different outputs and I cannot figure out why.
I use two named pipes and after writing to shared memory, the parent process opens the shared memory and reads the content of each memory.
The first child writes to memory as it gets but the second child converts to hexadecimal.
Here is my main function; assume that stringtohex() works correctly.
int main()
{
pid_t pid_1, pid_2;
int fd, sd; // pipes
const int SIZE = 4096;
const char infile[] = "in.txt";
FILE *tp; // file pointers
pid_1 = fork();
if (pid_1 < 0)
{
fprintf(stderr, "Fork 1 failed");
return(1);
}
if (pid_1 > 0)
{
pid_2 = fork();
if (pid_2 < 0)
{
fprintf(stderr, "Fork 2 failed");
return(1);
}
if (pid_2 > 0) // parent
{
tp = fopen(infile, "r");
if (tp == 0)
{
fprintf(stderr, "Failed to open %s for reading", infile);
return(1);
}
mknod(PIPE_NAME_1, S_IFIFO | 0666, 0);
mknod(PIPE_NAME_2, S_IFIFO | 0666, 0);
fd = open(PIPE_NAME_1, O_WRONLY);
sd = open(PIPE_NAME_2, O_WRONLY);
if (fd > 0 && sd > 0)
{
char line[300];
while (fgets(line, sizeof(line), tp))
{
int len = strlen(line);
int num_1 = write(fd, line, len);
int num_2 = write(sd, line, len);
if (num_1 != len || num_2 != len)
perror("write");
else
printf("Ch 1: wrote %d bytes\n", num_1);
printf("Ch 2: wrote %d bytes\n", num_2);
}
close(fd);
close(sd);
}
fclose(tp);
wait(NULL);
int shm_fd = shm_open("Ch_1", O_RDONLY, 0666);
if (shm_fd == -1)
{
fprintf(stderr, "Failed: Shared Memory 1");
exit(-1);
}
int shm_sd = shm_open("Ch_2", O_RDONLY, 0666);
if (shm_sd == -1)
{
fprintf(stderr, "Failed: Shared Memory 2");
exit(-1);
}
void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED)
{
printf("Map failed 1\n");
return -1;
}
void *ptr2 = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_sd, 0);
if (ptr2 == MAP_FAILED)
{
printf("Map failed 2\n");
return -1;
}
fprintf(stdout, "Normal input: \n%s\n", ptr);
fprintf(stderr, "Hexadecimal: \n%s\n", ptr2);
}
else // second child
{
// open shared memory segment
int shm_child_2 = shm_open("Ch_2", O_CREAT | O_RDWR, 0666);
// configure the size of the shared memory segment
ftruncate(shm_child_2, SIZE);
// map the pointer to the segment
void *ptr_child_2 = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_2, 0);
if (ptr_child_2 == MAP_FAILED)
{
printf("Map failed 3\n");
return -1;
}
// configure named pipe
mknod(PIPE_NAME_2, S_IFIFO | 0666, 0);
sd = open(PIPE_NAME_2, O_RDONLY);
if (sd > 0) // reading from pipe
{
int num;
char s[300];
while ((num = read(sd, s, sizeof(s))) > 0)
{
// convert to hexadecimal
char hex[strlen(s) * 2 + 1];
stringtohex(s, hex);
// write into segment
sprintf(ptr_child_2, "%s", hex);
ptr_child_2 += strlen(s) * 2;
}
close(sd);
}
exit(0);
}
}
else // first child
{
// create shared memory segment
int shm_child_1 = shm_open("Ch_1", O_CREAT | O_RDWR, 0666);
// configure the size of the shared memory segment
ftruncate(shm_child_1, SIZE);
// map the pointer to the segment
void *ptr_child_1 = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_child_1, 0);
if (ptr_child_1 == MAP_FAILED)
{
printf("Map failed 4\n");
return -1;
}
// configure named pipe
mknod(PIPE_NAME_1, S_IFIFO | 0666, 0);
fd = open(PIPE_NAME_1, O_RDONLY);
if (fd > 0) // reading from pipe
{
int num;
char s[300];
while ((num = read(fd, s, strlen(s))) > 0)
{
// write into segment
sprintf(ptr_child_1, "%s", s);
ptr_child_1 += strlen(s);
}
close(fd);
}
exit(0);
}
return 0;
}
For example input file has:
Harun
sasmaz
59900
1234
Aaaa
Results are:
Normal input:
HARUN
sasmaz
59900
1234
Aaaa4
Hexadecimal:
484152554E0A7361736D617A0A35393930300A313233340A41616161
or
Normal input:
HARUN
sasmaz
asmaz59900
1234
Aaaa
Hexadecimal:
484152554E0A7361736D617A0A35393930300A0A313233340A41616161FF03

ELF - Getting a SEGFAULT when changing the entry point

I'm trying to patch the entry point of an ELF file directly via the e_entry field:
Elf64_Ehdr *ehdr = NULL;
Elf64_Phdr *phdr = NULL;
Elf64_Shdr *shdr = NULL;
if (argc < 2)
{
printf("Usage: %s <executable>\n", argv[0]);
exit(EXIT_SUCCESS);
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
perror("open");
exit(EXIT_FAILURE);
}
if (fstat(fd, &st) < 0)
{
perror("fstat");
exit(EXIT_FAILURE);
}
/* map whole executable into memory */
mapped_file = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mapped_file < 0)
{
perror("mmap");
exit(EXIT_FAILURE);
}
// check for an ELF file
check_elf(mapped_file, argv);
ehdr = (Elf64_Ehdr *) mapped_file;
phdr = (Elf64_Phdr *) &mapped_file[ehdr->e_phoff];
shdr = (Elf64_Shdr *) &mapped_file[ehdr->e_shoff];
mprotect((void *)((uintptr_t)&ehdr->e_entry & ~(uintptr_t)4095), 4096, PROT_READ | PROT_WRITE);
if (ehdr->e_type != ET_EXEC)
{
fprintf(stderr, "%s is not an ELF executable.\n", argv[1]);
exit(EXIT_FAILURE);
}
printf("Program entry point: %08x\n", ehdr->e_entry);
int text_found = 0;
uint64_t test_addr;
uint64_t text_end;
size_t test_len = strlen(shellcode);
int text_idx;
for (i = 0; i < ehdr->e_phnum; ++i)
{
if (text_found)
{
phdr[i].p_offset += PAGE_SIZE;
continue;
}
if (phdr[i].p_type == PT_LOAD && phdr[i].p_flags == ( PF_R | PF_X))
{
test_addr = phdr[i].p_vaddr + phdr[i].p_filesz;
text_end = phdr[i].p_vaddr + phdr[i].p_filesz;
printf("TEXT SEGMENT ends at 0x%x\n", text_end);
puts("Changing entry point...");
ehdr->e_entry = (Elf64_Addr *) test_addr;
memmove(test_addr, shellcode, test_len);
phdr[i].p_filesz += test_len;
phdr[i].p_memsz += test_len;
text_found++;
}
}
//patch sections
for (i = 0; i < ehdr->e_shnum; ++i)
{
if (shdr->sh_offset >= test_addr)
shdr->sh_offset += PAGE_SIZE;
else
if (shdr->sh_size + shdr->sh_addr == test_addr)
shdr->sh_size += test_len;
}
ehdr->e_shoff += PAGE_SIZE;
close(fd);
}
The shellcode in this case is just a bunch of NOPs with an int3 instruction at the end.
I made sure to adjust the segments and sections that come after this new code, but the problem is that as soon as I patch the entry point the program crashes, why is that?
changing:
memmove(test_addr, shellcode, test_len);
to:
memmove(mapped_file + phdr[i].p_offset + phdr[i].p_filesz, shellcode, test_len);
Seems to fix your problem. test_addr is a virtual address belong to the file you have mapped; you cannot use that directly as a pointer. The bits you want to muck with are the file map address, p_offset and p_filesz.
I suspect that you haven't enable write-access to program's header. You can do this via something like
const uintptr_t page_size = 4096;
mprotect((void *)((uintptr_t)&ehdr->e_entry & ~(uintptr_t)4095), 4096, PROT_READ | PROT_WRITE);
ehdr->e_entry = test_addr;

MPI_Bcast error on multiple nodes

Background: I am writing MPI versions of I/O system calls, which are based on the collfs project.
The code runs without error on multiple processors on a single node.
However, running on multiple nodes causes a segmentation fault... The error message with 2 processes, 1 process per node is the following:
$ qsub test.sub
$ cat test.e291810
0: pasc_open(./libSDL.so, 0, 0)
1: pasc_open(./libSDL.so, 0, 0)
1: mptr[0]=0 mptr[len-1]=0
1: MPI_Bcast(mptr=eed11000, len=435104, MPI_BYTE, 0, MPI_COMM_WORLD)
0: mptr[0]=127 mptr[len-1]=0
0: MPI_Bcast(mptr=eeb11000, len=435104, MPI_BYTE, 0, MPI_COMM_WORLD)
_pmiu_daemon(SIGCHLD): [NID 00632] [c3-0c0s14n0] [Sun May 18 13:10:30 2014] PE RANK 0 exit signal Segmentation fault
[NID 00632] 2014-05-18 13:10:30 Apid 8283706: initiated application termination
The function where the error occurs is the following:
static int nextfd = BASE_FD;
#define next_fd() (nextfd++)
int pasc_open(const char *pathname, int flags, mode_t mode)
{
int rank;
int err;
if(!init)
return ((pasc_open_fp) def.open)(pathname, flags, mode);
if(MPI_Comm_rank(MPI_COMM_WORLD, &rank) != MPI_SUCCESS)
return -1;
dprintf("%d: %s(%s, %x, %x)\n", rank, __FUNCTION__, pathname, flags, mode);
/* Handle just read-only access for now. */
if(flags == O_RDONLY || flags == (O_RDONLY | O_CLOEXEC)) {
int fd, len, xlen, mptr_is_null;
void *mptr;
struct mpi_buf { int len, en; } buf;
struct file_entry *file;
if(rank == 0) {
len = -1;
fd = ((pasc_open_fp) def.open)(pathname, flags, mode);
/* Call stat to get file size and check for errors */
if(fd >= 0) {
struct stat st;
if(fstat(fd, &st) >= 0)
len = st.st_size;
else
((pasc_close_fp) def.close)(fd);
}
/* Record them */
buf.len = len;
buf.en = errno;
}
/* Propagate file size and errno */
if(MPI_Bcast(&buf, 2, MPI_INT, 0, MPI_COMM_WORLD) != MPI_SUCCESS)
return -1;
len = buf.len;
if(len < 0) {
dprintf("error opening file, len < 0");
return -1;
}
/* Get the page-aligned size */
xlen = page_extend(len);
/* `mmap` the file into memory */
if(rank == 0) {
mptr = ((pasc_mmap_fp) def.mmap)(0, xlen, PROT_READ, MAP_PRIVATE,
fd, 0);
} else {
fd = next_fd();
mptr = ((pasc_mmap_fp) def.mmap)(0, xlen, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
}
((pasc_lseek_fp) def.lseek)(fd, 0, SEEK_SET);
/* Ensure success on all aux. processes */
if(rank != 0)
mptr_is_null = !mptr;
MPI_Allreduce(MPI_IN_PLACE, &mptr_is_null, 1, MPI_INT, MPI_LAND,
MPI_COMM_WORLD);
if(mptr_is_null) {
if(mptr)
((pasc_munmap_fp) def.munmap)(mptr, xlen);
dprintf("%d: error: mmap/malloc error\n", rank);
return -1;
}
dprintf("%d: mptr[0]=%d mptr[len-1]=%d\n", rank, ((char*)mptr)[0], ((char*)mptr)[len-1]);
/* Propagate file contents */
dprintf("%d: MPI_Bcast(mptr=%x, len=%d, MPI_BYTE, 0, MPI_COMM_WORLD)\n",
rank, mptr, len);
if(MPI_Bcast(mptr, len, MPI_BYTE, 0, MPI_COMM_WORLD) != MPI_SUCCESS)
return -1;
if(rank != 0)
fd = next_fd();
/* Register the file in the linked list */
file = malloc(sizeof(struct file_entry));
file->fd = fd;
file->refcnt = 1;
strncpy(file->fn, pathname, PASC_FNMAX);
file->mptr = mptr;
file->len = len;
file->xlen = xlen;
file->offset = 0;
/* Reverse stack */
file->next = open_files;
open_files = file;
return fd;
}
/* Fall back to independent access */
return ((pasc_open_fp) def.open)(pathname, flags, mode);
}
The error occurs at the final MPI_Bcast call. I am at a loss as to why it is happening: the memory it copies from and to I can dereference just fine.
I am using MPICH on a custom Cray XC30 machine running SUSE Linux x86_64.
Thanks!
EDIT: I have tried replacing the MPI_Bcast call with a MPI_Send/MPI_Recv pair, and the result is the same.
The Cray MPI implementation probably does some magic for performance reasons. Without knowing the internals much of the answer is a guess.
The inter-node communication likely does not utilize the network stack, relying on some sort of shared memory communication. When you try to send mmap-ed buffer over the network stack something somewhere breaks - the DMA engine (I'm wildly guessing here) cannot handle this case.
You can try to page lock the mmaped buffer - perhaps mlock will work just fine.
If that fails, then go with copying the data into malloced buffer.

MMAP reading and writing files

Im trying to use mmap to read in a file and then encrypt it and then write the encryption to the output file. I'm trying to also do this with mmap but when I run the code, it tells me that it was not able to unmmap due to "Invalid Argument".
//Open files initialy and obtain a handle to the file.
inputFile = open(inFileName, O_RDONLY, S_IREAD);
outputFile = open(outFileName, O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, S_IWRITE);
//Allocate buffers for encrption.
from = (unsigned char*)malloc(blockSize);
to = (unsigned char*)malloc(blockSize);
mmapWriteBuff = (unsigned char*)malloc(blockSize);
mmapReadBuff = (unsigned char*)malloc(blockSize);
memset(to, 0, blockSize);
memset(from, 0, blockSize);
memset(mmapWriteBuff, 0, blockSize);
memset(mmapReadBuff, 0, blockSize);
//Make sure we have permission to read the file provided.
setFilePermissions(inFileName, PERMISSION_MODE);
setFilePermissions(outFileName, PERMISSION_MODE);
if(encriptParam)
{
printf("*Encripting file: %s *\n", inFileName);
do//Go through the entire file.
{
if(memParam)
{
currAmt = lseek(inputFile, blockSize, SEEK_SET);
mmapReadBuff = mmap(0, blockSize, PROT_READ, MAP_SHARED, inputFile, 0);
/*
*This is how you encrypt an input char* buffer "from", of length "len"
*onto output buffer "to", using key "key". Jyst pass "iv" and "&n" as
*shown, and don't forget to actually tell the function to BF_ENCRYPT.
*/
BF_cfb64_encrypt(mmapReadBuff, mmapWriteBuff, blockSize, &key, iv, &n, BF_ENCRYPT);
if(currAmt < blockSize)
{
writeAmt = lseek(outputFile, currAmt, SEEK_SET);
mmapWriteBuff = mmap(0, currAmt, PROT_WRITE, MAP_SHARED, outputFile, 0);
if(errno == EINVAL)
{
perror("MMAP failed to start write buffer: ");
exit(MMAP_IO_ERROR);
}
}
else
{
writeAmt = lseek(outputFile, blockSize, SEEK_SET);
mmapWriteBuff = mmap(0, blockSize, PROT_WRITE, MAP_SHARED, outputFile, 0);
if(errno == EINVAL)
{
perror("MMAP failed to start write buffer: ");
exit(MMAP_IO_ERROR);
}
}
mmapWriteBuff = to;
}
else
{
currAmt = read(inputFile, from, blockSize);
/*
*This is how you encrypt an input char* buffer "from", of length "len" *onto output buffer "to", using key "key". Jyst pass "iv" and "n" as
*shown, and don't forget to actually tell the function to BF_ENCRYT.
*/
BF_cfb64_encrypt(from, to, blockSize, &key, iv, &n, BF_ENCRYPT);
if(currAmt < blockSize)
{
writeAmt = write(outputFile, to, currAmt);
}
else
{
writeAmt = write(outputFile, to, blockSize);
}
}
if(memParam)
{
//if(currAmt < blockSize)
//{
// if(munmap(mmapWriteBuff, currAmt) == -1)
// {
// perror("MMAP failed to unmap itself: ");
//
// exit(MMAP_IO_ERROR);
// }
//
// if(munmap(mmapReadBuff, currAmt) == -1)
// {
// perror("MMAP failed to unmap itself: ");
//
// exit(MMAP_IO_ERROR);
// }
//}
//else
//{
if(munmap(mmapReadBuff, blockSize) == -1)
{
perror("MMAP Read Buffer failed to unmap itself: ");
exit(MMAP_IO_ERROR);
}
if(munmap(mmapWriteBuff, blockSize) == -1)
{
perror("MMAP Write Buffer failed to unmap itself: ");
exit(MMAP_IO_ERROR);
}
//}
}
memset(to, 0, strlen((char *)to));
memset(from, 0, strlen((char *)from));
memset(mmapReadBuff, 0, strlen((char*)mmapReadBuff));
memset(mmapWriteBuff, 0, strlen((char*)mmapWriteBuff));
}
while(currAmt > 0);
printf("*Saving file: %s *\n", outFileName);
}
Generally speaking, it seems like you might want to try setting up the outputFile file descriptor without the O_WRONLY flag. Using the O_WRONLY flag for mmap() isn't sufficient.
Thus, you may need to change this:
outputFile = open(outFileName, O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, S_IWRITE);
to this:
outputFile = open(outFileName, O_APPEND | O_CREAT | O_TRUNC | O_RDWR, S_IWRITE);
I am not an expert with mmap(), but I know that you might want to give it both read and write permissions when opening the file descriptor.
EDIT:
Also you want want to try casting every mmap() call to (int*) like so:
mmapReadBuff = (int*)mmap(0, blockSize, PROT_READ, MAP_SHARED, inputFile, 0);

Is it possible to map just part of a file using mmap?

I have a input file which has a header like this:
P6\n
width\n
height\n
depth\n
and then a struct is writen, pixel*, into this file, which is going to be mapped.
So, I want to skip the header and make my mmap function return the ptr to that structure. How can I do this? with lseek perhaps? Could you please exemplify?
I will leave part of my code here:
printf("Saving header to output file\n");
if (writeImageHeader(h, fpout) == -1) {
printf("Could not write to output file\n");
return -1;
}
last_index = (int)ftell(fpout);
//printf("offset after header= %d\n",last_index);
//alloc mem space for one row (width * size of one pixel struct)
row = malloc(h->width * sizeof (pixel));
/*Create a copy of the original image to the output file, which will be inverted*/
printf("Starting work\n");
for (i = 0; i < h->height; i++) {
printf("Reading row... ");
if (getImageRow(h->width, row, fpin) == -1) {
printf("Error while reading row\n");
}
printf("Got row %d || ", (i + 1));
printf("Saving row... ");
if (writeRow(h->width, row, fpout) == -1) {
printf("Error while reading row\n");
}
printf("Done\n");
}
/*Open file descriptor of the ouput file.
* O_RDWR - Read and Write operations both permitted
* O_CREAT - Create file if it doesn't already exist
* O_TRUNC - Delete existing contents of file*/
if ((fdout = open(argv[2], O_RDWR, FILE_MODE)) < 0) {
fprintf(stderr, "Can't create %s for writing\n", argv[2]);
exit(1);
}
/*Get size of the output file*/
if (fstat(fdout, &sbuf) == -1) {
perror("Stat error ---------->\n");
exit(1);
}
//printf("Size of output file: %d\n",(int)sbuf.st_size);
/*Maps output file to memory*/
if ((data = mmap((caddr_t) 0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0)) == (caddr_t) (-1)) {
perror("Error mmaping");
exit(EXIT_FAILURE);
}
As you see, right now my ppm image is mapped to char* data, but I want to skip the header and map just to the pixel* part.
Here's my code with the suggestion of using 2 pointers, a char* from mmap and another one equals that + offset.
main
c functions
header
makefile
If you read the man page for mmap, you wil find that its final parameter is off_t offset. The description:
... continuing or at most 'len' bytes to be mapped from the object described by 'fd', starting at byte offset 'offset'.
I suspect if you pass your offset in as that parameter, it will do what you want.
You can't if the amount you need to skip is less than the system page size, since offset must be a multiple of the page size on some systems.
You just need to keep 2 pointers - the pointer to the start of the mmap'd block, and the pointer to the start of the data you want inside there. As in:
unsigned char *block = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0);
unsigned char *data = block + offset;
where offset is the offset in the file to the data you want.
So, from what I understand, can I do something like this?
off_t offset_after_header = lseek(fdout, last_index, SEEK_SET);
printf("Pointer is on %d\n",(int)offset_after_header);
/*Maps output file to memory*/
if ((data = mmap((caddr_t) 0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, offset_after_header)) == (caddr_t) (-1)) {
perror("Error mmaping");
exit(EXIT_FAILURE);
}
and, from that, I could map my file to whatever type I want, in this case the pixel*
If this is ok, what cautions should I take? For example, like those Ignacio Vazquez-Abrams said
Um, you did notice the 'offset' parameter that you are supplying with a zero? Assuming you know the absolute offset of what you want, you pass it.

Resources