2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int log_before_transfer
;
27 extern int log_format_has_i
;
28 extern int daemon_log_format_has_i
;
29 extern int csum_length
;
31 extern int protocol_version
;
32 extern int remove_sent_files
;
33 extern int updating_basis_file
;
34 extern int make_backups
;
35 extern int do_progress
;
37 extern struct stats stats
;
38 extern struct file_list
*the_file_list
;
39 extern char *log_format
;
45 * The sender gets checksums from the generator, calculates deltas,
46 * and transmits them to the receiver. The sender process runs on the
47 * machine holding the source files.
51 * Receive the checksums for a buffer
53 static struct sum_struct
*receive_sums(int f
)
59 if (!(s
= new(struct sum_struct
)))
60 out_of_memory("receive_sums");
67 rprintf(FINFO
, "count=%.0f n=%ld rem=%ld\n",
68 (double)s
->count
, (long)s
->blength
, (long)s
->remainder
);
74 if (!(s
->sums
= new_array(struct sum_buf
, s
->count
)))
75 out_of_memory("receive_sums");
77 for (i
= 0; i
< s
->count
; i
++) {
78 s
->sums
[i
].sum1
= read_int(f
);
79 read_buf(f
, s
->sums
[i
].sum2
, s
->s2length
);
81 s
->sums
[i
].offset
= offset
;
84 if (i
== s
->count
-1 && s
->remainder
!= 0)
85 s
->sums
[i
].len
= s
->remainder
;
87 s
->sums
[i
].len
= s
->blength
;
88 offset
+= s
->sums
[i
].len
;
92 "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
93 i
, s
->sums
[i
].len
, (double)s
->sums
[i
].offset
,
103 void successful_send(int ndx
)
105 char fname
[MAXPATHLEN
];
106 struct file_struct
*file
;
109 if (ndx
< 0 || ndx
>= the_file_list
->count
)
112 file
= the_file_list
->files
[ndx
];
113 /* The generator might tell us about symlinks we didn't send. */
114 if (!(file
->flags
& FLAG_SENT
) && !S_ISLNK(file
->mode
))
116 if (file
->dir
.root
) {
117 offset
= stringjoin(fname
, sizeof fname
,
118 file
->dir
.root
, "/", NULL
);
121 f_name_to(file
, fname
+ offset
);
122 if (remove_sent_files
&& do_unlink(fname
) == 0 && verbose
> 1) {
123 rprintf(FINFO
, "sender removed %s\n",
124 safe_fname(fname
+ offset
));
128 static void write_ndx_and_attrs(int f_out
, int ndx
, int iflags
,
129 uchar fnamecmp_type
, char *buf
, int len
)
131 write_int(f_out
, ndx
);
132 if (protocol_version
< 29)
134 write_shortint(f_out
, iflags
);
135 if (iflags
& ITEM_BASIS_TYPE_FOLLOWS
)
136 write_byte(f_out
, fnamecmp_type
);
137 if (iflags
& ITEM_XNAME_FOLLOWS
)
138 write_vstring(f_out
, buf
, len
);
141 /* This is also used by receive.c with f_out = -1. */
142 int read_item_attrs(int f_in
, int f_out
, int ndx
, uchar
*type_ptr
,
143 char *buf
, int *len_ptr
)
146 uchar fnamecmp_type
= FNAMECMP_FNAME
;
147 int iflags
= protocol_version
>= 29 ? read_shortint(f_in
)
148 : ITEM_TRANSFER
| ITEM_MISSING_DATA
;
150 /* Handle the new keep-alive (no-op) packet. */
151 if (ndx
== the_file_list
->count
&& iflags
== ITEM_IS_NEW
)
153 else if (ndx
< 0 || ndx
>= the_file_list
->count
) {
154 rprintf(FERROR
, "Invalid file index: %d (count=%d) [%s]\n",
155 ndx
, the_file_list
->count
, who_am_i());
156 exit_cleanup(RERR_PROTOCOL
);
157 } else if (iflags
== ITEM_IS_NEW
) {
158 rprintf(FERROR
, "Invalid itemized flag word: %x [%s]\n",
160 exit_cleanup(RERR_PROTOCOL
);
163 if (iflags
& ITEM_BASIS_TYPE_FOLLOWS
)
164 fnamecmp_type
= read_byte(f_in
);
165 *type_ptr
= fnamecmp_type
;
167 if (iflags
& ITEM_XNAME_FOLLOWS
) {
168 if ((len
= read_vstring(f_in
, buf
, MAXPATHLEN
)) < 0)
169 exit_cleanup(RERR_PROTOCOL
);
176 /* Temporary handling of 2.6.4pre3 */
177 if (iflags
& ITEM_DUMMY_BIT
&& iflags
& (ITEM_LOCAL_CHANGE
|ITEM_TRANSFER
))
178 iflags
&= ~ITEM_DUMMY_BIT
;
180 if (iflags
& ITEM_TRANSFER
) {
181 if (!S_ISREG(the_file_list
->files
[ndx
]->mode
)) {
183 "received request to transfer non-regular file: %d [%s]\n",
185 exit_cleanup(RERR_PROTOCOL
);
187 } else if (f_out
>= 0) {
188 write_ndx_and_attrs(f_out
, ndx
, iflags
,
189 fnamecmp_type
, buf
, len
);
195 void send_files(struct file_list
*flist
, int f_out
, int f_in
)
198 struct sum_struct
*s
;
199 struct map_struct
*mbuf
= NULL
;
201 char *fname2
, fname
[MAXPATHLEN
];
202 char xname
[MAXPATHLEN
];
205 struct file_struct
*file
;
206 int phase
= 0, max_phase
= protocol_version
>= 29 ? 2 : 1;
207 struct stats initial_stats
;
208 int save_make_backups
= make_backups
;
209 int itemizing
= am_daemon
? daemon_log_format_has_i
210 : !am_server
&& log_format_has_i
;
214 rprintf(FINFO
, "send_files starting\n");
221 if (++phase
> max_phase
)
223 csum_length
= SUM_LENGTH
;
225 rprintf(FINFO
, "send_files phase=%d\n", phase
);
226 write_int(f_out
, -1);
227 /* For inplace: redo phase turns off the backup
228 * flag so that we do a regular inplace send. */
233 iflags
= read_item_attrs(f_in
, f_out
, i
, &fnamecmp_type
,
235 if (iflags
== ITEM_IS_NEW
) /* no-op packet */
238 file
= flist
->files
[i
];
239 if (file
->dir
.root
) {
240 /* N.B. We're sure that this fits, so offset is OK. */
241 offset
= strlcpy(fname
, file
->dir
.root
, sizeof fname
);
242 if (!offset
|| fname
[offset
-1] != '/')
243 fname
[offset
++] = '/';
246 fname2
= f_name_to(file
, fname
+ offset
);
249 rprintf(FINFO
, "send_files(%d, %s)\n", i
, fname
);
251 if (!(iflags
& ITEM_TRANSFER
)) {
252 maybe_log_item(file
, iflags
, itemizing
, xname
);
257 "got transfer request in phase 2 [%s]\n",
259 exit_cleanup(RERR_PROTOCOL
);
262 updating_basis_file
= inplace
&& (protocol_version
>= 29
263 ? fnamecmp_type
== FNAMECMP_FNAME
: !make_backups
);
265 stats
.current_file_index
= i
;
266 stats
.num_transferred_files
++;
267 stats
.total_transferred_size
+= file
->length
;
269 if (dry_run
) { /* log the transfer */
270 if (!am_server
&& log_format
)
271 log_item(file
, &stats
, iflags
, NULL
);
272 write_ndx_and_attrs(f_out
, i
, iflags
, fnamecmp_type
,
277 initial_stats
= stats
;
279 if (!(s
= receive_sums(f_in
))) {
280 io_error
|= IOERR_GENERAL
;
281 rprintf(FERROR
, "receive_sums failed\n");
285 fd
= do_open(fname
, O_RDONLY
, 0);
287 if (errno
== ENOENT
) {
288 enum logcode c
= am_daemon
289 && protocol_version
< 28 ? FERROR
291 io_error
|= IOERR_VANISHED
;
292 rprintf(c
, "file has vanished: %s\n",
295 io_error
|= IOERR_GENERAL
;
296 rsyserr(FERROR
, errno
,
297 "send_files failed to open %s",
304 /* map the local file */
305 if (do_fstat(fd
, &st
) != 0) {
306 io_error
|= IOERR_GENERAL
;
307 rsyserr(FERROR
, errno
, "fstat failed");
314 int32 read_size
= MAX(s
->blength
* 3, MAX_MAP_SIZE
);
315 mbuf
= map_file(fd
, st
.st_size
, read_size
, s
->blength
);
320 rprintf(FINFO
, "send_files mapped %s of size %.0f\n",
321 safe_fname(fname
), (double)st
.st_size
);
324 write_ndx_and_attrs(f_out
, i
, iflags
, fnamecmp_type
,
326 write_sum_head(f_out
, s
);
329 rprintf(FINFO
, "calling match_sums %s\n",
333 if (log_before_transfer
)
334 log_item(file
, &initial_stats
, iflags
, NULL
);
335 else if (!am_server
&& verbose
&& do_progress
)
336 rprintf(FINFO
, "%s\n", safe_fname(fname2
));
338 set_compression(fname
);
340 match_sums(f_out
, s
, mbuf
, st
.st_size
);
342 end_progress(st
.st_size
);
344 if (!log_before_transfer
)
345 log_item(file
, &initial_stats
, iflags
, NULL
);
348 j
= unmap_file(mbuf
);
350 io_error
|= IOERR_GENERAL
;
352 "read errors mapping %s",
361 rprintf(FINFO
, "sender finished %s\n",
365 /* Flag that we actually sent this entry. */
366 file
->flags
|= FLAG_SENT
;
368 make_backups
= save_make_backups
;
371 rprintf(FINFO
, "send files finished\n");
375 write_int(f_out
, -1);