Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liblongpath-rsync
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liblongpath
liblongpath-rsync
Commits
f3d6d480
Commit
f3d6d480
authored
Dec 28, 2006
by
Wayne Davison
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Handle the new incremental-recursion mode.
parent
8ef246e0
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
524 additions
and
308 deletions
+524
-308
generator.c
generator.c
+242
-151
main.c
main.c
+55
-41
receiver.c
receiver.c
+59
-39
rsync.c
rsync.c
+87
-18
sender.c
sender.c
+81
-59
No files found.
generator.c
View file @
f3d6d480
This diff is collapsed.
Click to expand it.
main.c
View file @
f3d6d480
...
...
@@ -34,6 +34,7 @@ extern int am_server;
extern
int
am_sender
;
extern
int
am_generator
;
extern
int
am_daemon
;
extern
int
incremental
;
extern
int
blocking_io
;
extern
int
remove_source_files
;
extern
int
daemon_over_rsh
;
...
...
@@ -47,6 +48,7 @@ extern int copy_dirlinks;
extern
int
keep_dirlinks
;
extern
int
preserve_hard_links
;
extern
int
protocol_version
;
extern
int
file_total
;
extern
int
recurse
;
extern
int
relative_paths
;
extern
int
sanitize_paths
;
...
...
@@ -58,7 +60,6 @@ extern int whole_file;
extern
int
read_batch
;
extern
int
write_batch
;
extern
int
batch_fd
;
extern
int
batch_gen_fd
;
extern
int
filesfrom_fd
;
extern
pid_t
cleanup_child_pid
;
extern
struct
stats
stats
;
...
...
@@ -75,7 +76,7 @@ extern struct filter_list_struct server_filter_list;
int
local_server
=
0
;
int
new_root_dir
=
0
;
mode_t
orig_umask
=
0
;
struct
file_list
*
the_file_list
;
int
batch_gen_fd
=
-
1
;
/* There's probably never more than at most 2 outstanding child processes,
* but set it higher, just in case. */
...
...
@@ -476,7 +477,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if
(
verbose
>
2
)
{
rprintf
(
FINFO
,
"get_local_name count=%d %s
\n
"
,
f
list
->
count
,
NS
(
dest_path
));
f
ile_total
,
NS
(
dest_path
));
}
if
(
!
dest_path
||
list_only
)
...
...
@@ -493,14 +494,13 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
}
return
NULL
;
}
if
(
f
list
->
count
>
1
)
{
if
(
f
ile_total
>
1
)
{
rprintf
(
FERROR
,
"ERROR: destination must be a directory when"
" copying more than 1 file
\n
"
);
exit_cleanup
(
RERR_FILESELECT
);
}
/* Caution: flist->count could be 0! */
if
(
flist
->
count
==
1
&&
S_ISDIR
(
flist
->
files
[
0
]
->
mode
))
{
if
(
file_total
==
1
&&
S_ISDIR
(
flist
->
files
[
0
]
->
mode
))
{
rprintf
(
FERROR
,
"ERROR: cannot overwrite non-directory"
" with a directory
\n
"
);
...
...
@@ -518,7 +518,7 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
/* If we need a destination directory because the transfer is not
* of a single non-directory or the user has requested one via a
* destination path ending in a slash, create one and use mode 1. */
if
(
f
list
->
count
>
1
||
(
cp
&&
!
cp
[
1
]))
{
if
(
f
ile_total
>
1
||
(
cp
&&
!
cp
[
1
]))
{
/* Lop off the final slash (if any). */
if
(
cp
&&
!
cp
[
1
])
*
cp
=
'\0'
;
...
...
@@ -611,17 +611,15 @@ static void fix_basis_dirs(void)
/* This is only called by the sender. */
static
void
read_final_goodbye
(
int
f_in
,
int
f_out
)
{
int
i
;
int
i
,
iflags
,
xlen
;
uchar
fnamecmp_type
;
char
xname
[
MAXPATHLEN
];
if
(
protocol_version
<
29
)
i
=
read_int
(
f_in
);
else
{
while
((
i
=
read_int
(
f_in
))
==
the_file_list
->
count
&&
read_shortint
(
f_in
)
==
ITEM_IS_NEW
)
{
/* Forward the keep-alive (no-op) to the receiver. */
write_int
(
f_out
,
the_file_list
->
count
);
write_shortint
(
f_out
,
ITEM_IS_NEW
);
}
i
=
read_ndx_and_attrs
(
f_in
,
f_out
,
&
iflags
,
&
fnamecmp_type
,
xname
,
&
xlen
);
}
if
(
i
!=
NDX_DONE
)
{
...
...
@@ -673,12 +671,10 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
flist
=
send_file_list
(
f_out
,
argc
,
argv
);
if
(
!
flist
||
flist
->
count
==
0
)
exit_cleanup
(
0
);
the_file_list
=
flist
;
io_start_buffering_in
();
io_start_buffering_out
();
io_start_buffering_in
(
f_in
);
send_files
(
f
list
,
f_out
,
f_in
);
send_files
(
f
_in
,
f_out
);
io_flush
(
FULL_FLUSH
);
handle_stats
(
f_out
);
if
(
protocol_version
>=
24
)
...
...
@@ -688,7 +684,7 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
}
static
int
do_recv
(
int
f_in
,
int
f_out
,
struct
file_list
*
flist
,
char
*
local_name
)
static
int
do_recv
(
int
f_in
,
int
f_out
,
char
*
local_name
)
{
int
pid
;
int
exit_code
=
0
;
...
...
@@ -721,12 +717,13 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
close
(
f_out
);
/* we can't let two processes write to the socket at one time */
close_multiplexing
_out
();
io_end_multiplex
_out
();
/* set place to send errors */
set_msg_fd_out
(
error_pipe
[
1
]);
io_start_buffering_out
(
error_pipe
[
1
]);
recv_files
(
f_in
,
flist
,
local_name
);
recv_files
(
f_in
,
local_name
);
io_flush
(
FULL_FLUSH
);
handle_stats
(
f_in
);
...
...
@@ -736,11 +733,15 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
/* Handle any keep-alive packets from the post-processing work
* that the generator does. */
if
(
protocol_version
>=
29
)
{
int
iflags
,
xlen
;
uchar
fnamecmp_type
;
char
xname
[
MAXPATHLEN
];
kluge_around_eof
=
-
1
;
/* This should only get stopped via a USR2 signal. */
while
(
read_int
(
f_in
)
==
flist
->
count
&&
read_shortint
(
f_in
)
==
ITEM_IS_NEW
)
{}
read_ndx_and_attrs
(
f_in
,
-
1
,
&
iflags
,
&
fnamecmp_type
,
xname
,
&
xlen
);
rprintf
(
FERROR
,
"Invalid packet at end of run [%s]
\n
"
,
who_am_i
());
...
...
@@ -755,7 +756,8 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
}
am_generator
=
1
;
close_multiplexing_in
();
io_end_multiplex_in
();
if
(
write_batch
&&
!
am_server
)
stop_write_batch
();
...
...
@@ -763,11 +765,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
if
(
f_in
!=
f_out
)
close
(
f_in
);
io_start_buffering_out
();
io_start_buffering_out
(
f_out
);
set_msg_fd_in
(
error_pipe
[
0
]);
io_start_buffering_in
(
error_pipe
[
0
]);
generate_files
(
f_out
,
flist
,
local_name
);
generate_files
(
f_out
,
local_name
);
handle_stats
(
-
1
);
io_flush
(
FULL_FLUSH
);
...
...
@@ -783,7 +786,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
return
exit_code
;
}
static
void
do_server_recv
(
int
f_in
,
int
f_out
,
int
argc
,
char
*
argv
[])
static
void
do_server_recv
(
int
f_in
,
int
f_out
,
int
argc
,
char
*
argv
[])
{
int
exit_code
;
struct
file_list
*
flist
;
...
...
@@ -819,7 +822,10 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
}
io_start_buffering_in
();
if
(
protocol_version
>=
30
)
io_start_multiplex_in
();
else
io_start_buffering_in
(
f_in
);
recv_filter_list
(
f_in
);
if
(
filesfrom_fd
>=
0
)
{
...
...
@@ -833,12 +839,13 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
flist
=
recv_file_list
(
f_in
);
verbose
=
save_verbose
;
if
(
!
flist
)
{
rprintf
(
FERROR
,
"server_recv: recv_file_list error
\n
"
);
exit_cleanup
(
RERR_FILESELECT
);
}
the_file_list
=
flist
;
if
(
incremental
&&
file_total
==
1
)
recv_additional_file_list
(
f_in
);
verbose
=
save_verbose
;
if
(
argc
>
0
)
local_name
=
get_local_name
(
flist
,
argv
[
0
]);
...
...
@@ -873,7 +880,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
}
exit_code
=
do_recv
(
f_in
,
f_out
,
flist
,
local_name
);
exit_code
=
do_recv
(
f_in
,
f_out
,
local_name
);
exit_cleanup
(
exit_code
);
}
...
...
@@ -933,9 +940,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
setup_iconv
();
#endif
if
(
protocol_version
>=
23
&&
!
read_batch
)
io_start_multiplex_in
();
/* We set our stderr file handle to blocking because ssh might have
* set it to non-blocking. This can be particularly troublesome if
* stderr is a clone of stdout, because ssh would have set our stdout
...
...
@@ -948,7 +952,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if
(
am_sender
)
{
keep_dirlinks
=
0
;
/* Must be disabled on the sender. */
io_start_buffering_out
();
if
(
protocol_version
>=
30
)
io_start_multiplex_out
();
else
io_start_buffering_out
(
f_out
);
if
(
!
filesfrom_host
)
set_msg_fd_in
(
f_in
);
send_filter_list
(
f_out
);
...
...
@@ -961,10 +968,12 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
set_msg_fd_in
(
-
1
);
if
(
verbose
>
3
)
rprintf
(
FINFO
,
"file list sent
\n
"
);
the_file_list
=
flist
;
if
(
protocol_version
>=
23
)
io_start_multiplex_in
();
io_flush
(
NORMAL_FLUSH
);
send_files
(
f
list
,
f_out
,
f_in
);
send_files
(
f
_in
,
f_out
);
io_flush
(
FULL_FLUSH
);
handle_stats
(
-
1
);
if
(
protocol_version
>=
24
)
...
...
@@ -980,8 +989,12 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
exit_cleanup
(
exit_code
);
}
if
(
need_messages_from_generator
&&
!
read_batch
)
io_start_multiplex_out
();
if
(
!
read_batch
)
{
if
(
protocol_version
>=
23
)
io_start_multiplex_in
();
if
(
need_messages_from_generator
)
io_start_multiplex_out
();
}
if
(
argc
==
0
)
list_only
|=
1
;
...
...
@@ -996,14 +1009,15 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if
(
write_batch
&&
!
am_server
)
start_write_batch
(
f_in
);
flist
=
recv_file_list
(
f_in
);
the_file_list
=
flist
;
if
(
incremental
&&
file_total
==
1
)
recv_additional_file_list
(
f_in
);
if
(
flist
&&
flist
->
count
>
0
)
{
local_name
=
get_local_name
(
flist
,
argv
[
0
]);
fix_basis_dirs
();
exit_code2
=
do_recv
(
f_in
,
f_out
,
flist
,
local_name
);
exit_code2
=
do_recv
(
f_in
,
f_out
,
local_name
);
}
else
{
handle_stats
(
-
1
);
output_summary
();
...
...
receiver.c
View file @
f3d6d480
...
...
@@ -26,6 +26,7 @@ extern int verbose;
extern
int
do_xfers
;
extern
int
am_server
;
extern
int
do_progress
;
extern
int
incremental
;
extern
int
log_before_transfer
;
extern
int
stdout_format_has_i
;
extern
int
logfile_format_has_i
;
...
...
@@ -52,7 +53,7 @@ extern char *stdout_format;
extern
char
*
tmpdir
;
extern
char
*
partial_dir
;
extern
char
*
basis_dir
[];
extern
struct
file_list
*
the_file_
list
;
extern
struct
file_list
*
cur_flist
,
*
first_f
list
;
extern
struct
filter_list_struct
server_filter_list
;
static
struct
bitbag
*
delayed_bits
=
NULL
;
...
...
@@ -60,7 +61,6 @@ static int phase = 0;
/* We're either updating the basis file or an identical copy: */
static
int
updating_basis
;
/*
* get_tmpname() - create a tmp filename for a given filename
*
...
...
@@ -151,7 +151,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_init
(
checksum_seed
);
if
(
append_mode
)
{
if
(
append_mode
>
0
)
{
OFF_T
j
;
sum
.
flength
=
(
OFF_T
)
sum
.
count
*
sum
.
blength
;
if
(
sum
.
remainder
)
...
...
@@ -277,16 +277,16 @@ static void discard_receive_data(int f_in, OFF_T length)
receive_data
(
f_in
,
NULL
,
-
1
,
0
,
NULL
,
-
1
,
length
);
}
static
void
handle_delayed_updates
(
struct
file_list
*
flist
,
char
*
local_name
)
static
void
handle_delayed_updates
(
char
*
local_name
)
{
char
*
fname
,
*
partialptr
;
int
ndx
;
for
(
ndx
=
-
1
;
(
ndx
=
bitbag_next_bit
(
delayed_bits
,
ndx
))
>=
0
;
)
{
struct
file_struct
*
file
=
flist
->
files
[
ndx
];
struct
file_struct
*
file
=
cur_
flist
->
files
[
ndx
];
fname
=
local_name
?
local_name
:
f_name
(
file
,
NULL
);
if
((
partialptr
=
partial_dir_fname
(
fname
))
!=
NULL
)
{
if
(
make_backups
&&
!
make_backup
(
fname
))
if
(
make_backups
>
0
&&
!
make_backup
(
fname
))
continue
;
if
(
verbose
>
2
)
{
rprintf
(
FINFO
,
"renaming %s to %s
\n
"
,
...
...
@@ -308,28 +308,31 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
}
}
static
int
get_next_gen_ndx
(
int
batch_gen_
fd
,
int
next_gen_ndx
,
int
desired_ndx
)
static
int
get_next_gen_ndx
(
int
fd
,
int
next_gen_ndx
,
int
desired_ndx
)
{
while
(
next_gen_ndx
<
desired_ndx
)
{
if
(
next_gen_ndx
>=
0
)
{
rprintf
(
FINFO
,
"(No batched update for%s
\"
%s
\"
)
\n
"
,
phase
?
" resend of"
:
""
,
f_name
(
the_file_list
->
files
[
next_gen_ndx
],
NULL
));
f_name
(
cur_flist
->
files
[
next_gen_ndx
],
NULL
));
}
next_gen_ndx
=
read_int
(
fd
);
if
(
next_gen_ndx
==
-
1
)
{
if
(
incremental
)
next_gen_ndx
=
first_flist
->
prev
->
count
+
first_flist
->
prev
->
ndx_start
;
else
next_gen_ndx
=
cur_flist
->
count
;
}
next_gen_ndx
=
read_int
(
batch_gen_fd
);
if
(
next_gen_ndx
==
-
1
)
next_gen_ndx
=
the_file_list
->
count
;
}
return
next_gen_ndx
;
}
/**
* main routine for receiver process.
*
* Receiver process runs on the same host as the generator process. */
int
recv_files
(
int
f_in
,
struct
file_list
*
flist
,
char
*
local_name
)
int
recv_files
(
int
f_in
,
char
*
local_name
)
{
int
next_gen_ndx
=
-
1
;
int
fd1
,
fd2
;
...
...
@@ -343,53 +346,49 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
uchar
fnamecmp_type
;
struct
file_struct
*
file
;
struct
stats
initial_stats
;
int
save_make_backups
=
make_backups
;
int
itemizing
=
am_server
?
logfile_format_has_i
:
stdout_format_has_i
;
enum
logcode
log_code
=
log_before_transfer
?
FLOG
:
FINFO
;
int
max_phase
=
protocol_version
>=
29
?
2
:
1
;
int
ndx
,
recv_ok
;
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"recv_files(%d) starting
\n
"
,
flist
->
count
);
rprintf
(
FINFO
,
"recv_files(%d) starting
\n
"
,
cur_
flist
->
count
);
if
(
delay_updates
)
delayed_bits
=
bitbag_create
(
flist
->
count
);
delayed_bits
=
bitbag_create
(
cur_flist
->
count
+
1
);
updating_basis
=
inplace
;
while
(
1
)
{
cleanup_disable
();
ndx
=
read_int
(
f_in
);
/* This call also sets cur_flist. */
ndx
=
read_ndx_and_attrs
(
f_in
,
-
1
,
&
iflags
,
&
fnamecmp_type
,
xname
,
&
xlen
);
if
(
ndx
==
NDX_DONE
)
{
if
(
read_batch
)
{
get_next_gen_ndx
(
batch_gen_fd
,
next_gen_ndx
,
flist
->
count
);
if
(
incremental
&&
first_flist
)
{
flist_free
(
first_flist
);
if
(
first_flist
)
continue
;
}
if
(
read_batch
&&
cur_flist
)
{
int
high
=
incremental
?
first_flist
->
prev
->
count
+
first_flist
->
prev
->
ndx_start
:
cur_flist
->
count
;
get_next_gen_ndx
(
batch_gen_fd
,
next_gen_ndx
,
high
);
next_gen_ndx
=
-
1
;
}
if
(
++
phase
>
max_phase
)
break
;
csum_length
=
SUM_LENGTH
;
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"recv_files phase=%d
\n
"
,
phase
);
if
(
phase
==
2
&&
delay_updates
)
handle_delayed_updates
(
flist
,
local_name
);
handle_delayed_updates
(
local_name
);
send_msg
(
MSG_DONE
,
""
,
0
);
if
(
keep_partial
&&
!
partial_dir
)
make_backups
=
0
;
/* prevents double backup */
if
(
append_mode
)
{
append_mode
=
0
;
sparse_files
=
0
;
}
continue
;
}
iflags
=
read_item_attrs
(
f_in
,
-
1
,
ndx
,
&
fnamecmp_type
,
xname
,
&
xlen
);
if
(
iflags
==
ITEM_IS_NEW
)
/* no-op packet */
continue
;
file
=
flist
->
files
[
ndx
];
file
=
cur_flist
->
files
[
ndx
-
cur_flist
->
ndx_start
];
fname
=
local_name
?
local_name
:
f_name
(
file
,
fbuf
);
if
(
verbose
>
2
)
...
...
@@ -406,6 +405,24 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
exit_cleanup
(
RERR_PROTOCOL
);
}
if
(
file
->
flags
&
FLAG_FILE_SENT
)
{
if
(
csum_length
==
SHORT_SUM_LENGTH
)
{
if
(
keep_partial
&&
!
partial_dir
)
make_backups
=
-
make_backups
;
/* prevents double backup */
append_mode
=
-
append_mode
;
sparse_files
=
-
sparse_files
;
csum_length
=
SUM_LENGTH
;
}
}
else
{
if
(
csum_length
!=
SHORT_SUM_LENGTH
)
{
if
(
keep_partial
&&
!
partial_dir
)
make_backups
=
-
make_backups
;
append_mode
=
-
append_mode
;
sparse_files
=
-
sparse_files
;
csum_length
=
SHORT_SUM_LENGTH
;
}
}
stats
.
current_file_index
=
ndx
;
stats
.
num_transferred_files
++
;
stats
.
total_transferred_size
+=
F_LENGTH
(
file
);
...
...
@@ -483,7 +500,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
else
{
/* Reminder: --inplace && --partial-dir are never
* enabled at the same time. */
if
(
inplace
&&
make_backups
)
{
if
(
inplace
&&
make_backups
>
0
)
{
if
(
!
(
fnamecmp
=
get_backup_name
(
fname
)))
fnamecmp
=
fname
;
}
else
if
(
partial_dir
&&
partialptr
)
...
...
@@ -646,7 +663,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
cleanup_disable
();
if
(
recv_ok
>
0
)
{
if
(
remove_source_files
if
(
remove_source_files
||
incremental
||
(
preserve_hard_links
&&
F_IS_HLINKED
(
file
)))
send_msg_int
(
MSG_SUCCESS
,
ndx
);
}
else
if
(
!
recv_ok
)
{
...
...
@@ -670,14 +687,17 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
"%s: %s failed verification -- update %s%s.
\n
"
,
errstr
,
fname
,
keptstr
,
redostr
);
}
if
(
!
phase
)
if
(
!
phase
||
incremental
)
{
send_msg_int
(
MSG_REDO
,
ndx
);
file
->
flags
|=
FLAG_FILE_SENT
;
}
}
}
make_backups
=
save_make_backups
;
if
(
make_backups
<
0
)
make_backups
=
-
make_backups
;
if
(
phase
==
2
&&
delay_updates
)
/* for protocol_version < 29 */
handle_delayed_updates
(
flist
,
local_name
);
handle_delayed_updates
(
local_name
);
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"recv_files finished
\n
"
);
...
...
rsync.c
View file @
f3d6d480
...
...
@@ -45,12 +45,14 @@ extern int allow_8bit_chars;
extern
int
protocol_version
;
extern
int
preserve_uid
;
extern
int
preserve_gid
;
extern
int
incremental
;
extern
int
inplace
;
extern
int
flist_eof
;
extern
int
keep_dirlinks
;
extern
int
make_backups
;
extern
mode_t
orig_umask
;
extern
struct
stats
stats
;
extern
struct
file_list
*
the_file_
list
;
extern
struct
file_list
*
cur_flist
,
*
first_flist
,
*
dir_f
list
;
extern
struct
chmod_mode_struct
*
daemon_chmod_modes
;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
...
...
@@ -93,26 +95,72 @@ void setup_iconv()
/* This is used by sender.c with a valid f_out, and by receive.c with
* f_out = -1. */
int
read_
item_attrs
(
int
f_in
,
int
f_out
,
int
ndx
,
uchar
*
type
_ptr
,
char
*
buf
,
int
*
len_ptr
)
int
read_
ndx_and_attrs
(
int
f_in
,
int
f_out
,
int
*
iflag
_ptr
,
uchar
*
type_ptr
,
char
*
buf
,
int
*
len_ptr
)
{
int
len
;
int
len
,
iflags
=
0
;
struct
file_list
*
flist
;
uchar
fnamecmp_type
=
FNAMECMP_FNAME
;
int
iflags
=
protocol_version
>=
29
?
read_shortint
(
f_in
)
int
verbose_save
,
ndx
;
read_loop:
while
(
1
)
{
ndx
=
read_int
(
f_in
);
if
(
ndx
>=
0
)
break
;
if
(
ndx
==
NDX_DONE
)
return
ndx
;
if
(
!
incremental
||
am_sender
)
goto
invalid_ndx
;
if
(
ndx
==
NDX_FLIST_EOF
)
{
flist_eof
=
1
;
send_msg
(
MSG_FLIST_EOF
,
""
,
0
);
continue
;
}
ndx
=
NDX_FLIST_OFFSET
-
ndx
;
if
(
ndx
<
0
||
ndx
>=
dir_flist
->
count
)
{
ndx
=
NDX_FLIST_OFFSET
-
ndx
;
rprintf
(
FERROR
,
"Invalid dir index: %d (%d - %d)
\n
"
,
ndx
,
NDX_FLIST_OFFSET
,
NDX_FLIST_OFFSET
-
dir_flist
->
count
);
exit_cleanup
(
RERR_PROTOCOL
);
}
verbose_save
=
verbose
;
verbose
=
0
;
/* TODO allow verbose messages? */
/* Send everything read from f_in to msg_fd_out. */
send_msg_int
(
MSG_FLIST
,
ndx
);
start_flist_forward
(
f_in
);
flist
=
recv_file_list
(
f_in
);
flist
->
parent_ndx
=
ndx
;
stop_flist_forward
();
verbose
=
verbose_save
;
}
iflags
=
protocol_version
>=
29
?
read_shortint
(
f_in
)
:
ITEM_TRANSFER
|
ITEM_MISSING_DATA
;
/* Handle the new keep-alive (no-op) packet. */
if
(
ndx
==
the_file_list
->
count
&&
iflags
==
ITEM_IS_NEW
)
;
else
if
(
ndx
<
0
||
ndx
>=
the_file_list
->
count
)
{
rprintf
(
FERROR
,
"Invalid file index: %d (count=%d) [%s]
\n
"
,
ndx
,
the_file_list
->
count
,
who_am_i
());
exit_cleanup
(
RERR_PROTOCOL
);
}
else
if
(
iflags
==
ITEM_IS_NEW
)
{
rprintf
(
FERROR
,
"Invalid itemized flag word: %x [%s]
\n
"
,
iflags
,
who_am_i
());
/* Honor the old-style keep-alive indicator. */
if
(
protocol_version
<
30
&&
ndx
==
cur_flist
->
count
&&
iflags
==
ITEM_IS_NEW
)
{
if
(
am_sender
)
maybe_send_keepalive
();
goto
read_loop
;
}
if
(
!
(
flist
=
flist_for_ndx
(
ndx
)))
{
invalid_ndx:
rprintf
(
FERROR
,
"Invalid file index: %d (%d - %d) with iflags %x [%s]
\n
"
,
ndx
,
first_flist
->
ndx_start
+
first_flist
->
ndx_start
,
first_flist
->
prev
->
ndx_start
+
first_flist
->
ndx_start
+
first_flist
->
prev
->
count
-
1
,
iflags
,
who_am_i
());
exit_cleanup
(
RERR_PROTOCOL
);
}
cur_flist
=
flist
;
if
(
iflags
&
ITEM_BASIS_TYPE_FOLLOWS
)
fnamecmp_type
=
read_byte
(
f_in
);
...
...
@@ -128,7 +176,8 @@ int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
*
len_ptr
=
len
;
if
(
iflags
&
ITEM_TRANSFER
)
{
if
(
!
S_ISREG
(
the_file_list
->
files
[
ndx
]
->
mode
))
{
int
i
=
ndx
-
cur_flist
->
ndx_start
;
if
(
!
S_ISREG
(
cur_flist
->
files
[
i
]
->
mode
))
{
rprintf
(
FERROR
,
"received request to transfer non-regular file: %d [%s]
\n
"
,
ndx
,
who_am_i
());
...
...
@@ -139,7 +188,8 @@ int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
fnamecmp_type
,
buf
,
len
);
}
return
iflags
;
*
iflag_ptr
=
iflags
;
return
ndx
;
}
/*
...
...
@@ -314,7 +364,7 @@ void finish_transfer(char *fname, char *fnametmp, char *partialptr,
goto
do_set_file_attrs
;
}
if
(
make_backups
&&
overwriting_basis
&&
!
make_backup
(
fname
))
if
(
make_backups
>
0
&&
overwriting_basis
&&
!
make_backup
(
fname
))
return
;
/* Change permissions before putting the file into place. */
...
...
@@ -354,6 +404,25 @@ void finish_transfer(char *fname, char *fnametmp, char *partialptr,
}
}
struct
file_list
*
flist_for_ndx
(
int
ndx
)
{
struct
file_list
*
flist
=
cur_flist
;
if
(
!
flist
)
return
NULL
;
while
(
ndx
<
flist
->
ndx_start
)
{
if
(
flist
==
first_flist
)
return
NULL
;
flist
=
flist
->
prev
;
}
while
(
ndx
>=
flist
->
ndx_start
+
flist
->
count
)
{
if
(
!
(
flist
=
flist
->
next
))
return
NULL
;
}
return
flist
;
}
const
char
*
who_am_i
(
void
)
{
if
(
am_starting_up
)
...
...
sender.c
View file @
f3d6d480
...
...
@@ -26,6 +26,7 @@ extern int verbose;
extern
int
do_xfers
;
extern
int
am_server
;
extern
int
am_daemon
;
extern
int
incremental
;
extern
int
log_before_transfer
;
extern
int
stdout_format_has_i
;
extern
int
logfile_format_has_i
;
...
...
@@ -42,10 +43,9 @@ extern int inplace;
extern
int
batch_fd
;
extern
int
write_batch
;
extern
struct
stats
stats
;
extern
struct
file_list
*
the_file_
list
;
extern
struct
file_list
*
cur_flist
,
*
first_f
list
;
extern
char
*
stdout_format
;
/**
* @file
*
...
...
@@ -76,7 +76,7 @@ static struct sum_struct *receive_sums(int f)
(
double
)
s
->
count
,
(
long
)
s
->
blength
,
(
long
)
s
->
remainder
);
}
if
(
append_mode
)
{
if
(
append_mode
>
0
)
{
s
->
flength
=
(
OFF_T
)
s
->
count
*
s
->
blength
;
if
(
s
->
remainder
)
s
->
flength
-=
s
->
blength
-
s
->
remainder
;
...
...
@@ -122,25 +122,28 @@ void successful_send(int ndx)
{
char
fname
[
MAXPATHLEN
];
struct
file_struct
*
file
;
unsigned
int
offse
t
;
struct
file_list
*
flis
t
;
if
(
ndx
<
0
||
ndx
>=
the_file_list
->
count
)
if
(
!
remove_source_files
)
return
;
file
=
the_file_list
->
files
[
ndx
];
if
(
F_ROOTDIR
(
file
))
{
offset
=
stringjoin
(
fname
,
sizeof
fname
,
F_ROOTDIR
(
file
),
"/"
,
NULL
);
}
else
offset
=
0
;
f_name
(
file
,
fname
+
offset
);
if
(
remove_source_files
)
{
if
(
do_unlink
(
fname
)
==
0
)
{
if
(
verbose
>
1
)
rprintf
(
FINFO
,
"sender removed %s
\n
"
,
fname
+
offset
);
}
else
rsyserr
(
FERROR
,
errno
,
"sender failed to remove %s"
,
fname
+
offset
);
if
(
!
(
flist
=
flist_for_ndx
(
ndx
)))
{
rprintf
(
FERROR
,
"INTERNAL ERROR: unable to find flist for item %d
\n
"
,
ndx
);
return
;
}
file
=
flist
->
files
[
ndx
-
flist
->
ndx_start
];
if
(
!
push_flist_dir
(
F_ROOTDIR
(
file
),
-
1
))
return
;
f_name
(
file
,
fname
);
if
(
do_unlink
(
fname
)
==
0
)
{
if
(
verbose
>
1
)
rprintf
(
FINFO
,
"sender removed %s
\n
"
,
fname
);
}
else
rsyserr
(
FERROR
,
errno
,
"sender failed to remove %s"
,
fname
);
}
void
write_ndx_and_attrs
(
int
f_out
,
int
ndx
,
int
iflags
,
...
...
@@ -156,63 +159,63 @@ void write_ndx_and_attrs(int f_out, int ndx, int iflags,
write_vstring
(
f_out
,
buf
,
len
);
}
void
send_files
(
struct
file_list
*
flist
,
int
f_out
,
int
f_in
)
void
send_files
(
int
f_in
,
int
f_out
)
{
int
fd
=
-
1
;
struct
sum_struct
*
s
;
struct
map_struct
*
mbuf
=
NULL
;
STRUCT_STAT
st
;
char
*
fname2
,
f
name
[
MAXPATHLEN
];
c
har
xname
[
MAXPATHLEN
]
;
char
fname
[
MAXPATHLEN
],
x
name
[
MAXPATHLEN
];
c
onst
char
*
path
,
*
slash
;
uchar
fnamecmp_type
;
int
iflags
,
xlen
;
struct
file_struct
*
file
;
int
phase
=
0
,
max_phase
=
protocol_version
>=
29
?
2
:
1
;
struct
stats
initial_stats
;
int
save_make_backups
=
make_backups
;
int
itemizing
=
am_server
?
logfile_format_has_i
:
stdout_format_has_i
;
enum
logcode
log_code
=
log_before_transfer
?
FLOG
:
FINFO
;
int
f_xfer
=
write_batch
<
0
?
batch_fd
:
f_out
;
int
i
,
j
;
int
ndx
,
j
;
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"send_files starting
\n
"
);
while
(
1
)
{
unsigned
int
offset
;
i
=
read_int
(
f_in
);
if
(
i
==
NDX_DONE
)
{
if
(
incremental
)
send_extra_file_list
(
f_out
,
1000
);
/* This call also sets cur_flist. */
ndx
=
read_ndx_and_attrs
(
f_in
,
f_out
,
&
iflags
,
&
fnamecmp_type
,
xname
,
&
xlen
);
if
(
ndx
==
NDX_DONE
)
{
if
(
incremental
&&
first_flist
)
{
flist_free
(
first_flist
);
if
(
first_flist
)
{
write_int
(
f_out
,
NDX_DONE
);
continue
;
}
}
if
(
++
phase
>
max_phase
)
break
;
csum_length
=
SUM_LENGTH
;
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"send_files phase=%d
\n
"
,
phase
);
write_int
(
f_out
,
NDX_DONE
);
/* For inplace: redo phase turns off the backup
* flag so that we do a regular inplace send. */
make_backups
=
0
;
append_mode
=
0
;
continue
;
}
iflags
=
read_item_attrs
(
f_in
,
f_out
,
i
,
&
fnamecmp_type
,
xname
,
&
xlen
);
if
(
iflags
==
ITEM_IS_NEW
)
/* no-op packet */
continue
;
file
=
flist
->
files
[
i
];
file
=
cur_flist
->
files
[
ndx
-
cur_flist
->
ndx_start
];
if
(
F_ROOTDIR
(
file
))
{
/* N.B. We're sure that this fits, so offset is OK. */
offset
=
strlcpy
(
fname
,
F_ROOTDIR
(
file
),
sizeof
fname
);
if
(
!
offset
||
fname
[
offset
-
1
]
!=
'/'
)
fname
[
offset
++
]
=
'/'
;
}
else
offset
=
0
;
fname2
=
f_name
(
file
,
fname
+
offset
);
path
=
F_ROOTDIR
(
file
);
slash
=
"/"
;
}
else
{
path
=
slash
=
""
;
}
if
(
!
push_flist_dir
(
F_ROOTDIR
(
file
),
-
1
))
continue
;
f_name
(
file
,
fname
);
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"send_files(%d, %s
)
\n
"
,
i
,
fname
);
rprintf
(
FINFO
,
"send_files(%d, %s
%s%s)
\n
"
,
ndx
,
path
,
slash
,
fname
);
if
(
!
(
iflags
&
ITEM_TRANSFER
))
{
maybe_log_item
(
file
,
iflags
,
itemizing
,
xname
);
...
...
@@ -225,16 +228,32 @@ void send_files(struct file_list *flist, int f_out, int f_in)
exit_cleanup
(
RERR_PROTOCOL
);
}
if
(
file
->
flags
&
FLAG_FILE_SENT
)
{
if
(
csum_length
==
SHORT_SUM_LENGTH
)
{
/* For inplace: redo phase turns off the backup
* flag so that we do a regular inplace send. */
make_backups
=
-
make_backups
;
append_mode
=
-
append_mode
;
csum_length
=
SUM_LENGTH
;
}
}
else
{
if
(
csum_length
!=
SHORT_SUM_LENGTH
)
{
make_backups
=
-
make_backups
;
append_mode
=
-
append_mode
;
csum_length
=
SHORT_SUM_LENGTH
;
}
}
updating_basis_file
=
inplace
&&
(
protocol_version
>=
29
?
fnamecmp_type
==
FNAMECMP_FNAME
:
!
make_backups
);
?
fnamecmp_type
==
FNAMECMP_FNAME
:
make_backups
<=
0
);
stats
.
current_file_index
=
i
;
stats
.
current_file_index
=
ndx
;
stats
.
num_transferred_files
++
;
stats
.
total_transferred_size
+=
F_LENGTH
(
file
);
if
(
!
do_xfers
)
{
/* log the transfer */
log_item
(
FCLIENT
,
file
,
&
stats
,
iflags
,
NULL
);
write_ndx_and_attrs
(
f_out
,
i
,
iflags
,
fnamecmp_type
,
write_ndx_and_attrs
(
f_out
,
ndx
,
iflags
,
fnamecmp_type
,
xname
,
xlen
);
continue
;
}
...
...
@@ -244,7 +263,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
if
(
!
(
s
=
receive_sums
(
f_in
)))
{
io_error
|=
IOERR_GENERAL
;
rprintf
(
FERROR
,
"receive_sums failed
\n
"
);
return
;
exit_cleanup
(
RERR_PROTOCOL
)
;
}
fd
=
do_open
(
fname
,
O_RDONLY
,
0
);
...
...
@@ -263,6 +282,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
full_fname
(
fname
));
}
free_sums
(
s
);
if
(
protocol_version
>=
30
)
send_msg_int
(
MSG_NO_SEND
,
ndx
);
continue
;
}
...
...
@@ -272,7 +293,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
rsyserr
(
FERROR
,
errno
,
"fstat failed"
);
free_sums
(
s
);
close
(
fd
);
return
;
exit_cleanup
(
RERR_PROTOCOL
)
;
}
if
(
st
.
st_size
)
{
...
...
@@ -282,21 +303,21 @@ void send_files(struct file_list *flist, int f_out, int f_in)
mbuf
=
NULL
;
if
(
verbose
>
2
)
{
rprintf
(
FINFO
,
"send_files mapped %s of size %.0f
\n
"
,
fname
,
(
double
)
st
.
st_size
);
rprintf
(
FINFO
,
"send_files mapped %s
%s%s
of size %.0f
\n
"
,
path
,
slash
,
fname
,
(
double
)
st
.
st_size
);
}
write_ndx_and_attrs
(
f_out
,
i
,
iflags
,
fnamecmp_type
,
write_ndx_and_attrs
(
f_out
,
ndx
,
iflags
,
fnamecmp_type
,
xname
,
xlen
);
write_sum_head
(
f_xfer
,
s
);
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"calling match_sums %s
\n
"
,
fname
);
rprintf
(
FINFO
,
"calling match_sums %s
%s%s
\n
"
,
path
,
slash
,
fname
);
if
(
log_before_transfer
)
log_item
(
FCLIENT
,
file
,
&
initial_stats
,
iflags
,
NULL
);
else
if
(
!
am_server
&&
verbose
&&
do_progress
)
rprintf
(
FCLIENT
,
"%s
\n
"
,
fname
2
);
rprintf
(
FCLIENT
,
"%s
\n
"
,
fname
);
set_compression
(
fname
);
...
...
@@ -320,12 +341,13 @@ void send_files(struct file_list *flist, int f_out, int f_in)
free_sums
(
s
);
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"sender finished %s
\n
"
,
fname
);
rprintf
(
FINFO
,
"sender finished %s
%s%s
\n
"
,
path
,
slash
,
fname
);
/* Flag that we actually sent this entry. */
file
->
flags
|=
FLAG_SENT
;
file
->
flags
|=
FLAG_
FILE_
SENT
;
}
make_backups
=
save_make_backups
;
if
(
make_backups
<
0
)
make_backups
=
-
make_backups
;
if
(
verbose
>
2
)
rprintf
(
FINFO
,
"send files finished
\n
"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment