Returning information associated with a directory structure

Updated: October 26, 2022

Instead of returning just the struct dirent in the _IO_READ message, you can also return a struct stat, as a potential optimization. This is basically a usage question. If your device is typically used in such a way that first readdir() is called and then stat() is called, it will be more efficient to return both. If not, it is more efficient to not return the stat information. See the documentation for readdir() in the 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_extra_stat structure must be aligned on an 8-byte boundary but it follows a variable-length pathname. 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 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().