class FAT(object): "Decodifica una FAT (12, 16, 32 o EX) dal disco" def __init__ (self, stream, offset, clusters, bitsize=32, exfat=0): # Crea uno stream autonomo, con propria cache self.stream = DiskFile(stream._file.name, stream._file.mode) self.offset = offset # offset iniziale della FAT in esso self.size = clusters # numero di cluster (=slot della FAT) self.bits = bitsize # bit dello slot (12, 16 o 32) self.exfat = exfat # se si tratta di EXFAT self.reserved = 0x0FF0 self.bad = 0x0FF7 self.last = 0x0FF8 if bitsize == 16: self.reserved |= 0xFF00 self.bad |= 0xFF00 elif bitsize ==32: self.reserved |= 0x0FFFFF00 # FAT32 usa solo 28 bit self.bad |= 0x0FFFFF00 self.last |= 0x0FFFFF00 if exfat: self.reserved |= 0xF0000000 # EXFAT li usa tutti self.bad |= 0xF0000000 self.last |= 0xF0000000 def __getitem__ (self, index): self.stream.seek(self.offset+(index*self.bits)/8) if self.bits == 32: n, fmt = 4, '<I' else: n, fmt = 2, '<H' slot = struct.unpack(fmt, self.stream.read(n))[0] if self.bits == 12: # Ricava i 12 bit di interesse if index % 2: # indice dispari slot = slot >> 4 else: slot = slot & 0x0FFF return slot def isvalid(self, index): "Determina se il numero di cluster dati è valido per questa FAT" if (index > 1 and index <= self.size) or self.islast(index) or self.isbad(index): return 1 logging.debug("indice di cluster non valido: %x", index) return 0 def islast(self, index): "Determina se è l'ultimo cluster della catena" return self.last <= index <= self.last+7 # *F8 ... *FF def isbad(self, index): return index == self.bad
def __init__ (self, stream, offset, clusters, bitsize=32, exfat=0): # Crea uno stream autonomo, con propria cache self.stream = DiskFile(stream._file.name, stream._file.mode) self.offset = offset # offset iniziale della FAT in esso self.size = clusters # numero di cluster (=slot della FAT) self.bits = bitsize # bit dello slot (12, 16 o 32) self.exfat = exfat # se si tratta di EXFAT self.reserved = 0x0FF0 self.bad = 0x0FF7 self.last = 0x0FF8 if bitsize == 16: self.reserved |= 0xFF00 self.bad |= 0xFF00 elif bitsize ==32: self.reserved |= 0x0FFFFF00 # FAT32 usa solo 28 bit self.bad |= 0x0FFFFF00 self.last |= 0x0FFFFF00 if exfat: self.reserved |= 0xF0000000 # EXFAT li usa tutti self.bad |= 0xF0000000 self.last |= 0xF0000000
buf = chain.read(32*(1<<20)) md.update(buf) fp.write( '%s *U:%s\n' % (md.hexdigest(), os.path.join(slot.Parent,name)) ) print name #~ good = md5.new(open(os.path.join("U:",slot.Parent,name),'rb').read()).hexdigest() #~ if md.hexdigest() != good: #~ print "I checksum MD5 per %s non coincidono!" % name #~ else: #~ print "Checksum MD5 corretto per", name action = lambda x, y, z: fat_recover_slot(x, y, z, 'H:') action = lambda x, y, z: list_slot(x, y, z) outmd5 = open('checksums.md5','w') action = lambda x, y, z: md5_slot(x, y, z, outmd5) logging.basicConfig(level=logging.ERROR, filename='FAT32.log', filemode='w') start = datetime.now() disk = DiskFile('\\\\.\\z:', 'rb') boot = Boot(disk) fat = FAT(disk, boot.fatoffs, boot.fatsize) fat_traverse_tree(boot, fat, boot.dwRootCluster, '.', test=lambda x: 1, action=action) disk.cache.print_stats() print "Durata dell'esecuzione:", datetime.now() - start