Interactive Files and Handler Detection

A handler in AmigaDOS is one of two things:

  • A file system — owns volumes; creates non-interactive filehandles whose contents and length are determined by the storage itself (FFS, RAM-Handler, third-party filesystems).
  • A non-filesystem handler — creates interactive filehandles whose contents and state depend on the outside world. Reads and writes may block indefinitely. (CON-Handler, Port-Handler, Queue-Handler for PIPE:, and the PRT:/SER:/PAR: devices managed by the Port-Handler.)

The functions in this article tell those two apart, and provide the I/O control primitives that only make sense on interactive files.

IsInteractive — test an open filehandle

BOOL IsInteractive(BPTR file);   /* classic */

Returns non-zero if file is interactive, FALSE otherwise. Cannot fail; does not alter IoErr().

Which handlers are interactive:

Handler / device Interactive?
FFS, OFS, RAM-Handler, SFS, PFS No (file systems)
CON-Handler (CON:, RAW:, AUX:) Yes
Port-Handler (PRT:, SER:, PAR:) Yes
Queue-Handler (PIPE:) Yes
NIL: No (always-empty non-interactive stream)

Don't Seek or SetFileSize on interactive files. They typically fail (return -1 / ERROR_ACTION_NOT_KNOWN) or are nonsensical.

IsFileSystem — test a path's handler

BOOL IsFileSystem(STRPTR path);   /* V36 */

Returns non-zero if the handler that would serve path is a file system. The path does not need to identify an existing object — it only needs to identify the handler. To make the lookup unambiguous, prefer a complete device or volume path with trailing colon, e.g. "DF0:" rather than "DF0:something".

If the path has no colon, IsFileSystem() checks the handler responsible for the current directory of the calling process.

Side effect. IsFileSystem() may load and run the handler if it is not already running. Plan accordingly; see the side-effect notes for GetDeviceProc() in The AmigaDOS Device List.

Pre-V36 workaround

Before V36 there was no IsFileSystem(). The standard workaround was to try locking the root of the path:

LONG IsFileSystem34(STRPTR path)
{
    UBYTE *colon = strchr(path, ':');

    if (colon && colon > path) {
        BPTR lock;
        colon[1] = '\0';
        UnLock(lock = Lock(path, SHARED_LOCK));
        return lock ? DOSTRUE : DOSFALSE;
    }
    if (!strcmp(path, "*")) {
        return DOSFALSE;   /* the console is never a file system */
    }
    return DOSTRUE;
}

This suffers the same load-and-start side effect as the V36+ function. It also wastes a lock on every call.

WaitForChar — non-blocking input poll

BOOL WaitForChar(BPTR file, LONG timeout_micros);   /* V36 */

Polls the handler behind file for the availability of at least one byte. Returns non-zero if at least one byte is ready (so a Read() will not block). Returns 0 otherwise or on error. timeout_micros is in microseconds, not ticks — much finer granularity than Delay().

WaitForChar() operates at the handler level only — it does not see bytes already buffered in the filehandle by the buffered-I/O functions of section 5.6. If buffered data exists, WaitForChar() may report "no input" while FGets() would still return data.

IoErr() rules:

  • 0 return + IoErr() == 0 → timed out cleanly.
  • 0 return + IoErr() != 0 → real error.
  • Non-zero return → data is available; IoErr() is handler-dependent. The CON-Handler deposits the number of pending lines in the line buffer here. Do not assume IoErr() == 0 on success.

File systems typically reject this call with ERROR_ACTION_NOT_KNOWN since they do not block.

Pre-V36, a timeout of 0 misbehaved; fixed in V36.

SetMode — change the console buffer mode

BOOL SetMode(BPTR fh, LONG mode);   /* V36 */

For the CON-Handler (CON:, RAW:, AUX:), sets the line-buffer mode:

Mode Behaviour
0 Cooked — buffer full lines, line editing, deliver on RETURN.
1 Raw — every keystroke available immediately; no line editing, no echo. Equivalent to opening RAW:.
2 Medium (V47+) — line editing but cursor-up/down and TAB are reported immediately. Used by the Amiga Shell for history and TAB expansion. No corresponding device name.

All other values are reserved.

SetMode() returns non-zero on success. On success, IoErr() is set to 1 if the console window is currently attached to an Intuition window, or 0 otherwise (closed window, or non-graphical AUX console). The mode applies to the filehandle — RAW: is implemented as a CON: window pre-set to mode 1.

Example: read a single key without waiting for RETURN

LONG getch(BPTR file)
{
    UBYTE c = 0;
    LONG  err = -1;

    if (SetMode(file, 1)) {              /* raw */
        if (Read(file, &c, 1) == 1)
            err = 0;
        SetMode(file, 0);                /* back to cooked */
    }
    return err < 0 ? err : c;
}

See Also


Sources: Thomas Richter, "ROM Kernel Reference Manual: AmigaDOS" (First Edition, 2024), Chapter 5.5 — Interactive File and Handler Support. Raw: raw/rkm/rkm-dos-book.md Updated: 2026-10-02