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.42 2006/08/24 01:57:15 paddy_s Exp $
35 /*#define NET_READ_DEBUG*/
38 #define netprintf(x) dbprintf(x)
43 static int make_socket(sa_family_t family);
44 static int connect_port(struct sockaddr_storage *addrp, in_port_t port, char *proto,
45 struct sockaddr_storage *svaddr, int nonblock);
48 * Keep calling read() until we've read buflen's worth of data, or EOF,
51 * Returns the number of bytes read, 0 on EOF, or negative on error.
59 ssize_t nread, tot = 0;
60 char *buf = vbuf; /* cast to char so we can ++ it */
63 nread = read(fd, buf, buflen);
65 if ((errno == EINTR) || (errno == EAGAIN))
67 return ((tot > 0) ? tot : -1);
81 * Keep calling write() until we've written buflen's worth of data,
84 * Returns the number of bytes written, or negative on error.
92 ssize_t nwritten, tot = 0;
93 const char *buf = vbuf; /* cast to char so we can ++ it */
96 nwritten = write(fd, buf, buflen);
98 if ((errno == EINTR) || (errno == EAGAIN))
100 return ((tot > 0) ? tot : -1);
115 #if defined(SO_KEEPALIVE) || defined(USE_REUSEADDR)
120 s = socket(family, SOCK_STREAM, 0);
123 dbprintf(("%s: make_socket: socket() failed: %s\n",
124 debug_prefix_time(NULL),
125 strerror(save_errno)));
129 if (s < 0 || s >= (int)FD_SETSIZE) {
131 errno = EMFILE; /* out of range */
136 r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
139 dbprintf(("%s: stream_server: setsockopt(SO_REUSEADDR) failed: %s\n",
140 debug_prefix_time(NULL),
147 r = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
148 (void *)&on, SIZEOF(on));
151 dbprintf(("%s: make_socket: setsockopt() failed: %s\n",
152 debug_prefix_time(NULL),
153 strerror(save_errno)));
163 /* addrp is my address */
164 /* svaddr is the address of the remote machine */
165 /* return socket on success */
166 /* return -1 on failure */
169 struct sockaddr_storage *addrp,
170 in_port_t first_port,
173 struct sockaddr_storage *svaddr,
178 static in_port_t port_in_use[1024];
179 static int nb_port_in_use = 0;
182 assert(first_port <= last_port);
183 /* Try a port already used */
184 for(i=0; i < nb_port_in_use; i++) {
185 port = port_in_use[i];
186 if(port >= first_port && port <= last_port) {
187 s = connect_port(addrp, port, proto, svaddr, nonblock);
188 if(s == -2) return -1;
195 /* Try a port in the range */
196 for (port = first_port; port <= last_port; port++) {
197 s = connect_port(addrp, port, proto, svaddr, nonblock);
198 if(s == -2) return -1;
200 port_in_use[nb_port_in_use++] = port;
205 dbprintf(("%s: connect_portrange: all ports between %d and %d busy\n",
206 debug_prefix_time(NULL),
213 /* addrp is my address */
214 /* svaddr is the address of the remote machine */
215 /* return -2: Don't try again */
216 /* return -1: Try with another port */
217 /* return >0: this is the connected socket */
220 struct sockaddr_storage *addrp,
223 struct sockaddr_storage *svaddr,
227 struct servent * servPort;
232 servPort = getservbyport((int)htons(port), proto);
233 if (servPort != NULL && !strstr(servPort->s_name, "amanda")) {
234 dbprintf(("%s: connect_port: Skip port %d: Owned by %s.\n",
235 debug_prefix_time(NULL), port, servPort->s_name));
240 dbprintf(("%s: connect_port: Try port %d: Available - \n",
241 debug_prefix_time(NULL), port));
243 dbprintf(("%s: connect_port: Try port %d: Owned by %s - \n",
244 debug_prefix_time(NULL), port, servPort->s_name));
247 if ((s = make_socket(addrp->ss_family)) == -1) return -2;
249 SS_SET_PORT(addrp, port);
250 socklen = SS_LEN(addrp);
251 if (bind(s, (struct sockaddr *)addrp, socklen) != 0) {
254 if (save_errno != EADDRINUSE) {
255 dbprintf(("errno %d strerror %s\n",
256 errno, strerror(errno)));
264 /* find out what port was actually used */
266 len = sizeof(*addrp);
267 if (getsockname(s, (struct sockaddr *)addrp, &len) == -1) {
269 dbprintf(("%s: connect_port: getsockname() failed: %s\n",
270 debug_prefix_time(NULL),
271 strerror(save_errno)));
278 fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0)|O_NONBLOCK);
279 if (connect(s, (struct sockaddr *)svaddr, SS_LEN(svaddr)) == -1 && !nonblock) {
281 dbprintf(("%s: connect_portrange: connect from %s failed: %s\n",
282 debug_prefix_time(NULL),
284 strerror(save_errno)));
285 dbprintf(("%s: connect_portrange: connect to %s failed: %s\n",
286 debug_prefix_time(NULL),
287 str_sockaddr(svaddr),
288 strerror(save_errno)));
291 if (save_errno == ECONNREFUSED ||
292 save_errno == EHOSTUNREACH ||
293 save_errno == ENETUNREACH ||
294 save_errno == ETIMEDOUT) {
300 dbprintf(("%s: connected to %s\n",
301 debug_prefix_time(NULL),
302 str_sockaddr(svaddr)));
303 dbprintf(("%s: our side is %s\n",
304 debug_prefix_time(NULL),
305 str_sockaddr(addrp)));
311 * Bind to a port in the given range. Takes a begin,end pair of port numbers.
313 * Returns negative on error (EGAIN if all ports are in use). Returns 0
319 struct sockaddr_storage *addrp,
320 in_port_t first_port,
327 struct servent *servPort;
328 const in_port_t num_ports = (in_port_t)(last_port - first_port + 1);
330 assert(first_port <= last_port);
333 * We pick a different starting port based on our pid and the current
334 * time to avoid always picking the same reserved port twice.
336 port = (in_port_t)(((getpid() + time(0)) % num_ports) + first_port);
339 * Scan through the range, trying all available ports that are either
340 * not taken in /etc/services or registered for *amanda*. Wrap around
341 * if we don't happen to start at the beginning.
343 for (cnt = 0; cnt < num_ports; cnt++) {
344 servPort = getservbyport((int)htons(port), proto);
345 if ((servPort == NULL) || strstr(servPort->s_name, "amanda")) {
346 if (servPort == NULL) {
347 dbprintf(("%s: bind_portrange2: Try port %d: Available - ",
348 debug_prefix_time(NULL), port));
350 dbprintf(("%s: bind_portrange2: Try port %d: Owned by %s - ",
351 debug_prefix_time(NULL), port, servPort->s_name));
353 SS_SET_PORT(addrp, port);
354 socklen = SS_LEN(addrp);
355 if (bind(s, (struct sockaddr *)addrp, socklen) >= 0) {
356 dbprintf(("Success\n"));
359 dbprintf(("%s\n", strerror(errno)));
361 dbprintf(("%s: bind_portrange2: Skip port %d: Owned by %s.\n",
362 debug_prefix_time(NULL), port, servPort->s_name));
364 if (++port > last_port)
367 dbprintf(("%s: bind_portrange: all ports between %d and %d busy\n",
368 debug_prefix_time(NULL),
376 * Construct a datestamp (YYYYMMDD) from a time_t.
383 char datestamp[3 * NUM_STR_SIZE];
387 when = time((time_t *)NULL);
391 tm = localtime(&when);
393 return stralloc("19000101");
395 snprintf(datestamp, SIZEOF(datestamp),
396 "%04d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
397 return stralloc(datestamp);
401 * Construct a timestamp (YYYYMMDDHHMMSS) from a time_t.
408 char timestamp[6 * NUM_STR_SIZE];
412 when = time((time_t *)NULL);
416 tm = localtime(&when);
418 return stralloc("19000101000000");
420 snprintf(timestamp, SIZEOF(timestamp),
421 "%04d%02d%02d%02d%02d%02d",
422 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
423 tm->tm_hour, tm->tm_min, tm->tm_sec);
424 return stralloc(timestamp);
432 return (match("[ \t\f\r\n\"]", str) != 0);
437 * For backward compatibility we are trying for minimal quoting.
438 * We only quote a string if it contains whitespace or is misquoted...
448 if ((str == NULL) || (*str == '\0')) {
449 ret = stralloc("\"\"");
450 } else if ((match("[\\\"[:space:][:cntrl:]]", str)) == 0) {
452 * String does not need to be quoted since it contains
453 * neither whitespace, control or quote characters.
458 * Allocate maximum possible string length.
459 * (a string of all quotes plus room for leading ", trailing " and NULL)
461 ret = s = alloc((strlen(str) * 2) + 2 + 1);
463 while (*str != '\0') {
469 } else if (*str == '\n') {
474 } else if (*str == '\r') {
479 } else if (*str == '\f') {
484 } else if (*str == '\\') {
507 if ((str == NULL) || (*str == '\0')) {
513 ret = in = out = stralloc(str);
514 while (*in != '\0') {
526 } else if (*in == 't') {
530 } else if (*in == 'r') {
534 } else if (*in == 'f') {
554 if ((str == NULL) || (*str == '\0')) {
558 for (s = ret; *s != '\0'; s++) {
569 char * tok = strtok(NULL, " ");
571 if ((tok != NULL) && (tok[0] == '"')) {
577 t = strtok(NULL, " ");
580 } while ((t != NULL) &&
581 (tok[len - 1] != '"') && (tok[len - 2] != '\\'));
593 FILE *stream = popen("od -c -x -", "w");
595 if (stream != NULL) {
597 rc = (ssize_t)fwrite(buffer, len, 1, stream);
606 Return 0 if the following characters are present
607 * ( ) < > [ ] , ; : ! $ \ / "
615 return !match("\\*|<|>|\\(|\\)|\\[|\\]|,|;|:|\\\\|/|\"|\\!|\\$|\\|", mailto);
621 struct sockaddr_storage *sa)
624 char ipstr[INET6_ADDRSTRLEN];
626 char ipstr[INET_ADDRSTRLEN];
630 port = SS_GET_PORT(sa);
632 if ( sa->ss_family == (sa_family_t)AF_INET6) {
633 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
634 ipstr, sizeof(ipstr));
635 dbprintf(("%s: (sockaddr_in6 *)%p = { %d, %d, %s }\n",
636 debug_prefix_time(NULL), sa,
637 ((struct sockaddr_in6 *)sa)->sin6_family,
643 inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, ipstr,
645 dbprintf(("%s: (sockaddr_in *)%p = { %d, %d, %s }\n",
646 debug_prefix_time(NULL), sa,
647 ((struct sockaddr_in *)sa)->sin_family,
655 static char mystr_sockaddr[INET6_ADDRSTRLEN + 20];
657 static char mystr_sockaddr[INET_ADDRSTRLEN + 20];
662 struct sockaddr_storage *sa)
665 char ipstr[INET6_ADDRSTRLEN];
667 char ipstr[INET_ADDRSTRLEN];
671 port = SS_GET_PORT(sa);
673 if ( sa->ss_family == (sa_family_t)AF_INET6) {
674 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
675 ipstr, sizeof(ipstr));
679 inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, ipstr,
682 snprintf(mystr_sockaddr,sizeof(mystr_sockaddr),"%s.%d", ipstr, port);
683 return mystr_sockaddr;
689 struct sockaddr_storage *ss1,
690 struct sockaddr_storage *ss2,
693 /* if addresses are v4mapped, "unmap" them */
695 #ifdef IN6_IS_ADDR_V4MAPPED
696 struct sockaddr_in ss1_v4;
697 struct sockaddr_in ss2_v4;
699 if (ss1->ss_family == AF_INET6 &&
700 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss1)->sin6_addr)) {
701 memset(&ss1_v4, 0, sizeof(struct sockaddr_in));
702 memcpy(&ss1_v4.sin_addr.s_addr,
703 &(((struct sockaddr_in6 *)ss1)->sin6_addr.s6_addr[12]),
704 sizeof(struct in_addr));
705 ss1_v4.sin_family = AF_INET;
706 SS_SET_PORT((struct sockaddr_storage *)&ss1_v4, SS_GET_PORT(ss1));
707 ss1 = (struct sockaddr_storage *)&ss1_v4;
710 if (ss2->ss_family == AF_INET6 &&
711 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss2)->sin6_addr)) {
712 memset(&ss2_v4, 0, sizeof(struct sockaddr_in));
713 memcpy(&ss2_v4.sin_addr.s_addr,
714 &(((struct sockaddr_in6 *)ss2)->sin6_addr.s6_addr[12]),
715 sizeof(struct in_addr));
716 ss2_v4.sin_family = AF_INET;
717 SS_SET_PORT((struct sockaddr_storage *)&ss2_v4, SS_GET_PORT(ss2));
718 ss2 = (struct sockaddr_storage *)&ss2_v4;
723 if (ss1->ss_family == ss2->ss_family) {
726 if(ss1->ss_family == (sa_family_t)AF_INET6)
728 &((struct sockaddr_in6 *)ss1)->sin6_addr,
729 &((struct sockaddr_in6 *)ss2)->sin6_addr,
730 sizeof(((struct sockaddr_in6 *)ss1)->sin6_addr));
734 &((struct sockaddr_in *)ss1)->sin_addr,
735 &((struct sockaddr_in *)ss2)->sin_addr,
736 sizeof(((struct sockaddr_in *)ss1)->sin_addr));
738 return memcmp(ss1, ss2, SS_LEN(ss1));
741 /* compare families to give a total order */
742 if (ss1->ss_family < ss2->ss_family)
761 if ((infd = open(src, O_RDONLY)) == -1) {
763 quoted = quote_string(src);
764 *errmsg = vstralloc("Can't open file ", quoted, " for reading: %s",
765 strerror(save_errno), NULL);
770 if ((outfd = open(dst, O_WRONLY|O_CREAT, 0600)) == -1) {
772 quoted = quote_string(dst);
773 *errmsg = vstralloc("Can't open file ", quoted, " for writting: %s",
774 strerror(save_errno), NULL);
780 while((nb=read(infd, &buf, SIZEOF(buf))) > 0) {
781 if(fullwrite(outfd,&buf,(size_t)nb) < nb) {
783 quoted = quote_string(dst);
784 *errmsg = vstralloc("Error writing to \"", quoted, "\":",
785 strerror(save_errno), NULL);
795 quoted = quote_string(src);
796 *errmsg = vstralloc("Error reading from \"", quoted, "\":",
797 strerror(save_errno), NULL);
808 #ifndef HAVE_LIBREADLINE
810 * simple readline() replacements
817 printf("%s", prompt);
827 (void)line; /* Quite unused parameter warning */