16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/time.h>
22 #include <linux/kernel.h>
30 #define FAT_MAX_SHORT_SIZE ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1)
35 #define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1)
36 #define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t))
38 static inline unsigned char fat_tolower(
unsigned char c)
40 return ((c >=
'A') && (c <=
'Z')) ? c+32 :
c;
44 struct buffer_head *bh,
47 return ((loff_t)bh->b_blocknr << MSDOS_SB(sb)->dir_per_block_bits)
51 static inline void fat_dir_readahead(
struct inode *dir,
sector_t iblock,
56 struct buffer_head *bh;
66 bh = sb_find_get_block(sb, phys);
67 if (bh ==
NULL || !buffer_uptodate(bh)) {
69 sb_breadahead(sb, phys + sec);
84 static int fat__get_entry(
struct inode *dir, loff_t *
pos,
89 unsigned long mapped_blocks;
98 err =
fat_bmap(dir, iblock, &phys, &mapped_blocks, 0);
102 fat_dir_readahead(dir, iblock, phys);
104 *bh = sb_bread(sb, phys);
107 "Directory bread(block %llu) failed", (
llu)phys);
120 static inline int fat_get_entry(
struct inode *dir, loff_t *pos,
121 struct buffer_head **bh,
127 MSDOS_SB(dir->
i_sb)->dir_per_block - 1) {
132 return fat__get_entry(dir, pos, bh, de);
145 static int uni16_to_x8(
struct super_block *sb,
unsigned char *ascii,
146 const wchar_t *uni,
int len,
struct nls_table *nls)
148 int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
164 if (uni_xlate == 1) {
166 op = hex_byte_pack(op, ec >> 8);
167 op = hex_byte_pack(op, ec);
178 "filename was truncated while converting.");
185 static inline int fat_uni_to_x8(
struct super_block *sb,
const wchar_t *uni,
193 return uni16_to_x8(sb, buf, uni, size, sbi->
nls_io);
197 fat_short2uni(
struct nls_table *
t,
unsigned char *
c,
int clen,
wchar_t *uni)
201 charlen = t->
char2uni(c, clen, uni);
210 fat_short2lower_uni(
struct nls_table *t,
unsigned char *c,
211 int clen,
wchar_t *uni)
216 charlen = t->
char2uni(c, clen, &wc);
220 }
else if (charlen <= 1) {
239 wchar_t *uni_buf,
unsigned short opt,
int lower)
244 len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);
246 len = fat_short2uni(nls, buf, buf_size, uni_buf);
249 len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);
251 len = fat_short2uni(nls, buf, buf_size, uni_buf);
253 len = fat_short2uni(nls, buf, buf_size, uni_buf);
259 const unsigned char *
a,
int a_len,
260 const unsigned char *
b,
int b_len)
265 if (sbi->
options.name_check !=
's')
266 return !nls_strnicmp(sbi->
nls_io, a, b, a_len);
268 return !
memcmp(a, b, a_len);
283 static int fat_parse_long(
struct inode *dir, loff_t *pos,
285 wchar_t **
unicode,
unsigned char *nr_slots)
304 if (slots > 20 || !slots)
315 fat16_towchar(*unicode + offset, ds->
name0_4, 5);
316 fat16_towchar(*unicode + offset + 5, ds->
name5_10, 6);
317 fat16_towchar(*unicode + offset + 11, ds->
name11_12, 2);
320 (*unicode)[offset + 13] = 0;
321 if (fat_get_entry(dir, pos, bh, de) < 0)
328 if ((ds->
id & ~0x40) !=
slot)
356 unsigned char *
name,
int dot_hidden)
359 int isvfat = sbi->
options.isvfat;
360 int nocase = sbi->
options.nocase;
361 unsigned short opt_shortname = sbi->
options.shortname;
363 wchar_t uni_name[14];
365 unsigned char *ptname =
name;
366 int chi, chl,
i,
j,
k;
381 for (i = 0, j = 0; i < 8;) {
385 chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
386 &uni_name[j++], opt_shortname,
390 ptname[
i] = nocase ? c : fat_tolower(c);
401 for (chi = 0; chi < chl && i < 8; chi++, i++)
411 fat_short2uni(nls_disk,
".", 1, &uni_name[j++]);
421 chl = fat_shortname2uni(nls_disk, &work[k], MSDOS_NAME - k,
422 &uni_name[j++], opt_shortname,
427 ptname[
i] = nocase ? c : fat_tolower(c);
436 int offset =
min(chl, MSDOS_NAME-k);
451 name_len += dotoffset;
454 uni_name[uni_len] = 0x0000;
455 name_len = fat_uni_to_x8(sb, uni_name, name,
472 struct buffer_head *bh =
NULL;
474 unsigned char nr_slots;
475 wchar_t *unicode =
NULL;
482 if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
493 int status = fat_parse_long(inode, &cpos, &bh, &de,
494 &unicode, &nr_slots);
511 len = fat_parse_short(sb, de, bufname, 0);
516 if (fat_name_match(sbi, name, name_len, bufname, len))
524 len = fat_uni_to_x8(sb, unicode, longname, size);
525 if (fat_name_match(sbi, name, name_len, longname, len))
532 sinfo->
slot_off = cpos - nr_slots *
sizeof(*de);
536 sinfo->
i_pos = fat_make_i_pos(sb, sinfo->
bh, sinfo->
de);
561 struct buffer_head *bh;
563 unsigned char nr_slots;
564 wchar_t *unicode =
NULL;
566 int isvfat = sbi->
options.isvfat;
567 const char *fill_name =
NULL;
569 unsigned long lpos,
dummy, *furrfu = &lpos;
571 int short_len = 0, fill_len = 0;
580 if (filldir(dirent,
"..", cpos+1, cpos,
599 if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
607 if (isvfat && !short_only) {
620 int status = fat_parse_long(inode, &cpos, &bh, &de,
621 &unicode, &nr_slots);
636 int len = fat_uni_to_x8(sb, unicode, longname, size);
638 fill_name = longname;
646 short_len = fat_parse_short(sb, de, bufname, sbi->
options.dotsOK);
672 loff_t i_pos = fat_make_i_pos(sb, bh, de);
681 if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
700 static int fat_readdir(
struct file *filp,
void *dirent,
filldir_t filldir)
702 struct inode *inode = filp->
f_path.dentry->d_inode;
703 return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
706 #define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type) \
707 static int func(void *__buf, const char *name, int name_len, \
708 loff_t offset, u64 ino, unsigned int d_type) \
710 struct fat_ioctl_filldir_callback *buf = __buf; \
711 struct dirent_type __user *d1 = buf->dirent; \
712 struct dirent_type __user *d2 = d1 + 1; \
718 if (name != NULL) { \
720 if (name_len >= sizeof(d1->d_name)) \
721 name_len = sizeof(d1->d_name) - 1; \
723 if (put_user(0, d2->d_name) || \
724 put_user(0, &d2->d_reclen) || \
725 copy_to_user(d1->d_name, name, name_len) || \
726 put_user(0, d1->d_name + name_len) || \
727 put_user(name_len, &d1->d_reclen)) \
731 const char *longname = buf->longname; \
732 int long_len = buf->long_len; \
733 const char *shortname = buf->shortname; \
734 int short_len = buf->short_len; \
736 if (long_len >= sizeof(d1->d_name)) \
737 long_len = sizeof(d1->d_name) - 1; \
738 if (short_len >= sizeof(d1->d_name)) \
739 short_len = sizeof(d1->d_name) - 1; \
741 if (copy_to_user(d2->d_name, longname, long_len) || \
742 put_user(0, d2->d_name + long_len) || \
743 put_user(long_len, &d2->d_reclen) || \
744 put_user(ino, &d2->d_ino) || \
745 put_user(offset, &d2->d_off) || \
746 copy_to_user(d1->d_name, shortname, short_len) || \
747 put_user(0, d1->d_name + short_len) || \
748 put_user(short_len, &d1->d_reclen)) \
753 buf->result = -EFAULT; \
761 int short_only,
int both)
771 ret = __fat_readdir(inode, filp, &buf, filldir,
780 static long fat_dir_ioctl(
struct file *filp,
unsigned int cmd,
783 struct inode *inode = filp->
f_path.dentry->d_inode;
785 int short_only,
both;
810 return fat_ioctl_readdir(inode, filp, d1, fat_ioctl_filldir,
815 #define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2])
816 #define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2])
820 static
long fat_compat_dir_ioctl(
struct file *filp,
unsigned cmd,
823 struct inode *inode = filp->f_path.dentry->d_inode;
824 struct compat_dirent
__user *d1 = compat_ptr(arg);
825 int short_only,
both;
850 return fat_ioctl_readdir(inode, filp, d1, fat_compat_ioctl_filldir,
858 .readdir = fat_readdir,
859 .unlocked_ioctl = fat_dir_ioctl,
861 .compat_ioctl = fat_compat_dir_ioctl,
866 static int fat_get_short_entry(
struct inode *dir, loff_t *pos,
867 struct buffer_head **bh,
870 while (fat_get_entry(dir, pos, bh, de) >= 0) {
893 while (fat_get_short_entry(dir, &offset, bh, de) >= 0) {
904 struct buffer_head *bh;
911 while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
929 struct buffer_head *bh;
936 while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
948 int fat_scan(
struct inode *dir,
const unsigned char *name,
955 while (fat_get_short_entry(dir, &sinfo->
slot_off, &sinfo->
bh,
957 if (!
strncmp(sinfo->
de->name, name, MSDOS_NAME)) {
960 sinfo->
i_pos = fat_make_i_pos(sb, sinfo->
bh, sinfo->
de);
968 static int __fat_remove_entries(
struct inode *dir, loff_t pos,
int nr_slots)
971 struct buffer_head *bh;
973 int err = 0, orig_slots;
977 if (fat_get_entry(dir, &pos, &bh, &de) < 0) {
982 orig_slots = nr_slots;
984 while (nr_slots && de < endp) {
997 pos += ((orig_slots - nr_slots) *
sizeof(*de)) -
sizeof(*de);
1007 struct buffer_head *bh;
1008 int err = 0, nr_slots;
1038 err = __fat_remove_entries(dir, sinfo->
slot_off, nr_slots);
1041 "Couldn't remove the long name slots");
1049 mark_inode_dirty(dir);
1055 static int fat_zeroed_cluster(
struct inode *dir,
sector_t blknr,
int nr_used,
1056 struct buffer_head **bhs,
int nr_bhs)
1059 sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus;
1065 while (blknr < last_blknr) {
1066 bhs[
n] = sb_getblk(sb, blknr);
1072 set_buffer_uptodate(bhs[n]);
1083 for (i = 0; i <
n; i++)
1093 for (i = 0; i <
n; i++)
1099 for (i = 0; i <
n; i++)
1108 struct buffer_head *bhs[MAX_BUF_PER_PAGE];
1119 blknr = fat_clus_to_blknr(sbi, cluster);
1120 bhs[0] = sb_getblk(sb, blknr);
1146 fat_set_start(&de[0], cluster);
1147 fat_set_start(&de[1], MSDOS_I(dir)->i_logstart);
1150 set_buffer_uptodate(bhs[0]);
1153 err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE);
1166 static int fat_add_new_entries(
struct inode *dir,
void *slots,
int nr_slots,
1168 struct buffer_head **bh, loff_t *i_pos)
1172 struct buffer_head *bhs[MAX_BUF_PER_PAGE];
1173 sector_t blknr, start_blknr, last_blknr;
1174 unsigned long size, copy;
1197 start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]);
1199 while (blknr < last_blknr) {
1200 bhs[
n] = sb_getblk(sb, blknr);
1208 memcpy(bhs[n]->b_data, slots, copy);
1211 set_buffer_uptodate(bhs[n]);
1218 }
while (++i < *nr_cluster);
1225 *i_pos = fat_make_i_pos(sb, *bh, *de);
1228 err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE);
1239 for (i = 0; i <
n; i++)
1251 struct buffer_head *bh, *
prev, *bhs[3];
1253 int err, free_slots,
i, nr_bhs;
1259 free_slots = nr_bhs = 0;
1263 while (fat_get_entry(dir, &pos, &bh, &de) > -1) {
1271 bhs[nr_bhs] = prev = bh;
1275 if (free_slots == nr_slots)
1278 for (i = 0; i < nr_bhs; i++)
1281 free_slots = nr_bhs = 0;
1287 }
else if (MSDOS_I(dir)->i_start == 0) {
1289 MSDOS_I(dir)->i_pos);
1296 pos -= free_slots *
sizeof(*de);
1297 nr_slots -= free_slots;
1304 int size = free_slots *
sizeof(*de);
1306 int long_bhs = nr_bhs - (nr_slots == 0);
1309 for (i = 0; i < long_bhs; i++) {
1311 memcpy(bhs[i]->b_data + offset, slots, copy);
1319 if (!err && i < nr_bhs) {
1322 memcpy(bhs[i]->b_data + offset, slots, copy);
1327 for (i = 0; i < nr_bhs; i++)
1341 cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster,
1358 MSDOS_I(dir)->mmu_private += nr_cluster << sbi->
cluster_bits;
1363 sinfo->
i_pos = fat_make_i_pos(sb, sinfo->
bh, sinfo->
de);
1369 for (i = 0; i < nr_bhs; i++)
1376 __fat_remove_entries(dir, pos, free_slots);