Changes in tools/mkfat.py [87608a5:a9a6d8d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/mkfat.py
r87608a5 ra9a6d8d 168 168 """ 169 169 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 = '' 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 ascii_parts = ascii_name.split('.') 208 209 short_name = '' 210 short_ext = '' 211 212 if len(ascii_name) > 11: 170 LFN_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. 183 name83_list = [] 184 185 def name83(fname): 186 "Create a 8.3 name for the given fname" 187 188 # FIXME: filter illegal characters 189 parts = fname.split('.') 190 191 name = '' 192 ext = '' 193 lfn = False 194 195 if len(fname) > 11 : 213 196 lfn = True 214 215 if len( ascii_parts) > 0:216 short_name = ascii_parts[0]217 if len( short_name) > 8:197 198 if len(parts) > 0: 199 name = parts[0] 200 if len(name) > 8 : 218 201 lfn = True 219 220 if len( ascii_parts) > 1:221 short_ext = ascii_parts[-1]222 if len( short_ext) > 3:202 203 if len(parts) > 1 : 204 ext = parts[-1] 205 if len(ext) > 3 : 223 206 lfn = True 224 225 if len( ascii_parts) > 2:207 208 if len(parts) > 2 : 226 209 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 210 211 if (lfn == False) : 212 return (name.ljust(8)[0:8], ext.ljust(3)[0:3], False) 213 232 214 # For filenames with multiple extensions, we treat the last one 233 215 # as the actual extension. The rest of the filename is stripped 234 216 # 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: 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 : 247 230 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 252 def 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 274 def 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 283 def create_dirent(name, name83_list, directory, cluster, size): 284 short_name, short_ext, lfn = fat_name83(name, name83_list) 231 232 name83_list.append(name + ext) 233 234 return (name.ljust(8)[0:8], ext.ljust(3)[0:3], True) 235 236 def 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 249 def 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 262 263 def create_dirent(name, directory, cluster, size): 285 264 286 265 dir_entry = xstruct.create(DIR_ENTRY) 287 266 288 dir_entry.name = short_name 289 dir_entry.ext = short_ext 290 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 291 272 if (directory): 292 273 dir_entry.attr = 0x30 … … 308 289 dir_entry.size = size 309 290 291 310 292 if not lfn: 311 293 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() 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 325 313 return entries 326 314 … … 367 355 368 356 directory = [] 369 name83_list = [] 370 371 if not head: 357 358 if (not head): 372 359 # Directory cluster preallocation 373 360 empty_cluster = fat.index(0) 374 fat[empty_cluster] = 0x FFFF361 fat[empty_cluster] = 0xffff 375 362 376 363 directory.append(create_dot_dirent(empty_cluster)) … … 379 366 empty_cluster = 0 380 367 381 for item in listdir_items(root): 368 for item in listdir_items(root): 382 369 if item.is_file: 383 370 rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters) 384 directory.extend(create_dirent(item.name, name83_list,False, rv[0], rv[1]))371 directory.extend(create_dirent(item.name, False, rv[0], rv[1])) 385 372 elif item.is_dir: 386 373 rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster) 387 directory.extend(create_dirent(item.name, name83_list,True, rv[0], rv[1]))388 389 if head:374 directory.extend(create_dirent(item.name, True, rv[0], rv[1])) 375 376 if (head): 390 377 outf.seek(root_start) 391 378 for dir_entry in directory: … … 444 431 extra_bytes = int(sys.argv[1]) 445 432 446 path = os.path.abspath(sys.argv[2] .decode())433 path = os.path.abspath(sys.argv[2]) 447 434 if (not os.path.isdir(path)): 448 435 print("<PATH> must be a directory") … … 542 529 543 530 outf.close() 544 531 545 532 if __name__ == '__main__': 546 533 main()
Note:
See TracChangeset
for help on using the changeset viewer.