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