blob: b576b1382a4d8a6daa6bc5944a4df9ca28cb8d59 [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;
Wayne Davison716e73d2004-06-05 16:16:30 +000029extern int keep_dirlinks;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000030extern int preserve_links;
31extern int am_root;
32extern int preserve_devices;
33extern int preserve_hard_links;
Wayne Davison6744b622004-01-02 16:50:06 +000034extern int preserve_perms;
35extern int preserve_uid;
36extern int preserve_gid;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000037extern int update_only;
Martin Pool3d6fead2002-01-25 10:42:23 +000038extern int opt_ignore_existing;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000039extern int csum_length;
40extern int ignore_times;
Andrew Tridgellf83f0541999-02-18 03:48:24 +000041extern int size_only;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000042extern int io_timeout;
Wayne Davisond04e9c52003-09-09 15:58:48 +000043extern int protocol_version;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000044extern int always_checksum;
David Dykstra60c8d7b2000-08-04 21:11:46 +000045extern char *compare_dest;
David Dykstra59c95e42002-08-29 14:44:55 +000046extern int link_dest;
Wayne Davison57747862004-04-15 16:55:23 +000047extern int whole_file;
48extern int local_server;
Wayne Davison57747862004-04-15 16:55:23 +000049extern int list_only;
Wayne Davisonb9f592f2004-07-15 02:20:08 +000050extern int read_batch;
Wayne Davison57747862004-04-15 16:55:23 +000051extern int only_existing;
52extern int orig_umask;
53extern int safe_symlinks;
Wayne Davisonec8290c2004-06-18 16:30:24 +000054extern unsigned int block_size;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000055
Wayne Davison97f9dca2004-05-18 00:14:10 +000056extern struct exclude_list_struct server_exclude_list;
57
Andrew Tridgell2f03f951998-07-25 02:25:22 +000058
59/* choose whether to skip a particular file */
Wayne Davisondfd5ba62004-01-04 18:43:18 +000060static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
Andrew Tridgell2f03f951998-07-25 02:25:22 +000061{
Wayne Davisoncc1e9972004-06-23 16:51:21 +000062 if (st->st_size != file->length)
Wayne Davison84acca02004-06-23 21:21:19 +000063 return 0;
David Dykstra59c95e42002-08-29 14:44:55 +000064 if (link_dest) {
Wayne Davisone7bc9b62004-01-02 08:05:20 +000065 if (preserve_perms
Wayne Davison67e78a82004-03-07 20:29:59 +000066 && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
Wayne Davison84acca02004-06-23 21:21:19 +000067 return 0;
J.W. Schultzbb240282003-03-26 20:26:06 +000068
Wayne Davison6744b622004-01-02 16:50:06 +000069 if (am_root && preserve_uid && st->st_uid != file->uid)
Wayne Davison84acca02004-06-23 21:21:19 +000070 return 0;
J.W. Schultzbb240282003-03-26 20:26:06 +000071
J.W. Schultza60e2dc2004-01-03 13:17:32 +000072 if (preserve_gid && file->gid != GID_NONE
73 && st->st_gid != file->gid)
Wayne Davison84acca02004-06-23 21:21:19 +000074 return 0;
David Dykstra59c95e42002-08-29 14:44:55 +000075 }
76
Wayne Davison2cda2562003-03-21 18:53:00 +000077 /* if always checksum is set then we use the checksum instead
Andrew Tridgell2f03f951998-07-25 02:25:22 +000078 of the file time to determine whether to sync */
79 if (always_checksum && S_ISREG(st->st_mode)) {
80 char sum[MD4_SUM_LENGTH];
David Dykstra60c8d7b2000-08-04 21:11:46 +000081 char fnamecmpdest[MAXPATHLEN];
82
83 if (compare_dest != NULL) {
84 if (access(fname, 0) != 0) {
Wayne Davison248ed452004-01-20 05:09:36 +000085 pathjoin(fnamecmpdest, sizeof fnamecmpdest,
86 compare_dest, fname);
David Dykstra60c8d7b2000-08-04 21:11:46 +000087 fname = fnamecmpdest;
88 }
89 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +000090 file_checksum(fname,sum,st->st_size);
Wayne Davison728d0922004-01-11 07:28:45 +000091 return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
Wayne Davison84acca02004-06-23 21:21:19 +000092 : MD4_SUM_LENGTH) == 0;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000093 }
94
Wayne Davisoncc1e9972004-06-23 16:51:21 +000095 if (size_only)
Wayne Davisoncc1e9972004-06-23 16:51:21 +000096 return 1;
97
Wayne Davison84acca02004-06-23 21:21:19 +000098 if (ignore_times)
99 return 0;
100
101 return cmp_modtime(st->st_mtime, file->modtime) == 0;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000102}
103
104
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000105/*
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000106 * NULL sum_struct means we have no checksums
J.W. Schultz195bd902003-04-10 02:04:58 +0000107 */
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000108void write_sum_head(int f, struct sum_struct *sum)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000109{
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000110 static struct sum_struct null_sum;
111
Wayne Davisonc3384602004-02-27 08:03:49 +0000112 if (sum == NULL)
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000113 sum = &null_sum;
114
115 write_int(f, sum->count);
116 write_int(f, sum->blength);
Wayne Davisond04e9c52003-09-09 15:58:48 +0000117 if (protocol_version >= 27)
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000118 write_int(f, sum->s2length);
119 write_int(f, sum->remainder);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000120}
121
Wayne Davisonec8290c2004-06-18 16:30:24 +0000122/*
J.W. Schultz195bd902003-04-10 02:04:58 +0000123 * set (initialize) the size entries in the per-file sum_struct
Wayne Davisonec8290c2004-06-18 16:30:24 +0000124 * calculating dynamic block and checksum sizes.
J.W. Schultz195bd902003-04-10 02:04:58 +0000125 *
Wayne Davisonec8290c2004-06-18 16:30:24 +0000126 * This is only called from generate_and_send_sums() but is a separate
J.W. Schultz195bd902003-04-10 02:04:58 +0000127 * function to encapsulate the logic.
128 *
129 * The block size is a rounded square root of file length.
130 *
131 * The checksum size is determined according to:
132 * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
133 * provided by Donovan Baarda which gives a probability of rsync
134 * algorithm corrupting data and falling back using the whole md4
135 * checksums.
136 *
137 * This might be made one of several selectable heuristics.
138 */
Martin Poolbceec822002-03-19 03:39:42 +0000139
Wayne Davison423dba82003-12-24 01:14:16 +0000140static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
J.W. Schultz195bd902003-04-10 02:04:58 +0000141{
Wayne Davisonda9d12f2004-01-03 18:37:41 +0000142 unsigned int blength;
143 int s2length;
J.W. Schultz195bd902003-04-10 02:04:58 +0000144 uint32 c;
145 uint64 l;
146
147 if (block_size) {
148 blength = block_size;
149 } else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
150 blength = BLOCK_SIZE;
151 } else {
152 l = len;
153 c = 1;
154 while (l >>= 2) {
155 c <<= 1;
156 }
157 blength = 0;
158 do {
159 blength |= c;
Wayne Davisonfb55e282003-08-22 05:42:13 +0000160 if (len < (uint64)blength * blength)
J.W. Schultz195bd902003-04-10 02:04:58 +0000161 blength &= ~c;
162 c >>= 1;
163 } while (c >= 8); /* round to multiple of 8 */
164 blength = MAX(blength, BLOCK_SIZE);
Wayne Davisonefd5ee52004-07-16 18:04:23 +0000165 blength = MIN(blength, MAX_MAP_SIZE);
J.W. Schultz195bd902003-04-10 02:04:58 +0000166 }
167
Wayne Davisond04e9c52003-09-09 15:58:48 +0000168 if (protocol_version < 27) {
J.W. Schultz195bd902003-04-10 02:04:58 +0000169 s2length = csum_length;
170 } else if (csum_length == SUM_LENGTH) {
171 s2length = SUM_LENGTH;
172 } else {
Wayne Davisonda9d12f2004-01-03 18:37:41 +0000173 int b = BLOCKSUM_BIAS;
J.W. Schultz195bd902003-04-10 02:04:58 +0000174 l = len;
175 while (l >>= 1) {
176 b += 2;
177 }
178 c = blength;
179 while (c >>= 1 && b) {
180 b--;
181 }
182 s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
183 * subtract rollsum,
184 * round up
185 * --optimize in compiler--
186 */
187 s2length = MAX(s2length, csum_length);
188 s2length = MIN(s2length, SUM_LENGTH);
189 }
190
191 sum->flength = len;
192 sum->blength = blength;
193 sum->s2length = s2length;
194 sum->count = (len + (blength - 1)) / blength;
195 sum->remainder = (len % blength);
196
197 if (sum->count && verbose > 2) {
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000198 rprintf(FINFO, "count=%.0f rem=%u blength=%u s2length=%d flength=%.0f\n",
199 (double)sum->count, sum->remainder, sum->blength,
Wayne Davisonda9d12f2004-01-03 18:37:41 +0000200 sum->s2length, (double)sum->flength);
J.W. Schultz195bd902003-04-10 02:04:58 +0000201 }
202}
Wayne Davison80605142002-07-31 21:20:07 +0000203
Martin Poolbceec822002-03-19 03:39:42 +0000204
Wayne Davison80605142002-07-31 21:20:07 +0000205/*
206 * Generate and send a stream of signatures/checksums that describe a buffer
Martin Poole66dfd12002-04-08 09:05:26 +0000207 *
Wayne Davison80605142002-07-31 21:20:07 +0000208 * Generate approximately one checksum every block_len bytes.
209 */
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000210static void generate_and_send_sums(int fd, OFF_T len, int f_out)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000211{
Wayne Davison80605142002-07-31 21:20:07 +0000212 size_t i;
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000213 struct map_struct *mapbuf;
Wayne Davison80605142002-07-31 21:20:07 +0000214 struct sum_struct sum;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000215 OFF_T offset = 0;
216
Wayne Davison423dba82003-12-24 01:14:16 +0000217 sum_sizes_sqroot(&sum, len);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000218
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000219 if (len > 0)
220 mapbuf = map_file(fd, len, sum.blength);
221 else
222 mapbuf = NULL;
223
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000224 write_sum_head(f_out, &sum);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000225
Wayne Davison80605142002-07-31 21:20:07 +0000226 for (i = 0; i < sum.count; i++) {
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000227 unsigned int n1 = MIN(len, sum.blength);
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000228 char *map = map_ptr(mapbuf, offset, n1);
Wayne Davison80605142002-07-31 21:20:07 +0000229 uint32 sum1 = get_checksum1(map, n1);
230 char sum2[SUM_LENGTH];
Martin Poole66dfd12002-04-08 09:05:26 +0000231
Wayne Davison80605142002-07-31 21:20:07 +0000232 get_checksum2(map, n1, sum2);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000233
Wayne Davison80605142002-07-31 21:20:07 +0000234 if (verbose > 3) {
Martin Poole66dfd12002-04-08 09:05:26 +0000235 rprintf(FINFO,
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000236 "chunk[%.0f] offset=%.0f len=%u sum1=%08lx\n",
237 (double)i, (double)offset, n1,
238 (unsigned long)sum1);
Wayne Davison80605142002-07-31 21:20:07 +0000239 }
240 write_int(f_out, sum1);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000241 write_buf(f_out, sum2, sum.s2length);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000242 len -= n1;
243 offset += n1;
244 }
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000245
246 if (mapbuf)
247 unmap_file(mapbuf);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000248}
249
250
Martin Poolef1aa912000-11-10 03:17:08 +0000251
Wayne Davisonfd322ee2004-06-29 19:19:00 +0000252/*
Martin Pool420ef2c2002-04-08 08:02:08 +0000253 * Acts on file number @p i from @p flist, whose name is @p fname.
Martin Poolef1aa912000-11-10 03:17:08 +0000254 *
255 * First fixes up permissions, then generates checksums for the file.
256 *
Martin Pool420ef2c2002-04-08 08:02:08 +0000257 * @note This comment was added later by mbp who was trying to work it
258 * out. It might be wrong.
Wayne Davisonfd322ee2004-06-29 19:19:00 +0000259 */
260static void recv_generator(char *fname, struct file_struct *file, int i,
261 int f_out)
Wayne Davison2cda2562003-03-21 18:53:00 +0000262{
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000263 int fd;
264 STRUCT_STAT st;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000265 int statret;
David Dykstra375a4551998-10-26 21:42:38 +0000266 char *fnamecmp;
267 char fnamecmpbuf[MAXPATHLEN];
Andrew Tridgellf7632fc1998-11-02 00:52:01 +0000268
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000269 if (list_only)
270 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000271
272 if (verbose > 2)
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000273 rprintf(FINFO, "recv_generator(%s,%d)\n", safe_fname(fname), i);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000274
Wayne Davison97f9dca2004-05-18 00:14:10 +0000275 if (server_exclude_list.head
276 && check_exclude(&server_exclude_list, fname,
Wayne Davison3e35c342004-05-18 08:50:17 +0000277 S_ISDIR(file->mode)) < 0) {
278 if (verbose) {
279 rprintf(FINFO, "skipping server-excluded file \"%s\"\n",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000280 safe_fname(fname));
Wayne Davison3e35c342004-05-18 08:50:17 +0000281 }
Wayne Davison97f9dca2004-05-18 00:14:10 +0000282 return;
Wayne Davison3e35c342004-05-18 08:50:17 +0000283 }
Wayne Davison97f9dca2004-05-18 00:14:10 +0000284
Wayne Davison6218c7b2004-06-11 07:40:51 +0000285 statret = link_stat(fname, &st, keep_dirlinks && S_ISDIR(file->mode));
Martin Pool63787382001-12-14 02:16:20 +0000286
Andrew Tridgell1347d512000-01-23 01:53:18 +0000287 if (only_existing && statret == -1 && errno == ENOENT) {
288 /* we only want to update existing files */
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000289 if (verbose > 1) {
290 rprintf(FINFO, "not creating new file \"%s\"\n",
291 safe_fname(fname));
292 }
Andrew Tridgell1347d512000-01-23 01:53:18 +0000293 return;
294 }
295
Wayne Davisond9b4d262004-07-23 16:59:38 +0000296 if (statret == 0 && !preserve_perms
297 && S_ISDIR(st.st_mode) == S_ISDIR(file->mode)) {
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000298 /* if the file exists already and we aren't perserving
Wayne Davison2cda2562003-03-21 18:53:00 +0000299 * permissions then act as though the remote end sent
300 * us the file permissions we already have */
Wayne Davison67e78a82004-03-07 20:29:59 +0000301 file->mode = (file->mode & ~CHMOD_BITS)
302 | (st.st_mode & CHMOD_BITS);
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000303 }
304
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000305 if (S_ISDIR(file->mode)) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000306 /* The file to be received is a directory, so we need
307 * to prepare appropriately. If there is already a
308 * file of that name and it is *not* a directory, then
309 * we need to delete it. If it doesn't exist, then
310 * recursively create it. */
311
Wayne Davisonec8290c2004-06-18 16:30:24 +0000312 if (dry_run)
313 return; /* TODO: causes inaccuracies -- fix */
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 Davisond62bcc12004-05-15 19:31:10 +0000316 rsyserr(FERROR, errno,
317 "recv_generator: unlink %s to make room for directory",
318 full_fname(fname));
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 Davisond62bcc12004-05-15 19:31:10 +0000324 if (!(relative_paths && errno == ENOENT
325 && create_directory_path(fname, orig_umask) == 0
326 && do_mkdir(fname, file->mode) == 0)) {
327 rsyserr(FERROR, errno,
328 "recv_generator: mkdir %s failed",
329 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000330 }
331 }
Wayne Davison716e73d2004-06-05 16:16:30 +0000332 /* f_out is set to -1 when doing final directory-permission
333 * and modification-time repair. */
334 if (set_perms(fname, file, statret ? NULL : &st, 0)
335 && verbose && f_out != -1)
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000336 rprintf(FINFO, "%s/\n", safe_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000337 return;
338 }
339
340 if (preserve_links && S_ISLNK(file->mode)) {
341#if SUPPORT_LINKS
342 char lnk[MAXPATHLEN];
343 int l;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000344
Wayne Davison728d0922004-01-11 07:28:45 +0000345 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000346 if (verbose) {
Wayne Davisonea425412003-09-11 04:53:05 +0000347 rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
Wayne Davison728d0922004-01-11 07:28:45 +0000348 full_fname(fname), file->u.link);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000349 }
350 return;
351 }
352 if (statret == 0) {
353 l = readlink(fname,lnk,MAXPATHLEN-1);
354 if (l > 0) {
355 lnk[l] = 0;
Martin Pool85d4d142001-12-14 02:14:58 +0000356 /* A link already pointing to the
357 * right place -- no further action
358 * required. */
Wayne Davison728d0922004-01-11 07:28:45 +0000359 if (strcmp(lnk,file->u.link) == 0) {
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000360 set_perms(fname, file, &st,
361 PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000362 return;
363 }
Wayne Davison2cda2562003-03-21 18:53:00 +0000364 }
Martin Pool85d4d142001-12-14 02:14:58 +0000365 /* Not a symlink, so delete whatever's
366 * already there and put a new symlink
Wayne Davison2cda2562003-03-21 18:53:00 +0000367 * in place. */
Andrew Tridgell4b3977b2000-06-23 13:54:08 +0000368 delete_file(fname);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000369 }
Wayne Davison728d0922004-01-11 07:28:45 +0000370 if (do_symlink(file->u.link,fname) != 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000371 rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000372 full_fname(fname), safe_fname(file->u.link));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000373 } else {
374 set_perms(fname,file,NULL,0);
375 if (verbose) {
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000376 rprintf(FINFO, "%s -> %s\n", safe_fname(fname),
377 safe_fname(file->u.link));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000378 }
379 }
380#endif
381 return;
382 }
383
384#ifdef HAVE_MKNOD
385 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000386 if (statret != 0 ||
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000387 st.st_mode != file->mode ||
Wayne Davison3915fd72004-04-12 16:52:43 +0000388 st.st_rdev != file->u.rdev) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000389 delete_file(fname);
Wayne Davisond62bcc12004-05-15 19:31:10 +0000390 if (verbose > 2) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000391 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000392 safe_fname(fname),
393 (int)file->mode, (int)file->u.rdev);
Wayne Davisond62bcc12004-05-15 19:31:10 +0000394 }
Wayne Davison728d0922004-01-11 07:28:45 +0000395 if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000396 rsyserr(FERROR, errno, "mknod %s failed",
397 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000398 } else {
399 set_perms(fname,file,NULL,0);
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000400 if (verbose) {
401 rprintf(FINFO, "%s\n",
402 safe_fname(fname));
403 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000404 }
405 } else {
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000406 set_perms(fname, file, &st, PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000407 }
408 return;
409 }
410#endif
411
Wayne Davison6dff5992004-01-25 22:32:09 +0000412 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000413 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000414
415 if (!S_ISREG(file->mode)) {
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000416 rprintf(FINFO, "skipping non-regular file \"%s\"\n",
417 safe_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000418 return;
419 }
420
David Dykstra375a4551998-10-26 21:42:38 +0000421 fnamecmp = fname;
422
Wayne Davisonc3384602004-02-27 08:03:49 +0000423 if (statret == -1 && compare_dest != NULL) {
David Dykstra375a4551998-10-26 21:42:38 +0000424 /* try the file at compare_dest instead */
425 int saveerrno = errno;
Wayne Davison248ed452004-01-20 05:09:36 +0000426 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
Wayne Davison6218c7b2004-06-11 07:40:51 +0000427 statret = link_stat(fnamecmpbuf, &st, 0);
David Dykstra375a4551998-10-26 21:42:38 +0000428 if (!S_ISREG(st.st_mode))
429 statret = -1;
430 if (statret == -1)
431 errno = saveerrno;
David Dykstra59c95e42002-08-29 14:44:55 +0000432#if HAVE_LINK
433 else if (link_dest && !dry_run) {
434 if (do_link(fnamecmpbuf, fname) != 0) {
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000435 if (verbose > 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000436 rsyserr(FINFO, errno, "link %s => %s",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000437 fnamecmpbuf, safe_fname(fname));
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000438 }
David Dykstra59c95e42002-08-29 14:44:55 +0000439 }
440 fnamecmp = fnamecmpbuf;
441 }
442#endif
David Dykstra375a4551998-10-26 21:42:38 +0000443 else
444 fnamecmp = fnamecmpbuf;
445 }
446
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000447 if (statret == -1) {
Wayne Davison6dff5992004-01-25 22:32:09 +0000448 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
449 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000450 if (errno == ENOENT) {
451 write_int(f_out,i);
Wayne Davison727b35f2004-07-21 23:59:25 +0000452 if (!dry_run && !read_batch)
Wayne Davisonec8290c2004-06-18 16:30:24 +0000453 write_sum_head(f_out, NULL);
Wayne Davisonea425412003-09-11 04:53:05 +0000454 } else if (verbose > 1) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000455 rsyserr(FERROR, errno,
456 "recv_generator: failed to open %s",
457 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000458 }
459 return;
460 }
461
462 if (!S_ISREG(st.st_mode)) {
463 if (delete_file(fname) != 0) {
464 return;
465 }
466
467 /* now pretend the file didn't exist */
Wayne Davison6dff5992004-01-25 22:32:09 +0000468 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
469 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000470 write_int(f_out,i);
Wayne Davison727b35f2004-07-21 23:59:25 +0000471 if (!dry_run && !read_batch)
Wayne Davisonec8290c2004-06-18 16:30:24 +0000472 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000473 return;
474 }
475
Wayne Davison2cda2562003-03-21 18:53:00 +0000476 if (opt_ignore_existing && fnamecmp == fname) {
Martin Pool3d6fead2002-01-25 10:42:23 +0000477 if (verbose > 1)
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000478 rprintf(FINFO, "%s exists\n", safe_fname(fname));
Martin Pool3d6fead2002-01-25 10:42:23 +0000479 return;
Wayne Davison2cda2562003-03-21 18:53:00 +0000480 }
Martin Pool3d6fead2002-01-25 10:42:23 +0000481
Wayne Davisond3a43752004-06-29 16:22:54 +0000482 if (update_only && fnamecmp == fname
483 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000484 if (verbose > 1)
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000485 rprintf(FINFO, "%s is newer\n", safe_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000486 return;
487 }
488
Wayne Davison84acca02004-06-23 21:21:19 +0000489 if (skip_file(fname, file, &st)) {
David Dykstrabd4ed7f1999-04-02 18:24:27 +0000490 if (fnamecmp == fname)
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000491 set_perms(fname, file, &st, PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000492 return;
493 }
494
Wayne Davison727b35f2004-07-21 23:59:25 +0000495 if (dry_run || read_batch) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000496 write_int(f_out,i);
497 return;
498 }
499
Wayne Davisonf38bd4a2004-07-13 01:45:51 +0000500 if (whole_file > 0) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000501 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000502 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000503 return;
504 }
505
Wayne Davison2cda2562003-03-21 18:53:00 +0000506 /* open the file */
Andrew Tridgell8c9fd201999-10-25 22:04:09 +0000507 fd = do_open(fnamecmp, O_RDONLY, 0);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000508
509 if (fd == -1) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000510 rsyserr(FERROR, errno, "failed to open %s, continuing",
511 full_fname(fnamecmp));
David Dykstra60be6ac2000-01-06 16:15:36 +0000512 /* pretend the file didn't exist */
Wayne Davison6dff5992004-01-25 22:32:09 +0000513 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
514 return;
David Dykstra60be6ac2000-01-06 16:15:36 +0000515 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000516 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000517 return;
518 }
519
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000520 if (verbose > 3) {
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000521 rprintf(FINFO, "gen mapped %s of size %.0f\n",
522 safe_fname(fnamecmp), (double)st.st_size);
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000523 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000524
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000525 if (verbose > 2)
Wayne Davison80605142002-07-31 21:20:07 +0000526 rprintf(FINFO, "generating and sending sums for %d\n", i);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000527
528 write_int(f_out,i);
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000529 generate_and_send_sums(fd, st.st_size, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000530
531 close(fd);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000532}
533
534
Wayne Davison7daccb82004-07-12 20:42:48 +0000535void generate_files(int f_out, struct file_list *flist, char *local_name)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000536{
537 int i;
Wayne Davisone1f67412004-06-30 07:27:30 +0000538 int phase = 0;
Wayne Davison968c8032004-01-02 08:19:26 +0000539 char fbuf[MAXPATHLEN];
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000540
Wayne Davison45e08ed2004-01-27 08:02:31 +0000541 if (verbose > 2) {
542 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
543 (long)getpid(), flist->count);
544 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000545
Martin Pool3e7053a2002-04-08 08:06:18 +0000546 if (verbose >= 2) {
547 rprintf(FINFO,
Wayne Davisonf38bd4a2004-07-13 01:45:51 +0000548 whole_file > 0
Martin Pool3e7053a2002-04-08 08:06:18 +0000549 ? "delta-transmission disabled for local transfer or --whole-file\n"
550 : "delta transmission enabled\n");
551 }
Wayne Davison2cda2562003-03-21 18:53:00 +0000552
Andrew Tridgella57873b2001-09-09 04:42:09 +0000553 /* we expect to just sit around now, so don't exit on a
554 timeout. If we really get a timeout then the other process should
555 exit */
556 io_timeout = 0;
557
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000558 for (i = 0; i < flist->count; i++) {
559 struct file_struct *file = flist->files[i];
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000560 struct file_struct copy;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000561
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000562 if (!file->basename)
563 continue;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000564 /* we need to ensure that any directories we create have writeable
565 permissions initially so that we can create the files within
566 them. This is then fixed after the files are transferred */
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000567 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
568 copy = *file;
Wayne Davison2cda2562003-03-21 18:53:00 +0000569 /* XXX: Could this be causing a problem on SCO? Perhaps their
570 * handling of permissions is strange? */
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000571 copy.mode |= S_IWUSR; /* user write */
572 file = &copy;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000573 }
574
Wayne Davison3fef5362004-01-22 04:38:18 +0000575 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
Wayne Davison7daccb82004-07-12 20:42:48 +0000576 file, i, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000577 }
578
579 phase++;
580 csum_length = SUM_LENGTH;
Wayne Davisone1f67412004-06-30 07:27:30 +0000581 ignore_times = 1;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000582
583 if (verbose > 2)
584 rprintf(FINFO,"generate_files phase=%d\n",phase);
585
Wayne Davison7daccb82004-07-12 20:42:48 +0000586 write_int(f_out, -1);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000587
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000588 /* files can cycle through the system more than once
589 * to catch initial checksum errors */
Wayne Davisonb9b15fb2004-01-15 07:42:15 +0000590 while ((i = get_redo_num()) != -1) {
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000591 struct file_struct *file = flist->files[i];
Wayne Davison3fef5362004-01-22 04:38:18 +0000592 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
Wayne Davison7daccb82004-07-12 20:42:48 +0000593 file, i, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000594 }
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000595
596 phase++;
597 if (verbose > 2)
598 rprintf(FINFO,"generate_files phase=%d\n",phase);
599
Wayne Davison7daccb82004-07-12 20:42:48 +0000600 write_int(f_out, -1);
Wayne Davison6dff5992004-01-25 22:32:09 +0000601
602 if (preserve_hard_links)
603 do_hard_links();
604
605 /* now we need to fix any directory permissions that were
606 * modified during the transfer */
607 for (i = 0; i < flist->count; i++) {
608 struct file_struct *file = flist->files[i];
Wayne Davisonec8290c2004-06-18 16:30:24 +0000609 if (!file->basename || !S_ISDIR(file->mode))
610 continue;
Wayne Davison6dff5992004-01-25 22:32:09 +0000611 recv_generator(local_name ? local_name : f_name(file),
612 file, i, -1);
613 }
614
615 if (verbose > 2)
616 rprintf(FINFO,"generate_files finished\n");
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000617}