multipath-tools: replace <> with "" for local headers
[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 #ifdef USE_SYSTEMD
20 #include <systemd/sd-daemon.h>
21 #endif
22 #include "mpath_cmd.h"
23
24 #include "memory.h"
25 #include "uxsock.h"
26 #include "debug.h"
27 /*
28  * create a unix domain socket and start listening on it
29  * return a file descriptor open on the socket
30  */
31 int ux_socket_listen(const char *name)
32 {
33         int fd, len;
34 #ifdef USE_SYSTEMD
35         int num;
36 #endif
37         struct sockaddr_un addr;
38
39 #ifdef USE_SYSTEMD
40         num = sd_listen_fds(0);
41         if (num > 1) {
42                 condlog(3, "sd_listen_fds returned %d fds", num);
43                 return -1;
44         } else if (num == 1) {
45                 fd = SD_LISTEN_FDS_START + 0;
46                 condlog(3, "using fd %d from sd_listen_fds", fd);
47                 return fd;
48         }
49 #endif
50         fd = socket(AF_LOCAL, SOCK_STREAM, 0);
51         if (fd == -1) {
52                 condlog(3, "Couldn't create ux_socket, error %d", errno);
53                 return -1;
54         }
55
56         memset(&addr, 0, sizeof(addr));
57         addr.sun_family = AF_LOCAL;
58         addr.sun_path[0] = '\0';
59         len = strlen(name) + 1 + sizeof(sa_family_t);
60         strncpy(&addr.sun_path[1], name, len);
61
62         if (bind(fd, (struct sockaddr *)&addr, len) == -1) {
63                 condlog(3, "Couldn't bind to ux_socket, error %d", errno);
64                 close(fd);
65                 return -1;
66         }
67
68         if (listen(fd, 10) == -1) {
69                 condlog(3, "Couldn't listen to ux_socket, error %d", errno);
70                 close(fd);
71                 return -1;
72         }
73         return fd;
74 }
75
76 /*
77  * keep writing until it's all sent
78  */
79 size_t write_all(int fd, const void *buf, size_t len)
80 {
81         size_t total = 0;
82
83         while (len) {
84                 ssize_t n = write(fd, buf, len);
85                 if (n < 0) {
86                         if ((errno == EINTR) || (errno == EAGAIN))
87                                 continue;
88                         return total;
89                 }
90                 if (!n)
91                         return total;
92                 buf = n + (char *)buf;
93                 len -= n;
94                 total += n;
95         }
96         return total;
97 }
98
99 /*
100  * keep reading until its all read
101  */
102 ssize_t read_all(int fd, void *buf, size_t len, unsigned int timeout)
103 {
104         size_t total = 0;
105         ssize_t n;
106         int ret;
107         struct pollfd pfd;
108
109         while (len) {
110                 pfd.fd = fd;
111                 pfd.events = POLLIN;
112                 ret = poll(&pfd, 1, timeout);
113                 if (!ret) {
114                         return -ETIMEDOUT;
115                 } else if (ret < 0) {
116                         if (errno == EINTR)
117                                 continue;
118                         return -errno;
119                 } else if (!pfd.revents & POLLIN)
120                         continue;
121                 n = read(fd, buf, len);
122                 if (n < 0) {
123                         if ((errno == EINTR) || (errno == EAGAIN))
124                                 continue;
125                         return -errno;
126                 }
127                 if (!n)
128                         return total;
129                 buf = n + (char *)buf;
130                 len -= n;
131                 total += n;
132         }
133         return total;
134 }
135
136 /*
137  * send a packet in length prefix format
138  */
139 int send_packet(int fd, const char *buf)
140 {
141         int ret = 0;
142         sigset_t set, old;
143
144         /* Block SIGPIPE */
145         sigemptyset(&set);
146         sigaddset(&set, SIGPIPE);
147         pthread_sigmask(SIG_BLOCK, &set, &old);
148
149         ret = mpath_send_cmd(fd, buf);
150
151         /* And unblock it again */
152         pthread_sigmask(SIG_SETMASK, &old, NULL);
153
154         return ret;
155 }
156
157 /*
158  * receive a packet in length prefix format
159  */
160 int recv_packet(int fd, char **buf, unsigned int timeout)
161 {
162         int err;
163         ssize_t len;
164
165         *buf = NULL;
166         len = mpath_recv_reply_len(fd, timeout);
167         if (len <= 0)
168                 return len;
169         (*buf) = MALLOC(len);
170         if (!*buf)
171                 return -ENOMEM;
172         err = mpath_recv_reply_data(fd, *buf, len, timeout);
173         if (err) {
174                 FREE(*buf);
175                 (*buf) = NULL;
176                 return err;
177         }
178         return 0;
179 }