2 Bacula® - The Network Backup Solution
4 Copyright (C) 2007-2007 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation plus additions
11 that are listed in the file LICENSE.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of John Walker.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Network Utility Routines
33 * Version $Id: bnet.c 3670 2006-11-21 16:13:58Z kerns $
41 #ifndef ENODATA /* not defined on BSD systems */
46 #define socketRead(fd, buf, len) ::recv(fd, buf, len, 0)
47 #define socketWrite(fd, buf, len) ::send(fd, buf, len, 0)
48 #define socketClose(fd) ::closesocket(fd)
50 #define socketRead(fd, buf, len) ::read(fd, buf, len)
51 #define socketWrite(fd, buf, len) ::write(fd, buf, len)
52 #define socketClose(fd) ::close(fd)
56 * Send a message over the network. The send consists of
57 * two network packets. The first is sends a 32 bit integer containing
58 * the length of the data packet which follows.
60 * Returns: false on failure
69 if (errors || terminated || msglen > 1000000) {
72 /* Compute total packet length */
74 pktsiz = sizeof(pktsiz); /* signal, no data */
76 pktsiz = msglen + sizeof(pktsiz); /* data */
78 /* Store packet length at head of message -- note, we
79 * have reserved an int32_t just before msg, so we can
82 hdr = (int32_t *)(msg - (int)sizeof(pktsiz));
83 *hdr = htonl(msglen); /* store signal/length */
85 out_msg_no++; /* increment message number */
87 /* send data packet */
88 timer_start = watchdog_time; /* start timer */
90 /* Full I/O done in one write */
91 rc = write_nbytes(this, (char *)hdr, pktsiz);
92 timer_start = 0; /* clear timer */
101 if (!suppress_error_msgs) {
102 Qmsg5(m_jcr, M_ERROR, 0,
103 _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"),
105 m_host, m_port, bnet_strerror(this));
108 Qmsg5(m_jcr, M_ERROR, 0,
109 _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
110 msglen, m_who, m_host, m_port, rc);
118 * Format and send a message
119 * Returns: false on error
122 bool BSOCK::fsend(const char *fmt, ...)
127 if (errors || terminated) {
130 /* This probably won't work, but we vsnprintf, then if we
131 * get a negative length or a length greater than our buffer
132 * (depending on which library is used), the printf was truncated, so
133 * get a bigger buffer and try again.
136 maxlen = sizeof_pool_memory(msg) - 1;
137 va_start(arg_ptr, fmt);
138 msglen = bvsnprintf(msg, maxlen, fmt, arg_ptr);
140 if (msglen > 0 && msglen < (maxlen - 5)) {
143 msg = realloc_pool_memory(msg, maxlen + maxlen / 2);
149 * Receive a message from the other end. Each message consists of
150 * two packets. The first is a header that contains the size
151 * of the data that follows in the second packet.
152 * Returns number of bytes read (may return zero)
153 * Returns -1 on signal (BNET_SIGNAL)
154 * Returns -2 on hard end of file (BNET_HARDEOF)
155 * Returns -3 on error (BNET_ERROR)
157 * Unfortunately, it is a bit complicated because we have these
160 * 2. Signal including end of data stream
161 * 3. Hard end of file
163 * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
165 int32_t BSOCK::recv()
172 if (errors || terminated) {
176 read_seqno++; /* bump sequence number */
177 timer_start = watchdog_time; /* set start wait time */
179 /* get data size -- in int32_t */
180 if ((nbytes = read_nbytes(this, (char *)&pktsiz, sizeof(int32_t))) <= 0) {
181 timer_start = 0; /* clear timer */
182 /* probably pipe broken because client died */
189 return BNET_HARDEOF; /* assume hard EOF received */
191 timer_start = 0; /* clear timer */
192 if (nbytes != sizeof(int32_t)) {
195 Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
196 sizeof(int32_t), nbytes, m_who, m_host, m_port);
200 pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
202 if (pktsiz == 0) { /* No data transferred */
203 timer_start = 0; /* clear timer */
206 return 0; /* zero bytes read */
209 /* If signal or packet size too big */
210 if (pktsiz < 0 || pktsiz > 1000000) {
211 if (pktsiz > 0) { /* if packet too big */
212 Qmsg3(m_jcr, M_FATAL, 0,
213 _("Packet size too big from \"%s:%s:%d. Terminating connection.\n"),
214 m_who, m_host, m_port);
215 pktsiz = BNET_TERMINATE; /* hang up */
217 if (pktsiz == BNET_TERMINATE) {
220 timer_start = 0; /* clear timer */
222 msglen = pktsiz; /* signal code */
223 return BNET_SIGNAL; /* signal */
226 /* Make sure the buffer is big enough + one byte for EOS */
227 if (pktsiz >= (int32_t) sizeof_pool_memory(msg)) {
228 msg = realloc_pool_memory(msg, pktsiz + 100);
231 timer_start = watchdog_time; /* set start wait time */
233 /* now read the actual data */
234 if ((nbytes = read_nbytes(this, msg, pktsiz)) <= 0) {
235 timer_start = 0; /* clear timer */
242 Qmsg4(m_jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
243 m_who, m_host, m_port, bnet_strerror(this));
246 timer_start = 0; /* clear timer */
249 if (nbytes != pktsiz) {
252 Qmsg5(m_jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"),
253 pktsiz, nbytes, m_who, m_host, m_port);
256 /* always add a zero by to properly terminate any
257 * string that was send to us. Note, we ensured above that the
258 * buffer is at least one byte longer than the message length.
260 msg[nbytes] = 0; /* terminate in case it is a string */
261 sm_check(__FILE__, __LINE__, false);
262 return nbytes; /* return actual length of message */
269 bool BSOCK::signal(int signal)
272 if (signal == BNET_TERMINATE) {
273 suppress_error_msgs = true;
279 * Despool spooled attributes
281 bool BSOCK::despool(void update_attr_spool_size(ssize_t size), ssize_t tsize)
285 ssize_t last = 0, size = 0;
290 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
291 posix_fadvise(fileno(spool_fd), 0, 0, POSIX_FADV_WILLNEED);
294 while (fread((char *)&pktsiz, 1, sizeof(int32_t), spool_fd) ==
296 size += sizeof(int32_t);
297 msglen = ntohl(pktsiz);
299 if (msglen > (int32_t) sizeof_pool_memory(msg)) {
300 msg = realloc_pool_memory(msg, msglen + 1);
302 nbytes = fread(msg, 1, msglen, spool_fd);
303 if (nbytes != (size_t) msglen) {
305 Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, msglen);
306 Qmsg1(jcr(), M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
308 update_attr_spool_size(tsize - last);
312 if ((++count & 0x3F) == 0) {
313 update_attr_spool_size(size - last);
319 update_attr_spool_size(tsize - last);
320 if (ferror(spool_fd)) {
322 Qmsg1(jcr(), M_FATAL, 0, _("fread attr spool error. ERR=%s\n"),
335 for (; bsock; bsock = next) {
336 next = bsock->m_next; /* get possible pointer to next before destoryed */
339 /* Shutdown tls cleanly. */
341 tls_bsock_shutdown(bsock);
342 free_tls_connection(bsock->tls);
345 #endif /* HAVE_TLS */
346 if (bsock->timed_out) {
347 shutdown(bsock->fd, 2); /* discard any pending I/O */
349 socketClose(bsock->fd); /* normal close */
351 destroy(); /* free the packet */
356 void BSOCK::destroy()
359 free_pool_memory(msg);
362 ASSERT(1 == 0); /* double close */
365 free_pool_memory(errmsg);