From 8b8faaf74ce154f9f2275bef92d514e4fe160d09 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Fri, 10 Oct 2008 14:34:14 +0200 Subject: [PATCH] Time renamed to RTime to avoid ambiguity on case insensitive filesystems --- rdiff_backup/Hardlink.py | 2 +- rdiff_backup/Main.py | 42 ++++---- rdiff_backup/RTime.py | 247 ++++++++++++++++++++++++++++++++++++++++++++ rdiff_backup/Security.py | 4 +- rdiff_backup/Time.py | 247 -------------------------------------------- rdiff_backup/backup.py | 4 +- rdiff_backup/connection.py | 2 +- rdiff_backup/increment.py | 6 +- rdiff_backup/manage.py | 12 +- rdiff_backup/metadata.py | 6 +- rdiff_backup/regress.py | 8 +- rdiff_backup/restore.py | 2 +- rdiff_backup/rpath.py | 6 +- rdiff_backup/statistics.py | 14 ++-- 14 files changed, 301 insertions(+), 301 deletions(-) create mode 100644 rdiff_backup/RTime.py delete mode 100644 rdiff_backup/Time.py diff --git a/rdiff_backup/Hardlink.py b/rdiff_backup/Hardlink.py index d0cb19f..53fa93e 100644 --- a/rdiff_backup/Hardlink.py +++ b/rdiff_backup/Hardlink.py @@ -31,7 +31,7 @@ source side should only transmit inode information. """ from __future__ import generators -import Globals, Time, log, robust, errno +import Globals, RTime, log, robust, errno # The keys in this dictionary are (inode, devloc) pairs. The values # are a pair (index, remaining_links, dest_key, sha1sum) where index diff --git a/rdiff_backup/Main.py b/rdiff_backup/Main.py index 6e050c0..06a6c80 100644 --- a/rdiff_backup/Main.py +++ b/rdiff_backup/Main.py @@ -22,7 +22,7 @@ from __future__ import generators import getopt, sys, re, os, cStringIO, tempfile from log import Log, LoggerError, ErrorLog -import Globals, Time, SetConnections, selection, robust, rpath, \ +import Globals, RTime, SetConnections, selection, robust, rpath, \ manage, backup, connection, restore, FilenameMapping, \ Security, Hardlink, regress, C, fs_abilities, statistics, compare @@ -244,7 +244,7 @@ def commandline_error(message): def misc_setup(rps): """Set default change ownership flag, umask, relay regexps""" os.umask(077) - Time.setcurtime(Globals.current_time) + RTime.setcurtime(Globals.current_time) SetConnections.UpdateGlobal("client_conn", Globals.local_connection) Globals.postset_regexp('no_compression_regexp', Globals.no_compression_regexp_string) @@ -336,7 +336,7 @@ def Backup(rpin, rpout): backup_set_select(rpin) backup_warn_if_infinite_regress(rpin, rpout) if prevtime: - Time.setprevtime(prevtime) + RTime.setprevtime(prevtime) rpout.conn.Main.backup_touch_curmirror_local(rpin, rpout) backup.Mirror_and_increment(rpin, rpout, incdir) rpout.conn.Main.backup_remove_curmirror_local() @@ -434,10 +434,10 @@ def backup_final_init(rpout): Log.open_logfile(Globals.rbdir.append("backup.log")) checkdest_if_necessary(rpout) prevtime = backup_get_mirrortime() - if prevtime >= Time.curtime: Log.FatalError( + if prevtime >= RTime.curtime: Log.FatalError( """Time of Last backup is not in the past. This is probably caused by running two backups in less than a second. Wait a second a try again.""") - ErrorLog.open(Time.curtimestr, compress = Globals.compression) + ErrorLog.open(RTime.curtimestr, compress = Globals.compression) if not incdir.lstat(): incdir.mkdir() def backup_touch_curmirror_local(rpin, rpout): @@ -452,7 +452,7 @@ def backup_touch_curmirror_local(rpin, rpout): everything else is in place. """ - mirrorrp = Globals.rbdir.append("current_mirror.%s.%s" % (Time.curtimestr, + mirrorrp = Globals.rbdir.append("current_mirror.%s.%s" % (RTime.curtimestr, "data")) Log("Writing mirror marker %s" % mirrorrp.path, 6) try: pid = os.getpid() @@ -490,8 +490,8 @@ def Restore(src_rp, dest_rp, restore_as_of = None): restore_check_backup_dir(restore_root, src_rp, restore_as_of) inc_rpath = Globals.rbdir.append_path('increments', restore_index) if restore_as_of: - try: time = Time.genstrtotime(restore_timestr, rp = inc_rpath) - except Time.TimeException, exc: Log.FatalError(str(exc)) + try: time = RTime.genstrtotime(restore_timestr, rp = inc_rpath) + except RTime.TimeException, exc: Log.FatalError(str(exc)) else: time = src_rp.getinctime() restore_set_select(restore_root, dest_rp) restore_start_log(src_rp, dest_rp, time) @@ -539,7 +539,7 @@ def restore_start_log(rpin, target, time): # Log following message at file verbosity 3, but term verbosity 4 log_message = ("Starting restore of %s to %s as it was as of %s." % - (rpin.path, target.path, Time.timetopretty(time))) + (rpin.path, target.path, RTime.timetopretty(time))) if Log.term_verbosity >= 4: Log.log_to_term(log_message, 4) if Log.verbosity >= 3: Log.log_to_file(log_message) @@ -681,19 +681,19 @@ def RemoveOlderThan(rootrp): def rot_check_time(time_string): """Check remove older than time_string, return time in seconds""" - try: time = Time.genstrtotime(time_string) - except Time.TimeException, exc: Log.FatalError(str(exc)) + try: time = RTime.genstrtotime(time_string) + except RTime.TimeException, exc: Log.FatalError(str(exc)) times_in_secs = [inc.getinctime() for inc in restore.get_inclist(Globals.rbdir.append_path("increments"))] times_in_secs = filter(lambda t: t < time, times_in_secs) if not times_in_secs: Log("No increments older than %s found, exiting." % - (Time.timetopretty(time),), 3) + (RTime.timetopretty(time),), 3) return None times_in_secs.sort() - inc_pretty_time = "\n".join(map(Time.timetopretty, times_in_secs)) + inc_pretty_time = "\n".join(map(RTime.timetopretty, times_in_secs)) if len(times_in_secs) > 1 and not force: Log.FatalError("Found %d relevant increments, dated:\n%s" "\nIf you want to delete multiple increments in this way, " @@ -714,8 +714,8 @@ def rot_require_rbdir_base(rootrp): def ListChangedSince(rp): """List all the files under rp that have changed since restoretime""" rp = require_root_set(rp, 1) - try: rest_time = Time.genstrtotime(restore_timestr) - except Time.TimeException, exc: Log.FatalError(str(exc)) + try: rest_time = RTime.genstrtotime(restore_timestr) + except RTime.TimeException, exc: Log.FatalError(str(exc)) mirror_rp = restore_root.new_index(restore_index) inc_rp = mirror_rp.append_path("increments", restore_index) for rorp in rp.conn.restore.ListChangedSince(mirror_rp, inc_rp, rest_time): @@ -726,8 +726,8 @@ def ListChangedSince(rp): def ListAtTime(rp): """List files in archive under rp that are present at restoretime""" rp = require_root_set(rp, 1) - try: rest_time = Time.genstrtotime(restore_timestr) - except Time.TimeException, exc: Log.FatalError(str(exc)) + try: rest_time = RTime.genstrtotime(restore_timestr) + except RTime.TimeException, exc: Log.FatalError(str(exc)) mirror_rp = restore_root.new_index(restore_index) inc_rp = mirror_rp.append_path("increments", restore_index) for rorp in rp.conn.restore.ListAtTime(mirror_rp, inc_rp, rest_time): @@ -747,8 +747,8 @@ def Compare(compare_type, src_rp, dest_rp, compare_time = None): global return_val dest_rp = require_root_set(dest_rp, 1) if not compare_time: - try: compare_time = Time.genstrtotime(restore_timestr) - except Time.TimeException, exc: Log.FatalError(str(exc)) + try: compare_time = RTime.genstrtotime(restore_timestr) + except RTime.TimeException, exc: Log.FatalError(str(exc)) mirror_rp = restore_root.new_index(restore_index) inc_rp = Globals.rbdir.append_path("increments", restore_index) @@ -765,8 +765,8 @@ def Verify(dest_rp, verify_time = None): global return_val dest_rp = require_root_set(dest_rp, 1) if not verify_time: - try: verify_time = Time.genstrtotime(restore_timestr) - except Time.TimeException, exc: Log.FatalError(str(exc)) + try: verify_time = RTime.genstrtotime(restore_timestr) + except RTime.TimeException, exc: Log.FatalError(str(exc)) mirror_rp = restore_root.new_index(restore_index) inc_rp = Globals.rbdir.append_path("increments", restore_index) diff --git a/rdiff_backup/RTime.py b/rdiff_backup/RTime.py new file mode 100644 index 0000000..6ee3b0a --- /dev/null +++ b/rdiff_backup/RTime.py @@ -0,0 +1,247 @@ +# Copyright 2002 Ben Escoto +# +# This file is part of rdiff-backup. +# +# rdiff-backup is free software; you can redistribute it and/or modify +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# rdiff-backup is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with rdiff-backup; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + +"""Provide time related exceptions and functions""" + +import time, types, re, sys, calendar +import Globals + + +class TimeException(Exception): pass + +_interval_conv_dict = {"s": 1, "m": 60, "h": 3600, "D": 86400, + "W": 7*86400, "M": 30*86400, "Y": 365*86400} +_integer_regexp = re.compile("^[0-9]+$") +_session_regexp = re.compile("^[0-9]+B$") +_interval_regexp = re.compile("^([0-9]+)([smhDWMY])") +_genstr_date_regexp1 = re.compile("^(?P[0-9]{4})[-/]" + "(?P[0-9]{1,2})[-/](?P[0-9]{1,2})$") +_genstr_date_regexp2 = re.compile("^(?P[0-9]{1,2})[-/]" + "(?P[0-9]{1,2})[-/](?P[0-9]{4})$") +curtime = curtimestr = None + +def setcurtime(curtime = None): + """Sets the current time in curtime and curtimestr on all systems""" + t = curtime or time.time() + for conn in Globals.connections: + conn.RTime.setcurtime_local(long(t)) + +def setcurtime_local(timeinseconds): + """Only set the current time locally""" + global curtime, curtimestr + curtime, curtimestr = timeinseconds, timetostring(timeinseconds) + +def setprevtime(timeinseconds): + """Sets the previous inc time in prevtime and prevtimestr""" + assert 0 < timeinseconds < curtime, \ + "Time %s is out of bounds" % (timeinseconds,) + timestr = timetostring(timeinseconds) + for conn in Globals.connections: + conn.RTime.setprevtime_local(timeinseconds, timestr) + +def setprevtime_local(timeinseconds, timestr): + """Like setprevtime but only set the local version""" + global prevtime, prevtimestr + prevtime, prevtimestr = timeinseconds, timestr + +def timetostring(timeinseconds): + """Return w3 datetime compliant listing of timeinseconds""" + s = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(timeinseconds)) + return s + gettzd(timeinseconds) + +def stringtotime(timestring): + """Return time in seconds from w3 timestring + + If there is an error parsing the string, or it doesn't look + like a w3 datetime string, return None. + + """ + try: + date, daytime = timestring[:19].split("T") + year, month, day = map(int, date.split("-")) + hour, minute, second = map(int, daytime.split(":")) + assert 1900 < year < 2100, year + assert 1 <= month <= 12 + assert 1 <= day <= 31 + assert 0 <= hour <= 23 + assert 0 <= minute <= 59 + assert 0 <= second <= 61 # leap seconds + timetuple = (year, month, day, hour, minute, second, -1, -1, 0) + utc_in_secs = calendar.timegm(timetuple) + + return long(utc_in_secs) + tzdtoseconds(timestring[19:]) + except (TypeError, ValueError, AssertionError): return None + +def timetopretty(timeinseconds): + """Return pretty version of time""" + return time.asctime(time.localtime(timeinseconds)) + +def stringtopretty(timestring): + """Return pretty version of time given w3 time string""" + return timetopretty(stringtotime(timestring)) + +def prettytotime(prettystring): + """Converts time like "Mon Jun 5 11:00:23" to epoch sec, or None""" + try: return time.mktime(time.strptime(prettystring)) + except ValueError: return None + +def inttopretty(seconds): + """Convert num of seconds to readable string like "2 hours".""" + partlist = [] + hours, seconds = divmod(seconds, 3600) + if hours > 1: partlist.append("%d hours" % hours) + elif hours == 1: partlist.append("1 hour") + + minutes, seconds = divmod(seconds, 60) + if minutes > 1: partlist.append("%d minutes" % minutes) + elif minutes == 1: partlist.append("1 minute") + + if seconds == 1: partlist.append("1 second") + elif not partlist or seconds > 1: + if isinstance(seconds, int) or isinstance(seconds, long): + partlist.append("%s seconds" % seconds) + else: partlist.append("%.2f seconds" % seconds) + return " ".join(partlist) + +def intstringtoseconds(interval_string): + """Convert a string expressing an interval (e.g. "4D2s") to seconds""" + def error(): + raise TimeException("""Bad interval string "%s" + +Intervals are specified like 2Y (2 years) or 2h30m (2.5 hours). The +allowed special characters are s, m, h, D, W, M, and Y. See the man +page for more information. +""" % interval_string) + if len(interval_string) < 2: error() + + total = 0 + while interval_string: + match = _interval_regexp.match(interval_string) + if not match: error() + num, ext = int(match.group(1)), match.group(2) + if not ext in _interval_conv_dict or num < 0: error() + total += num*_interval_conv_dict[ext] + interval_string = interval_string[match.end(0):] + return total + +def gettzd(timeinseconds = None): + """Return w3's timezone identification string. + + Expresed as [+/-]hh:mm. For instance, PDT is -07:00 during + dayling savings and -08:00 otherwise. Zone is coincides with what + localtime(), etc., use. If no argument given, use the current + time. + + """ + if timeinseconds is None: timeinseconds = time.time() + dst_in_effect = time.daylight and time.localtime(timeinseconds)[8] + if dst_in_effect: offset = -time.altzone/60 + else: offset = -time.timezone/60 + if offset > 0: prefix = "+" + elif offset < 0: prefix = "-" + else: return "Z" # time is already in UTC + + hours, minutes = map(abs, divmod(offset, 60)) + assert 0 <= hours <= 23 + assert 0 <= minutes <= 59 + return "%s%02d:%02d" % (prefix, hours, minutes) + +def tzdtoseconds(tzd): + """Given w3 compliant TZD, return how far ahead UTC is""" + if tzd == "Z": return 0 + assert len(tzd) == 6 # only accept forms like +08:00 for now + assert (tzd[0] == "-" or tzd[0] == "+") and tzd[3] == ":" + return -60 * (60 * int(tzd[:3]) + int(tzd[4:])) + +def cmp(time1, time2): + """Compare time1 and time2 and return -1, 0, or 1""" + if type(time1) is types.StringType: + time1 = stringtotime(time1) + assert time1 is not None + if type(time2) is types.StringType: + time2 = stringtotime(time2) + assert time2 is not None + + if time1 < time2: return -1 + elif time1 == time2: return 0 + else: return 1 + +def time_from_session(session_num, rp = None): + """Return time in seconds of given backup + + The current mirror is session_num 0, the next oldest increment has + number 1, etc. Requires that the Globals.rbdir directory be set. + + """ + session_times = Globals.rbdir.conn.restore.MirrorStruct \ + .get_increment_times() + session_times.sort() + if len(session_times) <= session_num: + return session_times[0] # Use oldest if too few backups + return session_times[-session_num-1] + +def genstrtotime(timestr, curtime = None, rp = None): + """Convert a generic time string to a time in seconds + + rp is used when the time is of the form "4B" or similar. Then the + times of the increments of that particular file are used. + + """ + if curtime is None: curtime = globals()['curtime'] + if timestr == "now": return curtime + + def error(): + raise TimeException("""Bad time string "%s" + +The acceptible time strings are intervals (like "3D64s"), w3-datetime +strings, like "2002-04-26T04:22:01-07:00" (strings like +"2002-04-26T04:22:01" are also acceptable - rdiff-backup will use the +current time zone), or ordinary dates like 2/4/1997 or 2001-04-23 +(various combinations are acceptable, but the month always precedes +the day).""" % timestr) + + # Test for straight integer + if _integer_regexp.search(timestr): return int(timestr) + + # Test for w3-datetime format, possibly missing tzd + t = stringtotime(timestr) or stringtotime(timestr+gettzd()) + if t: return t + + # Test for time given as number of backups, like 3B + if _session_regexp.search(timestr): + return time_from_session(int(timestr[:-1]), rp) + + # Try for long time, like "Mon Jun 5 11:00:23 1990" + t = prettytotime(timestr) + if t is not None: return t + + try: # test for an interval, like "2 days ago" + return curtime - intstringtoseconds(timestr) + except TimeException: pass + + # Now check for dates like 2001/3/23 + match = _genstr_date_regexp1.search(timestr) or \ + _genstr_date_regexp2.search(timestr) + if not match: error() + timestr = "%s-%02d-%02dT00:00:00%s" % (match.group('year'), + int(match.group('month')), int(match.group('day')), gettzd()) + t = stringtotime(timestr) + if t: return t + else: error() + diff --git a/rdiff_backup/Security.py b/rdiff_backup/Security.py index 8dc26bc..c00dab3 100644 --- a/rdiff_backup/Security.py +++ b/rdiff_backup/Security.py @@ -138,7 +138,7 @@ def set_allowed_requests(sec_level): sec_level == "all"): l.extend(["rpath.make_file_dict", "os.listdir", "rpath.ea_get", "rpath.acl_get", "rpath.setdata_local", - "log.Log.log_to_file", "os.getuid", "Time.setcurtime_local", + "log.Log.log_to_file", "os.getuid", "RTime.setcurtime_local", "rpath.gzip_open_local_read", "rpath.open_local_read", "Hardlink.initialize_dictionaries", "user_group.uid2uname", "user_group.gid2gname"]) @@ -190,7 +190,7 @@ def set_allowed_requests(sec_level): if Globals.server: l.extend(["SetConnections.init_connection_remote", "log.Log.setverbosity", "log.Log.setterm_verbosity", - "Time.setprevtime_local", "Globals.postset_regexp_local", + "RTime.setprevtime_local", "Globals.postset_regexp_local", "Globals.set_select", "backup.SourceStruct.set_session_info", "backup.DestinationStruct.set_session_info", "user_group.init_user_mapping", diff --git a/rdiff_backup/Time.py b/rdiff_backup/Time.py deleted file mode 100644 index 377f0b7..0000000 --- a/rdiff_backup/Time.py +++ /dev/null @@ -1,247 +0,0 @@ -# Copyright 2002 Ben Escoto -# -# This file is part of rdiff-backup. -# -# rdiff-backup is free software; you can redistribute it and/or modify -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# rdiff-backup is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with rdiff-backup; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -"""Provide time related exceptions and functions""" - -import time, types, re, sys, calendar -import Globals - - -class TimeException(Exception): pass - -_interval_conv_dict = {"s": 1, "m": 60, "h": 3600, "D": 86400, - "W": 7*86400, "M": 30*86400, "Y": 365*86400} -_integer_regexp = re.compile("^[0-9]+$") -_session_regexp = re.compile("^[0-9]+B$") -_interval_regexp = re.compile("^([0-9]+)([smhDWMY])") -_genstr_date_regexp1 = re.compile("^(?P[0-9]{4})[-/]" - "(?P[0-9]{1,2})[-/](?P[0-9]{1,2})$") -_genstr_date_regexp2 = re.compile("^(?P[0-9]{1,2})[-/]" - "(?P[0-9]{1,2})[-/](?P[0-9]{4})$") -curtime = curtimestr = None - -def setcurtime(curtime = None): - """Sets the current time in curtime and curtimestr on all systems""" - t = curtime or time.time() - for conn in Globals.connections: - conn.Time.setcurtime_local(long(t)) - -def setcurtime_local(timeinseconds): - """Only set the current time locally""" - global curtime, curtimestr - curtime, curtimestr = timeinseconds, timetostring(timeinseconds) - -def setprevtime(timeinseconds): - """Sets the previous inc time in prevtime and prevtimestr""" - assert 0 < timeinseconds < curtime, \ - "Time %s is out of bounds" % (timeinseconds,) - timestr = timetostring(timeinseconds) - for conn in Globals.connections: - conn.Time.setprevtime_local(timeinseconds, timestr) - -def setprevtime_local(timeinseconds, timestr): - """Like setprevtime but only set the local version""" - global prevtime, prevtimestr - prevtime, prevtimestr = timeinseconds, timestr - -def timetostring(timeinseconds): - """Return w3 datetime compliant listing of timeinseconds""" - s = time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(timeinseconds)) - return s + gettzd(timeinseconds) - -def stringtotime(timestring): - """Return time in seconds from w3 timestring - - If there is an error parsing the string, or it doesn't look - like a w3 datetime string, return None. - - """ - try: - date, daytime = timestring[:19].split("T") - year, month, day = map(int, date.split("-")) - hour, minute, second = map(int, daytime.split(":")) - assert 1900 < year < 2100, year - assert 1 <= month <= 12 - assert 1 <= day <= 31 - assert 0 <= hour <= 23 - assert 0 <= minute <= 59 - assert 0 <= second <= 61 # leap seconds - timetuple = (year, month, day, hour, minute, second, -1, -1, 0) - utc_in_secs = calendar.timegm(timetuple) - - return long(utc_in_secs) + tzdtoseconds(timestring[19:]) - except (TypeError, ValueError, AssertionError): return None - -def timetopretty(timeinseconds): - """Return pretty version of time""" - return time.asctime(time.localtime(timeinseconds)) - -def stringtopretty(timestring): - """Return pretty version of time given w3 time string""" - return timetopretty(stringtotime(timestring)) - -def prettytotime(prettystring): - """Converts time like "Mon Jun 5 11:00:23" to epoch sec, or None""" - try: return time.mktime(time.strptime(prettystring)) - except ValueError: return None - -def inttopretty(seconds): - """Convert num of seconds to readable string like "2 hours".""" - partlist = [] - hours, seconds = divmod(seconds, 3600) - if hours > 1: partlist.append("%d hours" % hours) - elif hours == 1: partlist.append("1 hour") - - minutes, seconds = divmod(seconds, 60) - if minutes > 1: partlist.append("%d minutes" % minutes) - elif minutes == 1: partlist.append("1 minute") - - if seconds == 1: partlist.append("1 second") - elif not partlist or seconds > 1: - if isinstance(seconds, int) or isinstance(seconds, long): - partlist.append("%s seconds" % seconds) - else: partlist.append("%.2f seconds" % seconds) - return " ".join(partlist) - -def intstringtoseconds(interval_string): - """Convert a string expressing an interval (e.g. "4D2s") to seconds""" - def error(): - raise TimeException("""Bad interval string "%s" - -Intervals are specified like 2Y (2 years) or 2h30m (2.5 hours). The -allowed special characters are s, m, h, D, W, M, and Y. See the man -page for more information. -""" % interval_string) - if len(interval_string) < 2: error() - - total = 0 - while interval_string: - match = _interval_regexp.match(interval_string) - if not match: error() - num, ext = int(match.group(1)), match.group(2) - if not ext in _interval_conv_dict or num < 0: error() - total += num*_interval_conv_dict[ext] - interval_string = interval_string[match.end(0):] - return total - -def gettzd(timeinseconds = None): - """Return w3's timezone identification string. - - Expresed as [+/-]hh:mm. For instance, PDT is -07:00 during - dayling savings and -08:00 otherwise. Zone is coincides with what - localtime(), etc., use. If no argument given, use the current - time. - - """ - if timeinseconds is None: timeinseconds = time.time() - dst_in_effect = time.daylight and time.localtime(timeinseconds)[8] - if dst_in_effect: offset = -time.altzone/60 - else: offset = -time.timezone/60 - if offset > 0: prefix = "+" - elif offset < 0: prefix = "-" - else: return "Z" # time is already in UTC - - hours, minutes = map(abs, divmod(offset, 60)) - assert 0 <= hours <= 23 - assert 0 <= minutes <= 59 - return "%s%02d:%02d" % (prefix, hours, minutes) - -def tzdtoseconds(tzd): - """Given w3 compliant TZD, return how far ahead UTC is""" - if tzd == "Z": return 0 - assert len(tzd) == 6 # only accept forms like +08:00 for now - assert (tzd[0] == "-" or tzd[0] == "+") and tzd[3] == ":" - return -60 * (60 * int(tzd[:3]) + int(tzd[4:])) - -def cmp(time1, time2): - """Compare time1 and time2 and return -1, 0, or 1""" - if type(time1) is types.StringType: - time1 = stringtotime(time1) - assert time1 is not None - if type(time2) is types.StringType: - time2 = stringtotime(time2) - assert time2 is not None - - if time1 < time2: return -1 - elif time1 == time2: return 0 - else: return 1 - -def time_from_session(session_num, rp = None): - """Return time in seconds of given backup - - The current mirror is session_num 0, the next oldest increment has - number 1, etc. Requires that the Globals.rbdir directory be set. - - """ - session_times = Globals.rbdir.conn.restore.MirrorStruct \ - .get_increment_times() - session_times.sort() - if len(session_times) <= session_num: - return session_times[0] # Use oldest if too few backups - return session_times[-session_num-1] - -def genstrtotime(timestr, curtime = None, rp = None): - """Convert a generic time string to a time in seconds - - rp is used when the time is of the form "4B" or similar. Then the - times of the increments of that particular file are used. - - """ - if curtime is None: curtime = globals()['curtime'] - if timestr == "now": return curtime - - def error(): - raise TimeException("""Bad time string "%s" - -The acceptible time strings are intervals (like "3D64s"), w3-datetime -strings, like "2002-04-26T04:22:01-07:00" (strings like -"2002-04-26T04:22:01" are also acceptable - rdiff-backup will use the -current time zone), or ordinary dates like 2/4/1997 or 2001-04-23 -(various combinations are acceptable, but the month always precedes -the day).""" % timestr) - - # Test for straight integer - if _integer_regexp.search(timestr): return int(timestr) - - # Test for w3-datetime format, possibly missing tzd - t = stringtotime(timestr) or stringtotime(timestr+gettzd()) - if t: return t - - # Test for time given as number of backups, like 3B - if _session_regexp.search(timestr): - return time_from_session(int(timestr[:-1]), rp) - - # Try for long time, like "Mon Jun 5 11:00:23 1990" - t = prettytotime(timestr) - if t is not None: return t - - try: # test for an interval, like "2 days ago" - return curtime - intstringtoseconds(timestr) - except TimeException: pass - - # Now check for dates like 2001/3/23 - match = _genstr_date_regexp1.search(timestr) or \ - _genstr_date_regexp2.search(timestr) - if not match: error() - timestr = "%s-%02d-%02dT00:00:00%s" % (match.group('year'), - int(match.group('month')), int(match.group('day')), gettzd()) - t = stringtotime(timestr) - if t: return t - else: error() - diff --git a/rdiff_backup/backup.py b/rdiff_backup/backup.py index cf9c52d..a9ab611 100644 --- a/rdiff_backup/backup.py +++ b/rdiff_backup/backup.py @@ -22,7 +22,7 @@ from __future__ import generators import errno import Globals, metadata, rorpiter, RTempFile, Hardlink, robust, increment, \ - rpath, static, log, selection, Time, Rdiff, statistics, iterfile, \ + rpath, static, log, selection, RTime, Rdiff, statistics, iterfile, \ hash, longname def Mirror(src_rpath, dest_rpath): @@ -137,7 +137,7 @@ class DestinationStruct: metadata.SetManager() if use_metadata: - rorp_iter = metadata.ManagerObj.GetAtTime(Time.prevtime) + rorp_iter = metadata.ManagerObj.GetAtTime(RTime.prevtime) if rorp_iter: return rorp_iter return get_iter_from_fs() diff --git a/rdiff_backup/connection.py b/rdiff_backup/connection.py index 873d475..299a5ee 100644 --- a/rdiff_backup/connection.py +++ b/rdiff_backup/connection.py @@ -534,7 +534,7 @@ class VirtualFile: # everything has to be available here for remote connection's use, but # put at bottom to reduce circularities. -import Globals, Time, Rdiff, Hardlink, FilenameMapping, C, Security, \ +import Globals, RTime, Rdiff, Hardlink, FilenameMapping, C, Security, \ Main, rorpiter, selection, increment, statistics, manage, lazy, \ iterfile, rpath, robust, restore, manage, backup, connection, \ RTempFile, SetConnections, librsync, log, regress, fs_abilities, \ diff --git a/rdiff_backup/increment.py b/rdiff_backup/increment.py index afab0d2..1c41410 100644 --- a/rdiff_backup/increment.py +++ b/rdiff_backup/increment.py @@ -19,7 +19,7 @@ """Provides functions and *ITR classes, for writing increment files""" -import Globals, Time, rpath, Rdiff, log, statistics, robust +import Globals, RTime, rpath, Rdiff, log, statistics, robust def Increment(new, mirror, incpref): @@ -112,8 +112,8 @@ def get_inc(rp, typestr, time = None): whole filename is in the base (which is not quoted). """ - if time is None: time = Time.prevtime - addtostr = lambda s: "%s.%s.%s" % (s, Time.timetostring(time), typestr) + if time is None: time = RTime.prevtime + addtostr = lambda s: "%s.%s.%s" % (s, RTime.timetostring(time), typestr) if rp.index: incrp = rp.__class__(rp.conn, rp.base, rp.index[:-1] + (addtostr(rp.index[-1]),)) diff --git a/rdiff_backup/manage.py b/rdiff_backup/manage.py index 2c9c7de..05c8ff7 100644 --- a/rdiff_backup/manage.py +++ b/rdiff_backup/manage.py @@ -21,7 +21,7 @@ from __future__ import generators from log import Log -import Globals, Time, static, statistics, restore, selection, FilenameMapping +import Globals, RTime, static, statistics, restore, selection, FilenameMapping class ManageException(Exception): pass @@ -72,12 +72,12 @@ def describe_incs_human(incs, mirror_time, mirrorrp): for time, inc in incpairs: result.append(" %s %s" % (FilenameMapping.unquote(inc.dirsplit()[1]), - Time.timetopretty(time))) + RTime.timetopretty(time))) else: for time, inc in incpairs: result.append(" %s %s" % - (inc.dirsplit()[1], Time.timetopretty(time))) - result.append("Current mirror: %s" % Time.timetopretty(mirror_time)) + (inc.dirsplit()[1], RTime.timetopretty(time))) + result.append("Current mirror: %s" % RTime.timetopretty(mirror_time)) return "\n".join(result) def delete_earlier_than(baserp, time): @@ -127,7 +127,7 @@ class IncObj: def pretty_time(self): """Return a formatted version of inc's time""" - return Time.timetopretty(self.time) + return RTime.timetopretty(self.time) def full_description(self): """Return string describing increment""" @@ -193,7 +193,7 @@ def ListIncrementSizes(mirror_root, index): """Convert triple to display string""" time, size, cum_size = triple return "%24s %13s %15s" % \ - (Time.timetopretty(time), + (RTime.timetopretty(time), stat_obj.get_byte_summary_string(size), stat_obj.get_byte_summary_string(cum_size)) diff --git a/rdiff_backup/metadata.py b/rdiff_backup/metadata.py index 1bbc5c6..6e0d433 100644 --- a/rdiff_backup/metadata.py +++ b/rdiff_backup/metadata.py @@ -56,7 +56,7 @@ field names and values. from __future__ import generators import re, gzip, os, binascii -import log, Globals, rpath, Time, robust, increment, static, rorpiter +import log, Globals, rpath, RTime, robust, increment, static, rorpiter class ParsingError(Exception): """This is raised when bad or unparsable data is received""" @@ -543,8 +543,8 @@ class Manager: def _writer_helper(self, prefix, flatfileclass, typestr, time): """Used in the get_xx_writer functions, returns a writer class""" - if time is None: timestr = Time.curtimestr - else: timestr = Time.timetostring(time) + if time is None: timestr = RTime.curtimestr + else: timestr = RTime.timetostring(time) filename = '%s.%s.%s' % (prefix, timestr, typestr) rp = Globals.rbdir.append(filename) assert not rp.lstat(), "File %s already exists!" % (rp.path,) diff --git a/rdiff_backup/regress.py b/rdiff_backup/regress.py index 51bfafc..335c5ac 100644 --- a/rdiff_backup/regress.py +++ b/rdiff_backup/regress.py @@ -36,7 +36,7 @@ be recovered. from __future__ import generators import signal, errno, re, os import Globals, restore, log, rorpiter, RTempFile, metadata, rpath, C, \ - Time, backup, robust, longname + RTime, backup, robust, longname # regress_time should be set to the time we want to regress back to # (usually the time of the last successful backup) @@ -89,7 +89,7 @@ def set_regress_time(): mirror_rp_to_delete = curmir_incs[0] regress_time = curmir_incs[1].getinctime() unsuccessful_backup_time = mirror_rp_to_delete.getinctime() - log.Log("Regressing to " + Time.timetopretty(regress_time), 4) + log.Log("Regressing to " + RTime.timetopretty(regress_time), 4) return manager, mirror_rp_to_delete def set_restore_times(): @@ -149,7 +149,7 @@ def recreate_meta(meta_manager): writer.close() finalrp = Globals.rbdir.append("mirror_metadata.%s.snapshot.gz" % - Time.timetostring(regress_time)) + RTime.timetostring(regress_time)) assert not finalrp.lstat(), finalrp rpath.rename(temprp[0], finalrp) if Globals.fsync_directories: Globals.rbdir.fsync() @@ -182,7 +182,7 @@ def yield_metadata(): metadata_iter = metadata.ManagerObj.GetAtTime(regress_time) if metadata_iter: return metadata_iter log.Log.FatalError("No metadata for time %s (%s) found,\ncannot regress" - % (Time.timetopretty(regress_time), regress_time)) + % (RTime.timetopretty(regress_time), regress_time)) def iterate_meta_rfs(mirror_rp, inc_rp): """Yield RegressFile objects with extra metadata information added diff --git a/rdiff_backup/restore.py b/rdiff_backup/restore.py index 1e2c4be..4b056b0 100644 --- a/rdiff_backup/restore.py +++ b/rdiff_backup/restore.py @@ -738,6 +738,6 @@ class PermissionChanger: for index, rp, perms in self.open_index_list: rp.chmod(perms) -import Globals, Time, Rdiff, Hardlink, selection, rpath, \ +import Globals, RTime, Rdiff, Hardlink, selection, rpath, \ log, robust, metadata, statistics, RTempFile, hash, longname diff --git a/rdiff_backup/rpath.py b/rdiff_backup/rpath.py index 0dadd43..0f990a5 100644 --- a/rdiff_backup/rpath.py +++ b/rdiff_backup/rpath.py @@ -36,7 +36,7 @@ are dealing with are local or remote. """ import os, stat, re, sys, shutil, gzip, socket, time, errno -import Globals, Time, static, log, user_group, C +import Globals, RTime, static, log, user_group, C class SkipFileException(Exception): @@ -364,7 +364,7 @@ def get_incfile_info(basename): compressed = None if len(dotsplit) < 3: return None timestring, ext = dotsplit[-2:] - if Time.stringtotime(timestring) is None: return None + if RTime.stringtotime(timestring) is None: return None if not (ext == "snapshot" or ext == "dir" or ext == "missing" or ext == "diff" or ext == "data"): return None @@ -1184,7 +1184,7 @@ class RPath(RORPath): def getinctime(self): """Return time in seconds of an increment file""" - return Time.stringtotime(self.inc_timestr) + return RTime.stringtotime(self.inc_timestr) def getincbase(self): """Return the base filename of an increment file in rp form""" diff --git a/rdiff_backup/statistics.py b/rdiff_backup/statistics.py index b16fb12..f709ec8 100644 --- a/rdiff_backup/statistics.py +++ b/rdiff_backup/statistics.py @@ -20,7 +20,7 @@ """Generate and process aggregated backup information""" import re, os, time -import Globals, Time, increment, log, static, metadata +import Globals, RTime, increment, log, static, metadata class StatsException(Exception): pass @@ -136,16 +136,16 @@ class StatsObj: timelist = [] if self.StartTime is not None: timelist.append("StartTime %.2f (%s)\n" % - (self.StartTime, Time.timetopretty(self.StartTime))) + (self.StartTime, RTime.timetopretty(self.StartTime))) if self.EndTime is not None: timelist.append("EndTime %.2f (%s)\n" % - (self.EndTime, Time.timetopretty(self.EndTime))) + (self.EndTime, RTime.timetopretty(self.EndTime))) if self.ElapsedTime or (self.StartTime is not None and self.EndTime is not None): if self.ElapsedTime is None: self.ElapsedTime = self.EndTime - self.StartTime timelist.append("ElapsedTime %.2f (%s)\n" % - (self.ElapsedTime, Time.inttopretty(self.ElapsedTime))) + (self.ElapsedTime, RTime.inttopretty(self.ElapsedTime))) return "".join(timelist) def get_filestats_string(self): @@ -270,7 +270,7 @@ class StatFileObj(StatsObj): """StatFileObj initializer - zero out file attributes""" StatsObj.__init__(self) for attr in self.stat_file_attrs: self.set_stat(attr, 0) - if start_time is None: start_time = Time.curtime + if start_time is None: start_time = RTime.curtime self.StartTime = start_time self.Errors = 0 @@ -338,7 +338,7 @@ def write_active_statfileobj(): global _active_statfileobj assert _active_statfileobj rp_base = Globals.rbdir.append("session_statistics") - session_stats_rp = increment.get_inc(rp_base, 'data', Time.curtime) + session_stats_rp = increment.get_inc(rp_base, 'data', RTime.curtime) _active_statfileobj.finish() _active_statfileobj.write_stats_to_rp(session_stats_rp) _active_statfileobj = None @@ -362,7 +362,7 @@ class FileStats: assert not (cls._fileobj or cls._rp), (cls._fileobj, cls._rp) rpbase = Globals.rbdir.append("file_statistics") suffix = Globals.compression and 'data.gz' or 'data' - cls._rp = increment.get_inc(rpbase, suffix, Time.curtime) + cls._rp = increment.get_inc(rpbase, suffix, RTime.curtime) assert not cls._rp.lstat() cls._fileobj = cls._rp.open("wb", compress = Globals.compression) -- 1.5.6.3