1from __future__ import absolute_import 2from __future__ import print_function 3 4from amitools.fs.block.rdb.FSHeaderBlock import * 5from amitools.fs.block.rdb.LoadSegBlock import * 6from amitools.util.HexDump import * 7import amitools.fs.DosType as DosType 8 9class FileSystem: 10 def __init__(self, blkdev, blk_num, num): 11 self.blkdev = blkdev 12 self.blk_num = blk_num 13 self.num = num 14 self.fshd = None 15 self.valid = False 16 self.lsegs = [] 17 self.data = None 18 19 def get_next_fs_blk(self): 20 if self.fshd != None: 21 return self.fshd.next 22 else: 23 return 0xffffffff 24 25 def get_blk_nums(self): 26 res = [self.blk_num] 27 for ls in self.lsegs: 28 res.append(ls.blk_num) 29 return res 30 31 def read(self): 32 # read fs header 33 self.fshd = FSHeaderBlock(self.blkdev, self.blk_num) 34 if not self.fshd.read(): 35 self.valid = False 36 return False 37 # read lseg blocks 38 lseg_blk = self.fshd.dev_node.seg_list_blk 39 self.lsegs = [] 40 data = "" 41 while lseg_blk != 0xffffffff: 42 ls = LoadSegBlock(self.blkdev, lseg_blk) 43 if not ls.read(): 44 self.valid = False 45 return False 46 lseg_blk = ls.next 47 data += ls.get_data() 48 self.lsegs.append(ls) 49 self.data = data 50 return True 51 52 def get_data(self): 53 return self.data 54 55 # ----- create ------ 56 57 def get_total_blocks(self, data): 58 size = len(data) 59 lseg_size = self.blkdev.block_bytes - 20 60 num_lseg = int((size + lseg_size - 1)/lseg_size) 61 return num_lseg + 1 62 63 def create(self, blks, data, version, dos_type, dev_flags=None): 64 self.data = data 65 # create fs header 66 self.fshd = FSHeaderBlock(self.blkdev, self.blk_num) 67 self.fshd.create(version=version, dos_type=dos_type) 68 # store begin of seg list 69 self.fshd.set_flag('seg_list_blk',blks[0]) 70 self.fshd.set_flag('global_vec', 0xffffffff) 71 # add custom flags 72 if dev_flags is not None: 73 for p in dev_flags: 74 self.fshd.set_flag(p[0], p[1]) 75 # create lseg blocks 76 self.lsegs = [] 77 lseg_size = self.blkdev.block_bytes - 20 78 off = 0 79 size = len(data) 80 blk_off = 0 81 while(off < size): 82 blk_len = size - off 83 if blk_len > lseg_size: 84 blk_len = lseg_size 85 blk_data = data[off:off+blk_len] 86 # create new lseg block 87 ls = LoadSegBlock(self.blkdev, blks[blk_off]) 88 # get next block 89 if blk_off == len(blks)-1: 90 next = Block.no_blk 91 else: 92 next = blks[blk_off+1] 93 ls.create(next=next) 94 ls.set_data(blk_data) 95 self.lsegs.append(ls) 96 # next round 97 off += blk_len 98 blk_off += 1 99 100 def write(self, only_fshd=False): 101 self.fshd.write() 102 if not only_fshd: 103 for lseg in self.lsegs: 104 lseg.write() 105 106 # ----- query ----- 107 108 def dump(self, hex_dump=False): 109 if self.fshd != None: 110 self.fshd.dump() 111 # only dump ids of lseg blocks 112 print("LoadSegBlocks:") 113 ids = [] 114 for ls in self.lsegs: 115 ids.append(str(ls.blk_num)) 116 print(" lseg blks: %s" % ",".join(ids)) 117 print(" data size: %d" % len(self.data)) 118 if hex_dump: 119 print_hex(self.data) 120 121 def get_flags_info(self): 122 flags = self.fshd.get_flags() 123 res = [] 124 for f in flags: 125 res.append("%s=0x%x" % f) 126 return " ".join(res) 127 128 def get_valid_flag_names(self): 129 return self.fshd.get_valid_flag_names() 130 131 def get_info(self): 132 flags = self.get_flags_info() 133 dt = self.fshd.dos_type 134 dt_str = DosType.num_to_tag_str(dt) 135 return "FileSystem #%d %s/0x%04x version=%s size=%d %s" % (self.num, dt_str, dt, self.fshd.get_version_string(), len(self.data), flags) 136 137 # ----- edit ----- 138 139 def clear_flags(self): 140 self.fshd.patch_flags = 0 141 self.fshd.write() 142 return True 143 144 def set_flags(self, flags, clear=False): 145 if clear: 146 self.fshd.patch_flags = 0 147 self.fshd.set_flags(flags) 148 self.fshd.write() 149 150