]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/xstat.py
Update base_version to 0.34~ for 0.34 development
[bup.git] / lib / bup / xstat.py
index 23483f5991f6d0c226b672a03ce4445722dcf156..a0941294202864931e5e013318845aad1916d391 100644 (file)
@@ -1,65 +1,74 @@
 """Enhanced stat operations for bup."""
-import os
+
+from __future__ import absolute_import
+import os, sys
 import stat as pystat
 from bup import _helpers
 
 try:
     _bup_utimensat = _helpers.bup_utimensat
-except AttributeError, e:
+except AttributeError as e:
     _bup_utimensat = False
 
 try:
     _bup_utimes = _helpers.bup_utimes
-except AttributeError, e:
+except AttributeError as e:
     _bup_utimes = False
 
 try:
     _bup_lutimes = _helpers.bup_lutimes
-except AttributeError, e:
+except AttributeError as e:
     _bup_lutimes = False
 
+assert sys.version_info[0] < 3 \
+    or not (_bup_utimensat or _bup_utimes or _bup_lutimes)
+
 
-def timespec_to_nsecs((ts_s, ts_ns)):
-    # c.f. _helpers.c: timespec_vals_to_py_ns()
-    if ts_ns < 0 or ts_ns > 999999999:
-        raise Exception('invalid timespec nsec value')
+def timespec_to_nsecs(ts):
+    ts_s, ts_ns = ts
     return ts_s * 10**9 + ts_ns
 
 
 def nsecs_to_timespec(ns):
     """Return (s, ns) where ns is always non-negative
-    and t = s + ns / 10e8""" # metadata record rep (and libc rep)
+    and t = s + ns / 10e8""" # metadata record rep
     ns = int(ns)
-    return (ns / 10**9, ns % 10**9)
+    return (ns // 10**9, ns % 10**9)
 
 
 def nsecs_to_timeval(ns):
     """Return (s, us) where ns is always non-negative
     and t = s + us / 10e5"""
     ns = int(ns)
-    return (ns / 10**9, (ns % 10**9) / 1000)
+    return (ns // 10**9, (ns % 10**9) // 1000)
 
 
 def fstime_floor_secs(ns):
     """Return largest integer not greater than ns / 10e8."""
-    return int(ns) / 10**9;
+    return int(ns) // 10**9;
 
 
 def fstime_to_timespec(ns):
     return nsecs_to_timespec(ns)
 
 
-def fstime_to_sec_str(fstime):
+def fstime_to_sec_bytes(fstime):
     (s, ns) = fstime_to_timespec(fstime)
     if(s < 0):
         s += 1
     if ns == 0:
-        return '%d' % s
+        return b'%d' % s
     else:
-        return '%d.%09d' % (s, ns)
-
+        return b'%d.%09d' % (s, ns)
 
-if _bup_utimensat:
+if sys.version_info[0] > 2:
+    def utime(path, times):
+        """Times must be provided as (atime_ns, mtime_ns)."""
+        os.utime(path, ns=times)
+    def lutime(path, times):
+        """Times must be provided as (atime_ns, mtime_ns)."""
+        os.utime(path, ns=times, follow_symlinks=False)
+elif _bup_utimensat:
     def utime(path, times):
         """Times must be provided as (atime_ns, mtime_ns)."""
         atime = nsecs_to_timespec(times[0])
@@ -83,10 +92,21 @@ else: # Must have these if utimensat isn't available.
         mtime = nsecs_to_timeval(times[1])
         _bup_lutimes(path, (atime, mtime))
 
+_cygwin_sys = sys.platform.startswith('cygwin')
+
+def _fix_cygwin_id(id):
+    if id < 0:
+        id += 0x100000000
+        assert(id >= 0)
+    return id
+
 
 class stat_result:
+    __slots__ = ('st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid',
+                 'st_rdev', 'st_size', 'st_atime', 'st_mtime', 'st_ctime')
     @staticmethod
     def from_xstat_rep(st):
+        global _cygwin_sys
         result = stat_result()
         (result.st_mode,
          result.st_ino,
@@ -99,9 +119,13 @@ class stat_result:
          result.st_atime,
          result.st_mtime,
          result.st_ctime) = st
-        result.st_atime = timespec_to_nsecs(result.st_atime)
-        result.st_mtime = timespec_to_nsecs(result.st_mtime)
-        result.st_ctime = timespec_to_nsecs(result.st_ctime)
+        # Inlined timespec_to_nsecs after profiling
+        result.st_atime = result.st_atime[0] * 10**9 + result.st_atime[1]
+        result.st_mtime = result.st_mtime[0] * 10**9 + result.st_mtime[1]
+        result.st_ctime = result.st_ctime[0] * 10**9 + result.st_ctime[1]
+        if _cygwin_sys:
+            result.st_uid = _fix_cygwin_id(result.st_uid)
+            result.st_gid = _fix_cygwin_id(result.st_gid)
         return result
 
 
@@ -119,6 +143,7 @@ def lstat(path):
 
 def mode_str(mode):
     result = ''
+    # FIXME: Other types?
     if pystat.S_ISREG(mode):
         result += '-'
     elif pystat.S_ISDIR(mode):
@@ -146,3 +171,23 @@ def mode_str(mode):
     result += 'w' if (mode & pystat.S_IWOTH) else '-'
     result += 'x' if (mode & pystat.S_IXOTH) else '-'
     return result
+
+
+def classification_str(mode, include_exec):
+    if pystat.S_ISREG(mode):
+        if include_exec \
+           and (pystat.S_IMODE(mode) \
+                & (pystat.S_IXUSR | pystat.S_IXGRP | pystat.S_IXOTH)):
+            return '*'
+        else:
+            return ''
+    elif pystat.S_ISDIR(mode):
+        return '/'
+    elif pystat.S_ISLNK(mode):
+        return '@'
+    elif pystat.S_ISFIFO(mode):
+        return '|'
+    elif pystat.S_ISSOCK(mode):
+        return '='
+    else:
+        return ''