Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 344
neverMind Avatar asked Oct 18 '25 21:10

neverMind


2 Answers

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.

like image 132
Steven Schlansker Avatar answered Oct 20 '25 11:10

Steven Schlansker


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.

like image 23
Ignacio Vazquez-Abrams Avatar answered Oct 20 '25 10:10

Ignacio Vazquez-Abrams



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!