blob: 8c299e50860b379c0eab2891debc46aad4912fce [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
342static
343UInt my_htonl ( UInt x )
344{
sewardja1c4bfb2005-10-18 02:15:39 +0000345# if defined(VG_BIGENDIAN)
346 return x;
347# else
njneb8896b2005-06-04 20:03:55 +0000348 return
349 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
350 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000351# endif
njneb8896b2005-06-04 20:03:55 +0000352}
353
354static
355UShort my_htons ( UShort x )
356{
sewardja1c4bfb2005-10-18 02:15:39 +0000357# if defined(VG_BIGENDIAN)
358 return x;
359# else
njneb8896b2005-06-04 20:03:55 +0000360 return
361 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000362# endif
njneb8896b2005-06-04 20:03:55 +0000363}
364
365
366/* The main function.
367
368 Supplied string contains either an ip address "192.168.0.1" or
369 an ip address and port pair, "192.168.0.1:1500". Parse these,
370 and return:
371 -1 if there is a parse error
372 -2 if no parse error, but specified host:port cannot be opened
373 the relevant file (socket) descriptor, otherwise.
374 is used.
375*/
376Int VG_(connect_via_socket)( UChar* str )
377{
378 Int sd, res;
379 struct vki_sockaddr_in servAddr;
380 UInt ip = 0;
381 UShort port = VG_CLO_DEFAULT_LOGPORT;
382 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
383 if (!ok)
384 return -1;
385
386 //if (0)
387 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
388 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
389 // (ip >> 8) & 0xFF, ip & 0xFF,
390 // (UInt)port );
391
392 servAddr.sin_family = VKI_AF_INET;
393 servAddr.sin_addr.s_addr = my_htonl(ip);
394 servAddr.sin_port = my_htons(port);
395
396 /* create socket */
397 sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
398 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000399 /* this shouldn't happen ... nevertheless */
400 return -2;
njneb8896b2005-06-04 20:03:55 +0000401 }
sewardja1c4bfb2005-10-18 02:15:39 +0000402
njneb8896b2005-06-04 20:03:55 +0000403 /* connect to server */
404 res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
405 sizeof(servAddr));
406 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000407 /* connection failed */
408 return -2;
njneb8896b2005-06-04 20:03:55 +0000409 }
410
411 return sd;
412}
413
414
415/* Let d = one or more digits. Accept either:
416 d.d.d.d or d.d.d.d:d
417*/
418Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
419{
420# define GET_CH ((*str) ? (*str++) : 0)
421 UInt ipa, i, j, c, any;
422 ipa = 0;
423 for (i = 0; i < 4; i++) {
424 j = 0;
425 any = 0;
426 while (1) {
427 c = GET_CH;
428 if (c < '0' || c > '9') break;
429 j = 10 * j + (int)(c - '0');
430 any = 1;
431 }
432 if (any == 0 || j > 255) goto syntaxerr;
433 ipa = (ipa << 8) + j;
434 if (i <= 2 && c != '.') goto syntaxerr;
435 }
436 if (c == 0 || c == ':')
437 *ip_addr = ipa;
438 if (c == 0) goto ok;
439 if (c != ':') goto syntaxerr;
440 j = 0;
441 any = 0;
442 while (1) {
443 c = GET_CH;
444 if (c < '0' || c > '9') break;
445 j = j * 10 + (int)(c - '0');
446 any = 1;
447 if (j > 65535) goto syntaxerr;
448 }
449 if (any == 0 || c != 0) goto syntaxerr;
450 if (j < 1024) goto syntaxerr;
451 *port = (UShort)j;
452 ok:
453 return 1;
454 syntaxerr:
455 return 0;
456# undef GET_CH
457}
458
njneb8896b2005-06-04 20:03:55 +0000459static
460Int my_socket ( Int domain, Int type, Int protocol )
461{
sewardj21ccba82005-10-07 23:04:17 +0000462#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000463 SysRes res;
464 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000465 args[0] = domain;
466 args[1] = type;
467 args[2] = protocol;
468 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000469 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000470
471#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000472 SysRes res;
473 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
474 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000475
cerion85665ca2005-06-20 15:51:07 +0000476#else
477# error Unknown arch
478#endif
njneb8896b2005-06-04 20:03:55 +0000479}
480
481static
482Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
483 Int addrlen )
484{
sewardj21ccba82005-10-07 23:04:17 +0000485#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000486 SysRes res;
487 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000488 args[0] = sockfd;
489 args[1] = (UWord)serv_addr;
490 args[2] = addrlen;
491 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000492 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000493
494#elif defined(VGP_amd64_linux)
sewardj1e866562005-09-28 19:58:58 +0000495 SysRes res;
496 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
497 return res.isError ? -1 : res.val;
cerion85665ca2005-06-20 15:51:07 +0000498
cerion85665ca2005-06-20 15:51:07 +0000499#else
500# error Unknown arch
501#endif
njneb8896b2005-06-04 20:03:55 +0000502}
503
504Int VG_(write_socket)( Int sd, void *msg, Int count )
505{
njneb8896b2005-06-04 20:03:55 +0000506 /* This is actually send(). */
njneb8896b2005-06-04 20:03:55 +0000507 /* Requests not to send SIGPIPE on errors on stream oriented
508 sockets when the other end breaks the connection. The EPIPE
509 error is still returned. */
510 Int flags = VKI_MSG_NOSIGNAL;
511
sewardja1c4bfb2005-10-18 02:15:39 +0000512#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000513 SysRes res;
514 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000515 args[0] = sd;
516 args[1] = (UWord)msg;
517 args[2] = count;
518 args[3] = flags;
519 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (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_syscall6)(__NR_sendto, sd, (UWord)msg, count, flags, 0,0);
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_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
533{
sewardja8d8e232005-06-07 20:04:56 +0000534 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000535
sewardj8a851282005-07-02 10:13:05 +0000536#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000537 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000538 args[0] = sd;
539 args[1] = (UWord)name;
540 args[2] = (UWord)namelen;
541 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000542 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000543
cerion85665ca2005-06-20 15:51:07 +0000544#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000545 res = VG_(do_syscall3)( __NR_getsockname,
546 (UWord)sd, (UWord)name, (UWord)namelen );
547 return res.isError ? -1 : res.val;
548
cerion85665ca2005-06-20 15:51:07 +0000549#else
550# error Unknown arch
551#endif
njneb8896b2005-06-04 20:03:55 +0000552}
553
554Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
555{
sewardja8d8e232005-06-07 20:04:56 +0000556 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000557
sewardj8a851282005-07-02 10:13:05 +0000558#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000559 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000560 args[0] = sd;
561 args[1] = (UWord)name;
562 args[2] = (UWord)namelen;
563 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000564 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000565
cerion85665ca2005-06-20 15:51:07 +0000566#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000567 res = VG_(do_syscall3)( __NR_getpeername,
568 (UWord)sd, (UWord)name, (UWord)namelen );
569 return res.isError ? -1 : res.val;
570
cerion85665ca2005-06-20 15:51:07 +0000571#else
sewardj8a851282005-07-02 10:13:05 +0000572# error Unknown archx
cerion85665ca2005-06-20 15:51:07 +0000573#endif
njneb8896b2005-06-04 20:03:55 +0000574}
575
576Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
577 Int *optlen)
578{
sewardja8d8e232005-06-07 20:04:56 +0000579 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000580
sewardj8a851282005-07-02 10:13:05 +0000581#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardja8d8e232005-06-07 20:04:56 +0000582 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000583 args[0] = sd;
584 args[1] = level;
585 args[2] = optname;
586 args[3] = (UWord)optval;
587 args[4] = (UWord)optlen;
588 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
sewardja8d8e232005-06-07 20:04:56 +0000589 return res.isError ? -1 : res.val;
sewardja5c9e4a2005-06-09 13:21:58 +0000590
cerion85665ca2005-06-20 15:51:07 +0000591#elif defined(VGP_amd64_linux)
sewardja5c9e4a2005-06-09 13:21:58 +0000592 res = VG_(do_syscall5)( __NR_getsockopt,
593 (UWord)sd, (UWord)level, (UWord)optname,
594 (UWord)optval, (UWord)optlen );
595 return res.isError ? -1 : res.val;
596
cerion85665ca2005-06-20 15:51:07 +0000597#else
598# error Unknown arch
599#endif
njneb8896b2005-06-04 20:03:55 +0000600}
601
602
603
604/*--------------------------------------------------------------------*/
605/*--- end ---*/
606/*--------------------------------------------------------------------*/
607