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