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>