summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/TempFile.py
blob: 824d480cfad62725a653ed123d5ca93b8a00560a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 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

"""Manage temp files

Earlier this had routines for keeping track of existing tempfiles.
Now we just use normal rpaths instead of the TempFile class.

"""

import os
import Globals, rpath

# To make collisions less likely, this gets put in the file name
# and incremented whenever a new file is requested.
_tfindex = 0

def new(rp_base):
	"""Return new tempfile that isn't in use in same dir as rp_base"""
	return new_in_dir(rp_base.get_parent_rp())

def new_in_dir(dir_rp):
	"""Return new temp rpath in directory dir_rp"""
	global _tfindex
	assert dir_rp.conn is Globals.local_connection
	while 1:
		if _tfindex > 100000000:
			Log("Warning: Resetting tempfile index", 2)
			_tfindex = 0
		tf = dir_rp.append('rdiff-backup.tmp.%d' % _tfindex)
		_tfindex = _tfindex+1
		if not tf.lstat(): return tf




class TempFile(rpath.RPath):
	"""Like an RPath, but keep track of which ones are still here"""
	def rename(self, rp_dest):
		"""Rename temp file to permanent location, possibly overwriting"""
		if not self.lstat(): # "Moving" empty file, so just delete
			if rp_dest.lstat(): rp_dest.delete()
			remove_listing(self)
			return

		if self.isdir() and not rp_dest.isdir():
			# Cannot move a directory directly over another file
			rp_dest.delete()
		rpath.rename(self, rp_dest)

		# Sometimes this just seems to fail silently, as in one
		# hardlinked twin is moved over the other.  So check to make
		# sure below.
		self.setdata()
		if self.lstat():
			rp_dest.delete()
			rpath.rename(self, rp_dest)
			self.setdata()
			if self.lstat(): raise OSError("Cannot rename tmp file correctly")
		remove_listing(self)

	def delete(self):
		rpath.RPath.delete(self)
		remove_listing(self)