X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fbup%2Fxstat.py;h=a0941294202864931e5e013318845aad1916d391;hb=HEAD;hp=8daa2c2509e34246f917cadf08e94046aa4d02f1;hpb=85982e45546486479d09d0409d0c70b7b73a1013;p=bup.git diff --git a/lib/bup/xstat.py b/lib/bup/xstat.py index 8daa2c2..a094129 100644 --- a/lib/bup/xstat.py +++ b/lib/bup/xstat.py @@ -1,25 +1,31 @@ """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)): +def timespec_to_nsecs(ts): + ts_s, ts_ns = ts return ts_s * 10**9 + ts_ns @@ -27,36 +33,42 @@ def nsecs_to_timespec(ns): """Return (s, ns) where ns is always non-negative 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]) @@ -80,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, @@ -96,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 @@ -116,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): @@ -143,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 ''