23 |
import errno |
import errno |
24 |
import Globals, metadata, rorpiter, TempFile, Hardlink, robust, increment, \ |
import Globals, metadata, rorpiter, TempFile, Hardlink, robust, increment, \ |
25 |
rpath, static, log, selection, Time, Rdiff, statistics, iterfile, \ |
rpath, static, log, selection, Time, Rdiff, statistics, iterfile, \ |
26 |
eas_acls |
eas_acls, hash |
27 |
|
|
28 |
def Mirror(src_rpath, dest_rpath): |
def Mirror(src_rpath, dest_rpath): |
29 |
"""Turn dest_rpath into a copy of src_rpath""" |
"""Turn dest_rpath into a copy of src_rpath""" |
85 |
"""Attach file of snapshot to diff_rorp, w/ error checking""" |
"""Attach file of snapshot to diff_rorp, w/ error checking""" |
86 |
fileobj = robust.check_common_error( |
fileobj = robust.check_common_error( |
87 |
error_handler, rpath.RPath.open, (src_rp, "rb")) |
error_handler, rpath.RPath.open, (src_rp, "rb")) |
88 |
if fileobj: diff_rorp.setfile(fileobj) |
if fileobj: diff_rorp.setfile(hash.FileWrapper(fileobj)) |
89 |
else: diff_rorp.zero() |
else: diff_rorp.zero() |
90 |
diff_rorp.set_attached_filetype('snapshot') |
diff_rorp.set_attached_filetype('snapshot') |
91 |
|
|
92 |
def attach_diff(diff_rorp, src_rp, dest_sig): |
def attach_diff(diff_rorp, src_rp, dest_sig): |
93 |
"""Attach file of diff to diff_rorp, w/ error checking""" |
"""Attach file of diff to diff_rorp, w/ error checking""" |
94 |
fileobj = robust.check_common_error( |
fileobj = robust.check_common_error( |
95 |
error_handler, Rdiff.get_delta_sigrp, (dest_sig, src_rp)) |
error_handler, Rdiff.get_delta_sigrp_hash, (dest_sig, src_rp)) |
96 |
if fileobj: |
if fileobj: |
97 |
diff_rorp.setfile(fileobj) |
diff_rorp.setfile(fileobj) |
98 |
diff_rorp.set_attached_filetype('diff') |
diff_rorp.set_attached_filetype('diff') |
255 |
we enter them to computer signatures, and then reset after we |
we enter them to computer signatures, and then reset after we |
256 |
are done patching everything inside them. |
are done patching everything inside them. |
257 |
|
|
258 |
|
4. We need some place to put hashes (like SHA1) after computing |
259 |
|
them and before writing them to the metadata. |
260 |
|
|
261 |
The class caches older source_rorps and dest_rps so the patch |
The class caches older source_rorps and dest_rps so the patch |
262 |
function can retrieve them if necessary. The patch function can |
function can retrieve them if necessary. The patch function can |
263 |
also update the processed correctly flag. When an item falls out |
also update the processed correctly flag. When an item falls out |
297 |
# after we're finished with them |
# after we're finished with them |
298 |
self.dir_perms_list = [] |
self.dir_perms_list = [] |
299 |
|
|
300 |
|
# A dictionary of {index: source_rorp}. We use this to |
301 |
|
# hold the digest of a hard linked file so it only needs to be |
302 |
|
# computed once. |
303 |
|
self.inode_digest_dict = {} |
304 |
|
|
305 |
def __iter__(self): return self |
def __iter__(self): return self |
306 |
|
|
307 |
def next(self): |
def next(self): |
324 |
|
|
325 |
""" |
""" |
326 |
if Globals.preserve_hardlinks and source_rorp: |
if Globals.preserve_hardlinks and source_rorp: |
327 |
Hardlink.add_rorp(source_rorp, dest_rorp) |
if Hardlink.add_rorp(source_rorp, dest_rorp): |
328 |
|
self.inode_digest_dict[source_rorp.index] = source_rorp |
329 |
if (dest_rorp and dest_rorp.isdir() and Globals.process_uid != 0 |
if (dest_rorp and dest_rorp.isdir() and Globals.process_uid != 0 |
330 |
and dest_rorp.getperms() % 01000 < 0700): |
and dest_rorp.getperms() % 01000 < 0700): |
331 |
self.unreadable_dir_init(source_rorp, dest_rorp) |
self.unreadable_dir_init(source_rorp, dest_rorp) |
368 |
|
|
369 |
""" |
""" |
370 |
if Globals.preserve_hardlinks and source_rorp: |
if Globals.preserve_hardlinks and source_rorp: |
371 |
Hardlink.del_rorp(source_rorp) |
if Hardlink.del_rorp(source_rorp): |
372 |
|
del self.inode_digest_dict[source_rorp.index] |
373 |
|
|
374 |
if not changed or success: |
if not changed or success: |
375 |
if source_rorp: self.statfileobj.add_source_file(source_rorp) |
if source_rorp: self.statfileobj.add_source_file(source_rorp) |
434 |
"""Retrieve mirror_rorp with given index from cache""" |
"""Retrieve mirror_rorp with given index from cache""" |
435 |
return self.cache_dict[index][1] |
return self.cache_dict[index][1] |
436 |
|
|
437 |
|
def update_hash(self, index, sha1sum): |
438 |
|
"""Update the source rorp's SHA1 hash""" |
439 |
|
self.get_source_rorp(index).set_sha1(sha1sum) |
440 |
|
|
441 |
|
def update_hardlink_hash(self, diff_rorp): |
442 |
|
"""Tag associated source_rorp with same hash diff_rorp points to""" |
443 |
|
orig_rorp = self.inode_digest_dict[diff_rorp.get_link_flag()] |
444 |
|
if orig_rorp.has_sha1(): |
445 |
|
new_source_rorp = self.get_source_rorp(diff_rorp.index) |
446 |
|
new_source_rorp.set_sha1(orig_rorp.get_sha1()) |
447 |
|
|
448 |
def close(self): |
def close(self): |
449 |
"""Process the remaining elements in the cache""" |
"""Process the remaining elements in the cache""" |
450 |
while self.cache_indicies: self.shorten_cache() |
while self.cache_indicies: self.shorten_cache() |
507 |
if tf.lstat(): tf.delete() |
if tf.lstat(): tf.delete() |
508 |
|
|
509 |
def patch_to_temp(self, basis_rp, diff_rorp, new): |
def patch_to_temp(self, basis_rp, diff_rorp, new): |
510 |
"""Patch basis_rp, writing output in new, which doesn't exist yet""" |
"""Patch basis_rp, writing output in new, which doesn't exist yet |
511 |
|
|
512 |
|
Returns true if able to write new as desired, false if |
513 |
|
UpdateError or similar gets in the way. |
514 |
|
|
515 |
|
""" |
516 |
if diff_rorp.isflaglinked(): |
if diff_rorp.isflaglinked(): |
517 |
Hardlink.link_rp(diff_rorp, new, self.basis_root_rp) |
self.patch_hardlink_to_temp(diff_rorp, new) |
518 |
elif diff_rorp.get_attached_filetype() == 'snapshot': |
elif diff_rorp.get_attached_filetype() == 'snapshot': |
519 |
if diff_rorp.isspecial(): |
if not self.patch_snapshot_to_temp(diff_rorp, new): |
520 |
self.write_special(diff_rorp, new) |
return 0 |
521 |
rpath.copy_attribs(diff_rorp, new) |
elif not self.patch_diff_to_temp(basis_rp, diff_rorp, new): |
522 |
return 1 |
return 0 |
|
elif robust.check_common_error(self.error_handler, rpath.copy, |
|
|
(diff_rorp, new)) == 0: return 0 |
|
|
else: |
|
|
assert diff_rorp.get_attached_filetype() == 'diff' |
|
|
if robust.check_common_error(self.error_handler, |
|
|
Rdiff.patch_local, (basis_rp, diff_rorp, new)) == 0: return 0 |
|
523 |
if new.lstat() and not diff_rorp.isflaglinked(): |
if new.lstat() and not diff_rorp.isflaglinked(): |
524 |
rpath.copy_attribs(diff_rorp, new) |
rpath.copy_attribs(diff_rorp, new) |
525 |
return self.matches_cached_rorp(diff_rorp, new) |
return self.matches_cached_rorp(diff_rorp, new) |
526 |
|
|
527 |
|
def patch_hardlink_to_temp(self, diff_rorp, new): |
528 |
|
"""Hardlink diff_rorp to temp, update hash if necessary""" |
529 |
|
Hardlink.link_rp(diff_rorp, new, self.basis_root_rp) |
530 |
|
self.CCPP.update_hardlink_hash(diff_rorp) |
531 |
|
|
532 |
|
def patch_snapshot_to_temp(self, diff_rorp, new): |
533 |
|
"""Write diff_rorp to new, return true if successful""" |
534 |
|
if diff_rorp.isspecial(): |
535 |
|
self.write_special(diff_rorp, new) |
536 |
|
rpath.copy_attribs(diff_rorp, new) |
537 |
|
return 1 |
538 |
|
|
539 |
|
report = robust.check_common_error(self.error_handler, rpath.copy, |
540 |
|
(diff_rorp, new)) |
541 |
|
if isinstance(report, hash.Report): |
542 |
|
self.CCPP.update_hash(diff_rorp.index, report.sha1_digest) |
543 |
|
return 1 |
544 |
|
return report != 0 # if == 0, error_handler caught something |
545 |
|
|
546 |
|
def patch_diff_to_temp(self, basis_rp, diff_rorp, new): |
547 |
|
"""Apply diff_rorp to basis_rp, write output in new""" |
548 |
|
assert diff_rorp.get_attached_filetype() == 'diff' |
549 |
|
report = robust.check_common_error(self.error_handler, |
550 |
|
Rdiff.patch_local, (basis_rp, diff_rorp, new)) |
551 |
|
if isinstance(report, hash.Report): |
552 |
|
self.CCPP.update_hash(diff_rorp.index, report.sha1_digest) |
553 |
|
return 1 |
554 |
|
return report != 0 # if report == 0, error |
555 |
|
|
556 |
def matches_cached_rorp(self, diff_rorp, new_rp): |
def matches_cached_rorp(self, diff_rorp, new_rp): |
557 |
"""Return true if new_rp matches cached src rorp |
"""Return true if new_rp matches cached src rorp |
558 |
|
|