4 * directory handling functions for fat-based filesystems
6 * Written 1992,1993 by Werner Almesberger
8 * Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
10 * VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu>
11 * Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk>
12 * Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV
15 #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
17 #include <linux/version.h>
19 #include <linux/msdos_fs.h>
20 #include <linux/nls.h>
21 #include <linux/kernel.h>
22 #include <linux/errno.h>
23 #include <linux/stat.h>
24 #include <linux/string.h>
25 #include <linux/ioctl.h>
26 #include <linux/dirent.h>
28 #include <linux/ctype.h>
30 #include <asm/uaccess.h>
36 static ssize_t
fat_dir_read(struct file
* filp
, char * buf
,
37 size_t count
, loff_t
*ppos
)
42 struct file_operations fat_dir_operations
= {
43 NULL
, /* lseek - default */
44 fat_dir_read
, /* read */
45 NULL
, /* write - bad */
46 fat_readdir
, /* readdir */
47 NULL
, /* select v2.0.x/poll v2.1.x - default */
48 fat_dir_ioctl
, /* ioctl - default */
50 NULL
, /* no special open code */
52 NULL
, /* no special release code */
53 file_fsync
/* fsync */
57 * Convert Unicode 16 to UTF8, translated Unicode, or ASCII.
58 * If uni_xlate is enabled and we
59 * can't get a 1:1 conversion, use a colon as an escape character since
60 * it is normally invalid on the vfat filesystem. The following three
61 * characters are a sort of uuencoded 16 bit Unicode value. This lets
62 * us do a full dump and restore of Unicode filenames. We could get
63 * into some trouble with long Unicode names, but ignore that right now.
64 * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
67 uni16_to_x8(unsigned char *ascii
, unsigned char *uni
, int uni_xlate
,
68 struct nls_table
*nls
)
70 unsigned char *ip
, *op
;
72 unsigned char *uni_page
;
78 while (*ip
|| ip
[1]) {
82 uni_page
= nls
->page_uni2charset
[ch
];
83 if (uni_page
&& uni_page
[cl
]) {
89 op
[2] = fat_uni2esc
[val
& 0x3f];
91 op
[1] = fat_uni2esc
[val
& 0x3f];
93 *op
= fat_uni2esc
[val
& 0x3f];
99 /* We have some slack there, so it's OK */
110 static void dump_de(struct msdos_dir_entry
*de
)
113 unsigned char *p
= (unsigned char *) de
;
116 for (i
= 0; i
< 32; i
++, p
++) {
122 static int memicmp(const char *s1
, const char *s2
, int len
) {
123 while(len
--) if (tolower(*s1
++)!=tolower(*s2
++)) return 1;
128 * Return values: negative -> error, 0 -> not found, positive -> found,
129 * value is the total amount of slots, including the shortname entry.
132 struct inode
*inode
, const char *name
, int name_len
, int anycase
,
133 loff_t
*spos
, loff_t
*lpos
)
135 struct super_block
*sb
= inode
->i_sb
;
138 struct buffer_head
*bh
= NULL
;
139 struct msdos_dir_entry
*de
;
142 unsigned char long_slots
;
143 int uni_xlate
= MSDOS_SB(sb
)->options
.unicode_xlate
;
144 int utf8
= MSDOS_SB(sb
)->options
.utf8
;
145 unsigned char *unicode
= NULL
;
146 struct nls_table
*nls
= MSDOS_SB(sb
)->nls_io
;
150 if (fat_get_entry(inode
,&cpos
,&bh
,&de
,&ino
) == -1)
154 if (de
->name
[0] == (__s8
) DELETED_FLAG
)
156 if (de
->attr
!= ATTR_EXT
&& (de
->attr
& ATTR_VOLUME
))
158 if (de
->attr
!= ATTR_EXT
&& IS_FREE(de
->name
))
160 if (de
->attr
== ATTR_EXT
) {
161 struct msdos_dir_slot
*ds
;
167 unsigned char alias_checksum
;
170 unicode
= (unsigned char *)
171 __get_free_page(GFP_KERNEL
);
180 ds
= (struct msdos_dir_slot
*) de
;
185 if (slots
> 20 || !slots
) /* ceil(256 * 2 / 26) */
188 alias_checksum
= ds
->alias_checksum
;
194 memcpy(&unicode
[offset
], ds
->name0_4
, 10);
195 memcpy(&unicode
[offset
+10], ds
->name5_10
, 12);
196 memcpy(&unicode
[offset
+22], ds
->name11_12
, 4);
201 unicode
[offset
+1] = 0;
203 if (fat_get_entry(inode
,&cpos
,&bh
,&de
,&ino
)<0)
207 ds
= (struct msdos_dir_slot
*) de
;
208 if (ds
->attr
!= ATTR_EXT
)
210 if ((ds
->id
& ~0x40) != slot
)
212 if (ds
->alias_checksum
!= alias_checksum
)
215 if (de
->name
[0] == (__s8
) DELETED_FLAG
)
217 if (de
->attr
== ATTR_EXT
)
219 if (IS_FREE(de
->name
) || (de
->attr
& ATTR_VOLUME
))
221 for (sum
= 0, i
= 0; i
< 11; i
++)
222 sum
= (((sum
&1)<<7)|((sum
&0xfe)>>1)) + de
->name
[i
];
223 if (sum
!= alias_checksum
)
227 for (i
= 0, last
= 0; i
< 8;) {
228 if (!(c
= de
->name
[i
])) break;
229 if (c
>= 'A' && c
<= 'Z') c
+= 32;
230 if (c
== 0x05) c
= 0xE5;
231 if ((bufname
[i
++] = c
) != ' ')
236 for (i2
= 0; i2
< 3; i2
++) {
237 if (!(c
= de
->ext
[i2
])) break;
238 if (c
>= 'A' && c
<= 'Z') c
+= 32;
239 if ((bufname
[i
++] = c
) != ' ')
246 if ((!anycase
&& !memcmp(name
, bufname
, last
)) ||
247 (anycase
&& !memicmp(name
, bufname
, last
)))
250 char longname
[260]; /* 256 + 4 */
251 unsigned char long_len
;
253 ?utf8_wcstombs(longname
, (__u16
*) unicode
, 260)
254 :uni16_to_x8(longname
, unicode
, uni_xlate
, nls
);
255 if (long_len
!= name_len
)
257 if ((!anycase
&& !memcmp(name
, longname
, long_len
)) ||
258 (anycase
&& !memicmp(name
, longname
, long_len
)))
265 res
= long_slots
+ 1;
266 *spos
= cpos
- sizeof(struct msdos_dir_entry
);
267 *lpos
= cpos
- res
*sizeof(struct msdos_dir_entry
);
270 free_page((unsigned long) unicode
);
275 static int fat_readdirx(
283 struct super_block
*sb
= inode
->i_sb
;
284 int ino
,inum
,i
,i2
,last
;
286 struct buffer_head
*bh
;
287 struct msdos_dir_entry
*de
;
290 unsigned char long_slots
;
291 int uni_xlate
= MSDOS_SB(sb
)->options
.unicode_xlate
;
292 int utf8
= MSDOS_SB(sb
)->options
.utf8
;
293 unsigned char *unicode
= NULL
;
294 struct nls_table
*nls
= MSDOS_SB(sb
)->nls_io
;
296 char *ptname
= bufname
;
298 unsigned long *furrfu
= &lpos
;
302 /* Fake . and .. for the root directory. */
303 if (inode
->i_ino
== MSDOS_ROOT_INO
) {
305 if (filldir(dirent
, "..", cpos
+1, cpos
, MSDOS_ROOT_INO
) < 0)
316 if (cpos
& (sizeof(struct msdos_dir_entry
)-1))
322 if (fat_get_entry(inode
,&cpos
,&bh
,&de
,&ino
) == -1)
324 /* Check for long filename entry */
325 if (MSDOS_SB(sb
)->options
.isvfat
) {
326 if (de
->name
[0] == (__s8
) DELETED_FLAG
)
328 if (de
->attr
!= ATTR_EXT
&& (de
->attr
& ATTR_VOLUME
))
330 if (de
->attr
!= ATTR_EXT
&& IS_FREE(de
->name
))
333 if ((de
->attr
& ATTR_VOLUME
) || IS_FREE(de
->name
))
337 if (MSDOS_SB(sb
)->options
.isvfat
&& de
->attr
== ATTR_EXT
) {
338 struct msdos_dir_slot
*ds
;
344 unsigned char alias_checksum
;
347 unicode
= (unsigned char *)
348 __get_free_page(GFP_KERNEL
);
358 ds
= (struct msdos_dir_slot
*) de
;
363 if (slots
> 20 || !slots
) /* ceil(256 * 2 / 26) */
366 alias_checksum
= ds
->alias_checksum
;
372 memcpy(&unicode
[offset
], ds
->name0_4
, 10);
373 memcpy(&unicode
[offset
+10], ds
->name5_10
, 12);
374 memcpy(&unicode
[offset
+22], ds
->name11_12
, 4);
379 unicode
[offset
+1] = 0;
381 if (fat_get_entry(inode
,&cpos
,&bh
,&de
,&ino
) == -1)
385 ds
= (struct msdos_dir_slot
*) de
;
386 if (ds
->attr
!= ATTR_EXT
)
387 goto RecEnd
; /* XXX */
388 if ((ds
->id
& ~0x40) != slot
)
390 if (ds
->alias_checksum
!= alias_checksum
)
393 if (de
->name
[0] == (__s8
) DELETED_FLAG
)
395 if (de
->attr
== ATTR_EXT
)
397 if (IS_FREE(de
->name
) || (de
->attr
& ATTR_VOLUME
))
399 for (sum
= 0, i
= 0; i
< 11; i
++)
400 sum
= (((sum
&1)<<7)|((sum
&0xfe)>>1)) + de
->name
[i
];
401 if (sum
!= alias_checksum
)
405 if ((de
->attr
& ATTR_HIDDEN
) && MSDOS_SB(sb
)->options
.dotsOK
) {
409 for (i
= 0, last
= 0; i
< 8;) {
410 if (!(c
= de
->name
[i
])) break;
411 if (c
>= 'A' && c
<= 'Z') c
+= 32;
412 /* see namei.c, msdos_format_name */
413 if (c
== 0x05) c
= 0xE5;
414 if ((ptname
[i
++] = c
) != ' ')
419 for (i2
= 0; i2
< 3; i2
++) {
420 if (!(c
= de
->ext
[i2
])) break;
421 if (c
>= 'A' && c
<= 'Z') c
+= 32;
422 if ((ptname
[i
++] = c
) != ' ')
428 i
= last
+ dotoffset
;
430 lpos
= cpos
- (long_slots
+1)*sizeof(struct msdos_dir_entry
);
431 if (!memcmp(de
->name
,MSDOS_DOT
,11))
433 else if (!memcmp(de
->name
,MSDOS_DOTDOT
,11)) {
434 /* inum = fat_parent_ino(inode,0); */
435 inum
= filp
->f_dentry
->d_parent
->d_inode
->i_ino
;
437 struct inode
*tmp
= fat_iget(sb
, ino
);
442 inum
= iunique(sb
, MSDOS_ROOT_INO
);
445 if (!long_slots
||shortnames
) {
448 if (filldir(dirent
, bufname
, i
, *furrfu
, inum
) < 0)
452 unsigned char long_len
= utf8
453 ? utf8_wcstombs(longname
, (__u16
*) unicode
, 275)
454 : uni16_to_x8(longname
, unicode
, uni_xlate
, nls
);
456 memcpy(&longname
[long_len
+1], bufname
, i
);
459 if (filldir(dirent
, longname
, long_len
, *furrfu
, inum
) < 0)
473 free_page((unsigned long) unicode
);
478 int fat_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
480 struct inode
*inode
= filp
->f_dentry
->d_inode
;
481 return fat_readdirx(inode
, filp
, dirent
, filldir
, 0, 0);
484 static int vfat_ioctl_fill(
491 struct dirent
*d1
= (struct dirent
*)buf
;
492 struct dirent
*d2
= d1
+ 1;
496 get_user(len
, &d1
->d_reclen
);
501 if ((name_len
== 1 && name
[0] == '.') ||
502 (name_len
== 2 && name
[0] == '.' && name
[1] == '.')) {
509 if (len
!= name_len
) {
510 copy_to_user(d2
->d_name
, name
, len
);
511 put_user(0, d2
->d_name
+ len
);
512 put_user(len
, &d2
->d_reclen
);
513 put_user(ino
, &d2
->d_ino
);
514 put_user(offset
, &d2
->d_off
);
515 slen
= name_len
- len
;
516 copy_to_user(d1
->d_name
, name
+len
+1, slen
);
517 put_user(0, d1
->d_name
+slen
);
518 put_user(slen
, &d1
->d_reclen
);
520 put_user(0, d2
->d_name
);
521 put_user(0, &d2
->d_reclen
);
522 copy_to_user(d1
->d_name
, name
, len
);
523 put_user(0, d1
->d_name
+len
);
524 put_user(len
, &d1
->d_reclen
);
526 PRINTK(("FAT d1=%p d2=%p len=%d, name_len=%d\n",
527 d1
, d2
, len
, name_len
));
532 int fat_dir_ioctl(struct inode
* inode
, struct file
* filp
,
533 unsigned int cmd
, unsigned long arg
)
537 * We want to provide an interface for Samba to be able
538 * to get the short filename for a given long filename.
539 * Samba should use this ioctl instead of readdir() to
540 * get the information it needs.
543 case VFAT_IOCTL_READDIR_BOTH
: {
544 struct dirent
*d1
= (struct dirent
*)arg
;
545 err
= verify_area(VERIFY_WRITE
, d1
, sizeof(struct dirent
[2]));
548 put_user(0, &d1
->d_reclen
);
549 return fat_readdirx(inode
,filp
,(void *)arg
,
550 vfat_ioctl_fill
, 0, 1);
552 case VFAT_IOCTL_READDIR_SHORT
: {
553 struct dirent
*d1
= (struct dirent
*)arg
;
554 put_user(0, &d1
->d_reclen
);
555 err
= verify_area(VERIFY_WRITE
, d1
, sizeof(struct dirent
[2]));
558 return fat_readdirx(inode
,filp
,(void *)arg
,
559 vfat_ioctl_fill
, 1, 1);
562 /* forward ioctl to CVF extension */
563 if (MSDOS_SB(inode
->i_sb
)->cvf_format
&&
564 MSDOS_SB(inode
->i_sb
)->cvf_format
->cvf_dir_ioctl
)
565 return MSDOS_SB(inode
->i_sb
)->cvf_format
566 ->cvf_dir_ioctl(inode
,filp
,cmd
,arg
);
573 /***** See if directory is empty */
574 int fat_dir_empty(struct inode
*dir
)
577 struct buffer_head
*bh
;
578 struct msdos_dir_entry
*de
;
583 while (fat_get_entry(dir
,&pos
,&bh
,&de
,&ino
) > -1) {
584 /* Ignore vfat longname entries */
585 if (de
->attr
== ATTR_EXT
)
587 if (!IS_FREE(de
->name
) &&
588 strncmp(de
->name
,MSDOS_DOT
, MSDOS_NAME
) &&
589 strncmp(de
->name
,MSDOS_DOTDOT
, MSDOS_NAME
)) {
595 fat_brelse(dir
->i_sb
, bh
);
600 /* This assumes that size of cluster is above the 32*slots */
602 int fat_add_entries(struct inode
*dir
,int slots
, struct buffer_head
**bh
,
603 struct msdos_dir_entry
**de
, int *ino
)
605 struct super_block
*sb
= dir
->i_sb
;
608 struct buffer_head
*new_bh
;
613 while (fat_get_entry(dir
,&curr
,bh
,de
,ino
) > -1) {
614 if (IS_FREE((*de
)->name
)) {
622 if ((dir
->i_ino
== MSDOS_ROOT_INO
) && (MSDOS_SB(sb
)->fat_bits
!= 32))
624 new_bh
= fat_extend_dir(dir
);
627 fat_brelse(sb
, new_bh
);
628 do fat_get_entry(dir
,&curr
,bh
,de
,ino
); while (++row
<slots
);
632 int fat_new_dir(struct inode
*dir
, struct inode
*parent
, int is_vfat
)
634 struct super_block
*sb
= dir
->i_sb
;
635 struct buffer_head
*bh
;
636 struct msdos_dir_entry
*de
;
639 if ((bh
= fat_extend_dir(dir
)) == NULL
) return -ENOSPC
;
640 /* zeroed out, so... */
641 fat_date_unix2dos(dir
->i_mtime
,&time
,&date
);
642 de
= (struct msdos_dir_entry
*)&bh
->b_data
[0];
643 memcpy(de
[0].name
,MSDOS_DOT
,MSDOS_NAME
);
644 memcpy(de
[1].name
,MSDOS_DOTDOT
,MSDOS_NAME
);
645 de
[0].attr
= de
[1].attr
= ATTR_DIR
;
646 de
[0].time
= de
[1].time
= CT_LE_W(time
);
647 de
[0].date
= de
[1].date
= CT_LE_W(date
);
648 if (is_vfat
) { /* extra timestamps */
649 de
[0].ctime
= de
[1].ctime
= CT_LE_W(time
);
650 de
[0].adate
= de
[0].cdate
=
651 de
[1].adate
= de
[1].cdate
= CT_LE_W(date
);
653 de
[0].start
= CT_LE_W(MSDOS_I(dir
)->i_logstart
);
654 de
[0].starthi
= CT_LE_W(MSDOS_I(dir
)->i_logstart
>>16);
655 de
[1].start
= CT_LE_W(MSDOS_I(parent
)->i_logstart
);
656 de
[1].starthi
= CT_LE_W(MSDOS_I(parent
)->i_logstart
>>16);
657 fat_mark_buffer_dirty(sb
, bh
, 1);
659 dir
->i_atime
= dir
->i_ctime
= dir
->i_mtime
= CURRENT_TIME
;
660 mark_inode_dirty(dir
);
666 * Overrides for Emacs so that we follow Linus's tabbing style.
667 * Emacs will notice this stuff at the end of the file and automatically
668 * adjust the settings for this buffer only. This must remain at the end
670 * ---------------------------------------------------------------------------
673 * c-brace-imaginary-offset: 0
675 * c-argdecl-indent: 8
677 * c-continued-statement-offset: 8
678 * c-continued-brace-offset: 0