2 * Copyright (C) 2015 Red Hat, Inc.
4 * This file is part of the device-mapper multipath userspace tools.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
24 #include <sys/socket.h>
31 #include "mpath_cmd.h"
34 * keep reading until its all read
36 static ssize_t read_all(int fd, void *buf, size_t len, unsigned int timeout)
46 ret = poll(&pfd, 1, timeout);
54 } else if (!(pfd.revents & POLLIN))
56 n = recv(fd, buf, len, 0);
58 if ((errno == EINTR) || (errno == EAGAIN))
64 buf = n + (char *)buf;
72 * keep writing until it's all sent
74 static size_t write_all(int fd, const void *buf, size_t len)
79 ssize_t n = send(fd, buf, len, MSG_NOSIGNAL);
81 if ((errno == EINTR) || (errno == EAGAIN))
87 buf = n + (const char *)buf;
95 * connect to a unix domain socket
97 int __mpath_connect(int nonblocking)
100 struct sockaddr_un addr;
103 memset(&addr, 0, sizeof(addr));
104 addr.sun_family = AF_LOCAL;
105 addr.sun_path[0] = '\0';
106 strncpy(&addr.sun_path[1], DEFAULT_SOCKET, sizeof(addr.sun_path) - 1);
107 len = strlen(DEFAULT_SOCKET) + 1 + sizeof(sa_family_t);
108 if (len > sizeof(struct sockaddr_un))
109 len = sizeof(struct sockaddr_un);
111 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
116 flags = fcntl(fd, F_GETFL, 0);
118 (void)fcntl(fd, F_SETFL, flags|O_NONBLOCK);
121 if (connect(fd, (struct sockaddr *)&addr, len) == -1) {
129 if (nonblocking && flags != -1)
130 (void)fcntl(fd, F_SETFL, flags);
136 * connect to a unix domain socket
138 int mpath_connect(void)
140 return __mpath_connect(0);
143 int mpath_disconnect(int fd)
148 ssize_t mpath_recv_reply_len(int fd, unsigned int timeout)
153 ret = read_all(fd, &len, sizeof(len), timeout);
156 if (ret != sizeof(len)) {
160 if (len <= 0 || len >= MAX_REPLY_LEN) {
167 int mpath_recv_reply_data(int fd, char *reply, size_t len,
168 unsigned int timeout)
172 ret = read_all(fd, reply, len, timeout);
179 reply[len - 1] = '\0';
183 int mpath_recv_reply(int fd, char **reply, unsigned int timeout)
189 len = mpath_recv_reply_len(fd, timeout);
192 *reply = malloc(len);
195 err = mpath_recv_reply_data(fd, *reply, len, timeout);
204 int mpath_send_cmd(int fd, const char *cmd)
209 len = strlen(cmd) + 1;
212 if (write_all(fd, &len, sizeof(len)) != sizeof(len))
214 if (len && write_all(fd, cmd, len) != len)
219 int mpath_process_cmd(int fd, const char *cmd, char **reply,
220 unsigned int timeout)
222 if (mpath_send_cmd(fd, cmd) != 0)
224 return mpath_recv_reply(fd, reply, timeout);