1

I'm working on an assignment that involves creating files and manipulating characters within them using what the lecturer describes as "File and System I/O calls" in C.

Specifically, I am using open, creat, read, write, lseek, close, and unlink.

Without revealing too much and violating academic integrity, essentially the assignment just entails creating files, copying characters between them, changing the characters, etc.

All of this was going perfectly until a certain point of the program after which read just... Wouldn't work. It doesn't matter what file I am accessing, or what other calls I put before it- for instance, I have tried closing and re-opening a file before trying to read, writing before reading (worked perfectly, put the characters right at the file position the lseek intended), etc.

I have checked the returns of all previous commands, none are giving errors other than the read, which is giving me errorno 9. Having looked this up, it appears to refer to having an incorrect file descriptor, but this doesn't make sense to me as I can use the same fid for any other command. Using ls -l, I confirmed that I have read and write permission (groups and public do not, if that helps).

I am at a total loss of where to go troubleshooting from here, any help would be immensely appreciated. Here is the code snippet in question:

readStatus = lseek(WWWfid,500,0);
if (readStatus<0) {
    printf("error with lseek"); 
    return 0;
}
/*printf("Read status: %i\n", readStatus);/*DEBUG*/
writeStatus = write(WWWfid, "wtf", 3);
if (writeStatus<0) {
    printf("error with write");
    return 0;
}
        
readStatus = read(WWWfid, buffer, 26);
int errorNum = errno;
/*buffer[27] = '\0';*/
if (readStatus<0) {
    printf("error with read before loop, error %i\n", errorNum);
    return 0;
}

I can likely include more without invoking the wroth of my uni but I'd prefer not to- also seems likely to be irrelevant given that all proceeding code appears to be functioning correctly. Thanks for reading, please let me know if you have any insight at all

shellter
  • 36,525
  • 7
  • 83
  • 90
man_idk
  • 55
  • 5
  • 2
    Use `perror()` to print readable error messages. – Barmar Sep 10 '20 at 21:04
  • 1
    Please provide a [minimal verifiable example](https://stackoverflow.com/help/minimal-reproducible-example). No, we're not asking for the full assignment code. We need the smallest amount of complete code that can reproduce the problem. – kaylum Sep 10 '20 at 21:05
  • 1
    Not nearly enough detail, but you may have come up against a system resource limit, which is easy to fix. How many files do you have simultaneously open? How much data have you written to disk? etc. – EML Sep 10 '20 at 21:07
  • You might have an out-of-bounds array reference that's overwriting `WWWfid`. Or some other part of the program might be closing the FD. – Barmar Sep 10 '20 at 21:07
  • Run your program in a debugger. When you get the error, check if the value of `WWWfid` is what it should be. – Barmar Sep 10 '20 at 21:09
  • `EBADF` has nothing to do with permissions. It means that the value of `WWWfid` is not a file descriptor that's open for reading. – Barmar Sep 10 '20 at 21:10
  • 1
    `errno` is nearly useless on its own. Don't bother including it in error messages. Instead, use it as an index into the system's list of error messages. That is, instead of the useless `printf("error %i\n", errorNum)`, you ought to do `fprintf(stderr, "error %s\n", strerror(errNum))` (or just use `perror`). Whatever you do, make sure your error messages go to stderr and include the system error message. – William Pursell Sep 10 '20 at 21:30
  • @Barmar thanks for all the ideas! I understand what the error number refers to(via google) but using perror in C wasn't working- syntax example? – man_idk Sep 10 '20 at 21:36
  • `if (readStatus < 0) { perror("error with read"); return 0;}` – Barmar Sep 10 '20 at 21:37
  • @Barmar nevermind, see someone else added- apologies, still very new. To respond to your debugger comment, I attempted this, and the WWWfid (my fileId name) does not change after the read is performed or before. This makes sense, as read wasn't working with my other files as well- I am going to look into whether I overflowed the char array I was writing into and also William_Pursell 's error idea. Thanks to everyone who has been helping! – man_idk Sep 10 '20 at 21:38
  • 1
    @wildplasser He only uses `errorNum` after checking that the return value was negative. – Barmar Sep 10 '20 at 21:39
  • @WilliamPursell thanks for the answer! Any idea why that line causes a segmentation fault? Perror worked fine but the fprintf crashed it- maybe because I used both? – man_idk Sep 10 '20 at 21:52
  • How large is `buffer`? If you get a segmentation fault from a read, you're probably overwriting data. Is it at least size 28? Or, you have an error elsewhere in your code that gets triggered here. Or the error isn't occurring here at all, but just seems to. Have you examined a core dump? – William Pursell Sep 10 '20 at 22:07
  • I would try running the program via `strace`, to see if its system call results match what you're seeing, or give any other hints. – aschepler Sep 10 '20 at 22:40
  • It may be that even if your code doesn't intend to modify `WWWfid`, that you have a bug that overwrites it unintentionally. That is common in C code - if you write outside the bounds of an object (e.g. by reading more bytes than fit in a buffer), you overwrite memory that contains other variables. So if `WWWfid` really has changed, then forget about the failing `read` itself - it's not the bug - and debug the rest of your code to figure out where it changed. – Nate Eldredge Sep 10 '20 at 22:40
  • 2
    "all preceding code appears to be functioning correctly" - given the subtlety possible with bugs in C, "appears" doesn't mean very much. – Nate Eldredge Sep 10 '20 at 22:41
  • You are writing and reading to the same file descriptor without an intervening seek. – stark Sep 10 '20 at 22:52
  • @stark: I think that's legal for POSIX I/O, though it may well not be what OP really wants. Perhaps you're thinking of ISO "streams" I/O with fread/fwrite/fseek? – Nate Eldredge Sep 10 '20 at 23:42
  • @NateEldredge It may be legal, but it is unusual to write then read from that position. EBADF happens when reading on an fd open for write. – stark Sep 11 '20 at 13:49
  • You're probably overwriting `WWWfid` by writing more elements to some unrelated array (`buffer`?). Compile your program with `cc -g` and run it via `valgrind`: it does catch most simple bugs of this kind. –  Sep 12 '20 at 04:55

0 Answers0