blob: 33fcf2abee96b04336e3ef79e6f6dafe64afe3fe [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)
273 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
274
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",
280 fname);
281 }
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 Davison3e35c342004-05-18 08:50:17 +0000289 if (verbose > 1)
290 rprintf(FINFO, "not creating new file \"%s\"\n", fname);
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)
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;
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",
370 full_fname(fname), file->u.link);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000371 } else {
372 set_perms(fname,file,NULL,0);
373 if (verbose) {
Wayne Davison728d0922004-01-11 07:28:45 +0000374 rprintf(FINFO,"%s -> %s\n", fname,file->u.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 Davison3915fd72004-04-12 16:52:43 +0000385 st.st_rdev != file->u.rdev) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000386 delete_file(fname);
Wayne Davisond62bcc12004-05-15 19:31:10 +0000387 if (verbose > 2) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000388 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
Wayne Davison728d0922004-01-11 07:28:45 +0000389 fname,(int)file->mode,(int)file->u.rdev);
Wayne Davisond62bcc12004-05-15 19:31:10 +0000390 }
Wayne Davison728d0922004-01-11 07:28:45 +0000391 if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000392 rsyserr(FERROR, errno, "mknod %s failed",
393 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000394 } else {
395 set_perms(fname,file,NULL,0);
396 if (verbose)
397 rprintf(FINFO,"%s\n",fname);
398 }
399 } else {
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000400 set_perms(fname, file, &st, PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000401 }
402 return;
403 }
404#endif
405
Wayne Davison6dff5992004-01-25 22:32:09 +0000406 if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000407 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000408
409 if (!S_ISREG(file->mode)) {
David Dykstra1bbd10f2002-02-07 16:36:12 +0000410 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000411 return;
412 }
413
David Dykstra375a4551998-10-26 21:42:38 +0000414 fnamecmp = fname;
415
Wayne Davisonc3384602004-02-27 08:03:49 +0000416 if (statret == -1 && compare_dest != NULL) {
David Dykstra375a4551998-10-26 21:42:38 +0000417 /* try the file at compare_dest instead */
418 int saveerrno = errno;
Wayne Davison248ed452004-01-20 05:09:36 +0000419 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
Wayne Davison6218c7b2004-06-11 07:40:51 +0000420 statret = link_stat(fnamecmpbuf, &st, 0);
David Dykstra375a4551998-10-26 21:42:38 +0000421 if (!S_ISREG(st.st_mode))
422 statret = -1;
423 if (statret == -1)
424 errno = saveerrno;
David Dykstra59c95e42002-08-29 14:44:55 +0000425#if HAVE_LINK
426 else if (link_dest && !dry_run) {
427 if (do_link(fnamecmpbuf, fname) != 0) {
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000428 if (verbose > 0) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000429 rsyserr(FINFO, errno, "link %s => %s",
430 fnamecmpbuf, fname);
Wayne Davisone7bc9b62004-01-02 08:05:20 +0000431 }
David Dykstra59c95e42002-08-29 14:44:55 +0000432 }
433 fnamecmp = fnamecmpbuf;
434 }
435#endif
David Dykstra375a4551998-10-26 21:42:38 +0000436 else
437 fnamecmp = fnamecmpbuf;
438 }
439
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000440 if (statret == -1) {
Wayne Davison6dff5992004-01-25 22:32:09 +0000441 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
442 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000443 if (errno == ENOENT) {
444 write_int(f_out,i);
Wayne Davison727b35f2004-07-21 23:59:25 +0000445 if (!dry_run && !read_batch)
Wayne Davisonec8290c2004-06-18 16:30:24 +0000446 write_sum_head(f_out, NULL);
Wayne Davisonea425412003-09-11 04:53:05 +0000447 } else if (verbose > 1) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000448 rsyserr(FERROR, errno,
449 "recv_generator: failed to open %s",
450 full_fname(fname));
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000451 }
452 return;
453 }
454
455 if (!S_ISREG(st.st_mode)) {
456 if (delete_file(fname) != 0) {
457 return;
458 }
459
460 /* now pretend the file didn't exist */
Wayne Davison6dff5992004-01-25 22:32:09 +0000461 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
462 return;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000463 write_int(f_out,i);
Wayne Davison727b35f2004-07-21 23:59:25 +0000464 if (!dry_run && !read_batch)
Wayne Davisonec8290c2004-06-18 16:30:24 +0000465 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000466 return;
467 }
468
Wayne Davison2cda2562003-03-21 18:53:00 +0000469 if (opt_ignore_existing && fnamecmp == fname) {
Martin Pool3d6fead2002-01-25 10:42:23 +0000470 if (verbose > 1)
471 rprintf(FINFO,"%s exists\n",fname);
472 return;
Wayne Davison2cda2562003-03-21 18:53:00 +0000473 }
Martin Pool3d6fead2002-01-25 10:42:23 +0000474
Wayne Davisond3a43752004-06-29 16:22:54 +0000475 if (update_only && fnamecmp == fname
476 && cmp_modtime(st.st_mtime, file->modtime) > 0) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000477 if (verbose > 1)
478 rprintf(FINFO,"%s is newer\n",fname);
479 return;
480 }
481
Wayne Davison84acca02004-06-23 21:21:19 +0000482 if (skip_file(fname, file, &st)) {
David Dykstrabd4ed7f1999-04-02 18:24:27 +0000483 if (fnamecmp == fname)
Wayne Davisonc41b52c2004-05-13 06:55:01 +0000484 set_perms(fname, file, &st, PERMS_REPORT);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000485 return;
486 }
487
Wayne Davison727b35f2004-07-21 23:59:25 +0000488 if (dry_run || read_batch) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000489 write_int(f_out,i);
490 return;
491 }
492
Wayne Davisonf38bd4a2004-07-13 01:45:51 +0000493 if (whole_file > 0) {
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000494 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000495 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000496 return;
497 }
498
Wayne Davison2cda2562003-03-21 18:53:00 +0000499 /* open the file */
Andrew Tridgell8c9fd201999-10-25 22:04:09 +0000500 fd = do_open(fnamecmp, O_RDONLY, 0);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000501
502 if (fd == -1) {
Wayne Davisond62bcc12004-05-15 19:31:10 +0000503 rsyserr(FERROR, errno, "failed to open %s, continuing",
504 full_fname(fnamecmp));
David Dykstra60be6ac2000-01-06 16:15:36 +0000505 /* pretend the file didn't exist */
Wayne Davison6dff5992004-01-25 22:32:09 +0000506 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
507 return;
David Dykstra60be6ac2000-01-06 16:15:36 +0000508 write_int(f_out,i);
J.W. Schultzfc0257c2003-04-10 01:13:30 +0000509 write_sum_head(f_out, NULL);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000510 return;
511 }
512
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000513 if (verbose > 3) {
514 rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
515 (double)st.st_size);
516 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000517
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000518 if (verbose > 2)
Wayne Davison80605142002-07-31 21:20:07 +0000519 rprintf(FINFO, "generating and sending sums for %d\n", i);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000520
521 write_int(f_out,i);
Wayne Davison6e45e1d2004-07-20 21:35:55 +0000522 generate_and_send_sums(fd, st.st_size, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000523
524 close(fd);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000525}
526
527
Wayne Davison7daccb82004-07-12 20:42:48 +0000528void generate_files(int f_out, struct file_list *flist, char *local_name)
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000529{
530 int i;
Wayne Davisone1f67412004-06-30 07:27:30 +0000531 int phase = 0;
Wayne Davison968c8032004-01-02 08:19:26 +0000532 char fbuf[MAXPATHLEN];
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000533
Wayne Davison45e08ed2004-01-27 08:02:31 +0000534 if (verbose > 2) {
535 rprintf(FINFO, "generator starting pid=%ld count=%d\n",
536 (long)getpid(), flist->count);
537 }
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000538
Martin Pool3e7053a2002-04-08 08:06:18 +0000539 if (verbose >= 2) {
540 rprintf(FINFO,
Wayne Davisonf38bd4a2004-07-13 01:45:51 +0000541 whole_file > 0
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];
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000553 struct file_struct copy;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000554
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000555 if (!file->basename)
556 continue;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000557 /* we need to ensure that any directories we create have writeable
558 permissions initially so that we can create the files within
559 them. This is then fixed after the files are transferred */
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000560 if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
561 copy = *file;
Wayne Davison2cda2562003-03-21 18:53:00 +0000562 /* XXX: Could this be causing a problem on SCO? Perhaps their
563 * handling of permissions is strange? */
Wayne Davisondfd5ba62004-01-04 18:43:18 +0000564 copy.mode |= S_IWUSR; /* user write */
565 file = &copy;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000566 }
567
Wayne Davison3fef5362004-01-22 04:38:18 +0000568 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
Wayne Davison7daccb82004-07-12 20:42:48 +0000569 file, i, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000570 }
571
572 phase++;
573 csum_length = SUM_LENGTH;
Wayne Davisone1f67412004-06-30 07:27:30 +0000574 ignore_times = 1;
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000575
576 if (verbose > 2)
577 rprintf(FINFO,"generate_files phase=%d\n",phase);
578
Wayne Davison7daccb82004-07-12 20:42:48 +0000579 write_int(f_out, -1);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000580
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000581 /* files can cycle through the system more than once
582 * to catch initial checksum errors */
Wayne Davisonb9b15fb2004-01-15 07:42:15 +0000583 while ((i = get_redo_num()) != -1) {
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000584 struct file_struct *file = flist->files[i];
Wayne Davison3fef5362004-01-22 04:38:18 +0000585 recv_generator(local_name ? local_name : f_name_to(file, fbuf),
Wayne Davison7daccb82004-07-12 20:42:48 +0000586 file, i, f_out);
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000587 }
J.W. Schultzbc63ae32003-03-31 17:28:34 +0000588
589 phase++;
590 if (verbose > 2)
591 rprintf(FINFO,"generate_files phase=%d\n",phase);
592
Wayne Davison7daccb82004-07-12 20:42:48 +0000593 write_int(f_out, -1);
Wayne Davison6dff5992004-01-25 22:32:09 +0000594
595 if (preserve_hard_links)
596 do_hard_links();
597
598 /* now we need to fix any directory permissions that were
599 * modified during the transfer */
600 for (i = 0; i < flist->count; i++) {
601 struct file_struct *file = flist->files[i];
Wayne Davisonec8290c2004-06-18 16:30:24 +0000602 if (!file->basename || !S_ISDIR(file->mode))
603 continue;
Wayne Davison6dff5992004-01-25 22:32:09 +0000604 recv_generator(local_name ? local_name : f_name(file),
605 file, i, -1);
606 }
607
608 if (verbose > 2)
609 rprintf(FINFO,"generate_files finished\n");
Andrew Tridgell2f03f951998-07-25 02:25:22 +0000610}