blob: f86f2e2772566b6223b5f8f541ea6901d70b04ec [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"
sewardjfdf91b42005-09-28 00:53:09 +000035#include "pub_core_libcprint.h" // VG_(sprintf)
sewardj45f4e7c2005-09-27 19:20:21 +000036#include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
sewardjfdf91b42005-09-28 00:53:09 +000037#include "pub_core_clientstate.h" // VG_(fd_hard_limit)
njn9abd6082005-06-17 21:31:45 +000038#include "pub_core_syscall.h"
njneb8896b2005-06-04 20:03:55 +000039#include "vki_unistd.h"
40
41/* ---------------------------------------------------------------------
42 File stuff
43 ------------------------------------------------------------------ */
44
45static inline Bool fd_exists(Int fd)
46{
47 struct vki_stat st;
48
49 return VG_(fstat)(fd, &st) == 0;
50}
51
52/* Move an fd into the Valgrind-safe range */
53Int VG_(safe_fd)(Int oldfd)
54{
55 Int newfd;
56
57 vg_assert(VG_(fd_hard_limit) != -1);
58
59 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
60 if (newfd != -1)
61 VG_(close)(oldfd);
62
63 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
64
65 vg_assert(newfd >= VG_(fd_hard_limit));
66 return newfd;
67}
68
njnae7359b2005-06-19 21:10:42 +000069/* Given a file descriptor, attempt to deduce its filename. To do
70 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
njnf845f8f2005-06-23 02:26:47 +000071 or if it doesn't exist, we return False. */
72Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
njnae7359b2005-06-19 21:10:42 +000073{
74 HChar tmp[64];
75
76 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
njnf845f8f2005-06-23 02:26:47 +000077 VG_(memset)(buf, 0, n_buf);
njnae7359b2005-06-19 21:10:42 +000078
sewardj45f4e7c2005-09-27 19:20:21 +000079 if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/')
njnf845f8f2005-06-23 02:26:47 +000080 return True;
81 else
82 return False;
njnae7359b2005-06-19 21:10:42 +000083}
84
sewardj92645592005-07-23 09:18:34 +000085SysRes VG_(open) ( const Char* pathname, Int flags, Int mode )
njneb8896b2005-06-04 20:03:55 +000086{
sewardja8d8e232005-06-07 20:04:56 +000087 SysRes res = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
sewardj92645592005-07-23 09:18:34 +000088 return res;
njneb8896b2005-06-04 20:03:55 +000089}
90
91void VG_(close) ( Int fd )
92{
sewardja8d8e232005-06-07 20:04:56 +000093 (void)VG_(do_syscall1)(__NR_close, fd);
njneb8896b2005-06-04 20:03:55 +000094}
95
96Int VG_(read) ( Int fd, void* buf, Int count)
97{
sewardja8d8e232005-06-07 20:04:56 +000098 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
99 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000100}
101
102Int VG_(write) ( Int fd, const void* buf, Int count)
103{
sewardja8d8e232005-06-07 20:04:56 +0000104 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
105 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000106}
107
108Int VG_(pipe) ( Int fd[2] )
109{
sewardja8d8e232005-06-07 20:04:56 +0000110 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
111 return res.isError ? -1 : 0;
njneb8896b2005-06-04 20:03:55 +0000112}
113
sewardj45f4e7c2005-09-27 19:20:21 +0000114OffT VG_(lseek) ( Int fd, OffT offset, Int whence )
njneb8896b2005-06-04 20:03:55 +0000115{
sewardja8d8e232005-06-07 20:04:56 +0000116 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
117 return res.isError ? (-1) : 0;
sewardj45f4e7c2005-09-27 19:20:21 +0000118 /* if you change the error-reporting conventions of this, also
119 change VG_(pread) and all other usage points. */
njneb8896b2005-06-04 20:03:55 +0000120}
121
tom6c93c4f2005-08-05 07:46:32 +0000122SysRes VG_(stat) ( Char* file_name, struct vki_stat* buf )
njneb8896b2005-06-04 20:03:55 +0000123{
sewardja8d8e232005-06-07 20:04:56 +0000124 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
tom6c93c4f2005-08-05 07:46:32 +0000125 return res;
njneb8896b2005-06-04 20:03:55 +0000126}
127
128Int VG_(fstat) ( Int fd, struct vki_stat* buf )
129{
sewardja8d8e232005-06-07 20:04:56 +0000130 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
131 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000132}
133
sewardj45f4e7c2005-09-27 19:20:21 +0000134Int VG_(fsize) ( Int fd )
njneb8896b2005-06-04 20:03:55 +0000135{
sewardj45f4e7c2005-09-27 19:20:21 +0000136 struct vki_stat buf;
137 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
138 return res.isError ? (-1) : buf.st_size;
139}
140
141SysRes VG_(dup) ( Int oldfd )
142{
143 return VG_(do_syscall1)(__NR_dup, oldfd);
njneb8896b2005-06-04 20:03:55 +0000144}
145
njn327fe8a2005-06-12 02:49:35 +0000146/* Returns -1 on error. */
147Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
148{
149 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
150 return res.isError ? -1 : res.val;
151}
152
njneb8896b2005-06-04 20:03:55 +0000153Int VG_(rename) ( Char* old_name, Char* new_name )
154{
sewardja8d8e232005-06-07 20:04:56 +0000155 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
156 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000157}
158
159Int VG_(unlink) ( Char* file_name )
160{
sewardja8d8e232005-06-07 20:04:56 +0000161 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
162 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000163}
164
165/* Nb: we do not allow the Linux extension which malloc()s memory for the
166 buffer if buf==NULL, because we don't want Linux calling malloc() */
njn57ca7ab2005-06-21 23:44:58 +0000167Bool VG_(getcwd) ( Char* buf, SizeT size )
njneb8896b2005-06-04 20:03:55 +0000168{
sewardja8d8e232005-06-07 20:04:56 +0000169 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000170 vg_assert(buf != NULL);
171 res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
njn57ca7ab2005-06-21 23:44:58 +0000172 return res.isError ? False : True;
njneb8896b2005-06-04 20:03:55 +0000173}
174
175Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
176{
sewardja8d8e232005-06-07 20:04:56 +0000177 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000178 /* res = readlink( path, buf, bufsiz ); */
179 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardja8d8e232005-06-07 20:04:56 +0000180 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000181}
182
183Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
184{
sewardja8d8e232005-06-07 20:04:56 +0000185 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000186 /* res = getdents( fd, dirp, count ); */
187 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
sewardja8d8e232005-06-07 20:04:56 +0000188 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000189}
190
sewardj45f4e7c2005-09-27 19:20:21 +0000191/* Check accessibility of a file. Returns zero for access granted,
192 nonzero otherwise. */
193Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
194{
195#if defined(VGO_linux)
196 /* Very annoyingly, I cannot find any definition for R_OK et al in
197 the kernel interfaces. Therefore I reluctantly resort to
198 hardwiring in these magic numbers that I determined by
199 experimentation. */
200 UWord w = (irusr ? 4/*R_OK*/ : 0)
201 | (iwusr ? 2/*W_OK*/ : 0)
202 | (ixusr ? 1/*X_OK*/ : 0);
203 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
204 return res.isError ? 1 : res.val;
205#else
206# error "Don't know how to do VG_(access) on this OS"
207#endif
208}
209
210SysRes VG_(pread) ( Int fd, void* buf, Int count, Int offset )
211{
212 OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET);
213 if (off != 0)
214 return VG_(mk_SysRes_Error)( VKI_EINVAL );
tom60a4b0b2005-10-12 10:45:27 +0000215 return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
sewardj45f4e7c2005-09-27 19:20:21 +0000216}
217
218/* Create and open (-rw------) a tmp file name incorporating said arg.
219 Returns -1 on failure, else the fd of the file. If fullname is
220 non-NULL, the file's name is written into it. The number of bytes
221 written is guaranteed not to exceed 64+strlen(part_of_name). */
222
223Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
224{
225 HChar buf[200];
226 Int n, tries, fd;
227 UInt seed;
228 SysRes sres;
229
230 vg_assert(part_of_name);
231 n = VG_(strlen)(part_of_name);
232 vg_assert(n > 0 && n < 100);
233
234 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
235
236 tries = 0;
237 while (True) {
238 if (tries > 10)
239 return -1;
240 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
241 part_of_name, VG_(random)( &seed ));
242 if (0)
243 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
244
245 sres = VG_(open)(buf,
246 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
247 VKI_S_IRUSR|VKI_S_IWUSR);
248 if (sres.isError)
249 continue;
250 /* VG_(safe_fd) doesn't return if it fails. */
251 fd = VG_(safe_fd)( sres.val );
252 if (fullname)
253 VG_(strcpy)( fullname, buf );
254 return fd;
255 }
256 /* NOTREACHED */
257}
258
259
njneb8896b2005-06-04 20:03:55 +0000260/* ---------------------------------------------------------------------
261 Socket-related stuff. This is very Linux-kernel specific.
262 ------------------------------------------------------------------ */
263
264static
265Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
266
267static
268Int my_socket ( Int domain, Int type, Int protocol );
269
270static
271Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
272 Int addrlen );
273
274static
275UInt my_htonl ( UInt x )
276{
277 return
278 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
279 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
280}
281
282static
283UShort my_htons ( UShort x )
284{
285 return
286 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
287}
288
289
290/* The main function.
291
292 Supplied string contains either an ip address "192.168.0.1" or
293 an ip address and port pair, "192.168.0.1:1500". Parse these,
294 and return:
295 -1 if there is a parse error
296 -2 if no parse error, but specified host:port cannot be opened
297 the relevant file (socket) descriptor, otherwise.
298 is used.
299*/
300Int VG_(connect_via_socket)( UChar* str )
301{
302 Int sd, res;
303 struct vki_sockaddr_in servAddr;
304 UInt ip = 0;
305 UShort port = VG_CLO_DEFAULT_LOGPORT;
306 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
307 if (!ok)
308 return -1;
309
310 //if (0)
311 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
312 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
313 // (ip >> 8) & 0xFF, ip & 0xFF,
314 // (UInt)port );
315
316 servAddr.sin_family = VKI_AF_INET;
317 servAddr.sin_addr.s_addr = my_htonl(ip);
318 servAddr.sin_port = my_htons(port);
319
320 /* create socket */
321 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
322 if (sd < 0) {
323 /* this shouldn't happen ... nevertheless */
324 return -2;
325 }
326
327 /* connect to server */
328 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
329 sizeof(servAddr));
330 if (res < 0) {
331 /* connection failed */
332 return -2;
333 }
334
335 return sd;
336}
337
338
339/* Let d = one or more digits. Accept either:
340 d.d.d.d or d.d.d.d:d
341*/
342Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
343{
344# define GET_CH ((*str) ? (*str++) : 0)
345 UInt ipa, i, j, c, any;
346 ipa = 0;
347 for (i = 0; i < 4; i++) {
348 j = 0;
349 any = 0;
350 while (1) {
351 c = GET_CH;
352 if (c < '0' || c > '9') break;
353 j = 10 * j + (int)(c - '0');
354 any = 1;
355 }
356 if (any == 0 || j > 255) goto syntaxerr;
357 ipa = (ipa << 8) + j;
358 if (i <= 2 && c != '.') goto syntaxerr;
359 }
360 if (c == 0 || c == ':')
361 *ip_addr = ipa;
362 if (c == 0) goto ok;
363 if (c != ':') goto syntaxerr;
364 j = 0;
365 any = 0;
366 while (1) {
367 c = GET_CH;
368 if (c < '0' || c > '9') break;
369 j = j * 10 + (int)(c - '0');
370 any = 1;
371 if (j > 65535) goto syntaxerr;
372 }
373 if (any == 0 || c != 0) goto syntaxerr;
374 if (j < 1024) goto syntaxerr;
375 *port = (UShort)j;
376 ok:
377 return 1;
378 syntaxerr:
379 return 0;
380# undef GET_CH
381}
382
njneb8896b2005-06-04 20:03:55 +0000383static
384Int my_socket ( Int domain, Int type, Int protocol )
385{
sewardj21ccba82005-10-07 23:04:17 +0000386#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000387 SysRes res;
388 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000389 args[0] = domain;
390 args[1] = type;
391 args[2] = protocol;
392 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000393 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000394
395#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000396 SysRes res;
397 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
398 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000399
cerion85665ca2005-06-20 15:51:07 +0000400#else
401# error Unknown arch
402#endif
njneb8896b2005-06-04 20:03:55 +0000403}
404
405static
406Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
407 Int addrlen )
408{
sewardj21ccba82005-10-07 23:04:17 +0000409#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000410 SysRes res;
411 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000412 args[0] = sockfd;
413 args[1] = (UWord)serv_addr;
414 args[2] = addrlen;
415 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000416 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000417
418#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000419 SysRes res;
420 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
421 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000422
cerion85665ca2005-06-20 15:51:07 +0000423#else
424# error Unknown arch
425#endif
njneb8896b2005-06-04 20:03:55 +0000426}
427
428Int VG_(write_socket)( Int sd, void *msg, Int count )
429{
njneb8896b2005-06-04 20:03:55 +0000430 /* This is actually send(). */
njneb8896b2005-06-04 20:03:55 +0000431 /* Requests not to send SIGPIPE on errors on stream oriented
432 sockets when the other end breaks the connection. The EPIPE
433 error is still returned. */
434 Int flags = VKI_MSG_NOSIGNAL;
435
cerion85665ca2005-06-20 15:51:07 +0000436#if defined(VGP_x86_linux)
sewardja8d8e232005-06-07 20:04:56 +0000437 SysRes res;
438 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000439 args[0] = sd;
440 args[1] = (UWord)msg;
441 args[2] = count;
442 args[3] = flags;
443 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000444 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000445
446#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000447 SysRes res;
448 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, flags, 0,0);
449 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000450
451#elif defined(VGP_ppc32_linux)
sewardj8a851282005-07-02 10:13:05 +0000452 //CAB: TODO
cerion85665ca2005-06-20 15:51:07 +0000453 I_die_here;
454 flags = 0; // stop compiler complaints
455
456#else
457# error Unknown arch
458#endif
njneb8896b2005-06-04 20:03:55 +0000459}
460
461Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
462{
sewardja8d8e232005-06-07 20:04:56 +0000463 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000464
sewardj8a851282005-07-02 10:13:05 +0000465#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000466 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000467 args[0] = sd;
468 args[1] = (UWord)name;
469 args[2] = (UWord)namelen;
470 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000471 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000472
cerion85665ca2005-06-20 15:51:07 +0000473#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000474 res = VG_(do_syscall3)( __NR_getsockname,
475 (UWord)sd, (UWord)name, (UWord)namelen );
476 return res.isError ? -1 : res.val;
477
cerion85665ca2005-06-20 15:51:07 +0000478#else
479# error Unknown arch
480#endif
njneb8896b2005-06-04 20:03:55 +0000481}
482
483Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
484{
sewardja8d8e232005-06-07 20:04:56 +0000485 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000486
sewardj8a851282005-07-02 10:13:05 +0000487#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000488 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000489 args[0] = sd;
490 args[1] = (UWord)name;
491 args[2] = (UWord)namelen;
492 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000493 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000494
cerion85665ca2005-06-20 15:51:07 +0000495#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000496 res = VG_(do_syscall3)( __NR_getpeername,
497 (UWord)sd, (UWord)name, (UWord)namelen );
498 return res.isError ? -1 : res.val;
499
cerion85665ca2005-06-20 15:51:07 +0000500#else
sewardj8a851282005-07-02 10:13:05 +0000501# error Unknown archx
cerion85665ca2005-06-20 15:51:07 +0000502#endif
njneb8896b2005-06-04 20:03:55 +0000503}
504
505Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
506 Int *optlen)
507{
sewardja8d8e232005-06-07 20:04:56 +0000508 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000509
sewardj8a851282005-07-02 10:13:05 +0000510#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000511 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000512 args[0] = sd;
513 args[1] = level;
514 args[2] = optname;
515 args[3] = (UWord)optval;
516 args[4] = (UWord)optlen;
517 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000518 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000519
cerion85665ca2005-06-20 15:51:07 +0000520#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000521 res = VG_(do_syscall5)( __NR_getsockopt,
522 (UWord)sd, (UWord)level, (UWord)optname,
523 (UWord)optval, (UWord)optlen );
524 return res.isError ? -1 : res.val;
525
cerion85665ca2005-06-20 15:51:07 +0000526#else
527# error Unknown arch
528#endif
njneb8896b2005-06-04 20:03:55 +0000529}
530
531
532
533/*--------------------------------------------------------------------*/
534/*--- end ---*/
535/*--------------------------------------------------------------------*/
536