Finished tar
This commit is contained in:
parent
b5e985cd86
commit
667f937c00
55
tar.py
55
tar.py
|
|
@ -1,3 +1,4 @@
|
||||||
|
import builtins
|
||||||
from flask import Response
|
from flask import Response
|
||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
|
|
@ -5,6 +6,12 @@ import os
|
||||||
# 4MiB chunks
|
# 4MiB chunks
|
||||||
CHUNK_SIZE = 4_194_304
|
CHUNK_SIZE = 4_194_304
|
||||||
|
|
||||||
|
# ASCII value for space
|
||||||
|
SPACE = ord(' ')
|
||||||
|
|
||||||
|
# ASCII value for zero
|
||||||
|
ZERO = ord('0')
|
||||||
|
|
||||||
# Specification de l'entête du fichier
|
# Specification de l'entête du fichier
|
||||||
# Numéro Nom Début Taille Description
|
# Numéro Nom Début Taille Description
|
||||||
# 1 name 0 100 Nom du fichier
|
# 1 name 0 100 Nom du fichier
|
||||||
|
|
@ -19,45 +26,47 @@ CHUNK_SIZE = 4_194_304
|
||||||
|
|
||||||
|
|
||||||
def header_chunk(filename: str, filepath: str) -> bytes:
|
def header_chunk(filename: str, filepath: str) -> bytes:
|
||||||
|
|
||||||
|
# Returns the octal representation without the initial
|
||||||
|
def oct(i: int) -> str:
|
||||||
|
return builtins.oct(i)[2:]
|
||||||
|
|
||||||
stat = os.stat(filepath)
|
stat = os.stat(filepath)
|
||||||
buffer = bytearray()
|
buffer = bytearray(512)
|
||||||
|
|
||||||
# Field 1: filename on 100 bytes
|
# Field 1: filename on 100 bytes
|
||||||
buffer += filename.encode('ascii')
|
buffer[0:len(filename)] = filename.encode('ascii')
|
||||||
buffer += b'\x00' * (100 - len(filename))
|
|
||||||
|
|
||||||
# Field 2: mode, on 8 bytes
|
# Field 2: mode, on 8 bytes, octal, last byte must be \x00, so we set only the first 7 bytes
|
||||||
# TODO we put 777 for test
|
buffer[100:107] = oct(stat.st_mode).rjust(7, '0').encode('ascii')
|
||||||
buffer += '0000777'.encode('ascii') + b'\x00'
|
|
||||||
|
|
||||||
# Field 3: owner, we put 1000, default user
|
# Field 3: owner, on 8 bytes, octal, last byte must be \x00, so we set only the first 7 bytes
|
||||||
buffer += '0001000'.encode('ascii') + b'\x00'
|
buffer[108:115] = oct(stat.st_uid).rjust(7, '0').encode('ascii')
|
||||||
|
|
||||||
# Field 4: group, we put 1000
|
# Field 4: group, on 8 bytes, octal, last byte must be \x00, so we set only the first 7 bytes
|
||||||
buffer += '0001000'.encode('ascii') + b'\x00'
|
buffer[116:123] = oct(stat.st_gid).rjust(7, '0').encode('ascii')
|
||||||
|
|
||||||
# Field 5: file size in bytes in ascii
|
# Field 5: file size in bytes, on 12 bytes, octal, last byte must be \x00, so we set only the first 11 bytes
|
||||||
buffer += oct(stat.st_size)[2:].rjust(11, '0').encode('ascii') + b'\x00'
|
buffer[124:135] = oct(stat.st_size).rjust(11, '0').encode('ascii')
|
||||||
|
|
||||||
# Field 6: last modified, zeros for now
|
# Field 6: last modified, on 12 bytes, octal, last byte must be \x00, so we set only the first 11 bytes
|
||||||
# buffer += '00000000000'.encode('ascii') + b'\x00'
|
buffer[136:147] = oct(int(stat.st_mtime)).rjust(11, '0').encode('ascii')
|
||||||
buffer += oct(1721728914)[2:].rjust(11, '0').encode('ascii') + b'\x00'
|
|
||||||
|
|
||||||
# Field 7: checksum, we put spaces and we will edit it at the end
|
# Field 7: checksum, we fill it at the end
|
||||||
buffer += ' '.encode('ascii')
|
|
||||||
|
|
||||||
# Field 8: type flag, 0 because we only have regular files
|
# Field 8: type flag, 0 because we only have regular files
|
||||||
buffer += b'0'
|
buffer[156] = ZERO
|
||||||
|
|
||||||
# Field 9: linkname, \x00s because we only have regular files
|
# Field 9: linkname, \x00s because we only have regular files
|
||||||
buffer += b'\x00' * 100
|
|
||||||
|
|
||||||
# POSIX 1003.1-1990: 255 empty bytes
|
# POSIX 1003.1-1990: 255 empty bytes
|
||||||
buffer += b'\x00' * 255
|
|
||||||
|
|
||||||
# Compute the checksum
|
# Compute the checksum: we start at 248 which are the 8 fields of checksum filled with spaces (32 * 8)
|
||||||
checksum = oct(functools.reduce(lambda x, y: x + y, buffer))[2:].rjust(6, '0').encode('ascii') + b'\x00 '
|
checksum = oct(functools.reduce(lambda x, y: x + y, buffer, 256)).rjust(6, '0').encode('ascii')
|
||||||
buffer[148:156] = checksum
|
buffer[148:154] = checksum
|
||||||
|
|
||||||
|
# Don't ask me why, but the checksum must end with b'\x00 ', so we skip the \x00 and write the space
|
||||||
|
buffer[155] = SPACE
|
||||||
|
|
||||||
return bytes(buffer)
|
return bytes(buffer)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue