Annotation of embedaddon/rsync/hashlink.c, revision 1.1
1.1 ! misho 1: /*
! 2: Copyright (C) Cronosys, LLC 2004
! 3:
! 4: This program is free software; you can redistribute it and/or modify
! 5: it under the terms of the GNU General Public License as published by
! 6: the Free Software Foundation; either version 2 of the License, or
! 7: (at your option) any later version.
! 8:
! 9: This program is distributed in the hope that it will be useful,
! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 12: GNU General Public License for more details.
! 13:
! 14: You should have received a copy of the GNU General Public License
! 15: along with this program; if not, write to the Free Software
! 16: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
! 17: */
! 18:
! 19: /* This file contains code used by the --link-by-hash option. */
! 20:
! 21: #include "rsync.h"
! 22: #include "inums.h"
! 23:
! 24: extern int protocol_version;
! 25: extern char *link_by_hash_dir;
! 26: extern char sender_file_sum[MAX_DIGEST_LEN];
! 27:
! 28: char link_by_hash_extra_sum[MAX_DIGEST_LEN]; /* Only used when md4 sums are in the transfer */
! 29:
! 30: #ifdef HAVE_LINK
! 31:
! 32: /* This function is always called after a file is received, so the
! 33: * sender_file_sum buffer has whatever the last checksum was for the
! 34: * transferred file. */
! 35: void link_by_hash(const char *fname, const char *fnametmp, struct file_struct *file)
! 36: {
! 37: STRUCT_STAT st;
! 38: char *hashname, *last_slash, *num_str;
! 39: const char *hex;
! 40: int num = 0;
! 41:
! 42: /* We don't bother to hard-link 0-length files. */
! 43: if (F_LENGTH(file) == 0)
! 44: return;
! 45:
! 46: hex = sum_as_hex(5, protocol_version >= 30 ? sender_file_sum : link_by_hash_extra_sum, 0);
! 47: if (asprintf(&hashname, "%s/%.3s/%.3s/%.3s/%s.%s.000000",
! 48: link_by_hash_dir, hex, hex+3, hex+6, hex+9, big_num(F_LENGTH(file))) < 0)
! 49: {
! 50: out_of_memory("make_hash_name");
! 51: }
! 52:
! 53: last_slash = strrchr(hashname, '/');
! 54: num_str = strrchr(last_slash, '.') + 1;
! 55:
! 56: while (1) {
! 57: if (num >= 999999) { /* Surely we'll never reach this... */
! 58: if (DEBUG_GTE(HASHLINK, 1))
! 59: rprintf(FINFO, "link-by-hash: giving up after \"%s\".\n", hashname);
! 60: goto cleanup;
! 61: }
! 62: if (num > 0 && DEBUG_GTE(HASHLINK, 1))
! 63: rprintf(FINFO, "link-by-hash: max link count exceeded, starting new file \"%s\".\n", hashname);
! 64:
! 65: snprintf(num_str, 7, "%d", num++);
! 66: if (do_stat(hashname, &st) < 0)
! 67: break;
! 68:
! 69: if (do_link(hashname, fnametmp) < 0) {
! 70: if (errno == EMLINK)
! 71: continue;
! 72: rsyserr(FERROR, errno, "link \"%s\" -> \"%s\"", hashname, full_fname(fname));
! 73: } else {
! 74: if (DEBUG_GTE(HASHLINK, 2))
! 75: rprintf(FINFO, "link-by-hash (existing): \"%s\" -> %s\n", hashname, full_fname(fname));
! 76: robust_rename(fnametmp, fname, NULL, 0644);
! 77: }
! 78:
! 79: goto cleanup;
! 80: }
! 81:
! 82: if (DEBUG_GTE(HASHLINK, 2))
! 83: rprintf(FINFO, "link-by-hash (new): %s -> \"%s\"\n", full_fname(fname), hashname);
! 84:
! 85: if (do_link(fname, hashname) < 0
! 86: && (errno != ENOENT || make_path(hashname, MKP_DROP_NAME) < 0 || do_link(fname, hashname) < 0))
! 87: rsyserr(FERROR, errno, "link \"%s\" -> \"%s\"", full_fname(fname), hashname);
! 88:
! 89: cleanup:
! 90: free(hashname);
! 91: }
! 92: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>