Example #1
0
def output_format(file, windows=False, archive=None):
    if file[T_TYPE] == 'X':
        return '--- TRUNCATED ---'

    name = to_utf8(file[T_NAME])

    if archive:
        name += u' \u25bb ' + archive

    if windows:
        out = u'  {}{}{}{}'.format(
            u'{:<10}'.format(file_timestamp(file[T_TIMESTAMP])),
            u'{:<3}'.format(file[T_TYPE]),
            u'{:<11}'.format(size_human_readable(file[T_SIZE])),
            u'{:<40}'.format(name))
    else:
        out = u'  {}{}{}{}{}{}{}'.format(
            u'{:<10}'.format(file_timestamp(file[T_TIMESTAMP])),
            u'{:<3}'.format(file[T_TYPE]),
            u'{:<5}'.format(file[T_UID]),
            u'{:<5}'.format(file[T_GID]),
            u' {:06o} '.format(file[T_MODE]),
            u'{:<11}'.format(size_human_readable(file[T_SIZE])),
            u'{:<40}'.format(name))

    if archive:
        out=Color(out, 'yellow')
    elif file[T_TYPE] == 'D':
        out=Color(out, 'lightyellow')
    elif 'U' in file[T_SPEC]:
        out=Color(out, 'lightred')
    elif 'G' in file[T_SPEC]:
        out=Color(out, 'red')
    elif file[T_TYPE] == 'B':
        out=Color(out, 'grey')
    elif file[T_TYPE] == 'C':
        out=Color(out, 'grey')
    elif file[T_TYPE] == 'F':
        out=Color(out, 'cyan')
    elif file[T_TYPE] == 'S':
        out=Color(out, 'magenta')
    elif file[T_TYPE] == 'L':
        out=Color(out, 'grey')
    elif not file[T_SIZE]:
        out=Color(out, 'darkgrey')
    elif 'E' in file[T_SPEC]:
        out=Color(out, 'lightgreen')
    elif 'W' in file[T_SPEC] and not windows:
        out=Color(out, 'blue')

    return out
Example #2
0
def print_psinfo(fout,
                 families,
                 socktypes,
                 data,
                 colinfo,
                 sections=[],
                 wide=False):
    keys = ('id', 'key', 'PROPERTY', 'VAR', 'TYPE')
    sorter = lambda x, y: -1 if (x in keys and y not in keys) else (1 if (
        y in keys and not x in keys) else cmp(x, y))

    parts = []

    for pid, info in data.iteritems():
        if sections is not None:
            infosecs = {'general': []}
            for prop, value in info.iteritems():
                if type(value) not in (list, dict):
                    infosecs['general'].append({
                        'PROPERTY':
                        prop,
                        'VALUE':
                        '{:3}%'.format(int(value)) if
                        ('_percent' in prop) else value
                    })
                else:
                    if prop == 'environ':
                        maxvar = max(len(x) for x in value.iterkeys())
                        maxval = max(len(x) for x in value.itervalues())
                        infosecs[prop] = [{
                            'VAR': x,
                            'VALUE': y
                        } for x, y in value.iteritems()]
                        continue
                    elif prop == 'connections':
                        newvalue = []
                        for connection in value:
                            newvalue.append({
                                'status':
                                connection['status'],
                                'raddr':
                                ':'.join([str(x)
                                          for x in connection['raddr']]),
                                'laddr':
                                ':'.join([str(x)
                                          for x in connection['laddr']]),
                                'family':
                                families[connection['family']],
                                'type':
                                socktypes[connection['type']],
                            })

                        infosecs[prop] = newvalue
                        continue
                    elif prop == 'memory_maps':
                        filtered = ('path', 'rss', 'size')
                    elif prop == 'memory_info':
                        infosecs[prop] = [{
                            'TYPE':
                            item['KEY'],
                            'SIZE':
                            size_human_readable(item['VALUE'])
                        } for item in value]
                        continue
                    else:
                        filtered = None

                    infosecs[prop] = [{
                        k: v
                        for k, v in item.iteritems()
                        if filtered is None or k in filtered
                    } for item in (value if type(value) == list else [value])]

            if sections:
                for section in sections:
                    section = section.lower()
                    if section in infosecs:
                        labels = sorted(infosecs[section][0], cmp=sorter)
                        parts.append(
                            TruncateToTerm(
                                Table(infosecs[section], labels,
                                      Color(section.upper(), 'yellow'))))

            else:
                for section, table in infosecs.iteritems():
                    labels = sorted(table[0], cmp=sorter)
                    parts.append(
                        TruncateToTerm(
                            Table(table, labels,
                                  Color(section.upper(), 'yellow'))))

            fout(MultiPart(parts))

        else:
            outcols = ['pid'] + [
                x for x in ('cpu_percent', 'memory_percent', 'username', 'exe',
                            'name', 'cmdline') if x in colinfo
            ]
            info['pid'] = pid
            columns = gen_columns(info, colinfo)

            fout(gen_output_line(columns, outcols, info, wide) + '\n')
Example #3
0
File: ls.py Project: txtaly/pupy
class ls(PupyModule):
    """ list system files """
    is_module = False

    dependencies = ['pupyutils.basic_cmds', 'scandir']

    @classmethod
    def init_argparse(cls):
        cls.arg_parser = PupyArgumentParser(prog="ls", description=cls.__doc__)
        cls.arg_parser.add_argument('-d',
                                    '--dir',
                                    action='store_false',
                                    default=True,
                                    help='do not list directories')
        sort = cls.arg_parser.add_mutually_exclusive_group()
        sort.add_argument(
            '-L',
            '--limit',
            type=int,
            default=1024,
            help='List no more than this amount of files (server side), '
            'to not to stuck on huge dirs. Default: 1024')
        sort.add_argument('-s',
                          '--size',
                          dest='sort',
                          action='store_const',
                          const=T_SIZE,
                          help='sort by size')
        sort.add_argument('-t',
                          '--time',
                          dest='sort',
                          action='store_const',
                          const=T_TIMESTAMP,
                          help='sort by time')
        cls.arg_parser.add_argument('-r',
                                    '--reverse',
                                    action='store_true',
                                    default=False,
                                    help='reverse sort order')
        cls.arg_parser.add_argument('path',
                                    type=str,
                                    nargs='?',
                                    help='path of a specific file',
                                    completer=remote_path_completer)

    def run(self, args):
        try:
            ls = self.client.remote('pupyutils.basic_cmds', 'ls')

            results = ls(args.path, args.dir, args.limit)
        except Exception, e:
            self.error(' '.join(x for x in e.args
                                if type(x) in (str, unicode)))
            return

        # results = obtain(results)
        windows = self.client.is_windows()

        if not results:
            return

        total_cnt = 0
        files_size = 0
        files_cnt = 0
        dirs_cnt = 0

        for r in results:
            if T_FILES in r:
                self.log(r[T_PATH] + ':')

                if not args.sort:
                    dirs = []
                    files = []
                    truncated = 0

                    for x in r[T_FILES]:
                        if T_TRUNCATED in x:
                            truncated = x[T_TRUNCATED]
                            total_cnt += truncated
                        elif x[T_TYPE] == 'D':
                            dirs.append(x)
                            total_cnt += 1
                            dirs_cnt += 1
                        else:
                            files.append(x)
                            files_size += x[T_SIZE]
                            total_cnt += 1
                            files_cnt += 1

                    for f in sorted(dirs,
                                    key=lambda x: to_utf8(x.get(T_NAME)),
                                    reverse=args.reverse):
                        self.log(output_format(f, windows))

                    for f in sorted(files,
                                    key=lambda x: to_utf8(x.get(T_NAME)),
                                    reverse=args.reverse):
                        self.log(output_format(f, windows))

                    if truncated:
                        self.warning(
                            'Folder is too big. Not listed: {} (-L {})'.format(
                                truncated, args.limit))

                        self.info(
                            'Summary (observed): Files: {} Dirs: {} Total: {}'.
                            format(
                                '{}+'.format(files_cnt) if files_cnt else '??',
                                '{}+'.format(dirs_cnt) if dirs_cnt else '??',
                                total_cnt))
                    else:
                        self.info(
                            'Summary: Files: {} (size: {}) Dirs: {} Total: {}'.
                            format(files_cnt, size_human_readable(files_size),
                                   dirs_cnt, total_cnt))

                else:
                    truncated = False
                    for f in sorted(r[T_FILES],
                                    key=lambda x: x.get(args.sort),
                                    reverse=args.reverse):
                        if T_TRUNCATED in f:
                            truncated = True
                            continue

                        self.log(output_format(f, windows))

                    if truncated:
                        self.log('--- TRUNCATED ---')

            elif T_FILE in r:
                self.log(output_format(r[T_FILE], windows))
            else:
                self.error('Old format. Update pupyutils.basic_cmds')
                return
Example #4
0
class FStat(PupyModule):
    '''Show a bit more info about file path. ACLs/Caps/Owner for now'''

    dependencies = {
        'all': ['pupyutils.basic_cmds', 'fsutils', 'fsutils_ext'],
        'windows': ['junctions', 'ntfs_streams', 'pupwinutils.security'],
        'linux': ['xattr', 'posix1e', 'prctl', '_prctl']
    }

    @classmethod
    def init_argparse(cls):
        cls.arg_parser = PupyArgumentParser(prog='stat',
                                            description=cls.__doc__)
        cls.arg_parser.add_argument(
            '-v',
            '--verbose',
            action='store_true',
            default=False,
            help='Print more information (certificates for example)')
        cls.arg_parser.add_argument('path',
                                    type=str,
                                    nargs=REMAINDER,
                                    help='path of a specific file',
                                    completer=remote_path_completer)

    def run(self, args):
        getfilesec = self.client.remote('fsutils_ext', 'getfilesec')

        path = ' '.join(args.path)

        try:
            sec = getfilesec(path)
        except Exception, e:
            self.error(' '.join(x for x in e.args
                                if type(x) in (str, unicode)))
            return

        ctime, atime, mtime, size, owner, group, header, mode, extra = sec

        owner_id, owner_name, owner_domain = owner
        group_id, group_name, group_domain = group

        default = {
            'Created':
            file_timestamp(ctime, time=True),
            'Accessed':
            file_timestamp(atime, time=True),
            'Modified':
            file_timestamp(mtime, time=True),
            'Size':
            '{} ({})'.format(size_human_readable(size), size),
            'Owner':
            '{}{} ({})'.format(owner_domain + '\\' if owner_domain else '',
                               owner_name, owner_id),
            'Group':
            '{}{} ({})'.format(group_domain + '\\' if group_domain else '',
                               group_name, group_id),
            'Mode':
            mode,
        }

        infos = []

        infos.append(
            Table([{
                'Property': p,
                'Value': default[p]
            } for p in ('Created', 'Accessed', 'Modified', 'Size', 'Owner',
                        'Group', 'Mode')], ['Property', 'Value'],
                  legend=False))

        oneliners = []

        certificates = None

        for extra, values in extra.iteritems():
            if extra == 'Certificates':
                certificates = [
                    load_cert_string(cert, FORMAT_DER).as_text()
                    for cert in values
                ]
            elif isinstance(values, dict):
                records = [{
                    'KEY':
                    k.decode('utf-8'),
                    'VALUE':
                    v.decode('utf-8') if isinstance(v, str) else str(v)
                } for k, v in values.iteritems()]

                infos.append(Table(records, ['KEY', 'VALUE'], caption=extra))
            elif isinstance(values, (list, tuple)):
                if all(
                        isinstance(value, (list, tuple)) and len(value) == 2
                        for value in values):
                    infos.append(
                        List('{}: {}'.format(key, value)
                             for key, value in values))
                else:
                    infos.append(List(values, caption=extra))
            elif isinstance(values, int):
                oneliners.append('{}: {}'.format(extra, values))
            elif '\n' in values:
                infos.append(Line(extra + ':', values))
            else:
                oneliners.append(extra + ': ' + values)

        if args.verbose:
            magic = ''
            if header:
                with Magic() as libmagic:
                    magic = libmagic.id_buffer(header)

            if magic:
                oneliners.append('Magic: {}'.format(magic))

            if certificates:
                infos.extend(certificates)

        if oneliners:
            infos.append(List(oneliners, caption='Other'))

        self.log(MultiPart(infos))
Example #5
0
    def run(self, args):
        ok = False
        if self.client.is_posix():
            tier1 = ('network', 'fuse', 'dm', 'block', 'vm')

            mounts = self.client.remote('mount', 'mounts')
            getuid = self.client.remote('os', 'getuid')
            getgid = self.client.remote('os', 'getgid')

            mountinfo = mounts()
            uid = getuid()
            gid = getgid()

            option_colors = {
                'rw': 'yellow',
                'nosuid': 'grey',
                'nodev': 'grey',
                'noexec': 'lightgreen',
                'uid': {
                    '0': 'green',
                    str(uid): 'red'
                },
                'gid': {
                    '0': 'green',
                    str(gid): 'red'
                },
                'ro': 'green',
                'user_id': {
                    '0': 'green',
                    str(uid): 'red'
                },
                'group_id': {
                    '0': 'green',
                    str(gid): 'red'
                },
                'allow_other': 'yellow',
                'xattr': 'yellow',
                'acl': 'yellow',
                'username': '******',
                'domain': 'red',
                'forceuid': 'yellow',
                'forcegid': 'yellow',
                'addr': 'red',
                'unix': 'red'
            }

            def colorize_option(option):
                if len(option) > 1:
                    k, v = option
                else:
                    k = option[0]
                    v = None

                color = option_colors.get(k)
                if color:
                    if type(color) == dict:
                        if v in color:
                            return colorize('='.join([x for x in [k, v] if x]),
                                            color.get(v))
                        else:
                            return '='.join([x for x in [k, v] if x])
                    else:
                        return colorize('='.join([x for x in [k, v] if x]),
                                        color)
                else:
                    return '='.join([x for x in [k, v] if x])

            output = []

            for fstype in mountinfo.iterkeys():
                if fstype in tier1:
                    continue

                output.append('{}:'.format(colorize(fstype, 'yellow')))

                dst_max = max([len(x['dst']) for x in mountinfo[fstype]])
                fsname_max = max([len(x['fsname']) for x in mountinfo[fstype]])
                free_max = max([
                    len(x['hfree']) if x['total'] else 0
                    for x in mountinfo[fstype]
                ])

                for info in mountinfo[fstype]:
                    fmt = '{{:<{}}} {{:<{}}} {{:>{}}} {{}}'.format(
                        dst_max, fsname_max,
                        (free_max + 3 + 4) if free_max else 0)

                    output.append(
                        fmt.format(
                            info['dst'], info['fsname'], (colorize(
                                ('{{:>3}}% ({{:>{}}})'.format(free_max)
                                 ).format(info['pused'], info['hfree']),
                                'white' if info['pused'] < 90 else 'yellow'))
                            if info['total'] else '', ','.join([
                                colorize_option(option)
                                for option in info['options']
                            ])))

                output.append('')

            for fstype in tier1:
                if not fstype in mountinfo:
                    continue

                src_max = max([len(x['src']) for x in mountinfo[fstype]])
                dst_max = max([len(x['dst']) for x in mountinfo[fstype]])
                fsname_max = max([len(x['fsname']) for x in mountinfo[fstype]])
                free_max = max([
                    len(x['hfree']) if x['total'] else 0
                    for x in mountinfo[fstype]
                ])

                output.append('{}:'.format(colorize(fstype, 'green')))
                for info in mountinfo[fstype]:
                    fmt = '{{:<{}}} {{:<{}}} {{:<{}}} {{:>{}}} {{}}'.format(
                        dst_max, src_max, fsname_max,
                        (free_max + 3 + 4) if free_max else 0)

                    output.append(
                        fmt.format(
                            info['dst'], info['src'], info['fsname'],
                            (colorize(
                                ('{{:>3}}% ({{:>{}}})'.format(free_max)
                                 ).format(info['pused'], info['hfree']),
                                'white' if info['pused'] < 90 else 'yellow'))
                            if info['total'] else '', ','.join([
                                colorize_option(option)
                                for option in info['options']
                            ])))

                output.append('')

            self.log('\n'.join(output))

            ok = True

        elif self.client.is_windows():
            try:
                list_drives = self.client.remote('pupwinutils.drives',
                                                 'list_drives')
                self.log(list_drives())
                ok = True
            except:
                self.warning('WMI failed')
                pass

        if not ok:
            list_drives = self.client.remote('pupyps', 'drives')
            drives = list_drives()

            formatted_drives = []

            for drive in drives:
                formatted_drives.append({
                    'DEV':
                    drive['device'],
                    'MP':
                    drive['mountpoint'],
                    'FS':
                    drive['fstype'],
                    'OPTS':
                    drive['opts'],
                    'USED': ('{}% ({}/{})'.format(
                        drive['percent'], size_human_readable(drive['used']),
                        size_human_readable(drive['total']))) if
                    ('used' in drive and 'total' in drive) else '?'
                })

            self.log(
                Table(formatted_drives, ['DEV', 'MP', 'FS', 'OPTS', 'USED']))
Example #6
0
    def run(self, args):
        if self.client.is_posix():
            tier1 = ('network', 'fuse', 'dm', 'block', 'vm')

            mounts = self.client.remote('mount', 'mounts')
            getuid = self.client.remote('os', 'getuid')
            getgid = self.client.remote('os', 'getgid')

            mountinfo = mounts()
            uid = getuid()
            gid = getgid()

            option_colors = {
                'rw': 'yellow',
                'nosuid': 'grey',
                'nodev': 'grey',
                'noexec': 'lightgreen',
                'uid': {
                    '0': 'green',
                    str(uid): 'red'
                },
                'gid': {
                    '0': 'green',
                    str(gid): 'red'
                },
                'ro': 'green',
                'user_id': {
                    '0': 'green',
                    str(uid): 'red'
                },
                'group_id': {
                    '0': 'green',
                    str(gid): 'red'
                },
                'allow_other': 'yellow',
                'xattr': 'yellow',
                'acl': 'yellow',
                'username': '******',
                'domain': 'red',
                'forceuid': 'yellow',
                'forcegid': 'yellow',
                'addr': 'red',
                'unix': 'red'
            }

            def colorize_option(option):
                if len(option) > 1:
                    k, v = option
                else:
                    k = option[0]
                    v = None

                color = option_colors.get(k)
                if color:
                    if type(color) == dict:
                        if v in color:
                            return colorize('='.join([x for x in [k, v] if x]),
                                            color.get(v))
                        else:
                            return '='.join([x for x in [k, v] if x])
                    else:
                        return colorize('='.join([x for x in [k, v] if x]),
                                        color)
                else:
                    return '='.join([x for x in [k, v] if x])

            output = []

            for fstype in mountinfo.iterkeys():
                if fstype in tier1:
                    continue

                output.append('{}:'.format(colorize(fstype, 'yellow')))

                dst_max = max([len(x['dst']) for x in mountinfo[fstype]])
                fsname_max = max([len(x['fsname']) for x in mountinfo[fstype]])
                free_max = max([
                    len(x['hfree']) if x['total'] else 0
                    for x in mountinfo[fstype]
                ])

                for info in mountinfo[fstype]:
                    fmt = '{{:<{}}} {{:<{}}} {{:>{}}} {{}}'.format(
                        dst_max, fsname_max,
                        (free_max + 3 + 4) if free_max else 0)

                    output.append(
                        fmt.format(
                            info['dst'], info['fsname'], (colorize(
                                ('{{:>3}}% ({{:>{}}})'.format(free_max)
                                 ).format(info['pused'], info['hfree']),
                                'white' if info['pused'] < 90 else 'yellow'))
                            if info['total'] else '', ','.join([
                                colorize_option(option)
                                for option in info['options']
                            ])))

                output.append('')

            for fstype in tier1:
                if fstype not in mountinfo:
                    continue

                src_max = max([len(x['src']) for x in mountinfo[fstype]])
                dst_max = max([len(x['dst']) for x in mountinfo[fstype]])
                fsname_max = max([len(x['fsname']) for x in mountinfo[fstype]])
                free_max = max([
                    len(x['hfree']) if x['total'] else 0
                    for x in mountinfo[fstype]
                ])

                output.append('{}:'.format(colorize(fstype, 'green')))
                for info in mountinfo[fstype]:
                    fmt = '{{:<{}}} {{:<{}}} {{:<{}}} {{:>{}}} {{}}'.format(
                        dst_max, src_max, fsname_max,
                        (free_max + 3 + 4) if free_max else 0)

                    output.append(
                        fmt.format(
                            info['dst'], info['src'], info['fsname'],
                            (colorize(
                                ('{{:>3}}% ({{:>{}}})'.format(free_max)
                                 ).format(info['pused'], info['hfree']),
                                'white' if info['pused'] < 90 else 'yellow'))
                            if info['total'] else '', ','.join([
                                colorize_option(option)
                                for option in info['options']
                            ])))

                output.append('')

            self.log('\n'.join(output))

        elif self.client.is_windows():
            list_drives = self.client.remote('pupyps', 'drives')
            EnumNetResources = self.client.remote('netresources',
                                                  'EnumNetResources')
            drives = list_drives()

            formatted_drives = []
            parts = []

            for drive in drives:
                formatted_drives.append({
                    'MP':
                    drive['mountpoint'],
                    'FS':
                    drive['fstype'],
                    'OPTS':
                    drive['opts'],
                    'USED': ('{}% ({}/{})'.format(
                        drive['percent'], size_human_readable(drive['used']),
                        size_human_readable(drive['total']))) if
                    ('used' in drive and 'total' in drive) else '?'
                })

            parts.append(Table(formatted_drives, ['MP', 'FS', 'OPTS', 'USED']))

            providers = {}

            net_resources = EnumNetResources()
            for resource in net_resources:
                if resource['provider'] not in providers:
                    providers[resource['provider']] = []

                if 'used' in resource:
                    resource['used'] = '{}% ({}/{})'.format(
                        resource['percent'],
                        size_human_readable(resource['used']),
                        size_human_readable(resource['total']))
                else:
                    resource['used'] = '?'

                providers[resource['provider']].append(
                    dict((k, v) for k, v in resource.iteritems()
                         if k not in ('usage', 'provider', 'scope')))

            for provider, records in providers.iteritems():

                parts.append(
                    Table(records, ['remote', 'local', 'type', 'used'],
                          caption=provider))

            self.log(MultiPart(parts))
Example #7
0
def output_format(file,
                  windows=False,
                  archive=None,
                  time=False,
                  uid_len=0,
                  gid_len=0):
    if file[T_TYPE] == 'X':
        return '--- TRUNCATED ---'

    name = to_str(file[T_NAME])

    if archive:
        name += u' \u25bb ' + archive

    timestamp_field = u'{:<18}' if time else u'{:<10}'

    if windows:
        out = u'  {}{}{}{}{}{}'.format(
            timestamp_field.format(file_timestamp(file[T_TIMESTAMP], time)),
            u'{:<2}'.format(file[T_TYPE] + ('+' if file[T_HAS_XATTR] else '')),
            to_str(file[T_UID]).rjust(uid_len + 1) + u' ' if uid_len else u'',
            to_str(file[T_GID]).rjust(gid_len + 1) + u' ' if gid_len else u'',
            u'{:>9}'.format(size_human_readable(file[T_SIZE])),
            u' {:<40}'.format(name))
    else:
        if not uid_len:
            uid_len = 5

        if not gid_len:
            gid_len = 5

        out = u'  {}{}{}{}{}{}{}'.format(
            timestamp_field.format(file_timestamp(file[T_TIMESTAMP], time)),
            u'{:<2}'.format(file[T_TYPE] + ('+' if file[T_HAS_XATTR] else '')),
            to_str(file[T_UID]).rjust(uid_len + 1) + ' ',
            to_str(file[T_GID]).rjust(gid_len + 1) + ' ',
            u'{:04o} '.format(file[T_MODE] & 0o7777),
            u'{:>9}'.format(size_human_readable(file[T_SIZE])),
            u' {:<40}'.format(name))

    if archive:
        out = Color(out, 'yellow')
    elif file[T_TYPE] == 'D':
        out = Color(out, 'lightyellow')
    elif 'U' in file[T_SPEC]:
        out = Color(out, 'lightred')
    elif 'G' in file[T_SPEC]:
        out = Color(out, 'red')
    elif file[T_TYPE] == 'B':
        out = Color(out, 'grey')
    elif file[T_TYPE] == 'C':
        out = Color(out, 'grey')
    elif file[T_TYPE] == 'F':
        out = Color(out, 'cyan')
    elif file[T_TYPE] == 'S':
        out = Color(out, 'magenta')
    elif file[T_TYPE] == 'L':
        out = Color(out, 'grey')
    elif not file[T_SIZE]:
        out = Color(out, 'darkgrey')
    elif 'W' in file[T_SPEC] and not windows:
        out = Color(out, 'blue')
    elif file[T_HAS_XATTR]:
        out = Color(out, 'lightmagenta')
    elif 'E' in file[T_SPEC]:
        out = Color(out, 'lightgreen')

    return out
Example #8
0
class ls(PupyModule):
    """ list system files """
    is_module = False

    dependencies = ['pupyutils.basic_cmds']

    @classmethod
    def init_argparse(cls):
        cls.arg_parser = PupyArgumentParser(prog="ls", description=cls.__doc__)
        cls.arg_parser.add_argument('-d',
                                    '--dir',
                                    action='store_false',
                                    default=True,
                                    help='do not list directories')

        cls.arg_parser.add_argument('-u',
                                    '--userinfo',
                                    action='store_true',
                                    help='show uid info')
        cls.arg_parser.add_argument('-g',
                                    '--groupinfo',
                                    action='store_true',
                                    help='show gid info')

        sort = cls.arg_parser.add_mutually_exclusive_group()
        sort.add_argument(
            '-L',
            '--limit',
            type=int,
            default=1024,
            help='List no more than this amount of files (server side), '
            'to not to stuck on huge dirs. Default: 1024')
        sort.add_argument('-A',
                          '--archive',
                          action='store_true',
                          help='list archives (tar/zip)')
        sort.add_argument('-s',
                          '--size',
                          dest='sort',
                          action='store_const',
                          const=T_SIZE,
                          help='sort by size')
        sort.add_argument('-t',
                          '--time',
                          dest='sort',
                          action='store_const',
                          const=T_TIMESTAMP,
                          help='sort by time')
        cls.arg_parser.add_argument('-r',
                                    '--reverse',
                                    action='store_true',
                                    default=False,
                                    help='reverse sort order')
        cls.arg_parser.add_argument('path',
                                    type=str,
                                    nargs=REMAINDER,
                                    help='path of a specific file',
                                    completer=remote_path_completer)

    def run(self, args):
        try:
            ls = self.client.remote('pupyutils.basic_cmds', 'ls')

            path = ' '.join(args.path)

            results = ls(path, args.dir, args.limit, args.archive,
                         args.userinfo or args.groupinfo)

        except Exception, e:
            self.error(' '.join(x for x in e.args
                                if type(x) in (str, unicode)))
            return

        # results = obtain(results)
        windows = self.client.is_windows()

        if not results:
            return

        total_cnt = 0
        files_size = 0
        files_cnt = 0
        dirs_cnt = 0

        show_time = args.sort == T_TIMESTAMP

        for r in results:
            uid_len = 0
            gid_len = 0

            if T_FILES in r:
                archive = None
                is_windows = windows

                if args.userinfo or args.groupinfo:
                    for x in r[T_FILES]:
                        if args.userinfo:
                            uid = x.get(T_UID, '?')
                            if type(uid) == int:
                                uid = str(uid)

                            if elen(uid) > uid_len:
                                uid_len = elen(uid)

                        if args.groupinfo:
                            gid = x.get(T_GID, '?')
                            if type(gid) == int:
                                gid = str(gid)

                            if elen(gid) > gid_len:
                                gid_len = elen(gid)

                if T_ZIPFILE in r:
                    self.log(Color('ZIP: ' + r[T_ZIPFILE] + ':', 'lightred'))
                    is_windows = True
                elif T_TARFILE in r:
                    self.log(Color('TAR: ' + r[T_TARFILE] + ':', 'lightred'))
                    is_windows = False
                elif T_PATH in r:
                    self.log(r[T_PATH] + ':')

                if not args.sort:
                    dirs = []
                    files = []
                    truncated = 0

                    for x in r[T_FILES] or []:
                        if T_TRUNCATED in x:
                            truncated = x[T_TRUNCATED]
                            total_cnt += truncated
                        elif x[T_TYPE] == 'D':
                            dirs.append(x)
                            total_cnt += 1
                            dirs_cnt += 1
                        else:
                            files.append(x)
                            files_size += x[T_SIZE]
                            total_cnt += 1
                            files_cnt += 1

                    for f in sorted(dirs,
                                    key=lambda x: to_str(x.get(T_NAME)),
                                    reverse=args.reverse):
                        self.log(
                            output_format(f,
                                          is_windows,
                                          time=show_time,
                                          uid_len=uid_len,
                                          gid_len=gid_len))

                    for f in sorted(files,
                                    key=lambda x: to_str(x.get(T_NAME)),
                                    reverse=args.reverse):
                        self.log(
                            output_format(f,
                                          is_windows,
                                          time=show_time,
                                          uid_len=uid_len,
                                          gid_len=gid_len))

                    if truncated:
                        self.warning(
                            'Folder is too big. Not listed: {} (-L {})'.format(
                                truncated, args.limit))

                        self.info(
                            'Summary (observed): Files: {} Dirs: {} Total: {}'.
                            format(
                                '{}+'.format(files_cnt) if files_cnt else '??',
                                '{}+'.format(dirs_cnt) if dirs_cnt else '??',
                                total_cnt))
                    else:
                        self.info(
                            'Summary: Files: {} (size: {}) Dirs: {} Total: {}'.
                            format(files_cnt, size_human_readable(files_size),
                                   dirs_cnt, total_cnt))

                else:
                    truncated = False
                    for f in sorted(r[T_FILES],
                                    key=lambda x: x.get(args.sort),
                                    reverse=args.reverse):
                        if T_TRUNCATED in f:
                            truncated = True
                            continue

                        self.log(
                            output_format(f,
                                          is_windows,
                                          time=show_time,
                                          uid_len=uid_len,
                                          gid_len=gid_len))

                    if truncated:
                        self.log('--- TRUNCATED ---')

            elif T_FILE in r:
                is_windows = windows
                archive = ''
                if T_ZIPFILE in r:
                    archive = 'ZIP'
                    is_windows = True
                elif T_TARFILE in r:
                    archive = 'TAR'
                    is_windows = False

                if args.userinfo:
                    uid = r[T_FILE][T_UID]
                    if type(uid) == int:
                        uid = str(uid)

                    uid_len = elen(uid)

                if args.groupinfo:
                    gid = r[T_FILE][T_GID]
                    if type(gid) == int:
                        gid = str(gid)

                    gid_len = elen(gid)

                self.log(
                    output_format(r[T_FILE],
                                  is_windows,
                                  archive,
                                  show_time,
                                  uid_len=uid_len,
                                  gid_len=gid_len))

            else:
                self.error('Old format. Update pupyutils.basic_cmds')
                return
Example #9
0
class FStat(PupyModule):
    '''Show a bit more info about file path. ACLs/Caps/Owner for now'''

    dependencies = {
        'all': ['pupyutils', 'fsutils', 'fsutils_ext'],
        'windows': ['junctions', 'ntfs_streams'],
        'linux': ['xattr', 'posix1e', 'prctl', '_prctl']
    }

    @classmethod
    def init_argparse(cls):
        cls.arg_parser = PupyArgumentParser(prog='stat',
                                            description=cls.__doc__)
        cls.arg_parser.add_argument('path',
                                    type=str,
                                    nargs=REMAINDER,
                                    help='path of a specific file',
                                    completer=remote_path_completer)

    def run(self, args):
        getfilesec = self.client.remote('fsutils_ext', 'getfilesec')

        path = ' '.join(args.path)

        try:
            sec = getfilesec(path)
        except Exception, e:
            self.error(' '.join(x for x in e.args
                                if type(x) in (str, unicode)))
            return

        ctime, atime, mtime, size, owner, group, header, mode, extra = sec

        owner_id, owner_name, owner_domain = owner
        group_id, group_name, group_domain = group

        magic = ''
        if header:
            with Magic() as libmagic:
                magic = libmagic.id_buffer(header)

        default = {
            'Created':
            file_timestamp(ctime, time=True),
            'Accessed':
            file_timestamp(atime, time=True),
            'Modified':
            file_timestamp(mtime, time=True),
            'Size':
            '{} ({})'.format(size_human_readable(size), size),
            'Owner':
            '{}{} ({})'.format(owner_domain + '\\' if owner_domain else '',
                               owner_name, owner_id),
            'Group':
            '{}{} ({})'.format(group_domain + '\\' if group_domain else '',
                               group_name, group_id),
            'Mode':
            mode,
        }

        infos = []

        infos.append(
            Table([{
                'Property': p,
                'Value': default[p]
            } for p in ('Created', 'Accessed', 'Modified', 'Size', 'Owner',
                        'Group', 'Mode')], ['Property', 'Value'],
                  legend=False))

        if magic:
            infos.append('Magic: {}'.format(magic))

        for extra, values in extra.iteritems():
            if type(values) in (list, tuple):
                infos.append(List(values, caption=extra))
            else:
                infos.append(Line(extra + ':', values))

        self.log(MultiPart(infos))