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