Hi,
pcmattman wrote:Well, the problem is that it's in my kernel and I don't have any standard library there. For the time being I've just written an fsize() function.
pcmattman wrote:In the newlib (or any other standard C library), does feof() call fstat to find out how big the file is? How does it know when the end of the file comes around?
There 2 types of file I/O functions. The first type is low level I/O using functions like "open()", "close()", "read()", "write()", "lseek()", "fstat()", "stat()", etc. Conceptually, these functions deal directly with the (virtual) file system.
The second type is streams, which are like a high level wrapper (on top of the lower level functions) that exists inside the library. This includes functions like "fopen()", "fclose()", "fread()", "fwrite()", "fseek()", "fflush()", "feof()", etc. The library itself maintains file buffers and other things so that (for e.g.) you can get one byte at a time (while the library just gets the byte from the buffer instead of asking the kernel/VFS for it, and does a "read()" of several KB at a time if the buffer is empty).
The "feof()" function is for streams. It'd check if there's more bytes in the buffer and return zero if there is. If the buffer is empty it'd probably try to do a "read()" and see if it can get more data into the buffer (and return zero if it does get more data). It may also use some sort of "I'm at the end of the file" flag or keep track of the size of the file so it doesn't need to check "read()", but this may or may not work, depending on what type of stream it is, how it was opened and how file sharing works.
For example, if the stream is a socket then you might be at the end of the stream until someone sends data to the socket. For some (most?) systems, if you open a normal file as "read only" then some other software can open the same file as "append only", and the end of the file can keep shifting as more data is appended to the file (I'd assume this is common for things like logs - imagine having to stop Apache just to read the web server log). In both these cases the library would need to check "read()" each time you call "feof()" because the end of the stream may have moved.
Also remember that a function like "read()" may not return all the data you ask for, even when there is enough data. For example, if you try to "read(fileDes, myBuffer, sizeOfFile)" then the file system code might read part of the file and stop. This allows the file system code to return the first N sectors/bytes and wait for you to ask for the next N sectors/bytes, which makes it much easier to write the file system code and can have other advantages.
For example, if there's a bad sector in the middle of the file it can return all the data before the bad sector (and then return a "bad sector error" when you try to get the next N sectors/bytes). Alternatively, the file might be fragmented (where the file system driver returns N contiguous sectors only), or the hardware might not handle large transfers (where the file system driver returns what it can do in one transfer, and sets up a new transfer when it gets the next "read()" request), or the file system driver might be optimizing disk access (doing all pending transfers that don't involve shifting the disk heads before shifting the disk heads), or using some sort of file I/O priorities (stop transfering your data to/from disk if a higher priority request is received).
This means your code should be something like:
Code: Select all
int filesz = 0;
int totalBytes = 0;
int readBytes;
filesz = fsize( fp );
if( filesz <= 0 ) {
return ERROR_CODE;
}
fileData = kmalloc( filesz );
while( totalBytes < filesz ) {
readBytes = read( fp, fileData + totalBytes, 1, filesz - totalBytes );
if(readBytes == 0) {
/* EOF sooner than expected */
return ERROR_CODE;
}
if(readBytes < 0) {
/* Some sort of error reading the data */
return ERROR_CODE;
}
totalBytes += readBytes;
}
BTW it doesn't matter if you've got a standard library in the kernel or not - if you're using functions that look like they are part of a standard library then make them the same as a the functions you'd find in a standard library. Otherwise use completely different function names to avoid confusing everyone (e.g "kread()" and not "fread()", just like the way you're using "kmalloc()" and not "malloc()") .
Cheers,
Brendan