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