Changes in tools/mkfat.py [cc1a727:87608a5] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • tools/mkfat.py

    rcc1a727 r87608a5  
    168168"""
    169169
    170 def mangle_fname(name):
    171         # FIXME: filter illegal characters
    172         parts = name.split('.')
    173        
    174         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]
    206 
    207 def create_dirent(name, directory, cluster, size):
     170LFN_DIR_ENTRY = """little:
     171        uint8_t seq                /* sequence number */
     172        char name1[10]             /* first part of the name */
     173        uint8_t attr               /* attributes */
     174        uint8_t rec_type           /* LFN record type */
     175        uint8_t checksum           /* LFN checksum */
     176        char name2[12]             /* second part of the name */
     177        uint16_t cluster           /* cluster */
     178        char name3[4]              /* third part of the name */
     179"""
     180
     181lchars = set(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
     182              'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
     183              'U', 'V', 'W', 'X', 'Y', 'Z',
     184              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
     185              '!', '#', '$', '%', '&', '\'', '(', ')', '-', '@',
     186              '^', '_', '`', '{', '}', '~', '.'])
     187
     188def fat_lchars(name):
     189        "Filter FAT legal characters"
     190       
     191        filtered_name = ''
     192        filtered = False
     193       
     194        for char in name.encode('ascii', 'replace').upper():
     195                if char in lchars:
     196                        filtered_name += char
     197                else:
     198                        filtered_name += b'_'
     199                        filtered = True
     200       
     201        return (filtered_name, filtered)
     202
     203def fat_name83(name, name83_list):
     204        "Create a 8.3 name for the given name"
     205       
     206        ascii_name, lfn = fat_lchars(name)
     207        ascii_parts = ascii_name.split('.')
     208       
     209        short_name = ''
     210        short_ext = ''
     211       
     212        if len(ascii_name) > 11:
     213                lfn = True
     214       
     215        if len(ascii_parts) > 0:
     216                short_name = ascii_parts[0]
     217                if len(short_name) > 8:
     218                        lfn = True
     219       
     220        if len(ascii_parts) > 1:
     221                short_ext = ascii_parts[-1]
     222                if len(short_ext) > 3:
     223                        lfn = True
     224       
     225        if len(ascii_parts) > 2:
     226                lfn = True
     227       
     228        if lfn == False:
     229                name83_list.append(short_name + '.' + short_ext)
     230                return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], False)
     231       
     232        # For filenames with multiple extensions, we treat the last one
     233        # as the actual extension. The rest of the filename is stripped
     234        # of dots and concatenated to form the short name
     235        for part in ascii_parts[1:-1]:
     236                short_name += part
     237       
     238        for number in range(1, 999999):
     239                number_str = ('~' + str(number)).upper()
     240               
     241                if len(short_name) + len(number_str) > 8:
     242                        short_name = short_name[0:8 - len(number_str)]
     243               
     244                short_name += number_str;
     245               
     246                if not (short_name + '.' + short_ext) in name83_list:
     247                        break
     248       
     249        name83_list.append(short_name + '.' + short_ext)
     250        return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], True)
     251
     252def create_lfn_dirent(name, seq, checksum):
     253        "Create LFN directory entry"
     254       
     255        entry = xstruct.create(LFN_DIR_ENTRY)
     256        name_rest = name[26:]
     257       
     258        if len(name_rest) > 0:
     259                entry.seq = seq
     260        else:
     261                entry.seq = seq | 0x40
     262       
     263        entry.name1 = name[0:10]
     264        entry.name2 = name[10:22]
     265        entry.name3 = name[22:26]
     266       
     267        entry.attr = 0x0F
     268        entry.rec_type = 0
     269        entry.checksum = checksum
     270        entry.cluster = 0
     271       
     272        return (entry, name_rest)
     273
     274def lfn_checksum(name):
     275        "Calculate LFN checksum"
     276       
     277        checksum = 0
     278        for i in range(0, 11):
     279                checksum = (((checksum & 1) << 7) + (checksum >> 1) + ord(name[i])) & 0xFF
     280       
     281        return checksum
     282
     283def create_dirent(name, name83_list, directory, cluster, size):
     284        short_name, short_ext, lfn = fat_name83(name, name83_list)
     285       
    208286        dir_entry = xstruct.create(DIR_ENTRY)
    209287       
    210         dir_entry.name = mangle_fname(name).encode('ascii')
    211         dir_entry.ext = mangle_ext(name).encode('ascii')
     288        dir_entry.name = short_name
     289        dir_entry.ext = short_ext
    212290       
    213291        if (directory):
     
    230308                dir_entry.size = size
    231309       
    232         return dir_entry
     310        if not lfn:
     311                return [dir_entry]
     312       
     313        long_name = name.encode('utf_16_le')
     314        entries = [dir_entry]
     315       
     316        seq = 1
     317        checksum = lfn_checksum(dir_entry.name + dir_entry.ext)
     318       
     319        while len(long_name) > 0:
     320                long_entry, long_name = create_lfn_dirent(long_name, seq, checksum)
     321                entries.append(long_entry)
     322                seq += 1
     323       
     324        entries.reverse()
     325        return entries
    233326
    234327def create_dot_dirent(empty_cluster):
     
    274367       
    275368        directory = []
    276        
    277         if (not head):
     369        name83_list = []
     370       
     371        if not head:
    278372                # Directory cluster preallocation
    279373                empty_cluster = fat.index(0)
    280                 fat[empty_cluster] = 0xffff
     374                fat[empty_cluster] = 0xFFFF
    281375               
    282376                directory.append(create_dot_dirent(empty_cluster))
     
    285379                empty_cluster = 0
    286380       
    287         for item in listdir_items(root):               
     381        for item in listdir_items(root):
    288382                if item.is_file:
    289383                        rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
    290                         directory.append(create_dirent(item.name, False, rv[0], rv[1]))
     384                        directory.extend(create_dirent(item.name, name83_list, False, rv[0], rv[1]))
    291385                elif item.is_dir:
    292386                        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]))
    294        
    295         if (head):
     387                        directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1]))
     388       
     389        if head:
    296390                outf.seek(root_start)
    297391                for dir_entry in directory:
     
    350444        extra_bytes = int(sys.argv[1])
    351445       
    352         path = os.path.abspath(sys.argv[2])
     446        path = os.path.abspath(sys.argv[2].decode())
    353447        if (not os.path.isdir(path)):
    354448                print("<PATH> must be a directory")
     
    448542       
    449543        outf.close()
    450        
     544
    451545if __name__ == '__main__':
    452546        main()
Note: See TracChangeset for help on using the changeset viewer.