blob: 1adb7a71a35d900e7222ca5491a6249c6cd46551 [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;
Wayne Davisona7260c42004-07-29 16:06:38 +000045extern char *partial_dir;
David Dykstra60c8d7b2000-08-04 21:11:46 +000046extern char *compare_dest;
David Dykstra59c95e42002-08-29 14:44:55 +000047extern int link_dest;
Wayne Davison57747862004-04-15 16:55:23 +000048extern int whole_file;
49extern int local_server;
Wayne Davison57747862004-04-15 16:55:23 +000050extern int list_only;
Wayne Davisonb9f592f2004-07-15 02:20:08 +000051extern int read_batch;
Wayne Davison57747862004-04-15 16:55:23 +000052extern int only_existing;
53extern int orig_umask;
54extern int safe_symlinks;
Wayne Davisonec8290c2004-06-18 16:30:24 +000055extern unsigned int block_size;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000056
Wayne Davison97f9dca2004-05-18 00:14:10 +000057extern struct exclude_list_struct server_exclude_list;
58
Andrew Tridgell2f03f951998-07-25 02:25:22 +000059
60/* choose whether to skip a particular file */
Wayne Davisondfd5ba62004-01-04 18:43:18 +000061static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
Andrew Tridgell2f03f951998-07-25 02:25:22 +000062{
Wayne Davisoncc1e9972004-06-23 16:51:21 +000063 if (st->st_size != file->length)
Wayne Davison84acca02004-06-23 21:21:19 +000064 return 0;
David Dykstra59c95e42002-08-29 14:44:55 +000065 if (link_dest) {
Wayne Davisone7bc9b62004-01-02 08:05:20 +000066 if (preserve_perms
Wayne Davison67e78a82004-03-07 20:29:59 +000067 && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
Wayne Davison84acca02004-06-23 21:21:19 +000068 return 0;
J.W. Schultzbb240282003-03-26 20:26:06 +000069
Wayne Davison6744b622004-01-02 16:50:06 +000070 if (am_root && preserve_uid && st->st_uid != file->uid)
Wayne Davison84acca02004-06-23 21:21:19 +000071 return 0;
J.W. Schultzbb240282003-03-26 20:26:06 +000072
J.W. Schultza60e2dc2004-01-03 13:17:32 +000073 if (preserve_gid && file->gid != GID_NONE
74 && st->st_gid != file->gid)
Wayne Davison84acca02004-06-23 21:21:19 +000075 return 0;
David Dykstra59c95e42002-08-29 14:44:55 +000076 }
77
Wayne Davison2cda2562003-03-21 18:53:00 +000078 /* if always checksum is set then we use the checksum instead
Andrew Tridgell2f03f951998-07-25 02:25:22 +000079 of the file time to determine whether to sync */
80 if (always_checksum && S_ISREG(st->st_mode)) {
81 char sum[MD4_SUM_LENGTH];
82 file_checksum(fname,sum,st->st_size);
Wayne Davison728d0922004-01-11 07:28:45 +000083 return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
Wayne Davison84acca02004-06-23 21:21:19 +000084 : MD4_SUM_LENGTH) == 0;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000085 }
86
Wayne Davisoncc1e9972004-06-23 16:51:21 +000087 if (size_only)
Wayne Davisoncc1e9972004-06-23 16:51:21 +000088 return 1;
89
Wayne Davison84acca02004-06-23 21:21:19 +000090 if (ignore_times)
91 return 0;
92
93 return cmp_modtime(st->st_mtime, file->modtime) == 0;
Andrew Tridgell2f03f951998-07-25 02:25:22 +000094}
95
96
Andrew Tridgell2f03f951998-07-25 02:25:22 +000097/*
Wayne Davison0e36d9d2004-01-03 19:28:03 +000098 * NULL sum_struct means we have no checksums
J.W. Schultz195bd902003-04-10 02:04:58 +000099 */
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000100void write_sum_head(int f, struct sum_struct *sum)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000101{
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000102 static struct sum_struct null_sum;
103
Wayne Davisonc3384602004-02-27 08:03:49 +0000104 if (sum == NULL)
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000105 sum = &null_sum;
106
107 write_int(f, sum->count);
108 write_int(f, sum->blength);
Wayne Davisond04e9c52003-09-09 15:58:48 +0000109 if (protocol_version >= 27)
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000110 write_int(f, sum->s2length);
111 write_int(f, sum->remainder);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000112}
113
Wayne Davisonec8290c2004-06-18 16:30:24 +0000114/*
J.W. Schultz195bd902003-04-10 02:04:58 +0000115 * set (initialize) the size entries in the per-file sum_struct
Wayne Davisonec8290c2004-06-18 16:30:24 +0000116 * calculating dynamic block and checksum sizes.
J.W. Schultz195bd902003-04-10 02:04:58 +0000117 *
Wayne Davisonec8290c2004-06-18 16:30:24 +0000118 * This is only called from generate_and_send_sums() but is a separate
J.W. Schultz195bd902003-04-10 02:04:58 +0000119 * function to encapsulate the logic.
120 *
121 * The block size is a rounded square root of file length.
122 *
123 * The checksum size is determined according to:
124 * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
125 * provided by Donovan Baarda which gives a probability of rsync
126 * algorithm corrupting data and falling back using the whole md4
127 * checksums.
128 *
129 * This might be made one of several selectable heuristics.
130 */
Martin Poolbceec822002-03-19 03:39:42 +0000131
Wayne Davison423dba82003-12-24 01:14:16 +0000132static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
J.W. Schultz195bd902003-04-10 02:04:58 +0000133{
Wayne Davisonda9d12f2004-01-03 18:37:41 +0000134 unsigned int blength;
135 int s2length;
J.W. Schultz195bd902003-04-10 02:04:58 +0000136 uint32 c;
137 uint64 l;
138
139 if (block_size) {
140 blength = block_size;
141 } else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
142 blength = BLOCK_SIZE;
143 } else {
144 l = len;
145 c = 1;
146 while (l >>= 2) {
147 c <<= 1;
148 }
149 blength = 0;
150 do {
151 blength |= c;
Wayne Davisonfb55e282003-08-22 05:42:13 +0000152 if (len < (uint64)blength * blength)
J.W. Schultz195bd902003-04-10 02:04:58 +0000153 blength &= ~c;
154 c >>= 1;
155 } while (c >= 8); /* round to multiple of 8 */
156 blength = MAX(blength, BLOCK_SIZE);
157 }
158
Wayne Davisond04e9c52003-09-09 15:58:48 +0000159 if (protocol_version < 27) {
J.W. Schultz195bd902003-04-10 02:04:58 +0000160 s2length = csum_length;
161 } else if (csum_length == SUM_LENGTH) {
162 s2length = SUM_LENGTH;
163 } else {
Wayne Davisonda9d12f2004-01-03 18:37:41 +0000164 int b = BLOCKSUM_BIAS;
J.W. Schultz195bd902003-04-10 02:04:58 +0000165 l = len;
166 while (l >>= 1) {
167 b += 2;
168 }
169 c = blength;
170 while (c >>= 1 && b) {
171 b--;
172 }
173 s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
174 * subtract rollsum,
175 * round up
176 * --optimize in compiler--
177 */
178 s2length = MAX(s2length, csum_length);
179 s2length = MIN(s2length, SUM_LENGTH);
180 }
181
182 sum->flength = len;
183 sum->blength = blength;
184 sum->s2length = s2length;
185 sum->count = (len + (blength - 1)) / blength;
186 sum->remainder = (len % blength);
187
188 if (sum->count && verbose > 2) {
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000189 rprintf(FINFO, "count=%.0f rem=%u blength=%u s2length=%d flength=%.0f\n",
190 (double)sum->count, sum->remainder, sum->blength,
Wayne Davisonda9d12f2004-01-03 18:37:41 +0000191 sum->s2length, (double)sum->flength);
J.W. Schultz195bd902003-04-10 02:04:58 +0000192 }
193}
Wayne Davison80605142002-07-31 21:20:07 +0000194
Martin Poolbceec822002-03-19 03:39:42 +0000195
Wayne Davison80605142002-07-31 21:20:07 +0000196/*
197 * Generate and send a stream of signatures/checksums that describe a buffer
Martin Poole66dfd12002-04-08 09:05:26 +0000198 *
Wayne Davison80605142002-07-31 21:20:07 +0000199 * Generate approximately one checksum every block_len bytes.
200 */
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000201static void generate_and_send_sums(int fd, OFF_T len, int f_out)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000202{
Wayne Davison80605142002-07-31 21:20:07 +0000203 size_t i;
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000204 struct map_struct *mapbuf;
Wayne Davison80605142002-07-31 21:20:07 +0000205 struct sum_struct sum;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000206 OFF_T offset = 0;
207
Wayne Davison423dba82003-12-24 01:14:16 +0000208 sum_sizes_sqroot(&sum, len);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000209
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000210 if (len > 0)
Wayne Davison96d910c2004-08-03 08:05:27 +0000211 mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength);
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000212 else
213 mapbuf = NULL;
214
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000215 write_sum_head(f_out, &sum);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000216
Wayne Davison80605142002-07-31 21:20:07 +0000217 for (i = 0; i < sum.count; i++) {
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000218 unsigned int n1 = MIN(len, sum.blength);
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000219 char *map = map_ptr(mapbuf, offset, n1);
Wayne Davison80605142002-07-31 21:20:07 +0000220 uint32 sum1 = get_checksum1(map, n1);
221 char sum2[SUM_LENGTH];
Martin Poole66dfd12002-04-08 09:05:26 +0000222
Wayne Davison80605142002-07-31 21:20:07 +0000223 get_checksum2(map, n1, sum2);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000224
Wayne Davison80605142002-07-31 21:20:07 +0000225 if (verbose > 3) {
Martin Poole66dfd12002-04-08 09:05:26 +0000226 rprintf(FINFO,
Wayne Davison0e36d9d2004-01-03 19:28:03 +0000227 "chunk[%.0f] offset=%.0f len=%u sum1=%08lx\n",
228 (double)i, (double)offset, n1,
229 (unsigned long)sum1);
Wayne Davison80605142002-07-31 21:20:07 +0000230 }
231 write_int(f_out, sum1);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000232 write_buf(f_out, sum2, sum.s2length);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000233 len -= n1;
234 offset += n1;
235 }
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000236
237 if (mapbuf)
238 unmap_file(mapbuf);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000239}
240
241
Martin Poolef1aa912000-11-10 03:17:08 +0000242
Wayne Davisonfd322ee2004-06-29 19:19:00 +0000243/*
Martin Pool420ef2c2002-04-08 08:02:08 +0000244 * Acts on file number @p i from @p flist, whose name is @p fname.
Martin Poolef1aa912000-11-10 03:17:08 +0000245 *
246 * First fixes up permissions, then generates checksums for the file.
247 *
Martin Pool420ef2c2002-04-08 08:02:08 +0000248 * @note This comment was added later by mbp who was trying to work it
249 * out. It might be wrong.
Wayne Davisonfd322ee2004-06-29 19:19:00 +0000250 */
251static void recv_generator(char *fname, struct file_struct *file, int i,
252 int f_out)
Wayne Davison2cda2562003-03-21 18:53:00 +0000253{
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000254 int fd;
Wayne Davison89f7eff2004-09-07 16:50:07 +0000255 STRUCT_STAT st, partial_st;
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000256 int statret, stat_errno;
Wayne Davison89f7eff2004-09-07 16:50:07 +0000257 char *fnamecmp, *partialptr = NULL;
David Dykstra375a4551998-10-26 21:42:38 +0000258 char fnamecmpbuf[MAXPATHLEN];
Andrew Tridgellf7632fc1998-11-02 00:52:01 +0000259
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000260 if (list_only)
261 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000262
263 if (verbose > 2)
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000264 rprintf(FINFO, "recv_generator(%s,%d)\n", safe_fname(fname), i);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000265
Wayne Davison97f9dca2004-05-18 00:14:10 +0000266 if (server_exclude_list.head
267 && check_exclude(&server_exclude_list, fname,
Wayne Davison3e35c342004-05-18 08:50:17 +0000268 S_ISDIR(file->mode)) < 0) {
269 if (verbose) {
270 rprintf(FINFO, "skipping server-excluded file \"%s\"\n",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000271 safe_fname(fname));
Wayne Davison3e35c342004-05-18 08:50:17 +0000272 }
Wayne Davison97f9dca2004-05-18 00:14:10 +0000273 return;
Wayne Davison3e35c342004-05-18 08:50:17 +0000274 }
Wayne Davison97f9dca2004-05-18 00:14:10 +0000275
Wayne Davison73f7af02004-08-05 18:18:36 +0000276 if (dry_run > 1) {
277 statret = -1;
278 stat_errno = ENOENT;
279 } else {
280 statret = link_stat(fname, &st,
281 keep_dirlinks && S_ISDIR(file->mode));
282 stat_errno = errno;
283 }
Martin Pool63787382001-12-14 02:16:20 +0000284
Wayne Davisona7260c42004-07-29 16:06:38 +0000285 if (only_existing && statret == -1 && stat_errno == ENOENT) {
Andrew Tridgell1347d512000-01-23 01:53:18 +0000286 /* we only want to update existing files */
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000287 if (verbose > 1) {
288 rprintf(FINFO, "not creating new file \"%s\"\n",
289 safe_fname(fname));
290 }
Andrew Tridgell1347d512000-01-23 01:53:18 +0000291 return;
292 }
293
Wayne Davisond9b4d262004-07-23 16:59:38 +0000294 if (statret == 0 && !preserve_perms
295 && S_ISDIR(st.st_mode) == S_ISDIR(file->mode)) {
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000296 /* if the file exists already and we aren't perserving
Wayne Davison2cda2562003-03-21 18:53:00 +0000297 * permissions then act as though the remote end sent
298 * us the file permissions we already have */
Wayne Davison67e78a82004-03-07 20:29:59 +0000299 file->mode = (file->mode & ~CHMOD_BITS)
300 | (st.st_mode & CHMOD_BITS);
Andrew Tridgell4df9f361999-10-31 04:28:03 +0000301 }
302
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000303 if (S_ISDIR(file->mode)) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000304 /* The file to be received is a directory, so we need
305 * to prepare appropriately. If there is already a
306 * file of that name and it is *not* a directory, then
307 * we need to delete it. If it doesn't exist, then
308 * recursively create it. */
309
Wayne Davisonec8290c2004-06-18 16:30:24 +0000310 if (dry_run)
311 return; /* TODO: causes inaccuracies -- fix */
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000312 if (statret == 0 && !S_ISDIR(st.st_mode)) {
David Dykstrac7c11a01999-03-11 22:17:42 +0000313 if (robust_unlink(fname) != 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000314 rsyserr(FERROR, errno,
315 "recv_generator: unlink %s to make room for directory",
316 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000317 return;
318 }
319 statret = -1;
320 }
321 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000322 if (!(relative_paths && errno == ENOENT
323 && create_directory_path(fname, orig_umask) == 0
324 && do_mkdir(fname, file->mode) == 0)) {
325 rsyserr(FERROR, errno,
326 "recv_generator: mkdir %s failed",
327 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000328 }
329 }
Wayne Davison716e73d2004-06-05 16:16:30 +0000330 /* f_out is set to -1 when doing final directory-permission
331 * and modification-time repair. */
332 if (set_perms(fname, file, statret ? NULL : &st, 0)
333 && verbose && f_out != -1)
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000334 rprintf(FINFO, "%s/\n", safe_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000335 return;
336 }
337
338 if (preserve_links && S_ISLNK(file->mode)) {
339#if SUPPORT_LINKS
340 char lnk[MAXPATHLEN];
341 int l;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000342
Wayne Davison728d0922004-01-11 07:28:45 +0000343 if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000344 if (verbose) {
Wayne Davisonea425412003-09-11 04:53:05 +0000345 rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
Wayne Davison728d0922004-01-11 07:28:45 +0000346 full_fname(fname), file->u.link);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000347 }
348 return;
349 }
350 if (statret == 0) {
351 l = readlink(fname,lnk,MAXPATHLEN-1);
352 if (l > 0) {
353 lnk[l] = 0;
Martin Pool85d4d142001-12-14 02:14:58 +0000354 /* A link already pointing to the
355 * right place -- no further action
356 * required. */
Wayne Davison728d0922004-01-11 07:28:45 +0000357 if (strcmp(lnk,file->u.link) == 0) {
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000358 set_perms(fname, file, &st,
359 PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000360 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 }
Wayne Davison728d0922004-01-11 07:28:45 +0000368 if (do_symlink(file->u.link,fname) != 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000369 rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000370 full_fname(fname), safe_fname(file->u.link));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000371 } else {
372 set_perms(fname,file,NULL,0);
373 if (verbose) {
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000374 rprintf(FINFO, "%s -> %s\n", safe_fname(fname),
375 safe_fname(file->u.link));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000376 }
377 }
378#endif
379 return;
380 }
381
382#ifdef HAVE_MKNOD
383 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
Wayne Davison2cda2562003-03-21 18:53:00 +0000384 if (statret != 0 ||
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000385 st.st_mode != file->mode ||
Wayne Davison3915fd72004-04-12 16:52:43 +0000386 st.st_rdev != file->u.rdev) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000387 delete_file(fname);
Wayne Davisond62bcc12004-05-15 19:31:10 +0000388 if (verbose > 2) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000389 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000390 safe_fname(fname),
391 (int)file->mode, (int)file->u.rdev);
Wayne Davisond62bcc12004-05-15 19:31:10 +0000392 }
Wayne Davison728d0922004-01-11 07:28:45 +0000393 if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000394 rsyserr(FERROR, errno, "mknod %s failed",
395 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000396 } else {
397 set_perms(fname,file,NULL,0);
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000398 if (verbose) {
399 rprintf(FINFO, "%s\n",
400 safe_fname(fname));
401 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000402 }
403 } else {
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000404 set_perms(fname, file, &st, PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000405 }
406 return;
407 }
408#endif
409
Wayne Davison6dff5992004-01-25 22:32:09 +0000410 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000411 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000412
413 if (!S_ISREG(file->mode)) {
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000414 rprintf(FINFO, "skipping non-regular file \"%s\"\n",
415 safe_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000416 return;
417 }
418
David Dykstra375a4551998-10-26 21:42:38 +0000419 fnamecmp = fname;
420
Wayne Davisonc3384602004-02-27 08:03:49 +0000421 if (statret == -1 && compare_dest != NULL) {
David Dykstra375a4551998-10-26 21:42:38 +0000422 /* try the file at compare_dest instead */
Wayne Davison248ed452004-01-20 05:09:36 +0000423 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000424 if (link_stat(fnamecmpbuf, &st, 0) == 0
425 && S_ISREG(st.st_mode)) {
David Dykstra59c95e42002-08-29 14:44:55 +0000426#if HAVE_LINK
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000427 if (link_dest && !dry_run) {
428 if (do_link(fnamecmpbuf, fname) < 0) {
429 if (verbose) {
430 rsyserr(FINFO, errno,
431 "link %s => %s",
432 fnamecmpbuf,
433 safe_fname(fname));
434 }
435 fnamecmp = fnamecmpbuf;
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000436 }
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000437 } else
David Dykstra59c95e42002-08-29 14:44:55 +0000438#endif
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000439 fnamecmp = fnamecmpbuf;
440 statret = 0;
441 }
442 }
443
444 if (statret == 0 && !S_ISREG(st.st_mode)) {
445 if (delete_file(fname) != 0)
446 return;
447 statret = -1;
448 stat_errno = ENOENT;
David Dykstra375a4551998-10-26 21:42:38 +0000449 }
450
Wayne Davison89f7eff2004-09-07 16:50:07 +0000451 if (partial_dir) {
452 if ((partialptr = partial_dir_fname(fname))
453 && link_stat(partialptr, &partial_st, 0) == 0
454 && S_ISREG(partial_st.st_mode)) {
455 if (statret == -1)
456 goto prepare_to_open;
457 } else
458 partialptr = NULL;
459 }
460
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000461 if (statret == -1) {
Wayne Davison6dff5992004-01-25 22:32:09 +0000462 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
463 return;
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000464 if (stat_errno == ENOENT) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000465 write_int(f_out,i);
Wayne Davison727b35f2004-07-21 23:59:25 +0000466 if (!dry_run && !read_batch)
Wayne Davisonec8290c2004-06-18 16:30:24 +0000467 write_sum_head(f_out, NULL);
Wayne Davisonea425412003-09-11 04:53:05 +0000468 } else if (verbose > 1) {
Wayne Davisone7d13fe2004-07-28 10:04:06 +0000469 rsyserr(FERROR, stat_errno,
470 "recv_generator: failed to stat %s",
Wayne Davisond62bcc12004-05-15 19:31:10 +0000471 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000472 }
473 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 Davison065a6052004-07-29 16:45:48 +0000489 if (skip_file(fnamecmp, 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 Davison89f7eff2004-09-07 16:50:07 +0000495prepare_to_open:
Wayne Davison727b35f2004-07-21 23:59:25 +0000496 if (dry_run || read_batch) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000497 write_int(f_out,i);
498 return;
499 }
500
Wayne Davisonf38bd4a2004-07-13 01:45:51 +0000501 if (whole_file > 0) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000502 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000503 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000504 return;
505 }
506
Wayne Davison89f7eff2004-09-07 16:50:07 +0000507 if (partialptr) {
508 st = partial_st;
509 fnamecmp = partialptr;
Wayne Davisona7260c42004-07-29 16:06:38 +0000510 }
511
Wayne Davison2cda2562003-03-21 18:53:00 +0000512 /* open the file */
Andrew Tridgell8c9fd201999-10-25 22:04:09 +0000513 fd = do_open(fnamecmp, O_RDONLY, 0);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000514
515 if (fd == -1) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000516 rsyserr(FERROR, errno, "failed to open %s, continuing",
517 full_fname(fnamecmp));
David Dykstra60be6ac2000-01-06 16:15:36 +0000518 /* pretend the file didn't exist */
Wayne Davison6dff5992004-01-25 22:32:09 +0000519 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
520 return;
David Dykstra60be6ac2000-01-06 16:15:36 +0000521 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000522 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000523 return;
524 }
525
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000526 if (verbose > 3) {
Wayne Davisonecc81fc2004-07-26 16:36:59 +0000527 rprintf(FINFO, "gen mapped %s of size %.0f\n",
528 safe_fname(fnamecmp), (double)st.st_size);
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000529 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000530
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000531 if (verbose > 2)
Wayne Davison80605142002-07-31 21:20:07 +0000532 rprintf(FINFO, "generating and sending sums for %d\n", i);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000533
534 write_int(f_out,i);
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000535 generate_and_send_sums(fd, st.st_size, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000536
537 close(fd);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000538}
539
540
Wayne Davison7daccb82004-07-12 20:42:48 +0000541void generate_files(int f_out, struct file_list *flist, char *local_name)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000542{
543 int i;
Wayne Davisone1f67412004-06-30 07:27:30 +0000544 int phase = 0;
Wayne Davison968c8032004-01-02 08:19:26 +0000545 char fbuf[MAXPATHLEN];
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000546
Wayne Davison45e08ed2004-01-27 08:02:31 +0000547 if (verbose > 2) {
548 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
549 (long)getpid(), flist->count);
550 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000551
Martin Pool3e7053a2002-04-08 08:06:18 +0000552 if (verbose >= 2) {
553 rprintf(FINFO,
Wayne Davisonf38bd4a2004-07-13 01:45:51 +0000554 whole_file > 0
Martin Pool3e7053a2002-04-08 08:06:18 +0000555 ? "delta-transmission disabled for local transfer or --whole-file\n"
556 : "delta transmission enabled\n");
557 }
Wayne Davison2cda2562003-03-21 18:53:00 +0000558
Andrew Tridgella57873b2001-09-09 04:42:09 +0000559 /* we expect to just sit around now, so don't exit on a
560 timeout. If we really get a timeout then the other process should
561 exit */
562 io_timeout = 0;
563
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000564 for (i = 0; i < flist->count; i++) {
565 struct file_struct *file = flist->files[i];
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000566 struct file_struct copy;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000567
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000568 if (!file->basename)
569 continue;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000570 /* we need to ensure that any directories we create have writeable
571 permissions initially so that we can create the files within
572 them. This is then fixed after the files are transferred */
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000573 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
574 copy = *file;
Wayne Davison2cda2562003-03-21 18:53:00 +0000575 /* XXX: Could this be causing a problem on SCO? Perhaps their
576 * handling of permissions is strange? */
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000577 copy.mode |= S_IWUSR; /* user write */
578 file = &copy;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000579 }
580
Wayne Davison3fef5362004-01-22 04:38:18 +0000581 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
Wayne Davison7daccb82004-07-12 20:42:48 +0000582 file, i, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000583 }
584
585 phase++;
586 csum_length = SUM_LENGTH;
Wayne Davisone1f67412004-06-30 07:27:30 +0000587 ignore_times = 1;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000588
589 if (verbose > 2)
590 rprintf(FINFO,"generate_files phase=%d\n",phase);
591
Wayne Davison7daccb82004-07-12 20:42:48 +0000592 write_int(f_out, -1);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000593
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000594 /* files can cycle through the system more than once
595 * to catch initial checksum errors */
Wayne Davisonb9b15fb2004-01-15 07:42:15 +0000596 while ((i = get_redo_num()) != -1) {
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000597 struct file_struct *file = flist->files[i];
Wayne Davison3fef5362004-01-22 04:38:18 +0000598 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
Wayne Davison7daccb82004-07-12 20:42:48 +0000599 file, i, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000600 }
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000601
602 phase++;
603 if (verbose > 2)
604 rprintf(FINFO,"generate_files phase=%d\n",phase);
605
Wayne Davison7daccb82004-07-12 20:42:48 +0000606 write_int(f_out, -1);
Wayne Davison6dff5992004-01-25 22:32:09 +0000607
608 if (preserve_hard_links)
609 do_hard_links();
610
611 /* now we need to fix any directory permissions that were
612 * modified during the transfer */
613 for (i = 0; i < flist->count; i++) {
614 struct file_struct *file = flist->files[i];
Wayne Davisonec8290c2004-06-18 16:30:24 +0000615 if (!file->basename || !S_ISDIR(file->mode))
616 continue;
Wayne Davison6dff5992004-01-25 22:32:09 +0000617 recv_generator(local_name ? local_name : f_name(file),
618 file, i, -1);
619 }
620
621 if (verbose > 2)
622 rprintf(FINFO,"generate_files finished\n");
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000623}