Returning information associated with a directory structure

Instead of returning just the struct dirent in the _IO_READ message, you can also return a struct stat. Although this will improve efficiency, returning the struct stat is entirely optional. If you don't return one, the users of your device will then have to call stat() or lstat() to get that information. (This is basically a usage question. If your device is typically used in such a way that readdir() is called, and then stat() is called, it will be more efficient to return both. See the documentation for readdir() in the QNX Neutrino C Library Reference for more information.)

The client can set the xtype member of the message to _IO_XFLAG_DIR_EXTRA_HINT to send a hint to the filesystem to return the extra information, however the filesystem isn't guaranteed to do so. If the resource manager provides the information, it must put it in a struct dirent_extra_stat, which is defined as follows:

struct dirent_extra_stat {
    uint16_t            d_datalen;
    uint16_t            d_type;
    uint32_t            d_reserved;
    struct stat         d_stat;

The resource manager must set d_type to the appropriate _DTYPE_LSTAT* or _DTYPE_STAT* value, depending on whether or not it resolves symbolic links, whether the information is for a 32- or 64-bit architecture, and which version of POSIX is being used (see readdir()). For example:

if(msg->i.xtype & _IO_XFLAG_DIR_EXTRA_HINT) { 
    struct dirent_extra_stat    extra;
    extra.d_datalen = sizeof extra.d_stat;
    extra.d_type = _DTYPE_LSTAT;
    extra.d_reserved = 0;
    iofunc_stat(ctp, &attr, &extra.d_stat);

There's a dirent_extra_stat after each directory entry:

Figure 1. Returning the optional struct dirent_extra_stat along with the struct dirent entry can improve efficiency.
Note: The dirent structures must be aligned on 4-byte boundaries, and the dirent_extra_stat structures on 8-byte boundaries. The d_reclen member of the struct dirent must contain the size of both structures, including any space necessary for the pathname and alignment. There must be no more than seven bytes of alignment filler.

The client has to check for extra data by using the _DEXTRA_*() macros (see the entry for readdir() in the QNX Neutrino C Library Reference.) If this check fails, the client will need to call lstat() or stat() explicitly. For example, ls -l checks for extra _DTYPE_LSTAT information; if it isn't present, ls calls lstat(). The ls -L command checks for extra _DTYPE_STAT information; if it isn't present, ls calls stat().