IOCTL_FAT - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
ioctl_fat-操作FAT文件系统
语法
#include <linux/msdos_fs.h>
#include <sys/ioctl.h>
int ioctl(int fd, FAT_IOCTL_GET_ATTRIBUTES, uint32_t *attr);
int ioctl(int fd, FAT_IOCTL_SET_ATTRIBUTES, uint32_t *attr);
int ioctl(int fd, FAT_IOCTL_GET_VOLUME_ID, uint32_t *id);
int ioctl(int fd, VFAT_IOCTL_READDIR_BOTH,
struct __fat_dirent[2] entry);
int ioctl(int fd, VFAT_IOCTL_READDIR_SHORT,
struct __fat_dirent[2] entry);
说明
ioctl(2)系统调用可用于读取和写入无法使用其他系统调用访问的FAT文件系统的元数据。
Reading and setting file attributes
FAT文件系统中的文件和目录具有属性位掩码,可以使用FAT_IOCTL_GET_ATTRIBUTES读取并使用FAT_IOCTL_SET_ATTRIBUTES写入。
fd参数包含文件或目录的文件描述符。通过使用O_RDONLY标志调用open(2)来创建文件描述符就足够了。
attr参数包含一个指向位掩码的指针。位掩码的位是:
- ATTR_RO
- 该位指定文件或目录是只读的。
- ATTR_HIDDEN
- 该位指定文件或目录是隐藏的。
- ATTR_SYS
- 该位指定文件是系统文件。
- ATTR_VOLUME
- 该位指定文件为卷标。此属性是只读的。
- ATTR_DIR
- 该位指定这是一个目录。此属性是只读的。
- ATTR_ARCH
- 该位指示该文件或目录应该被存档。在创建或修改文件时设置。它由归档系统重置。
零值ATTR_NONE可用于指示未设置任何属性位。
Reading the volume ID
FAT文件系统由卷ID标识。可以使用FAT_IOCTL_GET_VOLUME_ID读取卷ID。
fd参数可以是文件系统的任何文件或目录的文件描述符。通过使用O_RDONLY标志调用open(2)创建文件描述符就足够了。
id参数是指向将用卷ID填充的字段的指针。通常,卷ID作为两个16位字段的组显示给用户:
printf("Volume ID %04x-%04x\n", id >> 16, id & 0xFFFF);
Reading short filenames of a directory
FAT文件系统上的文件或目录始终具有较短的文件名,该文件名最多由8个大写字母组成,可以选择后面跟一个句点,并为文件扩展名最多3个大写字母。如果实际文件名不适合此方案,则将其存储为长文件名,最多255个UTF-16字符。
可以使用VFAT_IOCTL_READDIR_SHORT读取目录中的短文件名。 VFAT_IOCTL_READDIR_BOTH读取短文件名和长文件名。
fd参数必须是目录的文件描述符。通过使用O_RDONLY标志调用open(2)创建文件描述符就足够了。通过重复调用ioctl(2),文件描述符只能用于一次迭代目录条目。
entry参数是具有以下结构的两元素数组:
struct __fat_dirent {
long d_ino;
__kernel_off_t d_off;
uint32_t short d_reclen;
char d_name[256];
};
数组中的第一个条目是短文件名。第二项是长文件名。
d_ino和d_off字段仅填充长文件名。 d_ino字段保存目录的索引节点号。 d_off字段保存目录中文件条目的偏移量。由于这些值不适用于短文件名,因此用户代码应该简单地忽略它们。
字段d_reclen包含字段d_name中文件名的长度。为了保持向后兼容性,短文件名的长度为0表示已到达目录的末尾。但是,检测目录结尾的首选方法是测试ioctl(2)返回值。如果不存在长文件名,则字段d_reclen设置为0,并且d_name是长文件名的长度为0的字符串。
返回值
如果出错,则返回-1,并且将errno设置为指示错误。
对于VFAT_IOCTL_READDIR_BOTH和VFAT_IOCTL_READDIR_SHORT,返回值1表示已读取新目录条目,返回值0表示已到达目录末尾。
错误说明
- ENOENT
- 如果文件描述符fd指向已删除但仍处于打开状态的目录,则VFAT_IOCTL_READDIR_BOTH和VFAT_IOCTL_READDIR_SHORT返回此错误。
- ENOTDIR
- 如果文件描述符fd不引用目录,则VFAT_IOCTL_READDIR_BOTH和VFAT_IOCTL_READDIR_SHORT返回此错误。
- ENOTTY
- 文件描述符fd不引用FAT文件系统中的对象。
有关更多错误值,请参见ioctl(2)。
版本
VFAT_IOCTL_READDIR_BOTH和VFAT_IOCTL_READDIR_SHORT最早出现在Linux 2.0中。
FAT_IOCTL_GET_ATTRIBUTES和FAT_IOCTL_SET_ATTRIBUTES首次出现在Linux 2.6.12中。
FAT_IOCTL_GET_VOLUME_ID在Linux内核的版本3.11中引入。
遵循规范
该API是特定于Linux的。
示例
Toggling the archive flag
以下程序演示了ioctl(2)操纵文件属性的用法。该程序读取并显示文件的存档属性。反转属性值后,程序将读取并再次显示属性。
将程序应用到文件/ mnt / user / foo时,记录了以下内容:
# ./toggle_fat_archive_flag /mnt/user/foo Archive flag is set Toggling archive flag Archive flag is not set
Program source (toggle_fat_archive_flag.c)
#include <fcntl.h>
#include <linux/msdos_fs.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
/*
* Read file attributes of a file on a FAT filesystem.
* Output the state of the archive flag.
*/
static uint32_t
readattr(int fd)
{
uint32_t attr;
int ret;
ret = ioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, &attr);
if (ret == -1) {
perror("ioctl");
exit(EXIT_FAILURE);
}
if (attr & ATTR_ARCH)
printf("Archive flag is set\n");
else
printf("Archive flag is not set\n");
return attr;
}
int
main(int argc, char *argv[])
{
uint32_t attr;
int fd;
int ret;
if (argc != 2) {
printf("Usage: %s FILENAME\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
/*
* Read and display the FAT file attributes.
*/
attr = readattr(fd);
/*
* Invert archive attribute.
*/
printf("Toggling archive flag\n");
attr ha= ATTR_ARCH;
/*
* Write the changed FAT file attributes.
*/
ret = ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
if (ret == -1) {
perror("ioctl");
exit(EXIT_FAILURE);
}
/*
* Read and display the FAT file attributes.
*/
readattr(fd);
close(fd);
exit(EXIT_SUCCESS);
}
Reading the volume ID
以下程序演示了如何使用ioctl(2)显示FAT文件系统的卷ID。
将程序应用到目录/ mnt / user时,记录了以下输出:
$ ./display_fat_volume_id /mnt/user Volume ID 6443-6241
Program source (display_fat_volume_id.c)
#include <fcntl.h>
#include <linux/msdos_fs.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
uint32_t id;
int fd;
int ret;
if (argc != 2) {
printf("Usage: %s FILENAME\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
/*
* Read volume ID.
*/
ret = ioctl(fd, FAT_IOCTL_GET_VOLUME_ID, &id);
if (ret == -1) {
perror("ioctl");
exit(EXIT_FAILURE);
}
/*
* Format the output as two groups of 16 bits each.
*/
printf("Volume ID %04x-%04x\n", id >> 16, id & 0xFFFF);
close(fd);
exit(EXIT_SUCCESS);
}
Listing a directory
以下程序演示了如何使用ioctl(2)列出目录。
将程序应用到目录/ mnt / user时记录了以下内容:
$ ./fat_dir /mnt/user [char46] -> '' [char46]. -> '' ALONGFti1.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[])
{
struct __fat_dirent entry[2];
int fd;
int ret;
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);
}
另外参见
ioctl(2)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。

