def _parse_header(inf): """ @param inf: an object which I can call read(1) on to get another byte @return: tuple of (m, k, pad, sh,); side-effect: the first one to four bytes of inf will be read """ # The first 8 bits always encode m. ch = inf.read(1) if not ch: raise CorruptedShareFilesError("Share files were corrupted -- share file %r didn't have a complete metadata header at the front. Perhaps the file was truncated." % (inf.name,)) byte = ord(ch) m = byte + 1 # The next few bits encode k. kbits = log_ceil(m, 2) # num bits needed to store all possible values of k b2_bits_left = 8-kbits kbitmask = MASK(kbits) << b2_bits_left ch = inf.read(1) if not ch: raise CorruptedShareFilesError("Share files were corrupted -- share file %r didn't have a complete metadata header at the front. Perhaps the file was truncated." % (inf.name,)) byte = ord(ch) k = ((byte & kbitmask) >> b2_bits_left) + 1 shbits = log_ceil(m, 2) # num bits needed to store all possible values of shnum padbits = log_ceil(k, 2) # num bits needed to store all possible values of pad val = byte & (~kbitmask) needed_padbits = padbits - b2_bits_left if needed_padbits > 0: ch = inf.read(1) if not ch: raise CorruptedShareFilesError("Share files were corrupted -- share file %r didn't have a complete metadata header at the front. Perhaps the file was truncated." % (inf.name,)) byte = struct.unpack(">B", ch)[0] val <<= 8 val |= byte needed_padbits -= 8 assert needed_padbits <= 0 extrabits = -needed_padbits pad = val >> extrabits val &= MASK(extrabits) needed_shbits = shbits - extrabits if needed_shbits > 0: ch = inf.read(1) if not ch: raise CorruptedShareFilesError("Share files were corrupted -- share file %r didn't have a complete metadata header at the front. Perhaps the file was truncated." % (inf.name,)) byte = struct.unpack(">B", ch)[0] val <<= 8 val |= byte needed_shbits -= 8 assert needed_shbits <= 0 gotshbits = -needed_shbits sh = val >> gotshbits return (m, k, pad, sh,)
def num_chars_that_this_many_octets_encode_to(numos): return log_ceil(256**numos, 62)
def _build_header(m, k, pad, sh): """ @param m: the total number of shares; 1 <= m <= 256 @param k: the number of shares required to reconstruct; 1 <= k <= m @param pad: the number of bytes of padding added to the file before encoding; 0 <= pad < k @param sh: the shnum of this share; 0 <= k < m @return: a compressed string encoding m, k, pad, and sh """ assert m >= 1 assert m <= 2**8 assert k >= 1 assert k <= m assert pad >= 0 assert pad < k assert sh >= 0 assert sh < m bitsused = 0 val = 0 val |= (m - 1) bitsused += 8 # the first 8 bits always encode m kbits = log_ceil(m, 2) # num bits needed to store all possible values of k val <<= kbits bitsused += kbits val |= (k - 1) padbits = log_ceil(k, 2) # num bits needed to store all possible values of pad val <<= padbits bitsused += padbits val |= pad shnumbits = log_ceil(m, 2) # num bits needed to store all possible values of shnum val <<= shnumbits bitsused += shnumbits val |= sh assert bitsused >= 8, bitsused assert bitsused <= 32, bitsused if bitsused <= 16: val <<= (16-bitsused) cs = struct.pack('>H', val) assert cs[:-2] == '\x00' * (len(cs)-2) return cs[-2:] if bitsused <= 24: val <<= (24-bitsused) cs = struct.pack('>I', val) assert cs[:-3] == '\x00' * (len(cs)-3) return cs[-3:] else: val <<= (32-bitsused) cs = struct.pack('>I', val) assert cs[:-4] == '\x00' * (len(cs)-4) return cs[-4:]
def _build_header(m, k, pad, sh): """ @param m: the total number of shares; 1 <= m <= 256 @param k: the number of shares required to reconstruct; 1 <= k <= m @param pad: the number of bytes of padding added to the file before encoding; 0 <= pad < k @param sh: the shnum of this share; 0 <= k < m @return: a compressed string encoding m, k, pad, and sh """ assert m >= 1 assert m <= 2**8 assert k >= 1 assert k <= m assert pad >= 0 assert pad < k assert sh >= 0 assert sh < m bitsused = 0 val = 0 val |= (m - 1) bitsused += 8 # the first 8 bits always encode m kbits = log_ceil(m, 2) # num bits needed to store all possible values of k val <<= kbits bitsused += kbits val |= (k - 1) padbits = log_ceil(k, 2) # num bits needed to store all possible values of pad val <<= padbits bitsused += padbits val |= pad shnumbits = log_ceil(m, 2) # num bits needed to store all possible values of shnum val <<= shnumbits bitsused += shnumbits val |= sh assert bitsused >= 8, bitsused assert bitsused <= 32, bitsused if bitsused <= 16: val <<= (16-bitsused) cs = struct.pack('>H', val) assert cs[:-2] == b'\x00' * (len(cs)-2) return cs[-2:] if bitsused <= 24: val <<= (24-bitsused) cs = struct.pack('>I', val) assert cs[:-3] == b'\x00' * (len(cs)-3) return cs[-3:] else: val <<= (32-bitsused) cs = struct.pack('>I', val) assert cs[:-4] == b'\x00' * (len(cs)-4) return cs[-4:]