e7868992a9e9cd4e2fae3cb6896464a9be116967
[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
23 /*
24  * connect to a unix domain socket
25  */
26 int ux_socket_connect(const char *name)
27 {
28         int fd;
29         struct sockaddr_un addr;
30
31         memset(&addr, 0, sizeof(addr));
32         addr.sun_family = AF_UNIX;
33         strncpy(addr.sun_path, name, sizeof(addr.sun_path));
34
35         fd = socket(AF_UNIX, SOCK_STREAM, 0);
36         if (fd == -1) {
37                 return -1;
38         }
39
40         if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
41                 close(fd);
42                 return -1;
43         }
44
45         return fd;
46 }
47
48 /*
49  * create a unix domain socket and start listening on it
50  * return a file descriptor open on the socket
51  */
52 int ux_socket_listen(const char *name)
53 {
54         int fd;
55         struct sockaddr_un addr;
56
57         /* get rid of any old socket */
58         unlink(name);
59
60         fd = socket(AF_UNIX, SOCK_STREAM, 0);
61         if (fd == -1) return -1;
62
63         memset(&addr, 0, sizeof(addr));
64         addr.sun_family = AF_UNIX;
65         strncpy(addr.sun_path, name, sizeof(addr.sun_path));
66
67         if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
68                 close(fd);
69                 return -1;
70         }
71
72         if (listen(fd, 10) == -1) {
73                 close(fd);
74                 return -1;
75         }
76
77         return fd;
78 }
79
80 /*
81  * keep writing until it's all sent
82  */
83 size_t write_all(int fd, const void *buf, size_t len)
84 {
85         size_t total = 0;
86
87         while (len) {
88                 ssize_t n = write(fd, buf, len);
89                 if (n < 0) {
90                         if ((errno == EINTR) || (errno == EAGAIN))
91                                 continue;
92                         return total;
93                 }
94                 if (!n)
95                         return total;
96                 buf = n + (char *)buf;
97                 len -= n;
98                 total += n;
99         }
100         return total;
101 }
102
103 /*
104  * keep reading until its all read
105  */
106 size_t read_all(int fd, void *buf, size_t len)
107 {
108         size_t total = 0;
109
110         while (len) {
111                 ssize_t n = read(fd, buf, len);
112                 if (n < 0) {
113                         if ((errno == EINTR) || (errno == EAGAIN))
114                                 continue;
115                         return total;
116                 }
117                 if (!n)
118                         return total;
119                 buf = n + (char *)buf;
120                 len -= n;
121                 total += n;
122         }
123         return total;
124 }
125
126 /*
127  * send a packet in length prefix format
128  */
129 int send_packet(int fd, const char *buf, size_t len)
130 {
131         int ret = 0;
132         sigset_t set, old;
133
134         /* Block SIGPIPE */
135         sigemptyset(&set);
136         sigaddset(&set, SIGPIPE);
137         pthread_sigmask(SIG_BLOCK, &set, &old);
138
139         if (write_all(fd, &len, sizeof(len)) != sizeof(len))
140                 ret = -1;
141         if (!ret && write_all(fd, buf, len) != len)
142                 ret = -1;
143
144         /* And unblock it again */
145         pthread_sigmask(SIG_SETMASK, &old, NULL);
146
147         return ret;
148 }
149
150 /*
151  * receive a packet in length prefix format
152  */
153 int recv_packet(int fd, char **buf, size_t *len)
154 {
155         if (read_all(fd, len, sizeof(*len)) != sizeof(*len)) {
156                 (*buf) = NULL;
157                 *len = 0;
158                 return -1;
159         }
160         if (len == 0) {
161                 (*buf) = NULL;
162                 return 0;
163         }
164         (*buf) = MALLOC(*len);
165         if (!*buf)
166                 return -1;
167         if (read_all(fd, *buf, *len) != *len) {
168                 FREE(*buf);
169                 (*buf) = NULL;
170                 *len = 0;
171                 return -1;
172         }
173         return 0;
174 }