+/*
+ * 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>
#include <poll.h>
#include <string.h>
#include <errno.h>
+#include <fcntl.h>
#include "mpath_cmd.h"
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;
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;
}
if (!n)
return total;
- buf = n + (char *)buf;
+ buf = n + (const char *)buf;
len -= n;
total += n;
}
/*
* 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);
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;
}
if (err) {
free(*reply);
*reply = NULL;
- return err;
+ return -1;
}
return 0;
}