blob: 4afe9cfd51b243e8cd3b6bfc67f7098fe6d335b4 [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
sewardje4b0bf02006-06-05 23:21:15 +000010 Copyright (C) 2000-2006 Julian Seward
njneb8896b2005-06-04 20:03:55 +000011 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);
tomf4c23102005-10-31 17:05:21 +0000117 return res.isError ? (-1) : res.val;
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{
tom574b8932006-07-05 17:47:46 +0000136#ifdef __NR_fstat64
137 struct vki_stat64 buf;
138 SysRes res = VG_(do_syscall2)(__NR_fstat64, fd, (UWord)&buf);
139#else
sewardj45f4e7c2005-09-27 19:20:21 +0000140 struct vki_stat buf;
141 SysRes res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)&buf);
tom574b8932006-07-05 17:47:46 +0000142#endif
sewardj45f4e7c2005-09-27 19:20:21 +0000143 return res.isError ? (-1) : buf.st_size;
144}
145
njn73750612005-10-14 03:11:30 +0000146Bool VG_(is_dir) ( HChar* f )
147{
148 struct vki_stat buf;
149 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)f, (UWord)&buf);
150 return res.isError ? False
151 : VKI_S_ISDIR(buf.st_mode) ? True : False;
152}
153
sewardj45f4e7c2005-09-27 19:20:21 +0000154SysRes VG_(dup) ( Int oldfd )
155{
156 return VG_(do_syscall1)(__NR_dup, oldfd);
njneb8896b2005-06-04 20:03:55 +0000157}
158
njn327fe8a2005-06-12 02:49:35 +0000159/* Returns -1 on error. */
160Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
161{
162 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
163 return res.isError ? -1 : res.val;
164}
165
njneb8896b2005-06-04 20:03:55 +0000166Int VG_(rename) ( Char* old_name, Char* new_name )
167{
sewardja8d8e232005-06-07 20:04:56 +0000168 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
169 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000170}
171
172Int VG_(unlink) ( Char* file_name )
173{
sewardja8d8e232005-06-07 20:04:56 +0000174 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
175 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000176}
177
178/* Nb: we do not allow the Linux extension which malloc()s memory for the
179 buffer if buf==NULL, because we don't want Linux calling malloc() */
njn57ca7ab2005-06-21 23:44:58 +0000180Bool VG_(getcwd) ( Char* buf, SizeT size )
njneb8896b2005-06-04 20:03:55 +0000181{
sewardja8d8e232005-06-07 20:04:56 +0000182 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000183 vg_assert(buf != NULL);
184 res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
njn57ca7ab2005-06-21 23:44:58 +0000185 return res.isError ? False : True;
njneb8896b2005-06-04 20:03:55 +0000186}
187
188Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
189{
sewardja8d8e232005-06-07 20:04:56 +0000190 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000191 /* res = readlink( path, buf, bufsiz ); */
192 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardja8d8e232005-06-07 20:04:56 +0000193 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000194}
195
196Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
197{
sewardja8d8e232005-06-07 20:04:56 +0000198 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000199 /* res = getdents( fd, dirp, count ); */
200 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
sewardja8d8e232005-06-07 20:04:56 +0000201 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000202}
203
sewardj45f4e7c2005-09-27 19:20:21 +0000204/* Check accessibility of a file. Returns zero for access granted,
205 nonzero otherwise. */
206Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
207{
208#if defined(VGO_linux)
209 /* Very annoyingly, I cannot find any definition for R_OK et al in
210 the kernel interfaces. Therefore I reluctantly resort to
211 hardwiring in these magic numbers that I determined by
212 experimentation. */
213 UWord w = (irusr ? 4/*R_OK*/ : 0)
214 | (iwusr ? 2/*W_OK*/ : 0)
215 | (ixusr ? 1/*X_OK*/ : 0);
216 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
217 return res.isError ? 1 : res.val;
218#else
219# error "Don't know how to do VG_(access) on this OS"
220#endif
221}
222
njn73750612005-10-14 03:11:30 +0000223/*
224 Emulate the normal Unix permissions checking algorithm.
225
226 If owner matches, then use the owner permissions, else
227 if group matches, then use the group permissions, else
228 use other permissions.
229
230 Note that we can't deal with SUID/SGID, so we refuse to run them
231 (otherwise the executable may misbehave if it doesn't have the
232 permissions it thinks it does).
233*/
234/* returns: 0 = success, non-0 is failure */
235Int VG_(check_executable)(HChar* f)
236{
toma346c262006-09-29 08:12:08 +0000237#ifdef __NR_stat64
238 struct vki_stat64 st;
239 SysRes res = VG_(do_syscall2)(__NR_stat64, (UWord)f, (UWord)&st);
240#else
njn73750612005-10-14 03:11:30 +0000241 struct vki_stat st;
toma346c262006-09-29 08:12:08 +0000242 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)f, (UWord)&st);
243#endif
njn73750612005-10-14 03:11:30 +0000244
njn73750612005-10-14 03:11:30 +0000245 if (res.isError) {
246 return res.val;
247 }
248
249 if (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) {
250 //VG_(printf)("Can't execute suid/sgid executable %s\n", exe);
251 return VKI_EACCES;
252 }
253
254 if (VG_(geteuid)() == st.st_uid) {
255 if (!(st.st_mode & VKI_S_IXUSR))
256 return VKI_EACCES;
257 } else {
258 int grpmatch = 0;
259
260 if (VG_(getegid)() == st.st_gid)
261 grpmatch = 1;
262 else {
263 UInt groups[32];
264 Int ngrp = VG_(getgroups)(32, groups);
265 Int i;
266 /* ngrp will be -1 if VG_(getgroups) failed. */
267 for (i = 0; i < ngrp; i++) {
268 if (groups[i] == st.st_gid) {
269 grpmatch = 1;
270 break;
271 }
272 }
273 }
274
275 if (grpmatch) {
276 if (!(st.st_mode & VKI_S_IXGRP)) {
277 return VKI_EACCES;
278 }
279 } else if (!(st.st_mode & VKI_S_IXOTH)) {
280 return VKI_EACCES;
281 }
282 }
283
284 return 0;
285}
286
sewardj45f4e7c2005-09-27 19:20:21 +0000287SysRes VG_(pread) ( Int fd, void* buf, Int count, Int offset )
288{
289 OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET);
tomf4c23102005-10-31 17:05:21 +0000290 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000291 return VG_(mk_SysRes_Error)( VKI_EINVAL );
tom60a4b0b2005-10-12 10:45:27 +0000292 return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
sewardj45f4e7c2005-09-27 19:20:21 +0000293}
294
295/* Create and open (-rw------) a tmp file name incorporating said arg.
296 Returns -1 on failure, else the fd of the file. If fullname is
297 non-NULL, the file's name is written into it. The number of bytes
298 written is guaranteed not to exceed 64+strlen(part_of_name). */
299
300Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
301{
302 HChar buf[200];
303 Int n, tries, fd;
304 UInt seed;
305 SysRes sres;
306
307 vg_assert(part_of_name);
308 n = VG_(strlen)(part_of_name);
309 vg_assert(n > 0 && n < 100);
310
311 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
312
313 tries = 0;
314 while (True) {
315 if (tries > 10)
316 return -1;
317 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
318 part_of_name, VG_(random)( &seed ));
319 if (0)
320 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
321
322 sres = VG_(open)(buf,
323 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
324 VKI_S_IRUSR|VKI_S_IWUSR);
325 if (sres.isError)
326 continue;
327 /* VG_(safe_fd) doesn't return if it fails. */
328 fd = VG_(safe_fd)( sres.val );
329 if (fullname)
330 VG_(strcpy)( fullname, buf );
331 return fd;
332 }
333 /* NOTREACHED */
334}
335
336
njneb8896b2005-06-04 20:03:55 +0000337/* ---------------------------------------------------------------------
338 Socket-related stuff. This is very Linux-kernel specific.
339 ------------------------------------------------------------------ */
340
341static
342Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
343
344static
345Int my_socket ( Int domain, Int type, Int protocol );
346
347static
348Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
349 Int addrlen );
350
toma4a4f412005-11-17 12:01:56 +0000351UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000352{
sewardja1c4bfb2005-10-18 02:15:39 +0000353# if defined(VG_BIGENDIAN)
354 return x;
355# else
njneb8896b2005-06-04 20:03:55 +0000356 return
357 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
358 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000359# endif
njneb8896b2005-06-04 20:03:55 +0000360}
361
toma4a4f412005-11-17 12:01:56 +0000362UInt VG_(ntohl) ( UInt x )
363{
364# if defined(VG_BIGENDIAN)
365 return x;
366# else
367 return
368 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
369 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
370# endif
371}
372
373UShort VG_(htons) ( UShort x )
374{
375# if defined(VG_BIGENDIAN)
376 return x;
377# else
378 return
379 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
380# endif
381}
382
383UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000384{
sewardja1c4bfb2005-10-18 02:15:39 +0000385# if defined(VG_BIGENDIAN)
386 return x;
387# else
njneb8896b2005-06-04 20:03:55 +0000388 return
389 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000390# endif
njneb8896b2005-06-04 20:03:55 +0000391}
392
393
394/* The main function.
395
396 Supplied string contains either an ip address "192.168.0.1" or
397 an ip address and port pair, "192.168.0.1:1500". Parse these,
398 and return:
399 -1 if there is a parse error
400 -2 if no parse error, but specified host:port cannot be opened
401 the relevant file (socket) descriptor, otherwise.
402 is used.
403*/
404Int VG_(connect_via_socket)( UChar* str )
405{
406 Int sd, res;
407 struct vki_sockaddr_in servAddr;
408 UInt ip = 0;
409 UShort port = VG_CLO_DEFAULT_LOGPORT;
410 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
411 if (!ok)
412 return -1;
413
414 //if (0)
415 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
416 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
417 // (ip >> 8) & 0xFF, ip & 0xFF,
418 // (UInt)port );
419
420 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +0000421 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
422 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +0000423
424 /* create socket */
425 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
426 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000427 /* this shouldn't happen ... nevertheless */
428 return -2;
njneb8896b2005-06-04 20:03:55 +0000429 }
sewardja1c4bfb2005-10-18 02:15:39 +0000430
njneb8896b2005-06-04 20:03:55 +0000431 /* connect to server */
432 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
433 sizeof(servAddr));
434 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000435 /* connection failed */
436 return -2;
njneb8896b2005-06-04 20:03:55 +0000437 }
438
439 return sd;
440}
441
442
443/* Let d = one or more digits. Accept either:
444 d.d.d.d or d.d.d.d:d
445*/
446Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
447{
448# define GET_CH ((*str) ? (*str++) : 0)
449 UInt ipa, i, j, c, any;
450 ipa = 0;
451 for (i = 0; i < 4; i++) {
452 j = 0;
453 any = 0;
454 while (1) {
455 c = GET_CH;
456 if (c < '0' || c > '9') break;
457 j = 10 * j + (int)(c - '0');
458 any = 1;
459 }
460 if (any == 0 || j > 255) goto syntaxerr;
461 ipa = (ipa << 8) + j;
462 if (i <= 2 && c != '.') goto syntaxerr;
463 }
464 if (c == 0 || c == ':')
465 *ip_addr = ipa;
466 if (c == 0) goto ok;
467 if (c != ':') goto syntaxerr;
468 j = 0;
469 any = 0;
470 while (1) {
471 c = GET_CH;
472 if (c < '0' || c > '9') break;
473 j = j * 10 + (int)(c - '0');
474 any = 1;
475 if (j > 65535) goto syntaxerr;
476 }
477 if (any == 0 || c != 0) goto syntaxerr;
478 if (j < 1024) goto syntaxerr;
479 *port = (UShort)j;
480 ok:
481 return 1;
482 syntaxerr:
483 return 0;
484# undef GET_CH
485}
486
njneb8896b2005-06-04 20:03:55 +0000487static
488Int my_socket ( Int domain, Int type, Int protocol )
489{
sewardj2c48c7b2005-11-29 13:05:56 +0000490#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000491 SysRes res;
492 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000493 args[0] = domain;
494 args[1] = type;
495 args[2] = protocol;
496 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000497 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000498
499#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000500 SysRes res;
501 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
502 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000503
cerion85665ca2005-06-20 15:51:07 +0000504#else
505# error Unknown arch
506#endif
njneb8896b2005-06-04 20:03:55 +0000507}
508
509static
510Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
511 Int addrlen )
512{
sewardj2c48c7b2005-11-29 13:05:56 +0000513#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000514 SysRes res;
515 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000516 args[0] = sockfd;
517 args[1] = (UWord)serv_addr;
518 args[2] = addrlen;
519 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000520 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000521
522#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000523 SysRes res;
524 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
525 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000526
cerion85665ca2005-06-20 15:51:07 +0000527#else
528# error Unknown arch
529#endif
njneb8896b2005-06-04 20:03:55 +0000530}
531
532Int VG_(write_socket)( Int sd, void *msg, Int count )
533{
njneb8896b2005-06-04 20:03:55 +0000534 /* This is actually send(). */
njneb8896b2005-06-04 20:03:55 +0000535 /* Requests not to send SIGPIPE on errors on stream oriented
536 sockets when the other end breaks the connection. The EPIPE
537 error is still returned. */
538 Int flags = VKI_MSG_NOSIGNAL;
539
sewardj2c48c7b2005-11-29 13:05:56 +0000540#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000541 SysRes res;
542 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000543 args[0] = sd;
544 args[1] = (UWord)msg;
545 args[2] = count;
546 args[3] = flags;
547 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000548 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000549
550#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000551 SysRes res;
552 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, flags, 0,0);
553 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000554
cerion85665ca2005-06-20 15:51:07 +0000555#else
556# error Unknown arch
557#endif
njneb8896b2005-06-04 20:03:55 +0000558}
559
560Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
561{
sewardja8d8e232005-06-07 20:04:56 +0000562 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000563
sewardj2c48c7b2005-11-29 13:05:56 +0000564#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000565 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000566 args[0] = sd;
567 args[1] = (UWord)name;
568 args[2] = (UWord)namelen;
569 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000570 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000571
cerion85665ca2005-06-20 15:51:07 +0000572#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000573 res = VG_(do_syscall3)( __NR_getsockname,
574 (UWord)sd, (UWord)name, (UWord)namelen );
575 return res.isError ? -1 : res.val;
576
cerion85665ca2005-06-20 15:51:07 +0000577#else
578# error Unknown arch
579#endif
njneb8896b2005-06-04 20:03:55 +0000580}
581
582Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
583{
sewardja8d8e232005-06-07 20:04:56 +0000584 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000585
sewardj2c48c7b2005-11-29 13:05:56 +0000586#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000587 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000588 args[0] = sd;
589 args[1] = (UWord)name;
590 args[2] = (UWord)namelen;
591 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000592 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000593
cerion85665ca2005-06-20 15:51:07 +0000594#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000595 res = VG_(do_syscall3)( __NR_getpeername,
596 (UWord)sd, (UWord)name, (UWord)namelen );
597 return res.isError ? -1 : res.val;
598
cerion85665ca2005-06-20 15:51:07 +0000599#else
sewardj8a851282005-07-02 10:13:05 +0000600# error Unknown archx
cerion85665ca2005-06-20 15:51:07 +0000601#endif
njneb8896b2005-06-04 20:03:55 +0000602}
603
604Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
605 Int *optlen)
606{
sewardja8d8e232005-06-07 20:04:56 +0000607 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000608
sewardj2c48c7b2005-11-29 13:05:56 +0000609#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000610 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000611 args[0] = sd;
612 args[1] = level;
613 args[2] = optname;
614 args[3] = (UWord)optval;
615 args[4] = (UWord)optlen;
616 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000617 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000618
cerion85665ca2005-06-20 15:51:07 +0000619#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000620 res = VG_(do_syscall5)( __NR_getsockopt,
621 (UWord)sd, (UWord)level, (UWord)optname,
622 (UWord)optval, (UWord)optlen );
623 return res.isError ? -1 : res.val;
624
cerion85665ca2005-06-20 15:51:07 +0000625#else
626# error Unknown arch
627#endif
njneb8896b2005-06-04 20:03:55 +0000628}
629
630
631
632/*--------------------------------------------------------------------*/
633/*--- end ---*/
634/*--------------------------------------------------------------------*/
635