From 43e4938a0960a68068ca1d41fba8406a44a69149 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Wed, 22 Aug 2012 10:31:35 +0300 Subject: [PATCH 1/2] Ticket #2864: New implementation of uc1541 VFS Due to date formatting, uc1541 extfs plugin is unusable, even tough the date formatting, which is the one cause of the problem is coherent with the attached documentation (MM-DD-YYYY hh:mm). Another problem with uc1541 script is connected rather with legal characters used in filename rather than with script itself - in PET ASCII it is perfectly fine to use slash "/" character in filenames, and as a side effect all files containing slash inside d64 image are represented as directories on MC. Signed-off-by: Slava Zanko --- configure.ac | 1 - src/vfs/extfs/helpers/.gitignore | 1 - src/vfs/extfs/helpers/Makefile.am | 4 +- src/vfs/extfs/helpers/uc1541 | 238 ++++++++++++++++++++++++++++++ src/vfs/extfs/helpers/uc1541.in | 74 ---------- 5 files changed, 239 insertions(+), 79 deletions(-) create mode 100755 src/vfs/extfs/helpers/uc1541 delete mode 100644 src/vfs/extfs/helpers/uc1541.in diff --git a/configure.ac b/configure.ac index 845add256..8eff3a76d 100644 --- a/configure.ac +++ b/configure.ac @@ -549,7 +549,6 @@ src/vfs/extfs/helpers/ualz src/vfs/extfs/helpers/uar src/vfs/extfs/helpers/uarc src/vfs/extfs/helpers/uarj -src/vfs/extfs/helpers/uc1541 src/vfs/extfs/helpers/ucab src/vfs/extfs/helpers/uha src/vfs/extfs/helpers/ulha diff --git a/src/vfs/extfs/helpers/.gitignore b/src/vfs/extfs/helpers/.gitignore index 8c9f1133d..c20df8014 100644 --- a/src/vfs/extfs/helpers/.gitignore +++ b/src/vfs/extfs/helpers/.gitignore @@ -25,4 +25,3 @@ uzip uzoo uace uarc -uc1541 diff --git a/src/vfs/extfs/helpers/Makefile.am b/src/vfs/extfs/helpers/Makefile.am index 06ea7898d..53184c0c5 100644 --- a/src/vfs/extfs/helpers/Makefile.am +++ b/src/vfs/extfs/helpers/Makefile.am @@ -6,7 +6,7 @@ EXTFSCONFFILES = sfs.ini EXTFS_MISC = README README.extfs # Scripts hat don't need adaptation to the local system -EXTFS_CONST = bpp changesetfs gitfs+ patchsetfs rpm trpm u7z +EXTFS_CONST = bpp changesetfs gitfs+ patchsetfs rpm trpm uc1541 u7z # Scripts that need adaptation to the local system - source files EXTFS_IN = \ @@ -29,7 +29,6 @@ EXTFS_IN = \ uar.in \ uarc.in \ uarj.in \ - uc1541.in \ ucab.in \ uha.in \ ulha.in \ @@ -59,7 +58,6 @@ EXTFS_OUT = \ uar \ uarc \ uarj \ - uc1541 \ ucab \ uha \ ulha \ diff --git a/src/vfs/extfs/helpers/uc1541 b/src/vfs/extfs/helpers/uc1541 new file mode 100755 index 000000000..9aa205735 --- /dev/null +++ b/src/vfs/extfs/helpers/uc1541 @@ -0,0 +1,238 @@ +#! /usr/bin/env python +""" +UC1541 Virtual filesystem + +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-16 +Version: 1.2 +Licence: BSD +""" + +import sys +import re +import os +from subprocess import Popen, PIPE + + +class Uc1541(object): + """ + Class for interact with c1541 program and MC + """ + PRG = re.compile(r'(\d+)\s+"([^"]*)".+?\s(del|prg)([\s<])') + + def __init__(self, archname): + 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): + """ + List contents of D64 image. + Convert filenames to be unix filesystem friendly + Add suffix to show user what kind of file do he dealing with. + """ + if not self._call_command('list'): + return self._show_error() + + for line in self.out.split("\n"): + 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('/', '\\') + + if ext == 'del': + perms = "----------" + else: + perms = "-r%s-r--r--" % (rw.strip() and "-" or "w") + + 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 + + def rm(self, dst): + """ + Remove file from D64 image + """ + dst = self._correct_fname(dst) + if not self._call_command('delete', dst=dst): + return self._show_error() + + # 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() + + return 0 + + def copyin(self, dst, src): + """ + Copy file to the D64 image. Destination filename has to be corrected. + """ + dst = self._correct_fname(dst) + + if not self._call_command('write', src=src, dst=dst): + return self._show_error() + + return 0 + + def copyout(self, src, dst): + """ + Copy file form the D64 image. Source filename has to be corrected, + since it's representaion differ from the real one inside D64 image. + """ + src = self._correct_fname(src) + + if not self._call_command('read', src=src, dst=dst): + return self._show_error() + + return 0 + + def _correct_fname(self, fname): + """ + Correct filenames containing backslashes (since in unices slash in + filenames is forbidden, and on PET ASCII there is no backslash, but + slash in filenames is accepted) and make it into slash. Also remove + .del/.prg suffix, since destination, correct file will always be prg. + """ + if "\\" in fname: + fname = fname.replace('\\', '/') + + if fname.lower().endswith('.prg') or fname.lower().endswith('.del'): + fname = fname[:-4] + + return fname + + def _show_error(self): + """ + Pass out error output from c1541 execution + """ + if self._verbose: + sys.exit(self.err) + else: + sys.exit(1) + + def _call_command(self, cmd, src=None, dst=None): + """ + Return status of the provided command, which can be one of: + write + read + delete + dir/list + """ + command = ['c1541', '-attach', self.arch, '-%s' % cmd] + if src and dst: + command.append(src) + command.append(dst) + elif src or dst: + command.append(src and src or dst) + + self.out, self.err = Popen(command, stdout=PIPE, + stderr=PIPE).communicate() + return not self.err + + +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 " + "image") + parser_copyin = subparsers.add_parser('copyin', help="Copy file into D64 " + "image") + parser_copyout = subparsers.add_parser('copyout', help="Copy file out of " + "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.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=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=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=CALL_MAP['rm']) + + args = parser.parse_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() diff --git a/src/vfs/extfs/helpers/uc1541.in b/src/vfs/extfs/helpers/uc1541.in deleted file mode 100644 index 842c1d1bf..000000000 --- a/src/vfs/extfs/helpers/uc1541.in +++ /dev/null @@ -1,74 +0,0 @@ -#! /bin/sh - -# -# UC1541 Virtual filesystem executive v0.1 - -# This is for accessing 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. - -# Copyright (C) 2008 Jacques Pelletier -# May be distributed under the terms of the GNU Public License -# -# - -# Define which archiver you are using with appropriate options -C1541="c1541" - -# There are no time stamps in the disk image, so a bogus timestamp is displayed -mc_c1541_fs_list() -{ - if [ x"$UID" = x ]; then - UID=`id -ru 2>/dev/null` - if [ "x$UID" = "x" ]; then - UID=0 - fi - fi - $C1541 "$1" -list | @AWK@ -v uid=$UID ' -BEGIN { FS = "\"" } -/No LINES!/ { next } -/BLOCKS FREE/ { next } -$1 == 0 { next } -{ - printf "-rw-r--r-- 1 %-8d %-8d %8d Jan 01 1980 00:00 %s\n", uid, 0, $1 * 256, $2 -}' 2>/dev/null -} - -# Command: copyout archivename storedfilename extractto -# -read image 1541name [fsname] -mc_c1541_fs_copyout() -{ - $C1541 "$1" -read "$2" 2> /dev/null - mv "$2" "$3" -} - -# FIXME mc can't do chown of the file inside the archive -# Command: copyin archivename storedfilename sourcefile -# -write image fsname [1541name] -mc_c1541_fs_copyin() -{ - mv "$3" "$2" - $C1541 "$1" -write "$2" 2> /dev/null -} - -# Command: rm archivename storedfilename -# -delete image files -mc_c1541_fs_rm() -{ - $C1541 "$1" -delete "$2" 2> /dev/null -} - -# The main routine -umask 077 - -cmd="$1" -shift - -case "$cmd" in - list) mc_c1541_fs_list "$@" ;; - copyout) mc_c1541_fs_copyout "$@" ;; -# copyin) mc_c1541_fs_copyin "$@" ;; - rm) mc_c1541_fs_rm "$@" ;; - *) exit 1 ;; -esac -exit 0 From 198a10ca7d6cdfc9c08da4647f4be72453b2a9fd Mon Sep 17 00:00:00 2001 From: Roman 'gryf' Dobosz Date: Wed, 5 Sep 2012 14:23:15 +0300 Subject: [PATCH 2/2] fixes following issues: * F3/F4 on 'del' and 0-length files works, however it is impossible to change 'del' files (cached content can be confusing) * Koala files and other with non-ASCII characters are supported (implemented directory reading routine in pure python - for now only D64 format is supported) * Added workaround for filenames with space at the beginning (however, as it was stressed before, it is more generic issue than this script. Maybe it is good idea to use pcre instead of iterating and splitting?) * minor bugfixes and code cleanup Signed-off-by: Slava Zanko --- src/vfs/extfs/helpers/uc1541 | 321 ++++++++++++++++++++++++++++++----- 1 file changed, 283 insertions(+), 38 deletions(-) diff --git a/src/vfs/extfs/helpers/uc1541 b/src/vfs/extfs/helpers/uc1541 index 9aa205735..9e6b49b54 100755 --- a/src/vfs/extfs/helpers/uc1541 +++ b/src/vfs/extfs/helpers/uc1541 @@ -7,6 +7,10 @@ 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: + 2.0 Added reading raw D64 image, and mapping for jokers. Now it is + possible to read files with PET-ASCII/control sequences in filenames. + Working with d64 images only. Added workaround for space at the + beggining of the filename. 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. @@ -16,8 +20,8 @@ Changelog: 1.0 Initial release Author: Roman 'gryf' Dobosz -Date: 2012-08-16 -Version: 1.2 +Date: 2012-09-02 +Version: 2.0 Licence: BSD """ @@ -26,55 +30,243 @@ import re import os from subprocess import Popen, PIPE +if os.getenv('UC1541_DEBUG'): + import logging + LOG = logging.getLogger('UC1541') + LOG.setLevel(logging.DEBUG) + FILE_HANDLER = logging.FileHandler("/tmp/uc1541.log") + FILE_FORMATTER = logging.Formatter("%(asctime)s %(levelname)-8s " + "%(lineno)s %(funcName)s - %(message)s") + FILE_HANDLER.setFormatter(FILE_FORMATTER) + FILE_HANDLER.setLevel(logging.DEBUG) + LOG.addHandler(FILE_HANDLER) +else: + class LOG(object): + """ + Dummy logger object. does nothing. + """ + @classmethod + def debug(*args, **kwargs): + pass + + @classmethod + def info(*args, **kwargs): + pass + + @classmethod + def warning(*args, **kwargs): + pass + + @classmethod + def error(*args, **kwargs): + pass + + @classmethod + def critical(*args, **kwargs): + pass + + +class D64(object): + """ + Implement d64 directory reader + """ + CHAR_MAP = {32: ' ', 33: '!', 34: '"', 35: '#', 36: '$', 37: '%', 38: '&', + 39: "'", 40: '(', 41: ')', 42: '*', 43: '+', 44: ',', 45: '-', + 46: '.', 47: '/', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', + 53: '5', 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 60: '<', + 61: '=', 62: '>', 63: '?', 64: '@', 65: 'a', 66: 'b', 67: 'c', + 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', 73: 'i', 74: 'j', + 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', 80: 'p', 81: 'q', + 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', 87: 'w', 88: 'x', + 89: 'y', 90: 'z', 91: '[', 93: ']', 97: 'A', 98: 'B', 99: 'C', + 100: 'D', 101: 'E', 102: 'F', 103: 'G', 104: 'H', 105: 'I', + 106: 'J', 107: 'K', 108: 'L', 109: 'M', 110: 'N', 111: 'O', + 112: 'P', 113: 'Q', 114: 'R', 115: 'S', 116: 'T', 117: 'U', + 118: 'V', 119: 'W', 120: 'X', 121: 'Y', 122: 'Z', 193: 'A', + 194: 'B', 195: 'C', 196: 'D', 197: 'E', 198: 'F', 199: 'G', + 200: 'H', 201: 'I', 202: 'J', 203: 'K', 204: 'L', 205: 'M', + 206: 'N', 207: 'O', 208: 'P', 209: 'Q', 210: 'R', 211: 'S', + 212: 'T', 213: 'U', 214: 'V', 215: 'W', 216: 'X', 217: 'Y', + 218: 'Z'} + + FILE_TYPES = {0b000: 'del', + 0b001: 'seq', + 0b010: 'prg', + 0b011: 'usr', + 0b100: 'rel'} + + def __init__(self, dimage): + """ + Init + """ + LOG.debug('image: %s', dimage) + dimage = open(dimage, 'rb') + self.raw = dimage.read() + dimage.close() + + self.current_sector_data = None + self._sector_shift = 256 + self.next_sector = 0 + self.next_track = None + self._directory_contents = [] + + def _map_filename(self, string): + """ + Transcode filename to ASCII compatible. Replace not supported + characters with jokers. + """ + + filename = list() + in_fname = True + + for chr_ in string: + character = D64.CHAR_MAP.get(ord(chr_), '?') + + if in_fname: + if ord(chr_) == 160: + in_fname = False + else: + filename.append(character) + + LOG.debug("string: ``%s'' mapped to: ``%s''", string, + "".join(filename)) + return "".join(filename) + + def _go_to_next_sector(self): + """ + Fetch (if exist) next sector from a directory chain + Return False if the chain ends, True otherwise + """ + + if self.next_track == 0 and self.next_sector == 255: + LOG.debug("End of directory") + return False + + if self.next_track is None: + LOG.debug("Going to the track: 18,1") + offset = self._get_d64_offset(18, 1) + else: + offset = self._get_d64_offset(self.next_track, self.next_sector) + LOG.debug("Going to the track: %s,%s", self.next_track, + self.next_sector) + + self.current_sector_data = self.raw[offset:offset + self._sector_shift] + + self.next_track = ord(self.current_sector_data[0]) + self.next_sector = ord(self.current_sector_data[1]) + LOG.debug("Next track: %s,%s", self.next_track, self.next_sector) + return True + + def _get_ftype(self, num): + """ + Get filetype as a string + """ + return D64.FILE_TYPES.get(int("%d%d%d" % (num & 4 and 1, + num & 2 and 1, + num & 1), 2), '???') + + def _get_d64_offset(self, track, sector): + """ + Return offset (in bytes) for specified track and sector. + """ + + offset = 0 + truncate_track = 0 + + if track > 17: + offset = 17 * 21 * 256 + truncate_track = 17 + + if track > 24: + offset += 6 * 19 * 256 + truncate_track = 24 + + if track > 30: + offset += 5 * 18 * 256 + truncate_track = 30 + + track = track - truncate_track + offset += track * sector * 256 + + return offset + + def _harvest_entries(self): + """ + Traverse through sectors and store entries in _directory_contents + """ + sector = self.current_sector_data + for x in range(8): + entry = sector[:32] + ftype = ord(entry[2]) + + if ftype == 0: # deleted + sector = sector[32:] + continue + + type_verbose = self._get_ftype(ftype) + + protect = ord(entry[2]) & 64 and "<" or " " + fname = entry[5:21] + if ftype == 'rel': + size = ord(entry[23]) + else: + size = ord(entry[30]) + ord(entry[31]) * 226 + + self._directory_contents.append({'fname': self._map_filename(fname), + 'ftype': type_verbose, + 'size': size, + 'protect': protect}) + sector = sector[32:] + + def list_dir(self): + """ + Return directory list as list of dict with keys: + fname, ftype, protect and size + """ + while self._go_to_next_sector(): + self._harvest_entries() + + return self._directory_contents + class Uc1541(object): """ Class for interact with c1541 program and MC """ - PRG = re.compile(r'(\d+)\s+"([^"]*)".+?\s(del|prg)([\s<])') + PRG = re.compile(r'(\d+)\s+"([^"]*)".+?\s(del|prg|rel|seq|usr)([\s<])') def __init__(self, archname): self.arch = archname self.out = '' self.err = '' self._verbose = os.getenv("UC1541_VERBOSE", False) - self._hide_del = os.getenv("UC1541_HIDE_DEL", False) + self._hide_del = os.getenv("UC1541_HIDE_DEL", False) + + self.pyd64 = D64(archname).list_dir() + self.file_map = {} + self.directory = [] def list(self): """ - List contents of D64 image. + Output list contents of D64 image. Convert filenames to be unix filesystem friendly Add suffix to show user what kind of file do he dealing with. """ - if not self._call_command('list'): - return self._show_error() + LOG.info("List contents of %s", self.arch) + directory = self._get_dir() - for line in self.out.split("\n"): - 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('/', '\\') - - if ext == 'del': - perms = "----------" - else: - perms = "-r%s-r--r--" % (rw.strip() and "-" or "w") - - 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)) + for entry in directory: + sys.stdout.write("%(perms)s 1 %(uid)-8d %(gid)-8d %(size)8d " + "Jan 01 1980 %(display_name)s\n" % entry) return 0 def rm(self, dst): """ Remove file from D64 image """ - dst = self._correct_fname(dst) + LOG.info("Removing file %s", dst) + dst = self._get_masked_fname(dst) + if not self._call_command('delete', dst=dst): return self._show_error() @@ -92,6 +284,7 @@ class Uc1541(object): """ Copy file to the D64 image. Destination filename has to be corrected. """ + LOG.info("Copy into D64 %s as %s", src, dst) dst = self._correct_fname(dst) if not self._call_command('write', src=src, dst=dst): @@ -104,27 +297,77 @@ class Uc1541(object): Copy file form the D64 image. Source filename has to be corrected, since it's representaion differ from the real one inside D64 image. """ - src = self._correct_fname(src) + LOG.info("Copy form D64 %s as %s", src, dst) + if not src.endswith(".prg"): + return "canot read" + + src = self._get_masked_fname(src) if not self._call_command('read', src=src, dst=dst): return self._show_error() return 0 - def _correct_fname(self, fname): + def _get_masked_fname(self, fname): """ - Correct filenames containing backslashes (since in unices slash in - filenames is forbidden, and on PET ASCII there is no backslash, but - slash in filenames is accepted) and make it into slash. Also remove - .del/.prg suffix, since destination, correct file will always be prg. + Return masked filename with '?' jokers instead of non ASCII + characters, usefull for copying or deleting files with c1541. In case + of several files with same name exists in directory, only first one + will be operative (first as appeared in directory). + + Warning! If there are two different names but the only differenc is in + non-ASCII characters (some PET ASCII or controll characters) there is + a risk that one can remove both files. """ - if "\\" in fname: - fname = fname.replace('\\', '/') + directory = self._get_dir() - if fname.lower().endswith('.prg') or fname.lower().endswith('.del'): - fname = fname[:-4] + for entry in directory: + if entry['display_name'] == fname: + return entry['pattern_name'] - return fname + def _get_dir(self): + """ + Retrieve directory via c1541 program + """ + directory = [] + + uid = os.getuid() + gid = os.getgid() + + if not self._call_command('list'): + return self._show_error() + + idx = 0 + for line in self.out.split("\n"): + if Uc1541.PRG.match(line): + blocks, fname, ext, rw = Uc1541.PRG.match(line).groups() + + if ext == 'del' and self._hide_del: + continue + + display_name = ".".join([fname, ext]) + pattern_name = self.pyd64[idx]['fname'] + + if '/' in fname: + display_name = fname.replace('/', '|') + + # workaround for space at the beggining of the filename + if fname[0] == ' ': + display_name = '~' + display_name[1:] + + if ext == 'del': + perms = "----------" + else: + perms = "-r%s-r--r--" % (rw.strip() and "-" or "w") + + directory.append({'pattern_name': pattern_name, + 'display_name': display_name, + 'uid': uid, + 'gid': gid, + 'size': int(blocks) * 256, + 'perms': perms}) + idx += 1 + return directory def _show_error(self): """ @@ -197,6 +440,7 @@ def parse_args(): args = parser.parse_args() return args.func(args) + def no_parse(): """ Failsafe argument "parsing". Note, that it blindly takes positional @@ -229,6 +473,7 @@ def no_parse(): CALL_MAP[sys.argv[1]](arg) if __name__ == "__main__": + LOG.debug("Script params: %s", str(sys.argv)) try: from argparse import ArgumentParser parse_func = parse_args