Invalid error code when using multipathd CLI
[multipath-tools/.git] / libmultipath / uxsock.c
index 880257f..7e5a144 100644 (file)
 #include "memory.h"
 #include "uxsock.h"
 #include "debug.h"
+
+/*
+ * Code is similar with mpath_recv_reply() with data size limitation
+ * and debug-able malloc.
+ * When limit == 0, it means no limit on data size, used for socket client
+ * to receiving data from multipathd.
+ */
+static int _recv_packet(int fd, char **buf, unsigned int timeout,
+                       ssize_t limit);
+
 /*
  * create a unix domain socket and start listening on it
  * return a file descriptor open on the socket
@@ -73,94 +83,50 @@ int ux_socket_listen(const char *name)
        return fd;
 }
 
-/*
- * keep writing until it's all sent
- */
-size_t write_all(int fd, const void *buf, size_t len)
-{
-       size_t total = 0;
-
-       while (len) {
-               ssize_t n = send(fd, buf, len, MSG_NOSIGNAL);
-               if (n < 0) {
-                       if ((errno == EINTR) || (errno == EAGAIN))
-                               continue;
-                       return total;
-               }
-               if (!n)
-                       return total;
-               buf = n + (char *)buf;
-               len -= n;
-               total += n;
-       }
-       return total;
-}
-
-/*
- * keep reading until its all read
- */
-ssize_t read_all(int fd, void *buf, size_t len, unsigned int timeout)
-{
-       size_t total = 0;
-       ssize_t n;
-       int ret;
-       struct pollfd pfd;
-
-       while (len) {
-               pfd.fd = fd;
-               pfd.events = POLLIN;
-               ret = poll(&pfd, 1, timeout);
-               if (!ret) {
-                       return -ETIMEDOUT;
-               } else if (ret < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       return -errno;
-               } else if (!pfd.revents & POLLIN)
-                       continue;
-               n = read(fd, buf, len);
-               if (n < 0) {
-                       if ((errno == EINTR) || (errno == EAGAIN))
-                               continue;
-                       return -errno;
-               }
-               if (!n)
-                       return total;
-               buf = n + (char *)buf;
-               len -= n;
-               total += n;
-       }
-       return total;
-}
-
 /*
  * send a packet in length prefix format
  */
 int send_packet(int fd, const char *buf)
 {
-       return mpath_send_cmd(fd, buf);
+       if (mpath_send_cmd(fd, buf) < 0)
+               return -errno;
+       return 0;
 }
 
-/*
- * receive a packet in length prefix format
- */
-int recv_packet(int fd, char **buf, unsigned int timeout)
+static int _recv_packet(int fd, char **buf, unsigned int timeout, ssize_t limit)
 {
-       int err;
-       ssize_t len;
+       int err = 0;
+       ssize_t len = 0;
 
        *buf = NULL;
        len = mpath_recv_reply_len(fd, timeout);
-       if (len <= 0)
+       if (len == 0)
                return len;
+       if (len < 0)
+               return -errno;
+       if ((limit > 0) && (len > limit))
+               return -EINVAL;
        (*buf) = MALLOC(len);
        if (!*buf)
                return -ENOMEM;
        err = mpath_recv_reply_data(fd, *buf, len, timeout);
-       if (err) {
+       if (err != 0) {
                FREE(*buf);
                (*buf) = NULL;
-               return err;
+               return -errno;
        }
-       return 0;
+       return err;
+}
+
+/*
+ * receive a packet in length prefix format
+ */
+int recv_packet(int fd, char **buf, unsigned int timeout)
+{
+       return _recv_packet(fd, buf, timeout, 0 /* no limit */);
+}
+
+int recv_packet_from_client(int fd, char **buf, unsigned int timeout)
+{
+       return _recv_packet(fd, buf, timeout, _MAX_CMD_LEN);
 }