Exemplo n.º 1
0
 def get_info(self):
     res = []
     # physical disk info
     pd = self.rdb.phy_drv
     total_blks = self.get_total_blocks()
     total_bytes = self.get_total_bytes()
     extra = "heads=%d sectors=%d" % (pd.heads, pd.secs)
     res.append("PhysicalDisk:        %8d %8d  %10d  %s  %s" \
       % (0, pd.cyls-1, total_blks, ByteSize.to_byte_size_str(total_bytes), extra))
     # logical disk info
     ld = self.rdb.log_drv
     extra = "rdb_blks=[%d:%d,#%d] used=[hi=%d,#%d] cyl_blks=%d" % (
         ld.rdb_blk_lo, ld.rdb_blk_hi, self.max_blks, ld.high_rdsk_blk,
         len(self.used_blks), ld.cyl_blks)
     logic_blks = self.get_logical_blocks()
     logic_bytes = self.get_logical_bytes()
     res.append("LogicalDisk:         %8d %8d  %10d  %s  %s" \
       % (ld.lo_cyl, ld.hi_cyl, logic_blks, ByteSize.to_byte_size_str(logic_bytes), extra))
     # add partitions
     for p in self.parts:
         res.append(p.get_info(logic_blks))
     # add fileystems
     for f in self.fs:
         res.append(f.get_info())
     return res
Exemplo n.º 2
0
 def get_info(self):
   res = []
   # physical disk info
   pd = self.rdb.phy_drv
   total_blks = self.get_total_blocks()
   total_bytes = self.get_total_bytes()
   bs = self.rdb.block_size
   extra="heads=%d sectors=%d block_size=%d" % (pd.heads, pd.secs, bs)
   res.append("PhysicalDisk:        %8d %8d  %10d  %s  %s" \
     % (0, pd.cyls-1, total_blks, ByteSize.to_byte_size_str(total_bytes), extra))
   # logical disk info
   ld = self.rdb.log_drv
   extra="rdb_blks=[%d:%d,#%d] used=[hi=%d,#%d] cyl_blks=%d" % (ld.rdb_blk_lo, ld.rdb_blk_hi, self.max_blks, ld.high_rdsk_blk, len(self.used_blks), ld.cyl_blks)
   logic_blks = self.get_logical_blocks()
   logic_bytes = self.get_logical_bytes()
   res.append("LogicalDisk:         %8d %8d  %10d  %s  %s" \
     % (ld.lo_cyl, ld.hi_cyl, logic_blks, ByteSize.to_byte_size_str(logic_bytes), extra))
   # add partitions
   for p in self.parts:
     res.append(p.get_info(logic_blks))
     extra = p.get_extra_infos()
     for e in extra:
       res.append("%s%s" % (" " * 70, e))
   # add fileystems
   for f in self.fs:
     res.append(f.get_info())
   return res
Exemplo n.º 3
0
 def get_info(self, part_name=None):
     res = []
     part = None
     # only show single partition
     if part_name:
         part = self.find_partition_by_string(part_name)
         if not part:
             res.append("Partition not found: %s!" % part_name)
             return res
     # physical disk info
     if part:
         logic_blks = self.get_logical_blocks()
         res.append(part.get_info(logic_blks))
         extra = part.get_extra_infos()
         for e in extra:
             res.append("%s%s" % (" " * 70, e))
     else:
         pd = self.rdb.phy_drv
         total_blks = self.get_total_blocks()
         total_bytes = self.get_total_bytes()
         bs = self.rdb.block_size
         extra = "heads=%d sectors=%d block_size=%d" % (pd.heads, pd.secs,
                                                        bs)
         res.append("PhysicalDisk:        %8d %8d  %10d  %s  %s" % (
             0,
             pd.cyls - 1,
             total_blks,
             ByteSize.to_byte_size_str(total_bytes),
             extra,
         ))
         # logical disk info
         ld = self.rdb.log_drv
         extra = "rdb_blks=[%d:%d,#%d] used=[hi=%d,#%d] cyl_blks=%d" % (
             ld.rdb_blk_lo,
             ld.rdb_blk_hi,
             self.max_blks,
             ld.high_rdsk_blk,
             len(self.used_blks),
             ld.cyl_blks,
         )
         logic_blks = self.get_logical_blocks()
         logic_bytes = self.get_logical_bytes()
         res.append("LogicalDisk:         %8d %8d  %10d  %s  %s" % (
             ld.lo_cyl,
             ld.hi_cyl,
             logic_blks,
             ByteSize.to_byte_size_str(logic_bytes),
             extra,
         ))
         # add partitions
         for p in self.parts:
             res.append(p.get_info(logic_blks))
             extra = p.get_extra_infos()
             for e in extra:
                 res.append("%s%s" % (" " * 70, e))
         # add fileystems
         for f in self.fs:
             res.append(f.get_info())
     return res
Exemplo n.º 4
0
 def get_info(self, all=False):
   # block usage: data + fs blocks
   (data,fs) = self.get_block_usage(all=all)
   total = data + fs
   bb = self.blkdev.block_bytes
   btotal = total * bb
   bdata = data * bb
   bfs = fs * bb
   prc_data = 10000 * data / total
   prc_fs = 10000 - prc_data
   res = []
   res.append("sum:    %10d  %s  %12d" % (total, ByteSize.to_byte_size_str(btotal), btotal))
   res.append("data:   %10d  %s  %12d  %5.2f%%" % (data, ByteSize.to_byte_size_str(bdata), bdata, prc_data / 100.0))
   res.append("fs:     %10d  %s  %12d  %5.2f%%" % (fs, ByteSize.to_byte_size_str(bfs), bfs, prc_fs / 100.0))
   return res
Exemplo n.º 5
0
 def get_info(self, total_blks=0):
   """return a string line with typical info about this partition"""
   p = self.part_blk
   de = p.dos_env
   name = "'%s'" % p.drv_name
   part_blks = self.get_num_blocks()
   part_bytes = self.get_num_bytes()
   extra = ""
   if total_blks != 0:
     ratio = 100.0 * part_blks / total_blks
     extra += "%6.2f%%  " % ratio
   # add dos type
   dos_type = de.dos_type
   extra += DosType.num_to_tag_str(dos_type)
   extra += "/0x%04x" % dos_type
   # max transfer
   extra += " max_transfer=0x%x" % de.max_transfer
   extra += " mask=0x%x" % de.mask
   extra += " num_buffer=%d" % de.num_buffer
   # add flags
   flags = p.flags
   if flags & PartitionBlock.FLAG_BOOTABLE == PartitionBlock.FLAG_BOOTABLE:
     extra += " bootable pri=%d" % de.boot_pri
   if flags & PartitionBlock.FLAG_NO_AUTOMOUNT == PartitionBlock.FLAG_NO_AUTOMOUNT:
     extra += " no_automount"
   return "Partition: #%d %-06s %8d %8d  %10d  %s  %s" \
     % (self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra)
Exemplo n.º 6
0
 def get_info(self, total_blks=0):
     """return a string line with typical info about this partition"""
     p = self.part_blk
     de = p.dos_env
     name = "'%s'" % p.drv_name
     part_blks = self.get_num_blocks()
     part_bytes = self.get_num_bytes()
     extra = ""
     if total_blks != 0:
         ratio = 100.0 * part_blks / total_blks
         extra += "%6.2f%%  " % ratio
     # add dos type
     dos_type = de.dos_type
     extra += DosType.num_to_tag_str(dos_type)
     extra += "/0x%04x" % dos_type
     # max transfer
     extra += " max_transfer=0x%x" % de.max_transfer
     extra += " mask=0x%x" % de.mask
     extra += " num_buffer=%d" % de.num_buffer
     # add flags
     flags = p.flags
     if flags & PartitionBlock.FLAG_BOOTABLE == PartitionBlock.FLAG_BOOTABLE:
         extra += " bootable pri=%d" % de.boot_pri
     if flags & PartitionBlock.FLAG_NO_AUTOMOUNT == PartitionBlock.FLAG_NO_AUTOMOUNT:
         extra += " no_automount"
     return "Partition: #%d %-06s %8d %8d  %10d  %s  %s" \
       % (self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra)
Exemplo n.º 7
0
 def get_info(self):
   """return an array of strings with information on the volume"""
   res = []
   total = self.get_total_blocks()
   free  = self.get_free_blocks()
   used  = total - free
   bb = self.blkdev.block_bytes
   btotal = total * bb
   bfree  = free * bb
   bused  = used * bb
   prc_free = 10000 * free / total
   prc_used = 10000 - prc_free
   res.append("total:  %10d  %s  %12d" % (total, ByteSize.to_byte_size_str(btotal), btotal))
   res.append("used:   %10d  %s  %12d  %5.2f%%" % (used, ByteSize.to_byte_size_str(bused), bused, prc_used / 100.0))
   res.append("free:   %10d  %s  %12d  %5.2f%%" % (free, ByteSize.to_byte_size_str(bfree), bfree, prc_free / 100.0))
   return res
Exemplo n.º 8
0
 def setup(self, options, block_bytes=512):
   """setup a new geometry by giving options
      return bytes required by geometry or None if geometry is invalid
   """
   if options == None:
     return False
   c = None
   h = None
   s = None
   (c, h, s) = self._parse_chs(options)
   # chs is fully specified
   if c != None and h != None and s != None:
     self.cyls = c
     self.heads = h
     self.secs = s
     return self.get_num_bytes()
   else:
     # we require a size
     if not options.has_key('size'):
       return None
     # parse size
     size = options['size']
     if type(size) != int:
       size = ByteSize.parse_byte_size_str(size)
       if size == None:
         return None
     # select guess algo
     algo = None
     if options.has_key('algo'):
       algo = int(options['algo'])
     # guess size
     return self._guess_for_size(size, approx=True, algo=algo, secs=s, heads=h)  
Exemplo n.º 9
0
    def get_cyl_range(self):
        start = None
        if 'start' in self.popts:
            start = int(self.popts['start'])
        # range with start=<n> end=<n>
        if 'end' in self.popts:
            end = int(self.popts['end'])
            if start == None or end <= start:
                return None
            else:
                return (start, end)
        # expect a size
        elif 'size' in self.popts:
            size = self.popts['size']
            cyls = None
            if type(size) == int:
                cyls = size
            # size in bytes
            elif size[-1] in ('b', 'B'):
                num_bytes = ByteSize.parse_byte_size_str(size[:-1])
                if num_bytes == None:
                    return None
                cyls = num_bytes // self.rdisk.get_cylinder_bytes()
            # size in percent
            elif size[-1] == '%':
                prc = float(size[:-1])
                cyls = int(prc * self.rdisk.get_logical_cylinders() / 100.0)
            # size in cylinders
            else:
                cyls = ByteSize.parse_byte_size_str(size)

            # check cyls
            if cyls == None or cyls < 1:
                return None
            # find a range if no start is given
            if start == None:
                start = self.rdisk.find_free_cyl_range_start(cyls)
                if start == None:
                    return None
            return (start, start + cyls - 1)
        # nothing specified -> get next free range
        else:
            ranges = self.rdisk.get_free_cyl_ranges()
            if ranges == None:
                return None
            return ranges[0]
Exemplo n.º 10
0
  def get_cyl_range(self):
    start = None
    if self.popts.has_key('start'):
      start = int(self.popts['start'])
    # range with start=<n> end=<n>
    if self.popts.has_key('end'):
      end = int(self.popts['end'])
      if start == None or end <= start:
        return None
      else:
        return (start, end)
    # expect a size
    elif self.popts.has_key('size'):
      size = self.popts['size']
      cyls = None
      if type(size) == int:
        cyls = size
      # size in bytes
      elif size[-1] in ('b','B'):
        bytes = ByteSize.parse_byte_size_str(size[:-1])
        if bytes == None:
          return None
        cyls = bytes / self.rdisk.get_cylinder_bytes()
      # size in percent
      elif size[-1] == '%':
        prc = float(size[:-1])
        cyls = int(prc * self.rdisk.get_logical_cylinders() / 100.0)
      # size in cylinders
      else:
        cyls = ByteSize.parse_byte_size_str(size)

      # check cyls
      if cyls == None or cyls < 1:
        return None
      # find a range if no start is given
      if start == None:
        start = self.rdisk.find_free_cyl_range_start(cyls)
        if start == None:
          return None
      return (start, start + cyls - 1)
    # nothing specified -> get next free range
    else:
      ranges = self.rdisk.get_free_cyl_ranges()
      if ranges == None:
        return None
      return ranges[0]
Exemplo n.º 11
0
 def get_info(self, all=False):
     # block usage: data + fs blocks
     (data, fs) = self.get_block_usage(all=all)
     total = data + fs
     bb = self.blkdev.block_bytes
     btotal = total * bb
     bdata = data * bb
     bfs = fs * bb
     prc_data = 10000 * data / total
     prc_fs = 10000 - prc_data
     res = []
     res.append("sum:    %10d  %s  %12d" %
                (total, ByteSize.to_byte_size_str(btotal), btotal))
     res.append(
         "data:   %10d  %s  %12d  %5.2f%%" %
         (data, ByteSize.to_byte_size_str(bdata), bdata, prc_data / 100.0))
     res.append("fs:     %10d  %s  %12d  %5.2f%%" %
                (fs, ByteSize.to_byte_size_str(bfs), bfs, prc_fs / 100.0))
     return res
Exemplo n.º 12
0
 def __str__(self):
     size = self.get_num_bytes()
     return "chs=%d,%d,%d bs=%d size=%d/%s" % (
         self.cyls,
         self.heads,
         self.secs,
         self.block_bytes,
         size,
         ByteSize.to_byte_size_str(size),
     )
Exemplo n.º 13
0
 def get_info(self):
     """return an array of strings with information on the volume"""
     res = []
     total = self.get_total_blocks()
     free = self.get_free_blocks()
     used = total - free
     bb = self.blkdev.block_bytes
     btotal = total * bb
     bfree = free * bb
     bused = used * bb
     prc_free = 10000 * free / total
     prc_used = 10000 - prc_free
     res.append("total:  %10d  %s  %12d" %
                (total, ByteSize.to_byte_size_str(btotal), btotal))
     res.append(
         "used:   %10d  %s  %12d  %5.2f%%" %
         (used, ByteSize.to_byte_size_str(bused), bused, prc_used / 100.0))
     res.append(
         "free:   %10d  %s  %12d  %5.2f%%" %
         (free, ByteSize.to_byte_size_str(bfree), bfree, prc_free / 100.0))
     return res
Exemplo n.º 14
0
 def setup(self, options, cyls=None, heads=None, sectors=None):
     """setup a new geometry by giving options
     return bytes required by geometry or None if geometry is invalid
     """
     if options is None:
         return False
     (c, h, s) = self._parse_chs(options)
     if not c:
         c = cyls
     if not h:
         h = heads
     if not s:
         s = sectors
     self._update_block_size(options)
     # chs is fully specified
     if c and h and s:
         self.cyls = c
         self.heads = h
         self.secs = s
         return self.get_num_bytes()
     else:
         # fetch size from another image
         if "from" in options:
             file_name = options["from"]
             size = ImageFile.get_image_size(file_name)
         # we require a size
         elif "size" in options:
             # parse size
             size = options["size"]
             if type(size) != int:
                 size = ByteSize.parse_byte_size_str(size)
                 if size is None:
                     return None
         # no size given
         else:
             return None
         # select guess algo
         algo = None
         if "algo" in options:
             algo = int(options["algo"])
         # guess size
         return self._guess_for_size(size,
                                     approx=True,
                                     algo=algo,
                                     secs=s,
                                     heads=h)
Exemplo n.º 15
0
 def get_info(self, total_blks=0):
   """return a string line with typical info about this partition"""
   p = self.part_blk
   de = p.dos_env
   name = "'%s'" % p.drv_name
   part_blks = self.get_num_blocks()
   part_bytes = self.get_num_bytes()
   extra = ""
   if total_blks != 0:
     ratio = 100.0 * part_blks / total_blks
     extra += "%6.2f%%  " % ratio
   # add dos type
   dos_type = de.dos_type
   extra += DosType.num_to_tag_str(dos_type)
   extra += "/0x%04x" % dos_type
   return "Partition: #%d %-06s %8d %8d  %10d  %s  %s" \
     % (self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra)
Exemplo n.º 16
0
 def get_info(self, total_blks=0):
     """return a string line with typical info about this partition"""
     p = self.part_blk
     de = p.dos_env
     name = "'%s'" % p.drv_name
     part_blks = self.get_num_blocks()
     part_bytes = self.get_num_bytes()
     extra = ""
     if total_blks != 0:
         ratio = 100.0 * part_blks / total_blks
         extra += "%6.2f%%  " % ratio
     # add dos type
     dos_type = de.dos_type
     extra += DosType.num_to_tag_str(dos_type)
     extra += "/0x%04x" % dos_type
     return "Partition: #%d %-06s %8d %8d  %10d  %s  %s" \
       % (self.num, name, de.low_cyl, de.high_cyl, part_blks, ByteSize.to_byte_size_str(part_bytes), extra)
Exemplo n.º 17
0
 def handle_rdisk(self, rdisk):
     part_name = None
     if len(self.opts) > 0:
         part_name = self.opts[0]
     else:
         # blkdev info
         geo = self.blkdev.geo
         extra = "heads=%d sectors=%d block_size=%d" % (
             geo.heads,
             geo.secs,
             geo.block_bytes,
         )
         print("BlockDevice:         %8d %8d  %10d  %s  %s" % (
             0,
             geo.cyls - 1,
             geo.get_num_blocks(),
             ByteSize.to_byte_size_str(geo.get_num_bytes()),
             extra,
         ))
     lines = rdisk.get_info(part_name)
     for l in lines:
         print(l)
     return 0
Exemplo n.º 18
0
def main(args=None):
    if not args:
        a = sys.argv
    else:
        a = args
    n = len(a)
    if n < 3:
        print(
            "Usage: (detect <size|file> [options] | setup <options> | open <file> [options] | create <file> <options>)"
        )
        print("""Options:
             size=<size>
             chs=<n>,<n>,<n>
             c=<n> h=<n> s=<n>
             algo=1|2
             """)
        return 1
    else:
        cmd = a[1]
        # detect disk geometry from given image file
        if cmd == "detect":
            if os.path.exists(a[2]):
                # its a file
                size = os.path.getsize(a[2])
            else:
                # parse size string
                size = ByteSize.parse_byte_size_str(a[2])
            if size == None:
                print("Invalid size!")
            else:
                d = DiskGeometry()
                opts = None
                if n > 3:
                    opts = KeyValue.parse_key_value_strings(a[3:])
                print("size:  ", size)
                print("opts:  ", opts)
                size = d.detect(size, opts)
                if size != None:
                    print("geo:   ", d)
                else:
                    print("FAILED")
        # setup a new disk geometry from options
        elif cmd == "setup":
            d = DiskGeometry()
            opts = KeyValue.parse_key_value_strings(a[2:])
            print("opts:  ", opts)
            size = d.setup(opts)
            if size != None:
                print("setup: ", size, ByteSize.to_byte_size_str(size))
                print("geo:   ", d)
            else:
                print("FAILED")
        # open a blkdev and detect geometry
        elif cmd == "open":
            opts = None
            if n > 3:
                opts = KeyValue.parse_key_value_strings(a[3:])
            print("opts:   ", opts)
            f = BlkDevFactory()
            blkdev = f.open(a[2], options=opts)
            if blkdev != None:
                print("blkdev: ", blkdev.__class__.__name__)
                print("geo:    ", blkdev.get_geometry())
                blkdev.close()
            else:
                print("FAILED")
        # create a new blkdev with setup geometry
        elif cmd == "create":
            opts = KeyValue.parse_key_value_strings(a[3:])
            print("opts:   ", opts)
            f = BlkDevFactory()
            blkdev = f.create(a[2], options=opts)
            if blkdev != None:
                print("blkdev: ", blkdev.__class__.__name__)
                print("geo:    ", blkdev.get_geometry())
                blkdev.close()
            else:
                print("FAILED")
        return 0
Exemplo n.º 19
0
def main():
    a = sys.argv
    n = len(a)
    if n < 3:
        print "Usage: (detect <size|file> [options] | setup <options> | open <file> [options] | create <file> <options>)"
        print """Options:
             size=<size>
             chs=<n>,<n>,<n>
             c=<n> h=<n> s=<n>
             algo=1|2
             """
        return 1
    else:
        cmd = a[1]
        # detect disk geometry from given image file
        if cmd == 'detect':
            if os.path.exists(a[2]):
                # its a file
                size = os.path.getsize(a[2])
            else:
                # parse size string
                size = ByteSize.parse_byte_size_str(a[2])
            if size == None:
                print "Invalid size!"
            else:
                d = DiskGeometry()
                opts = None
                if n > 3:
                    opts = KeyValue.parse_key_value_strings(a[3:])
                print "size:  ", size
                print "opts:  ", opts
                size = d.detect(size, opts)
                if size != None:
                    print "geo:   ", d
                else:
                    print "FAILED"
        # setup a new disk geometry from options
        elif cmd == 'setup':
            d = DiskGeometry()
            opts = KeyValue.parse_key_value_strings(a[2:])
            print "opts:  ", opts
            size = d.setup(opts)
            if size != None:
                print "setup: ", size, ByteSize.to_byte_size_str(size)
                print "geo:   ", d
            else:
                print "FAILED"
        # open a blkdev and detect geometry
        elif cmd == 'open':
            opts = None
            if n > 3:
                opts = KeyValue.parse_key_value_strings(a[3:])
            print "opts:   ", opts
            f = BlkDevFactory()
            blkdev = f.open(a[2], options=opts)
            if blkdev != None:
                print "blkdev: ", blkdev.__class__.__name__
                print "geo:    ", blkdev.get_geometry()
                blkdev.close()
            else:
                print "FAILED"
        # create a new blkdev with setup geometry
        elif cmd == 'create':
            opts = KeyValue.parse_key_value_strings(a[3:])
            print "opts:   ", opts
            f = BlkDevFactory()
            blkdev = f.create(a[2], options=opts)
            if blkdev != None:
                print "blkdev: ", blkdev.__class__.__name__
                print "geo:    ", blkdev.get_geometry()
                blkdev.close()
            else:
                print "FAILED"
        return 0
Exemplo n.º 20
0
def main():
  a = sys.argv
  n = len(a)
  if n < 3:
    print "Usage: (detect <size|file> [options] | setup <options> | open <file> [options] | create <file> <options>)"
    print """Options:
             size=<size>
             chs=<n>,<n>,<n>
             c=<n> h=<n> s=<n>
             algo=1|2
             """
    return 1
  else:
    cmd = a[1]
    # detect disk geometry from given image file
    if cmd == 'detect':
      if os.path.exists(a[2]):
        # its a file
        size = os.path.getsize(a[2])
      else:
        # parse size string
        size = ByteSize.parse_byte_size_str(a[2])
      if size == None:
        print "Invalid size!"
      else:
        d = DiskGeometry()
        opts = None
        if n > 3:
          opts = KeyValue.parse_key_value_strings(a[3:])
        print "size:  ",size
        print "opts:  ",opts
        size = d.detect(size, opts)
        if size != None:
          print "geo:   ",d
        else:
          print "FAILED"
    # setup a new disk geometry from options
    elif cmd == 'setup' :
      d = DiskGeometry()
      opts = KeyValue.parse_key_value_strings(a[2:])
      print "opts:  ",opts
      size = d.setup(opts)
      if size != None:
        print "setup: ",size,ByteSize.to_byte_size_str(size)
        print "geo:   ",d
      else:
        print "FAILED"
    # open a blkdev and detect geometry
    elif cmd == 'open':
      opts = None
      if n > 3:
        opts = KeyValue.parse_key_value_strings(a[3:])
      print "opts:   ",opts
      f = BlkDevFactory()
      blkdev = f.open(a[2], options=opts)
      if blkdev != None:
        print "blkdev: ",blkdev.__class__.__name__
        print "geo:    ",blkdev.get_geometry()
        blkdev.close()
      else:
        print "FAILED"
    # create a new blkdev with setup geometry
    elif cmd == 'create':
      opts = KeyValue.parse_key_value_strings(a[3:])
      print "opts:   ",opts
      f = BlkDevFactory()
      blkdev = f.create(a[2], options=opts)
      if blkdev != None:
        print "blkdev: ",blkdev.__class__.__name__
        print "geo:    ",blkdev.get_geometry()
        blkdev.close()
      else:
        print "FAILED"
    return 0
Exemplo n.º 21
0
 def __str__(self):
   size = self.get_num_bytes()
   return "chs=%d,%d,%d size=%d/%s" % (self.cyls, self.heads, self.secs, size, ByteSize.to_byte_size_str(size))