0

I have this code provided by my teacher, it opens a file, maps into the memory with mmap and then write a string using gets. The problem is that it writes only the first 2 characters of the string into the file even if the printf prints all the string. Any advice?

#include <stdlib.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#define PAGE_SIZE (8192) 


int main(int argc, char** argv){

    pid_t pid;
    int fd;
    char* buffer;

    if (argc!= 2) {
            printf("Syntax: prog file_name\n");
        return -1;
    }


    fd=open(argv[1], O_RDWR);

    if (fd== -1) {
     printf("open error");
     return -2; 
    }


    buffer = (char*)mmap(NULL,PAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    close(fd);
    if (buffer == NULL){
        printf("mmap error\n");
        return -3;

    }   

    pid = fork();

    if(pid == -1){
        printf("fork error\n"); 
        return -4;

    }

    if(pid == 0){
        gets(buffer);       
        return 0;
    }   

    waitpid(pid, NULL);

    printf("%s\n",buffer);

    return 0;


}
  • 2
    See [Why the `gets()` function is so dangerous it should never be used!](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) – Jonathan Leffler Jun 08 '18 at 15:21
  • The return value from `mmap()` on failure is MAP_FAILED, which need not be the same as NULL. I don't know whether it's an issue in practice. – Jonathan Leffler Jun 08 '18 at 15:28
  • 1
    You could help yourself by including sensible diagnostic printing. For example, in the child, after the ill-advised `gets()`, you should echo what was read: `printf("Got [%s]\n", buffer);` — which will give you an indication of what the child sees. – Jonathan Leffler Jun 08 '18 at 15:30
  • the issue occurs also with scanf() – Leonardo Petraglia Jun 08 '18 at 15:31
  • @JonathanLeffler I'm pretty sure `MAP_FAILED` is `((void*)-1)`, not `NULL`. – melpomene Jun 08 '18 at 15:47

1 Answers1

2

mmap creates an association between a region of memory and the current extent of a file (called the "backing file"). It does not alter the size of the file, and it does not necessarily take into account any changes in the size of the file.

Perhaps your teacher is trying to show you that fact with this example.

In the case that the file is shorter than the mapped memory extent, the rest of the extent is zero-filled when the mmap is executed. However, modifications to this region will not be written out to the backing file, and may or may not be visible to other processes sharing the mapping, even though MAP_SHARED has been set.

If you have created a mapped region with write enabled, you should avoid referring to the part of the region not present in the file. (If you just want the file as a persistent backup of shared memory, you should probably use ftruncate to set the file's size to the desired mapping size.) You must do that before you call mmap, because if the size of the file is changed while the mapping is in effect, the result is undefined behaviour.

rici
  • 234,347
  • 28
  • 237
  • 341