• Please review our updated Terms and Rules here

Does a file need to be closed before BDOS 35 get file size is correct?

alank2

Veteran Member
Joined
Aug 3, 2016
Messages
2,265
Location
USA
If I create a file and write 2 records into it and then call BDOS 35 - should it reflect the 2 records that were written? Or does the file need to be closed/opened for it to return 2 records?

edit: could what is happening here be that BDOS 35 scans the directory records which may not be updated because the file has been written, but not closed (thus updating the directory records)?
 
Last edited:
The documentation for BDOS function 35 says this:
Note: the BDOS does not require that the file be open to use Function 35. However,
if the file has been written to, it must be closed before calling Function 35. Other-
wise, an incorrect file size might be returned.
 
Always close a file after you're finished writing to it. You're risking corruption otherwise.

In theory, closing after reading shouldn't matter, but it's best to do it so the file's resources can be freed.
 
Technically, there are no resources to free for open files in CP/M. It is only a matter of doing the final update of the active directory entry, for files that have been written. And failing to close a file that was written cannot corrupt the disk, only lose the last data written. But, yes, it is good practice to always close files before exit - but that is mainly from a programming "correctness" standpoint.
 
Thanks; I was troubleshooting why an implementation of C fseek to find the end of the file was failing. It uses this BDOS function, but the file hasn't been closed yet which is why it is returning the wrong information.

The program CP/M player (virtualized CP/M, but not emulated CP/M) interestingly returns the correct information without having to close the file so that is what I get for testing it there (not real CP/M).

It sounds like compute file size can be used at the beginning (when opening a file) and the C runtime would need to keep track of the file length itself from that point forward since it can't call compute file size after write operations and get the correct value.

BTW - a second question. I found this page on exact file sizes for CP/M plus. Can any part of this translate or work with CP/M 2.2? Can the same place in the directory that holds the "last byte used count" still be used in CP/M 2.2, or is it appropriated for something else? What I'm asking I suppose is can any part of the below method be retrofitted to CP/M 2.2?

 
The CP/M 3 byte-count can be set on a file and won't cause problems if that file (disk) is used on CP/M 2.2. But, CP/M 2.2 has no knowledge of the byte-count, and also will not update it. Note that even CP/M 3 requires that the application take special actions in order to set/get the byte-count, and not all applications will do that. In fact, the CP/M 3 BDOS doesn't really do anything with the byte-count, it is entirely up to the applications to check it. It was a nice idea, but because of lack of adoption it is not as useful as it could be. Seems like very few apps (outside of the CP/M 3 distro) got updated to take full advantage of CP/M 3.
 
When writing to a file, BDOS will write the allocations, and request new allocations, and these are dynamics in the AV table, so there is no need to keep track of the allocation use outside of the FCB and it will not update the directory entry. However when the entry is full, the file will be "closed" and "reopened" since closing a file only writes the FCB into the directory entry. This is necessary as a new directory entry is created in the FCB and the process begins again.

So if the write operation fills the entry, then the file is automatically closed. I can't remember if it closes once full, or closes only because you try to write past the end of the allocations in the current entry.
 
...
So if the write operation fills the entry, then the file is automatically closed. I can't remember if it closes once full, or closes only because you try to write past the end of the allocations in the current entry.
Technically, the file is not closed. When the "extent" is full, it is closed and a new one opened. That extent may or may not represent the entire directory entry, but either way the directory entry (partial or full) is written to disk. This means that a file that is written but not closed will only be missing the last extent of data. But since the extent is 16K, it is often all the data that is lost.
 
This means that a file that is written but not closed will only be missing the last extent of data. But since the extent is 16K, it is often all the data that is lost.
Technically, you only need to write the entry when the entry is filled, so if the extent mask isn't zero, then there's a reasonable likelihood that the file entry won't get written until all of the extents in the entry are filled. So it could be up to 8 x 16K extents worst case, or 128K lost at most. Admittedly, that's going to be quite a lot of a file in a system that usually doesn't go past 64K.

Interestingly the data isn't lost - just not allocated. So if there was only one file open, there's a reasonable chance of file recovery if there was an application to do it, and there's no submit on the disk or other app that will write over unused allocations if it was a reboot event.

Which makes me wonder if anyone wrote such utilities back in the time of CP/M?
 
Technically, you only need to write the entry when the entry is filled, so if the extent mask isn't zero, then there's a reasonable likelihood that the file entry won't get written until all of the extents in the entry are filled. So it could be up to 8 x 16K extents worst case, or 128K lost at most. Admittedly, that's going to be quite a lot of a file in a system that usually doesn't go past 64K.

Interestingly the data isn't lost - just not allocated. So if there was only one file open, there's a reasonable chance of file recovery if there was an application to do it, and there's no submit on the disk or other app that will write over unused allocations if it was a reboot event.

Which makes me wonder if anyone wrote such utilities back in the time of CP/M?
The standard CP/M BDOS will write the whole directory entry when any extent gets filled. So if a directory entry contains multiple extents, it gets written multiple times while filling up. Max "lost" is 16K under that scheme.

As far as the definition of "lost", well... split that hair if you want.
 
The standard CP/M BDOS will write the whole directory entry when any extent gets filled.

I thought it went the other way but never checked. I went the same way then and close the file when the extent is written, so that it reloads the new extent from disk, even though it's the same extent. It was just less code that way and saved on memory.

But I had to recheck my code to see which way I programmed my own BDOS. And realized just how often I confused the word "Extent" and "Entry" in my comments.... Some days I'm surprised my code even works given how many assumption errors I made. Now I'm glad I didn't try to tackle CP/M 3 as the target to imitate... Too much learning curve.

Interestingly, I use the same code to close an extent as I do to open a new file. Since both opening and closing a file perform the same disk functions -ie, write the FCB to the directory entry location. I assume that CP/M also does it the same way?
 
Back
Top