forked from OSchip/llvm-project
Add an interactive mode to BSD archive parser.
llvm-svn: 343242
This commit is contained in:
parent
2a64d393ea
commit
95c23f6643
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import cmd
|
||||
import optparse
|
||||
import os
|
||||
import shlex
|
||||
|
@ -76,6 +77,22 @@ class Object(object):
|
|||
self.file.seek(saved_pos, 0)
|
||||
return bytes
|
||||
|
||||
def save(self, path=None, overwrite=False):
|
||||
'''
|
||||
Save the contents of the object to disk using 'path' argument as
|
||||
the path, or save it to the current working directory using the
|
||||
object name.
|
||||
'''
|
||||
|
||||
if path is None:
|
||||
path = self.name
|
||||
if not overwrite and os.path.exists(path):
|
||||
print('error: outfile "%s" already exists' % (path))
|
||||
return
|
||||
print('Saving "%s" to "%s"...' % (self.name, path))
|
||||
with open(path, 'w') as f:
|
||||
f.write(self.get_bytes())
|
||||
|
||||
|
||||
class StringTable(object):
|
||||
def __init__(self, bytes):
|
||||
|
@ -186,6 +203,67 @@ class Archive(object):
|
|||
for obj in self.objects:
|
||||
obj.dump(f=f, flat=flat)
|
||||
|
||||
class Interactive(cmd.Cmd):
|
||||
'''Interactive prompt for exploring contents of BSD archive files, type
|
||||
"help" to see a list of supported commands.'''
|
||||
image_option_parser = None
|
||||
|
||||
def __init__(self, archives):
|
||||
cmd.Cmd.__init__(self)
|
||||
self.use_rawinput = False
|
||||
self.intro = ('Interactive BSD archive prompt, type "help" to see a '
|
||||
'list of supported commands.')
|
||||
self.archives = archives
|
||||
self.prompt = '% '
|
||||
|
||||
def default(self, line):
|
||||
'''Catch all for unknown command, which will exit the interpreter.'''
|
||||
print("unknown command: %s" % line)
|
||||
return True
|
||||
|
||||
def do_q(self, line):
|
||||
'''Quit command'''
|
||||
return True
|
||||
|
||||
def do_quit(self, line):
|
||||
'''Quit command'''
|
||||
return True
|
||||
|
||||
def do_extract(self, line):
|
||||
args = shlex.split(line)
|
||||
if args:
|
||||
extracted = False
|
||||
for object_name in args:
|
||||
for archive in self.archives:
|
||||
matches = archive.find(object_name)
|
||||
if matches:
|
||||
for object in matches:
|
||||
object.save(overwrite=False)
|
||||
extracted = True
|
||||
if not extracted:
|
||||
print('error: no object matches "%s" in any archives' % (
|
||||
object_name))
|
||||
else:
|
||||
print('error: must specify the name of an object to extract')
|
||||
|
||||
def do_ls(self, line):
|
||||
args = shlex.split(line)
|
||||
if args:
|
||||
for object_name in args:
|
||||
for archive in self.archives:
|
||||
matches = archive.find(object_name)
|
||||
if matches:
|
||||
for object in matches:
|
||||
object.dump(flat=False)
|
||||
else:
|
||||
print('error: no object matches "%s" in "%s"' % (
|
||||
object_name, archive.path))
|
||||
else:
|
||||
for archive in self.archives:
|
||||
archive.dump(flat=True)
|
||||
print('')
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser(
|
||||
|
@ -243,9 +321,24 @@ def main():
|
|||
'then the extracted object file will be extracted into the '
|
||||
'current working directory if a file doesn\'t already exist '
|
||||
'with that name.'))
|
||||
parser.add_option(
|
||||
'-i', '--interactive',
|
||||
action='store_true',
|
||||
dest='interactive',
|
||||
default=False,
|
||||
help=('Enter an interactive shell that allows users to interactively '
|
||||
'explore contents of .a files.'))
|
||||
|
||||
(options, args) = parser.parse_args(sys.argv[1:])
|
||||
|
||||
if options.interactive:
|
||||
archives = []
|
||||
for path in args:
|
||||
archives.append(Archive(path))
|
||||
interpreter = Interactive(archives)
|
||||
interpreter.cmdloop()
|
||||
return
|
||||
|
||||
for path in args:
|
||||
archive = Archive(path)
|
||||
if options.object_name:
|
||||
|
@ -256,17 +349,7 @@ def main():
|
|||
if options.extract:
|
||||
if len(matches) == 1:
|
||||
dump_all = False
|
||||
if options.outfile is None:
|
||||
outfile_path = matches[0].name
|
||||
else:
|
||||
outfile_path = options.outfile
|
||||
if os.path.exists(outfile_path):
|
||||
print('error: outfile "%s" already exists' % (
|
||||
outfile_path))
|
||||
else:
|
||||
print('Saving file to "%s"...' % (outfile_path))
|
||||
with open(outfile_path, 'w') as outfile:
|
||||
outfile.write(matches[0].get_bytes())
|
||||
matches[0].save(path=options.outfile, overwrite=False)
|
||||
else:
|
||||
print('error: multiple objects match "%s". Specify '
|
||||
'the modification time using --mtime.' % (
|
||||
|
|
Loading…
Reference in New Issue