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