mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-06-09 15:29:27 +00:00
Added file manipulation commands to atrcopy script
This commit is contained in:
parent
8ec391edc9
commit
d19dd3b218
|
@ -45,21 +45,118 @@ def process(image, dirent, options):
|
||||||
else:
|
else:
|
||||||
print dirent
|
print dirent
|
||||||
|
|
||||||
|
def find_diskimage(filename):
|
||||||
|
with open(filename, "rb") as fh:
|
||||||
|
if options.verbose:
|
||||||
|
print "Loading file %s" % filename
|
||||||
|
rawdata = SegmentData(fh.read())
|
||||||
|
parser = None
|
||||||
|
for mime in mime_parse_order:
|
||||||
|
if options.verbose:
|
||||||
|
print "Trying MIME type %s" % mime
|
||||||
|
parser = guess_parser_for_mime(mime, rawdata, options.verbose)
|
||||||
|
if parser is None:
|
||||||
|
continue
|
||||||
|
if options.verbose:
|
||||||
|
print "Found parser %s" % parser.menu_name
|
||||||
|
print "%s: %s" % (filename, parser.image)
|
||||||
|
break
|
||||||
|
if parser is None:
|
||||||
|
print "%s: Unknown disk image type" % filename
|
||||||
|
parser.image.filename = filename
|
||||||
|
parser.image.ext = ""
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def extract_all(image):
|
||||||
|
if image.files or options.force:
|
||||||
|
for dirent in image.files:
|
||||||
|
try:
|
||||||
|
process(image, dirent)
|
||||||
|
except FileNumberMismatchError164:
|
||||||
|
print "Error 164: %s" % str(dirent)
|
||||||
|
except ByteNotInFile166:
|
||||||
|
print "Invalid sector for: %s" % str(dirent)
|
||||||
|
|
||||||
|
def extract_files(image, files):
|
||||||
|
for name in files:
|
||||||
|
try:
|
||||||
|
dirent = image.find_dirent(name)
|
||||||
|
except FileNotFound:
|
||||||
|
print "%s not in %s" % (name, image)
|
||||||
|
continue
|
||||||
|
print "extracting %s" % name
|
||||||
|
if not options.dry_run:
|
||||||
|
data = image.get_file(dirent)
|
||||||
|
with open(name, "wb") as fh:
|
||||||
|
fh.write(data)
|
||||||
|
|
||||||
|
def add_files(image, files):
|
||||||
|
filetype = options.filetype
|
||||||
|
if not filetype:
|
||||||
|
filetype = image.default_filetype
|
||||||
|
changed = False
|
||||||
|
for name in files:
|
||||||
|
try:
|
||||||
|
dirent = image.find_dirent(name)
|
||||||
|
if options.force:
|
||||||
|
image.delete_file(name)
|
||||||
|
else:
|
||||||
|
print "skipping %s, use -f to overwrite" % (name)
|
||||||
|
continue
|
||||||
|
except FileNotFound:
|
||||||
|
pass
|
||||||
|
print "copying %s to %s" % (name, image)
|
||||||
|
if not options.dry_run:
|
||||||
|
with open(name, "rb") as fh:
|
||||||
|
data = fh.read()
|
||||||
|
image.write_file(name, filetype, data)
|
||||||
|
changed = True
|
||||||
|
if changed:
|
||||||
|
image.save()
|
||||||
|
|
||||||
|
def remove_files(image, files):
|
||||||
|
changed = False
|
||||||
|
for name in files:
|
||||||
|
try:
|
||||||
|
dirent = image.find_dirent(name)
|
||||||
|
except FileNotFound:
|
||||||
|
print "%s not in %s" % (name, image)
|
||||||
|
continue
|
||||||
|
print "removing %s from %s" % (name, image)
|
||||||
|
if not options.dry_run:
|
||||||
|
image.delete_file(name)
|
||||||
|
changed = True
|
||||||
|
if changed:
|
||||||
|
image.save()
|
||||||
|
|
||||||
|
def list_files(image, files):
|
||||||
|
files = set(files)
|
||||||
|
for dirent in image.files:
|
||||||
|
if not files or dirent.filename in files:
|
||||||
|
print dirent
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
global options
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Extract images off ATR format disks")
|
parser = argparse.ArgumentParser(description="Manipulate files on several types of 8-bit computer disk images")
|
||||||
parser.add_argument("-v", "--verbose", default=0, action="count")
|
parser.add_argument("-v", "--verbose", default=0, action="count")
|
||||||
parser.add_argument("-d", "--debug", action="store_true", default=False, help="debug the currently under-development parser")
|
parser.add_argument("-d", "--debug", action="store_true", default=False, help="debug the currently under-development parser")
|
||||||
parser.add_argument("-l", "--lower", action="store_true", default=False, help="convert filenames to lower case")
|
parser.add_argument("-l", "--lower", action="store_true", default=False, help="convert filenames to lower case")
|
||||||
parser.add_argument("--dry-run", action="store_true", default=False, help="don't extract, just show what would have been extracted")
|
parser.add_argument("--dry-run", action="store_true", default=False, help="don't extract, just show what would have been extracted")
|
||||||
parser.add_argument("-n", "--no-sys", action="store_true", default=False, help="only extract things that look like games (no DOS or .SYS files)")
|
parser.add_argument("-n", "--no-sys", action="store_true", default=False, help="only extract things that look like games (no DOS or .SYS files)")
|
||||||
parser.add_argument("-x", "--extract", action="store_true", default=False, help="extract files")
|
parser.add_argument("--all", action="store_true", default=False, help="extract all files")
|
||||||
parser.add_argument("--xex", action="store_true", default=False, help="add .xex extension")
|
parser.add_argument("--xex", action="store_true", default=False, help="add .xex extension")
|
||||||
parser.add_argument("-f", "--force", action="store_true", default=False, help="force operation on disk images that have bad directory entries or look like boot disks")
|
parser.add_argument("-f", "--force", action="store_true", default=False, help="force operation, allowing file overwrites and operation on non-standard disk images")
|
||||||
parser.add_argument("files", metavar="ATR", nargs="+", help="an ATR image file [or a list of them]")
|
parser.add_argument("files", metavar="IMAGE", nargs="+", help="a disk image file [or a list of them]")
|
||||||
parser.add_argument("-s", "--segments", action="store_true", default=False, help="display segments")
|
parser.add_argument("-s", "--segments", action="store_true", default=False, help="display segments")
|
||||||
|
parser.add_argument("-x", "-e", "--extract", action="store_true", default=False, help="extract named files")
|
||||||
|
parser.add_argument("-a", "--add", action="store_true", default=False, help="add files to image")
|
||||||
|
parser.add_argument("-r", "--remove", action="store_true", default=False, help="remove named files from image")
|
||||||
|
parser.add_argument("-t", "--filetype", action="store", default="", help="file type metadata for writing to disk images that require it")
|
||||||
options, extra_args = parser.parse_known_args()
|
options, extra_args = parser.parse_known_args()
|
||||||
|
|
||||||
# Turn off debug messages by default
|
# Turn off debug messages by default
|
||||||
|
@ -69,31 +166,24 @@ def run():
|
||||||
else:
|
else:
|
||||||
log.setLevel(logging.INFO)
|
log.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
file_list = []
|
||||||
|
if options.add or options.extract or options.remove:
|
||||||
|
image = options.files.pop()
|
||||||
|
file_list = options.files
|
||||||
|
options.files = [image]
|
||||||
|
|
||||||
for filename in options.files:
|
for filename in options.files:
|
||||||
with open(filename, "rb") as fh:
|
parser = find_diskimage(filename)
|
||||||
if options.verbose:
|
if parser and parser.image:
|
||||||
print "Loading file %s" % filename
|
if options.all:
|
||||||
rawdata = SegmentData(fh.read())
|
extract_all(parser.image)
|
||||||
parser = None
|
elif options.segments:
|
||||||
for mime in mime_parse_order:
|
print "\n".join([str(a) for a in parser.segments])
|
||||||
if options.verbose:
|
elif options.add:
|
||||||
print "Trying MIME type %s" % mime
|
add_files(parser.image, file_list)
|
||||||
parser = guess_parser_for_mime(mime, rawdata, options.verbose)
|
elif options.extract:
|
||||||
if parser is None:
|
extract_files(parser.image, file_list)
|
||||||
continue
|
elif options.remove:
|
||||||
if options.verbose:
|
remove_files(parser.image, file_list)
|
||||||
print "Found parser %s" % parser.menu_name
|
else:
|
||||||
print "%s: %s" % (filename, parser.image)
|
list_files(parser.image, file_list)
|
||||||
if options.segments:
|
|
||||||
print "\n".join([str(a) for a in parser.segments])
|
|
||||||
elif parser.image.files or options.force:
|
|
||||||
for dirent in parser.image.files:
|
|
||||||
try:
|
|
||||||
process(parser.image, dirent, options)
|
|
||||||
except FileNumberMismatchError164:
|
|
||||||
print "Error 164: %s" % str(dirent)
|
|
||||||
except ByteNotInFile166:
|
|
||||||
print "Invalid sector for: %s" % str(dirent)
|
|
||||||
break
|
|
||||||
if parser is None:
|
|
||||||
print "%s: Unknown file type" % filename
|
|
||||||
|
|
|
@ -91,6 +91,7 @@ class DiskImageBase(object):
|
||||||
self.files = [] # all dirents that show up in a normal dir listing
|
self.files = [] # all dirents that show up in a normal dir listing
|
||||||
self.segments = []
|
self.segments = []
|
||||||
self.all_sane = True
|
self.all_sane = True
|
||||||
|
self.default_filetype = ""
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
|
|
|
@ -357,6 +357,7 @@ class Dos33Header(BaseHeader):
|
||||||
class Dos33DiskImage(DiskImageBase):
|
class Dos33DiskImage(DiskImageBase):
|
||||||
def __init__(self, rawdata, filename=""):
|
def __init__(self, rawdata, filename=""):
|
||||||
DiskImageBase.__init__(self, rawdata, filename)
|
DiskImageBase.__init__(self, rawdata, filename)
|
||||||
|
self.default_filetype = "B"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.header)
|
return str(self.header)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user