thursday, 7 june 2007

posted at 22:32
tags:

As mentioned previously, AROS DOS has some special magical device names that don't correspond to any underlying device - IN:, OUT:, etc. Because they're AROS-specific, I get to choose how they're implemented, but I also need to make sure that the right thing happens.

Before my changes recent changes Open() and Lock() knew about them explicitly, and other calls like IsFileSystem() did their own simplified DOSList traversal and so knew how to handle not finding them there.

My recent changes have made these names only known to Open(), much like CONSOLE: and NIL:. Everything else uses GetDeviceProc() which by design only knows about what is in the DOSList. And with my ErrorReport() changes, we now get this:

This happens because of the way More accesses the file. First it calls Open(), which is fine. Then it calls IsFileSystem() to decide if it should do its own buffering or not (which is actually not the right way to test this, but thats not relavent here). Later, it calls Lock() on the name, then NameFromLock() to generate the window title. The calls to IsFileSystem() and Lock() both yield requesters because both those functions use GetDeviceProc() underneath, and those "devices" aren't in the DOSList, so it requests them.

My first thought was that these cases should be like CONSOLE:, and not work. But then I thought a little more and realised this was no good. CONSOLE: always points to a console (unless you've really screwed something up, but then your software is broken), so you can assume its always interactive, never a filesystem, not lockable and nameless - simple. Standard I/O can be redirected however. After you Open("OUT:", MODE_OLDFILE) you don't know if the handle you got back is directed at the console, a file, a pipe, or whatever else. So it is entirely reasonable to do IsFileSystem("OUT:"), etc. A solution is needed.

To fix this requires either teaching GetDeviceProc() about these names or adding tests to every function that takes a name to deal with them. The former sucks because we can't really build a struct DevProc for these names without being able to return its DOSList entry in dvp_DevNode, which might not exist if the filehandle is pointed at CONSOLE: or NIL:. The latter sucks because we need special-case code everywhere - more clutter, harder to read, harder to maintain, etc.

There's a third option: making a new handler and having it handle these names. I do like this idea, but I'm not sure its practical. I'd need to add entries to the DOSList for each name (so six total), but I'm not sure of the best way to approach that. Adding DLT_VOLUME entries is out because then Wanderer will display them. DLT_DEVICE entries could be fine but then we'd be violating the "rule" of one DOS device to one handler task. Unless we made a separate task for each, but then there's six barely-used tasks kicking around in the task list.

There's also complications in the fact that these names need to provide access to the in/out/error streams of the calling process, so they can't really run in a separate task as we need to extract the handles from the process context. Thats not so bad - a PA_FASTCALL port could take care of that.

The whole thing really is fraught with danger, but there doesn't seem to be an easy way out. I haven't thought about it much though, so I'll ponder it some more and see if there's a clean way to add the special-case checking to the requisite functions. And I'll probably need to add "fix More" to my list too, because I need more to do :P