blob: f84a1c24c02a40508a393f4d1967e3c3f63feb23 [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{
237 struct vki_stat st;
238 SysRes res;
239
240 res = VG_(stat)(f, &st);
241 if (res.isError) {
242 return res.val;
243 }
244
245 if (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) {
246 //VG_(printf)("Can't execute suid/sgid executable %s\n", exe);
247 return VKI_EACCES;
248 }
249
250 if (VG_(geteuid)() == st.st_uid) {
251 if (!(st.st_mode & VKI_S_IXUSR))
252 return VKI_EACCES;
253 } else {
254 int grpmatch = 0;
255
256 if (VG_(getegid)() == st.st_gid)
257 grpmatch = 1;
258 else {
259 UInt groups[32];
260 Int ngrp = VG_(getgroups)(32, groups);
261 Int i;
262 /* ngrp will be -1 if VG_(getgroups) failed. */
263 for (i = 0; i < ngrp; i++) {
264 if (groups[i] == st.st_gid) {
265 grpmatch = 1;
266 break;
267 }
268 }
269 }
270
271 if (grpmatch) {
272 if (!(st.st_mode & VKI_S_IXGRP)) {
273 return VKI_EACCES;
274 }
275 } else if (!(st.st_mode & VKI_S_IXOTH)) {
276 return VKI_EACCES;
277 }
278 }
279
280 return 0;
281}
282
sewardj45f4e7c2005-09-27 19:20:21 +0000283SysRes VG_(pread) ( Int fd, void* buf, Int count, Int offset )
284{
285 OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET);
tomf4c23102005-10-31 17:05:21 +0000286 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000287 return VG_(mk_SysRes_Error)( VKI_EINVAL );
tom60a4b0b2005-10-12 10:45:27 +0000288 return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
sewardj45f4e7c2005-09-27 19:20:21 +0000289}
290
291/* Create and open (-rw------) a tmp file name incorporating said arg.
292 Returns -1 on failure, else the fd of the file. If fullname is
293 non-NULL, the file's name is written into it. The number of bytes
294 written is guaranteed not to exceed 64+strlen(part_of_name). */
295
296Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
297{
298 HChar buf[200];
299 Int n, tries, fd;
300 UInt seed;
301 SysRes sres;
302
303 vg_assert(part_of_name);
304 n = VG_(strlen)(part_of_name);
305 vg_assert(n > 0 && n < 100);
306
307 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
308
309 tries = 0;
310 while (True) {
311 if (tries > 10)
312 return -1;
313 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
314 part_of_name, VG_(random)( &seed ));
315 if (0)
316 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
317
318 sres = VG_(open)(buf,
319 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
320 VKI_S_IRUSR|VKI_S_IWUSR);
321 if (sres.isError)
322 continue;
323 /* VG_(safe_fd) doesn't return if it fails. */
324 fd = VG_(safe_fd)( sres.val );
325 if (fullname)
326 VG_(strcpy)( fullname, buf );
327 return fd;
328 }
329 /* NOTREACHED */
330}
331
332
njneb8896b2005-06-04 20:03:55 +0000333/* ---------------------------------------------------------------------
334 Socket-related stuff. This is very Linux-kernel specific.
335 ------------------------------------------------------------------ */
336
337static
338Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
339
340static
341Int my_socket ( Int domain, Int type, Int protocol );
342
343static
344Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
345 Int addrlen );
346
toma4a4f412005-11-17 12:01:56 +0000347UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000348{
sewardja1c4bfb2005-10-18 02:15:39 +0000349# if defined(VG_BIGENDIAN)
350 return x;
351# else
njneb8896b2005-06-04 20:03:55 +0000352 return
353 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
354 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000355# endif
njneb8896b2005-06-04 20:03:55 +0000356}
357
toma4a4f412005-11-17 12:01:56 +0000358UInt VG_(ntohl) ( UInt x )
359{
360# if defined(VG_BIGENDIAN)
361 return x;
362# else
363 return
364 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
365 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
366# endif
367}
368
369UShort VG_(htons) ( UShort x )
370{
371# if defined(VG_BIGENDIAN)
372 return x;
373# else
374 return
375 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
376# endif
377}
378
379UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000380{
sewardja1c4bfb2005-10-18 02:15:39 +0000381# if defined(VG_BIGENDIAN)
382 return x;
383# else
njneb8896b2005-06-04 20:03:55 +0000384 return
385 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000386# endif
njneb8896b2005-06-04 20:03:55 +0000387}
388
389
390/* The main function.
391
392 Supplied string contains either an ip address "192.168.0.1" or
393 an ip address and port pair, "192.168.0.1:1500". Parse these,
394 and return:
395 -1 if there is a parse error
396 -2 if no parse error, but specified host:port cannot be opened
397 the relevant file (socket) descriptor, otherwise.
398 is used.
399*/
400Int VG_(connect_via_socket)( UChar* str )
401{
402 Int sd, res;
403 struct vki_sockaddr_in servAddr;
404 UInt ip = 0;
405 UShort port = VG_CLO_DEFAULT_LOGPORT;
406 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
407 if (!ok)
408 return -1;
409
410 //if (0)
411 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
412 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
413 // (ip >> 8) & 0xFF, ip & 0xFF,
414 // (UInt)port );
415
416 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +0000417 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
418 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +0000419
420 /* create socket */
421 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
422 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000423 /* this shouldn't happen ... nevertheless */
424 return -2;
njneb8896b2005-06-04 20:03:55 +0000425 }
sewardja1c4bfb2005-10-18 02:15:39 +0000426
njneb8896b2005-06-04 20:03:55 +0000427 /* connect to server */
428 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
429 sizeof(servAddr));
430 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000431 /* connection failed */
432 return -2;
njneb8896b2005-06-04 20:03:55 +0000433 }
434
435 return sd;
436}
437
438
439/* Let d = one or more digits. Accept either:
440 d.d.d.d or d.d.d.d:d
441*/
442Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
443{
444# define GET_CH ((*str) ? (*str++) : 0)
445 UInt ipa, i, j, c, any;
446 ipa = 0;
447 for (i = 0; i < 4; i++) {
448 j = 0;
449 any = 0;
450 while (1) {
451 c = GET_CH;
452 if (c < '0' || c > '9') break;
453 j = 10 * j + (int)(c - '0');
454 any = 1;
455 }
456 if (any == 0 || j > 255) goto syntaxerr;
457 ipa = (ipa << 8) + j;
458 if (i <= 2 && c != '.') goto syntaxerr;
459 }
460 if (c == 0 || c == ':')
461 *ip_addr = ipa;
462 if (c == 0) goto ok;
463 if (c != ':') goto syntaxerr;
464 j = 0;
465 any = 0;
466 while (1) {
467 c = GET_CH;
468 if (c < '0' || c > '9') break;
469 j = j * 10 + (int)(c - '0');
470 any = 1;
471 if (j > 65535) goto syntaxerr;
472 }
473 if (any == 0 || c != 0) goto syntaxerr;
474 if (j < 1024) goto syntaxerr;
475 *port = (UShort)j;
476 ok:
477 return 1;
478 syntaxerr:
479 return 0;
480# undef GET_CH
481}
482
njneb8896b2005-06-04 20:03:55 +0000483static
484Int my_socket ( Int domain, Int type, Int protocol )
485{
sewardj2c48c7b2005-11-29 13:05:56 +0000486#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000487 SysRes res;
488 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000489 args[0] = domain;
490 args[1] = type;
491 args[2] = protocol;
492 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000493 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000494
495#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000496 SysRes res;
497 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
498 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000499
cerion85665ca2005-06-20 15:51:07 +0000500#else
501# error Unknown arch
502#endif
njneb8896b2005-06-04 20:03:55 +0000503}
504
505static
506Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
507 Int addrlen )
508{
sewardj2c48c7b2005-11-29 13:05:56 +0000509#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000510 SysRes res;
511 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000512 args[0] = sockfd;
513 args[1] = (UWord)serv_addr;
514 args[2] = addrlen;
515 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000516 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000517
518#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000519 SysRes res;
520 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
521 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000522
cerion85665ca2005-06-20 15:51:07 +0000523#else
524# error Unknown arch
525#endif
njneb8896b2005-06-04 20:03:55 +0000526}
527
528Int VG_(write_socket)( Int sd, void *msg, Int count )
529{
njneb8896b2005-06-04 20:03:55 +0000530 /* This is actually send(). */
njneb8896b2005-06-04 20:03:55 +0000531 /* Requests not to send SIGPIPE on errors on stream oriented
532 sockets when the other end breaks the connection. The EPIPE
533 error is still returned. */
534 Int flags = VKI_MSG_NOSIGNAL;
535
sewardj2c48c7b2005-11-29 13:05:56 +0000536#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000537 SysRes res;
538 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000539 args[0] = sd;
540 args[1] = (UWord)msg;
541 args[2] = count;
542 args[3] = flags;
543 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000544 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000545
546#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000547 SysRes res;
548 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, flags, 0,0);
549 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000550
cerion85665ca2005-06-20 15:51:07 +0000551#else
552# error Unknown arch
553#endif
njneb8896b2005-06-04 20:03:55 +0000554}
555
556Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
557{
sewardja8d8e232005-06-07 20:04:56 +0000558 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000559
sewardj2c48c7b2005-11-29 13:05:56 +0000560#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000561 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000562 args[0] = sd;
563 args[1] = (UWord)name;
564 args[2] = (UWord)namelen;
565 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000566 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000567
cerion85665ca2005-06-20 15:51:07 +0000568#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000569 res = VG_(do_syscall3)( __NR_getsockname,
570 (UWord)sd, (UWord)name, (UWord)namelen );
571 return res.isError ? -1 : res.val;
572
cerion85665ca2005-06-20 15:51:07 +0000573#else
574# error Unknown arch
575#endif
njneb8896b2005-06-04 20:03:55 +0000576}
577
578Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
579{
sewardja8d8e232005-06-07 20:04:56 +0000580 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000581
sewardj2c48c7b2005-11-29 13:05:56 +0000582#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000583 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000584 args[0] = sd;
585 args[1] = (UWord)name;
586 args[2] = (UWord)namelen;
587 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000588 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000589
cerion85665ca2005-06-20 15:51:07 +0000590#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000591 res = VG_(do_syscall3)( __NR_getpeername,
592 (UWord)sd, (UWord)name, (UWord)namelen );
593 return res.isError ? -1 : res.val;
594
cerion85665ca2005-06-20 15:51:07 +0000595#else
sewardj8a851282005-07-02 10:13:05 +0000596# error Unknown archx
cerion85665ca2005-06-20 15:51:07 +0000597#endif
njneb8896b2005-06-04 20:03:55 +0000598}
599
600Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
601 Int *optlen)
602{
sewardja8d8e232005-06-07 20:04:56 +0000603 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000604
sewardj2c48c7b2005-11-29 13:05:56 +0000605#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000606 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000607 args[0] = sd;
608 args[1] = level;
609 args[2] = optname;
610 args[3] = (UWord)optval;
611 args[4] = (UWord)optlen;
612 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000613 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000614
cerion85665ca2005-06-20 15:51:07 +0000615#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000616 res = VG_(do_syscall5)( __NR_getsockopt,
617 (UWord)sd, (UWord)level, (UWord)optname,
618 (UWord)optval, (UWord)optlen );
619 return res.isError ? -1 : res.val;
620
cerion85665ca2005-06-20 15:51:07 +0000621#else
622# error Unknown arch
623#endif
njneb8896b2005-06-04 20:03:55 +0000624}
625
626
627
628/*--------------------------------------------------------------------*/
629/*--- end ---*/
630/*--------------------------------------------------------------------*/
631