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
;
38 extern int write_batch
;
39 extern struct stats stats
;
40 extern struct file_list
*the_file_list
;
41 extern char *log_format
;
47 * The sender gets checksums from the generator, calculates deltas,
48 * and transmits them to the receiver. The sender process runs on the
49 * machine holding the source files.
53 * Receive the checksums for a buffer
55 static struct sum_struct
*receive_sums(int f
)
61 if (!(s
= new(struct sum_struct
)))
62 out_of_memory("receive_sums");
69 rprintf(FINFO
, "count=%.0f n=%ld rem=%ld\n",
70 (double)s
->count
, (long)s
->blength
, (long)s
->remainder
);
76 if (!(s
->sums
= new_array(struct sum_buf
, s
->count
)))
77 out_of_memory("receive_sums");
79 for (i
= 0; i
< s
->count
; i
++) {
80 s
->sums
[i
].sum1
= read_int(f
);
81 read_buf(f
, s
->sums
[i
].sum2
, s
->s2length
);
83 s
->sums
[i
].offset
= offset
;
86 if (i
== s
->count
-1 && s
->remainder
!= 0)
87 s
->sums
[i
].len
= s
->remainder
;
89 s
->sums
[i
].len
= s
->blength
;
90 offset
+= s
->sums
[i
].len
;
94 "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
95 i
, s
->sums
[i
].len
, (double)s
->sums
[i
].offset
,
105 void successful_send(int ndx
)
107 char fname
[MAXPATHLEN
];
108 struct file_struct
*file
;
111 if (ndx
< 0 || ndx
>= the_file_list
->count
)
114 file
= the_file_list
->files
[ndx
];
115 /* The generator might tell us about symlinks we didn't send. */
116 if (!(file
->flags
& FLAG_SENT
) && !S_ISLNK(file
->mode
))
118 if (file
->dir
.root
) {
119 offset
= stringjoin(fname
, sizeof fname
,
120 file
->dir
.root
, "/", NULL
);
123 f_name_to(file
, fname
+ offset
);
124 if (remove_sent_files
&& do_unlink(fname
) == 0 && verbose
> 1) {
125 rprintf(FINFO
, "sender removed %s\n",
126 safe_fname(fname
+ offset
));
130 static void write_ndx_and_attrs(int f_out
, int ndx
, int iflags
,
131 uchar fnamecmp_type
, char *buf
, int len
)
133 write_int(f_out
, ndx
);
134 if (protocol_version
< 29)
136 write_shortint(f_out
, iflags
);
137 if (iflags
& ITEM_BASIS_TYPE_FOLLOWS
)
138 write_byte(f_out
, fnamecmp_type
);
139 if (iflags
& ITEM_XNAME_FOLLOWS
)
140 write_vstring(f_out
, buf
, len
);
143 /* This is also used by receive.c with f_out = -1. */
144 int read_item_attrs(int f_in
, int f_out
, int ndx
, uchar
*type_ptr
,
145 char *buf
, int *len_ptr
)
148 uchar fnamecmp_type
= FNAMECMP_FNAME
;
149 int iflags
= protocol_version
>= 29 ? read_shortint(f_in
)
150 : ITEM_TRANSFER
| ITEM_MISSING_DATA
;
152 /* Handle the new keep-alive (no-op) packet. */
153 if (ndx
== the_file_list
->count
&& iflags
== ITEM_IS_NEW
)
155 else if (ndx
< 0 || ndx
>= the_file_list
->count
) {
156 rprintf(FERROR
, "Invalid file index: %d (count=%d) [%s]\n",
157 ndx
, the_file_list
->count
, who_am_i());
158 exit_cleanup(RERR_PROTOCOL
);
159 } else if (iflags
== ITEM_IS_NEW
) {
160 rprintf(FERROR
, "Invalid itemized flag word: %x [%s]\n",
162 exit_cleanup(RERR_PROTOCOL
);
165 if (iflags
& ITEM_BASIS_TYPE_FOLLOWS
)
166 fnamecmp_type
= read_byte(f_in
);
167 *type_ptr
= fnamecmp_type
;
169 if (iflags
& ITEM_XNAME_FOLLOWS
) {
170 if ((len
= read_vstring(f_in
, buf
, MAXPATHLEN
)) < 0)
171 exit_cleanup(RERR_PROTOCOL
);
178 if (iflags
& ITEM_TRANSFER
) {
179 if (!S_ISREG(the_file_list
->files
[ndx
]->mode
)) {
181 "received request to transfer non-regular file: %d [%s]\n",
183 exit_cleanup(RERR_PROTOCOL
);
185 } else if (f_out
>= 0) {
186 write_ndx_and_attrs(f_out
, ndx
, iflags
,
187 fnamecmp_type
, buf
, len
);
193 void send_files(struct file_list
*flist
, int f_out
, int f_in
)
196 struct sum_struct
*s
;
197 struct map_struct
*mbuf
= NULL
;
199 char *fname2
, fname
[MAXPATHLEN
];
200 char xname
[MAXPATHLEN
];
203 struct file_struct
*file
;
204 int phase
= 0, max_phase
= protocol_version
>= 29 ? 2 : 1;
205 struct stats initial_stats
;
206 int save_make_backups
= make_backups
;
207 int itemizing
= am_daemon
? daemon_log_format_has_i
208 : !am_server
&& log_format_has_i
;
209 int f_xfer
= write_batch
< 0 ? batch_fd
: f_out
;
213 rprintf(FINFO
, "send_files starting\n");
220 if (++phase
> max_phase
)
222 csum_length
= SUM_LENGTH
;
224 rprintf(FINFO
, "send_files phase=%d\n", phase
);
225 write_int(f_out
, -1);
226 /* For inplace: redo phase turns off the backup
227 * flag so that we do a regular inplace send. */
232 iflags
= read_item_attrs(f_in
, f_out
, i
, &fnamecmp_type
,
234 if (iflags
== ITEM_IS_NEW
) /* no-op packet */
237 file
= flist
->files
[i
];
238 if (file
->dir
.root
) {
239 /* N.B. We're sure that this fits, so offset is OK. */
240 offset
= strlcpy(fname
, file
->dir
.root
, sizeof fname
);
241 if (!offset
|| fname
[offset
-1] != '/')
242 fname
[offset
++] = '/';
245 fname2
= f_name_to(file
, fname
+ offset
);
248 rprintf(FINFO
, "send_files(%d, %s)\n", i
, fname
);
250 if (!(iflags
& ITEM_TRANSFER
)) {
251 maybe_log_item(file
, iflags
, itemizing
, xname
);
256 "got transfer request in phase 2 [%s]\n",
258 exit_cleanup(RERR_PROTOCOL
);
261 updating_basis_file
= inplace
&& (protocol_version
>= 29
262 ? fnamecmp_type
== FNAMECMP_FNAME
: !make_backups
);
264 stats
.current_file_index
= i
;
265 stats
.num_transferred_files
++;
266 stats
.total_transferred_size
+= file
->length
;
268 if (!do_xfers
) { /* log the transfer */
269 if (!am_server
&& log_format
)
270 log_item(file
, &stats
, iflags
, NULL
);
271 write_ndx_and_attrs(f_out
, i
, iflags
, fnamecmp_type
,
276 initial_stats
= stats
;
278 if (!(s
= receive_sums(f_in
))) {
279 io_error
|= IOERR_GENERAL
;
280 rprintf(FERROR
, "receive_sums failed\n");
284 fd
= do_open(fname
, O_RDONLY
, 0);
286 if (errno
== ENOENT
) {
287 enum logcode c
= am_daemon
288 && protocol_version
< 28 ? FERROR
290 io_error
|= IOERR_VANISHED
;
291 rprintf(c
, "file has vanished: %s\n",
294 io_error
|= IOERR_GENERAL
;
295 rsyserr(FERROR
, errno
,
296 "send_files failed to open %s",
303 /* map the local file */
304 if (do_fstat(fd
, &st
) != 0) {
305 io_error
|= IOERR_GENERAL
;
306 rsyserr(FERROR
, errno
, "fstat failed");
313 int32 read_size
= MAX(s
->blength
* 3, MAX_MAP_SIZE
);
314 mbuf
= map_file(fd
, st
.st_size
, read_size
, s
->blength
);
319 rprintf(FINFO
, "send_files mapped %s of size %.0f\n",
320 safe_fname(fname
), (double)st
.st_size
);
323 write_ndx_and_attrs(f_out
, i
, iflags
, fnamecmp_type
,
325 write_sum_head(f_xfer
, s
);
328 rprintf(FINFO
, "calling match_sums %s\n",
332 if (log_before_transfer
)
333 log_item(file
, &initial_stats
, iflags
, NULL
);
334 else if (!am_server
&& verbose
&& do_progress
)
335 rprintf(FINFO
, "%s\n", safe_fname(fname2
));
337 set_compression(fname
);
339 match_sums(f_xfer
, s
, mbuf
, st
.st_size
);
341 end_progress(st
.st_size
);
343 if (!log_before_transfer
)
344 log_item(file
, &initial_stats
, iflags
, NULL
);
347 j
= unmap_file(mbuf
);
349 io_error
|= IOERR_GENERAL
;
351 "read errors mapping %s",
360 rprintf(FINFO
, "sender finished %s\n",
364 /* Flag that we actually sent this entry. */
365 file
->flags
|= FLAG_SENT
;
367 make_backups
= save_make_backups
;
370 rprintf(FINFO
, "send files finished\n");
374 write_int(f_out
, -1);