Clarify uxsock logging
[multipath-tools/.git] / libmultipath / uxsock.c
1 /*
2  * Original author : tridge@samba.org, January 2002
3  *
4  * Copyright (c) 2005 Christophe Varoqui
5  * Copyright (c) 2005 Alasdair Kergon, Redhat
6  */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdarg.h>
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/un.h>
16 #include <sys/poll.h>
17 #include <signal.h>
18 #include <errno.h>
19
20 #include "memory.h"
21 #include "uxsock.h"
22 #include "debug.h"
23
24 /*
25  * connect to a unix domain socket
26  */
27 int ux_socket_connect(const char *name)
28 {
29         int fd, len;
30         struct sockaddr_un addr;
31
32         memset(&addr, 0, sizeof(addr));
33         addr.sun_family = AF_LOCAL;
34         addr.sun_path[0] = '\0';
35         len = strlen(name) + 1 + sizeof(sa_family_t);
36         strncpy(&addr.sun_path[1], name, len);
37
38         fd = socket(AF_LOCAL, SOCK_STREAM, 0);
39         if (fd == -1) {
40                 condlog(3, "Couldn't create ux_socket, error %d", errno);
41                 return -1;
42         }
43
44         if (connect(fd, (struct sockaddr *)&addr, len) == -1) {
45                 condlog(3, "Couldn't connect to ux_socket, error %d", errno);
46                 close(fd);
47                 return -1;
48         }
49
50         return fd;
51 }
52
53 /*
54  * create a unix domain socket and start listening on it
55  * return a file descriptor open on the socket
56  */
57 int ux_socket_listen(const char *name)
58 {
59         int fd, len;
60         struct sockaddr_un addr;
61
62         fd = socket(AF_LOCAL, SOCK_STREAM, 0);
63         if (fd == -1) {
64                 condlog(3, "Couldn't create ux_socket, error %d", errno);
65                 return -1;
66         }
67
68         memset(&addr, 0, sizeof(addr));
69         addr.sun_family = AF_LOCAL;
70         addr.sun_path[0] = '\0';
71         len = strlen(name) + 1 + sizeof(sa_family_t);
72         strncpy(&addr.sun_path[1], name, len);
73
74         if (bind(fd, (struct sockaddr *)&addr, len) == -1) {
75                 condlog(3, "Couldn't bind to ux_socket, error %d", errno);
76                 close(fd);
77                 return -1;
78         }
79
80         if (listen(fd, 10) == -1) {
81                 condlog(3, "Couldn't listen to ux_socket, error %d", errno);
82                 close(fd);
83                 return -1;
84         }
85         return fd;
86 }
87
88 /*
89  * keep writing until it's all sent
90  */
91 size_t write_all(int fd, const void *buf, size_t len)
92 {
93         size_t total = 0;
94
95         while (len) {
96                 ssize_t n = write(fd, buf, len);
97                 if (n < 0) {
98                         if ((errno == EINTR) || (errno == EAGAIN))
99                                 continue;
100                         return total;
101                 }
102                 if (!n)
103                         return total;
104                 buf = n + (char *)buf;
105                 len -= n;
106                 total += n;
107         }
108         return total;
109 }
110
111 /*
112  * keep reading until its all read
113  */
114 size_t read_all(int fd, void *buf, size_t len)
115 {
116         size_t total = 0;
117         ssize_t n;
118         int ret;
119         struct pollfd pfd;
120
121         while (len) {
122                 pfd.fd = fd;
123                 pfd.events = POLLIN;
124                 ret = poll(&pfd, 1, 1000);
125                 if (!ret) {
126                         errno = ETIMEDOUT;
127                         return total;
128                 } else if (ret < 0) {
129                         if (errno == EINTR)
130                                 continue;
131                         return total;
132                 } else if (!pfd.revents & POLLIN)
133                         continue;
134                 n = read(fd, buf, len);
135                 if (n < 0) {
136                         if ((errno == EINTR) || (errno == EAGAIN))
137                                 continue;
138                         return total;
139                 }
140                 if (!n)
141                         return total;
142                 buf = n + (char *)buf;
143                 len -= n;
144                 total += n;
145         }
146         return total;
147 }
148
149 /*
150  * send a packet in length prefix format
151  */
152 int send_packet(int fd, const char *buf, size_t len)
153 {
154         int ret = 0;
155         sigset_t set, old;
156
157         /* Block SIGPIPE */
158         sigemptyset(&set);
159         sigaddset(&set, SIGPIPE);
160         pthread_sigmask(SIG_BLOCK, &set, &old);
161
162         if (write_all(fd, &len, sizeof(len)) != sizeof(len))
163                 ret = -1;
164         if (!ret && write_all(fd, buf, len) != len)
165                 ret = -1;
166
167         /* And unblock it again */
168         pthread_sigmask(SIG_SETMASK, &old, NULL);
169
170         return ret;
171 }
172
173 /*
174  * receive a packet in length prefix format
175  */
176 int recv_packet(int fd, char **buf, size_t *len)
177 {
178         if (read_all(fd, len, sizeof(*len)) != sizeof(*len)) {
179                 (*buf) = NULL;
180                 *len = 0;
181                 return -1;
182         }
183         if (len == 0) {
184                 (*buf) = NULL;
185                 return 0;
186         }
187         (*buf) = MALLOC(*len);
188         if (!*buf)
189                 return -1;
190         if (read_all(fd, *buf, *len) != *len) {
191                 FREE(*buf);
192                 (*buf) = NULL;
193                 *len = 0;
194                 return -1;
195         }
196         return 0;
197 }