diff options
Diffstat (limited to '')
-rw-r--r-- | man2/ioctl_fat.2 | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/man2/ioctl_fat.2 b/man2/ioctl_fat.2 new file mode 100644 index 0000000..67b5a2c --- /dev/null +++ b/man2/ioctl_fat.2 @@ -0,0 +1,489 @@ +.\" Copyright (C) 2014, Heinrich Schuchardt <xypron.glpk@gmx.de> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.TH ioctl_fat 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +ioctl_fat \- manipulating the FAT filesystem +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.BR "#include <linux/msdos_fs.h>" " /* Definition of [" V ] FAT_* " and" +.BR " ATTR_* " constants */" +.B #include <sys/ioctl.h> +.PP +.BI "int ioctl(int " fd ", FAT_IOCTL_GET_ATTRIBUTES, uint32_t *" attr ); +.BI "int ioctl(int " fd ", FAT_IOCTL_SET_ATTRIBUTES, uint32_t *" attr ); +.BI "int ioctl(int " fd ", FAT_IOCTL_GET_VOLUME_ID, uint32_t *" id ); +.BI "int ioctl(int " fd ", VFAT_IOCTL_READDIR_BOTH," +.BI " struct __fat_dirent " entry [2]); +.BI "int ioctl(int " fd ", VFAT_IOCTL_READDIR_SHORT," +.BI " struct __fat_dirent " entry [2]); +.fi +.SH DESCRIPTION +The +.BR ioctl (2) +system call can be used to read and write metadata of FAT filesystems that +are not accessible using other system calls. +.SS Reading and setting file attributes +Files and directories in the FAT filesystem possess an attribute bit mask that +can be read with +.B FAT_IOCTL_GET_ATTRIBUTES +and written with +.BR FAT_IOCTL_SET_ATTRIBUTES . +.PP +The +.I fd +argument contains a file descriptor for a file or directory. +It is sufficient to create the file descriptor by calling +.BR open (2) +with the +.B O_RDONLY +flag. +.PP +The +.I attr +argument contains a pointer to a bit mask. +The bits of the bit mask are: +.TP +.B ATTR_RO +This bit specifies that the file or directory is read-only. +.TP +.B ATTR_HIDDEN +This bit specifies that the file or directory is hidden. +.TP +.B ATTR_SYS +This bit specifies that the file is a system file. +.TP +.B ATTR_VOLUME +This bit specifies that the file is a volume label. +This attribute is read-only. +.TP +.B ATTR_DIR +This bit specifies that this is a directory. +This attribute is read-only. +.TP +.B ATTR_ARCH +This bit indicates that this file or directory should be archived. +It is set when a file is created or modified. +It is reset by an archiving system. +.PP +The zero value +.B ATTR_NONE +can be used to indicate that no attribute bit is set. +.SS Reading the volume ID +FAT filesystems are identified by a volume ID. +The volume ID can be read with +.BR FAT_IOCTL_GET_VOLUME_ID . +.PP +The +.I fd +argument can be a file descriptor for any file or directory of the +filesystem. +It is sufficient to create the file descriptor by calling +.BR open (2) +with the +.B O_RDONLY +flag. +.PP +The +.I id +argument is a pointer to the field that will be filled with the volume ID. +Typically the volume ID is displayed to the user as a group of two +16-bit fields: +.PP +.in +4n +.EX +printf("Volume ID %04x\-%04x\en", id >> 16, id & 0xFFFF); +.EE +.in +.SS Reading short filenames of a directory +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. +.PP +The short filenames in a directory can be read with +.BR VFAT_IOCTL_READDIR_SHORT . +.B VFAT_IOCTL_READDIR_BOTH +reads both the short and the long filenames. +.PP +The +.I fd +argument must be a file descriptor for a directory. +It is sufficient to create the file descriptor by calling +.BR open (2) +with the +.B O_RDONLY +flag. +The file descriptor can be used only once to iterate over the directory +entries by calling +.BR ioctl (2) +repeatedly. +.PP +The +.I entry +argument is a two-element array of the following structures: +.PP +.in +4n +.EX +struct __fat_dirent { + long d_ino; + __kernel_off_t d_off; + uint32_t short d_reclen; + char d_name[256]; +}; +.EE +.in +.PP +The first entry in the array is for the short filename. +The second entry is for the long filename. +.PP +The +.I d_ino +and +.I d_off +fields are filled only for long filenames. +The +.I d_ino +field holds the inode number of the directory. +The +.I 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. +.PP +The field +.I d_reclen +contains the length of the filename in the field +.IR 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 +.BR ioctl (2) +return value. +If no long filename exists, field +.I d_reclen +is set to 0 and +.I d_name +is a character string of length 0 for the long filename. +.SH RETURN VALUE +On error, \-1 is returned, and +.I errno +is set to indicate the error. +.PP +For +.B VFAT_IOCTL_READDIR_BOTH +and +.B VFAT_IOCTL_READDIR_SHORT +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. +.SH ERRORS +.TP +.B ENOENT +This error is returned by +.B VFAT_IOCTL_READDIR_BOTH +and +.B VFAT_IOCTL_READDIR_SHORT +if the file descriptor +.I fd +refers to a removed, but still open directory. +.TP +.B ENOTDIR +This error is returned by +.B VFAT_IOCTL_READDIR_BOTH +and +.B VFAT_IOCTL_READDIR_SHORT +if the file descriptor +.I fd +does not refer to a directory. +.TP +.B ENOTTY +The file descriptor +.I fd +does not refer to an object in a FAT filesystem. +.PP +For further error values, see +.BR ioctl (2). +.SH STANDARDS +Linux. +.SH HISTORY +.TP +.B VFAT_IOCTL_READDIR_BOTH +.TQ +.B VFAT_IOCTL_READDIR_SHORT +Linux 2.0. +.TP +.B FAT_IOCTL_GET_ATTRIBUTES +.TQ +.B FAT_IOCTL_SET_ATTRIBUTES +.\" just before we got Git history +Linux 2.6.12. +.TP +.B FAT_IOCTL_GET_VOLUME_ID +Linux 3.11. +.\" commit 6e5b93ee55d401f1619092fb675b57c28c9ed7ec +.SH EXAMPLES +.SS Toggling the archive flag +The following program demonstrates the usage of +.BR ioctl (2) +to manipulate file attributes. +The program reads and displays the archive attribute of a file. +After inverting the value of the attribute, +the program reads and displays the attribute again. +.PP +The following was recorded when applying the program for the file +.IR /mnt/user/foo : +.PP +.in +4n +.EX +# ./toggle_fat_archive_flag /mnt/user/foo +Archive flag is set +Toggling archive flag +Archive flag is not set +.EE +.in +.SS Program source (toggle_fat_archive_flag.c) +\& +.\" SRC BEGIN (toggle_fat_archive_flag.c) +.EX +#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) +{ + int ret; + uint32_t attr; +\& + 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\en"); + else + printf("Archive flag is not set\en"); +\& + return attr; +} +\& +int +main(int argc, char *argv[]) +{ + int fd; + int ret; + uint32_t attr; +\& + if (argc != 2) { + printf("Usage: %s FILENAME\en", 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\en"); + 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); +} +.EE +.\" SRC END +.SS Reading the volume ID +The following program demonstrates the use of +.BR ioctl (2) +to display the volume ID of a FAT filesystem. +.PP +The following output was recorded when applying the program for +directory +.IR /mnt/user : +.PP +.in +4n +.EX +$ ./display_fat_volume_id /mnt/user +Volume ID 6443\-6241 +.EE +.in +.SS Program source (display_fat_volume_id.c) +\& +.\" SRC BEGIN (display_fat_volume_id.c) +.EX +#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[]) +{ + int fd; + int ret; + uint32_t id; +\& + if (argc != 2) { + printf("Usage: %s FILENAME\en", 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\en", id >> 16, id & 0xFFFF); +\& + close(fd); +\& + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SS Listing a directory +The following program demonstrates the use of +.BR ioctl (2) +to list a directory. +.PP +The following was recorded when applying the program to the directory +.IR /mnt/user : +.PP +.in +4n +.EX +$ \fB./fat_dir /mnt/user\fP +\&. \-> \[aq]\[aq] +\&.. \-> \[aq]\[aq] +ALONGF\[ti]1.TXT \-> \[aq]a long filename.txt\[aq] +UPPER.TXT \-> \[aq]\[aq] +LOWER.TXT \-> \[aq]lower.txt\[aq] +.EE +.in +.\" +.SS Program source +.in +4n +.\" SRC BEGIN (ioctl_fat.c) +.EX +#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\en", 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 \-> \[aq]%s\[aq]\en", 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); +} +.EE +.\" SRC END +.in +.SH SEE ALSO +.BR ioctl (2) |