0

I am trying to write a simple program that reads a file by encapsulating functions like open, lseek, pread.

My file for test contains:

first second third forth fifth sixth
seventh eighth

my main function that tries to read 20 bytes with offset 10 from the file:

#include <iostream>
#include "CacheFS.h"
using namespace std;
int main(int argc, const char * argv[]) {
    char * filename1 = "/Users/Desktop/File";
    int fd1 = CacheFS_open(filename1);
    //read from file and print it
    void* buf[20];
    CacheFS_pread(fd1, &buf, 20, 10);
    cout << (char*)buf << endl;
}

implementation of the functions that the main is using:

int CacheFS_open(const char *pathname)
{
    mode_t modes = O_SYNC | 0 | O_RDONLY;
    int fd = open(pathname, modes);
    return fd;
}

int CacheFS_pread(int file_id, void *buf, size_t count, off_t offset)
{
    off_t seek = lseek(file_id, offset, SEEK_SET);
    off_t fileLength = lseek(file_id, 0, SEEK_END);
    if (count + seek <= fileLength) //this case we are not getting to the file end when readin this chunk
    {
        pread(file_id, &buf, count, seek);
    } else { //count is too big so we can only read a part of the chunk
        off_t size = fileLength - seek;
        pread(file_id, &buf, size, seek);
    }
    return 0;
}

My main function prints this to the console:

\350\366\277_\377

I would expect it to print some values from the file itself, and not some numbers and slashes that represenet something I do not really understand. Why does this happen?

Eyzuky
  • 1,843
  • 2
  • 22
  • 45

1 Answers1

1

The following changes will make your program work:

  1. Your buffer has to be an existent char array and your CacheFS_pread function is called without the address operator & then. Also use the buffer size minus 1 because the pread function will override the terminating \0 because it's just read n bytes of the file. I use a zero initialized char array here so that there will be a null terminating \0 at least at the end.

    char buf[20] = { '\0' }; // declare and initialize with zeros
    CacheFS_pread(fd1, buf, sizeof(buf) - 1, 10);
    
  2. Your function header should accept only a char pointer for typesafety reasons.

    int CacheFS_pread(int file_id, char* buf, size_t count, off_t offset)
    
  3. Your pread call is then without the address operator &:

    pread(file_id, buf, count, seek);
    

Output: nd third forth fift because buffer is just 20!

Also I would check if your calculations and your if statements are right. I have the feeling that it's not exactly right. I would also recomment to use the return value of pread.

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
  • I implemented what you wrote in 3 (removed the & from buf calling read) and it worked. The other points I take as extra useful tips. Thanks!! – Eyzuky May 31 '17 at 11:51
  • The buffer need to be existent either on stack or heap. The `pread` function will **not** allocate it for you. If you ignore that you write to locations where you don't want to write following a stack or heap corruption. – Andre Kampling May 31 '17 at 11:54
  • I will implement the initialization as you explained, thank you sir. – Eyzuky May 31 '17 at 11:58
  • Regarding your second point, using char* and not void*. What if i want to support multiple types for reading? I thought casting void* would be a way to achieve that, but from what you say it looks pretty dangerous – Eyzuky May 31 '17 at 11:59
  • Therefore your're right. Then you can use the void* and should think about writing and reading binary data. – Andre Kampling May 31 '17 at 12:13
  • 1
    And what happens when `pread()` reads less than the requested number of bytes, or otherwise fails? The code in the question and in this answer ignores the return value, while unnecessarily adding extra code to limit the amount of bytes requested in order to not try reading past the end of the file - and in so doing needlessly changing the file descriptor's current offset. What happens if the file changes size? – Andrew Henle May 31 '17 at 12:13
  • I agree this code is only good for finding why my print was what it was and not more than that. I will take your tips in mind when I continue to write my library. Especially the error handling and offsets logic. – Eyzuky May 31 '17 at 12:16