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