1IOCTL-FAT(2) Linux Programmer's Manual IOCTL-FAT(2)
2
3
4
6 ioctl_fat - manipulating the FAT filesystem
7
9 #include <linux/msdos_fs.h>
10 #include <sys/ioctl.h>
11
12 int ioctl(int fd, FAT_IOCTL_GET_ATTRIBUTES, uint32_t *attr);
13 int ioctl(int fd, FAT_IOCTL_SET_ATTRIBUTES, uint32_t *attr);
14 int ioctl(int fd, FAT_IOCTL_GET_VOLUME_ID, uint32_t *id);
15 int ioctl(int fd, VFAT_IOCTL_READDIR_BOTH,
16 struct __fat_dirent[2] entry);
17 int ioctl(int fd, VFAT_IOCTL_READDIR_SHORT,
18 struct __fat_dirent[2] entry);
19
21 The ioctl(2) system call can be used to read and write metadata of FAT
22 filesystems that are not accessible using other system calls.
23
24 Reading and setting file attributes
25 Files and directories in the FAT filesystem possess an attribute bit
26 mask that can be read with FAT_IOCTL_GET_ATTRIBUTES and written with
27 FAT_IOCTL_SET_ATTRIBUTES.
28
29 The fd argument contains a file descriptor for a file or directory. It
30 is sufficient to create the file descriptor by calling open(2) with the
31 O_RDONLY flag.
32
33 The attr argument contains a pointer to a bit mask. The bits of the
34 bit mask are:
35
36 ATTR_RO
37 This bit specifies that the file or directory is read-only.
38
39 ATTR_HIDDEN
40 This bit specifies that the file or directory is hidden.
41
42 ATTR_SYS
43 This bit specifies that the file is a system file.
44
45 ATTR_VOLUME
46 This bit specifies that the file is a volume label. This
47 attribute is read-only.
48
49 ATTR_DIR
50 This bit specifies that this is a directory. This attribute is
51 read-only.
52
53 ATTR_ARCH
54 This bit indicates that this file or directory should be
55 archived. It is set when a file is created or modified. It is
56 reset by an archiving system.
57
58 The zero value ATTR_NONE can be used to indicate that no attribute bit
59 is set.
60
61 Reading the volume ID
62 FAT filesystems are identified by a volume ID. The volume ID can be
63 read with FAT_IOCTL_GET_VOLUME_ID.
64
65 The fd argument can be a file descriptor for any file or directory of
66 the filesystem. It is sufficient to create the file descriptor by
67 calling open(2) with the O_RDONLY flag.
68
69 The id argument is a pointer to the field that will be filled with the
70 volume ID. Typically the volume ID is displayed to the user as a group
71 of two 16-bit fields:
72
73 printf("Volume ID %04x-%04x\n", id >> 16, id & 0xFFFF);
74
75 Reading short file names of a directory
76 A file or directory on a FAT filesystem always has a short filename
77 consisting of up to 8 capital letters, optionally followed by a period
78 and up to 3 capital letters for the file extension. If the actual
79 filename does not fit into this scheme, it is stored as a long filename
80 of up to 255 UTF-16 characters.
81
82 The short filenames in a directory can be read with VFAT_IOCTL_READ‐
83 DIR_SHORT. VFAT_IOCTL_READDIR_BOTH reads both the short and the long
84 filenames.
85
86 The fd argument must be a file descriptor for a directory. It is suf‐
87 ficient to create the file descriptor by calling open(2) with the
88 O_RDONLY flag. The file descriptor can be used only once to iterate
89 over the directory entries by calling ioctl(2) repeatedly.
90
91 The entry argument is a two-element array of the following structures:
92
93 struct __fat_dirent {
94 long d_ino;
95 __kernel_off_t d_off;
96 uint32_t short d_reclen;
97 char d_name[256];
98 };
99
100 The first entry in the array is for the short filename. The second
101 entry is for the long filename.
102
103 The d_ino and d_off fields are filled only for long filenames. The
104 d_ino field holds the inode number of the directory. The d_off field
105 holds the offset of the file entry in the directory. As these values
106 are not available for short filenames, the user code should simply
107 ignore them.
108
109 The field d_reclen contains the length of the filename in the field
110 d_name. To keep backward compatibility, a length of 0 for the short
111 filename signals that the end of the directory has been reached. How‐
112 ever, the preferred method for detecting the end of the directory is to
113 test the ioctl(2) return value. If no long filename exists, field
114 d_reclen is set to 0 and d_name is a character string of length 0 for
115 the long filename.
116
118 On error, -1 is returned, and errno is set to indicate the error.
119
120 For VFAT_IOCTL_READDIR_BOTH and VFAT_IOCTL_READDIR_SHORT a return value
121 of 1 signals that a new directory entry has been read and a return
122 value of 0 signals that the end of the directory has been reached.
123
125 ENOENT This error is returned by VFAT_IOCTL_READDIR_BOTH and
126 VFAT_IOCTL_READDIR_SHORT if the file descriptor fd refers to a
127 removed, but still open directory.
128
129 ENOTDIR
130 This error is returned by VFAT_IOCTL_READDIR_BOTH and
131 VFAT_IOCTL_READDIR_SHORT if the file descriptor fd does not
132 refer to a directory.
133
134 ENOTTY The file descriptor fd does not refer to an object in a FAT
135 filesystem.
136
137 For further error values, see ioctl(2).
138
140 VFAT_IOCTL_READDIR_BOTH and VFAT_IOCTL_READDIR_SHORT first appeared in
141 Linux 2.0.
142
143 FAT_IOCTL_GET_ATTRIBUTES and FAT_IOCTL_SET_ATTRIBUTES first appeared in
144 Linux 2.6.12.
145
146 FAT_IOCTL_GET_VOLUME_ID was introduced in version 3.11 of the Linux
147 kernel.
148
150 This API is Linux-specific.
151
153 Toggling the archive flag
154 The following program demonstrates the usage of ioctl(2) to manipulate
155 file attributes. The program reads and displays the archive attribute
156 of a file. After inverting the value of the attribute, the program
157 reads and displays the attribute again.
158
159 The following was recorded when applying the program for the file
160 /mnt/user/foo:
161
162 # ./toggle_fat_archive_flag /mnt/user/foo
163 Archive flag is set
164 Toggling archive flag
165 Archive flag is not set
166
167 Program source (toggle_fat_archive_flag.c)
168
169 #include <fcntl.h>
170 #include <linux/msdos_fs.h>
171 #include <stdint.h>
172 #include <stdio.h>
173 #include <stdlib.h>
174 #include <sys/ioctl.h>
175 #include <unistd.h>
176
177 /*
178 * Read file attributes of a file on a FAT filesystem.
179 * Output the state of the archive flag.
180 */
181 static uint32_t
182 readattr(int fd)
183 {
184 uint32_t attr;
185 int ret;
186
187 ret = ioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, &attr);
188 if (ret == -1) {
189 perror("ioctl");
190 exit(EXIT_FAILURE);
191 }
192
193 if (attr & ATTR_ARCH)
194 printf("Archive flag is set\n");
195 else
196 printf("Archive flag is not set\n");
197
198 return attr;
199 }
200
201 int
202 main(int argc, char *argv[])
203 {
204 uint32_t attr;
205 int fd;
206 int ret;
207
208 if (argc != 2) {
209 printf("Usage: %s FILENAME\n", argv[0]);
210 exit(EXIT_FAILURE);
211 }
212
213 fd = open(argv[1], O_RDONLY);
214 if (fd == -1) {
215 perror("open");
216 exit(EXIT_FAILURE);
217 }
218
219 /*
220 * Read and display the FAT file attributes.
221 */
222 attr = readattr(fd);
223
224 /*
225 * Invert archive attribute.
226 */
227 printf("Toggling archive flag\n");
228 attr ^= ATTR_ARCH;
229
230 /*
231 * Write the changed FAT file attributes.
232 */
233 ret = ioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
234 if (ret == -1) {
235 perror("ioctl");
236 exit(EXIT_FAILURE);
237 }
238
239 /*
240 * Read and display the FAT file attributes.
241 */
242 readattr(fd);
243
244 close(fd);
245
246 exit(EXIT_SUCCESS);
247 }
248
249 Reading the volume ID
250 The following program demonstrates the use of ioctl(2) to display the
251 volume ID of a FAT filesystem.
252
253 The following output was recorded when applying the program for direc‐
254 tory /mnt/user:
255
256 $ ./display_fat_volume_id /mnt/user
257 Volume ID 6443-6241
258
259 Program source (display_fat_volume_id.c)
260
261 #include <fcntl.h>
262 #include <linux/msdos_fs.h>
263 #include <stdint.h>
264 #include <stdio.h>
265 #include <stdlib.h>
266 #include <sys/ioctl.h>
267 #include <unistd.h>
268
269 int
270 main(int argc, char *argv[])
271 {
272 uint32_t id;
273 int fd;
274 int ret;
275
276 if (argc != 2) {
277 printf("Usage: %s FILENAME\n", argv[0]);
278 exit(EXIT_FAILURE);
279 }
280
281 fd = open(argv[1], O_RDONLY);
282 if (fd == -1) {
283 perror("open");
284 exit(EXIT_FAILURE);
285 }
286
287 /*
288 * Read volume ID.
289 */
290 ret = ioctl(fd, FAT_IOCTL_GET_VOLUME_ID, &id);
291 if (ret == -1) {
292 perror("ioctl");
293 exit(EXIT_FAILURE);
294 }
295
296 /*
297 * Format the output as two groups of 16 bits each.
298 */
299 printf("Volume ID %04x-%04x\n", id >> 16, id & 0xFFFF);
300
301 close(fd);
302
303 exit(EXIT_SUCCESS);
304 }
305
306 Listing a directory
307 The following program demonstrates the use of ioctl(2) to list a direc‐
308 tory.
309
310 The following was recorded when applying the program to the directory
311 /mnt/user:
312
313 $ ./fat_dir /mnt/user
314 . -> ''
315 .. -> ''
316 ALONGF~1.TXT -> 'a long filename.txt'
317 UPPER.TXT -> ''
318 LOWER.TXT -> 'lower.txt'
319
320 Program source
321 #include <fcntl.h>
322 #include <linux/msdos_fs.h>
323 #include <stdio.h>
324 #include <stdlib.h>
325 #include <sys/ioctl.h>
326 #include <unistd.h>
327
328 int
329 main(int argc, char *argv[])
330 {
331 struct __fat_dirent entry[2];
332 int fd;
333 int ret;
334
335 if (argc != 2) {
336 printf("Usage: %s DIRECTORY\n", argv[0]);
337 exit(EXIT_FAILURE);
338 }
339
340 /*
341 * Open file descriptor for the directory.
342 */
343 fd = open(argv[1], O_RDONLY | O_DIRECTORY);
344 if (fd == -1) {
345 perror("open");
346 exit(EXIT_FAILURE);
347 }
348
349 for (;;) {
350
351 /*
352 * Read next directory entry.
353 */
354 ret = ioctl( fd, VFAT_IOCTL_READDIR_BOTH, entry);
355
356 /*
357 * If an error occurs, the return value is -1.
358 * If the end of the directory list has been reached,
359 * the return value is 0.
360 * For backward compatibility the end of the directory
361 * list is also signaled by d_reclen == 0.
362 */
363 if (ret < 1)
364 break;
365
366 /*
367 * Write both the short name and the long name.
368 */
369 printf("%s -> '%s'\n", entry[0].d_name, entry[1].d_name);
370 }
371
372 if (ret == -1) {
373 perror("VFAT_IOCTL_READDIR_BOTH");
374 exit(EXIT_FAILURE);
375 }
376
377 /*
378 * Close the file descriptor.
379 */
380 close(fd);
381
382 exit(EXIT_SUCCESS);
383 }
384
386 ioctl(2)
387
389 This page is part of release 4.16 of the Linux man-pages project. A
390 description of the project, information about reporting bugs, and the
391 latest version of this page, can be found at
392 https://www.kernel.org/doc/man-pages/.
393
394
395
396Linux 2017-09-15 IOCTL-FAT(2)