]> code.delx.au - pulseaudio/blob - src/util.c
fix recording for simpel and esound protocols
[pulseaudio] / src / util.c
1 #include <signal.h>
2 #include <errno.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <sys/un.h>
7 #include <netinet/in.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <netinet/tcp.h>
12 #include <netinet/ip.h>
13
14 #include "util.h"
15
16 void pa_make_nonblock_fd(int fd) {
17 int v;
18
19 if ((v = fcntl(fd, F_GETFL)) >= 0)
20 if (!(v & O_NONBLOCK))
21 fcntl(fd, F_SETFL, v|O_NONBLOCK);
22 }
23
24 void pa_peer_to_string(char *c, size_t l, int fd) {
25 struct stat st;
26
27 assert(c && l && fd >= 0);
28
29 if (fstat(fd, &st) < 0) {
30 snprintf(c, l, "Invalid client fd");
31 return;
32 }
33
34 if (S_ISSOCK(st.st_mode)) {
35 union {
36 struct sockaddr sa;
37 struct sockaddr_in in;
38 struct sockaddr_un un;
39 } sa;
40 socklen_t sa_len = sizeof(sa);
41
42 if (getpeername(fd, &sa.sa, &sa_len) >= 0) {
43
44 if (sa.sa.sa_family == AF_INET) {
45 uint32_t ip = ntohl(sa.in.sin_addr.s_addr);
46
47 snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
48 ip >> 24,
49 (ip >> 16) & 0xFF,
50 (ip >> 8) & 0xFF,
51 ip & 0xFF,
52 ntohs(sa.in.sin_port));
53 return;
54 } else if (sa.sa.sa_family == AF_LOCAL) {
55 snprintf(c, l, "UNIX socket client");
56 return;
57 }
58
59 }
60 snprintf(c, l, "Unknown network client");
61 return;
62 } else if (S_ISCHR(st.st_mode) && (fd == 0 || fd == 1)) {
63 snprintf(c, l, "STDIN/STDOUT client");
64 return;
65 }
66
67 snprintf(c, l, "Unknown client");
68 }
69
70 int pa_make_secure_dir(const char* dir) {
71 struct stat st;
72
73 if (mkdir(dir, 0700) < 0)
74 if (errno != EEXIST)
75 return -1;
76
77 if (lstat(dir, &st) < 0)
78 goto fail;
79
80 if (!S_ISDIR(st.st_mode) || (st.st_uid != getuid()) || ((st.st_mode & 0777) != 0700))
81 goto fail;
82
83 return 0;
84
85 fail:
86 rmdir(dir);
87 return -1;
88 }
89
90 int pa_socket_low_delay(int fd) {
91 int priority;
92 assert(fd >= 0);
93
94 priority = 7;
95 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority)) < 0)
96 return -1;
97
98 return 0;
99 }
100
101 int pa_socket_tcp_low_delay(int fd) {
102 int ret, tos;
103
104 assert(fd >= 0);
105
106 ret = pa_socket_low_delay(fd);
107
108 /* on = 1; */
109 /* if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) */
110 /* ret = -1; */
111
112 tos = IPTOS_LOWDELAY;
113 if (setsockopt(fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
114 ret = -1;
115
116 return ret;
117
118 }
119
120 int pa_socket_set_rcvbuf(int fd, size_t l) {
121 assert(fd >= 0);
122
123 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0)
124 return -1;
125
126 return 0;
127 }
128
129 int pa_socket_set_sndbuf(int fd, size_t l) {
130 assert(fd >= 0);
131
132 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0)
133 return -1;
134
135 return 0;
136 }
137
138 ssize_t pa_loop_read(int fd, void*data, size_t size) {
139 ssize_t ret = 0;
140 assert(fd >= 0 && data && size);
141
142 while (size > 0) {
143 ssize_t r;
144
145 if ((r = read(fd, data, size)) < 0)
146 return r;
147
148 if (r == 0)
149 break;
150
151 ret += r;
152 data += r;
153 size -= r;
154 }
155
156 return ret;
157 }
158
159 ssize_t pa_loop_write(int fd, const void*data, size_t size) {
160 ssize_t ret = 0;
161 assert(fd >= 0 && data && size);
162
163 while (size > 0) {
164 ssize_t r;
165
166 if ((r = write(fd, data, size)) < 0)
167 return r;
168
169 if (r == 0)
170 break;
171
172 ret += r;
173 data += r;
174 size -= r;
175 }
176
177 return ret;
178 }
179
180 int pa_unix_socket_is_stale(const char *fn) {
181 struct sockaddr_un sa;
182 int fd = -1, ret = -1;
183
184 if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
185 fprintf(stderr, "socket(): %s\n", strerror(errno));
186 goto finish;
187 }
188
189 sa.sun_family = AF_LOCAL;
190 strncpy(sa.sun_path, fn, sizeof(sa.sun_path)-1);
191 sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
192
193 if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
194 if (errno == ECONNREFUSED)
195 ret = 1;
196 } else
197 ret = 0;
198
199 finish:
200 if (fd >= 0)
201 close(fd);
202
203 return ret;
204 }
205
206 int pa_unix_socket_remove_stale(const char *fn) {
207 int r;
208
209 if ((r = pa_unix_socket_is_stale(fn)) < 0)
210 return errno != ENOENT ? -1 : 0;
211
212 if (!r)
213 return 0;
214
215 /* Yes, here is a race condition. But who cares? */
216 if (unlink(fn) < 0)
217 return -1;
218
219 return 0;
220 }
221
222 void pa_check_for_sigpipe(void) {
223 struct sigaction sa;
224
225 if (sigaction(SIGPIPE, NULL, &sa) < 0) {
226 fprintf(stderr, __FILE__": sigaction() failed: %s\n", strerror(errno));
227 return;
228 }
229
230 if (sa.sa_handler == SIG_DFL)
231 fprintf(stderr, "polypaudio: WARNING: SIGPIPE is not trapped. This might cause malfunction!\n");
232 }