blob: fd2ac596597d31a968325009129d01075cc6b045 [file] [log] [blame]
Martin Poolef1aa912000-11-10 03:17:08 +00001/* -*- c-file-style: "linux" -*-
Martin Pool91262d52002-01-23 07:54:13 +00002
3 rsync -- fast file replication program
Wayne Davison2cda2562003-03-21 18:53:00 +00004
5 Copyright (C) 1996-2000 by Andrew Tridgell
Andrew Tridgell2f03f951998-07-25 02:25:22 +00006 Copyright (C) Paul Mackerras 1996
Martin Pool91262d52002-01-23 07:54:13 +00007 Copyright (C) 2002 by Martin Pool <mbp@samba.org>
Wayne Davison2cda2562003-03-21 18:53:00 +00008
Andrew Tridgell2f03f951998-07-25 02:25:22 +00009 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
Wayne Davison2cda2562003-03-21 18:53:00 +000013
Andrew Tridgell2f03f951998-07-25 02:25:22 +000014 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
Wayne Davison2cda2562003-03-21 18:53:00 +000018
Andrew Tridgell2f03f951998-07-25 02:25:22 +000019 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "rsync.h"
25
26extern int verbose;
27extern int dry_run;
28extern int relative_paths;
29extern int preserve_links;
30extern int am_root;
31extern int preserve_devices;
32extern int preserve_hard_links;
33extern int update_only;
Martin Pool3d6fead2002-01-25 10:42:23 +000034extern int opt_ignore_existing;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000035extern int csum_length;
36extern int ignore_times;
Andrew Tridgellf83f0541999-02-18 03:48:24 +000037extern int size_only;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000038extern int io_timeout;
Wayne Davisond04e9c52003-09-09 15:58:48 +000039extern int protocol_version;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000040extern int always_checksum;
David Dykstra60c8d7b2000-08-04 21:11:46 +000041extern char *compare_dest;
David Dykstra59c95e42002-08-29 14:44:55 +000042extern int link_dest;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000043
44
45/* choose whether to skip a particular file */
46static int skip_file(char *fname,
47 struct file_struct *file, STRUCT_STAT *st)
48{
49 if (st->st_size != file->length) {
50 return 0;
51 }
David Dykstra59c95e42002-08-29 14:44:55 +000052 if (link_dest) {
J.W. Schultzbb240282003-03-26 20:26:06 +000053 extern int preserve_perms;
54 extern int preserve_uid;
55 extern int preserve_gid;
56
Wayne Davisone7bc9b62004-01-02 08:05:20 +000057 if (preserve_perms
58 && (st->st_mode & ~_S_IFMT) != (file->mode & ~_S_IFMT))
David Dykstra59c95e42002-08-29 14:44:55 +000059 return 0;
J.W. Schultzbb240282003-03-26 20:26:06 +000060
61 if (preserve_uid && st->st_uid != file->uid)
David Dykstra59c95e42002-08-29 14:44:55 +000062 return 0;
J.W. Schultzbb240282003-03-26 20:26:06 +000063
64 if (preserve_gid && st->st_gid != file->gid)
65 return 0;
David Dykstra59c95e42002-08-29 14:44:55 +000066 }
67
Wayne Davison2cda2562003-03-21 18:53:00 +000068 /* if always checksum is set then we use the checksum instead
Andrew Tridgell2f03f951998-07-25 02:25:22 +000069 of the file time to determine whether to sync */
70 if (always_checksum && S_ISREG(st->st_mode)) {
71 char sum[MD4_SUM_LENGTH];
David Dykstra60c8d7b2000-08-04 21:11:46 +000072 char fnamecmpdest[MAXPATHLEN];
73
74 if (compare_dest != NULL) {
75 if (access(fname, 0) != 0) {
Andrew Tridgell8950ac02001-05-07 06:59:37 +000076 snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
Wayne Davison2cda2562003-03-21 18:53:00 +000077 compare_dest,fname);
David Dykstra60c8d7b2000-08-04 21:11:46 +000078 fname = fnamecmpdest;
79 }
80 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +000081 file_checksum(fname,sum,st->st_size);
Wayne Davisond04e9c52003-09-09 15:58:48 +000082 if (protocol_version < 21) {
Andrew Tridgellf855a7d1999-06-26 01:06:38 +000083 return (memcmp(sum,file->sum,2) == 0);
84 } else {
85 return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
86 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +000087 }
88
Andrew Tridgellf83f0541999-02-18 03:48:24 +000089 if (size_only) {
90 return 1;
91 }
92
Andrew Tridgell2f03f951998-07-25 02:25:22 +000093 if (ignore_times) {
94 return 0;
95 }
96
Andrew Tridgell5b56cc12000-09-06 02:12:13 +000097 return (cmp_modtime(st->st_mtime,file->modtime) == 0);
Andrew Tridgell2f03f951998-07-25 02:25:22 +000098}
99
100
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000101/*
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000102 * NULL sum_struct means we have no checksums
J.W. Schultz195bd902003-04-10 02:04:58 +0000103 */
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000104
105void write_sum_head(int f, struct sum_struct *sum)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000106{
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000107 static struct sum_struct null_sum;
108
109 if (sum == (struct sum_struct *)NULL)
110 sum = &null_sum;
111
112 write_int(f, sum->count);
113 write_int(f, sum->blength);
Wayne Davisond04e9c52003-09-09 15:58:48 +0000114 if (protocol_version >= 27)
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000115 write_int(f, sum->s2length);
116 write_int(f, sum->remainder);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000117}
118
J.W. Schultz195bd902003-04-10 02:04:58 +0000119/*
120 * set (initialize) the size entries in the per-file sum_struct
121 * calulating dynamic block ans checksum sizes.
122 *
123 * This is only called from generate_and_send_sums() but is a seperate
124 * function to encapsulate the logic.
125 *
126 * The block size is a rounded square root of file length.
127 *
128 * The checksum size is determined according to:
129 * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
130 * provided by Donovan Baarda which gives a probability of rsync
131 * algorithm corrupting data and falling back using the whole md4
132 * checksums.
133 *
134 * This might be made one of several selectable heuristics.
135 */
Martin Poolbceec822002-03-19 03:39:42 +0000136
Wayne Davison423dba82003-12-24 01:14:16 +0000137static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
J.W. Schultz195bd902003-04-10 02:04:58 +0000138{
139 extern int block_size;
140 int blength, s2length, b;
141 uint32 c;
142 uint64 l;
143
144 if (block_size) {
145 blength = block_size;
146 } else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
147 blength = BLOCK_SIZE;
148 } else {
149 l = len;
150 c = 1;
151 while (l >>= 2) {
152 c <<= 1;
153 }
154 blength = 0;
155 do {
156 blength |= c;
Wayne Davisonfb55e282003-08-22 05:42:13 +0000157 if (len < (uint64)blength * blength)
J.W. Schultz195bd902003-04-10 02:04:58 +0000158 blength &= ~c;
159 c >>= 1;
160 } while (c >= 8); /* round to multiple of 8 */
161 blength = MAX(blength, BLOCK_SIZE);
162 }
163
Wayne Davisond04e9c52003-09-09 15:58:48 +0000164 if (protocol_version < 27) {
J.W. Schultz195bd902003-04-10 02:04:58 +0000165 s2length = csum_length;
166 } else if (csum_length == SUM_LENGTH) {
167 s2length = SUM_LENGTH;
168 } else {
169 b = BLOCKSUM_BIAS;
170 l = len;
171 while (l >>= 1) {
172 b += 2;
173 }
174 c = blength;
175 while (c >>= 1 && b) {
176 b--;
177 }
178 s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
179 * subtract rollsum,
180 * round up
181 * --optimize in compiler--
182 */
183 s2length = MAX(s2length, csum_length);
184 s2length = MIN(s2length, SUM_LENGTH);
185 }
186
187 sum->flength = len;
188 sum->blength = blength;
189 sum->s2length = s2length;
190 sum->count = (len + (blength - 1)) / blength;
191 sum->remainder = (len % blength);
192
193 if (sum->count && verbose > 2) {
194 rprintf(FINFO, "count=%ld rem=%ld blength=%ld s2length=%ld flength=%.0f\n",
195 (long) sum->count, (long) sum->remainder,
196 (long) sum->blength, (long) sum->s2length,
197 (double) sum->flength);
198 }
199}
Wayne Davison80605142002-07-31 21:20:07 +0000200
Martin Poolbceec822002-03-19 03:39:42 +0000201/**
202 * Perhaps we want to just send an empty checksum set for this file,
203 * which will force the whole thing to be literally transferred.
204 *
205 * When do we do this? If the user's explicitly said they
206 * want the whole thing, or if { they haven't explicitly
207 * requested a delta, and it's local but not batch mode.}
208 *
209 * Whew. */
210static BOOL disable_deltas_p(void)
211{
Wayne Davison2cda2562003-03-21 18:53:00 +0000212 extern int whole_file;
Martin Poolbceec822002-03-19 03:39:42 +0000213 extern int local_server;
214 extern int write_batch;
215
Wayne Davison2cda2562003-03-21 18:53:00 +0000216 if (whole_file > 0)
Martin Poolbceec822002-03-19 03:39:42 +0000217 return True;
Wayne Davison2cda2562003-03-21 18:53:00 +0000218 if (whole_file == 0 || write_batch)
Martin Poolbceec822002-03-19 03:39:42 +0000219 return False;
Wayne Davison2cda2562003-03-21 18:53:00 +0000220 return local_server;
Martin Poolbceec822002-03-19 03:39:42 +0000221}
222
223
Wayne Davison80605142002-07-31 21:20:07 +0000224/*
225 * Generate and send a stream of signatures/checksums that describe a buffer
Martin Poole66dfd12002-04-08 09:05:26 +0000226 *
Wayne Davison80605142002-07-31 21:20:07 +0000227 * Generate approximately one checksum every block_len bytes.
228 */
J.W. Schultz195bd902003-04-10 02:04:58 +0000229static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000230{
Wayne Davison80605142002-07-31 21:20:07 +0000231 size_t i;
232 struct sum_struct sum;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000233 OFF_T offset = 0;
234
Wayne Davison423dba82003-12-24 01:14:16 +0000235 sum_sizes_sqroot(&sum, len);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000236
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000237 write_sum_head(f_out, &sum);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000238
Wayne Davison80605142002-07-31 21:20:07 +0000239 for (i = 0; i < sum.count; i++) {
J.W. Schultz195bd902003-04-10 02:04:58 +0000240 int n1 = MIN(len, sum.blength);
Martin Poole66dfd12002-04-08 09:05:26 +0000241 char *map = map_ptr(buf, offset, n1);
Wayne Davison80605142002-07-31 21:20:07 +0000242 uint32 sum1 = get_checksum1(map, n1);
243 char sum2[SUM_LENGTH];
Martin Poole66dfd12002-04-08 09:05:26 +0000244
Wayne Davison80605142002-07-31 21:20:07 +0000245 get_checksum2(map, n1, sum2);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000246
Wayne Davison80605142002-07-31 21:20:07 +0000247 if (verbose > 3) {
Martin Poole66dfd12002-04-08 09:05:26 +0000248 rprintf(FINFO,
Wayne Davison88011382003-07-04 15:11:44 +0000249 "chunk[%ld] offset=%.0f len=%d sum1=%08lx\n",
250 (long)i,(double)offset,n1,(unsigned long)sum1);
Wayne Davison80605142002-07-31 21:20:07 +0000251 }
252 write_int(f_out, sum1);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000253 write_buf(f_out, sum2, sum.s2length);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000254 len -= n1;
255 offset += n1;
256 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000257}
258
259
Martin Poolef1aa912000-11-10 03:17:08 +0000260
Martin Pool420ef2c2002-04-08 08:02:08 +0000261/**
262 * Acts on file number @p i from @p flist, whose name is @p fname.
Martin Poolef1aa912000-11-10 03:17:08 +0000263 *
264 * First fixes up permissions, then generates checksums for the file.
265 *
Martin Pool420ef2c2002-04-08 08:02:08 +0000266 * @note This comment was added later by mbp who was trying to work it
267 * out. It might be wrong.
Wayne Davison2cda2562003-03-21 18:53:00 +0000268 **/
Martin Pool420ef2c2002-04-08 08:02:08 +0000269void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
Wayne Davison2cda2562003-03-21 18:53:00 +0000270{
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000271 int fd;
272 STRUCT_STAT st;
Wayne Davison968c8032004-01-02 08:19:26 +0000273 struct map_struct *mapbuf;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000274 int statret;
275 struct file_struct *file = flist->files[i];
David Dykstra375a4551998-10-26 21:42:38 +0000276 char *fnamecmp;
277 char fnamecmpbuf[MAXPATHLEN];
278 extern char *compare_dest;
Andrew Tridgellf7632fc1998-11-02 00:52:01 +0000279 extern int list_only;
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000280 extern int preserve_perms;
Andrew Tridgell1347d512000-01-23 01:53:18 +0000281 extern int only_existing;
Martin Poolb35d0d82002-04-08 04:10:20 +0000282 extern int orig_umask;
Andrew Tridgellf7632fc1998-11-02 00:52:01 +0000283
284 if (list_only) return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000285
286 if (verbose > 2)
287 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
288
289 statret = link_stat(fname,&st);
Martin Pool63787382001-12-14 02:16:20 +0000290
Andrew Tridgell1347d512000-01-23 01:53:18 +0000291 if (only_existing && statret == -1 && errno == ENOENT) {
292 /* we only want to update existing files */
David Dykstra1bbd10f2002-02-07 16:36:12 +0000293 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
Andrew Tridgell1347d512000-01-23 01:53:18 +0000294 return;
295 }
296
Wayne Davison2cda2562003-03-21 18:53:00 +0000297 if (statret == 0 &&
298 !preserve_perms &&
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000299 (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
300 /* if the file exists already and we aren't perserving
Wayne Davison2cda2562003-03-21 18:53:00 +0000301 * permissions then act as though the remote end sent
302 * us the file permissions we already have */
David Dykstra7e0ca8e1999-12-29 20:45:23 +0000303 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000304 }
305
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000306 if (S_ISDIR(file->mode)) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000307 /* The file to be received is a directory, so we need
308 * to prepare appropriately. If there is already a
309 * file of that name and it is *not* a directory, then
310 * we need to delete it. If it doesn't exist, then
311 * recursively create it. */
312
Martin Pool85d4d142001-12-14 02:14:58 +0000313 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000314 if (statret == 0 && !S_ISDIR(st.st_mode)) {
David Dykstrac7c11a01999-03-11 22:17:42 +0000315 if (robust_unlink(fname) != 0) {
Wayne Davisonea425412003-09-11 04:53:05 +0000316 rprintf(FERROR,
317 "recv_generator: unlink %s to make room for directory: %s\n",
318 full_fname(fname), strerror(errno));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000319 return;
320 }
321 statret = -1;
322 }
323 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000324 if (!(relative_paths && errno==ENOENT &&
325 create_directory_path(fname, orig_umask)==0 &&
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000326 do_mkdir(fname,file->mode)==0)) {
Wayne Davisonea425412003-09-11 04:53:05 +0000327 rprintf(FERROR, "recv_generator: mkdir %s failed: %s\n",
328 full_fname(fname), strerror(errno));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000329 }
330 }
Wayne Davison2cda2562003-03-21 18:53:00 +0000331 /* f_out is set to -1 when doing final directory
David Dykstrade343e32001-12-03 18:37:33 +0000332 permission and modification time repair */
Wayne Davison2cda2562003-03-21 18:53:00 +0000333 if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000334 rprintf(FINFO,"%s/\n",fname);
335 return;
336 }
337
338 if (preserve_links && S_ISLNK(file->mode)) {
339#if SUPPORT_LINKS
340 char lnk[MAXPATHLEN];
341 int l;
342 extern int safe_symlinks;
343
344 if (safe_symlinks && unsafe_symlink(file->link, fname)) {
345 if (verbose) {
Wayne Davisonea425412003-09-11 04:53:05 +0000346 rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
347 full_fname(fname), file->link);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000348 }
349 return;
350 }
351 if (statret == 0) {
352 l = readlink(fname,lnk,MAXPATHLEN-1);
353 if (l > 0) {
354 lnk[l] = 0;
Martin Pool85d4d142001-12-14 02:14:58 +0000355 /* A link already pointing to the
356 * right place -- no further action
357 * required. */
David Dykstra7e0ca8e1999-12-29 20:45:23 +0000358 if (strcmp(lnk,file->link) == 0) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000359 set_perms(fname,file,&st,1);
360 return;
361 }
Wayne Davison2cda2562003-03-21 18:53:00 +0000362 }
Martin Pool85d4d142001-12-14 02:14:58 +0000363 /* Not a symlink, so delete whatever's
364 * already there and put a new symlink
Wayne Davison2cda2562003-03-21 18:53:00 +0000365 * in place. */
Andrew Tridgell4b3977b2000-06-23 13:54:08 +0000366 delete_file(fname);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000367 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000368 if (do_symlink(file->link,fname) != 0) {
Wayne Davisonea425412003-09-11 04:53:05 +0000369 rprintf(FERROR, "symlink %s -> \"%s\" failed: %s\n",
370 full_fname(fname), file->link, strerror(errno));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000371 } else {
372 set_perms(fname,file,NULL,0);
373 if (verbose) {
David Dykstra1bbd10f2002-02-07 16:36:12 +0000374 rprintf(FINFO,"%s -> %s\n", fname,file->link);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000375 }
376 }
377#endif
378 return;
379 }
380
381#ifdef HAVE_MKNOD
382 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000383 if (statret != 0 ||
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000384 st.st_mode != file->mode ||
Wayne Davison365346c2003-08-21 23:46:10 +0000385 (DEV64_T)st.st_rdev != file->rdev) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000386 delete_file(fname);
387 if (verbose > 2)
388 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
389 fname,(int)file->mode,(int)file->rdev);
390 if (do_mknod(fname,file->mode,file->rdev) != 0) {
Wayne Davisonea425412003-09-11 04:53:05 +0000391 rprintf(FERROR, "mknod %s failed: %s\n",
392 full_fname(fname), strerror(errno));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000393 } else {
394 set_perms(fname,file,NULL,0);
395 if (verbose)
396 rprintf(FINFO,"%s\n",fname);
397 }
398 } else {
399 set_perms(fname,file,&st,1);
400 }
401 return;
402 }
403#endif
404
405 if (preserve_hard_links && check_hard_link(file)) {
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000406 if (verbose > 1) {
407 rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",
408 f_name(file));
409 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000410 return;
411 }
412
413 if (!S_ISREG(file->mode)) {
David Dykstra1bbd10f2002-02-07 16:36:12 +0000414 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000415 return;
416 }
417
David Dykstra375a4551998-10-26 21:42:38 +0000418 fnamecmp = fname;
419
420 if ((statret == -1) && (compare_dest != NULL)) {
421 /* try the file at compare_dest instead */
422 int saveerrno = errno;
Andrew Tridgell8950ac02001-05-07 06:59:37 +0000423 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
David Dykstra375a4551998-10-26 21:42:38 +0000424 statret = link_stat(fnamecmpbuf,&st);
425 if (!S_ISREG(st.st_mode))
426 statret = -1;
427 if (statret == -1)
428 errno = saveerrno;
David Dykstra59c95e42002-08-29 14:44:55 +0000429#if HAVE_LINK
430 else if (link_dest && !dry_run) {
431 if (do_link(fnamecmpbuf, fname) != 0) {
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000432 if (verbose > 0) {
David Dykstra59c95e42002-08-29 14:44:55 +0000433 rprintf(FINFO,"link %s => %s : %s\n",
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000434 fnamecmpbuf, fname,
David Dykstra59c95e42002-08-29 14:44:55 +0000435 strerror(errno));
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000436 }
David Dykstra59c95e42002-08-29 14:44:55 +0000437 }
438 fnamecmp = fnamecmpbuf;
439 }
440#endif
David Dykstra375a4551998-10-26 21:42:38 +0000441 else
442 fnamecmp = fnamecmpbuf;
443 }
444
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000445 if (statret == -1) {
446 if (errno == ENOENT) {
447 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000448 if (!dry_run) write_sum_head(f_out, NULL);
Wayne Davisonea425412003-09-11 04:53:05 +0000449 } else if (verbose > 1) {
450 rprintf(FERROR,
451 "recv_generator: failed to open %s: %s\n",
452 full_fname(fname), strerror(errno));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000453 }
454 return;
455 }
456
457 if (!S_ISREG(st.st_mode)) {
458 if (delete_file(fname) != 0) {
459 return;
460 }
461
462 /* now pretend the file didn't exist */
463 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000464 if (!dry_run) write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000465 return;
466 }
467
Wayne Davison2cda2562003-03-21 18:53:00 +0000468 if (opt_ignore_existing && fnamecmp == fname) {
Martin Pool3d6fead2002-01-25 10:42:23 +0000469 if (verbose > 1)
470 rprintf(FINFO,"%s exists\n",fname);
471 return;
Wayne Davison2cda2562003-03-21 18:53:00 +0000472 }
Martin Pool3d6fead2002-01-25 10:42:23 +0000473
Andrew Tridgell5b56cc12000-09-06 02:12:13 +0000474 if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000475 if (verbose > 1)
476 rprintf(FINFO,"%s is newer\n",fname);
477 return;
478 }
479
480 if (skip_file(fname, file, &st)) {
David Dykstrabd4ed7f1999-04-02 18:24:27 +0000481 if (fnamecmp == fname)
482 set_perms(fname,file,&st,1);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000483 return;
484 }
485
486 if (dry_run) {
487 write_int(f_out,i);
488 return;
489 }
490
Martin Poolbceec822002-03-19 03:39:42 +0000491 if (disable_deltas_p()) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000492 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000493 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000494 return;
495 }
496
Wayne Davison2cda2562003-03-21 18:53:00 +0000497 /* open the file */
Andrew Tridgell8c9fd201999-10-25 22:04:09 +0000498 fd = do_open(fnamecmp, O_RDONLY, 0);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000499
500 if (fd == -1) {
Wayne Davisonea425412003-09-11 04:53:05 +0000501 rprintf(FERROR, "failed to open %s, continuing: %s\n",
502 full_fname(fnamecmp), strerror(errno));
David Dykstra60be6ac2000-01-06 16:15:36 +0000503 /* pretend the file didn't exist */
504 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000505 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000506 return;
507 }
508
Wayne Davison968c8032004-01-02 08:19:26 +0000509 if (st.st_size > 0)
510 mapbuf = map_file(fd,st.st_size);
511 else
512 mapbuf = NULL;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000513
514 if (verbose > 3)
Andrew Tridgell5f808df2000-01-23 12:30:34 +0000515 rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000516
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000517 if (verbose > 2)
Wayne Davison80605142002-07-31 21:20:07 +0000518 rprintf(FINFO, "generating and sending sums for %d\n", i);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000519
520 write_int(f_out,i);
Wayne Davison968c8032004-01-02 08:19:26 +0000521 generate_and_send_sums(mapbuf, st.st_size, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000522
523 close(fd);
Wayne Davison968c8032004-01-02 08:19:26 +0000524 if (mapbuf) unmap_file(mapbuf);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000525}
526
527
528
529void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
530{
531 int i;
532 int phase=0;
Wayne Davison968c8032004-01-02 08:19:26 +0000533 char fbuf[MAXPATHLEN];
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000534
535 if (verbose > 2)
536 rprintf(FINFO,"generator starting pid=%d count=%d\n",
537 (int)getpid(),flist->count);
538
Martin Pool3e7053a2002-04-08 08:06:18 +0000539 if (verbose >= 2) {
540 rprintf(FINFO,
Wayne Davison2cda2562003-03-21 18:53:00 +0000541 disable_deltas_p()
Martin Pool3e7053a2002-04-08 08:06:18 +0000542 ? "delta-transmission disabled for local transfer or --whole-file\n"
543 : "delta transmission enabled\n");
544 }
Wayne Davison2cda2562003-03-21 18:53:00 +0000545
Andrew Tridgella57873b2001-09-09 04:42:09 +0000546 /* we expect to just sit around now, so don't exit on a
547 timeout. If we really get a timeout then the other process should
548 exit */
549 io_timeout = 0;
550
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000551 for (i = 0; i < flist->count; i++) {
552 struct file_struct *file = flist->files[i];
553 mode_t saved_mode = file->mode;
554 if (!file->basename) continue;
555
556 /* we need to ensure that any directories we create have writeable
557 permissions initially so that we can create the files within
558 them. This is then fixed after the files are transferred */
559 if (!am_root && S_ISDIR(file->mode)) {
560 file->mode |= S_IWUSR; /* user write */
Wayne Davison2cda2562003-03-21 18:53:00 +0000561 /* XXX: Could this be causing a problem on SCO? Perhaps their
562 * handling of permissions is strange? */
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000563 }
564
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000565 recv_generator(local_name? local_name
Wayne Davison968c8032004-01-02 08:19:26 +0000566 : f_name_to(file,fbuf,sizeof fbuf), flist, i, f);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000567
568 file->mode = saved_mode;
569 }
570
571 phase++;
572 csum_length = SUM_LENGTH;
573 ignore_times=1;
574
575 if (verbose > 2)
576 rprintf(FINFO,"generate_files phase=%d\n",phase);
577
578 write_int(f,-1);
579
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000580 /* files can cycle through the system more than once
581 * to catch initial checksum errors */
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000582 for (i = read_int(f_recv); i != -1; i = read_int(f_recv)) {
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000583 struct file_struct *file = flist->files[i];
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000584 recv_generator(local_name? local_name
Wayne Davison968c8032004-01-02 08:19:26 +0000585 : f_name_to(file,fbuf,sizeof fbuf), flist, i, f);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000586 }
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000587
588 phase++;
589 if (verbose > 2)
590 rprintf(FINFO,"generate_files phase=%d\n",phase);
591
592 write_int(f,-1);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000593}