IOCTL_FAT - Linux手册页

时间:2019-08-20 17:58:53  来源:igfitidea点击:

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/