mirror of
https://github.com/gryf/uc1541.git
synced 2026-02-02 19:55:46 +01:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0936db242 |
115
uc1541
115
uc1541
@@ -6,9 +6,18 @@ This extfs provides an access to disk image files for the Commodore
|
|||||||
VIC20/C64/C128. It requires the utility c1541 that comes bundled with Vice,
|
VIC20/C64/C128. It requires the utility c1541 that comes bundled with Vice,
|
||||||
the emulator for the VIC20, C64, C128 and other computers made by Commodore.
|
the emulator for the VIC20, C64, C128 and other computers made by Commodore.
|
||||||
|
|
||||||
|
Changelog:
|
||||||
|
1.2 Added configuration env variables: UC1541_VERBOSE and UC1541_HIDE_DEL.
|
||||||
|
First one, if set to any value, will cause that error messages from
|
||||||
|
c1541 program will be redirected as a failure messages visible in MC.
|
||||||
|
The other variable, when set to any value, cause "del" entries to be
|
||||||
|
not shown in the lister.
|
||||||
|
1.1 Added protect bits, added failsafe for argparse module
|
||||||
|
1.0 Initial release
|
||||||
|
|
||||||
Author: Roman 'gryf' Dobosz <gryf73@gmail.com>
|
Author: Roman 'gryf' Dobosz <gryf73@gmail.com>
|
||||||
Date: 2012-08-07
|
Date: 2012-08-16
|
||||||
Version: 1.0
|
Version: 1.2
|
||||||
Licence: BSD
|
Licence: BSD
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -16,7 +25,6 @@ import sys
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
from argparse import ArgumentParser
|
|
||||||
|
|
||||||
|
|
||||||
class Uc1541(object):
|
class Uc1541(object):
|
||||||
@@ -29,6 +37,8 @@ class Uc1541(object):
|
|||||||
self.arch = archname
|
self.arch = archname
|
||||||
self.out = ''
|
self.out = ''
|
||||||
self.err = ''
|
self.err = ''
|
||||||
|
self._verbose = os.getenv("UC1541_VERBOSE", False)
|
||||||
|
self._hide_del = os.getenv("UC1541_HIDE_DEL", False)
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
"""
|
"""
|
||||||
@@ -43,14 +53,20 @@ class Uc1541(object):
|
|||||||
if Uc1541.PRG.match(line):
|
if Uc1541.PRG.match(line):
|
||||||
blocks, fname, ext, rw = Uc1541.PRG.match(line).groups()
|
blocks, fname, ext, rw = Uc1541.PRG.match(line).groups()
|
||||||
|
|
||||||
|
if ext == 'del' and self._hide_del:
|
||||||
|
continue
|
||||||
|
|
||||||
if '/' in fname:
|
if '/' in fname:
|
||||||
fname = fname.replace('/', '\\')
|
fname = fname.replace('/', '\\')
|
||||||
|
|
||||||
rw = rw.strip() and "-" or "w"
|
if ext == 'del':
|
||||||
|
perms = "----------"
|
||||||
|
else:
|
||||||
|
perms = "-r%s-r--r--" % (rw.strip() and "-" or "w")
|
||||||
|
|
||||||
#fname = ".".join([fname, ext])
|
fname = ".".join([fname, ext])
|
||||||
sys.stdout.write("-r%s-r--r-- 1 %-8d %-8d %8d Jan 01 1980"
|
sys.stdout.write("%s 1 %-8d %-8d %8d Jan 01 1980"
|
||||||
" %s\n" % (rw, os.getuid(), os.getgid(),
|
" %s\n" % (perms, os.getuid(), os.getgid(),
|
||||||
int(blocks) * 256, fname))
|
int(blocks) * 256, fname))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -62,12 +78,15 @@ class Uc1541(object):
|
|||||||
if not self._call_command('delete', dst=dst):
|
if not self._call_command('delete', dst=dst):
|
||||||
return self._show_error()
|
return self._show_error()
|
||||||
|
|
||||||
# In case of error during removing, ERRORCODE is sent to stdout
|
# During removing, a message containing ERRORCODE is sent to stdout
|
||||||
# instead of stderr AND 'ERRORCODE 1' means: # 'everything fine'
|
# instead of stderr. Everything other than 'ERRORCODE 1' (which means:
|
||||||
if '\nERRORCODE 1\n' in self.out:
|
# 'everything fine') is actually a failure. In case of verbose error
|
||||||
return 0
|
# output it is needed to copy self.out to self.err.
|
||||||
|
if '\nERRORCODE 1\n' not in self.out:
|
||||||
|
self.err = self.out
|
||||||
|
return self._show_error()
|
||||||
|
|
||||||
sys.exit(self.out)
|
return 0
|
||||||
|
|
||||||
def copyin(self, dst, src):
|
def copyin(self, dst, src):
|
||||||
"""
|
"""
|
||||||
@@ -102,8 +121,8 @@ class Uc1541(object):
|
|||||||
if "\\" in fname:
|
if "\\" in fname:
|
||||||
fname = fname.replace('\\', '/')
|
fname = fname.replace('\\', '/')
|
||||||
|
|
||||||
#if fname.lower().endswith('.prg') or fname.lower().endswith('.del'):
|
if fname.lower().endswith('.prg') or fname.lower().endswith('.del'):
|
||||||
# fname = fname[:-4]
|
fname = fname[:-4]
|
||||||
|
|
||||||
return fname
|
return fname
|
||||||
|
|
||||||
@@ -111,7 +130,10 @@ class Uc1541(object):
|
|||||||
"""
|
"""
|
||||||
Pass out error output from c1541 execution
|
Pass out error output from c1541 execution
|
||||||
"""
|
"""
|
||||||
sys.exit(self.err)
|
if self._verbose:
|
||||||
|
sys.exit(self.err)
|
||||||
|
else:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def _call_command(self, cmd, src=None, dst=None):
|
def _call_command(self, cmd, src=None, dst=None):
|
||||||
"""
|
"""
|
||||||
@@ -133,7 +155,16 @@ class Uc1541(object):
|
|||||||
return not self.err
|
return not self.err
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
CALL_MAP = {'list': lambda a: Uc1541(a.ARCH).list(),
|
||||||
|
'copyin': lambda a: Uc1541(a.ARCH).copyin(a.SRC, a.DST),
|
||||||
|
'copyout': lambda a: Uc1541(a.ARCH).copyout(a.SRC, a.DST),
|
||||||
|
'rm': lambda a: Uc1541(a.ARCH).rm(a.DST)}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
"""
|
||||||
|
Use ArgumentParser to check for script arguments and execute.
|
||||||
|
"""
|
||||||
parser = ArgumentParser()
|
parser = ArgumentParser()
|
||||||
subparsers = parser.add_subparsers(help='supported commands')
|
subparsers = parser.add_subparsers(help='supported commands')
|
||||||
parser_list = subparsers.add_parser('list', help="List contents of D64 "
|
parser_list = subparsers.add_parser('list', help="List contents of D64 "
|
||||||
@@ -145,25 +176,63 @@ if __name__ == "__main__":
|
|||||||
parser_rm = subparsers.add_parser('rm', help="Delete file from D64 image")
|
parser_rm = subparsers.add_parser('rm', help="Delete file from D64 image")
|
||||||
|
|
||||||
parser_list.add_argument('ARCH', help="D64 Image filename")
|
parser_list.add_argument('ARCH', help="D64 Image filename")
|
||||||
parser_list.set_defaults(func=lambda a: Uc1541(a.ARCH).list())
|
parser_list.set_defaults(func=CALL_MAP['list'])
|
||||||
|
|
||||||
parser_copyin.add_argument('ARCH', help="D64 Image filename")
|
parser_copyin.add_argument('ARCH', help="D64 Image filename")
|
||||||
parser_copyin.add_argument('SRC', help="Source filename")
|
parser_copyin.add_argument('SRC', help="Source filename")
|
||||||
parser_copyin.add_argument('DST', help="Destination filename (to be "
|
parser_copyin.add_argument('DST', help="Destination filename (to be "
|
||||||
"written into D64 image)")
|
"written into D64 image)")
|
||||||
parser_copyin.set_defaults(func=lambda a: Uc1541(a.ARCH). \
|
parser_copyin.set_defaults(func=CALL_MAP['copyin'])
|
||||||
copyin(a.SRC, a.DST))
|
|
||||||
|
|
||||||
parser_copyout.add_argument('ARCH', help="D64 Image filename")
|
parser_copyout.add_argument('ARCH', help="D64 Image filename")
|
||||||
parser_copyout.add_argument('SRC', help="Source filename (to be read from"
|
parser_copyout.add_argument('SRC', help="Source filename (to be read from"
|
||||||
" D64 image")
|
" D64 image")
|
||||||
parser_copyout.add_argument('DST', help="Destination filename")
|
parser_copyout.add_argument('DST', help="Destination filename")
|
||||||
parser_copyout.set_defaults(func=lambda a: Uc1541(a.ARCH). \
|
parser_copyout.set_defaults(func=CALL_MAP['copyout'])
|
||||||
copyout(a.SRC, a.DST))
|
|
||||||
|
|
||||||
parser_rm.add_argument('ARCH', help="D64 Image filename")
|
parser_rm.add_argument('ARCH', help="D64 Image filename")
|
||||||
parser_rm.add_argument('DST', help="File inside D64 image to be deleted")
|
parser_rm.add_argument('DST', help="File inside D64 image to be deleted")
|
||||||
parser_rm.set_defaults(func=lambda a: Uc1541(a.ARCH).rm(a.DST))
|
parser_rm.set_defaults(func=CALL_MAP['rm'])
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
args.func(args)
|
return args.func(args)
|
||||||
|
|
||||||
|
def no_parse():
|
||||||
|
"""
|
||||||
|
Failsafe argument "parsing". Note, that it blindly takes positional
|
||||||
|
arguments without checking them. In case of wrong arguments it will
|
||||||
|
silently exit
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if sys.argv[1] not in ('list', 'copyin', 'copyout', 'rm'):
|
||||||
|
sys.exit(2)
|
||||||
|
except IndexError:
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
class Arg(object):
|
||||||
|
DST = None
|
||||||
|
SRC = None
|
||||||
|
ARCH = None
|
||||||
|
|
||||||
|
arg = Arg()
|
||||||
|
|
||||||
|
try:
|
||||||
|
arg.ARCH = sys.argv[2]
|
||||||
|
if sys.argv[1] in ('copyin', 'copyout'):
|
||||||
|
arg.SRC = sys.argv[3]
|
||||||
|
arg.DST = sys.argv[4]
|
||||||
|
elif sys.argv[1] == 'rm':
|
||||||
|
arg.DST = sys.argv[3]
|
||||||
|
except IndexError:
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
CALL_MAP[sys.argv[1]](arg)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
parse_func = parse_args
|
||||||
|
except ImportError:
|
||||||
|
parse_func = no_parse
|
||||||
|
|
||||||
|
parse_func()
|
||||||
|
|||||||
Reference in New Issue
Block a user