-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathvtar.py
More file actions
117 lines (91 loc) · 3.52 KB
/
vtar.py
File metadata and controls
117 lines (91 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import sys
import os, os.path
import struct
import argparse
import gzip
vmtar = struct.Struct('<'
'100s' # [0] 0x000 name
'8s' # [1] 0x064 mode
'8s' # [2] 0x06C uid
'8s' # [3] 0x074 gid
'12s' # [4] 0x07C size
'12s' # [5] 0x088 mtime
'8s' # [6] 0x094 chksum
'c' # [7] 0x09C type
'100s' # [8] 0x09D linkname
'6s' # [9] 0x101 magic
'2s' # [10] 0x107 version
'32s' # [11] 0x109 uname
'32s' # [12] 0x129 gname
'8s' # [13] 0x149 devmajor
'8s' # [14] 0x151 devminor
'151s' # [15] 0x159 prefix
'I' # [16] 0x1F0 offset
'I' # [17] 0x1F4 textoffset
'I' # [18] 0x1F8 textsize
'I' # [19] 0x1FC numfixuppgs
) # 0x200 (total size)
TAR_TYPE_FILE = '0'
TAR_TYPE_LINK = '1'
TAR_TYPE_SYMLINK = '2'
TAR_TYPE_CHARDEV = '3'
TAR_TYPE_BLOCKDEV = '4'
TAR_TYPE_DIR = '5'
TAR_TYPE_FIFO = '6'
TAR_TYPE_SHAREDFILE = '7'
TAR_TYPE_GNU_LONGLINK = 'K'
TAR_TYPE_GNU_LONGNAME = 'L'
GZIP_MAGIC = '\037\213'
def parse_args():
parser = argparse.ArgumentParser(description='Extracts VMware ESXi .vtar files')
parser.add_argument('vtarfile', help='.vtar file')
parser.add_argument('-C', '--directory', metavar='DIR', help='Change to directory DIR')
# Actions
grp = parser.add_mutually_exclusive_group(required=True)
grp.add_argument('-x', '--extract', action='store_true', help='Extract contents of vtarfile')
# TODO: Create
return parser.parse_args()
def main():
args = parse_args()
print args
with open(args.vtarfile, 'rb') as raw_input_file:
gzip_header = raw_input_file.read(2)
raw_input_file.seek(0)
f = raw_input_file
if gzip_header == GZIP_MAGIC:
f = gzip.GzipFile(fileobj=raw_input_file)
if args.directory:
os.chdir(args.directory)
print 'pos type offset txtoff txtsz nfix size name'
while True:
pos = f.tell()
buf = f.read(vmtar.size)
if len(buf) < vmtar.size:
raise Exception('Short read at 0x{0:X}'.format(pos))
obj = vmtar.unpack(buf)
hdr_magic = obj[9]
if hdr_magic != 'visor ': break
hdr_type = obj[7]
hdr_offset = obj[16]
hdr_textoffset = obj[17]
hdr_textsize = obj[18]
hdr_numfixuppgs = obj[19]
hdr_size = int(obj[4].rstrip('\0'), 8)
hdr_name = obj[0].rstrip('\0')
print '0x{0:08X} {1} {2:08X} {3:08X} {4:08X} {5:04X} {6:08X} {7}'.format(
pos, hdr_type, hdr_offset, hdr_textoffset, hdr_textsize, hdr_numfixuppgs, hdr_size, hdr_name)
if not args.extract: continue
if hdr_type == TAR_TYPE_DIR:
try:
os.mkdir(hdr_name)
except OSError:
pass
if hdr_type == TAR_TYPE_FILE:
pos = f.tell()
f.seek(hdr_offset, os.SEEK_SET)
blob = f.read(hdr_size)
with open(hdr_name, 'wb') as outf:
outf.write(blob)
f.seek(pos, os.SEEK_SET)
if __name__ == '__main__':
sys.exit(main())