]> arthur.barton.de Git - bup.git/blob - lib/bup/xstat.py
23483f5991f6d0c226b672a03ce4445722dcf156
[bup.git] / lib / bup / xstat.py
1 """Enhanced stat operations for bup."""
2 import os
3 import stat as pystat
4 from bup import _helpers
5
6 try:
7     _bup_utimensat = _helpers.bup_utimensat
8 except AttributeError, e:
9     _bup_utimensat = False
10
11 try:
12     _bup_utimes = _helpers.bup_utimes
13 except AttributeError, e:
14     _bup_utimes = False
15
16 try:
17     _bup_lutimes = _helpers.bup_lutimes
18 except AttributeError, e:
19     _bup_lutimes = False
20
21
22 def timespec_to_nsecs((ts_s, ts_ns)):
23     # c.f. _helpers.c: timespec_vals_to_py_ns()
24     if ts_ns < 0 or ts_ns > 999999999:
25         raise Exception('invalid timespec nsec value')
26     return ts_s * 10**9 + ts_ns
27
28
29 def nsecs_to_timespec(ns):
30     """Return (s, ns) where ns is always non-negative
31     and t = s + ns / 10e8""" # metadata record rep (and libc rep)
32     ns = int(ns)
33     return (ns / 10**9, ns % 10**9)
34
35
36 def nsecs_to_timeval(ns):
37     """Return (s, us) where ns is always non-negative
38     and t = s + us / 10e5"""
39     ns = int(ns)
40     return (ns / 10**9, (ns % 10**9) / 1000)
41
42
43 def fstime_floor_secs(ns):
44     """Return largest integer not greater than ns / 10e8."""
45     return int(ns) / 10**9;
46
47
48 def fstime_to_timespec(ns):
49     return nsecs_to_timespec(ns)
50
51
52 def fstime_to_sec_str(fstime):
53     (s, ns) = fstime_to_timespec(fstime)
54     if(s < 0):
55         s += 1
56     if ns == 0:
57         return '%d' % s
58     else:
59         return '%d.%09d' % (s, ns)
60
61
62 if _bup_utimensat:
63     def utime(path, times):
64         """Times must be provided as (atime_ns, mtime_ns)."""
65         atime = nsecs_to_timespec(times[0])
66         mtime = nsecs_to_timespec(times[1])
67         _bup_utimensat(_helpers.AT_FDCWD, path, (atime, mtime), 0)
68     def lutime(path, times):
69         """Times must be provided as (atime_ns, mtime_ns)."""
70         atime = nsecs_to_timespec(times[0])
71         mtime = nsecs_to_timespec(times[1])
72         _bup_utimensat(_helpers.AT_FDCWD, path, (atime, mtime),
73                        _helpers.AT_SYMLINK_NOFOLLOW)
74 else: # Must have these if utimensat isn't available.
75     def utime(path, times):
76         """Times must be provided as (atime_ns, mtime_ns)."""
77         atime = nsecs_to_timeval(times[0])
78         mtime = nsecs_to_timeval(times[1])
79         _bup_utimes(path, (atime, mtime))
80     def lutime(path, times):
81         """Times must be provided as (atime_ns, mtime_ns)."""
82         atime = nsecs_to_timeval(times[0])
83         mtime = nsecs_to_timeval(times[1])
84         _bup_lutimes(path, (atime, mtime))
85
86
87 class stat_result:
88     @staticmethod
89     def from_xstat_rep(st):
90         result = stat_result()
91         (result.st_mode,
92          result.st_ino,
93          result.st_dev,
94          result.st_nlink,
95          result.st_uid,
96          result.st_gid,
97          result.st_rdev,
98          result.st_size,
99          result.st_atime,
100          result.st_mtime,
101          result.st_ctime) = st
102         result.st_atime = timespec_to_nsecs(result.st_atime)
103         result.st_mtime = timespec_to_nsecs(result.st_mtime)
104         result.st_ctime = timespec_to_nsecs(result.st_ctime)
105         return result
106
107
108 def stat(path):
109     return stat_result.from_xstat_rep(_helpers.stat(path))
110
111
112 def fstat(path):
113     return stat_result.from_xstat_rep(_helpers.fstat(path))
114
115
116 def lstat(path):
117     return stat_result.from_xstat_rep(_helpers.lstat(path))
118
119
120 def mode_str(mode):
121     result = ''
122     if pystat.S_ISREG(mode):
123         result += '-'
124     elif pystat.S_ISDIR(mode):
125         result += 'd'
126     elif pystat.S_ISCHR(mode):
127         result += 'c'
128     elif pystat.S_ISBLK(mode):
129         result += 'b'
130     elif pystat.S_ISFIFO(mode):
131         result += 'p'
132     elif pystat.S_ISLNK(mode):
133         result += 'l'
134     elif pystat.S_ISSOCK(mode):
135         result += 's'
136     else:
137         result += '?'
138
139     result += 'r' if (mode & pystat.S_IRUSR) else '-'
140     result += 'w' if (mode & pystat.S_IWUSR) else '-'
141     result += 'x' if (mode & pystat.S_IXUSR) else '-'
142     result += 'r' if (mode & pystat.S_IRGRP) else '-'
143     result += 'w' if (mode & pystat.S_IWGRP) else '-'
144     result += 'x' if (mode & pystat.S_IXGRP) else '-'
145     result += 'r' if (mode & pystat.S_IROTH) else '-'
146     result += 'w' if (mode & pystat.S_IWOTH) else '-'
147     result += 'x' if (mode & pystat.S_IXOTH) else '-'
148     return result