File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / hashlink.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    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>