LCOV - code coverage report
Current view: top level - lkbce/fs/fat - dir.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 441 869 50.7 %
Date: 2017-01-25 Functions: 20 30 66.7 %

          Line data    Source code
       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/module.h>
      17             : #include <linux/slab.h>
      18             : #include <linux/time.h>
      19             : #include <linux/buffer_head.h>
      20             : #include <linux/compat.h>
      21             : #include <asm/uaccess.h>
      22             : #include "fat.h"
      23             : 
      24             : /*
      25             :  * Maximum buffer size of short name.
      26             :  * [(MSDOS_NAME + '.') * max one char + nul]
      27             :  * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul]
      28             :  */
      29             : #define FAT_MAX_SHORT_SIZE      ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1)
      30             : /*
      31             :  * Maximum buffer size of unicode chars from slots.
      32             :  * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)]
      33             :  */
      34             : #define FAT_MAX_UNI_CHARS       ((MSDOS_SLOTS - 1) * 13 + 1)
      35             : #define FAT_MAX_UNI_SIZE        (FAT_MAX_UNI_CHARS * sizeof(wchar_t))
      36             : 
      37             : static inline loff_t fat_make_i_pos(struct super_block *sb,
      38             :                                     struct buffer_head *bh,
      39             :                                     struct msdos_dir_entry *de)
      40          10 : {
      41          50 :         return ((loff_t)bh->b_blocknr << MSDOS_SB(sb)->dir_per_block_bits)
      42             :                 | (de - (struct msdos_dir_entry *)bh->b_data);
      43             : }
      44             : 
      45             : static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
      46             :                                      sector_t phys)
      47          16 : {
      48          32 :         struct super_block *sb = dir->i_sb;
      49          64 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
      50          16 :         struct buffer_head *bh;
      51          16 :         int sec;
      52          16 : 
      53             :         /* This is not a first sector of cluster, or sec_per_clus == 1 */
      54          96 :         if ((iblock & (sbi->sec_per_clus - 1)) || sbi->sec_per_clus == 1)
      55          16 :                 return;
      56             :         /* root dir of FAT12/FAT16 */
      57          80 :         if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
      58          16 :                 return;
      59             : 
      60          32 :         bh = sb_find_get_block(sb, phys);
      61         112 :         if (bh == NULL || !buffer_uptodate(bh)) {
      62         144 :                 for (sec = 0; sec < sbi->sec_per_clus; sec++)
      63          48 :                         sb_breadahead(sb, phys + sec);
      64          32 :         }
      65          64 :         brelse(bh);
      66          16 : }
      67             : 
      68             : /* Returns the inode number of the directory entry at offset pos. If bh is
      69             :    non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
      70             :    returned in bh.
      71             :    AV. Most often we do it item-by-item. Makes sense to optimize.
      72             :    AV. OK, there we go: if both bh and de are non-NULL we assume that we just
      73             :    AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
      74             :    AV. It's done in fat_get_entry() (inlined), here the slow case lives.
      75             :    AV. Additionally, when we return -1 (i.e. reached the end of directory)
      76             :    AV. we make bh NULL.
      77             :  */
      78             : static int fat__get_entry(struct inode *dir, loff_t *pos,
      79             :                           struct buffer_head **bh, struct msdos_dir_entry **de)
      80             : {
      81          32 :         struct super_block *sb = dir->i_sb;
      82          32 :         sector_t phys, iblock;
      83          16 :         unsigned long mapped_blocks;
      84          16 :         int err, offset;
      85          16 : 
      86          16 : next:
      87          32 :         if (*bh)
      88          32 :                 brelse(*bh);
      89             : 
      90          32 :         *bh = NULL;
      91          64 :         iblock = *pos >> sb->s_blocksize_bits;
      92         192 :         err = fat_bmap(dir, iblock, &phys, &mapped_blocks, 0);
      93          64 :         if (err || !phys)
      94          16 :                 return -1;      /* beyond EOF or error */
      95             : 
      96          48 :         fat_dir_readahead(dir, iblock, phys);
      97             : 
      98          32 :         *bh = sb_bread(sb, phys);
      99          32 :         if (*bh == NULL) {
     100          16 :                 printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
     101             :                        (llu)phys);
     102             :                 /* skip this block */
     103          32 :                 *pos = (iblock + 1) << sb->s_blocksize_bits;
     104          16 :                 goto next;
     105             :         }
     106             : 
     107          32 :         offset = *pos & (sb->s_blocksize - 1);
     108          16 :         *pos += sizeof(struct msdos_dir_entry);
     109          16 :         *de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
     110             : 
     111          16 :         return 0;
     112             : }
     113             : 
     114             : static inline int fat_get_entry(struct inode *dir, loff_t *pos,
     115             :                                 struct buffer_head **bh,
     116             :                                 struct msdos_dir_entry **de)
     117           8 : {
     118           8 :         /* Fast stuff first */
     119          72 :         if (*bh && *de &&
     120             :             (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
     121           8 :                 *pos += sizeof(struct msdos_dir_entry);
     122           8 :                 (*de)++;
     123           8 :                 return 0;
     124             :         }
     125          56 :         return fat__get_entry(dir, pos, bh, de);
     126             : }
     127             : 
     128             : /*
     129             :  * Convert Unicode 16 to UTF-8, translated Unicode, or ASCII.
     130             :  * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
     131             :  * colon as an escape character since it is normally invalid on the vfat
     132             :  * filesystem. The following four characters are the hexadecimal digits
     133             :  * of Unicode value. This lets us do a full dump and restore of Unicode
     134             :  * filenames. We could get into some trouble with long Unicode names,
     135             :  * but ignore that right now.
     136             :  * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
     137             :  */
     138             : static int uni16_to_x8(unsigned char *ascii, const wchar_t *uni, int len,
     139             :                        int uni_xlate, struct nls_table *nls)
     140             : {
     141           6 :         const wchar_t *ip;
     142           6 :         wchar_t ec;
     143           6 :         unsigned char *op, nc;
     144           6 :         int charlen;
     145           6 :         int k;
     146           6 : 
     147          12 :         ip = uni;
     148          12 :         op = ascii;
     149           6 : 
     150          30 :         while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) {
     151          24 :                 ec = *ip++;
     152          24 :                 if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) {
     153           6 :                         op += charlen;
     154           6 :                         len -= charlen;
     155             :                 } else {
     156          12 :                         if (uni_xlate == 1) {
     157           6 :                                 *op = ':';
     158          30 :                                 for (k = 4; k > 0; k--) {
     159          18 :                                         nc = ec & 0xF;
     160          42 :                                         op[k] = nc > 9       ? nc + ('a' - 10)
     161             :                                                         : nc + '0';
     162           6 :                                         ec >>= 4;
     163             :                                 }
     164           6 :                                 op += 5;
     165           6 :                                 len -= 5;
     166             :                         } else {
     167          18 :                                 *op++ = '?';
     168           6 :                                 len--;
     169             :                         }
     170          12 :                 }
     171             :         }
     172             : 
     173          24 :         if (unlikely(*ip)) {
     174           6 :                 printk(KERN_WARNING "FAT: filename was truncated while "
     175             :                        "converting.");
     176             :         }
     177             : 
     178           6 :         *op = 0;
     179           6 :         return (op - ascii);
     180             : }
     181             : 
     182             : static inline int fat_uni_to_x8(struct msdos_sb_info *sbi, const wchar_t *uni,
     183             :                                 unsigned char *buf, int size)
     184             : {
     185          18 :         if (sbi->options.utf8)
     186          18 :                 return utf16s_to_utf8s(uni, FAT_MAX_UNI_CHARS,
     187             :                                 UTF16_HOST_ENDIAN, buf, size);
     188             :         else
     189          18 :                 return uni16_to_x8(buf, uni, size, sbi->options.unicode_xlate,
     190             :                                    sbi->nls_io);
     191             : }
     192             : 
     193             : static inline int
     194             : fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
     195             : {
     196             :         int charlen;
     197          21 : 
     198          21 :         charlen = t->char2uni(c, clen, uni);
     199          42 :         if (charlen < 0) {
     200          21 :                 *uni = 0x003f;  /* a question mark */
     201          21 :                 charlen = 1;
     202             :         }
     203          21 :         return charlen;
     204             : }
     205             : 
     206             : static inline int
     207             : fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
     208             : {
     209             :         int charlen;
     210          12 :         wchar_t wc;
     211          12 : 
     212          24 :         charlen = t->char2uni(c, clen, &wc);
     213          24 :         if (charlen < 0) {
     214          12 :                 *uni = 0x003f;  /* a question mark */
     215          12 :                 charlen = 1;
     216          24 :         } else if (charlen <= 1) {
     217          12 :                 unsigned char nc = t->charset2lower[*c];
     218             : 
     219          24 :                 if (!nc)
     220          12 :                         nc = *c;
     221             : 
     222          36 :                 if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) {
     223          12 :                         *uni = 0x003f;  /* a question mark */
     224          12 :                         charlen = 1;
     225             :                 }
     226             :         } else
     227          12 :                 *uni = wc;
     228             : 
     229          12 :         return charlen;
     230             : }
     231             : 
     232             : static inline int
     233             : fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
     234             :                   wchar_t *uni_buf, unsigned short opt, int lower)
     235             : {
     236           6 :         int len = 0;
     237           6 : 
     238          12 :         if (opt & VFAT_SFN_DISPLAY_LOWER)
     239          12 :                 len =  fat_short2lower_uni(nls, buf, buf_size, uni_buf);
     240          12 :         else if (opt & VFAT_SFN_DISPLAY_WIN95)
     241          12 :                 len = fat_short2uni(nls, buf, buf_size, uni_buf);
     242          12 :         else if (opt & VFAT_SFN_DISPLAY_WINNT) {
     243          12 :                 if (lower)
     244          12 :                         len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);
     245             :                 else
     246          12 :                         len = fat_short2uni(nls, buf, buf_size, uni_buf);
     247             :         } else
     248          12 :                 len = fat_short2uni(nls, buf, buf_size, uni_buf);
     249             : 
     250          30 :         return len;
     251             : }
     252             : 
     253             : static inline int fat_name_match(struct msdos_sb_info *sbi,
     254             :                                  const unsigned char *a, int a_len,
     255             :                                  const unsigned char *b, int b_len)
     256           0 : {
     257           0 :         if (a_len != b_len)
     258           0 :                 return 0;
     259             : 
     260           0 :         if (sbi->options.name_check != 's')
     261           0 :                 return !nls_strnicmp(sbi->nls_io, a, b, a_len);
     262             :         else
     263           0 :                 return !memcmp(a, b, a_len);
     264             : }
     265             : 
     266             : enum { PARSE_INVALID = 1, PARSE_NOT_LONGNAME, PARSE_EOF, };
     267             : 
     268             : /**
     269             :  * fat_parse_long - Parse extended directory entry.
     270             :  *
     271             :  * This function returns zero on success, negative value on error, or one of
     272             :  * the following:
     273             :  *
     274             :  * %PARSE_INVALID - Directory entry is invalid.
     275             :  * %PARSE_NOT_LONGNAME - Directory entry does not contain longname.
     276             :  * %PARSE_EOF - Directory has no more entries.
     277             :  */
     278             : static int fat_parse_long(struct inode *dir, loff_t *pos,
     279             :                           struct buffer_head **bh, struct msdos_dir_entry **de,
     280             :                           wchar_t **unicode, unsigned char *nr_slots)
     281           3 : {
     282           3 :         struct msdos_dir_slot *ds;
     283           3 :         unsigned char id, slot, slots, alias_checksum;
     284           3 : 
     285           9 :         if (!*unicode) {
     286           9 :                 *unicode = __getname();
     287           9 :                 if (!*unicode) {
     288           9 :                         brelse(*bh);
     289           6 :                         return -ENOMEM;
     290             :                 }
     291             :         }
     292             : parse_long:
     293           3 :         slots = 0;
     294           3 :         ds = (struct msdos_dir_slot *)*de;
     295           3 :         id = ds->id;
     296           9 :         if (!(id & 0x40))
     297           3 :                 return PARSE_INVALID;
     298           3 :         slots = id & ~0x40;
     299           6 :         if (slots > 20 || !slots)    /* ceil(256 * 2 / 26) */
     300           3 :                 return PARSE_INVALID;
     301           3 :         *nr_slots = slots;
     302           3 :         alias_checksum = ds->alias_checksum;
     303             : 
     304           3 :         slot = slots;
     305           3 :         while (1) {
     306             :                 int offset;
     307             : 
     308           3 :                 slot--;
     309           3 :                 offset = slot * 13;
     310           6 :                 fat16_towchar(*unicode + offset, ds->name0_4, 5);
     311           6 :                 fat16_towchar(*unicode + offset + 5, ds->name5_10, 6);
     312           6 :                 fat16_towchar(*unicode + offset + 11, ds->name11_12, 2);
     313             : 
     314           9 :                 if (ds->id & 0x40)
     315           3 :                         (*unicode)[offset + 13] = 0;
     316          15 :                 if (fat_get_entry(dir, pos, bh, de) < 0)
     317           3 :                         return PARSE_EOF;
     318           6 :                 if (slot == 0)
     319           3 :                         break;
     320           3 :                 ds = (struct msdos_dir_slot *)*de;
     321           9 :                 if (ds->attr != ATTR_EXT)
     322           3 :                         return PARSE_NOT_LONGNAME;
     323           9 :                 if ((ds->id & ~0x40) != slot)
     324           3 :                         goto parse_long;
     325           9 :                 if (ds->alias_checksum != alias_checksum)
     326           3 :                         goto parse_long;
     327           3 :         }
     328           9 :         if ((*de)->name[0] == DELETED_FLAG)
     329           3 :                 return PARSE_INVALID;
     330           9 :         if ((*de)->attr == ATTR_EXT)
     331           3 :                 goto parse_long;
     332          21 :         if (IS_FREE((*de)->name) || ((*de)->attr & ATTR_VOLUME))
     333           3 :                 return PARSE_INVALID;
     334          12 :         if (fat_checksum((*de)->name) != alias_checksum)
     335           3 :                 *nr_slots = 0;
     336             : 
     337           3 :         return 0;
     338             : }
     339             : 
     340             : /*
     341             :  * Return values: negative -> error, 0 -> not found, positive -> found,
     342             :  * value is the total amount of slots, including the shortname entry.
     343             :  */
     344             : int fat_search_long(struct inode *inode, const unsigned char *name,
     345             :                     int name_len, struct fat_slot_info *sinfo)
     346             : {
     347           0 :         struct super_block *sb = inode->i_sb;
     348           0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     349           0 :         struct buffer_head *bh = NULL;
     350           0 :         struct msdos_dir_entry *de;
     351           0 :         struct nls_table *nls_disk = sbi->nls_disk;
     352           0 :         unsigned char nr_slots;
     353           0 :         wchar_t bufuname[14];
     354           0 :         wchar_t *unicode = NULL;
     355           0 :         unsigned char work[MSDOS_NAME];
     356           0 :         unsigned char bufname[FAT_MAX_SHORT_SIZE];
     357           0 :         unsigned short opt_shortname = sbi->options.shortname;
     358           0 :         loff_t cpos = 0;
     359           0 :         int chl, i, j, last_u, err, len;
     360           0 : 
     361           0 :         err = -ENOENT;
     362           0 :         while (1) {
     363           0 :                 if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
     364           0 :                         goto end_of_dir;
     365           0 : parse_record:
     366           0 :                 nr_slots = 0;
     367           0 :                 if (de->name[0] == DELETED_FLAG)
     368           0 :                         continue;
     369           0 :                 if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
     370           0 :                         continue;
     371           0 :                 if (de->attr != ATTR_EXT && IS_FREE(de->name))
     372           0 :                         continue;
     373           0 :                 if (de->attr == ATTR_EXT) {
     374           0 :                         int status = fat_parse_long(inode, &cpos, &bh, &de,
     375           0 :                                                     &unicode, &nr_slots);
     376           0 :                         if (status < 0) {
     377           0 :                                 err = status;
     378           0 :                                 goto end_of_dir;
     379           0 :                         } else if (status == PARSE_INVALID)
     380           0 :                                 continue;
     381           0 :                         else if (status == PARSE_NOT_LONGNAME)
     382           0 :                                 goto parse_record;
     383           0 :                         else if (status == PARSE_EOF)
     384           0 :                                 goto end_of_dir;
     385             :                 }
     386             : 
     387           0 :                 memcpy(work, de->name, sizeof(de->name));
     388             :                 /* see namei.c, msdos_format_name */
     389           0 :                 if (work[0] == 0x05)
     390           0 :                         work[0] = 0xE5;
     391           0 :                 for (i = 0, j = 0, last_u = 0; i < 8;) {
     392           0 :                         if (!work[i])
     393           0 :                                 break;
     394           0 :                         chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
     395             :                                                 &bufuname[j++], opt_shortname,
     396             :                                                 de->lcase & CASE_LOWER_BASE);
     397           0 :                         if (chl <= 1) {
     398           0 :                                 if (work[i] != ' ')
     399           0 :                                         last_u = j;
     400             :                         } else {
     401           0 :                                 last_u = j;
     402             :                         }
     403           0 :                         i += chl;
     404           0 :                 }
     405           0 :                 j = last_u;
     406           0 :                 fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
     407           0 :                 for (i = 8; i < MSDOS_NAME;) {
     408           0 :                         if (!work[i])
     409           0 :                                 break;
     410           0 :                         chl = fat_shortname2uni(nls_disk, &work[i],
     411             :                                                 MSDOS_NAME - i,
     412             :                                                 &bufuname[j++], opt_shortname,
     413           0 :                                                 de->lcase & CASE_LOWER_EXT);
     414           0 :                         if (chl <= 1) {
     415           0 :                                 if (work[i] != ' ')
     416           0 :                                         last_u = j;
     417             :                         } else {
     418           0 :                                 last_u = j;
     419             :                         }
     420           0 :                         i += chl;
     421           0 :                 }
     422           0 :                 if (!last_u)
     423           0 :                         continue;
     424             : 
     425             :                 /* Compare shortname */
     426           0 :                 bufuname[last_u] = 0x0000;
     427           0 :                 len = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname));
     428           0 :                 if (fat_name_match(sbi, name, name_len, bufname, len))
     429           0 :                         goto found;
     430             : 
     431           0 :                 if (nr_slots) {
     432           0 :                         void *longname = unicode + FAT_MAX_UNI_CHARS;
     433           0 :                         int size = PATH_MAX - FAT_MAX_UNI_SIZE;
     434             : 
     435             :                         /* Compare longname */
     436           0 :                         len = fat_uni_to_x8(sbi, unicode, longname, size);
     437           0 :                         if (fat_name_match(sbi, name, name_len, longname, len))
     438           0 :                                 goto found;
     439             :                 }
     440           0 :         }
     441           0 : 
     442             : found:
     443           0 :         nr_slots++;     /* include the de */
     444           0 :         sinfo->slot_off = cpos - nr_slots * sizeof(*de);
     445           0 :         sinfo->nr_slots = nr_slots;
     446           0 :         sinfo->de = de;
     447           0 :         sinfo->bh = bh;
     448           0 :         sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
     449           0 :         err = 0;
     450             : end_of_dir:
     451           0 :         if (unicode)
     452           0 :                 __putname(unicode);
     453             : 
     454           0 :         return err;
     455             : }
     456           1 : 
     457             : EXPORT_SYMBOL_GPL(fat_search_long);
     458             : 
     459             : struct fat_ioctl_filldir_callback {
     460             :         void __user *dirent;
     461             :         int result;
     462             :         /* for dir ioctl */
     463             :         const char *longname;
     464             :         int long_len;
     465             :         const char *shortname;
     466             :         int short_len;
     467             : };
     468             : 
     469             : static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent,
     470             :                          filldir_t filldir, int short_only, int both)
     471             : {
     472           3 :         struct super_block *sb = inode->i_sb;
     473           9 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
     474           3 :         struct buffer_head *bh;
     475           3 :         struct msdos_dir_entry *de;
     476           6 :         struct nls_table *nls_disk = sbi->nls_disk;
     477           3 :         unsigned char nr_slots;
     478           3 :         wchar_t bufuname[14];
     479           6 :         wchar_t *unicode = NULL;
     480           3 :         unsigned char c, work[MSDOS_NAME];
     481           6 :         unsigned char bufname[FAT_MAX_SHORT_SIZE], *ptname = bufname;
     482           6 :         unsigned short opt_shortname = sbi->options.shortname;
     483           6 :         int isvfat = sbi->options.isvfat;
     484           6 :         int nocase = sbi->options.nocase;
     485           6 :         const char *fill_name = NULL;
     486           3 :         unsigned long inum;
     487           6 :         unsigned long lpos, dummy, *furrfu = &lpos;
     488           3 :         loff_t cpos;
     489           9 :         int chi, chl, i, i2, j, last, last_u, dotoffset = 0, fill_len = 0;
     490           6 :         int ret = 0;
     491           3 : 
     492           6 :         lock_super(sb);
     493           3 : 
     494           6 :         cpos = filp->f_pos;
     495           3 :         /* Fake . and .. for the root directory. */
     496           9 :         if (inode->i_ino == MSDOS_ROOT_INO) {
     497          12 :                 while (cpos < 2) {
     498          50 :                         if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0)
     499           9 :                                 goto out;
     500           6 :                         cpos++;
     501           6 :                         filp->f_pos++;
     502           6 :                 }
     503           9 :                 if (cpos == 2) {
     504           6 :                         dummy = 2;
     505           6 :                         furrfu = &dummy;
     506           6 :                         cpos = 0;
     507           3 :                 }
     508           3 :         }
     509          15 :         if (cpos & (sizeof(struct msdos_dir_entry) - 1)) {
     510           9 :                 ret = -ENOENT;
     511           9 :                 goto out;
     512           3 :         }
     513           3 : 
     514           9 :         bh = NULL;
     515           9 : get_new:
     516          18 :         if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
     517           6 :                 goto end_of_dir;
     518           3 : parse_record:
     519           6 :         nr_slots = 0;
     520           3 :         /*
     521           6 :          * Check for long filename entry, but if short_only, we don't
     522           3 :          * need to parse long filename.
     523           3 :          */
     524          15 :         if (isvfat && !short_only) {
     525           9 :                 if (de->name[0] == DELETED_FLAG)
     526           6 :                         goto record_end;
     527          21 :                 if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
     528           6 :                         goto record_end;
     529          24 :                 if (de->attr != ATTR_EXT && IS_FREE(de->name))
     530           6 :                         goto record_end;
     531             :         } else {
     532          21 :                 if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))
     533           3 :                         goto record_end;
     534             :         }
     535             : 
     536          15 :         if (isvfat && de->attr == ATTR_EXT) {
     537          18 :                 int status = fat_parse_long(inode, &cpos, &bh, &de,
     538             :                                             &unicode, &nr_slots);
     539           6 :                 if (status < 0) {
     540           3 :                         filp->f_pos = cpos;
     541           3 :                         ret = status;
     542           3 :                         goto out;
     543           6 :                 } else if (status == PARSE_INVALID)
     544           3 :                         goto record_end;
     545           6 :                 else if (status == PARSE_NOT_LONGNAME)
     546           3 :                         goto parse_record;
     547           6 :                 else if (status == PARSE_EOF)
     548           3 :                         goto end_of_dir;
     549             : 
     550           6 :                 if (nr_slots) {
     551           3 :                         void *longname = unicode + FAT_MAX_UNI_CHARS;
     552           3 :                         int size = PATH_MAX - FAT_MAX_UNI_SIZE;
     553          12 :                         int len = fat_uni_to_x8(sbi, unicode, longname, size);
     554             : 
     555           3 :                         fill_name = longname;
     556           3 :                         fill_len = len;
     557             :                         /* !both && !short_only, so we don't need shortname. */
     558           6 :                         if (!both)
     559           3 :                                 goto start_filldir;
     560             :                 }
     561             :         }
     562             : 
     563          18 :         if (sbi->options.dotsOK) {
     564           9 :                 ptname = bufname;
     565           9 :                 dotoffset = 0;
     566          27 :                 if (de->attr & ATTR_HIDDEN) {
     567          27 :                         *ptname++ = '.';
     568           9 :                         dotoffset = 1;
     569             :                 }
     570             :         }
     571             : 
     572           9 :         memcpy(work, de->name, sizeof(de->name));
     573             :         /* see namei.c, msdos_format_name */
     574          18 :         if (work[0] == 0x05)
     575           9 :                 work[0] = 0xE5;
     576          51 :         for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {
     577          12 :                 if (!(c = work[i]))
     578           6 :                         break;
     579          27 :                 chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,
     580             :                                         &bufuname[j++], opt_shortname,
     581             :                                         de->lcase & CASE_LOWER_BASE);
     582           9 :                 if (chl <= 1) {
     583          36 :                         ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;
     584           6 :                         if (c != ' ') {
     585           3 :                                 last = i;
     586           3 :                                 last_u = j;
     587             :                         }
     588             :                 } else {
     589           3 :                         last_u = j;
     590          21 :                         for (chi = 0; chi < chl && i < 8; chi++) {
     591           9 :                                 ptname[i] = work[i];
     592           9 :                                 i++; last = i;
     593             :                         }
     594             :                 }
     595             :         }
     596           3 :         i = last;
     597           3 :         j = last_u;
     598          18 :         fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);
     599           9 :         ptname[i++] = '.';
     600          12 :         for (i2 = 8; i2 < MSDOS_NAME;) {
     601          12 :                 if (!(c = work[i2]))
     602           6 :                         break;
     603          27 :                 chl = fat_shortname2uni(nls_disk, &work[i2], MSDOS_NAME - i2,
     604             :                                         &bufuname[j++], opt_shortname,
     605             :                                         de->lcase & CASE_LOWER_EXT);
     606           9 :                 if (chl <= 1) {
     607           3 :                         i2++;
     608          36 :                         ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;
     609           6 :                         if (c != ' ') {
     610           3 :                                 last = i;
     611           3 :                                 last_u = j;
     612             :                         }
     613             :                 } else {
     614           3 :                         last_u = j;
     615          21 :                         for (chi = 0; chi < chl && i2 < MSDOS_NAME; chi++) {
     616          21 :                                 ptname[i++] = work[i2++];
     617           6 :                                 last = i;
     618             :                         }
     619             :                 }
     620             :         }
     621           6 :         if (!last)
     622           3 :                 goto record_end;
     623           6 : 
     624           3 :         i = last + dotoffset;
     625           3 :         j = last_u;
     626             : 
     627           6 :         if (isvfat) {
     628           3 :                 bufuname[j] = 0x0000;
     629           9 :                 i = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname));
     630             :         }
     631          12 :         if (nr_slots) {
     632             :                 /* hack for fat_ioctl_filldir() */
     633           6 :                 struct fat_ioctl_filldir_callback *p = dirent;
     634             : 
     635           6 :                 p->longname = fill_name;
     636           6 :                 p->long_len = fill_len;
     637           6 :                 p->shortname = bufname;
     638           6 :                 p->short_len = i;
     639           6 :                 fill_name = NULL;
     640           6 :                 fill_len = 0;
     641             :         } else {
     642           6 :                 fill_name = bufname;
     643           6 :                 fill_len = i;
     644             :         }
     645           6 : 
     646             : start_filldir:
     647           9 :         lpos = cpos - (nr_slots + 1) * sizeof(struct msdos_dir_entry);
     648          27 :         if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
     649           9 :                 inum = inode->i_ino;
     650          27 :         else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
     651          18 :                 inum = parent_ino(filp->f_path.dentry);
     652             :         } else {
     653          21 :                 loff_t i_pos = fat_make_i_pos(sb, bh, de);
     654           9 :                 struct inode *tmp = fat_iget(sb, i_pos);
     655           6 :                 if (tmp) {
     656           3 :                         inum = tmp->i_ino;
     657           3 :                         iput(tmp);
     658             :                 } else
     659           3 :                         inum = iunique(sb, MSDOS_ROOT_INO);
     660             :         }
     661             : 
     662         211 :         if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
     663          75 :                     (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
     664           7 :                 goto fill_failed;
     665             : 
     666             : record_end:
     667          15 :         furrfu = &lpos;
     668          22 :         filp->f_pos = cpos;
     669          15 :         goto get_new;
     670           6 : end_of_dir:
     671           6 :         filp->f_pos = cpos;
     672           6 : fill_failed:
     673          26 :         brelse(bh);
     674           6 :         if (unicode)
     675           3 :                 __putname(unicode);
     676             : out:
     677          14 :         unlock_super(sb);
     678          14 :         return ret;
     679             : }
     680           3 : 
     681             : static int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
     682             : {
     683           1 :         struct inode *inode = filp->f_path.dentry->d_inode;
     684           6 :         return __fat_readdir(inode, filp, dirent, filldir, 0, 0);
     685             : }
     686           1 : 
     687           1 : #define FAT_IOCTL_FILLDIR_FUNC(func, dirent_type)                          \
     688             : static int func(void *__buf, const char *name, int name_len,               \
     689             :                              loff_t offset, u64 ino, unsigned int d_type)  \
     690             : {                                                                          \
     691             :         struct fat_ioctl_filldir_callback *buf = __buf;                    \
     692             :         struct dirent_type __user *d1 = buf->dirent;                    \
     693             :         struct dirent_type __user *d2 = d1 + 1;                            \
     694             :                                                                            \
     695             :         if (buf->result)                                                \
     696             :                 return -EINVAL;                                            \
     697             :         buf->result++;                                                          \
     698             :                                                                            \
     699             :         if (name != NULL) {                                                \
     700             :                 /* dirent has only short name */                           \
     701             :                 if (name_len >= sizeof(d1->d_name))                          \
     702             :                         name_len = sizeof(d1->d_name) - 1;              \
     703             :                                                                            \
     704             :                 if (put_user(0, d2->d_name)                  ||         \
     705             :                     put_user(0, &d2->d_reclen)                   ||         \
     706             :                     copy_to_user(d1->d_name, name, name_len) ||         \
     707             :                     put_user(0, d1->d_name + name_len)               ||         \
     708             :                     put_user(name_len, &d1->d_reclen))                      \
     709             :                         goto efault;                                       \
     710             :         } else {                                                           \
     711             :                 /* dirent has short and long name */                       \
     712             :                 const char *longname = buf->longname;                           \
     713             :                 int long_len = buf->long_len;                                   \
     714             :                 const char *shortname = buf->shortname;                         \
     715             :                 int short_len = buf->short_len;                                 \
     716             :                                                                            \
     717             :                 if (long_len >= sizeof(d1->d_name))                          \
     718             :                         long_len = sizeof(d1->d_name) - 1;              \
     719             :                 if (short_len >= sizeof(d1->d_name))                         \
     720             :                         short_len = sizeof(d1->d_name) - 1;             \
     721             :                                                                            \
     722             :                 if (copy_to_user(d2->d_name, longname, long_len)     || \
     723             :                     put_user(0, d2->d_name + long_len)                       || \
     724             :                     put_user(long_len, &d2->d_reclen)                    || \
     725             :                     put_user(ino, &d2->d_ino)                            || \
     726             :                     put_user(offset, &d2->d_off)                 || \
     727             :                     copy_to_user(d1->d_name, shortname, short_len)   || \
     728             :                     put_user(0, d1->d_name + short_len)                      || \
     729             :                     put_user(short_len, &d1->d_reclen))                     \
     730             :                         goto efault;                                       \
     731             :         }                                                                  \
     732             :         return 0;                                                          \
     733             : efault:                                                                    \
     734             :         buf->result = -EFAULT;                                                  \
     735             :         return -EFAULT;                                                    \
     736             : }
     737             : 
     738        1056 : FAT_IOCTL_FILLDIR_FUNC(fat_ioctl_filldir, __fat_dirent)
     739         138 : 
     740             : static int fat_ioctl_readdir(struct inode *inode, struct file *filp,
     741           6 :                              void __user *dirent, filldir_t filldir,
     742           6 :                              int short_only, int both)
     743           6 : {
     744           6 :         struct fat_ioctl_filldir_callback buf;
     745           8 :         int ret;
     746           8 : 
     747           8 :         buf.dirent = dirent;
     748           8 :         buf.result = 0;
     749           8 :         mutex_lock(&inode->i_mutex);
     750           8 :         ret = -ENOENT;
     751          10 :         if (!IS_DEADDIR(inode)) {
     752          18 :                 ret = __fat_readdir(inode, filp, &buf, filldir,
     753           6 :                                     short_only, both);
     754           6 :         }
     755          10 :         mutex_unlock(&inode->i_mutex);
     756          14 :         if (ret >= 0)
     757          10 :                 ret = buf.result;
     758          10 :         return ret;
     759           6 : }
     760           6 : 
     761           6 : static int fat_dir_ioctl(struct inode *inode, struct file *filp,
     762           6 :                          unsigned int cmd, unsigned long arg)
     763           6 : {
     764           8 :         struct __fat_dirent __user *d1 = (struct __fat_dirent __user *)arg;
     765           7 :         int short_only, both;
     766           7 : 
     767           7 :         switch (cmd) {
     768          10 :         case VFAT_IOCTL_READDIR_SHORT:
     769           8 :                 short_only = 1;
     770           8 :                 both = 0;
     771           2 :                 break;
     772           5 :         case VFAT_IOCTL_READDIR_BOTH:
     773           2 :                 short_only = 0;
     774           2 :                 both = 1;
     775           1 :                 break;
     776           2 :         default:
     777           6 :                 return fat_generic_ioctl(inode, filp, cmd, arg);
     778             :         }
     779             : 
     780           7 :         if (!access_ok(VERIFY_WRITE, d1, sizeof(struct __fat_dirent[2])))
     781           1 :                 return -EFAULT;
     782             :         /*
     783             :          * Yes, we don't need this put_user() absolutely. However old
     784             :          * code didn't return the right value. So, app use this value,
     785             :          * in order to check whether it is EOF.
     786             :          */
     787          10 :         if (put_user(0, &d1->d_reclen))
     788           2 :                 return -EFAULT;
     789             : 
     790           4 :         return fat_ioctl_readdir(inode, filp, d1, fat_ioctl_filldir,
     791             :                                  short_only, both);
     792             : }
     793             : 
     794             : #ifdef CONFIG_COMPAT
     795             : #define VFAT_IOCTL_READDIR_BOTH32       _IOR('r', 1, struct compat_dirent[2])
     796             : #define VFAT_IOCTL_READDIR_SHORT32      _IOR('r', 2, struct compat_dirent[2])
     797             : 
     798        1044 : FAT_IOCTL_FILLDIR_FUNC(fat_compat_ioctl_filldir, compat_dirent)
     799         138 : 
     800             : static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
     801           6 :                                  unsigned long arg)
     802           7 : {
     803           8 :         struct inode *inode = filp->f_path.dentry->d_inode;
     804          10 :         struct compat_dirent __user *d1 = compat_ptr(arg);
     805           7 :         int short_only, both;
     806           7 : 
     807           7 :         switch (cmd) {
     808          10 :         case VFAT_IOCTL_READDIR_SHORT32:
     809           8 :                 short_only = 1;
     810           8 :                 both = 0;
     811           8 :                 break;
     812          11 :         case VFAT_IOCTL_READDIR_BOTH32:
     813           8 :                 short_only = 0;
     814           7 :                 both = 1;
     815           7 :                 break;
     816           8 :         default:
     817           8 :                 return -ENOIOCTLCMD;
     818           6 :         }
     819           6 : 
     820          13 :         if (!access_ok(VERIFY_WRITE, d1, sizeof(struct compat_dirent[2])))
     821           7 :                 return -EFAULT;
     822           6 :         /*
     823           6 :          * Yes, we don't need this put_user() absolutely. However old
     824           6 :          * code didn't return the right value. So, app use this value,
     825           6 :          * in order to check whether it is EOF.
     826           6 :          */
     827          16 :         if (put_user(0, &d1->d_reclen))
     828           8 :                 return -EFAULT;
     829           6 : 
     830          10 :         return fat_ioctl_readdir(inode, filp, d1, fat_compat_ioctl_filldir,
     831             :                                  short_only, both);
     832             : }
     833             : #endif /* CONFIG_COMPAT */
     834             : 
     835           1 : const struct file_operations fat_dir_operations = {
     836             :         .llseek         = generic_file_llseek,
     837             :         .read           = generic_read_dir,
     838             :         .readdir        = fat_readdir,
     839             :         .ioctl          = fat_dir_ioctl,
     840             : #ifdef CONFIG_COMPAT
     841             :         .compat_ioctl   = fat_compat_dir_ioctl,
     842             : #endif
     843             :         .fsync          = fat_file_fsync,
     844             : };
     845             : 
     846             : static int fat_get_short_entry(struct inode *dir, loff_t *pos,
     847             :                                struct buffer_head **bh,
     848             :                                struct msdos_dir_entry **de)
     849           2 : {
     850          12 :         while (fat_get_entry(dir, pos, bh, de) >= 0) {
     851           2 :                 /* free entry or long name entry or volume label */
     852          16 :                 if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
     853           2 :                         return 0;
     854             :         }
     855           2 :         return -ENOENT;
     856             : }
     857           2 : 
     858             : /*
     859             :  * The ".." entry can not provide the "struct fat_slot_info" informations
     860             :  * for inode. So, this function provide the some informations only.
     861             :  */
     862             : int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
     863             :                          struct msdos_dir_entry **de, loff_t *i_pos)
     864             : {
     865           1 :         loff_t offset;
     866           1 : 
     867           2 :         offset = 0;
     868           1 :         *bh = NULL;
     869           5 :         while (fat_get_short_entry(dir, &offset, bh, de) >= 0) {
     870           4 :                 if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME)) {
     871           3 :                         *i_pos = fat_make_i_pos(dir->i_sb, *bh, *de);
     872           1 :                         return 0;
     873             :                 }
     874             :         }
     875           1 :         return -ENOENT;
     876           1 : }
     877             : 
     878             : EXPORT_SYMBOL_GPL(fat_get_dotdot_entry);
     879             : 
     880             : /* See if directory is empty */
     881             : int fat_dir_empty(struct inode *dir)
     882             : {
     883           0 :         struct buffer_head *bh;
     884           0 :         struct msdos_dir_entry *de;
     885           0 :         loff_t cpos;
     886           0 :         int result = 0;
     887           0 : 
     888           0 :         bh = NULL;
     889           0 :         cpos = 0;
     890           0 :         while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
     891           0 :                 if (strncmp(de->name, MSDOS_DOT   , MSDOS_NAME) &&
     892           0 :                     strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
     893           0 :                         result = -ENOTEMPTY;
     894           0 :                         break;
     895             :                 }
     896           0 :         }
     897           0 :         brelse(bh);
     898           0 :         return result;
     899             : }
     900             : 
     901           0 : EXPORT_SYMBOL_GPL(fat_dir_empty);
     902             : 
     903             : /*
     904             :  * fat_subdirs counts the number of sub-directories of dir. It can be run
     905             :  * on directories being created.
     906             :  */
     907             : int fat_subdirs(struct inode *dir)
     908             : {
     909           1 :         struct buffer_head *bh;
     910           1 :         struct msdos_dir_entry *de;
     911           1 :         loff_t cpos;
     912           2 :         int count = 0;
     913           1 : 
     914           1 :         bh = NULL;
     915           1 :         cpos = 0;
     916           5 :         while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
     917           4 :                 if (de->attr & ATTR_DIR)
     918           2 :                         count++;
     919             :         }
     920           2 :         brelse(bh);
     921           1 :         return count;
     922           1 : }
     923             : 
     924             : /*
     925             :  * Scans a directory for a given file (name points to its formatted name).
     926             :  * Returns an error code or zero.
     927             :  */
     928             : int fat_scan(struct inode *dir, const unsigned char *name,
     929             :              struct fat_slot_info *sinfo)
     930           0 : {
     931           0 :         struct super_block *sb = dir->i_sb;
     932           0 : 
     933           0 :         sinfo->slot_off = 0;
     934           0 :         sinfo->bh = NULL;
     935           0 :         while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh,
     936           0 :                                    &sinfo->de) >= 0) {
     937           0 :                 if (!strncmp(sinfo->de->name, name, MSDOS_NAME)) {
     938           0 :                         sinfo->slot_off -= sizeof(*sinfo->de);
     939           0 :                         sinfo->nr_slots = 1;
     940           0 :                         sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
     941           0 :                         return 0;
     942             :                 }
     943             :         }
     944           0 :         return -ENOENT;
     945           0 : }
     946             : 
     947             : EXPORT_SYMBOL_GPL(fat_scan);
     948             : 
     949             : static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
     950             : {
     951           0 :         struct super_block *sb = dir->i_sb;
     952           0 :         struct buffer_head *bh;
     953           0 :         struct msdos_dir_entry *de, *endp;
     954           0 :         int err = 0, orig_slots;
     955           0 : 
     956           0 :         while (nr_slots) {
     957           0 :                 bh = NULL;
     958           0 :                 if (fat_get_entry(dir, &pos, &bh, &de) < 0) {
     959           0 :                         err = -EIO;
     960           0 :                         break;
     961             :                 }
     962           0 : 
     963           0 :                 orig_slots = nr_slots;
     964           0 :                 endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize);
     965           0 :                 while (nr_slots && de < endp) {
     966           0 :                         de->name[0] = DELETED_FLAG;
     967           0 :                         de++;
     968           0 :                         nr_slots--;
     969           0 :                 }
     970           0 :                 mark_buffer_dirty_inode(bh, dir);
     971           0 :                 if (IS_DIRSYNC(dir))
     972           0 :                         err = sync_dirty_buffer(bh);
     973           0 :                 brelse(bh);
     974           0 :                 if (err)
     975           0 :                         break;
     976             : 
     977             :                 /* pos is *next* de's position, so this does `- sizeof(de)' */
     978           0 :                 pos += ((orig_slots - nr_slots) * sizeof(*de)) - sizeof(*de);
     979           0 :         }
     980             : 
     981           0 :         return err;
     982             : }
     983             : 
     984             : int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
     985             : {
     986           0 :         struct msdos_dir_entry *de;
     987           0 :         struct buffer_head *bh;
     988           0 :         int err = 0, nr_slots;
     989           0 : 
     990           0 :         /*
     991           0 :          * First stage: Remove the shortname. By this, the directory
     992           0 :          * entry is removed.
     993             :          */
     994           0 :         nr_slots = sinfo->nr_slots;
     995           0 :         de = sinfo->de;
     996           0 :         sinfo->de = NULL;
     997           0 :         bh = sinfo->bh;
     998           0 :         sinfo->bh = NULL;
     999           0 :         while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) {
    1000           0 :                 de->name[0] = DELETED_FLAG;
    1001           0 :                 de--;
    1002           0 :                 nr_slots--;
    1003           0 :         }
    1004           0 :         mark_buffer_dirty_inode(bh, dir);
    1005           0 :         if (IS_DIRSYNC(dir))
    1006           0 :                 err = sync_dirty_buffer(bh);
    1007           0 :         brelse(bh);
    1008           0 :         if (err)
    1009           0 :                 return err;
    1010           0 :         dir->i_version++;
    1011             : 
    1012           0 :         if (nr_slots) {
    1013             :                 /*
    1014             :                  * Second stage: remove the remaining longname slots.
    1015             :                  * (This directory entry is already removed, and so return
    1016             :                  * the success)
    1017             :                  */
    1018           0 :                 err = __fat_remove_entries(dir, sinfo->slot_off, nr_slots);
    1019           0 :                 if (err) {
    1020           0 :                         printk(KERN_WARNING
    1021             :                                "FAT: Couldn't remove the long name slots\n");
    1022             :                 }
    1023             :         }
    1024             : 
    1025           0 :         dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
    1026           0 :         if (IS_DIRSYNC(dir))
    1027           0 :                 (void)fat_sync_inode(dir);
    1028             :         else
    1029           0 :                 mark_inode_dirty(dir);
    1030             : 
    1031           0 :         return 0;
    1032             : }
    1033             : 
    1034             : EXPORT_SYMBOL_GPL(fat_remove_entries);
    1035             : 
    1036             : static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,
    1037             :                               struct buffer_head **bhs, int nr_bhs)
    1038             : {
    1039           0 :         struct super_block *sb = dir->i_sb;
    1040           0 :         sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus;
    1041           0 :         int err, i, n;
    1042           0 : 
    1043           0 :         /* Zeroing the unused blocks on this cluster */
    1044           0 :         blknr += nr_used;
    1045           0 :         n = nr_used;
    1046           0 :         while (blknr < last_blknr) {
    1047           0 :                 bhs[n] = sb_getblk(sb, blknr);
    1048           0 :                 if (!bhs[n]) {
    1049           0 :                         err = -ENOMEM;
    1050           0 :                         goto error;
    1051             :                 }
    1052           0 :                 memset(bhs[n]->b_data, 0, sb->s_blocksize);
    1053           0 :                 set_buffer_uptodate(bhs[n]);
    1054           0 :                 mark_buffer_dirty_inode(bhs[n], dir);
    1055             : 
    1056           0 :                 n++;
    1057           0 :                 blknr++;
    1058           0 :                 if (n == nr_bhs) {
    1059           0 :                         if (IS_DIRSYNC(dir)) {
    1060           0 :                                 err = fat_sync_bhs(bhs, n);
    1061           0 :                                 if (err)
    1062           0 :                                         goto error;
    1063             :                         }
    1064           0 :                         for (i = 0; i < n; i++)
    1065           0 :                                 brelse(bhs[i]);
    1066           0 :                         n = 0;
    1067             :                 }
    1068             :         }
    1069           0 :         if (IS_DIRSYNC(dir)) {
    1070           0 :                 err = fat_sync_bhs(bhs, n);
    1071           0 :                 if (err)
    1072           0 :                         goto error;
    1073             :         }
    1074           0 :         for (i = 0; i < n; i++)
    1075           0 :                 brelse(bhs[i]);
    1076           0 : 
    1077           0 :         return 0;
    1078           0 : 
    1079             : error:
    1080           0 :         for (i = 0; i < n; i++)
    1081           0 :                 bforget(bhs[i]);
    1082           0 :         return err;
    1083             : }
    1084             : 
    1085             : int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
    1086             : {
    1087           0 :         struct super_block *sb = dir->i_sb;
    1088           0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
    1089           0 :         struct buffer_head *bhs[MAX_BUF_PER_PAGE];
    1090           0 :         struct msdos_dir_entry *de;
    1091           0 :         sector_t blknr;
    1092           0 :         __le16 date, time;
    1093           0 :         u8 time_cs;
    1094           0 :         int err, cluster;
    1095           0 : 
    1096           0 :         err = fat_alloc_clusters(dir, &cluster, 1);
    1097           0 :         if (err)
    1098           0 :                 goto error;
    1099           0 : 
    1100           0 :         blknr = fat_clus_to_blknr(sbi, cluster);
    1101           0 :         bhs[0] = sb_getblk(sb, blknr);
    1102           0 :         if (!bhs[0]) {
    1103           0 :                 err = -ENOMEM;
    1104           0 :                 goto error_free;
    1105           0 :         }
    1106           0 : 
    1107           0 :         fat_time_unix2fat(sbi, ts, &time, &date, &time_cs);
    1108           0 : 
    1109           0 :         de = (struct msdos_dir_entry *)bhs[0]->b_data;
    1110           0 :         /* filling the new directory slots ("." and ".." entries) */
    1111           0 :         memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME);
    1112           0 :         memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME);
    1113           0 :         de->attr = de[1].attr = ATTR_DIR;
    1114           0 :         de[0].lcase = de[1].lcase = 0;
    1115           0 :         de[0].time = de[1].time = time;
    1116           0 :         de[0].date = de[1].date = date;
    1117           0 :         if (sbi->options.isvfat) {
    1118             :                 /* extra timestamps */
    1119           0 :                 de[0].ctime = de[1].ctime = time;
    1120           0 :                 de[0].ctime_cs = de[1].ctime_cs = time_cs;
    1121           0 :                 de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date;
    1122             :         } else {
    1123           0 :                 de[0].ctime = de[1].ctime = 0;
    1124           0 :                 de[0].ctime_cs = de[1].ctime_cs = 0;
    1125           0 :                 de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0;
    1126             :         }
    1127           0 :         de[0].start = cpu_to_le16(cluster);
    1128           0 :         de[0].starthi = cpu_to_le16(cluster >> 16);
    1129           0 :         de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
    1130           0 :         de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16);
    1131           0 :         de[0].size = de[1].size = 0;
    1132           0 :         memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de));
    1133           0 :         set_buffer_uptodate(bhs[0]);
    1134           0 :         mark_buffer_dirty_inode(bhs[0], dir);
    1135             : 
    1136           0 :         err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE);
    1137           0 :         if (err)
    1138           0 :                 goto error_free;
    1139             : 
    1140           0 :         return cluster;
    1141           0 : 
    1142             : error_free:
    1143           0 :         fat_free_clusters(dir, cluster);
    1144             : error:
    1145           0 :         return err;
    1146             : }
    1147             : 
    1148             : EXPORT_SYMBOL_GPL(fat_alloc_new_dir);
    1149             : 
    1150             : static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots,
    1151             :                                int *nr_cluster, struct msdos_dir_entry **de,
    1152             :                                struct buffer_head **bh, loff_t *i_pos)
    1153             : {
    1154           0 :         struct super_block *sb = dir->i_sb;
    1155           0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
    1156           0 :         struct buffer_head *bhs[MAX_BUF_PER_PAGE];
    1157           0 :         sector_t blknr, start_blknr, last_blknr;
    1158           0 :         unsigned long size, copy;
    1159           0 :         int err, i, n, offset, cluster[2];
    1160           0 : 
    1161           0 :         /*
    1162           0 :          * The minimum cluster size is 512bytes, and maximum entry
    1163           0 :          * size is 32*slots (672bytes).  So, iff the cluster size is
    1164           0 :          * 512bytes, we may need two clusters.
    1165           0 :          */
    1166           0 :         size = nr_slots * sizeof(struct msdos_dir_entry);
    1167           0 :         *nr_cluster = (size + (sbi->cluster_size - 1)) >> sbi->cluster_bits;
    1168           0 :         BUG_ON(*nr_cluster > 2);
    1169           0 : 
    1170           0 :         err = fat_alloc_clusters(dir, cluster, *nr_cluster);
    1171           0 :         if (err)
    1172           0 :                 goto error;
    1173             : 
    1174             :         /*
    1175             :          * First stage: Fill the directory entry.  NOTE: This cluster
    1176             :          * is not referenced from any inode yet, so updates order is
    1177             :          * not important.
    1178             :          */
    1179           0 :         i = n = copy = 0;
    1180           0 :         do {
    1181           0 :                 start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]);
    1182           0 :                 last_blknr = start_blknr + sbi->sec_per_clus;
    1183           0 :                 while (blknr < last_blknr) {
    1184           0 :                         bhs[n] = sb_getblk(sb, blknr);
    1185           0 :                         if (!bhs[n]) {
    1186           0 :                                 err = -ENOMEM;
    1187           0 :                                 goto error_nomem;
    1188             :                         }
    1189           0 : 
    1190             :                         /* fill the directory entry */
    1191           0 :                         copy = min(size, sb->s_blocksize);
    1192           0 :                         memcpy(bhs[n]->b_data, slots, copy);
    1193           0 :                         slots += copy;
    1194           0 :                         size -= copy;
    1195           0 :                         set_buffer_uptodate(bhs[n]);
    1196           0 :                         mark_buffer_dirty_inode(bhs[n], dir);
    1197           0 :                         if (!size)
    1198           0 :                                 break;
    1199           0 :                         n++;
    1200           0 :                         blknr++;
    1201           0 :                 }
    1202           0 :         } while (++i < *nr_cluster);
    1203             : 
    1204           0 :         memset(bhs[n]->b_data + copy, 0, sb->s_blocksize - copy);
    1205           0 :         offset = copy - sizeof(struct msdos_dir_entry);
    1206           0 :         get_bh(bhs[n]);
    1207           0 :         *bh = bhs[n];
    1208           0 :         *de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
    1209           0 :         *i_pos = fat_make_i_pos(sb, *bh, *de);
    1210             : 
    1211             :         /* Second stage: clear the rest of cluster, and write outs */
    1212           0 :         err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE);
    1213           0 :         if (err)
    1214           0 :                 goto error_free;
    1215             : 
    1216           0 :         return cluster[0];
    1217           0 : 
    1218             : error_free:
    1219           0 :         brelse(*bh);
    1220           0 :         *bh = NULL;
    1221           0 :         n = 0;
    1222             : error_nomem:
    1223           0 :         for (i = 0; i < n; i++)
    1224           0 :                 bforget(bhs[i]);
    1225           0 :         fat_free_clusters(dir, cluster[0]);
    1226             : error:
    1227           0 :         return err;
    1228             : }
    1229             : 
    1230             : int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
    1231             :                     struct fat_slot_info *sinfo)
    1232           0 : {
    1233           0 :         struct super_block *sb = dir->i_sb;
    1234           0 :         struct msdos_sb_info *sbi = MSDOS_SB(sb);
    1235           0 :         struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */
    1236           0 :         struct msdos_dir_entry *de;
    1237           0 :         int err, free_slots, i, nr_bhs;
    1238           0 :         loff_t pos, i_pos;
    1239           0 : 
    1240           0 :         sinfo->nr_slots = nr_slots;
    1241           0 : 
    1242           0 :         /* First stage: search free direcotry entries */
    1243           0 :         free_slots = nr_bhs = 0;
    1244           0 :         bh = prev = NULL;
    1245           0 :         pos = 0;
    1246           0 :         err = -ENOSPC;
    1247           0 :         while (fat_get_entry(dir, &pos, &bh, &de) > -1) {
    1248           0 :                 /* check the maximum size of directory */
    1249           0 :                 if (pos >= FAT_MAX_DIR_SIZE)
    1250           0 :                         goto error;
    1251           0 : 
    1252           0 :                 if (IS_FREE(de->name)) {
    1253           0 :                         if (prev != bh) {
    1254           0 :                                 get_bh(bh);
    1255           0 :                                 bhs[nr_bhs] = prev = bh;
    1256           0 :                                 nr_bhs++;
    1257           0 :                         }
    1258           0 :                         free_slots++;
    1259           0 :                         if (free_slots == nr_slots)
    1260           0 :                                 goto found;
    1261             :                 } else {
    1262           0 :                         for (i = 0; i < nr_bhs; i++)
    1263           0 :                                 brelse(bhs[i]);
    1264           0 :                         prev = NULL;
    1265           0 :                         free_slots = nr_bhs = 0;
    1266             :                 }
    1267           0 :         }
    1268           0 :         if (dir->i_ino == MSDOS_ROOT_INO) {
    1269           0 :                 if (sbi->fat_bits != 32)
    1270           0 :                         goto error;
    1271           0 :         } else if (MSDOS_I(dir)->i_start == 0) {
    1272           0 :                 printk(KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n",
    1273             :                        MSDOS_I(dir)->i_pos);
    1274           0 :                 err = -EIO;
    1275           0 :                 goto error;
    1276             :         }
    1277             : 
    1278             : found:
    1279           0 :         err = 0;
    1280           0 :         pos -= free_slots * sizeof(*de);
    1281           0 :         nr_slots -= free_slots;
    1282           0 :         if (free_slots) {
    1283             :                 /*
    1284             :                  * Second stage: filling the free entries with new entries.
    1285             :                  * NOTE: If this slots has shortname, first, we write
    1286             :                  * the long name slots, then write the short name.
    1287             :                  */
    1288           0 :                 int size = free_slots * sizeof(*de);
    1289           0 :                 int offset = pos & (sb->s_blocksize - 1);
    1290           0 :                 int long_bhs = nr_bhs - (nr_slots == 0);
    1291             : 
    1292             :                 /* Fill the long name slots. */
    1293           0 :                 for (i = 0; i < long_bhs; i++) {
    1294           0 :                         int copy = min_t(int, sb->s_blocksize - offset, size);
    1295           0 :                         memcpy(bhs[i]->b_data + offset, slots, copy);
    1296           0 :                         mark_buffer_dirty_inode(bhs[i], dir);
    1297           0 :                         offset = 0;
    1298           0 :                         slots += copy;
    1299           0 :                         size -= copy;
    1300             :                 }
    1301           0 :                 if (long_bhs && IS_DIRSYNC(dir))
    1302           0 :                         err = fat_sync_bhs(bhs, long_bhs);
    1303           0 :                 if (!err && i < nr_bhs) {
    1304             :                         /* Fill the short name slot. */
    1305           0 :                         int copy = min_t(int, sb->s_blocksize - offset, size);
    1306           0 :                         memcpy(bhs[i]->b_data + offset, slots, copy);
    1307           0 :                         mark_buffer_dirty_inode(bhs[i], dir);
    1308           0 :                         if (IS_DIRSYNC(dir))
    1309           0 :                                 err = sync_dirty_buffer(bhs[i]);
    1310             :                 }
    1311           0 :                 for (i = 0; i < nr_bhs; i++)
    1312           0 :                         brelse(bhs[i]);
    1313           0 :                 if (err)
    1314           0 :                         goto error_remove;
    1315             :         }
    1316             : 
    1317           0 :         if (nr_slots) {
    1318             :                 int cluster, nr_cluster;
    1319             : 
    1320             :                 /*
    1321             :                  * Third stage: allocate the cluster for new entries.
    1322             :                  * And initialize the cluster with new entries, then
    1323             :                  * add the cluster to dir.
    1324             :                  */
    1325           0 :                 cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster,
    1326             :                                               &de, &bh, &i_pos);
    1327           0 :                 if (cluster < 0) {
    1328           0 :                         err = cluster;
    1329           0 :                         goto error_remove;
    1330             :                 }
    1331           0 :                 err = fat_chain_add(dir, cluster, nr_cluster);
    1332           0 :                 if (err) {
    1333           0 :                         fat_free_clusters(dir, cluster);
    1334           0 :                         goto error_remove;
    1335             :                 }
    1336           0 :                 if (dir->i_size & (sbi->cluster_size - 1)) {
    1337           0 :                         fat_fs_error(sb, "Odd directory size");
    1338           0 :                         dir->i_size = (dir->i_size + sbi->cluster_size - 1)
    1339             :                                 & ~((loff_t)sbi->cluster_size - 1);
    1340             :                 }
    1341           0 :                 dir->i_size += nr_cluster << sbi->cluster_bits;
    1342           0 :                 MSDOS_I(dir)->mmu_private += nr_cluster << sbi->cluster_bits;
    1343             :         }
    1344           0 :         sinfo->slot_off = pos;
    1345           0 :         sinfo->de = de;
    1346           0 :         sinfo->bh = bh;
    1347           0 :         sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
    1348             : 
    1349           0 :         return 0;
    1350           0 : 
    1351             : error:
    1352           0 :         brelse(bh);
    1353           0 :         for (i = 0; i < nr_bhs; i++)
    1354           0 :                 brelse(bhs[i]);
    1355           0 :         return err;
    1356           0 : 
    1357             : error_remove:
    1358           0 :         brelse(bh);
    1359           0 :         if (free_slots)
    1360           0 :                 __fat_remove_entries(dir, pos, free_slots);
    1361           0 :         return err;
    1362             : }
    1363             : 
    1364             : EXPORT_SYMBOL_GPL(fat_add_entries);

Generated by: LCOV version 1.10