Changes in tools/mkfat.py [67435b1:cc1a727] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • tools/mkfat.py

    r67435b1 rcc1a727  
    168168"""
    169169
    170 LFN_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 
    181 lchars = 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 
    188 def fat_lchars(name):
    189         "Filter FAT legal characters"
    190        
    191         filtered_name = b''
    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 
    203 def fat_name83(name, name83_list):
    204         "Create a 8.3 name for the given name"
    205        
    206         ascii_name, lfn = fat_lchars(name)
    207         # Splitting works only on strings, not on bytes
    208         ascii_parts = ascii_name.decode('utf8').split('.')
    209        
    210         short_name = ''
    211         short_ext = ''
    212        
    213         if len(ascii_name) > 11:
    214                 lfn = True
    215        
    216         if len(ascii_parts) > 0:
    217                 short_name = ascii_parts[0]
    218                 if len(short_name) > 8:
    219                         lfn = True
    220        
    221         if len(ascii_parts) > 1:
    222                 short_ext = ascii_parts[-1]
    223                 if len(short_ext) > 3:
    224                         lfn = True
    225        
    226         if len(ascii_parts) > 2:
    227                 lfn = True
    228        
    229         if lfn == False:
    230                 name83_list.append(short_name + '.' + short_ext)
    231                 return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], False)
    232        
    233         # For filenames with multiple extensions, we treat the last one
    234         # as the actual extension. The rest of the filename is stripped
    235         # of dots and concatenated to form the short name
    236         for part in ascii_parts[1:-1]:
    237                 short_name += part
    238        
    239         for number in range(1, 999999):
    240                 number_str = ('~' + str(number)).upper()
    241                
    242                 if len(short_name) + len(number_str) > 8:
    243                         short_name = short_name[0:8 - len(number_str)]
    244                
    245                 short_name += number_str;
    246                
    247                 if not (short_name + '.' + short_ext) in name83_list:
    248                         break
    249        
    250         name83_list.append(short_name + '.' + short_ext)
    251         return (short_name.ljust(8)[0:8], short_ext.ljust(3)[0:3], True)
    252 
    253 def create_lfn_dirent(name, seq, checksum):
    254         "Create LFN directory entry"
    255        
    256         entry = xstruct.create(LFN_DIR_ENTRY)
    257         name_rest = name[26:]
    258        
    259         if len(name_rest) > 0:
    260                 entry.seq = seq
    261         else:
    262                 entry.seq = seq | 0x40
    263        
    264         entry.name1 = name[0:10]
    265         entry.name2 = name[10:22]
    266         entry.name3 = name[22:26]
    267        
    268         entry.attr = 0x0F
    269         entry.rec_type = 0
    270         entry.checksum = checksum
    271         entry.cluster = 0
    272        
    273         return (entry, name_rest)
    274 
    275 def lfn_checksum(name):
    276         "Calculate LFN checksum"
    277        
    278         checksum = 0
    279         for i in range(0, 11):
    280                 checksum = (((checksum & 1) << 7) + (checksum >> 1) + ord(name[i])) & 0xFF
    281        
    282         return checksum
    283 
    284 def create_dirent(name, name83_list, directory, cluster, size):
    285         short_name, short_ext, lfn = fat_name83(name, name83_list)
    286        
     170def 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
     186def 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
     207def create_dirent(name, directory, cluster, size):
    287208        dir_entry = xstruct.create(DIR_ENTRY)
    288209       
    289         dir_entry.name = short_name
    290         dir_entry.ext = short_ext
     210        dir_entry.name = mangle_fname(name).encode('ascii')
     211        dir_entry.ext = mangle_ext(name).encode('ascii')
    291212       
    292213        if (directory):
     
    309230                dir_entry.size = size
    310231       
    311         if not lfn:
    312                 return [dir_entry]
    313        
    314         long_name = name.encode('utf_16_le')
    315         entries = [dir_entry]
    316        
    317         seq = 1
    318         checksum = lfn_checksum(dir_entry.name + dir_entry.ext)
    319        
    320         while len(long_name) > 0:
    321                 long_entry, long_name = create_lfn_dirent(long_name, seq, checksum)
    322                 entries.append(long_entry)
    323                 seq += 1
    324        
    325         entries.reverse()
    326         return entries
     232        return dir_entry
    327233
    328234def create_dot_dirent(empty_cluster):
     
    368274       
    369275        directory = []
    370         name83_list = []
    371        
    372         if not head:
     276       
     277        if (not head):
    373278                # Directory cluster preallocation
    374279                empty_cluster = fat.index(0)
    375                 fat[empty_cluster] = 0xFFFF
     280                fat[empty_cluster] = 0xffff
    376281               
    377282                directory.append(create_dot_dirent(empty_cluster))
     
    380285                empty_cluster = 0
    381286       
    382         for item in listdir_items(root):
     287        for item in listdir_items(root):               
    383288                if item.is_file:
    384289                        rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
    385                         directory.extend(create_dirent(item.name, name83_list, False, rv[0], rv[1]))
     290                        directory.append(create_dirent(item.name, False, rv[0], rv[1]))
    386291                elif item.is_dir:
    387292                        rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
    388                         directory.extend(create_dirent(item.name, name83_list, True, rv[0], rv[1]))
    389        
    390         if head:
     293                        directory.append(create_dirent(item.name, True, rv[0], rv[1]))
     294       
     295        if (head):
    391296                outf.seek(root_start)
    392297                for dir_entry in directory:
     
    543448       
    544449        outf.close()
    545 
     450       
    546451if __name__ == '__main__':
    547452        main()
Note: See TracChangeset for help on using the changeset viewer.