Annotation of embedaddon/rsync/hashlink.c, revision 1.1.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>