Search code examples
c++filefcntlunistd.h

Unable to read file contents into buffer using read()


Following is a sample code compiled using GNU compiler (g++ command) on an Ubuntu OS 16.04:

#include<iostream>
#include<unistd.h>
#include<fcntl.h>
#include <errno.h>
int main()
{           char* pBuffer;          

            char* storedfilepath = "/home/rtpl/Desktop/ts.mp4";

            std::cout<<"\n Opening file at "<<storedfilepath<<"\n";

            int NumBytesToRead = 1000 ;
            int filedes = open(storedfilepath,O_RDONLY);

            std::cout<<"\n value of error is "<<errno<<"\n";

            std::cout<<"\n value of filedes is "<<filedes;

            if (filedes==0)
            std::cout<<"\n File cannot be opened";
            else
            {
            std::cout<<"\n File opened successfully";
            std::cout<<"\n Now reading file\n"; 

            }

            //if(
            int ret = read(filedes,pBuffer,NumBytesToRead);

            std::cout<<"\n value of error is "<<errno<<"\n";

            if(ret!= -1)
            std::cout<<"\n File read successfully";
            else
            std::cout<<"\n File contents cannot be read";   

            std::cout<<"\nEnd.\n";  

            close(filedes);
            return 0;

} 

When compiled; I get this message:

rtpl@rtpl-desktop:~/Desktop$ g++ -g checkts.cpp
checkts.cpp: In function ‘int main()’:
checkts.cpp:8:27: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    char* storedfilepath = "/home/rtpl/Desktop/ts.mp4";

Upon execution:

rtpl@rtpl-desktop:~/Desktop$ ./a.out

 Opening file at /home/rtpl/Desktop/ts.mp4

 value of error is 0

 value of filedes is 3
 File opened successfully
 Now reading file

 value of error is 14

 File contents cannot be read
End.

Entire gdb debug can be found here.

Question : Why won't the file contents be read when the file is legit and the compiler throws no error?

Ts.mp4 permissions


Solution

  • Assuming you're running Linux, an errno value of 14 is EFAULT, or "bad address".

    Given the code

    char* pBuffer;
      .
      .
      .
    int ret = read(filedes,pBuffer,NumBytesToRead);
    

    pBuffer is not initialized or otherwise set, so the value in pBuffer is indeterminate and it certainly doesn't point to a valid address.

    You need to actually provide a buffer where read() can place the data read:

    char buffer[ 1024 ]
       .
       .
       .
    ssize_t ret = read(filedes,buffer,NumBytesToRead);
    

    would work, as long as NumBytesToRead does not exceed the number of bytes in buffer. Note also that ret is now the proper ssize_t instead of int.