This is a real WTF situation... Am I going mad!?
I noticed that my FUSE read operation had started filling the buffer with zeros after I had updated my code to stop my linter complaining:
int cramp_read(const char* path, char* buf, size_t size, off_t offset, struct fuse_file_info* fi) {
int res = 0;
struct my_filep* f = get_filep(fi);
(void)path;
if (f) {
switch (f->type) {
case fd_normal:
if (pread(f->filep, buf, size, offset) == -1) {
res = -errno;
}
break;
case fd_special:
if (my_read(f->specialp, buf, size, offset) == -1) {
res = -errno;
}
break;
default:
res = -EPERM;
}
} else {
res = -EBADF;
}
return res;
}
That is, specifically the pread
branch (I've yet to write my_read
). However, debugging showed pread
was correctly setting the buffer to the file contents... After some digging, I found the error was when I initialised my variables: that is, the int res = 0;
seems to be causing this behaviour. If I change it back to int res;
, it starts working again.
What's even more strange: When I leave the variable uninitialised and print it to stderr before the very last return
-- i.e., after all the work has been done -- the pread
fails and I get an EPERM
error.
Could someone explain what is going on here? I've initialised my variables elsewhere, at my linter's request, and now I'm worried I've introduced a load of time bombs just waiting to be discovered!
OK, I'm an idiot! After reading the FUSE documentation, I found that ones read
implementation is supposed to return the number of read bytes, rather than the usual FUSE interface of 0 for success and -errno
on failure.
The following fixed the problem, while leaving the initialisation:
...
if ((res = pread(f->filep, buf, size, offset)) == -1) {
...
(Likewise for my yet-to-be-implemented my_read
branch.)