blob: 8d3865f8a41163575ff57a237eba8343962084c7 [file] [log] [blame]
njneb8896b2005-06-04 20:03:55 +00001
2/*--------------------------------------------------------------------*/
3/*--- File- and socket-related libc stuff. m_libcfile.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2005 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njneb8896b2005-06-04 20:03:55 +000032#include "pub_core_libcbase.h"
33#include "pub_core_libcassert.h"
34#include "pub_core_libcfile.h"
njn351d0062005-06-21 22:23:59 +000035#include "pub_core_libcprint.h" // For VG_(sprintf)()
njn9abd6082005-06-17 21:31:45 +000036#include "pub_core_syscall.h"
njneb8896b2005-06-04 20:03:55 +000037#include "vki_unistd.h"
38
39/* ---------------------------------------------------------------------
40 File stuff
41 ------------------------------------------------------------------ */
42
njn63004dc2005-06-10 22:39:04 +000043/* Application-visible file descriptor limits */
44Int VG_(fd_soft_limit) = -1;
45Int VG_(fd_hard_limit) = -1;
46
njneb8896b2005-06-04 20:03:55 +000047static inline Bool fd_exists(Int fd)
48{
49 struct vki_stat st;
50
51 return VG_(fstat)(fd, &st) == 0;
52}
53
54/* Move an fd into the Valgrind-safe range */
55Int VG_(safe_fd)(Int oldfd)
56{
57 Int newfd;
58
59 vg_assert(VG_(fd_hard_limit) != -1);
60
61 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
62 if (newfd != -1)
63 VG_(close)(oldfd);
64
65 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
66
67 vg_assert(newfd >= VG_(fd_hard_limit));
68 return newfd;
69}
70
njnae7359b2005-06-19 21:10:42 +000071/* Given a file descriptor, attempt to deduce its filename. To do
72 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
njnf845f8f2005-06-23 02:26:47 +000073 or if it doesn't exist, we return False. */
74Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
njnae7359b2005-06-19 21:10:42 +000075{
76 HChar tmp[64];
77
78 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
njnf845f8f2005-06-23 02:26:47 +000079 VG_(memset)(buf, 0, n_buf);
njnae7359b2005-06-19 21:10:42 +000080
njnf845f8f2005-06-23 02:26:47 +000081 if (VG_(readlink)(tmp, buf, VKI_PATH_MAX) > 0 && buf[0] == '/')
82 return True;
83 else
84 return False;
njnae7359b2005-06-19 21:10:42 +000085}
86
njneb8896b2005-06-04 20:03:55 +000087/* Returns -1 on failure. */
88Int VG_(open) ( const Char* pathname, Int flags, Int mode )
89{
sewardja8d8e232005-06-07 20:04:56 +000090 SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
91 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +000092}
93
94void VG_(close) ( Int fd )
95{
sewardja8d8e232005-06-07 20:04:56 +000096 (void)VG_(do_syscall1)(__NR_close, fd);
njneb8896b2005-06-04 20:03:55 +000097}
98
99Int VG_(read) ( Int fd, void* buf, Int count)
100{
sewardja8d8e232005-06-07 20:04:56 +0000101 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
102 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000103}
104
105Int VG_(write) ( Int fd, const void* buf, Int count)
106{
sewardja8d8e232005-06-07 20:04:56 +0000107 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
108 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000109}
110
111Int VG_(pipe) ( Int fd[2] )
112{
sewardja8d8e232005-06-07 20:04:56 +0000113 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
114 return res.isError ? -1 : 0;
njneb8896b2005-06-04 20:03:55 +0000115}
116
117OffT VG_(lseek) ( Int fd, OffT offset, Int whence)
118{
sewardja8d8e232005-06-07 20:04:56 +0000119 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
120 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000121}
122
123Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
124{
sewardja8d8e232005-06-07 20:04:56 +0000125 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
126 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000127}
128
129Int VG_(fstat) ( Int fd, struct vki_stat* buf )
130{
sewardja8d8e232005-06-07 20:04:56 +0000131 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
132 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000133}
134
135Int VG_(dup2) ( Int oldfd, Int newfd )
136{
sewardja8d8e232005-06-07 20:04:56 +0000137 SysRes res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
138 return res.isError ? (-1) : res.val;
njneb8896b2005-06-04 20:03:55 +0000139}
140
njn327fe8a2005-06-12 02:49:35 +0000141/* Returns -1 on error. */
142Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
143{
144 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
145 return res.isError ? -1 : res.val;
146}
147
njneb8896b2005-06-04 20:03:55 +0000148Int VG_(rename) ( Char* old_name, Char* new_name )
149{
sewardja8d8e232005-06-07 20:04:56 +0000150 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
151 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000152}
153
154Int VG_(unlink) ( Char* file_name )
155{
sewardja8d8e232005-06-07 20:04:56 +0000156 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
157 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000158}
159
160/* Nb: we do not allow the Linux extension which malloc()s memory for the
161 buffer if buf==NULL, because we don't want Linux calling malloc() */
njn57ca7ab2005-06-21 23:44:58 +0000162Bool VG_(getcwd) ( Char* buf, SizeT size )
njneb8896b2005-06-04 20:03:55 +0000163{
sewardja8d8e232005-06-07 20:04:56 +0000164 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000165 vg_assert(buf != NULL);
166 res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
njn57ca7ab2005-06-21 23:44:58 +0000167 return res.isError ? False : True;
njneb8896b2005-06-04 20:03:55 +0000168}
169
170Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
171{
sewardja8d8e232005-06-07 20:04:56 +0000172 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000173 /* res = readlink( path, buf, bufsiz ); */
174 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardja8d8e232005-06-07 20:04:56 +0000175 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000176}
177
178Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
179{
sewardja8d8e232005-06-07 20:04:56 +0000180 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000181 /* res = getdents( fd, dirp, count ); */
182 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
sewardja8d8e232005-06-07 20:04:56 +0000183 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000184}
185
186/* ---------------------------------------------------------------------
187 Socket-related stuff. This is very Linux-kernel specific.
188 ------------------------------------------------------------------ */
189
190static
191Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
192
193static
194Int my_socket ( Int domain, Int type, Int protocol );
195
196static
197Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
198 Int addrlen );
199
200static
201UInt my_htonl ( UInt x )
202{
203 return
204 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
205 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
206}
207
208static
209UShort my_htons ( UShort x )
210{
211 return
212 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
213}
214
215
216/* The main function.
217
218 Supplied string contains either an ip address "192.168.0.1" or
219 an ip address and port pair, "192.168.0.1:1500". Parse these,
220 and return:
221 -1 if there is a parse error
222 -2 if no parse error, but specified host:port cannot be opened
223 the relevant file (socket) descriptor, otherwise.
224 is used.
225*/
226Int VG_(connect_via_socket)( UChar* str )
227{
228 Int sd, res;
229 struct vki_sockaddr_in servAddr;
230 UInt ip = 0;
231 UShort port = VG_CLO_DEFAULT_LOGPORT;
232 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
233 if (!ok)
234 return -1;
235
236 //if (0)
237 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
238 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
239 // (ip >> 8) & 0xFF, ip & 0xFF,
240 // (UInt)port );
241
242 servAddr.sin_family = VKI_AF_INET;
243 servAddr.sin_addr.s_addr = my_htonl(ip);
244 servAddr.sin_port = my_htons(port);
245
246 /* create socket */
247 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
248 if (sd < 0) {
249 /* this shouldn't happen ... nevertheless */
250 return -2;
251 }
252
253 /* connect to server */
254 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
255 sizeof(servAddr));
256 if (res < 0) {
257 /* connection failed */
258 return -2;
259 }
260
261 return sd;
262}
263
264
265/* Let d = one or more digits. Accept either:
266 d.d.d.d or d.d.d.d:d
267*/
268Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
269{
270# define GET_CH ((*str) ? (*str++) : 0)
271 UInt ipa, i, j, c, any;
272 ipa = 0;
273 for (i = 0; i < 4; i++) {
274 j = 0;
275 any = 0;
276 while (1) {
277 c = GET_CH;
278 if (c < '0' || c > '9') break;
279 j = 10 * j + (int)(c - '0');
280 any = 1;
281 }
282 if (any == 0 || j > 255) goto syntaxerr;
283 ipa = (ipa << 8) + j;
284 if (i <= 2 && c != '.') goto syntaxerr;
285 }
286 if (c == 0 || c == ':')
287 *ip_addr = ipa;
288 if (c == 0) goto ok;
289 if (c != ':') goto syntaxerr;
290 j = 0;
291 any = 0;
292 while (1) {
293 c = GET_CH;
294 if (c < '0' || c > '9') break;
295 j = j * 10 + (int)(c - '0');
296 any = 1;
297 if (j > 65535) goto syntaxerr;
298 }
299 if (any == 0 || c != 0) goto syntaxerr;
300 if (j < 1024) goto syntaxerr;
301 *port = (UShort)j;
302 ok:
303 return 1;
304 syntaxerr:
305 return 0;
306# undef GET_CH
307}
308
njneb8896b2005-06-04 20:03:55 +0000309static
310Int my_socket ( Int domain, Int type, Int protocol )
311{
cerion85665ca2005-06-20 15:51:07 +0000312#if defined(VGP_x86_linux)
sewardja8d8e232005-06-07 20:04:56 +0000313 SysRes res;
314 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000315 args[0] = domain;
316 args[1] = type;
317 args[2] = protocol;
318 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000319 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000320
321#elif defined(VGP_amd64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000322 // AMD64/Linux doesn't define __NR_socketcall... see comment above
323 // VG_(sigpending)() for more details.
324 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000325
326#elif defined(VGP_ppc32_linux)
sewardj8a851282005-07-02 10:13:05 +0000327 //CAB: TODO
cerion85665ca2005-06-20 15:51:07 +0000328 I_die_here;
329
330#else
331# error Unknown arch
332#endif
njneb8896b2005-06-04 20:03:55 +0000333}
334
335static
336Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
337 Int addrlen )
338{
cerion85665ca2005-06-20 15:51:07 +0000339#if defined(VGP_x86_linux)
sewardja8d8e232005-06-07 20:04:56 +0000340 SysRes res;
341 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000342 args[0] = sockfd;
343 args[1] = (UWord)serv_addr;
344 args[2] = addrlen;
345 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000346 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000347
348#elif defined(VGP_amd64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000349 // AMD64/Linux doesn't define __NR_socketcall... see comment above
350 // VG_(sigpending)() for more details.
351 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000352
353#elif defined(VGP_ppc32_linux)
sewardj8a851282005-07-02 10:13:05 +0000354 //CAB: TODO
cerion85665ca2005-06-20 15:51:07 +0000355 I_die_here;
356
357#else
358# error Unknown arch
359#endif
njneb8896b2005-06-04 20:03:55 +0000360}
361
362Int VG_(write_socket)( Int sd, void *msg, Int count )
363{
njneb8896b2005-06-04 20:03:55 +0000364 /* This is actually send(). */
njneb8896b2005-06-04 20:03:55 +0000365 /* Requests not to send SIGPIPE on errors on stream oriented
366 sockets when the other end breaks the connection. The EPIPE
367 error is still returned. */
368 Int flags = VKI_MSG_NOSIGNAL;
369
cerion85665ca2005-06-20 15:51:07 +0000370#if defined(VGP_x86_linux)
sewardja8d8e232005-06-07 20:04:56 +0000371 SysRes res;
372 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000373 args[0] = sd;
374 args[1] = (UWord)msg;
375 args[2] = count;
376 args[3] = flags;
377 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000378 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000379
380#elif defined(VGP_amd64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000381 // AMD64/Linux doesn't define __NR_socketcall... see comment above
382 // VG_(sigpending)() for more details.
383 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000384
385#elif defined(VGP_ppc32_linux)
sewardj8a851282005-07-02 10:13:05 +0000386 //CAB: TODO
cerion85665ca2005-06-20 15:51:07 +0000387 I_die_here;
388 flags = 0; // stop compiler complaints
389
390#else
391# error Unknown arch
392#endif
njneb8896b2005-06-04 20:03:55 +0000393}
394
395Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
396{
sewardja8d8e232005-06-07 20:04:56 +0000397 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000398
sewardj8a851282005-07-02 10:13:05 +0000399#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000400 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000401 args[0] = sd;
402 args[1] = (UWord)name;
403 args[2] = (UWord)namelen;
404 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000405 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000406
cerion85665ca2005-06-20 15:51:07 +0000407#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000408 res = VG_(do_syscall3)( __NR_getsockname,
409 (UWord)sd, (UWord)name, (UWord)namelen );
410 return res.isError ? -1 : res.val;
411
cerion85665ca2005-06-20 15:51:07 +0000412#else
413# error Unknown arch
414#endif
njneb8896b2005-06-04 20:03:55 +0000415}
416
417Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
418{
sewardja8d8e232005-06-07 20:04:56 +0000419 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000420
sewardj8a851282005-07-02 10:13:05 +0000421#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000422 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000423 args[0] = sd;
424 args[1] = (UWord)name;
425 args[2] = (UWord)namelen;
426 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000427 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000428
cerion85665ca2005-06-20 15:51:07 +0000429#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000430 res = VG_(do_syscall3)( __NR_getpeername,
431 (UWord)sd, (UWord)name, (UWord)namelen );
432 return res.isError ? -1 : res.val;
433
cerion85665ca2005-06-20 15:51:07 +0000434#else
sewardj8a851282005-07-02 10:13:05 +0000435# error Unknown archx
cerion85665ca2005-06-20 15:51:07 +0000436#endif
njneb8896b2005-06-04 20:03:55 +0000437}
438
439Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
440 Int *optlen)
441{
sewardja8d8e232005-06-07 20:04:56 +0000442 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000443
sewardj8a851282005-07-02 10:13:05 +0000444#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000445 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000446 args[0] = sd;
447 args[1] = level;
448 args[2] = optname;
449 args[3] = (UWord)optval;
450 args[4] = (UWord)optlen;
451 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000452 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000453
cerion85665ca2005-06-20 15:51:07 +0000454#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000455 res = VG_(do_syscall5)( __NR_getsockopt,
456 (UWord)sd, (UWord)level, (UWord)optname,
457 (UWord)optval, (UWord)optlen );
458 return res.isError ? -1 : res.val;
459
cerion85665ca2005-06-20 15:51:07 +0000460#else
461# error Unknown arch
462#endif
njneb8896b2005-06-04 20:03:55 +0000463}
464
465
466
467/*--------------------------------------------------------------------*/
468/*--- end ---*/
469/*--------------------------------------------------------------------*/
470