VFAT_IOCTL_READDIR_BOTH(2const)
π VFAT_IOCTL_READDIR_BOTH(2const) π
okay bestie, welcome to VFAT_IOCTL_READDIR_BOTH(2const) β this is the manual page (section 2const, the constants/ioctl girlies π
) that explains how to peek at the filenames chillin' inside a directory on a FAT filesystem. pull up a chair, we're doing this together. β¨
π NAME π
VFAT_IOCTL_READDIR_BOTH</p>, VFAT_IOCTL_READDIR_SHORT</p> β read the filenames of a directory in a FAT filesystem. no cap, that's literally the whole job.
π LIBRARY π
Standard C library (libc, <cyan>-lc</cyan>). she's standard, she's C, she's library. π
β¨ 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 πΈ
okay so every file or directory on a FAT filesystem always has a short filename β and bestie, it's giving very tight dress code: up to 8 capital letters, optionally followed by a period and up to 3 capital letters for the file extension. that's it, that's the whole fit. π
but if the actual filename does not fit into that scheme, it gets stored as a long filename of up to 255 UTF-16 characters. she simply could not be contained. β¨
- want just the short ones in a directory? that's
VFAT_IOCTL_READDIR_SHORT. VFAT_IOCTL_READDIR_BOTHreads both the short and the long filenames. both, babe. inclusive queen. π«Ά
the fd argument must be a file descriptor for a directory. and honestly? it is sufficient to create that file descriptor by calling open(2) with the O_RDONLY flag. and here's the tea: π₯ the file descriptor can be used only once to iterate over the directory entries, by calling ioctl(2) repeatedly. one and done, no takebacks.
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.
and now, the field lore π:
the d_ino and d_off fields are filled only for long filenames. d_ino holds the inode number of the directory. d_off holds the offset of the file entry in the directory. and because these values are not available for short filenames, your user code should simply ignore them. not me telling you to mind your business but like, mind your business. π
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) return value. do that instead, bestie, it's the main character move.
and 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. empty. void. nothing there. π
π₯ RETURN VALUE π₯
- a return value of 1 signals that a new directory entry has been read β¨
- 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. she's gone but she's still here, iconic honestly. π»ENOTDIRβ fd does not refer to a directory. wrong vibe check, bestie. π«
π STANDARDS π
Linux. π
π¦ HISTORY π¦
Linux 2.0. vintage. retro. elder icon.
π EXAMPLES π
the following program demonstrates the use of ioctl(2) 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 π
and that's the whole page, bestie!! π«Ά this was Linux man-pages 6.20, dated 2025-09-21, and honestly? she ate. go read a FAT directory, you've got this. π β¨π
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π the page's license: Linux-man-pages-copyleft
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms