A slight tweak to the conditionalized definition of SIGACTION().
[rsync/rsync.git] / cleanup.c
CommitLineData
ef1aa910 1/* -*- c-file-style: "linux" -*-
6e86c951 2
ef1aa910 3 Copyright (C) 1996-2000 by Andrew Tridgell
2f03f956 4 Copyright (C) Paul Mackerras 1996
e0fde757 5 Copyright (C) 2002 by Martin Pool
6e86c951 6
2f03f956
AT
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
6e86c951 11
2f03f956
AT
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
6e86c951 16
2f03f956
AT
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rsync.h"
23
6e86c951
WD
24extern int io_error;
25extern int keep_partial;
26extern int log_got_error;
d45898df 27extern char *partial_dir;
6e86c951 28
2b28968d
WD
29#if defined HAVE_SIGACTION && defined HAVE_SIGPROCMASK
30static struct sigaction sigact;
31#endif
32
9f639210
DD
33/**
34 * Close all open sockets and files, allowing a (somewhat) graceful
35 * shutdown() of socket connections. This eliminates the abortive
36 * TCP RST sent by a Winsock-based system when the close() occurs.
37 **/
18d6b679 38void close_all(void)
9f639210
DD
39{
40#ifdef SHUTDOWN_ALL_SOCKETS
41 int max_fd;
42 int fd;
43 int ret;
58fef0ac 44 STRUCT_STAT st;
9f639210
DD
45
46 max_fd = sysconf(_SC_OPEN_MAX) - 1;
47 for (fd = max_fd; fd >= 0; fd--) {
58fef0ac 48 if ((ret = do_fstat(fd, &st)) == 0) {
8186ae6b 49 if (is_a_socket(fd))
9f639210 50 ret = shutdown(fd, 2);
9f639210
DD
51 ret = close(fd);
52 }
53 }
54#endif
55}
56
e0fde757
MP
57/**
58 * @file cleanup.c
59 *
60 * Code for handling interrupted transfers. Depending on the @c
61 * --partial option, we may either delete the temporary file, or go
62 * ahead and overwrite the destination. This second behaviour only
63 * occurs if we've sent literal data and therefore hopefully made
64 * progress on the transfer.
65 **/
66
67/**
68 * Set to True once literal data has been sent across the link for the
69 * current file. (????)
70 *
71 * Handling the cleanup when a transfer is interrupted is tricky when
72 * --partial is selected. We need to ensure that the partial file is
73 * kept if any real data has been transferred.
74 **/
8186ae6b 75int cleanup_got_literal = 0;
2f03f956
AT
76
77static char *cleanup_fname;
78static char *cleanup_new_fname;
79static struct file_struct *cleanup_file;
b6609caf 80static int cleanup_fd_r, cleanup_fd_w;
65fc84b3 81static pid_t cleanup_pid = 0;
2f03f956 82
19b27a48 83pid_t cleanup_child_pid = -1;
ef1aa910 84
e0fde757 85/**
b0f451eb 86 * Eventually calls exit(), passing @p code, therefore does not return.
e0fde757
MP
87 *
88 * @param code one of the RERR_* codes from errcode.h.
89 **/
a9766ef1 90void _exit_cleanup(int code, const char *file, int line)
2f03f956 91{
9098bbf3 92 int ocode = code;
b765ec32
DD
93 static int inside_cleanup = 0;
94
aa2c47d8 95 if (inside_cleanup > 10) {
b765ec32
DD
96 /* prevent the occasional infinite recursion */
97 return;
98 }
aa2c47d8 99 inside_cleanup++;
2f03f956 100
2b28968d
WD
101 SIGACTION(SIGUSR1, SIG_IGN);
102 SIGACTION(SIGUSR2, SIG_IGN);
2f03f956 103
6e86c951
WD
104 if (verbose > 3) {
105 rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
45c49b52 106 code, file, line);
6e86c951 107 }
9098bbf3 108
19b27a48
AT
109 if (cleanup_child_pid != -1) {
110 int status;
ef1f6280
WD
111 if (wait_process(cleanup_child_pid, &status, WNOHANG)
112 == cleanup_child_pid) {
19b27a48 113 status = WEXITSTATUS(status);
8186ae6b
WD
114 if (status > code)
115 code = status;
19b27a48
AT
116 }
117 }
118
a7260c40
WD
119 if (cleanup_got_literal && cleanup_fname && keep_partial
120 && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
2f03f956
AT
121 char *fname = cleanup_fname;
122 cleanup_fname = NULL;
b6609caf
WD
123 if (cleanup_fd_r != -1)
124 close(cleanup_fd_r);
09e2bbce
WD
125 if (cleanup_fd_w != -1) {
126 flush_write_file(cleanup_fd_w);
b6609caf 127 close(cleanup_fd_w);
09e2bbce 128 }
12fa790e
WD
129 finish_transfer(cleanup_new_fname, fname, NULL,
130 cleanup_file, 0, !partial_dir);
2f03f956 131 }
ef732c3b 132 io_flush(FULL_FLUSH);
2f03f956
AT
133 if (cleanup_fname)
134 do_unlink(cleanup_fname);
8186ae6b 135 if (code)
2f03f956 136 kill_all(SIGUSR1);
65fc84b3 137 if (cleanup_pid && cleanup_pid == getpid()) {
27d3cdbc 138 char *pidf = lp_pid_file();
8186ae6b 139 if (pidf && *pidf)
27d3cdbc 140 unlink(lp_pid_file());
27d3cdbc 141 }
9b73d1c0 142
6e35c72f 143 if (code == 0) {
054abde2
WD
144 if (io_error & IOERR_DEL_LIMIT)
145 code = RERR_DEL_LIMIT;
146 if (io_error & IOERR_VANISHED)
6e35c72f 147 code = RERR_VANISHED;
054abde2
WD
148 if (io_error & IOERR_GENERAL || log_got_error)
149 code = RERR_PARTIAL;
ff81e809
AT
150 }
151
8186ae6b
WD
152 if (code)
153 log_exit(code, file, line);
19b27a48 154
6e86c951
WD
155 if (verbose > 2) {
156 rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
45c49b52 157 ocode, file, line, code);
6e86c951 158 }
9098bbf3 159
9f639210 160 close_all();
2f03f956
AT
161 exit(code);
162}
163
164void cleanup_disable(void)
165{
166 cleanup_fname = NULL;
167 cleanup_got_literal = 0;
168}
169
170
c6b81a98 171void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
b6609caf 172 int fd_r, int fd_w)
2f03f956 173{
3d7cc571 174 cleanup_fname = fname ? fnametmp : NULL;
2f03f956
AT
175 cleanup_new_fname = fname;
176 cleanup_file = file;
b6609caf
WD
177 cleanup_fd_r = fd_r;
178 cleanup_fd_w = fd_w;
2f03f956 179}
8638dd48 180
65fc84b3 181void cleanup_set_pid(pid_t pid)
8638dd48
DD
182{
183 cleanup_pid = pid;
184}