]> arthur.barton.de Git - bup.git/blob - lib/bup/xstat.py
Merge remote branch 'origin/master' into meta
[bup.git] / lib / bup / xstat.py
1 """Enhanced stat operations for bup."""
2 import os
3 import bup._helpers as _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 to_timespec(self):
22         """Return (s, ns) where ns is always non-negative
23         and t = s + ns / 10e8""" # metadata record rep (and libc rep)
24         s_ns = self.secs_nsecs()
25         if s_ns[0] > 0 or s_ns[1] >= 0:
26             return s_ns
27         return (s_ns[0] - 1, 10**9 + s_ns[1]) # ns is negative
28
29     @staticmethod
30     def from_secs(secs):
31         ts = FSTime()
32         ts._value = int(secs * 10**9)
33         return ts
34
35     @staticmethod
36     def from_timespec(timespec):
37         ts = FSTime()
38         ts._value = timespec[0] * 10**9 + timespec[1]
39         return ts
40
41     def approx_secs(self):
42         return self._value / 10e8;
43
44     def secs_nsecs(self):
45         "Return a (s, ns) pair: -1.5s -> (-1, -10**9 / 2)."
46         if self._value >= 0:
47             return (self._value / 10**9, self._value % 10**9)
48         abs_val = -self._value
49         return (- (abs_val / 10**9), - (abs_val % 10**9))
50
51     if _helpers._have_ns_fs_timestamps: # Use integer nanoseconds.
52
53         @staticmethod
54         def from_stat_time(stat_time):
55             return FSTime.from_timespec(stat_time)
56
57     else: # Use python default floating-point seconds.
58
59         @staticmethod
60         def from_stat_time(stat_time):
61             ts = FSTime()
62             x = math.modf(stat_time)
63             ts._value = int(x[1]) + int(x[0] * 10**9)
64             return ts
65
66
67 if _have_utimensat:
68
69     def lutime(path, times):
70         atime = times[0].to_timespec()
71         mtime = times[1].to_timespec()
72         return _helpers.utimensat(_helpers.AT_FDCWD, path, (atime, mtime),
73                                   _helpers.AT_SYMLINK_NOFOLLOW)
74     def utime(path, times):
75         atime = times[0].to_timespec()
76         mtime = times[1].to_timespec()
77         return _helpers.utimensat(_helpers.AT_FDCWD, path, (atime, mtime), 0)
78
79 else:
80
81     def lutime(path, times):
82         return None
83
84     def utime(path, times):
85         atime = times[0].approx_secs()
86         mtime = times[1].approx_secs()
87         os.utime(path, (atime, mtime))
88
89
90 class stat_result():
91
92     @staticmethod
93     def from_stat_rep(st):
94         result = stat_result()
95         if _helpers._have_ns_fs_timestamps:
96             (result.st_mode,
97              result.st_ino,
98              result.st_dev,
99              result.st_nlink,
100              result.st_uid,
101              result.st_gid,
102              result.st_rdev,
103              result.st_size,
104              atime,
105              mtime,
106              ctime) = st
107         else:
108             result.st_mode = st.st_mode
109             result.st_ino = st.st_ino
110             result.st_dev = st.st_dev
111             result.st_nlink = st.st_nlink
112             result.st_uid = st.st_uid
113             result.st_gid = st.st_gid
114             result.st_rdev = st.st_rdev
115             result.st_size = st.st_size
116             atime = FSTime.from_stat_time(st.st_atime)
117             mtime = FSTime.from_stat_time(st.st_mtime)
118             ctime = FSTime.from_stat_time(st.st_ctime)
119         result.st_atime = FSTime.from_stat_time(atime)
120         result.st_mtime = FSTime.from_stat_time(mtime)
121         result.st_ctime = FSTime.from_stat_time(ctime)
122         return result
123
124
125 try:
126     _stat = _helpers.stat
127 except AttributeError, e:
128     _stat = os.stat
129
130 def stat(path):
131     return stat_result.from_stat_rep(_stat(path))
132
133
134 try:
135     _fstat = _helpers.fstat
136 except AttributeError, e:
137     _fstat = os.fstat
138
139 def fstat(path):
140     return stat_result.from_stat_rep(_fstat(path))
141
142
143 try:
144     _lstat = _helpers.lstat
145 except AttributeError, e:
146     _lstat = os.lstat
147
148 def lstat(path):
149     return stat_result.from_stat_rep(_lstat(path))