Some simple whitespace tweaks.
[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;
27
9f639210
DD
28/**
29 * Close all open sockets and files, allowing a (somewhat) graceful
30 * shutdown() of socket connections. This eliminates the abortive
31 * TCP RST sent by a Winsock-based system when the close() occurs.
32 **/
18d6b679 33void close_all(void)
9f639210
DD
34{
35#ifdef SHUTDOWN_ALL_SOCKETS
36 int max_fd;
37 int fd;
38 int ret;
39 struct stat st;
40
41 max_fd = sysconf(_SC_OPEN_MAX) - 1;
42 for (fd = max_fd; fd >= 0; fd--) {
43 ret = fstat(fd,&st);
44 if (fstat(fd,&st) == 0) {
45 if (is_a_socket(fd)) {
46 ret = shutdown(fd, 2);
47 }
48 ret = close(fd);
49 }
50 }
51#endif
52}
53
e0fde757
MP
54/**
55 * @file cleanup.c
56 *
57 * Code for handling interrupted transfers. Depending on the @c
58 * --partial option, we may either delete the temporary file, or go
59 * ahead and overwrite the destination. This second behaviour only
60 * occurs if we've sent literal data and therefore hopefully made
61 * progress on the transfer.
62 **/
63
64/**
65 * Set to True once literal data has been sent across the link for the
66 * current file. (????)
67 *
68 * Handling the cleanup when a transfer is interrupted is tricky when
69 * --partial is selected. We need to ensure that the partial file is
70 * kept if any real data has been transferred.
71 **/
2f03f956
AT
72int cleanup_got_literal=0;
73
74static char *cleanup_fname;
75static char *cleanup_new_fname;
76static struct file_struct *cleanup_file;
c6b81a98
AT
77static int cleanup_fd1, cleanup_fd2;
78static struct map_struct *cleanup_buf;
65fc84b3 79static pid_t cleanup_pid = 0;
2f03f956 80
19b27a48 81pid_t cleanup_child_pid = -1;
ef1aa910 82
e0fde757 83/**
b0f451eb 84 * Eventually calls exit(), passing @p code, therefore does not return.
e0fde757
MP
85 *
86 * @param code one of the RERR_* codes from errcode.h.
87 **/
a9766ef1 88void _exit_cleanup(int code, const char *file, int line)
2f03f956 89{
9098bbf3 90 int ocode = code;
b765ec32
DD
91 static int inside_cleanup = 0;
92
aa2c47d8 93 if (inside_cleanup > 10) {
b765ec32
DD
94 /* prevent the occasional infinite recursion */
95 return;
96 }
aa2c47d8 97 inside_cleanup++;
2f03f956
AT
98
99 signal(SIGUSR1, SIG_IGN);
8b35435f 100 signal(SIGUSR2, SIG_IGN);
2f03f956 101
6e86c951
WD
102 if (verbose > 3) {
103 rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
9098bbf3 104 code, file, line);
6e86c951 105 }
9098bbf3 106
19b27a48
AT
107 if (cleanup_child_pid != -1) {
108 int status;
109 if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
110 status = WEXITSTATUS(status);
111 if (status > code) code = status;
112 }
113 }
114
2f03f956
AT
115 if (cleanup_got_literal && cleanup_fname && keep_partial) {
116 char *fname = cleanup_fname;
117 cleanup_fname = NULL;
c6b81a98
AT
118 if (cleanup_buf) unmap_file(cleanup_buf);
119 if (cleanup_fd1 != -1) close(cleanup_fd1);
120 if (cleanup_fd2 != -1) close(cleanup_fd2);
6e86c951 121 finish_transfer(cleanup_new_fname, fname, cleanup_file, 0);
2f03f956 122 }
ef732c3b 123 io_flush(FULL_FLUSH);
2f03f956
AT
124 if (cleanup_fname)
125 do_unlink(cleanup_fname);
126 if (code) {
127 kill_all(SIGUSR1);
128 }
65fc84b3 129 if (cleanup_pid && cleanup_pid == getpid()) {
27d3cdbc
AT
130 char *pidf = lp_pid_file();
131 if (pidf && *pidf) {
132 unlink(lp_pid_file());
133 }
134 }
9b73d1c0 135
6e35c72f
WD
136 if (code == 0) {
137 if ((io_error & ~IOERR_VANISHED) || log_got_error)
138 code = RERR_PARTIAL;
139 else if (io_error)
140 code = RERR_VANISHED;
ff81e809
AT
141 }
142
19b27a48
AT
143 if (code) log_exit(code, file, line);
144
6e86c951
WD
145 if (verbose > 2) {
146 rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
9098bbf3 147 ocode, file, line, code);
6e86c951 148 }
9098bbf3 149
9f639210 150 close_all();
2f03f956
AT
151 exit(code);
152}
153
154void cleanup_disable(void)
155{
156 cleanup_fname = NULL;
157 cleanup_got_literal = 0;
158}
159
160
c6b81a98
AT
161void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
162 struct map_struct *buf, int fd1, int fd2)
2f03f956
AT
163{
164 cleanup_fname = fnametmp;
165 cleanup_new_fname = fname;
166 cleanup_file = file;
c6b81a98
AT
167 cleanup_buf = buf;
168 cleanup_fd1 = fd1;
169 cleanup_fd2 = fd2;
2f03f956 170}
8638dd48 171
65fc84b3 172void cleanup_set_pid(pid_t pid)
8638dd48
DD
173{
174 cleanup_pid = pid;
175}