2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1999 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: util.c,v 1.17 2006/01/14 04:37:19 paddy_s Exp $
34 * Keep calling read() until we've read buflen's worth of data, or EOF,
37 * Returns the number of bytes read, 0 on EOF, or negative on error.
40 fullread(fd, vbuf, buflen)
45 ssize_t nread, tot = 0;
46 char *buf = vbuf; /* cast to char so we can ++ it */
49 nread = read(fd, buf, buflen);
51 if ((errno == EINTR) || (errno == EAGAIN))
53 return ((tot > 0) ? tot : -1);
67 * Keep calling write() until we've written buflen's worth of data,
70 * Returns the number of bytes written, or negative on error.
73 fullwrite(fd, vbuf, buflen)
78 ssize_t nwritten, tot = 0;
79 const char *buf = vbuf; /* cast to char so we can ++ it */
82 nwritten = write(fd, buf, buflen);
84 if ((errno == EINTR) || (errno == EAGAIN))
86 return ((tot > 0) ? tot : -1);
96 * Bind to a port in the given range. Takes a begin,end pair of port numbers.
98 * Returns negative on error (EGAIN if all ports are in use). Returns 0
102 bind_portrange(s, addrp, first_port, last_port, proto)
104 struct sockaddr_in *addrp;
105 int first_port, last_port;
109 const int num_ports = last_port - first_port + 1;
111 struct servent *servPort;
113 assert(first_port > 0 && first_port <= last_port && last_port < 65536);
116 * We pick a different starting port based on our pid and the current
117 * time to avoid always picking the same reserved port twice.
119 port = ((getpid() + time(0)) % num_ports) + first_port;
121 * Scan through the range, trying all available ports that are either
122 * not taken in /etc/services or registered for *amanda*. Wrap around
123 * if we don't happen to start at the beginning.
125 for (cnt = 0; cnt < num_ports; cnt++) {
126 servPort = getservbyport(htons(port), proto);
127 if((servPort == NULL) || strstr(servPort->s_name, "amanda")){
128 dbprintf(("%s: bind_portrange2: trying port=%d\n",
129 debug_prefix_time(NULL), port));
130 addrp->sin_port = htons(port);
131 if (bind(s, (struct sockaddr *)addrp, sizeof(*addrp)) >= 0)
134 * If the error was something other then port in use, stop.
136 if (errno != EADDRINUSE)
139 if (++port > last_port)
142 if (cnt == num_ports) {
143 dbprintf(("%s: bind_portrange: all ports between %d and %d busy\n",
144 debug_prefix_time(NULL),
148 } else if (last_port < IPPORT_RESERVED
150 && errno == EACCES) {
152 * Do not bother with an error message in this case because it
157 dbprintf(("%s: bind_portrange: port %d: %s\n",
158 debug_prefix_time(NULL),
167 * Construct a datestamp (YYYYMMDD) from a time_t.
170 construct_datestamp(t)
174 char datestamp[3*NUM_STR_SIZE];
178 when = time((time_t *)NULL);
182 tm = localtime(&when);
183 snprintf(datestamp, sizeof(datestamp),
184 "%04d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
185 return stralloc(datestamp);
189 * Construct a timestamp (YYYYMMDDHHMMSS) from a time_t.
192 construct_timestamp(t)
196 char timestamp[6*NUM_STR_SIZE];
200 when = time((time_t *)NULL);
204 tm = localtime(&when);
205 snprintf(timestamp, sizeof(timestamp),
206 "%04d%02d%02d%02d%02d%02d",
207 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
208 tm->tm_hour, tm->tm_min, tm->tm_sec);
209 return stralloc(timestamp);