From a0936db242605303a253a3da94032c3b05f9ffcb Mon Sep 17 00:00:00 2001 From: gryf Date: Mon, 24 Sep 2012 21:06:48 +0200 Subject: [PATCH] Added proctect bits, configuration variables --- uc1541 | 115 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 23 deletions(-) diff --git a/uc1541 b/uc1541 index a079fa9..9aa2057 100755 --- a/uc1541 +++ b/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, 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 -Date: 2012-08-07 -Version: 1.0 +Date: 2012-08-16 +Version: 1.2 Licence: BSD """ @@ -16,7 +25,6 @@ import sys import re import os from subprocess import Popen, PIPE -from argparse import ArgumentParser class Uc1541(object): @@ -29,6 +37,8 @@ class Uc1541(object): self.arch = archname self.out = '' self.err = '' + self._verbose = os.getenv("UC1541_VERBOSE", False) + self._hide_del = os.getenv("UC1541_HIDE_DEL", False) def list(self): """ @@ -43,14 +53,20 @@ class Uc1541(object): if Uc1541.PRG.match(line): blocks, fname, ext, rw = Uc1541.PRG.match(line).groups() + if ext == 'del' and self._hide_del: + continue + if '/' in fname: 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]) - sys.stdout.write("-r%s-r--r-- 1 %-8d %-8d %8d Jan 01 1980" - " %s\n" % (rw, os.getuid(), os.getgid(), + fname = ".".join([fname, ext]) + sys.stdout.write("%s 1 %-8d %-8d %8d Jan 01 1980" + " %s\n" % (perms, os.getuid(), os.getgid(), int(blocks) * 256, fname)) return 0 @@ -62,12 +78,15 @@ class Uc1541(object): if not self._call_command('delete', dst=dst): return self._show_error() - # In case of error during removing, ERRORCODE is sent to stdout - # instead of stderr AND 'ERRORCODE 1' means: # 'everything fine' - if '\nERRORCODE 1\n' in self.out: - return 0 + # During removing, a message containing ERRORCODE is sent to stdout + # instead of stderr. Everything other than 'ERRORCODE 1' (which means: + # 'everything fine') is actually a failure. In case of verbose error + # 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): """ @@ -102,8 +121,8 @@ class Uc1541(object): if "\\" in fname: fname = fname.replace('\\', '/') - #if fname.lower().endswith('.prg') or fname.lower().endswith('.del'): - # fname = fname[:-4] + if fname.lower().endswith('.prg') or fname.lower().endswith('.del'): + fname = fname[:-4] return fname @@ -111,7 +130,10 @@ class Uc1541(object): """ 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): """ @@ -133,7 +155,16 @@ class Uc1541(object): 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() subparsers = parser.add_subparsers(help='supported commands') 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_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('SRC', help="Source filename") parser_copyin.add_argument('DST', help="Destination filename (to be " "written into D64 image)") - parser_copyin.set_defaults(func=lambda a: Uc1541(a.ARCH). \ - copyin(a.SRC, a.DST)) + parser_copyin.set_defaults(func=CALL_MAP['copyin']) parser_copyout.add_argument('ARCH', help="D64 Image filename") parser_copyout.add_argument('SRC', help="Source filename (to be read from" " D64 image") parser_copyout.add_argument('DST', help="Destination filename") - parser_copyout.set_defaults(func=lambda a: Uc1541(a.ARCH). \ - copyout(a.SRC, a.DST)) + parser_copyout.set_defaults(func=CALL_MAP['copyout']) parser_rm.add_argument('ARCH', help="D64 Image filename") 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.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()