Imported Upstream version 0.8.2
[platform/upstream/multipath-tools.git] / libmpathcmd / mpath_cmd.c
index 1aaf5ea..f00bf7e 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This file is part of the device-mapper multipath userspace tools.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -7,6 +26,7 @@
 #include <poll.h>
 #include <string.h>
 #include <errno.h>
+#include <fcntl.h>
 
 #include "mpath_cmd.h"
 
@@ -31,9 +51,9 @@ static ssize_t read_all(int fd, void *buf, size_t len, unsigned int timeout)
                        if (errno == EINTR)
                                continue;
                        return -1;
-               } else if (!pfd.revents & POLLIN)
+               } else if (!(pfd.revents & POLLIN))
                        continue;
-               n = read(fd, buf, len);
+               n = recv(fd, buf, len, 0);
                if (n < 0) {
                        if ((errno == EINTR) || (errno == EAGAIN))
                                continue;
@@ -56,7 +76,7 @@ static size_t write_all(int fd, const void *buf, size_t len)
        size_t total = 0;
 
        while (len) {
-               ssize_t n = write(fd, buf, len);
+               ssize_t n = send(fd, buf, len, MSG_NOSIGNAL);
                if (n < 0) {
                        if ((errno == EINTR) || (errno == EAGAIN))
                                continue;
@@ -64,7 +84,7 @@ static size_t write_all(int fd, const void *buf, size_t len)
                }
                if (!n)
                        return total;
-               buf = n + (char *)buf;
+               buf = n + (const char *)buf;
                len -= n;
                total += n;
        }
@@ -74,29 +94,52 @@ static size_t write_all(int fd, const void *buf, size_t len)
 /*
  * connect to a unix domain socket
  */
-int mpath_connect(void)
+int __mpath_connect(int nonblocking)
 {
        int fd, len;
        struct sockaddr_un addr;
+       int flags = 0;
 
        memset(&addr, 0, sizeof(addr));
        addr.sun_family = AF_LOCAL;
        addr.sun_path[0] = '\0';
+       strncpy(&addr.sun_path[1], DEFAULT_SOCKET, sizeof(addr.sun_path) - 1);
        len = strlen(DEFAULT_SOCKET) + 1 + sizeof(sa_family_t);
-       strncpy(&addr.sun_path[1], DEFAULT_SOCKET, len);
+       if (len > sizeof(struct sockaddr_un))
+               len = sizeof(struct sockaddr_un);
 
        fd = socket(AF_LOCAL, SOCK_STREAM, 0);
        if (fd == -1)
                return -1;
 
+       if (nonblocking) {
+               flags = fcntl(fd, F_GETFL, 0);
+               if (flags != -1)
+                       (void)fcntl(fd, F_SETFL, flags|O_NONBLOCK);
+       }
+
        if (connect(fd, (struct sockaddr *)&addr, len) == -1) {
+               int err = errno;
+
                close(fd);
+               errno = err;
                return -1;
        }
 
+       if (nonblocking && flags != -1)
+               (void)fcntl(fd, F_SETFL, flags);
+
        return fd;
 }
 
+/*
+ * connect to a unix domain socket
+ */
+int mpath_connect(void)
+{
+       return __mpath_connect(0);
+}
+
 int mpath_disconnect(int fd)
 {
        return close(fd);
@@ -112,7 +155,11 @@ ssize_t mpath_recv_reply_len(int fd, unsigned int timeout)
                return ret;
        if (ret != sizeof(len)) {
                errno = EIO;
-               return ret;
+               return -1;
+       }
+       if (len <= 0 || len >= MAX_REPLY_LEN) {
+               errno = ERANGE;
+               return -1;
        }
        return len;
 }
@@ -149,7 +196,7 @@ int mpath_recv_reply(int fd, char **reply, unsigned int timeout)
        if (err) {
                free(*reply);
                *reply = NULL;
-               return err;
+               return -1;
        }
        return 0;
 }