blob: c3ed7d3e2d1445a0cf71ec2d052c22e32c55ca25 [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);
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{
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
njn73750612005-10-14 03:11:30 +0000141Bool VG_(is_dir) ( HChar* f )
142{
143 struct vki_stat buf;
144 SysRes res = VG_(do_syscall2)(__NR_stat, (UWord)f, (UWord)&buf);
145 return res.isError ? False
146 : VKI_S_ISDIR(buf.st_mode) ? True : False;
147}
148
sewardj45f4e7c2005-09-27 19:20:21 +0000149SysRes VG_(dup) ( Int oldfd )
150{
151 return VG_(do_syscall1)(__NR_dup, oldfd);
njneb8896b2005-06-04 20:03:55 +0000152}
153
njn327fe8a2005-06-12 02:49:35 +0000154/* Returns -1 on error. */
155Int VG_(fcntl) ( Int fd, Int cmd, Int arg )
156{
157 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
158 return res.isError ? -1 : res.val;
159}
160
njneb8896b2005-06-04 20:03:55 +0000161Int VG_(rename) ( Char* old_name, Char* new_name )
162{
sewardja8d8e232005-06-07 20:04:56 +0000163 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
164 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000165}
166
167Int VG_(unlink) ( Char* file_name )
168{
sewardja8d8e232005-06-07 20:04:56 +0000169 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
170 return res.isError ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000171}
172
173/* Nb: we do not allow the Linux extension which malloc()s memory for the
174 buffer if buf==NULL, because we don't want Linux calling malloc() */
njn57ca7ab2005-06-21 23:44:58 +0000175Bool VG_(getcwd) ( Char* buf, SizeT size )
njneb8896b2005-06-04 20:03:55 +0000176{
sewardja8d8e232005-06-07 20:04:56 +0000177 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000178 vg_assert(buf != NULL);
179 res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
njn57ca7ab2005-06-21 23:44:58 +0000180 return res.isError ? False : True;
njneb8896b2005-06-04 20:03:55 +0000181}
182
183Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
184{
sewardja8d8e232005-06-07 20:04:56 +0000185 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000186 /* res = readlink( path, buf, bufsiz ); */
187 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardja8d8e232005-06-07 20:04:56 +0000188 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000189}
190
191Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
192{
sewardja8d8e232005-06-07 20:04:56 +0000193 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000194 /* res = getdents( fd, dirp, count ); */
195 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
sewardja8d8e232005-06-07 20:04:56 +0000196 return res.isError ? -1 : res.val;
njneb8896b2005-06-04 20:03:55 +0000197}
198
sewardj45f4e7c2005-09-27 19:20:21 +0000199/* Check accessibility of a file. Returns zero for access granted,
200 nonzero otherwise. */
201Int VG_(access) ( HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
202{
203#if defined(VGO_linux)
204 /* Very annoyingly, I cannot find any definition for R_OK et al in
205 the kernel interfaces. Therefore I reluctantly resort to
206 hardwiring in these magic numbers that I determined by
207 experimentation. */
208 UWord w = (irusr ? 4/*R_OK*/ : 0)
209 | (iwusr ? 2/*W_OK*/ : 0)
210 | (ixusr ? 1/*X_OK*/ : 0);
211 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
212 return res.isError ? 1 : res.val;
213#else
214# error "Don't know how to do VG_(access) on this OS"
215#endif
216}
217
njn73750612005-10-14 03:11:30 +0000218/*
219 Emulate the normal Unix permissions checking algorithm.
220
221 If owner matches, then use the owner permissions, else
222 if group matches, then use the group permissions, else
223 use other permissions.
224
225 Note that we can't deal with SUID/SGID, so we refuse to run them
226 (otherwise the executable may misbehave if it doesn't have the
227 permissions it thinks it does).
228*/
229/* returns: 0 = success, non-0 is failure */
230Int VG_(check_executable)(HChar* f)
231{
232 struct vki_stat st;
233 SysRes res;
234
235 res = VG_(stat)(f, &st);
236 if (res.isError) {
237 return res.val;
238 }
239
240 if (st.st_mode & (VKI_S_ISUID | VKI_S_ISGID)) {
241 //VG_(printf)("Can't execute suid/sgid executable %s\n", exe);
242 return VKI_EACCES;
243 }
244
245 if (VG_(geteuid)() == st.st_uid) {
246 if (!(st.st_mode & VKI_S_IXUSR))
247 return VKI_EACCES;
248 } else {
249 int grpmatch = 0;
250
251 if (VG_(getegid)() == st.st_gid)
252 grpmatch = 1;
253 else {
254 UInt groups[32];
255 Int ngrp = VG_(getgroups)(32, groups);
256 Int i;
257 /* ngrp will be -1 if VG_(getgroups) failed. */
258 for (i = 0; i < ngrp; i++) {
259 if (groups[i] == st.st_gid) {
260 grpmatch = 1;
261 break;
262 }
263 }
264 }
265
266 if (grpmatch) {
267 if (!(st.st_mode & VKI_S_IXGRP)) {
268 return VKI_EACCES;
269 }
270 } else if (!(st.st_mode & VKI_S_IXOTH)) {
271 return VKI_EACCES;
272 }
273 }
274
275 return 0;
276}
277
sewardj45f4e7c2005-09-27 19:20:21 +0000278SysRes VG_(pread) ( Int fd, void* buf, Int count, Int offset )
279{
280 OffT off = VG_(lseek)( fd, (OffT)offset, VKI_SEEK_SET);
tomf4c23102005-10-31 17:05:21 +0000281 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000282 return VG_(mk_SysRes_Error)( VKI_EINVAL );
tom60a4b0b2005-10-12 10:45:27 +0000283 return VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
sewardj45f4e7c2005-09-27 19:20:21 +0000284}
285
286/* Create and open (-rw------) a tmp file name incorporating said arg.
287 Returns -1 on failure, else the fd of the file. If fullname is
288 non-NULL, the file's name is written into it. The number of bytes
289 written is guaranteed not to exceed 64+strlen(part_of_name). */
290
291Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
292{
293 HChar buf[200];
294 Int n, tries, fd;
295 UInt seed;
296 SysRes sres;
297
298 vg_assert(part_of_name);
299 n = VG_(strlen)(part_of_name);
300 vg_assert(n > 0 && n < 100);
301
302 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
303
304 tries = 0;
305 while (True) {
306 if (tries > 10)
307 return -1;
308 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
309 part_of_name, VG_(random)( &seed ));
310 if (0)
311 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
312
313 sres = VG_(open)(buf,
314 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
315 VKI_S_IRUSR|VKI_S_IWUSR);
316 if (sres.isError)
317 continue;
318 /* VG_(safe_fd) doesn't return if it fails. */
319 fd = VG_(safe_fd)( sres.val );
320 if (fullname)
321 VG_(strcpy)( fullname, buf );
322 return fd;
323 }
324 /* NOTREACHED */
325}
326
327
njneb8896b2005-06-04 20:03:55 +0000328/* ---------------------------------------------------------------------
329 Socket-related stuff. This is very Linux-kernel specific.
330 ------------------------------------------------------------------ */
331
332static
333Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
334
335static
336Int my_socket ( Int domain, Int type, Int protocol );
337
338static
339Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
340 Int addrlen );
341
toma4a4f412005-11-17 12:01:56 +0000342UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000343{
sewardja1c4bfb2005-10-18 02:15:39 +0000344# if defined(VG_BIGENDIAN)
345 return x;
346# else
njneb8896b2005-06-04 20:03:55 +0000347 return
348 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
349 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000350# endif
njneb8896b2005-06-04 20:03:55 +0000351}
352
toma4a4f412005-11-17 12:01:56 +0000353UInt VG_(ntohl) ( UInt x )
354{
355# if defined(VG_BIGENDIAN)
356 return x;
357# else
358 return
359 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
360 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
361# endif
362}
363
364UShort VG_(htons) ( UShort x )
365{
366# if defined(VG_BIGENDIAN)
367 return x;
368# else
369 return
370 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
371# endif
372}
373
374UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000375{
sewardja1c4bfb2005-10-18 02:15:39 +0000376# if defined(VG_BIGENDIAN)
377 return x;
378# else
njneb8896b2005-06-04 20:03:55 +0000379 return
380 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000381# endif
njneb8896b2005-06-04 20:03:55 +0000382}
383
384
385/* The main function.
386
387 Supplied string contains either an ip address "192.168.0.1" or
388 an ip address and port pair, "192.168.0.1:1500". Parse these,
389 and return:
390 -1 if there is a parse error
391 -2 if no parse error, but specified host:port cannot be opened
392 the relevant file (socket) descriptor, otherwise.
393 is used.
394*/
395Int VG_(connect_via_socket)( UChar* str )
396{
397 Int sd, res;
398 struct vki_sockaddr_in servAddr;
399 UInt ip = 0;
400 UShort port = VG_CLO_DEFAULT_LOGPORT;
401 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
402 if (!ok)
403 return -1;
404
405 //if (0)
406 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
407 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
408 // (ip >> 8) & 0xFF, ip & 0xFF,
409 // (UInt)port );
410
411 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +0000412 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
413 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +0000414
415 /* create socket */
416 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
417 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000418 /* this shouldn't happen ... nevertheless */
419 return -2;
njneb8896b2005-06-04 20:03:55 +0000420 }
sewardja1c4bfb2005-10-18 02:15:39 +0000421
njneb8896b2005-06-04 20:03:55 +0000422 /* connect to server */
423 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
424 sizeof(servAddr));
425 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000426 /* connection failed */
427 return -2;
njneb8896b2005-06-04 20:03:55 +0000428 }
429
430 return sd;
431}
432
433
434/* Let d = one or more digits. Accept either:
435 d.d.d.d or d.d.d.d:d
436*/
437Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
438{
439# define GET_CH ((*str) ? (*str++) : 0)
440 UInt ipa, i, j, c, any;
441 ipa = 0;
442 for (i = 0; i < 4; i++) {
443 j = 0;
444 any = 0;
445 while (1) {
446 c = GET_CH;
447 if (c < '0' || c > '9') break;
448 j = 10 * j + (int)(c - '0');
449 any = 1;
450 }
451 if (any == 0 || j > 255) goto syntaxerr;
452 ipa = (ipa << 8) + j;
453 if (i <= 2 && c != '.') goto syntaxerr;
454 }
455 if (c == 0 || c == ':')
456 *ip_addr = ipa;
457 if (c == 0) goto ok;
458 if (c != ':') goto syntaxerr;
459 j = 0;
460 any = 0;
461 while (1) {
462 c = GET_CH;
463 if (c < '0' || c > '9') break;
464 j = j * 10 + (int)(c - '0');
465 any = 1;
466 if (j > 65535) goto syntaxerr;
467 }
468 if (any == 0 || c != 0) goto syntaxerr;
469 if (j < 1024) goto syntaxerr;
470 *port = (UShort)j;
471 ok:
472 return 1;
473 syntaxerr:
474 return 0;
475# undef GET_CH
476}
477
njneb8896b2005-06-04 20:03:55 +0000478static
479Int my_socket ( Int domain, Int type, Int protocol )
480{
sewardj2c48c7b2005-11-29 13:05:56 +0000481#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000482 SysRes res;
483 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000484 args[0] = domain;
485 args[1] = type;
486 args[2] = protocol;
487 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000488 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000489
490#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000491 SysRes res;
492 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
493 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000494
cerion85665ca2005-06-20 15:51:07 +0000495#else
496# error Unknown arch
497#endif
njneb8896b2005-06-04 20:03:55 +0000498}
499
500static
501Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
502 Int addrlen )
503{
sewardj2c48c7b2005-11-29 13:05:56 +0000504#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000505 SysRes res;
506 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000507 args[0] = sockfd;
508 args[1] = (UWord)serv_addr;
509 args[2] = addrlen;
510 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000511 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000512
513#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000514 SysRes res;
515 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
516 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000517
cerion85665ca2005-06-20 15:51:07 +0000518#else
519# error Unknown arch
520#endif
njneb8896b2005-06-04 20:03:55 +0000521}
522
523Int VG_(write_socket)( Int sd, void *msg, Int count )
524{
njneb8896b2005-06-04 20:03:55 +0000525 /* This is actually send(). */
njneb8896b2005-06-04 20:03:55 +0000526 /* Requests not to send SIGPIPE on errors on stream oriented
527 sockets when the other end breaks the connection. The EPIPE
528 error is still returned. */
529 Int flags = VKI_MSG_NOSIGNAL;
530
sewardj2c48c7b2005-11-29 13:05:56 +0000531#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000532 SysRes res;
533 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000534 args[0] = sd;
535 args[1] = (UWord)msg;
536 args[2] = count;
537 args[3] = flags;
538 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000539 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000540
541#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000542 SysRes res;
543 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, count, flags, 0,0);
544 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000545
cerion85665ca2005-06-20 15:51:07 +0000546#else
547# error Unknown arch
548#endif
njneb8896b2005-06-04 20:03:55 +0000549}
550
551Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
552{
sewardja8d8e232005-06-07 20:04:56 +0000553 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000554
sewardj2c48c7b2005-11-29 13:05:56 +0000555#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000556 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000557 args[0] = sd;
558 args[1] = (UWord)name;
559 args[2] = (UWord)namelen;
560 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000561 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000562
cerion85665ca2005-06-20 15:51:07 +0000563#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000564 res = VG_(do_syscall3)( __NR_getsockname,
565 (UWord)sd, (UWord)name, (UWord)namelen );
566 return res.isError ? -1 : res.val;
567
cerion85665ca2005-06-20 15:51:07 +0000568#else
569# error Unknown arch
570#endif
njneb8896b2005-06-04 20:03:55 +0000571}
572
573Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
574{
sewardja8d8e232005-06-07 20:04:56 +0000575 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000576
sewardj2c48c7b2005-11-29 13:05:56 +0000577#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000578 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000579 args[0] = sd;
580 args[1] = (UWord)name;
581 args[2] = (UWord)namelen;
582 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000583 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000584
cerion85665ca2005-06-20 15:51:07 +0000585#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000586 res = VG_(do_syscall3)( __NR_getpeername,
587 (UWord)sd, (UWord)name, (UWord)namelen );
588 return res.isError ? -1 : res.val;
589
cerion85665ca2005-06-20 15:51:07 +0000590#else
sewardj8a851282005-07-02 10:13:05 +0000591# error Unknown archx
cerion85665ca2005-06-20 15:51:07 +0000592#endif
njneb8896b2005-06-04 20:03:55 +0000593}
594
595Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
596 Int *optlen)
597{
sewardja8d8e232005-06-07 20:04:56 +0000598 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000599
sewardj2c48c7b2005-11-29 13:05:56 +0000600#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000601 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000602 args[0] = sd;
603 args[1] = level;
604 args[2] = optname;
605 args[3] = (UWord)optval;
606 args[4] = (UWord)optlen;
607 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000608 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000609
cerion85665ca2005-06-20 15:51:07 +0000610#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000611 res = VG_(do_syscall5)( __NR_getsockopt,
612 (UWord)sd, (UWord)level, (UWord)optname,
613 (UWord)optval, (UWord)optlen );
614 return res.isError ? -1 : res.val;
615
cerion85665ca2005-06-20 15:51:07 +0000616#else
617# error Unknown arch
618#endif
njneb8896b2005-06-04 20:03:55 +0000619}
620
621
622
623/*--------------------------------------------------------------------*/
624/*--- end ---*/
625/*--------------------------------------------------------------------*/
626