]> arthur.barton.de Git - bup.git/blob - cmd/xstat-cmd.py
cmd/xstat: don't report mtime/atime for symlinks if we don't have_ns_timestamps.
[bup.git] / cmd / xstat-cmd.py
1 #!/usr/bin/env python
2 # Copyright (C) 2010 Rob Browning
3 #
4 # This code is covered under the terms of the GNU Library General
5 # Public License as described in the bup LICENSE file.
6 import sys, stat, errno
7 from bup import metadata, options, xstat
8 from bup.helpers import handle_ctrl_c, saved_errors, add_error, log
9 from bup import _helpers
10
11
12 def fstimestr(fstime):
13     (s, ns) = fstime.secs_nsecs()
14     if ns == 0:
15         return '%d' % s
16     else:
17         return '%d.%09d' % (s, ns)
18
19
20 optspec = """
21 bup pathinfo [OPTION ...] <PATH ...>
22 --
23 v,verbose       increase log output (can be used more than once)
24 q,quiet         don't show progress meter
25 exclude-fields= exclude comma-separated fields
26 include-fields= include comma-separated fields (definitive if first)
27 """
28
29 target_filename = ''
30 all_fields = frozenset(['path',
31                         'mode',
32                         'link-target',
33                         'rdev',
34                         'uid',
35                         'gid',
36                         'owner',
37                         'group',
38                         'atime',
39                         'mtime',
40                         'ctime',
41                         'linux-attr',
42                         'linux-xattr',
43                         'posix1e-acl'])
44 active_fields = all_fields
45
46 handle_ctrl_c()
47
48 o = options.Options(optspec)
49 (opt, flags, remainder) = o.parse(sys.argv[1:])
50
51 treat_include_fields_as_definitive = True
52 for flag, value in flags:
53     if flag == '--verbose' or flag == '-v':
54         metadata.verbose += 1
55     elif flag == '--quiet' or flag == '-q':
56         metadata.verbose = 0
57     elif flag == '--exclude-fields':
58         exclude_fields = frozenset(value.split(','))
59         for f in exclude_fields:
60             if not f in all_fields:
61                 o.fatal(f + ' is not a valid field name')
62         active_fields = active_fields - exclude_fields
63         treat_include_fields_as_definitive = False
64     elif flag == '--include-fields':
65         include_fields = frozenset(value.split(','))
66         for f in include_fields:
67             if not f in all_fields:
68                 o.fatal(f + ' is not a valid field name')
69         if treat_include_fields_as_definitive:
70             active_fields = include_fields
71             treat_include_fields_as_definitive = False
72         else:
73             active_fields = active_fields | include_fields
74
75 for path in remainder:
76     try:
77         m = metadata.from_path(path, archive_path = path)
78     except (OSError,IOError), e:
79         if e.errno == errno.ENOENT:
80             add_error(e)
81             continue
82         else:
83             raise
84     if 'path' in active_fields:
85         print 'path:', m.path
86     if 'mode' in active_fields:
87         print 'mode:', oct(m.mode)
88     if 'link-target' in active_fields and stat.S_ISLNK(m.mode):
89         print 'link-target:', m.symlink_target
90     if 'rdev' in active_fields:
91         print 'rdev:', m.rdev
92     if 'uid' in active_fields:
93         print 'uid:', m.uid
94     if 'gid' in active_fields:
95         print 'gid:', m.gid
96     if 'owner' in active_fields:
97         print 'owner:', m.owner
98     if 'group' in active_fields:
99         print 'group:', m.group
100     if 'atime' in active_fields:
101         # if we don't have_ns_fs_timestamps, that means we have to use
102         # utime(), and utime() has no way to set the mtime/atime of a
103         # symlink.  Thus, the mtime/atime of a symlink is meaningless, so
104         # let's not report it.  (That way scripts comparing before/after
105         # won't trigger.)
106         if _helpers._have_ns_fs_timestamps or not stat.S_ISLNK(m.mode):
107             print 'atime: ' + fstimestr(m.atime)
108         else:
109             print 'atime: 0'
110     if 'mtime' in active_fields:
111         if _helpers._have_ns_fs_timestamps or not stat.S_ISLNK(m.mode):
112             print 'mtime: ' + fstimestr(m.mtime)
113         else:
114             print 'mtime: 0'
115     if 'ctime' in active_fields:
116         print 'ctime: ' + fstimestr(m.ctime)
117     if 'linux-attr' in active_fields and m.linux_attr:
118         print 'linux-attr:', hex(m.linux_attr)
119     if 'linux-xattr' in active_fields and m.linux_xattr:
120         for name, value in m.linux_xattr:
121             print 'linux-xattr: %s -> %s' % (name, repr(value))
122     if 'posix1e-acl' in active_fields and m.posix1e_acl and metadata.posix1e:
123         flags = metadata.posix1e.TEXT_ABBREVIATE
124         if stat.S_ISDIR(m.mode):
125             acl = m.posix1e_acl[0]
126             default_acl = m.posix1e_acl[2]
127             print acl.to_any_text('posix1e-acl: ', '\n', flags)
128             print acl.to_any_text('posix1e-acl-default: ', '\n', flags)
129         else:
130             acl = m.posix1e_acl[0]
131             print acl.to_any_text('posix1e-acl: ', '\n', flags)
132
133 if saved_errors:
134     log('WARNING: %d errors encountered.\n' % len(saved_errors))
135     sys.exit(1)
136 else:
137     sys.exit(0)