OS_GBPB 1 misleading error message
Alan Adams (2486) 1149 posts |
If OS_GBPB is called with R4 (pointer to start writing) set to a negative value, the error “File too big” is returned. The online documentation (https://www.riscosopen.org/wiki/documentation/show/OS_GBPB%201) doesn’t describe what should happen. The printed RO3 PRM says “the file will be extended and the extra space zero filled”. “File too big” suggests that the pointer is being treated as an unsigned number, so the file should be extended. It would be helpful if either the documentation or the error message were to be changed so that they agree. I can forsee that such large numbers might be valid in future file system improvements however, so it will need some thought. |
Stuart Swales (8827) 1357 posts |
The file pointer is unsigned. Which file system is this on? |
Rick Murray (539) 13840 posts |
What’s the problem here? The pointer is logically an unsigned value – you won’t ever be writing at offset -20, and there are no magic values like -1 or whatever documented (plus doing that with a file pointer would be dumb anyway). If the file was to be extended as described, if you passed -1 (for example) then you’ve just asked for the file to be extended to a size of 4GiB, which maybe actually is “too big” for the underlying filing system. ;) |
Alan Adams (2486) 1149 posts |
SCSIFS
I’m calculating an offset into a file, and in some cases it returns a negative value. I don’t expect it to work, and I’ve now found and trapped a few of the places where it was occurring, but I’ve have preferred “invalid file pointer” for example, as that would have enabled me to work out what the problem was a bit quicker. |
Stuart Swales (8827) 1357 posts |
Why am I not surprised that in the BBC BASIC Reference Manual (Issue 3) description of “Integer giving the current length of the file from 0 to, in theory 2147483648, although in practice the extent is limited by the file medium in use.” We were careful in the filing system interface to make file pointers and extents unsigned even though we only had tiny drives BITD. “File too big” is a rubbish error msg I admit. |
Alan Adams (2486) 1149 posts |
So the maximum value is &7FFFFFFF, Which makes sense in the context of BASIC because BASIC can’t deal with unsigned 32-bit values. I wonder what would happen if a filesystem allowed files larger than that? Would a negative pointer from BASIC become valid? Would EXT# return an apparently negative value? I suspect it’s something that will become relevant fairly soon. |
Rick Murray (539) 13840 posts |
The maximum value envisaged then was 2GiB, bearing in mind this was written back when installed harddiscs were two digits and measured in megabytes 1, and FileCore had a half gigabyte partition size limit.
“It depends”. &FFFFFFFF is -1. ;)
In theory, nothing. Provided it is treated as unsigned all the way through and there isn’t one single signed comparison by mistake. ;) Note: it’s a trap I sometimes fall into, as it was fairly common in the old days to use GT and LT tests, because greater than or less than and it made sense. Fast forward decades (eek!) and suddenly stuff risks blowing up because it should have been HIgher or LOwer so it could cope with values that would, otherwise, be seen as a large negative number.
Arguably it already is, you just don’t have a capable filing system. ;)
It will be…. less than intuitive. But, then, somewhere along the way BASIC decided that it rather liked to say 2.34E-6 instead of a more readable (to normal people) 0.00000234. So, degrees of unintuitive. ;) 1 A decent quality MP3 of half of Nightwish’s songs would be larger than the average harddisc back then! |
Dave Higton (1515) 3525 posts |
This thread displays, again, misunderstandings about 2’s complement arithmetic. You can add or subtract numbers in the entire 32-bit range, and the numbers will come out correctly, whether they are signed or unsigned – provided that you don’t exceed the range of the type (signed or unsigned) of the number range you’re using. You can even add signed and unsigned numbers and get the correct result. Using BASIC. The unfortunate thing, because it clearly misleads some people, is that BASIC presents numbers as signed. But that’s just BASIC’s interpretation when asked to display them. |
Rick Murray (539) 13840 posts |
I know it works, messing with memory on a DA might get high addresses. It’s just less than intuitive for the meatsack looking at a bunch of negative numbers. Could be worth ignoring the likes of PRINT and STR$ and using OS_ConvertCardinal4 instead. Then the big numbers will look like they’re supposed to. ;) |
Alan Adams (2486) 1149 posts |
Not really. consider my situation. The offset is calculated by multiplying a record number by a record size. If the result of that exceeds &7fffffff BASIC will produce an overflow error, but the resulting value could be valid for a call to OS_GBPB. |
David J. Ruck (33) 1635 posts |
Best to maintain the limit of the current API at 2GB to avoid unsigned errors, and come up with that elusive 64 bit filing system stack for anything bigger. Allowing files between 2GB and 4GB is only marginally useful, as large things, such as video, can be much larger. |
Stuart Swales (8827) 1357 posts |
But the API limit is 4GB-1. It’s just BASIC that suggests otherwise. |
nemo (145) 2546 posts |
Rick deduced
The RMA must certainly never have b31 set. However, an additional High RMA certainly could, though there would need to be additional OS_Module reason codes to allocate, resize and free such blocks (my ModuleUtils module implements exactly this, as OS_Module,&86,&87 and &8D). Modules that can handle high address, and can guarantee their clients can too, could be loaded into the High RMA if they had a new Module Flags bit set, say b30. Alan complained
There are a number of ways to avoid this predictable difficulty, but the easiest is to use a real instead of an integer:
Hope that helps. |
nemo (145) 2546 posts |
Apropos of very little, a module automatically loading into High RMA: |
Alan Adams (2486) 1149 posts |
I hadn’t thought of that, probably because my programming history started with Fortran77, and I think the precision of reals there was 24 bit, with integers 32bit. As a result I always tend to avoid using reals in cases like this. |
nemo (145) 2546 posts |
Basic’s 40bit reals are an unsigned 32bit integer, a sign bit, and an eight bit exponent. So that’s effectively a 33bit signed int. Basic VI uses doubles, which are effectively a 53bit signed int plus 11bits of exponent. To enable int-real-int round-tripping in a 64bit integer Basic, it would need to use 96bit Extended format. |
Steve Pampling (1551) 8170 posts |
Ah, the things that can be done when using “Nemo RISC OS”. However, everyone else is using “ROOL RISC OS” or “ROL RISC OS”, with the nostalgia merchants using “Acorn RISC OS”". |
nemo (145) 2546 posts |
Touching on both points in this thread: 1. BASIC techniques for dealing with unsigned ints are universal. 2. RMA’s requirement to be at a positive address could easily slip some people’s minds, so it is useful to discuss the issue and outline the obvious API remedy (to avoid the unpleasantness of allowing The Wrong Thing™ to be done and then face determined hostility to any suggestion of fixing something that has been broken recently – I speak from long experience). I can rapidly prototype things because I’m unencumbered by the weighty responsibility of not breaking on a whim an OS that people rely upon <stares meaningfully>, and also I know how things actually work, which is a help. |
Rick Murray (539) 13840 posts |
Damn. That slap just triggered seismometers across the globe. |