]> arthur.barton.de Git - bup.git/blob - lib/bup/xstat.py
e3044bebfd505a9a9573dc73f9e454253e9802fa
[bup.git] / lib / bup / xstat.py
1 """Enhanced stat operations for bup."""
2 import os
3 from bup import _helpers
4
5
6 try:
7     _have_utimensat = _helpers.utimensat
8 except AttributeError, e:
9     _have_utimensat = False
10
11
12 class FSTime:
13     # Class to represent filesystem timestamps.  Use integer
14     # nanoseconds on platforms where we have the higher resolution
15     # lstat.  Use the native python stat representation (floating
16     # point seconds) otherwise.
17
18     def __cmp__(self, x):
19         return self._value.__cmp__(x._value)
20         
21     def __repr__(self):
22         return 'FSTime(%d)' % self._value
23         
24     def to_timespec(self):
25         """Return (s, ns) where ns is always non-negative
26         and t = s + ns / 10e8""" # metadata record rep (and libc rep)
27         s_ns = self.secs_nsecs()
28         if s_ns[0] > 0 or s_ns[1] >= 0:
29             return s_ns
30         return (s_ns[0] - 1, 10**9 + s_ns[1]) # ns is negative
31
32     @staticmethod
33     def from_secs(secs):
34         ts = FSTime()
35         ts._value = int(round(secs * 10**9))
36         return ts
37
38     @staticmethod
39     def from_timespec(timespec):
40         ts = FSTime()
41         ts._value = timespec[0] * 10**9 + timespec[1]
42         return ts
43
44     def approx_secs(self):
45         return self._value / 10e8;
46
47     def secs_nsecs(self):
48         "Return a (s, ns) pair: -1.5s -> (-1, -10**9 / 2)."
49         if self._value >= 0:
50             return (self._value / 10**9, self._value % 10**9)
51         abs_val = -self._value
52         return (- (abs_val / 10**9), - (abs_val % 10**9))
53
54
55 if _have_utimensat:
56     def lutime(path, times):
57         atime = times[0].to_timespec()
58         mtime = times[1].to_timespec()
59         return _helpers.utimensat(_helpers.AT_FDCWD, path, (atime, mtime),
60                                   _helpers.AT_SYMLINK_NOFOLLOW)
61     def utime(path, times):
62         atime = times[0].to_timespec()
63         mtime = times[1].to_timespec()
64         return _helpers.utimensat(_helpers.AT_FDCWD, path, (atime, mtime), 0)
65 else:
66     def lutime(path, times):
67         return None
68
69     def utime(path, times):
70         atime = times[0].approx_secs()
71         mtime = times[1].approx_secs()
72         os.utime(path, (atime, mtime))
73
74
75 class stat_result:
76     @staticmethod
77     def from_stat_rep(st):
78         result = stat_result()
79         (result.st_mode,
80          result.st_ino,
81          result.st_dev,
82          result.st_nlink,
83          result.st_uid,
84          result.st_gid,
85          result.st_rdev,
86          result.st_size,
87          result.st_atime,
88          result.st_mtime,
89          result.st_ctime) = st
90         result.st_atime = FSTime.from_timespec(result.st_atime)
91         result.st_mtime = FSTime.from_timespec(result.st_mtime)
92         result.st_ctime = FSTime.from_timespec(result.st_ctime)
93         return result
94
95
96 def stat(path):
97     return stat_result.from_stat_rep(_helpers.stat(path))
98
99
100 def fstat(path):
101     return stat_result.from_stat_rep(_helpers.fstat(path))
102
103
104 def lstat(path):
105     return stat_result.from_stat_rep(_helpers.lstat(path))