1 """Enhanced stat operations for bup."""
3 from __future__ import absolute_import
6 from bup import _helpers
9 _bup_utimensat = _helpers.bup_utimensat
10 except AttributeError as e:
11 _bup_utimensat = False
14 _bup_utimes = _helpers.bup_utimes
15 except AttributeError as e:
19 _bup_lutimes = _helpers.bup_lutimes
20 except AttributeError as e:
23 assert sys.version_info[0] < 3 \
24 or not (_bup_utimensat or _bup_utimes or _bup_lutimes)
27 def timespec_to_nsecs(ts):
29 return ts_s * 10**9 + ts_ns
32 def nsecs_to_timespec(ns):
33 """Return (s, ns) where ns is always non-negative
34 and t = s + ns / 10e8""" # metadata record rep
36 return (ns // 10**9, ns % 10**9)
39 def nsecs_to_timeval(ns):
40 """Return (s, us) where ns is always non-negative
41 and t = s + us / 10e5"""
43 return (ns // 10**9, (ns % 10**9) // 1000)
46 def fstime_floor_secs(ns):
47 """Return largest integer not greater than ns / 10e8."""
48 return int(ns) // 10**9;
51 def fstime_to_timespec(ns):
52 return nsecs_to_timespec(ns)
55 def fstime_to_sec_bytes(fstime):
56 (s, ns) = fstime_to_timespec(fstime)
62 return b'%d.%09d' % (s, ns)
64 if sys.version_info[0] > 2:
65 def utime(path, times):
66 """Times must be provided as (atime_ns, mtime_ns)."""
67 os.utime(path, ns=times)
68 def lutime(path, times):
69 """Times must be provided as (atime_ns, mtime_ns)."""
70 os.utime(path, ns=times, follow_symlinks=False)
72 def utime(path, times):
73 """Times must be provided as (atime_ns, mtime_ns)."""
74 atime = nsecs_to_timespec(times[0])
75 mtime = nsecs_to_timespec(times[1])
76 _bup_utimensat(_helpers.AT_FDCWD, path, (atime, mtime), 0)
77 def lutime(path, times):
78 """Times must be provided as (atime_ns, mtime_ns)."""
79 atime = nsecs_to_timespec(times[0])
80 mtime = nsecs_to_timespec(times[1])
81 _bup_utimensat(_helpers.AT_FDCWD, path, (atime, mtime),
82 _helpers.AT_SYMLINK_NOFOLLOW)
83 else: # Must have these if utimensat isn't available.
84 def utime(path, times):
85 """Times must be provided as (atime_ns, mtime_ns)."""
86 atime = nsecs_to_timeval(times[0])
87 mtime = nsecs_to_timeval(times[1])
88 _bup_utimes(path, (atime, mtime))
89 def lutime(path, times):
90 """Times must be provided as (atime_ns, mtime_ns)."""
91 atime = nsecs_to_timeval(times[0])
92 mtime = nsecs_to_timeval(times[1])
93 _bup_lutimes(path, (atime, mtime))
95 _cygwin_sys = sys.platform.startswith('cygwin')
97 def _fix_cygwin_id(id):
105 __slots__ = ('st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid',
106 'st_rdev', 'st_size', 'st_atime', 'st_mtime', 'st_ctime')
108 def from_xstat_rep(st):
110 result = stat_result()
121 result.st_ctime) = st
122 # Inlined timespec_to_nsecs after profiling
123 result.st_atime = result.st_atime[0] * 10**9 + result.st_atime[1]
124 result.st_mtime = result.st_mtime[0] * 10**9 + result.st_mtime[1]
125 result.st_ctime = result.st_ctime[0] * 10**9 + result.st_ctime[1]
127 result.st_uid = _fix_cygwin_id(result.st_uid)
128 result.st_gid = _fix_cygwin_id(result.st_gid)
133 return stat_result.from_xstat_rep(_helpers.stat(path))
137 return stat_result.from_xstat_rep(_helpers.fstat(path))
141 return stat_result.from_xstat_rep(_helpers.lstat(path))
146 # FIXME: Other types?
147 if pystat.S_ISREG(mode):
149 elif pystat.S_ISDIR(mode):
151 elif pystat.S_ISCHR(mode):
153 elif pystat.S_ISBLK(mode):
155 elif pystat.S_ISFIFO(mode):
157 elif pystat.S_ISLNK(mode):
159 elif pystat.S_ISSOCK(mode):
164 result += 'r' if (mode & pystat.S_IRUSR) else '-'
165 result += 'w' if (mode & pystat.S_IWUSR) else '-'
166 result += 'x' if (mode & pystat.S_IXUSR) else '-'
167 result += 'r' if (mode & pystat.S_IRGRP) else '-'
168 result += 'w' if (mode & pystat.S_IWGRP) else '-'
169 result += 'x' if (mode & pystat.S_IXGRP) else '-'
170 result += 'r' if (mode & pystat.S_IROTH) else '-'
171 result += 'w' if (mode & pystat.S_IWOTH) else '-'
172 result += 'x' if (mode & pystat.S_IXOTH) else '-'
176 def classification_str(mode, include_exec):
177 if pystat.S_ISREG(mode):
179 and (pystat.S_IMODE(mode) \
180 & (pystat.S_IXUSR | pystat.S_IXGRP | pystat.S_IXOTH)):
184 elif pystat.S_ISDIR(mode):
186 elif pystat.S_ISLNK(mode):
188 elif pystat.S_ISFIFO(mode):
190 elif pystat.S_ISSOCK(mode):