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/。