---
name: "VFAT_IOCTL_READDIR_BOTH"
section: "2const"
platform: "linux"
package: "man-pages"
version: "6.19-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/VFAT_IOCTL_READDIR_BOTH"
---

# VFAT\_IOCTL\_READDIR\_BOTH(2const)

read filenames of a directory in a FAT filesystem

## NAME

VFAT\_IOCTL\_READDIR\_BOTH, VFAT\_IOCTL\_READDIR\_SHORT - read filenames of a directory in a FAT filesystem

## LIBRARY

Standard C library (*libc*, *-lc*)

## SYNOPSIS

```
#include <linux/msdos_fs.h>  /* Definition of VFAT_* constants */
#include <sys/ioctl.h>
```

**int ioctl(int** *fd***, VFAT\_IOCTL\_READDIR\_BOTH,**           **struct \_\_fat\_dirent** *entry***\[2\]);** **int ioctl(int** *fd***, VFAT\_IOCTL\_READDIR\_SHORT,**           **struct \_\_fat\_dirent** *entry***\[2\]);**

## DESCRIPTION

A file or directory on a FAT filesystem always has a short filename consisting of up to 8 capital letters, optionally followed by a period and up to 3 capital letters for the file extension. If the actual filename does not fit into this scheme, it is stored as a long filename of up to 255 UTF-16 characters.

The short filenames in a directory can be read with **VFAT\_IOCTL\_READDIR\_SHORT**. **VFAT\_IOCTL\_READDIR\_BOTH** reads both the short and the long filenames.

The *fd* argument must be a file descriptor for a directory. It is sufficient to create the file descriptor by calling [**open**(2)](/open/2.md) with the **O\_RDONLY** flag. The file descriptor can be used only once to iterate over the directory entries by calling [**ioctl**(2)](/ioctl/2.md) repeatedly.

The *entry* argument is a two-element array of the following structures:

```
struct __fat_dirent {
    long            d_ino;
    __kernel_off_t  d_off;
    uint32_t short  d_reclen;
    char            d_name[256];
};
```

The first entry in the array is for the short filename. The second entry is for the long filename.

The *d\_ino* and *d\_off* fields are filled only for long filenames. The *d\_ino* field holds the inode number of the directory. The *d\_off* field holds the offset of the file entry in the directory. As these values are not available for short filenames, the user code should simply ignore them.

The field *d\_reclen* contains the length of the filename in the field *d\_name*. To keep backward compatibility, a length of 0 for the short filename signals that the end of the directory has been reached. However, the preferred method for detecting the end of the directory is to test the [**ioctl**(2)](/ioctl/2.md) return value. If no long filename exists, field *d\_reclen* is set to 0 and *d\_name* is a character string of length 0 for the long filename.

## RETURN VALUE

A return value of 1 signals that a new directory entry has been read and a return value of 0 signals that the end of the directory has been reached.

On error, -1 is returned, and *errno* is set to indicate the error.

## ERRORS

- **ENOENT**

  *fd* refers to a removed, but still open directory.

- **ENOTDIR**

  *fd* does not refer to a directory.

## STANDARDS

Linux.

## HISTORY

Linux 2.0.

## EXAMPLES

The following program demonstrates the use of [**ioctl**(2)](/ioctl/2.md) to list a directory.

The following was recorded when applying the program to the directory */mnt/user*:

```
$ ./fat_dir /mnt/user;
. -> ''
.. -> ''
ALONGF~1.TXT -> 'a long filename.txt'
UPPER.TXT -> ''
LOWER.TXT -> 'lower.txt'
```

### Program source

```
#include <fcntl.h>
#include <linux/msdos_fs.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
    int                  fd;
    int                  ret;
    struct __fat_dirent  entry[2];
    if (argc != 2) {
        printf("Usage: %s DIRECTORY\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    /*
     * Open file descriptor for the directory.
     */
    fd = open(argv[1], O_RDONLY | O_DIRECTORY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    for (;;) {
        /*
         * Read next directory entry.
         */
        ret = ioctl(fd, VFAT_IOCTL_READDIR_BOTH, entry);
        /*
         * If an error occurs, the return value is -1.
         * If the end of the directory list has been reached,
         * the return value is 0.
         * For backward compatibility the end of the directory
         * list is also signaled by d_reclen == 0.
         */
        if (ret < 1)
            break;
        /*
         * Write both the short name and the long name.
         */
        printf("%s -> '%s'\n", entry[0].d_name, entry[1].d_name);
    }
    if (ret == -1) {
        perror("VFAT_IOCTL_READDIR_BOTH");
        exit(EXIT_FAILURE);
    }
    /*
     * Close the file descriptor.
     */
    close(fd);
    exit(EXIT_SUCCESS);
}
```

## SEE ALSO

[**ioctl**(2)](/ioctl/2.md), [**ioctl\_fat**(2)](/ioctl_fat/2.md)
