Skip to content

Instantly share code, notes, and snippets.

@mipsparc

mipsparc/fat_ls.py

Last active Apr 20, 2016
Embed
What would you like to do?
Show LFN and SFN like ls on FAT12/16 (Support UTF-8/UTF-16 file name)
#!/usr/bin/env python3
import struct
from sys import argv
UTF8_prior = False
#FILENAME = input('img name?: ')
FILENAME = argv[1]
def getLFN(ldir_wholename):
ldir_wholename = ldir_wholename.replace(b'\xff\xff',b'') #remove padding
ldir_utf8name = ldir_wholename.replace(b'\0',b'') #UTF8だと想定してnull文字削除
if not UTF8_prior:
try:
ldir_strname = ldir_wholename.decode('utf_16_le')
#UTF8だった場合
except UnicodeDecodeError:
ldir_strname = ldir_utf8name.decode('utf_8')
else:
try:
ldir_strname = ldir_utf8name.decode('utf_8')
#UTF16だった場合
except UnicodeDecodeError:
ldir_strname = ldir_wholename.decode('utf_16_le')
return ldir_strname
data = open(FILENAME, 'rb').read()
BytesPerSec, SecPerClus, RsvdSecCnt, NumFATs, FATSize = struct.unpack_from(b'< 3x 8x H B H B 2x 2x x H', data)
dir_start = BytesPerSec * (RsvdSecCnt + FATSize * NumFATs) #BPB+FAT*2 0x600
entry_size = 32
saved_data = b''
delLFNContinue = False
while True:
name, attr = struct.unpack_from(b'< 11s c', data, dir_start)
if name==b'\x00'*11:
break
if attr==b'\x0f': #LFN
LDIR_Ord, LDIR_Name1, LDIR_Chksum, LDIR_Name2, LDIR_Name3 = struct.unpack_from(b'< B 10s x x c 12s 2x 4s', data, dir_start)
ldir_rawname = LDIR_Name1 + LDIR_Name2 + LDIR_Name3
#16進の一の位が1以外なら連続なので連結
ord_hex = format(LDIR_Ord, 'x')
if len(ord_hex) == 1: #2桁化
ord_hex = '0' + ord_hex
if ord_hex[1]!='1' and ord_hex!='e5': #e5は削除済みファイル
saved_data = ldir_rawname + saved_data
#削除済みLFNはどこまでか判定できないのでとりえあずスタックする
elif ord_hex=='e5':
saved_data = ldir_rawname + saved_data
delLFNContinue = True
else:
ldir_wholename = ldir_rawname + saved_data
saved_data = b''
ldir_strname = getLFN(ldir_wholename)
print('LFN: '+ldir_strname)
else: #SFN
#削除済みLFNが終わったことを確認
if delLFNContinue:
delLFNContinue = False
ldir_wholename = saved_data
saved_data = b''
ldir_strname = getLFN(ldir_wholename)
print('LFN: '+ldir_strname,' (DELETED)')
try:
if name[0:1]==b'\xe5': #一文字目が削除フラグ0xE5か
print('SFN: ?'+name[1:].decode('ascii'),' (DELETED)')
else:
print('SFN: '+name.decode('ascii'))
except UnicodeDecodeError:
print('SFN: (decoding failed)')
print()
dir_start += entry_size
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.