1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Manage temporary files"""
23
24 import os, sys
25
26 from duplicity import log
27 from duplicity import util
28 from duplicity import path
29 from duplicity import file_naming
30 from duplicity import tempdir
31 from duplicity import globals
32 from duplicity import gpg
33
34
41
42
44 """
45 Path object used as a temporary file
46 """
53
61
62
64 """
65 Return a file object open for writing, will write to filename
66
67 Data will be processed and written to a temporary file. When the
68 return fileobject is closed, rename to final position. filename
69 must be a recognizable duplicity data file.
70 """
71 if not globals.restart:
72 td = tempdir.TemporaryDirectory(dirpath.name)
73 tdpname = td.mktemp()
74 tdp = TempDupPath(tdpname, parseresults = file_naming.parse(partname))
75 fh = FileobjHooked(tdp.filtered_open("wb"), tdp = tdp, dirpath = dirpath,
76 partname = partname, permname = permname, remname = remname)
77 else:
78 dp = path.DupPath(dirpath.name, index = (partname,))
79 fh = FileobjHooked(dp.filtered_open("ab"), tdp = None, dirpath = dirpath,
80 partname = partname, permname = permname, remname = remname)
81
82 def rename_and_forget():
83 tdp.rename(dirpath.append(partname))
84 td.forget(tdpname)
85
86 if not globals.restart:
87 fh.addhook(rename_and_forget)
88
89 return fh
90
91
93 """
94 Return a new TempDupPath, using settings from parseresults
95 """
96 filename = tempdir.default().mktemp()
97 return TempDupPath(filename, parseresults = parseresults)
98
99
101 """
102 Like TempPath, but build around DupPath
103 """
110
118
127
128
130 """
131 Simulate a file, but add hook on close
132 """
133 - def __init__(self, fileobj, tdp = None, dirpath = None,
134 partname = None, permname = None, remname = None):
135 """
136 Initializer. fileobj is the file object to simulate
137 """
138 self.fileobj = fileobj
139 self.closed = False
140 self.hooklist = []
141 self.tdp = tdp
142 self.dirpath = dirpath
143 self.partname = partname
144 self.permname = permname
145 self.remname = remname
146
148 """
149 Write fileobj, return result of write()
150 """
151 return self.fileobj.write(buf)
152
154 """
155 Flush fileobj and force sync.
156 """
157 self.fileobj.flush()
158 os.fsync(self.fileobj.fileno())
159
161 """
162 We have achieved the first checkpoint, make file visible and permanent.
163 """
164 assert not globals.restart
165 self.tdp.rename(self.dirpath.append(self.partname))
166 self.fileobj.flush()
167 del self.hooklist[0]
168
185
187 """
188 We are finished, rename to final, gzip if needed.
189 """
190 src = self.dirpath.append(self.partname)
191 tgt = self.dirpath.append(self.permname)
192 src_iter = SrcIter(src)
193 pr = file_naming.parse(self.permname)
194 if pr.compressed:
195 gpg.GzipWriteFile(src_iter, tgt.name, size = sys.maxint)
196 os.unlink(src.name)
197 else:
198 os.rename(src.name, tgt.name)
199
200 - def read(self, length = -1):
201 """
202 Read fileobj, return result of read()
203 """
204 return self.fileobj.read(length)
205
207 """
208 Returns current location of fileobj
209 """
210 return self.fileobj.tell()
211
212 - def seek(self, offset):
213 """
214 Seeks to a location of fileobj
215 """
216 return self.fileobj.seek(offset)
217
219 """
220 Close fileobj, running hooks right afterwards
221 """
222 assert not self.fileobj.close()
223 for hook in self.hooklist:
224 hook()
225
227 """
228 Add hook (function taking no arguments) to run upon closing
229 """
230 self.hooklist.append(hook)
231
232
234 """
235 Return the name of the file
236 """
237 return self.fileobj.name
238
239 name = property(get_name)
240
241
243 """
244 Data block to return from SrcIter
245 """
248
250 """
251 Iterate over source and return Block of data.
252 """
254 self.src = src
255 self.fp = src.open("rb")
256 - def next(self, size):
257 try:
258 res = Block(self.fp.read(size))
259 except Exception:
260 log.FatalError(_("Failed to read %s: %s") %
261 (self.src.name, sys.exc_info()),
262 log.ErrorCode.generic)
263 if not res.data:
264 self.fp.close()
265 raise StopIteration
266 return res
269