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