2017-05-02 21:18:29 +00:00
import os
2017-05-02 18:17:32 +00:00
import sys
2017-05-04 17:09:15 +00:00
import zlib
2017-05-02 18:17:32 +00:00
2016-04-13 00:13:33 +00:00
import logging
2017-05-02 18:17:32 +00:00
log = logging . getLogger ( __name__ )
2016-02-13 04:36:33 +00:00
2017-05-03 02:43:21 +00:00
from _metadata import __version__
2016-02-13 04:36:33 +00:00
try :
import numpy as np
except ImportError :
raise RuntimeError ( " atrcopy %s requires numpy " % __version__ )
from errors import *
2017-03-21 23:25:59 +00:00
from ataridos import AtrHeader , AtariDosDiskImage , BootDiskImage , AtariDosFile , XexContainerSegment , get_xex , add_atr_header
2017-02-22 20:11:28 +00:00
from dos33 import Dos33DiskImage
2016-05-06 00:44:20 +00:00
from kboot import KBootImage , add_xexboot_header
2017-03-21 23:25:59 +00:00
from segments import SegmentData , SegmentSaver , DefaultSegment , EmptySegment , ObjSegment , RawSectorsSegment , SegmentedFileSegment , user_bit_mask , match_bit_mask , comment_bit_mask , data_style , selected_bit_mask , diff_bit_mask , not_user_bit_mask , interleave_segments , SegmentList , get_style_mask , get_style_bits
2016-02-13 04:36:33 +00:00
from spartados import SpartaDosDiskImage
2016-06-03 20:05:16 +00:00
from cartridge import A8CartHeader , AtariCartImage
2016-06-03 19:40:48 +00:00
from parsers import SegmentParser , DefaultSegmentParser , guess_parser_for_mime , guess_parser_for_system , iter_parsers , iter_known_segment_parsers , mime_parse_order
2017-02-26 20:31:34 +00:00
from utils import to_numpy , text_to_int
2016-02-13 05:36:08 +00:00
2016-02-13 04:36:33 +00:00
def process ( image , dirent , options ) :
skip = False
action = " copying to "
filename = dirent . get_filename ( )
outfilename = filename
if options . no_sys :
if dirent . ext == " SYS " :
skip = True
action = " skipping system file "
if not skip :
if options . xex :
outfilename = " %s %s .XEX " % ( dirent . filename , dirent . ext )
if options . lower :
outfilename = outfilename . lower ( )
2017-03-23 17:06:37 +00:00
2016-02-13 04:36:33 +00:00
if options . dry_run :
action = " DRY_RUN: %s " % action
skip = True
if options . extract :
print " %s : %s %s " % ( dirent , action , outfilename )
if not skip :
bytes = image . get_file ( dirent )
with open ( outfilename , " wb " ) as fh :
fh . write ( bytes )
else :
print dirent
2017-03-23 17:06:37 +00:00
2017-02-24 19:57:51 +00:00
def find_diskimage ( filename ) :
2017-03-07 18:43:46 +00:00
try :
with open ( filename , " rb " ) as fh :
2017-02-24 19:57:51 +00:00
if options . verbose :
2017-03-07 18:43:46 +00:00
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
break
2017-02-24 19:57:51 +00:00
if parser is None :
2017-03-07 18:43:46 +00:00
print " %s : Unknown disk image type " % filename
except UnsupportedDiskImage , e :
print " %s : %s " % ( filename , e )
return None
2017-05-04 16:45:20 +00:00
except IOError , e :
print " %s : %s " % ( filename , e )
return None
2017-03-07 18:43:46 +00:00
else :
parser . image . filename = filename
parser . image . ext = " "
return parser
2017-02-24 19:57:51 +00:00
2017-03-23 17:06:37 +00:00
2017-02-24 19:57:51 +00:00
def extract_files ( image , files ) :
2017-05-03 03:02:54 +00:00
if options . all :
files = image . files
2017-02-24 19:57:51 +00:00
for name in files :
try :
dirent = image . find_dirent ( name )
except FileNotFound :
print " %s not in %s " % ( name , image )
continue
2017-05-02 21:18:29 +00:00
output = dirent . filename
if options . lower :
output = output . lower ( )
2017-02-24 19:57:51 +00:00
if not options . dry_run :
data = image . get_file ( dirent )
2017-05-02 21:18:29 +00:00
if os . path . exists ( output ) and not options . force :
print " skipping %s , file exists. Use -f to overwrite " % output
continue
print " extracting %s -> %s " % ( name , output )
with open ( output , " wb " ) as fh :
2017-02-24 19:57:51 +00:00
fh . write ( data )
2017-05-02 21:18:29 +00:00
else :
print " extracting %s -> %s " % ( name , output )
2017-02-24 19:57:51 +00:00
2017-03-23 17:06:37 +00:00
2017-02-26 20:14:23 +00:00
def save_file ( image , name , filetype , data ) :
try :
dirent = image . find_dirent ( name )
if options . force :
image . delete_file ( name )
else :
print " skipping %s , use -f to overwrite " % ( name )
return False
except FileNotFound :
pass
2017-05-03 19:03:18 +00:00
print " copying %s to %s " % ( name , image . filename )
2017-02-26 20:14:23 +00:00
if not options . dry_run :
image . write_file ( name , filetype , data )
return True
return False
2017-02-24 19:57:51 +00:00
def add_files ( image , files ) :
filetype = options . filetype
if not filetype :
filetype = image . default_filetype
changed = False
for name in files :
2017-02-26 20:14:23 +00:00
with open ( name , " rb " ) as fh :
data = fh . read ( )
changed = save_file ( image , name , filetype , data )
2017-02-24 19:57:51 +00:00
if changed :
image . save ( )
2017-03-23 17:06:37 +00:00
2017-02-24 19:57:51 +00:00
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 ( )
2017-03-23 17:06:37 +00:00
2017-05-04 19:44:44 +00:00
def list_files ( image , files , show_crc = False , show_metadata = False ) :
2017-02-24 19:57:51 +00:00
files = set ( files )
for dirent in image . files :
if not files or dirent . filename in files :
2017-05-04 19:44:44 +00:00
if show_crc :
2017-05-04 17:09:15 +00:00
data = image . get_file ( dirent )
crc = zlib . crc32 ( data ) & 0xffffffff # correct for some platforms that return signed int
extra = " %08x " % crc
else :
extra = " "
print ( " %s %s " % ( dirent , extra ) )
2017-05-04 19:44:44 +00:00
if show_metadata :
2017-02-27 01:08:55 +00:00
print dirent . extra_metadata ( image )
2017-02-24 19:57:51 +00:00
2017-03-23 17:06:37 +00:00
2017-05-04 17:09:15 +00:00
def crc_files ( image , files ) :
files = set ( files )
for dirent in image . files :
if not files or dirent . filename in files :
data = image . get_file ( dirent )
crc = zlib . crc32 ( data ) & 0xffffffff # correct for some platforms that return signed int
print ( " %s : %08x " % ( dirent . filename , crc ) )
2017-05-02 18:17:32 +00:00
def assemble ( image , source_files , data_files , run_addr = " " ) :
2017-02-26 20:31:34 +00:00
if source_files :
try :
import pyatasm
except ImportError :
raise AtrError ( " Please install pyatasm to compile code. " )
2017-02-26 20:14:23 +00:00
changed = False
2017-02-26 20:31:34 +00:00
segments = SegmentList ( )
for name in source_files :
2017-02-26 20:14:23 +00:00
try :
asm = pyatasm . Assemble ( name )
except SyntaxError , e :
raise AtrError ( " Assembly error: %s " % e . msg )
2017-05-02 18:17:32 +00:00
log . debug ( " Assembled %s into: " % name )
2017-02-26 20:14:23 +00:00
for first , last , object_code in asm . segments :
2017-02-26 20:31:34 +00:00
s = segments . add_segment ( object_code , first )
2017-05-02 18:17:32 +00:00
log . debug ( " %s " % s . name )
2017-02-26 20:31:34 +00:00
for name in data_files :
if " @ " not in name :
raise AtrError ( " Data files must include a load address specified with the @ char " )
name , addr = name . rsplit ( " @ " , 1 )
first = text_to_int ( addr )
2017-05-02 18:17:32 +00:00
log . debug ( " Adding data file %s at $ %04x " % ( name , first ) )
subset = slice ( 0 , sys . maxint )
2017-05-01 15:41:23 +00:00
if " [ " in name and " ] " in name :
name , slicetext = name . rsplit ( " [ " , 1 )
if " : " in slicetext :
start , end = slicetext . split ( " : " , 1 )
try :
start = int ( start )
except :
start = 0
if end . endswith ( " ] " ) :
end = end [ : - 1 ]
try :
end = int ( end )
except :
end = None
subset = slice ( start , end )
2017-02-26 20:31:34 +00:00
with open ( name , ' rb ' ) as fh :
2017-05-01 15:41:23 +00:00
data = fh . read ( ) [ subset ]
2017-02-26 20:31:34 +00:00
s = segments . add_segment ( data , first )
2017-05-02 18:17:32 +00:00
log . debug ( " read data for %s " % s . name )
2017-02-26 20:14:23 +00:00
if options . verbose :
for s in segments :
print " %s - %04x ) " % ( str ( s ) [ : - 1 ] , s . start_addr + len ( s ) )
2017-05-02 18:17:32 +00:00
if run_addr :
try :
run_addr = text_to_int ( run_addr )
except ValueError :
run_addr = None
file_data , filetype = image . create_executable_file_image ( segments , run_addr )
2017-05-03 19:03:18 +00:00
print " total file size: $ %x ( %d ) bytes " % ( len ( file_data ) , len ( file_data ) )
2017-02-26 20:14:23 +00:00
changed = save_file ( image , options . output , filetype , file_data )
if changed :
image . save ( )
2017-03-23 17:06:37 +00:00
2017-02-26 21:07:36 +00:00
def shred_image ( image , value = 0 ) :
print " shredding: free sectors from %s filled with %d " % ( image , value )
if not options . dry_run :
image . shred ( )
image . save ( )
2017-02-24 19:57:51 +00:00
2017-05-03 19:25:37 +00:00
def get_template_path ( rel_path = " templates " ) :
path = __file__
template_path = os . path . normpath ( os . path . join ( os . path . dirname ( path ) , rel_path ) )
frozen = getattr ( sys , ' frozen ' , False )
if frozen :
if frozen == True :
# pyinstaller sets frozen=True and uses sys._MEIPASS
root = sys . _MEIPASS
template_path = os . path . normpath ( os . path . join ( root , template_path ) )
elif frozen == ' macosx_app ' :
#print "FROZEN!!! %s" % frozen
root = os . environ [ ' RESOURCEPATH ' ]
if " .zip/ " in template_path :
zippath , template_path = template_path . split ( " .zip/ " )
template_path = os . path . normpath ( os . path . join ( root , template_path ) )
else :
print " App packager %s not yet supported for image paths!!! "
return template_path
2017-05-05 04:29:07 +00:00
def get_template_info ( ) :
2017-05-03 19:25:37 +00:00
import glob
path = get_template_path ( )
files = glob . glob ( os . path . join ( path , " * " ) )
2017-05-05 04:29:07 +00:00
lines = [ ]
lines . append ( " available templates: " )
2017-05-04 17:45:45 +00:00
for name in sorted ( files ) :
2017-05-04 14:02:09 +00:00
if name . endswith ( " .inf " ) :
continue
try :
with open ( name + " .inf " , " r " ) as fh :
description = fh . read ( ) . strip ( )
except IOError :
description = " "
2017-05-05 04:29:07 +00:00
lines . append ( " %-14s %s " % ( os . path . basename ( name ) , description ) )
return os . linesep . join ( lines ) + os . linesep
2017-05-03 19:25:37 +00:00
def get_template_data ( template ) :
path = os . path . join ( get_template_path ( ) , template )
try :
with open ( path , " rb " ) as fh :
data = fh . read ( )
except :
raise InvalidDiskImage ( " Template disk image %s not found " % template )
2017-05-04 19:56:16 +00:00
try :
with open ( path + " .inf " , " r " ) as fh :
inf = fh . read ( ) . strip ( )
except IOError :
inf = " "
return data , inf
2017-05-03 19:25:37 +00:00
def create_image ( template , name ) :
2017-05-04 19:56:16 +00:00
data , inf = get_template_data ( template )
print " using %s template: %s " % ( template , inf )
2017-05-03 19:25:37 +00:00
if not options . dry_run :
if os . path . exists ( name ) and not options . force :
print " skipping %s , use -f to overwrite " % ( name )
else :
with open ( name , " wb " ) as fh :
fh . write ( data )
parser = find_diskimage ( name )
2017-05-04 19:56:16 +00:00
print " created %s : %s " % ( name , str ( parser . image ) )
2017-05-03 19:25:37 +00:00
list_files ( parser . image , [ ] )
2017-05-04 19:56:16 +00:00
else :
print " creating %s " % name
2017-05-03 19:25:37 +00:00
2017-05-02 21:18:29 +00:00
2016-02-13 04:36:33 +00:00
def run ( ) :
import argparse
2017-02-24 19:57:51 +00:00
global options
2017-03-23 17:06:37 +00:00
2017-05-02 21:18:29 +00:00
# Subparser command aliasing from: https://gist.github.com/sampsyo/471779
# released into the public domain by its author
class AliasedSubParsersAction ( argparse . _SubParsersAction ) :
class _AliasedPseudoAction ( argparse . Action ) :
def __init__ ( self , name , aliases , help ) :
dest = name
if aliases :
dest + = ' ( %s ) ' % ' , ' . join ( aliases )
sup = super ( AliasedSubParsersAction . _AliasedPseudoAction , self )
sup . __init__ ( option_strings = [ ] , dest = dest , help = help )
def add_parser ( self , name , * * kwargs ) :
if ' aliases ' in kwargs :
aliases = kwargs [ ' aliases ' ]
del kwargs [ ' aliases ' ]
else :
aliases = [ ]
parser = super ( AliasedSubParsersAction , self ) . add_parser ( name , * * kwargs )
# Make the aliases work.
for alias in aliases :
self . _name_parser_map [ alias ] = parser
# Make the help text reflect them, first removing old help entry.
if ' help ' in kwargs :
help = kwargs . pop ( ' help ' )
self . _choices_actions . pop ( )
pseudo_action = self . _AliasedPseudoAction ( name , aliases , help )
self . _choices_actions . append ( pseudo_action )
return parser
command_aliases = {
" list " : [ " t " , " ls " , " dir " , " catalog " ] ,
2017-05-04 17:09:15 +00:00
" crc " : [ ] ,
2017-05-02 21:18:29 +00:00
" extract " : [ " x " ] ,
" add " : [ " a " ] ,
" create " : [ " c " ] ,
" assemble " : [ " s " , " asm " ] ,
" delete " : [ " rm " , " del " ] ,
" vtoc " : [ " v " ] ,
" segments " : [ ] ,
}
2017-05-05 04:29:07 +00:00
# reverse aliases does the inverse mapping of command aliases, including
# the identity mapping of "command" to "command"
reverse_aliases = { z : k for k , v in command_aliases . iteritems ( ) for z in ( v + [ k ] ) }
2017-05-04 17:14:45 +00:00
skip_diskimage_summary = set ( [ " crc " ] )
2017-05-02 21:18:29 +00:00
usage = " %(prog)s [-h] [-v] [--dry-run] DISK_IMAGE [...] "
subparser_usage = " %(prog)s [-h] [-v] [--dry-run] DISK_IMAGE "
parser = argparse . ArgumentParser ( prog = " atrcopy DISK_IMAGE " , description = " Manipulate files on several types of 8-bit computer disk images. Type ' %(prog)s COMMAND --help ' for list of options available for each command. " )
parser . register ( ' action ' , ' parsers ' , AliasedSubParsersAction )
2016-02-13 04:36:33 +00:00
parser . add_argument ( " -v " , " --verbose " , default = 0 , action = " count " )
2017-02-27 20:38:28 +00:00
parser . add_argument ( " --dry-run " , action = " store_true " , default = False , help = " don ' t perform operation, just show what would have happened " )
2017-05-02 21:18:29 +00:00
subparsers = parser . add_subparsers ( dest = ' command ' , help = ' ' , metavar = " COMMAND " )
command = " list "
list_parser = subparsers . add_parser ( command , help = " List files on the disk image. This is the default if no command is specified " , aliases = command_aliases [ command ] )
list_parser . add_argument ( " -g " , " --segments " , action = " store_true " , default = False , help = " display segments " )
list_parser . add_argument ( " -m " , " --metadata " , action = " store_true " , default = False , help = " show extra metadata for named files " )
2017-05-04 17:09:15 +00:00
list_parser . add_argument ( " -c " , " --crc " , action = " store_true " , default = False , help = " compute CRC32 for each file " )
2017-05-02 21:18:29 +00:00
list_parser . add_argument ( " files " , metavar = " FILENAME " , nargs = " * " , help = " an optional list of files to display " )
2017-05-04 17:09:15 +00:00
command = " crc "
crc_parser = subparsers . add_parser ( command , help = " List files on the disk image and the CRC32 value in format suitable for parsing " , aliases = command_aliases [ command ] )
crc_parser . add_argument ( " files " , metavar = " FILENAME " , nargs = " * " , help = " an optional list of files to display " )
2017-05-02 21:18:29 +00:00
command = " extract "
extract_parser = subparsers . add_parser ( command , help = " Copy files from the disk image to the local filesystem " , aliases = command_aliases [ command ] )
extract_parser . add_argument ( " -a " , " --all " , action = " store_true " , default = False , help = " operate on all files on disk image " )
extract_parser . add_argument ( " -l " , " --lower " , action = " store_true " , default = False , help = " convert extracted filenames to lower case " )
#extract_parser.add_argument("-n", "--no-sys", action="store_true", default=False, help="only extract things that look like games (no DOS or .SYS files)")
extract_parser . add_argument ( " -e " , " --ext " , action = " store " , nargs = 1 , default = False , help = " add the specified extension " )
extract_parser . add_argument ( " -f " , " --force " , action = " store_true " , default = False , help = " allow file overwrites on local filesystem " )
extract_parser . add_argument ( " files " , metavar = " FILENAME " , nargs = " * " , help = " if not using the -a/--all option, a file (or list of files) to extract from the disk image. " )
command = " add "
add_parser = subparsers . add_parser ( command , help = " Add files to the disk image " , aliases = command_aliases [ command ] )
add_parser . add_argument ( " -f " , " --force " , action = " store_true " , default = False , help = " allow file overwrites in the disk image " )
add_parser . add_argument ( " -t " , " --filetype " , action = " store " , default = " " , help = " file type metadata for writing to disk images that require it (e.g. DOS 3.3) " )
add_parser . add_argument ( " files " , metavar = " FILENAME " , nargs = " + " , help = " a file (or list of files) to copy to the disk image " )
2017-05-03 19:25:37 +00:00
command = " create "
2017-05-05 04:29:07 +00:00
create_parser = subparsers . add_parser ( command , help = " Create a new disk image " , aliases = command_aliases [ command ] , epilog = " <generated on demand to list available templates> " , formatter_class = argparse . RawDescriptionHelpFormatter )
2017-05-03 19:25:37 +00:00
create_parser . add_argument ( " -f " , " --force " , action = " store_true " , default = False , help = " replace disk image file if it exists " )
2017-05-05 04:29:07 +00:00
create_parser . add_argument ( " template " , metavar = " TEMPLATE " , nargs = 1 , help = " template to use to create new disk image; see below for list of available built-in templates " )
2017-05-02 21:18:29 +00:00
command = " assemble "
assembly_parser = subparsers . add_parser ( command , help = " Create a new binary file in the disk image " , aliases = command_aliases [ command ] )
assembly_parser . add_argument ( " -f " , " --force " , action = " store_true " , default = False , help = " allow file overwrites in the disk image " )
assembly_parser . add_argument ( " -s " , " --asm " , nargs = " * " , action = " append " , help = " source file(s) to assemble using pyatasm " )
assembly_parser . add_argument ( " -d " , " -b " , " --data " , nargs = " * " , action = " append " , help = " binary data file(s) to add to assembly, specify as file@addr. Only a portion of the file may be included; specify the subset using standard python slice notation: file[subset]@addr " )
assembly_parser . add_argument ( " -r " , " --run-addr " , " --brun " , action = " store " , default = " " , help = " run address of binary file if not the first byte of the first segment " )
assembly_parser . add_argument ( " -o " , " --output " , action = " store " , default = " " , required = True , help = " output file name in disk image " )
command = " delete "
delete_parser = subparsers . add_parser ( command , help = " Delete files from the disk image " , aliases = command_aliases [ command ] )
delete_parser . add_argument ( " -f " , " --force " , action = " store_true " , default = False , help = " remove the file even if it is write protected ( ' locked ' in Atari DOS 2 terms), if write-protect is supported disk image " )
delete_parser . add_argument ( " files " , metavar = " FILENAME " , nargs = " + " , help = " a file (or list of files) to remove from the disk image " )
command = " vtoc "
vtoc_parser = subparsers . add_parser ( command , help = " Show a formatted display of sectors free in the disk image " , aliases = command_aliases [ command ] )
vtoc_parser . add_argument ( " -e " , " --clear-empty " , action = " store_true " , default = False , help = " fill empty sectors with 0 " )
command = " segments "
vtoc_parser = subparsers . add_parser ( command , help = " Show the list of parsed segments in the disk image " , aliases = command_aliases [ command ] )
# argparse doesn't seem to allow an argument fixed to item 1, so have to
# hack with the arg list to get arg #1 to be the disk image. Because of
# this hack, we have to perform an additional hack to figure out what the
# --help option applies to if it's in the argument list.
args = list ( sys . argv [ 1 : ] )
if len ( args ) > 0 :
found_help = - 1
first_non_dash = 0
num_non_dash = 0
2017-05-03 04:26:28 +00:00
non_dash = [ ]
for i , arg in enumerate ( args ) :
if arg . startswith ( " - " ) :
2017-05-02 21:18:29 +00:00
if i == 0 :
first_non_dash = - 1
2017-05-03 04:26:28 +00:00
if arg == " -h " or arg == " --help " :
2017-05-02 21:18:29 +00:00
found_help = i
else :
num_non_dash + = 1
2017-05-03 04:26:28 +00:00
non_dash . append ( arg )
2017-05-02 21:18:29 +00:00
if first_non_dash < 0 :
first_non_dash = i
if found_help > = 0 or first_non_dash < 0 :
if found_help == 0 or first_non_dash < 0 :
# put dummy argument so help for entire script will be shown
args = [ " --help " ]
2017-05-05 04:29:07 +00:00
elif non_dash [ 0 ] in reverse_aliases :
2017-05-02 21:18:29 +00:00
# if the first argument without a leading dash looks like a
# command instead of a disk image, show help for that command
2017-05-03 04:26:28 +00:00
args = [ non_dash [ 0 ] , " --help " ]
2017-05-05 04:29:07 +00:00
elif len ( non_dash ) > 0 and non_dash [ 1 ] in reverse_aliases :
2017-05-03 04:26:28 +00:00
# if the first argument without a leading dash looks like a
# command instead of a disk image, show help for that command
args = [ non_dash [ 1 ] , " --help " ]
2017-05-02 21:18:29 +00:00
else :
# show script help
args = [ " --help " ]
2017-05-05 17:59:28 +00:00
if reverse_aliases . get ( args [ 0 ] , None ) == " create " :
2017-05-05 04:29:07 +00:00
create_parser . epilog = get_template_info ( )
2017-05-02 21:18:29 +00:00
else :
2017-05-05 04:29:07 +00:00
# Allow global options to come before or after disk image name
disk_image_name = args [ first_non_dash ]
args [ first_non_dash : first_non_dash + 1 ] = [ ]
if num_non_dash == 1 :
# If there is only a disk image but no command specified,
# use the default
args . append ( ' list ' )
2017-05-02 21:18:29 +00:00
else :
disk_image_name = None
# print "parsing: %s" % str(args)
options = parser . parse_args ( args )
# print options
2017-05-05 04:29:07 +00:00
command = reverse_aliases [ options . command ]
2016-02-13 04:36:33 +00:00
2016-04-13 00:13:33 +00:00
# Turn off debug messages by default
2017-02-25 06:20:07 +00:00
logging . basicConfig ( level = logging . WARNING )
2016-04-13 00:13:33 +00:00
log = logging . getLogger ( " atrcopy " )
if options . verbose :
log . setLevel ( logging . DEBUG )
else :
log . setLevel ( logging . INFO )
2017-03-23 17:06:37 +00:00
2017-05-02 21:18:29 +00:00
if command == " create " :
2017-05-05 20:33:09 +00:00
create_image ( options . template [ 0 ] , disk_image_name )
2017-05-02 21:18:29 +00:00
else :
parser = find_diskimage ( disk_image_name )
2017-02-24 19:57:51 +00:00
if parser and parser . image :
2017-05-04 17:14:45 +00:00
if command not in skip_diskimage_summary :
print " %s : %s " % ( disk_image_name , parser . image )
2017-05-02 21:18:29 +00:00
if command == " vtoc " :
2017-02-26 22:14:25 +00:00
vtoc = parser . image . get_vtoc_object ( )
print vtoc
2017-05-02 21:18:29 +00:00
if options . clear_empty :
shred_image ( parser . image )
elif command == " list " :
2017-05-04 19:44:44 +00:00
list_files ( parser . image , options . files , options . crc , options . metadata )
2017-05-04 17:09:15 +00:00
elif command == " crc " :
crc_files ( parser . image , options . files )
2017-05-02 21:18:29 +00:00
elif command == " add " :
add_files ( parser . image , options . files )
elif command == " delete " :
remove_files ( parser . image , options . files )
elif command == " extract " :
extract_files ( parser . image , options . files )
elif command == " assemble " :
asm = options . asm [ 0 ] if options . asm else [ ]
data = options . data [ 0 ] if options . data else [ ]
assemble ( parser . image , asm , data , options . run_addr )
elif command == " segments " :
print " \n " . join ( [ str ( a ) for a in parser . segments ] )
else :
log . error ( " Invalid disk image: %s " % disk_image_name )