Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset a9a6d8d in mainline


Ignore:
Timestamp:
2012-03-29T07:56:17Z (8 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
master
Children:
ec351c3
Parents:
cc9f314
git-author:
Balaji Rao <> (2012-03-29 07:56:17)
git-committer:
Vojtech Horky <vojtechhorky@…> (2012-03-29 07:56:17)
Message:

Support for LFN in mkfat.py utility (#400)

mkfat.py is now able to handle long filenames. Support for filenames
with characters outside of base ASCII is still missing, though.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tools/mkfat.py

    rcc9f314 ra9a6d8d  
    168168"""
    169169
    170 def mangle_fname(name):
     170LFN_ENTRY = """little:
     171        uint8_t pos
     172        uint16_t name1[5]
     173        uint8_t attr
     174        uint8_t type
     175        uint8_t csum
     176        uint16_t name2[6]
     177        uint16_t fc
     178        uint16_t name3[2]
     179"""
     180
     181# Global variable to hold the file names in 8.3 format. Needed to
     182# keep track of "number" when creating a short fname from a LFN.
     183name83_list = []
     184
     185def name83(fname):
     186        "Create a 8.3 name for the given fname"
     187
    171188        # FIXME: filter illegal characters
    172         parts = name.split('.')
    173        
     189        parts = fname.split('.')
     190       
     191        name = ''
     192        ext = ''
     193        lfn = False
     194
     195        if len(fname) > 11 :
     196                lfn = True
     197
    174198        if len(parts) > 0:
    175                 fname = parts[0]
    176         else:
    177                 fname = ''
    178        
    179         if len(fname) > 8:
    180                 sys.stdout.write("mkfat.py: error: Directory entry " + name +
    181                     " base name is longer than 8 characters\n")
    182                 sys.exit(1);
    183        
    184         return (fname + '          ').upper()[0:8]
    185 
    186 def mangle_ext(name):
    187         # FIXME: filter illegal characters
    188         parts = name.split('.')
    189        
    190         if len(parts) > 1:
    191                 ext = parts[1]
    192         else:
    193                 ext = ''
    194        
    195         if len(parts) > 2:
    196                 sys.stdout.write("mkfat.py: error: Directory entry " + name +
    197                     " has more than one extension\n")
    198                 sys.exit(1);
    199        
    200         if len(ext) > 3:
    201                 sys.stdout.write("mkfat.py: error: Directory entry " + name +
    202                     " extension is longer than 3 characters\n")
    203                 sys.exit(1);
    204        
    205         return (ext + '   ').upper()[0:3]
     199                name = parts[0]
     200                if len(name) > 8 :
     201                        lfn = True
     202
     203        if len(parts) > 1 :
     204                ext = parts[-1]
     205                if len(ext) > 3 :
     206                        lfn = True
     207
     208        if len(parts) > 2 :
     209                lfn = True
     210
     211        if (lfn == False) :
     212                return (name.ljust(8)[0:8], ext.ljust(3)[0:3], False)
     213
     214        # For filenames with multiple extensions, we treat the last one
     215        # as the actual extension. The rest of the filename is stripped
     216        # of dots and concatenated to form the short name
     217        for _name in parts[1:-1]:
     218                name = name + _name             
     219
     220        global name83_list
     221        for number in range(1, 10000) :
     222                number_str = '~' + str(number)
     223
     224                if len(name) + len(number_str) > 8 :
     225                        name = name[0:8 - len(number_str)]
     226
     227                name = name + number_str;
     228
     229                if (name + ext) not in name83_list :
     230                        break
     231                       
     232        name83_list.append(name + ext) 
     233
     234        return (name.ljust(8)[0:8], ext.ljust(3)[0:3], True)
     235
     236def get_utf16(name, l) :
     237        "Create a int array out of a string which we can store in uint16_t arrays"
     238
     239        bs = [0xFFFF for i in range(l)]
     240
     241        for i in range(len(name)) :
     242                bs[i] = ord(name[i])
     243       
     244        if (len(name) < l) :
     245                bs[len(name)] = 0;
     246       
     247        return bs
     248
     249def create_lfn_entry((name, index)) :
     250        entry = xstruct.create(LFN_ENTRY)
     251
     252        entry.name1 = get_utf16(name[0:5], 5)
     253        entry.name2 = get_utf16(name[5:11], 6)
     254        entry.name3 = get_utf16(name[11:13], 2)
     255        entry.pos = index
     256
     257        entry.attr = 0xF
     258        entry.fc = 0
     259        entry.type = 0
     260
     261        return entry
    206262
    207263def create_dirent(name, directory, cluster, size):
     264       
    208265        dir_entry = xstruct.create(DIR_ENTRY)
    209266       
    210         dir_entry.name = mangle_fname(name).encode('ascii')
    211         dir_entry.ext = mangle_ext(name).encode('ascii')
    212        
     267        dir_entry.name, dir_entry.ext, lfn = name83(name)
     268
     269        dir_entry.name = dir_entry.name.upper().encode('ascii')
     270        dir_entry.ext = dir_entry.ext.upper().encode('ascii')
     271
    213272        if (directory):
    214273                dir_entry.attr = 0x30
     
    230289                dir_entry.size = size
    231290       
    232         return dir_entry
     291
     292        if not lfn:
     293                return [dir_entry]
     294
     295        n = len(name) / 13 + 1
     296        names = [(name[i * 13: (i + 1) * 13 + 1], i + 1) for i in range(n)]
     297
     298        entries = sorted(map (create_lfn_entry, names), reverse = True, key = lambda e : e.pos)
     299        entries[0].pos |= 0x40
     300
     301        fname11 = dir_entry.name + dir_entry.ext
     302
     303        csum = 0
     304        for i in range(0, 11) :
     305                csum = ((csum & 1) << 7) + (csum  >> 1) + ord(fname11[i])
     306                csum = csum & 0xFF
     307       
     308        for e in entries :
     309                e.csum = csum;
     310       
     311        entries.append(dir_entry)
     312
     313        return entries
    233314
    234315def create_dot_dirent(empty_cluster):
     
    288369                if item.is_file:
    289370                        rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
    290                         directory.append(create_dirent(item.name, False, rv[0], rv[1]))
     371                        directory.extend(create_dirent(item.name, False, rv[0], rv[1]))
    291372                elif item.is_dir:
    292373                        rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
    293                         directory.append(create_dirent(item.name, True, rv[0], rv[1]))
     374                        directory.extend(create_dirent(item.name, True, rv[0], rv[1]))
    294375       
    295376        if (head):
Note: See TracChangeset for help on using the changeset viewer.