ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / fs / fat / dir.c
1 /*
2  *  linux/fs/fat/dir.c
3  *
4  *  directory handling functions for fat-based filesystems
5  *
6  *  Written 1992,1993 by Werner Almesberger
7  *
8  *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
9  *
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
13  *  Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
14  */
15
16 #include <linux/slab.h>
17 #include <linux/time.h>
18 #include <linux/msdos_fs.h>
19 #include <linux/dirent.h>
20 #include <linux/smp_lock.h>
21 #include <linux/buffer_head.h>
22
23 #include <asm/uaccess.h>
24
25 struct file_operations fat_dir_operations = {
26         .read           = generic_read_dir,
27         .readdir        = fat_readdir,
28         .ioctl          = fat_dir_ioctl,
29         .fsync          = file_fsync,
30 };
31
32 /*
33  * Convert Unicode 16 to UTF8, translated Unicode, or ASCII.
34  * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
35  * colon as an escape character since it is normally invalid on the vfat
36  * filesystem. The following four characters are the hexadecimal digits
37  * of Unicode value. This lets us do a full dump and restore of Unicode
38  * filenames. We could get into some trouble with long Unicode names,
39  * but ignore that right now.
40  * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
41  */
42 static int
43 uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,
44             struct nls_table *nls)
45 {
46         wchar_t *ip, ec;
47         unsigned char *op, nc;
48         int charlen;
49         int k;
50
51         ip = uni;
52         op = ascii;
53
54         while (*ip) {
55                 ec = *ip++;
56                 if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) {
57                         op += charlen;
58                 } else {
59                         if (uni_xlate == 1) {
60                                 *op = ':';
61                                 for (k = 4; k > 0; k--) {
62                                         nc = ec & 0xF;
63                                         op[k] = nc > 9  ? nc + ('a' - 10)
64                                                         : nc + '0';
65                                         ec >>= 4;
66                                 }
67                                 op += 5;
68                         } else {
69                                 *op++ = '?';
70                         }
71                 }
72                 /* We have some slack there, so it's OK */
73                 if (op>ascii+256) {
74                         op = ascii + 256;
75                         break;
76                 }
77         }
78         *op = 0;
79         return (op - ascii);
80 }
81
82 #if 0
83 static void dump_de(struct msdos_dir_entry *de)
84 {
85         int i;
86         unsigned char *p = (unsigned char *) de;
87         printk("[");
88
89         for (i = 0; i < 32; i++, p++) {
90                 printk("%02x ", *p);
91         }
92         printk("]\n");
93 }
94 #endif
95
96 static inline unsigned char
97 fat_tolower(struct nls_table *t, unsigned char c)
98 {
99         unsigned char nc = t->charset2lower[c];
100
101         return nc ? nc : c;
102 }
103
104 static inline int
105 fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
106 {
107         int charlen;
108
109         charlen = t->char2uni(c, clen, uni);
110         if (charlen < 0) {
111                 *uni = 0x003f;  /* a question mark */
112                 charlen = 1;
113         }
114         return charlen;
115 }
116
117 static inline int
118 fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
119 {
120         int charlen;
121         wchar_t wc;
122
123         charlen = t->char2uni(c, clen, &wc);
124         if (charlen < 0) {
125                 *uni = 0x003f;  /* a question mark */
126                 charlen = 1;
127         } else if (charlen <= 1) {
128                 unsigned char nc = t->charset2lower[*c];
129                 
130                 if (!nc)
131                         nc = *c;
132                 
133                 if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) {
134                         *uni = 0x003f;  /* a question mark */
135                         charlen = 1;
136                 }
137         } else
138                 *uni = wc;
139         
140         return charlen;
141 }
142
143 static int
144 fat_strnicmp(struct nls_table *t, const unsigned char *s1,
145                                         const unsigned char *s2, int len)
146 {
147         while(len--)
148                 if (fat_tolower(t, *s1++) != fat_tolower(t, *s2++))
149                         return 1;
150
151         return 0;
152 }
153
154 static inline int
155 fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
156                   wchar_t *uni_buf, unsigned short opt, int lower)
157 {
158         int len = 0;
159
160         if (opt & VFAT_SFN_DISPLAY_LOWER)
161                 len =  fat_short2lower_uni(nls, buf, buf_size, uni_buf);
162         else if (opt & VFAT_SFN_DISPLAY_WIN95)
163                 len = fat_short2uni(nls, buf, buf_size, uni_buf);
164         else if (opt & VFAT_SFN_DISPLAY_WINNT) {
165                 if (lower)
166                         len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);
167                 else 
168                         len = fat_short2uni(nls, buf, buf_size, uni_buf);
169         } else
170                 len = fat_short2uni(nls, buf, buf_size, uni_buf);
171
172         return len;
173 }
174
175 /*
176  * Return values: negative -> error, 0 -> not found, positive -> found,
177  * value is the total amount of slots, including the shortname entry.
178  */
179 int fat_search_long(struct inode *inode, const unsigned char *name,
180                     int name_len, int anycase, loff_t *spos, loff_t *lpos)
181 {
182         struct super_block *sb = inode->i_sb;
183         struct buffer_head *bh = NULL;
184         struct msdos_dir_entry *de;
185         struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
186         struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
187         wchar_t bufuname[14];
188         unsigned char xlate_len, long_slots;
189         wchar_t *unicode = NULL;
190         unsigned char work[8], bufname[260];    /* 256 + 4 */
191         int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
192         int utf8 = MSDOS_SB(sb)->options.utf8;
193         unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
194         int chl, i, j, last_u, res = 0;
195         loff_t i_pos, cpos = 0;
196
197         while(1) {
198                 if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
199                         goto EODir;
200 parse_record:
201                 long_slots = 0;
202                 if (de->name[0] == DELETED_FLAG)
203                         continue;
204                 if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
205                         continue;
206                 if (de->attr != ATTR_EXT && IS_FREE(de->name))
207                         continue;
208                 if (de->attr == ATTR_EXT) {
209                         struct msdos_dir_slot *ds;
210                         unsigned char id;
211                         unsigned char slot;
212                         unsigned char slots;
213                         unsigned char sum;
214                         unsigned char alias_checksum;
215
216                         if (!unicode) {
217                                 unicode = (wchar_t *)
218                                         __get_free_page(GFP_KERNEL);
219                                 if (!unicode) {
220                                         brelse(bh);
221                                         return -ENOMEM;
222                                 }
223                         }
224 parse_long:
225                         slots = 0;
226                         ds = (struct msdos_dir_slot *) de;
227                         id = ds->id;
228                         if (!(id & 0x40))
229                                 continue;
230                         slots = id & ~0x40;
231                         if (slots > 20 || !slots)       /* ceil(256 * 2 / 26) */
232                                 continue;
233                         long_slots = slots;
234                         alias_checksum = ds->alias_checksum;
235
236                         slot = slots;
237                         while (1) {
238                                 int offset;
239
240                                 slot--;
241                                 offset = slot * 13;
242                                 fat16_towchar(unicode + offset, ds->name0_4, 5);
243                                 fat16_towchar(unicode + offset + 5, ds->name5_10, 6);
244                                 fat16_towchar(unicode + offset + 11, ds->name11_12, 2);
245
246                                 if (ds->id & 0x40) {
247                                         unicode[offset + 13] = 0;
248                                 }
249                                 if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos)<0)
250                                         goto EODir;
251                                 if (slot == 0)
252                                         break;
253                                 ds = (struct msdos_dir_slot *) de;
254                                 if (ds->attr !=  ATTR_EXT)
255                                         goto parse_record;
256                                 if ((ds->id & ~0x40) != slot)
257                                         goto parse_long;
258                                 if (ds->alias_checksum != alias_checksum)
259                                         goto parse_long;
260                         }
261                         if (de->name[0] == DELETED_FLAG)
262                                 continue;
263                         if (de->attr ==  ATTR_EXT)
264                                 goto parse_long;
265                         if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))
266                                 continue;
267                         for (sum = 0, i = 0; i < 11; i++)
268                                 sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
269                         if (sum != alias_checksum)
270                                 long_slots = 0;
271                 }
272
273                 memcpy(work, de->name, sizeof(de->name));
274                 /* see namei.c, msdos_format_name */
275                 if (work[0] == 0x05)
276                         work[0] = 0xE5;
277                 for (i = 0, j = 0, last_u = 0; i < 8;) {
278                         if (!work[i]) break;
279                         chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
280                                                 &bufuname[j++], opt_shortname,
281                                                 de->lcase & CASE_LOWER_BASE);
282                         if (chl <= 1) {
283                                 if (work[i] != ' ')
284                                         last_u = j;
285                         } else {
286                                 last_u = j;
287                         }
288                         i += chl;
289                 }
290                 j = last_u;
291                 fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
292                 for (i = 0; i < 3;) {
293                         if (!de->ext[i]) break;
294                         chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i,
295                                                 &bufuname[j++], opt_shortname,
296                                                 de->lcase & CASE_LOWER_EXT);
297                         if (chl <= 1) {
298                                 if (de->ext[i] != ' ')
299                                         last_u = j;
300                         } else {
301                                 last_u = j;
302                         }
303                         i += chl;
304                 }
305                 if (!last_u)
306                         continue;
307
308                 bufuname[last_u] = 0x0000;
309                 xlate_len = utf8
310                         ?utf8_wcstombs(bufname, bufuname, sizeof(bufname))
311                         :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
312                 if (xlate_len == name_len)
313                         if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
314                             (anycase && !fat_strnicmp(nls_io, name, bufname,
315                                                                 xlate_len)))
316                                 goto Found;
317
318                 if (long_slots) {
319                         xlate_len = utf8
320                                 ?utf8_wcstombs(bufname, unicode, sizeof(bufname))
321                                 :uni16_to_x8(bufname, unicode, uni_xlate, nls_io);
322                         if (xlate_len != name_len)
323                                 continue;
324                         if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
325                             (anycase && !fat_strnicmp(nls_io, name, bufname,
326                                                                 xlate_len)))
327                                 goto Found;
328                 }
329         }
330
331 Found:
332         res = long_slots + 1;
333         *spos = cpos - sizeof(struct msdos_dir_entry);
334         *lpos = cpos - res*sizeof(struct msdos_dir_entry);
335 EODir:
336         brelse(bh);
337         if (unicode) {
338                 free_page((unsigned long) unicode);
339         }
340         return res;
341 }
342
343 static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
344                         filldir_t filldir, int shortnames, int both)
345 {
346         struct super_block *sb = inode->i_sb;
347         struct buffer_head *bh;
348         struct msdos_dir_entry *de;
349         struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
350         struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
351         wchar_t bufuname[14];
352         unsigned char long_slots;
353         wchar_t *unicode = NULL;
354         unsigned char c, work[8], bufname[56], *ptname = bufname;
355         unsigned long lpos, dummy, *furrfu = &lpos;
356         int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
357         int isvfat = MSDOS_SB(sb)->options.isvfat;
358         int utf8 = MSDOS_SB(sb)->options.utf8;
359         int nocase = MSDOS_SB(sb)->options.nocase;
360         unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
361         unsigned long inum;
362         int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
363         loff_t i_pos, cpos;
364         int ret = 0;
365         
366         lock_kernel();
367
368         cpos = filp->f_pos;
369         /* Fake . and .. for the root directory. */
370         if (inode->i_ino == MSDOS_ROOT_INO) {
371                 while (cpos < 2) {
372                         if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0)
373                                 goto out;
374                         cpos++;
375                         filp->f_pos++;
376                 }
377                 if (cpos == 2) {
378                         dummy = 2;
379                         furrfu = &dummy;
380                         cpos = 0;
381                 }
382         }
383         if (cpos & (sizeof(struct msdos_dir_entry)-1)) {
384                 ret = -ENOENT;
385                 goto out;
386         }
387
388         bh = NULL;
389 GetNew:
390         long_slots = 0;
391         if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
392                 goto EODir;
393         /* Check for long filename entry */
394         if (isvfat) {
395                 if (de->name[0] == DELETED_FLAG)
396                         goto RecEnd;
397                 if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
398                         goto RecEnd;
399                 if (de->attr != ATTR_EXT && IS_FREE(de->name))
400                         goto RecEnd;
401         } else {
402                 if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))
403                         goto RecEnd;
404         }
405
406         if (isvfat && de->attr == ATTR_EXT) {
407                 struct msdos_dir_slot *ds;
408                 unsigned char id;
409                 unsigned char slot;
410                 unsigned char slots;
411                 unsigned char sum;
412                 unsigned char alias_checksum;
413
414                 if (!unicode) {
415                         unicode = (wchar_t *)
416                                 __get_free_page(GFP_KERNEL);
417                         if (!unicode) {
418                                 filp->f_pos = cpos;
419                                 brelse(bh);
420                                 ret = -ENOMEM;
421                                 goto out;
422                         }
423                 }
424 ParseLong:
425                 slots = 0;
426                 ds = (struct msdos_dir_slot *) de;
427                 id = ds->id;
428                 if (!(id & 0x40))
429                         goto RecEnd;
430                 slots = id & ~0x40;
431                 if (slots > 20 || !slots)       /* ceil(256 * 2 / 26) */
432                         goto RecEnd;
433                 long_slots = slots;
434                 alias_checksum = ds->alias_checksum;
435
436                 slot = slots;
437                 while (1) {
438                         int offset;
439
440                         slot--;
441                         offset = slot * 13;
442                         fat16_towchar(unicode + offset, ds->name0_4, 5);
443                         fat16_towchar(unicode + offset + 5, ds->name5_10, 6);
444                         fat16_towchar(unicode + offset + 11, ds->name11_12, 2);
445
446                         if (ds->id & 0x40) {
447                                 unicode[offset + 13] = 0;
448                         }
449                         if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
450                                 goto EODir;
451                         if (slot == 0)
452                                 break;
453                         ds = (struct msdos_dir_slot *) de;
454                         if (ds->attr !=  ATTR_EXT)
455                                 goto RecEnd;    /* XXX */
456                         if ((ds->id & ~0x40) != slot)
457                                 goto ParseLong;
458                         if (ds->alias_checksum != alias_checksum)
459                                 goto ParseLong;
460                 }
461                 if (de->name[0] == DELETED_FLAG)
462                         goto RecEnd;
463                 if (de->attr ==  ATTR_EXT)
464                         goto ParseLong;
465                 if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))
466                         goto RecEnd;
467                 for (sum = 0, i = 0; i < 11; i++)
468                         sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
469                 if (sum != alias_checksum)
470                         long_slots = 0;
471         }
472
473         if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
474                 *ptname++ = '.';
475                 dotoffset = 1;
476         }
477
478         memcpy(work, de->name, sizeof(de->name));
479         /* see namei.c, msdos_format_name */
480         if (work[0] == 0x05)
481                 work[0] = 0xE5;
482         for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {
483                 if (!(c = work[i])) break;
484                 chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
485                                         &bufuname[j++], opt_shortname,
486                                         de->lcase & CASE_LOWER_BASE);
487                 if (chl <= 1) {
488                         ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;
489                         if (c != ' ') {
490                                 last = i;
491                                 last_u = j;
492                         }
493                 } else {
494                         last_u = j;
495                         for (chi = 0; chi < chl && i < 8; chi++) {
496                                 ptname[i] = work[i];
497                                 i++; last = i;
498                         }
499                 }
500         }
501         i = last;
502         j = last_u;
503         fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
504         ptname[i++] = '.';
505         for (i2 = 0; i2 < 3;) {
506                 if (!(c = de->ext[i2])) break;
507                 chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2,
508                                         &bufuname[j++], opt_shortname,
509                                         de->lcase & CASE_LOWER_EXT);
510                 if (chl <= 1) {
511                         i2++;
512                         ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;
513                         if (c != ' ') {
514                                 last = i;
515                                 last_u = j;
516                         }
517                 } else {
518                         last_u = j;
519                         for (chi = 0; chi < chl && i2 < 3; chi++) {
520                                 ptname[i++] = de->ext[i2++];
521                                 last = i;
522                         }
523                 }
524         }
525         if (!last)
526                 goto RecEnd;
527
528         i = last + dotoffset;
529         j = last_u;
530
531         lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);
532         if (!memcmp(de->name,MSDOS_DOT,11))
533                 inum = inode->i_ino;
534         else if (!memcmp(de->name,MSDOS_DOTDOT,11)) {
535                 inum = parent_ino(filp->f_dentry);
536         } else {
537                 struct inode *tmp = fat_iget(sb, i_pos);
538                 if (tmp) {
539                         inum = tmp->i_ino;
540                         iput(tmp);
541                 } else
542                         inum = iunique(sb, MSDOS_ROOT_INO);
543         }
544
545         if (isvfat) {
546                 bufuname[j] = 0x0000;
547                 i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname))
548                          : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
549         }
550
551         if (!long_slots||shortnames) {
552                 if (both)
553                         bufname[i] = '\0';
554                 if (filldir(dirent, bufname, i, *furrfu, inum,
555                             (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
556                         goto FillFailed;
557         } else {
558                 unsigned char longname[275];
559                 int long_len = utf8
560                         ? utf8_wcstombs(longname, unicode, sizeof(longname))
561                         : uni16_to_x8(longname, unicode, uni_xlate,
562                                       nls_io);
563                 if (both) {
564                         memcpy(&longname[long_len+1], bufname, i);
565                         long_len += i;
566                 }
567                 if (filldir(dirent, longname, long_len, *furrfu, inum,
568                             (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
569                         goto FillFailed;
570         }
571
572 RecEnd:
573         furrfu = &lpos;
574         filp->f_pos = cpos;
575         goto GetNew;
576 EODir:
577         filp->f_pos = cpos;
578 FillFailed:
579         if (bh)
580                 brelse(bh);
581         if (unicode) {
582                 free_page((unsigned long) unicode);
583         }
584 out:
585         unlock_kernel();
586         return ret;
587 }
588
589 int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
590 {
591         struct inode *inode = filp->f_dentry->d_inode;
592         return fat_readdirx(inode, filp, dirent, filldir, 0, 0);
593 }
594
595 struct fat_ioctl_filldir_callback {
596         struct dirent __user *dirent;
597         int result;
598 };
599
600 static int fat_ioctl_filldir(void *__buf, const char * name, int name_len,
601                              loff_t offset, ino_t ino, unsigned int d_type)
602 {
603         struct fat_ioctl_filldir_callback *buf = __buf;
604         struct dirent __user *d1 = buf->dirent;
605         struct dirent __user *d2 = d1 + 1;
606         int len, slen;
607         int dotdir;
608
609         if (buf->result)
610                 return -EINVAL;
611         buf->result++;
612
613         if ((name_len == 1 && name[0] == '.') ||
614             (name_len == 2 && name[0] == '.' && name[1] == '.')) {
615                 dotdir = 1;
616                 len = name_len;
617         } else {
618                 dotdir = 0;
619                 len = strlen(name);
620         }
621         if (len != name_len) {
622                 slen = name_len - len;
623                 if (copy_to_user(d2->d_name, name, len)         ||
624                     put_user(0, d2->d_name + len)               ||
625                     put_user(len, &d2->d_reclen)                ||
626                     put_user(ino, &d2->d_ino)                   ||
627                     put_user(offset, &d2->d_off)                ||
628                     copy_to_user(d1->d_name, name+len+1, slen)  ||
629                     put_user(0, d1->d_name+slen)                ||
630                     put_user(slen, &d1->d_reclen))
631                         goto efault;
632         } else {
633                 if (put_user(0, d2->d_name)                     ||
634                     put_user(0, &d2->d_reclen)                  ||
635                     copy_to_user(d1->d_name, name, len)         ||
636                     put_user(0, d1->d_name+len)                 ||
637                     put_user(len, &d1->d_reclen))
638                         goto efault;
639         }
640         return 0;
641 efault:
642         buf->result = -EFAULT;
643         return -EFAULT;
644 }
645
646 int fat_dir_ioctl(struct inode * inode, struct file * filp,
647                   unsigned int cmd, unsigned long arg)
648 {
649         struct fat_ioctl_filldir_callback buf;
650         struct dirent __user *d1;
651         int ret, shortname, both;
652
653         switch (cmd) {
654         case VFAT_IOCTL_READDIR_SHORT:
655                 shortname = 1;
656                 both = 1;
657                 break;
658         case VFAT_IOCTL_READDIR_BOTH:
659                 shortname = 0;
660                 both = 1;
661                 break;
662         default:
663                 return -EINVAL;
664         }
665
666         d1 = (struct dirent __user *)arg;
667         if (!access_ok(VERIFY_WRITE, d1, sizeof(struct dirent[2])))
668                 return -EFAULT;
669         /*
670          * Yes, we don't need this put_user() absolutely. However old
671          * code didn't return the right value. So, app use this value,
672          * in order to check whether it is EOF.
673          */
674         if (put_user(0, &d1->d_reclen))
675                 return -EFAULT;
676
677         buf.dirent = d1;
678         buf.result = 0;
679         down(&inode->i_sem);
680         ret = -ENOENT;
681         if (!IS_DEADDIR(inode)) {
682                 ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir,
683                                    shortname, both);
684         }
685         up(&inode->i_sem);
686         if (ret >= 0)
687                 ret = buf.result;
688         return ret;
689 }
690
691 /* This assumes that size of cluster is above the 32*slots */
692
693 int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
694                   struct msdos_dir_entry **de, loff_t *i_pos)
695 {
696         struct super_block *sb = dir->i_sb;
697         loff_t offset, curr;
698         int row;
699         struct buffer_head *new_bh;
700
701         offset = curr = 0;
702         *bh = NULL;
703         row = 0;
704         while (fat_get_entry(dir, &curr, bh, de, i_pos) > -1) {
705                 /* check the maximum size of directory */
706                 if (curr >= FAT_MAX_DIR_SIZE) {
707                         brelse(*bh);
708                         return -ENOSPC;
709                 }
710
711                 if (IS_FREE((*de)->name)) {
712                         if (++row == slots)
713                                 return offset;
714                 } else {
715                         row = 0;
716                         offset = curr;
717                 }
718         }
719         if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32)) 
720                 return -ENOSPC;
721         new_bh = fat_extend_dir(dir);
722         if (IS_ERR(new_bh))
723                 return PTR_ERR(new_bh);
724         brelse(new_bh);
725         do {
726                 fat_get_entry(dir, &curr, bh, de, i_pos);
727         } while (++row < slots);
728
729         return offset;
730 }
731
732 int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
733 {
734         struct buffer_head *bh;
735         struct msdos_dir_entry *de;
736         __u16 date, time;
737
738         bh = fat_extend_dir(dir);
739         if (IS_ERR(bh))
740                 return PTR_ERR(bh);
741
742         /* zeroed out, so... */
743         fat_date_unix2dos(dir->i_mtime.tv_sec,&time,&date);
744         de = (struct msdos_dir_entry*)&bh->b_data[0];
745         memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
746         memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
747         de[0].attr = de[1].attr = ATTR_DIR;
748         de[0].time = de[1].time = CT_LE_W(time);
749         de[0].date = de[1].date = CT_LE_W(date);
750         if (is_vfat) {  /* extra timestamps */
751                 de[0].ctime = de[1].ctime = CT_LE_W(time);
752                 de[0].adate = de[0].cdate =
753                         de[1].adate = de[1].cdate = CT_LE_W(date);
754         }
755         de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
756         de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
757         de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart);
758         de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16);
759         mark_buffer_dirty(bh);
760         brelse(bh);
761         dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
762         mark_inode_dirty(dir);
763
764         return 0;
765 }
766
767 static int fat_get_short_entry(struct inode *dir, loff_t *pos,
768                                struct buffer_head **bh,
769                                struct msdos_dir_entry **de, loff_t *i_pos)
770 {
771         while (fat_get_entry(dir, pos, bh, de, i_pos) >= 0) {
772                 /* free entry or long name entry or volume label */
773                 if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
774                         return 0;
775         }
776         return -ENOENT;
777 }
778
779 /* See if directory is empty */
780 int fat_dir_empty(struct inode *dir)
781 {
782         struct buffer_head *bh;
783         struct msdos_dir_entry *de;
784         loff_t cpos, i_pos;
785         int result = 0;
786
787         bh = NULL;
788         cpos = 0;
789         while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
790                 if (strncmp(de->name, MSDOS_DOT   , MSDOS_NAME) &&
791                     strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
792                         result = -ENOTEMPTY;
793                         break;
794                 }
795         }
796         brelse(bh);
797         return result;
798 }
799
800 /*
801  * fat_subdirs counts the number of sub-directories of dir. It can be run
802  * on directories being created.
803  */
804 int fat_subdirs(struct inode *dir)
805 {
806         struct buffer_head *bh;
807         struct msdos_dir_entry *de;
808         loff_t cpos, i_pos;
809         int count = 0;
810
811         bh = NULL;
812         cpos = 0;
813         while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
814                 if (de->attr & ATTR_DIR)
815                         count++;
816         }
817         brelse(bh);
818         return count;
819 }
820
821 /*
822  * Scans a directory for a given file (name points to its formatted name).
823  * Returns an error code or zero.
824  */
825 int fat_scan(struct inode *dir, const unsigned char *name,
826              struct buffer_head **bh, struct msdos_dir_entry **de,
827              loff_t *i_pos)
828 {
829         loff_t cpos;
830
831         *bh = NULL;
832         cpos = 0;
833         while (fat_get_short_entry(dir, &cpos, bh, de, i_pos) >= 0) {
834                 if (!strncmp((*de)->name, name, MSDOS_NAME))
835                         return 0;
836         }
837         return -ENOENT;
838 }