Get Extended Media Information

This toolkit was started in the early 90's, before the SMSQ/E DMEDIUM_xxx
functions were added (V2.73), and later patched and added to over time.

DMEDIUM_xxx has largely made these redundant for SMSQ/E, and for Qdos,
some parts are not relevant. However, it is still useful to include with
any compiled program that requires to be compatible with both SMSQ/E and
Qdos, as most functions will work with both Level 1 and Level 2 Device
Drivers (DDL1/DDL2).

A short version of this toolkit, MD_bin, is also included. This is SMSQ/E
(DDL2) only. It adds some of the "missing bits" from DMEDIUM_xxx. For
details see MD_bin, below.

Most of the functions take the following parameters:

<device> =

        "filename" | "device"   - quoted string or string variable
   or    filename | device      - unquoted name
   or   #channel                - refering to an already open S*BASIC
                                  channel to a Directory Device

   Note: If no device parameter is given, the Data Default device is used
   Note: If a channel number is provided, the channel is left open after
         the call.

<filename> is otherwise as <device> above, but refers to a specific file
rather than a device in general.

        level = MDLEVEL(<device>)

        Returns the DD level, ie 1, 2, .. - or any error

        allc = MDALLOC(<device>)

        Returns the Allocation size in bytes, ie the number of bytes (or
        divide by 512 for the number of sectors) addressed as one block by
        the file system, for this device. (More under MDFSIZE, below.)

        file_header = MDFHEAD(<device>)

        Returns the size of the File header in bytes. (This will probably
        remain at 64b for all time.)

        total = MDGOOD(<device>)

        Returns the total available size of the medium, in bytes.
        Note: The corresponding DMEDIUM_TOTAL function returns the number
        of 512b sectors.

        free = MDFREE(<device>)

        Returns the amount of free space on the medium, in bytes.
        Note: The corresponding DMEDIUM_FREE function returns the number
        of 512b sectors.

        name$ = MDNAME$(<device>)

        Returns the Name of the medium, eg "System"

        rdonly = MDSTAT(<device>)

        Returns the read-only status of a device.
        1 => read only, 0 => read/write
        Note: Only DD2 devices can currently be made Read Only

        removable = MDREMV(<device>)

        Returns the Removable status of a device.
        1 => Removable, 0 => Not removable
        Note: Only DD2 devices can currently be set to Removable

        usize = MDFSIZE(<device>, fsize)

        Returns the size taken up by a file of size fsize on a given
        medium, in bytes.

        Another way of making this calculation may better demonstrate
        whats going on:

        DEFine FuNction Fsize(md$, sz)
        LOCal allc, fz, uz
        allc = MDALLOC(md$):            REMark Get File allocation size
        fz = sz + MDFHEAD(md$):         REMark Add header to file size
        uz = LDIV(fz, allc) * allc:     REMark Number of whole units
        IF fz > uz: uz = uz + allc:     REMark Round up to nearest unit
        RETurn uz:                      REMark File takes up this much space
        END DEFine Fsize

        There is one loose end, though: If you are adding a new file, there
        is a chance that the directory size will also reach a critical
        level, so that it needs to overflow into a new allocation block
        itself. There is no easy way to calculate this in advance (as, for
        example, empty slots may be re-used, etc.) So if you are trying to
        test in advance whether a new file will fit on a medium, you
        should add one extra allocation unit to the result to be quite

        file_header$ = MDHEADR$(<filename>)

        Returns the actual header of the given file as a (64 byte) string.
        For details of the file header, see dev8_keys_hdr in the SMSQ/E

This simplified version of MDINFO is only compatible with DDL2. It has a
subset of functions. Their meaning is the same as the corresponding ones
above. All return sizes are in bytes.

        file_size   = MDFSIZE(#channel, size)

        free_bytes  = MDFREE(#channel)

        header_size = MDFHEAD(#channel)

        alloc_block = MDALLOC(#channel)

The channel number must refer to an open channel on a Directory Device. It
remains open after the call.

Status of this software
All code is ©pjwitte, except for two PD utilites included in the
library which are ©Tony Tebby and ©David Oliver.

You may freely use this toolkit in your own programs, provided suitable
notice is given of the original authors.

By using this code you accept that the authors give no guarantees and
accept no responsibility to you or your down-stream users. Use at own

pjw, April 16th 2019

pjwitte at googlemail dot c0m