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>