Handling the xtype member

Updated: May 06, 2022

The message structures passed to the io_read, io_write, and io_openfd handlers contain a member called xtype. From struct _io_read:

struct _io_read {
    ...
    uint32_t            xtype;
    ...
}

Basically, the xtype contains extended information that can be used to adjust the behavior of a standard I/O function. This information includes a type and optionally some flags:

To isolate the type from the flags in _IO_READ and _IO_WRITE messages, use a bitwise AND of the xtype member with _IO_XTYPE_MASK:

if ((msg->i.xtype & _IO_XTYPE_MASK) == ...)

Most resource managers care about only a few types:

_IO_XTYPE_NONE
No extended type information is being provided.
_IO_XTYPE_OFFSET
If clients are calling pread(), pread64(), pwrite(), or pwrite64(), then they don't want you to use the offset in the OCB. Instead, they're providing a one-shot offset. That offset follows the struct _io_read or struct _io_write headers that reside at the beginning of the message buffers.

For example:

struct myread_offset {
    struct _io_read        read;
    struct _xtype_offset   offset;
}   

Some resource managers can be sure that their clients will never call pread*() or pwrite*(). (For example, a resource manager that's controlling a robot arm probably wouldn't care.) In this case, you can treat this type of message as an error.

_IO_XTYPE_READCOND
If a client is calling readcond(), they want to impose timing and return buffer size constraints on the read. Those constraints follow the struct _io_read or struct _io_write headers at the beginning of the message buffers. For example:
struct myreadcond {
    struct _io_read        read;
    struct _xtype_readcond cond;
}   

As with _IO_XTYPE_OFFSET, if your resource manager isn't prepared to handle readcond(), you can treat this type of message as an error.

_IO_XTYPE_READDIR
The readdir() function sets this flag in an _IO_READ message to indicate that the client is reading a directory. In your handler for this message, you could give an error of EISDIR if a client does a read() on a directory.

The following types are used for special purposes, so your resource manager probably doesn't need to handle them:

The xtype member may also include some flags. Your resource manager might be interested in the following:

_IO_XFLAG_DIR_EXTRA_HINT
This flag is valid only when you're reading from a directory. The filesystem should normally return extra directory information when it's easy to get. If this flag is set, it is a hint to the filesystem to try harder (possibly causing media lookups) to return the extra information. The most common use is to return _DTYPE_LSTAT information.

The readdir() function sets this flag in an _IO_READ message if you've used dircntl() to set D_FLAG_STAT for the directory.

_IO_XFLAG_DIR_STAT_FORM_*
(QNX Neutrino 7.0 or later) These bits specify which form of the stat structure your resource manager should return when a client reads a directory. The client can specify the form via dircntl(), and readdir() sets the flag accordingly:
dircntl() command xtype flag Structure
D_FLAG_STAT_FORM_UNSET _IO_XFLAG_DIR_STAT_FORM_UNSET The default for the 32- or 64-bit architecture that you're using
D_FLAG_STAT_FORM_T32_2001 _IO_XFLAG_DIR_STAT_FORM_T32_2001 struct __stat_t32_2001
D_FLAG_STAT_FORM_T32_2008 _IO_XFLAG_DIR_STAT_FORM_T32_2008 struct __stat_t32_2008
D_FLAG_STAT_FORM_T64_2008 _IO_XFLAG_DIR_STAT_FORM_T64_2008 struct __stat_t64_2008

You can use _IO_XFLAG_DIR_STAT_FORM_MASK to isolate these bits from the rest of the xtype.

The other defined flags are used for special purposes, so your resource manager probably doesn't need to handle them: