X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=cmd%2Fxstat-cmd.py;h=06a881263bf4ea5b39c9e5a26ee252d336b9c2f4;hb=aeafe13a9330e7deca3dc6b9c0496937d904663a;hp=99b9f192d583578f059c2e92d468ee2b53908852;hpb=a097314a5ac7d80a331139c17a148ad6b79404f9;p=bup.git diff --git a/cmd/xstat-cmd.py b/cmd/xstat-cmd.py index 99b9f19..06a8812 100755 --- a/cmd/xstat-cmd.py +++ b/cmd/xstat-cmd.py @@ -1,67 +1,76 @@ -#!/usr/bin/env python +#!/bin/sh +"""": # -*-python-*- +bup_python="$(dirname "$0")/bup-python" || exit $? +exec "$bup_python" "$0" ${1+"$@"} +""" +# end of bup preamble + # Copyright (C) 2010 Rob Browning # # This code is covered under the terms of the GNU Library General # Public License as described in the bup LICENSE file. + +from __future__ import absolute_import, print_function import sys, stat, errno + from bup import metadata, options, xstat -from bup.helpers import handle_ctrl_c, saved_errors, add_error, log +from bup.helpers import add_error, handle_ctrl_c, parse_timestamp, saved_errors, \ + add_error, log -def fstimestr(fstime): - (s, ns) = xstat.fstime_to_timespec(fstime) - if(s < 0): - s += 1 - if ns == 0: - return '%d' % s - else: - return '%d.%09d' % (s, ns) +def parse_timestamp_arg(field, value): + res = str(value) # Undo autoconversion. + try: + res = parse_timestamp(res) + except ValueError as ex: + if ex.args: + o.fatal('unable to parse %s resolution "%s" (%s)' + % (field, value, ex)) + else: + o.fatal('unable to parse %s resolution "%s"' % (field, value)) + + if res != 1 and res % 10: + o.fatal('%s resolution "%s" must be a power of 10' % (field, value)) + return res optspec = """ -bup pathinfo [OPTION ...] +bup xstat pathinfo [OPTION ...] -- v,verbose increase log output (can be used more than once) q,quiet don't show progress meter exclude-fields= exclude comma-separated fields include-fields= include comma-separated fields (definitive if first) +atime-resolution= limit s, ms, us, ns, 10ns (value must be a power of 10) [ns] +mtime-resolution= limit s, ms, us, ns, 10ns (value must be a power of 10) [ns] +ctime-resolution= limit s, ms, us, ns, 10ns (value must be a power of 10) [ns] """ target_filename = '' -all_fields = frozenset(['path', - 'mode', - 'link-target', - 'rdev', - 'uid', - 'gid', - 'owner', - 'group', - 'atime', - 'mtime', - 'ctime', - 'linux-attr', - 'linux-xattr', - 'posix1e-acl']) -active_fields = all_fields +active_fields = metadata.all_fields handle_ctrl_c() o = options.Options(optspec) (opt, flags, remainder) = o.parse(sys.argv[1:]) +atime_resolution = parse_timestamp_arg('atime', opt.atime_resolution) +mtime_resolution = parse_timestamp_arg('mtime', opt.mtime_resolution) +ctime_resolution = parse_timestamp_arg('ctime', opt.ctime_resolution) + treat_include_fields_as_definitive = True for flag, value in flags: if flag == '--exclude-fields': exclude_fields = frozenset(value.split(',')) for f in exclude_fields: - if not f in all_fields: + if not f in metadata.all_fields: o.fatal(f + ' is not a valid field name') active_fields = active_fields - exclude_fields treat_include_fields_as_definitive = False elif flag == '--include-fields': include_fields = frozenset(value.split(',')) for f in include_fields: - if not f in all_fields: + if not f in metadata.all_fields: o.fatal(f + ' is not a valid field name') if treat_include_fields_as_definitive: active_fields = include_fields @@ -73,63 +82,27 @@ opt.verbose = opt.verbose or 0 opt.quiet = opt.quiet or 0 metadata.verbose = opt.verbose - opt.quiet +first_path = True for path in remainder: try: m = metadata.from_path(path, archive_path = path) - except (OSError,IOError), e: + except (OSError,IOError) as e: if e.errno == errno.ENOENT: add_error(e) continue else: raise - if 'path' in active_fields: - print 'path:', m.path - if 'mode' in active_fields: - print 'mode:', oct(m.mode) - if 'link-target' in active_fields and stat.S_ISLNK(m.mode): - print 'link-target:', m.symlink_target - if 'rdev' in active_fields: - print 'rdev:', m.rdev - if 'uid' in active_fields: - print 'uid:', m.uid - if 'gid' in active_fields: - print 'gid:', m.gid - if 'owner' in active_fields: - print 'owner:', m.owner - if 'group' in active_fields: - print 'group:', m.group - if 'atime' in active_fields: - # If we don't have utimensat, that means we have to use - # utime(), and utime() has no way to set the mtime/atime of a - # symlink. Thus, the mtime/atime of a symlink is meaningless, - # so let's not report it. (That way scripts comparing - # before/after won't trigger.) - if xstat.lutime or not stat.S_ISLNK(m.mode): - print 'atime: ' + fstimestr(m.atime) - else: - print 'atime: 0' - if 'mtime' in active_fields: - if xstat.lutime or not stat.S_ISLNK(m.mode): - print 'mtime: ' + fstimestr(m.mtime) - else: - print 'mtime: 0' - if 'ctime' in active_fields: - print 'ctime: ' + fstimestr(m.ctime) - if 'linux-attr' in active_fields and m.linux_attr: - print 'linux-attr:', hex(m.linux_attr) - if 'linux-xattr' in active_fields and m.linux_xattr: - for name, value in m.linux_xattr: - print 'linux-xattr: %s -> %s' % (name, repr(value)) - if 'posix1e-acl' in active_fields and m.posix1e_acl and metadata.posix1e: - flags = metadata.posix1e.TEXT_ABBREVIATE - if stat.S_ISDIR(m.mode): - acl = m.posix1e_acl[0] - default_acl = m.posix1e_acl[2] - print acl.to_any_text('posix1e-acl: ', '\n', flags) - print acl.to_any_text('posix1e-acl-default: ', '\n', flags) - else: - acl = m.posix1e_acl[0] - print acl.to_any_text('posix1e-acl: ', '\n', flags) + if metadata.verbose >= 0: + if not first_path: + print() + if atime_resolution != 1: + m.atime = (m.atime / atime_resolution) * atime_resolution + if mtime_resolution != 1: + m.mtime = (m.mtime / mtime_resolution) * mtime_resolution + if ctime_resolution != 1: + m.ctime = (m.ctime / ctime_resolution) * ctime_resolution + print(metadata.detailed_str(m, active_fields)) + first_path = False if saved_errors: log('WARNING: %d errors encountered.\n' % len(saved_errors))