02 January 2024, 17:24 | #1 |
Hardware Designer
Join Date: Aug 2018
Location: Bialystok/Poland
Age: 51
Posts: 184
|
Creating a file in RAM: sets IoErr
AmigaOS 3.0. When I open a file for writing in RamDisk with
Open("RAM:foo", MODE_NEWFILE);and the file does not exist before, following IoErr()returns 205 (ERROR_OBJECT_NOT_FOUND) in spite of the file being created successfully. It does not happen when I do the same anywhere on harddisk (FFS, if it matters). IoErr()is still 0 then. Is it a bug? |
02 January 2024, 19:01 | #2 |
Registered User
Join Date: Jan 2002
Location: Germany
Posts: 7,043
|
Could be a bug. OS 3.0 is very old. But does it really matter? If Open() returns a non-zero value, it succeeded. You need to check IoErr only if Open returns null.
|
02 January 2024, 23:04 | #3 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,655
|
As thomas said, you can't rely on IoErr() if there is no error (unless explicitly specified so by the operation in question).
|
05 January 2024, 17:08 | #4 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,403
|
Well, actually, you should, and actually, IoErr() should be 0 on success (unless documented otherwise). This is a defect of the RAM-handler.
|
05 January 2024, 21:29 | #5 |
Registered User
Join Date: Mar 2018
Location: Hastings, New Zealand
Posts: 2,843
|
Autodocs 3.1: dos.doc
dos.library/IoErr NAME IoErr -- Return extra information from the systemSYNOPSIS error = IoErr()FUNCTION Most I/O routines return zero to indicate an error. When thisRESULTS error - integer |
05 January 2024, 22:23 | #6 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,403
|
Except that ACTION_FINDOUTPUT aka Open() shall create a 0 IoErr() on success. If it does not, it is a bug. There are functions in the dos.library which do not set IoErr(), or which set it to other values on success, but Open() is none of them.
|
06 January 2024, 10:36 | #7 | |
Registered User
Join Date: Aug 2010
Location: Germany
Posts: 538
|
Quote:
When you call Open("RAM:foo", MODE_NEWFILE), ram-handler will check if there already is an object named "foo". If it's a file, then checks will follow to determine whether it can be overwritten (it could be write-protected, a Lock or FileHandle may be associated with it). If it's a directory, then it can never be overwritten by a file. That sort of thing... But it all begins by checking if there is a directory entry of that name. ram-handler reuses the code which underpins the Lock()operation, among other things, and this function will put an error code of ERROR_OBJECT_NOT_FOUND into a global variable if there is no directory or file of that name. This global variable value will persist when the Open("RAM:foo", MODE_NEWFILE)call returns, even if it succeeds, and its value will go into the secondary result member of the DosPacket which underpins the file system interaction. That value will become available to you when you call the IoErr()function. That said, you should be aware that the value returned by the IoErr()function is meaningless without context. Hence, if Open("RAM:foo", MODE_NEWFILE)successfully returns a pointer to a FileHandle, then the IoErr()function value is meaningless. It only becomes meaningful if Open("RAM:foo", MODE_NEWFILE)returns NULL. There is some ambiguity here, I grant you. But for functions such as Lock(), Delete(), Rename(), etc. an indication of failure means that an error code will be available through IoErr(). This is a protocol or contract, if you will. |
|
06 January 2024, 11:09 | #8 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,403
|
No, Olaf, I beg you. This is an implementation detail that leaks outside, and that should not leak outside. If an operation via a packet succeeds, the Res2 of the packet shall be zero, as simple as that. There are unfortunately a couple of dos.library functions that do not set IoErr consistently in some cases, but that's also something I would call a defect that should better be fixed.
|
06 January 2024, 13:39 | #9 | |
Registered User
Join Date: Aug 2010
Location: Germany
Posts: 538
|
Quote:
I already checked what it takes to make Result2 consistently come up with 0 if an operation succeeds. It makes ram-handler significantly larger (this has to go into every single packet handling function), and we're already tight in terms of ROM space. If I should stumble down this rabbit hole, I need to save space elsewhere. Right now, the only thing which I believe might be easy to axe is the setdosdate function in dos.library. What do you think? Is booting off a BCPL file system even possible in Kickstart 2.x and beyond? |
|
06 January 2024, 13:39 | #10 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,655
|
That doesn't really matter much since the dos documentation explicitly specifies not to rely on IoErr when an operation returns success.
|
06 January 2024, 13:43 | #11 |
Registered User
Join Date: Aug 2010
Location: Germany
Posts: 538
|
The real problem is that "nobody" seems to read the documentation, and with good reason. It tends to be unhelpful and incomplete. Even the exceptionally well-researched "The Amiga Guru book" has its limitations, with errata unlikely to be published in the future
|
06 January 2024, 14:13 | #12 | ||
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,403
|
Quote:
Quote:
My original 1.2 boot disk booted fine under 3.2. But if you want to axe off something, I would look in the blib.c and all the BCPL emulation nonsense. This can run right into a software alert instead. The only thing remains are BCPL startup functions for the port-handler and "CLI" in createtask, and this should be moderately easy to get rid of either. At least, it would be more than 400 bytes you can save. |
||
06 January 2024, 14:17 | #13 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,403
|
Quote:
But it is a long story, and it takes a while to review. I'm now in the middle of the second iteration, checking every function and every description again, finding many defects, but nobody is perfect and certainly there are still errata left. Right in the middle of chapter 7 btw. As always, suggestions for improvement are welcome. |
|
06 January 2024, 15:00 | #14 | |||
Registered User
Join Date: Aug 2010
Location: Germany
Posts: 538
|
Quote:
Quote:
Fun fact: the "Volume last altered date and time" DateStamp does not contain the date and time of the last change made to the volume. It is more specific: the default file system updates it only when changes made to the bitmap are written back to disk. Basically, whenever storage space is released or allocated, the DateStamp will be updated, eventually. Quote:
This is an undocumented trap for file system developers. Basically, the FileInfoBlock structure as defined by the 3.0 header files only works for 'C' and assembly language code. If the client happens to be a legacy BCPL program, you can expect only the fields fib_DiskKey..fib_Comment to be accessible. If you write beyond the end of the fib_Comment field in your file system code, you may trash the BCPL stack. Last edited by Olaf Barthel; 06 January 2024 at 16:02. |
|||
10 January 2024, 19:23 | #15 |
Hardware Designer
Join Date: Aug 2018
Location: Bialystok/Poland
Age: 51
Posts: 184
|
Thank you all for extensive explanations. I have modified my code, so it only checks
IoErr()when Open()fails. |
12 January 2024, 05:45 | #16 |
Returning fan!
Join Date: Jan 2011
Location: Montréal, QC, Canada
Posts: 1,454
|
|
15 January 2024, 16:03 | #17 |
Registered User
Join Date: Aug 2010
Location: Germany
Posts: 538
|
Definitely sounds a bit like it. The recent rework (ahem) by yours truly was performed with the goals to render the code more readable, more maintainable and more robust, with no new features added and code size growing only in the low 20-100 bytes, if possible.
ram-handler is hard to maintain because the 'C' implementation is beholden to the design principles of the Kickstart 1.x BCPL version. Simple algorithms (not necessarily a bad thing), short functions which do the absolute minimum of what is required of them, terse variable and function names and code documentation which tends towards the decorative rather than the illuminating You'd hope that this foundation would make it easier to spot something amiss, but your hopes would be dashed so very quickly. ram-handler is simple, if not primitive, because it has to deliver, with very little code spent on making it work. The 'C' version uses function and variable naming a little better than the BCPL precursor, but it's often unhelpful because some data structure naming makes it hard to distinguish between the different types which, curiously, have very similar names. Part of my rewrite was to try and make the naming of things clearer so that you can tell from the name what you are dealing with. Without that foundation, maintaining the code becomes so much harder ram-handler is big on code reuse for the sake of keeping the code size under control. This has its perks, but they come with a Spaghettic Code tax. Yes, it is shorter and possibly faster, but you may wonder at some point if it's too much of a distraction from finding and fixing the bugs which hide in loops of the Spaghetti. And there were whole families of bugs hiding in plain sight, such as in the code which manages the memory allocation/free/resize operations. For example, due to a combination of bugs, closing a file just opened would almost always end up reallocating the memory spent on the last data chunk of the file, even if the file was unchanged. The code allocated new memory, copied the old data from the block to be replaced, then removed the old one, added the new one and freed the old block. Completely unnecessary, and not even a bit artful. Figuring out how much memory was being used and how that would relate to the total amount of memory installed on the Amiga was mostly guesswork, with some of the maintenance operations squirreled away into subroutines where nobody would ever look for them. As with all the file systems which came from the Tripos legacy, the ram-handler code rarely knew its own limitations, if at all. Not just file sizes, also name length for volumes and paths. Code reuse for the benefit of keeping ram-handler small had curious side effects. A file lock and a file handle were basically the same data structure type and you could in some dark corners of ram-handler use both interchangeably. How's that for fun? Looks like a magic trick, except when it goes wrong. I have some small hopes that the next person to walk into the current ram-handler code will no longer feel an uncanny urge to get the hell out of here before something slinky emerges from a ventilation shaft and grins without smiling... |
16 January 2024, 15:33 | #18 | |
Registered User
Join Date: Sep 2019
Location: Finland
Posts: 377
|
Quote:
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Amiga File Server - TOSEC Sets | CodyJarrett | project.Amiga File Server | 5 | 19 February 2022 11:32 |
creating HDZ file | pucci | support.WinUAE | 6 | 04 November 2011 09:13 |
Creating an empty hdf file | Harko33 | support.WinUAE | 1 | 25 September 2011 23:46 |
Creating a #?.info file | bytemind | project.WHDLoad | 24 | 15 May 2010 09:26 |
Creating a SFS HDF file | Bloodwych | support.WinUAE | 21 | 01 January 2007 16:53 |
|
|