]> arthur.barton.de Git - netatalk.git/blobdiff - libevent/evutil.c
Add silent rules to libevent
[netatalk.git] / libevent / evutil.c
index b769acc2b323fa7f90a42074d5bc81af8b395e06..b6634591a9bccbc0bfdfdad516d13550bee28c2f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2010 Niels Provos and Nick Mathewson
+ * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
-#ifdef _EVENT_HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
 #ifdef _EVENT_HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 #ifdef _EVENT_HAVE_NETINET_IN6_H
 #include <netinet/in6.h>
 #endif
+#ifdef _EVENT_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
 
 #ifndef _EVENT_HAVE_GETTIMEOFDAY
 #include <sys/timeb.h>
 #define stat _stati64
 #endif
 
+int
+evutil_open_closeonexec(const char *pathname, int flags, unsigned mode)
+{
+       int fd;
+
+#ifdef O_CLOEXEC
+       flags |= O_CLOEXEC;
+#endif
+
+       if (flags & O_CREAT)
+               fd = open(pathname, flags, (mode_t)mode);
+       else
+               fd = open(pathname, flags);
+       if (fd < 0)
+               return -1;
+
+#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
+       if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
+               return -1;
+#endif
+
+       return fd;
+}
+
 /**
    Read the contents of 'filename' into a newly allocated NUL-terminated
    string.  Set *content_out to hold this string, and *len_out to hold its
@@ -117,7 +141,7 @@ evutil_read_file(const char *filename, char **content_out, size_t *len_out,
                mode |= O_BINARY;
 #endif
 
-       fd = open(filename, mode);
+       fd = evutil_open_closeonexec(filename, mode, 0);
        if (fd < 0)
                return -1;
        if (fstat(fd, &st) || st.st_size < 0 ||
@@ -351,6 +375,8 @@ evutil_strtoll(const char *s, char **endptr, int base)
        r = (ev_int64_t) _atoi64(s);
        while (isspace(*s))
                ++s;
+       if (*s == '-')
+               ++s;
        while (isdigit(*s))
                ++s;
        if (endptr)
@@ -358,6 +384,36 @@ evutil_strtoll(const char *s, char **endptr, int base)
        return r;
 #elif defined(WIN32)
        return (ev_int64_t) _strtoi64(s, endptr, base);
+#elif defined(_EVENT_SIZEOF_LONG_LONG) && _EVENT_SIZEOF_LONG_LONG == 8
+       long long r;
+       int n;
+       if (base != 10 && base != 16)
+               return 0;
+       if (base == 10) {
+               n = sscanf(s, "%lld", &r);
+       } else {
+               unsigned long long ru=0;
+               n = sscanf(s, "%llx", &ru);
+               if (ru > EV_INT64_MAX)
+                       return 0;
+               r = (long long) ru;
+       }
+       if (n != 1)
+               return 0;
+       while (EVUTIL_ISSPACE(*s))
+               ++s;
+       if (*s == '-')
+               ++s;
+       if (base == 10) {
+               while (EVUTIL_ISDIGIT(*s))
+                       ++s;
+       } else {
+               while (EVUTIL_ISXDIGIT(*s))
+                       ++s;
+       }
+       if (endptr)
+               *endptr = (char*) s;
+       return r;
 #else
 #error "I don't know how to parse 64-bit integers."
 #endif
@@ -413,9 +469,9 @@ evutil_socket_connect(evutil_socket_t *fd_ptr, struct sockaddr *sa, int socklen)
        int made_fd = 0;
 
        if (*fd_ptr < 0) {
-               made_fd = 1;
                if ((*fd_ptr = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
                        goto err;
+               made_fd = 1;
                if (evutil_make_socket_nonblocking(*fd_ptr) < 0) {
                        goto err;
                }
@@ -479,6 +535,15 @@ evutil_socket_finished_connecting(evutil_socket_t fd)
    set by evutil_check_interfaces. */
 static int have_checked_interfaces, had_ipv4_address, had_ipv6_address;
 
+/* Macro: True iff the IPv4 address 'addr', in host order, is in 127.0.0.0/8
+ */
+#define EVUTIL_V4ADDR_IS_LOCALHOST(addr) (((addr)>>24) == 127)
+
+/* Macro: True iff the IPv4 address 'addr', in host order, is a class D
+ * (multiclass) address.
+ */
+#define EVUTIL_V4ADDR_IS_CLASSD(addr) ((((addr)>>24) & 0xf0) == 0xe0)
+
 /* Test whether we have an ipv4 interface and an ipv6 interface.  Return 0 if
  * the test seemed successful. */
 static int
@@ -522,8 +587,9 @@ evutil_check_interfaces(int force_recheck)
            getsockname(fd, (struct sockaddr*)&sin_out, &sin_out_len) == 0) {
                /* We might have an IPv4 interface. */
                ev_uint32_t addr = ntohl(sin_out.sin_addr.s_addr);
-               if (addr == 0 || (addr&0xff000000) == 127 ||
-                   (addr & 0xff) == 255 || (addr & 0xf0) == 14) {
+               if (addr == 0 ||
+                   EVUTIL_V4ADDR_IS_LOCALHOST(addr) ||
+                   EVUTIL_V4ADDR_IS_CLASSD(addr)) {
                        evutil_inet_ntop(AF_INET, &sin_out.sin_addr,
                            buf, sizeof(buf));
                        /* This is a reserved, ipv4compat, ipv4map, loopback,
@@ -721,6 +787,10 @@ evutil_getaddrinfo_infer_protocols(struct evutil_addrinfo *hints)
        }
 }
 
+#if AF_UNSPEC != PF_UNSPEC
+#error "I cannot build on a system where AF_UNSPEC != PF_UNSPEC"
+#endif
+
 /** Implements the part of looking up hosts by name that's common to both
  * the blocking and nonblocking resolver:
  *   - Adjust 'hints' to have a reasonable socktype and protocol.
@@ -771,7 +841,7 @@ evutil_getaddrinfo_common(const char *nodename, const char *servname,
                        memset(&sin6, 0, sizeof(sin6));
                        sin6.sin6_family = AF_INET6;
                        sin6.sin6_port = htons(port);
-                       if (hints->ai_flags & AI_PASSIVE) {
+                       if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
                                /* Bind to :: */
                        } else {
                                /* connect to ::1 */
@@ -788,7 +858,7 @@ evutil_getaddrinfo_common(const char *nodename, const char *servname,
                        memset(&sin, 0, sizeof(sin));
                        sin.sin_family = AF_INET;
                        sin.sin_port = htons(port);
-                       if (hints->ai_flags & AI_PASSIVE) {
+                       if (hints->ai_flags & EVUTIL_AI_PASSIVE) {
                                /* Bind to 0.0.0.0 */
                        } else {
                                /* connect to 127.0.0.1 */
@@ -958,8 +1028,13 @@ addrinfo_from_hostent(const struct hostent *ent,
                res = evutil_addrinfo_append(res, ai);
        }
 
-       if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name))
+       if (res && ((hints->ai_flags & EVUTIL_AI_CANONNAME) && ent->h_name)) {
                res->ai_canonname = mm_strdup(ent->h_name);
+               if (res->ai_canonname == NULL) {
+                       evutil_freeaddrinfo(res);
+                       return NULL;
+               }
+       }
 
        return res;
 }
@@ -1083,7 +1158,7 @@ apply_numeric_port_hack(int port, struct evutil_addrinfo **ai)
        }
 }
 
-static void
+static int
 apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
 {
        struct evutil_addrinfo *ai_new;
@@ -1092,6 +1167,8 @@ apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
                if (ai->ai_socktype || ai->ai_protocol)
                        continue;
                ai_new = mm_malloc(sizeof(*ai_new));
+               if (!ai_new)
+                       return -1;
                memcpy(ai_new, ai, sizeof(*ai_new));
                ai->ai_socktype = SOCK_STREAM;
                ai->ai_protocol = IPPROTO_TCP;
@@ -1101,6 +1178,7 @@ apply_socktype_protocol_hack(struct evutil_addrinfo *ai)
                ai_new->ai_next = ai->ai_next;
                ai->ai_next = ai_new;
        }
+       return 0;
 }
 #endif
 
@@ -1191,7 +1269,11 @@ evutil_getaddrinfo(const char *nodename, const char *servname,
                apply_numeric_port_hack(portnum, res);
 
        if (need_socktype_protocol_hack()) {
-               apply_socktype_protocol_hack(*res);
+               if (apply_socktype_protocol_hack(*res) < 0) {
+                       evutil_freeaddrinfo(*res);
+                       *res = NULL;
+                       return EVUTIL_EAI_MEMORY;
+               }
        }
        return err;
 #else