1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- File- and socket-related libc stuff. m_libcfile.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2015 Julian Seward
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 The GNU General Public License is contained in the file COPYING.
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_debuglog.h"
36 #include "pub_core_libcbase.h"
37 #include "pub_core_libcassert.h"
38 #include "pub_core_libcfile.h"
39 #include "pub_core_libcprint.h" // VG_(sprintf)
40 #include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
41 #include "pub_core_clientstate.h" // VG_(fd_hard_limit)
42 #include "pub_core_mallocfree.h" // VG_(realloc)
43 #include "pub_core_syscall.h"
45 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
46 of syscalls rather than the vanilla version, if a _nocancel version
47 is available. See docs/internals/Darwin-notes.txt for the reason
50 /* ---------------------------------------------------------------------
52 ------------------------------------------------------------------ */
54 /* Move an fd into the Valgrind-safe range */
55 Int
VG_(safe_fd
)(Int oldfd
)
59 vg_assert(VG_(fd_hard_limit
) != -1);
61 newfd
= VG_(fcntl
)(oldfd
, VKI_F_DUPFD
, VG_(fd_hard_limit
));
65 /* Set the close-on-exec flag for this fd. */
66 VG_(fcntl
)(newfd
, VKI_F_SETFD
, VKI_FD_CLOEXEC
);
68 vg_assert(newfd
>= VG_(fd_hard_limit
));
72 /* Given a file descriptor, attempt to deduce its filename. To do
73 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
74 or if it doesn't exist, we return False.
75 Upon successful completion *result contains the filename. The
76 filename will be overwritten with the next invocation so callers
77 need to copy the filename if needed. *result is NULL if the filename
79 Bool
VG_(resolve_filename
) ( Int fd
, const HChar
** result
)
81 # if defined(VGO_linux) || defined(VGO_solaris)
82 static HChar
*buf
= NULL
;
83 static SizeT bufsiz
= 0;
85 if (buf
== NULL
) { // first time
87 buf
= VG_(malloc
)("resolve_filename", bufsiz
);
90 HChar tmp
[64]; // large enough
92 # if defined(VGO_linux)
93 VG_(sprintf
)(tmp
, "/proc/self/fd/%d", fd
);
94 # elif defined(VGO_solaris)
95 VG_(sprintf
)(tmp
, "/proc/self/path/%d", fd
);
100 SSizeT res
= VG_(readlink
)(tmp
, buf
, bufsiz
);
102 if (res
== bufsiz
) { // buffer too small; increase and retry
104 buf
= VG_(realloc
)("resolve_filename", buf
, bufsiz
);
107 vg_assert(bufsiz
> res
); // paranoia
108 if (buf
[0] != '/') break;
118 # elif defined(VGO_darwin)
119 HChar tmp
[VKI_MAXPATHLEN
+1];
120 if (0 == VG_(fcntl
)(fd
, VKI_F_GETPATH
, (UWord
)tmp
)) {
121 static HChar
*buf
= NULL
;
124 buf
= VG_(malloc
)("resolve_filename", VKI_MAXPATHLEN
+1);
125 VG_(strcpy
)( buf
, tmp
);
128 if (buf
[0] == '/') return True
;
139 SysRes
VG_(mknod
) ( const HChar
* pathname
, Int mode
, UWord dev
)
141 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
142 /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
143 SysRes res
= VG_(do_syscall4
)(__NR_mknodat
,
144 VKI_AT_FDCWD
, (UWord
)pathname
, mode
, dev
);
145 # elif defined(VGO_linux) || defined(VGO_darwin)
146 SysRes res
= VG_(do_syscall3
)(__NR_mknod
,
147 (UWord
)pathname
, mode
, dev
);
148 # elif defined(VGO_solaris)
149 SysRes res
= VG_(do_syscall4
)(__NR_mknodat
,
150 VKI_AT_FDCWD
, (UWord
)pathname
, mode
, dev
);
157 SysRes
VG_(open
) ( const HChar
* pathname
, Int flags
, Int mode
)
159 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
160 /* ARM64 wants to use __NR_openat rather than __NR_open. */
161 SysRes res
= VG_(do_syscall4
)(__NR_openat
,
162 VKI_AT_FDCWD
, (UWord
)pathname
, flags
, mode
);
163 # elif defined(VGO_linux)
164 SysRes res
= VG_(do_syscall3
)(__NR_open
,
165 (UWord
)pathname
, flags
, mode
);
166 # elif defined(VGO_darwin)
167 SysRes res
= VG_(do_syscall3
)(__NR_open_nocancel
,
168 (UWord
)pathname
, flags
, mode
);
169 # elif defined(VGO_solaris)
170 SysRes res
= VG_(do_syscall4
)(__NR_openat
,
171 VKI_AT_FDCWD
, (UWord
)pathname
, flags
, mode
);
178 Int
VG_(fd_open
) (const HChar
* pathname
, Int flags
, Int mode
)
181 sr
= VG_(open
) (pathname
, flags
, mode
);
188 void VG_(close
) ( Int fd
)
190 /* Hmm. Return value is not checked. That's uncool. */
191 # if defined(VGO_linux) || defined(VGO_solaris)
192 (void)VG_(do_syscall1
)(__NR_close
, fd
);
193 # elif defined(VGO_darwin)
194 (void)VG_(do_syscall1
)(__NR_close_nocancel
, fd
);
200 Int
VG_(read
) ( Int fd
, void* buf
, Int count
)
203 # if defined(VGO_linux) || defined(VGO_solaris)
204 SysRes res
= VG_(do_syscall3
)(__NR_read
, fd
, (UWord
)buf
, count
);
205 # elif defined(VGO_darwin)
206 SysRes res
= VG_(do_syscall3
)(__NR_read_nocancel
, fd
, (UWord
)buf
, count
);
210 if (sr_isError(res
)) {
211 ret
= - (Int
)(Word
)sr_Err(res
);
214 ret
= (Int
)(Word
)sr_Res(res
);
220 Int
VG_(write
) ( Int fd
, const void* buf
, Int count
)
223 # if defined(VGO_linux) || defined(VGO_solaris)
224 SysRes res
= VG_(do_syscall3
)(__NR_write
, fd
, (UWord
)buf
, count
);
225 # elif defined(VGO_darwin)
226 SysRes res
= VG_(do_syscall3
)(__NR_write_nocancel
, fd
, (UWord
)buf
, count
);
230 if (sr_isError(res
)) {
231 ret
= - (Int
)(Word
)sr_Err(res
);
234 ret
= (Int
)(Word
)sr_Res(res
);
241 Int
VG_(pipe
) ( Int fd
[2] )
243 # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
244 /* __NR_pipe has a strange return convention on mips32-linux. */
245 SysRes res
= VG_(do_syscall1
)(__NR_pipe
, (UWord
)fd
);
246 if (!sr_isError(res
)) {
247 fd
[0] = (Int
)sr_Res(res
);
248 fd
[1] = (Int
)sr_ResEx(res
);
253 # elif defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
254 SysRes res
= VG_(do_syscall2
)(__NR_pipe2
, (UWord
)fd
, 0);
255 return sr_isError(res
) ? -1 : 0;
256 # elif defined(VGO_linux)
257 SysRes res
= VG_(do_syscall1
)(__NR_pipe
, (UWord
)fd
);
258 return sr_isError(res
) ? -1 : 0;
259 # elif defined(VGO_darwin)
260 /* __NR_pipe is UX64, so produces a double-word result */
261 SysRes res
= VG_(do_syscall0
)(__NR_pipe
);
262 if (!sr_isError(res
)) {
263 fd
[0] = (Int
)sr_Res(res
);
264 fd
[1] = (Int
)sr_ResHI(res
);
266 return sr_isError(res
) ? -1 : 0;
267 # elif defined(VGO_solaris)
268 # if defined(SOLARIS_NEW_PIPE_SYSCALL)
269 SysRes res
= VG_(do_syscall2
)(__NR_pipe
, (UWord
)fd
, 0);
270 return sr_isError(res
) ? -1 : 0;
272 SysRes res
= VG_(do_syscall0
)(__NR_pipe
);
273 if (!sr_isError(res
)) {
274 fd
[0] = (Int
)sr_Res(res
);
275 fd
[1] = (Int
)sr_ResHI(res
);
277 return sr_isError(res
) ? -1 : 0;
284 Off64T
VG_(lseek
) ( Int fd
, Off64T offset
, Int whence
)
286 # if defined(VGO_linux) || defined(VGP_amd64_darwin)
287 # if defined(__NR__llseek)
289 SysRes res
= VG_(do_syscall5
)(__NR__llseek
, fd
,
290 offset
>> 32, offset
& 0xffffffff,
291 (UWord
)&result
, whence
);
292 return sr_isError(res
) ? (-1) : result
;
294 SysRes res
= VG_(do_syscall3
)(__NR_lseek
, fd
, offset
, whence
);
295 vg_assert(sizeof(Off64T
) == sizeof(Word
));
296 return sr_isError(res
) ? (-1) : sr_Res(res
);
298 # elif defined(VGP_x86_darwin)
299 SysRes res
= VG_(do_syscall4
)(__NR_lseek
, fd
,
300 offset
& 0xffffffff, offset
>> 32, whence
);
301 return sr_isError(res
) ? (-1) : sr_Res(res
);
302 # elif defined(VGP_x86_solaris)
303 SysRes res
= VG_(do_syscall4
)(__NR_llseek
, fd
,
304 offset
& 0xffffffff, offset
>> 32, whence
);
305 return sr_isError(res
) ? (-1) : ((ULong
)sr_ResHI(res
) << 32 | sr_Res(res
));
306 # elif defined(VGP_amd64_solaris)
307 SysRes res
= VG_(do_syscall3
)(__NR_lseek
, fd
, offset
, whence
);
308 vg_assert(sizeof(Off64T
) == sizeof(Word
));
309 return sr_isError(res
) ? (-1) : sr_Res(res
);
311 # error "Unknown plat"
313 /* if you change the error-reporting conventions of this, also
314 change all usage points. */
318 /* stat/fstat support. It's uggerly. We have impedance-match into a
319 'struct vg_stat' in order to have a single structure that callers
320 can use consistently on all platforms. */
322 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
324 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
325 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
326 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
327 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
328 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
329 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
330 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
331 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
332 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
333 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
334 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
335 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
336 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
337 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
338 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
339 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
342 SysRes
VG_(stat
) ( const HChar
* file_name
, struct vg_stat
* vgbuf
)
345 VG_(memset
)(vgbuf
, 0, sizeof(*vgbuf
));
347 # if defined(VGO_linux) || defined(VGO_darwin)
348 /* First try with stat64. If that doesn't work out, fall back to
349 the vanilla version. */
350 # if defined(__NR_stat64)
351 { struct vki_stat64 buf64
;
352 res
= VG_(do_syscall2
)(__NR_stat64
, (UWord
)file_name
, (UWord
)&buf64
);
353 if (!(sr_isError(res
) && sr_Err(res
) == VKI_ENOSYS
)) {
354 /* Success, or any failure except ENOSYS */
355 if (!sr_isError(res
))
356 TRANSLATE_TO_vg_stat(vgbuf
, &buf64
);
360 # endif /* defined(__NR_stat64) */
361 /* This is the fallback ("vanilla version"). */
362 { struct vki_stat buf
;
363 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
364 res
= VG_(do_syscall3
)(__NR3264_fstatat
, VKI_AT_FDCWD
,
365 (UWord
)file_name
, (UWord
)&buf
);
367 res
= VG_(do_syscall2
)(__NR_stat
, (UWord
)file_name
, (UWord
)&buf
);
369 if (!sr_isError(res
))
370 TRANSLATE_TO_vg_stat(vgbuf
, &buf
);
373 # elif defined(VGO_solaris)
375 # if defined(VGP_x86_solaris)
376 struct vki_stat64 buf64
;
377 res
= VG_(do_syscall4
)(__NR_fstatat64
, VKI_AT_FDCWD
, (UWord
)file_name
,
379 # elif defined(VGP_amd64_solaris)
380 struct vki_stat buf64
;
381 res
= VG_(do_syscall4
)(__NR_fstatat
, VKI_AT_FDCWD
, (UWord
)file_name
,
384 # error "Unknown platform"
386 if (!sr_isError(res
))
387 TRANSLATE_TO_vg_stat(vgbuf
, &buf64
);
395 Int
VG_(fstat
) ( Int fd
, struct vg_stat
* vgbuf
)
398 VG_(memset
)(vgbuf
, 0, sizeof(*vgbuf
));
400 # if defined(VGO_linux) || defined(VGO_darwin)
401 /* First try with fstat64. If that doesn't work out, fall back to
402 the vanilla version. */
403 # if defined(__NR_fstat64)
404 { struct vki_stat64 buf64
;
405 res
= VG_(do_syscall2
)(__NR_fstat64
, (UWord
)fd
, (UWord
)&buf64
);
406 if (!(sr_isError(res
) && sr_Err(res
) == VKI_ENOSYS
)) {
407 /* Success, or any failure except ENOSYS */
408 if (!sr_isError(res
))
409 TRANSLATE_TO_vg_stat(vgbuf
, &buf64
);
410 return sr_isError(res
) ? (-1) : 0;
413 # endif /* if defined(__NR_fstat64) */
414 { struct vki_stat buf
;
415 res
= VG_(do_syscall2
)(__NR_fstat
, (UWord
)fd
, (UWord
)&buf
);
416 if (!sr_isError(res
))
417 TRANSLATE_TO_vg_stat(vgbuf
, &buf
);
418 return sr_isError(res
) ? (-1) : 0;
420 # elif defined(VGO_solaris)
422 # if defined(VGP_x86_solaris)
423 struct vki_stat64 buf64
;
424 res
= VG_(do_syscall4
)(__NR_fstatat64
, (UWord
)fd
, 0, (UWord
)&buf64
, 0);
425 # elif defined(VGP_amd64_solaris)
426 struct vki_stat buf64
;
427 res
= VG_(do_syscall4
)(__NR_fstatat
, (UWord
)fd
, 0, (UWord
)&buf64
, 0);
429 # error "Unknown platform"
431 if (!sr_isError(res
))
432 TRANSLATE_TO_vg_stat(vgbuf
, &buf64
);
433 return sr_isError(res
) ? (-1) : 0;
440 #undef TRANSLATE_TO_vg_stat
443 Long
VG_(fsize
) ( Int fd
)
446 Int res
= VG_(fstat
)( fd
, &buf
);
447 return (res
== -1) ? (-1LL) : buf
.size
;
450 SysRes
VG_(getxattr
) ( const HChar
* file_name
, const HChar
* attr_name
, Addr attr_value
, SizeT attr_value_len
)
453 #if defined(VGO_linux)
454 res
= VG_(do_syscall4
)(__NR_getxattr
, (UWord
)file_name
, (UWord
)attr_name
,
455 attr_value
, attr_value_len
);
457 res
= VG_(mk_SysRes_Error
)(VKI_ENOSYS
);
462 Bool
VG_(is_dir
) ( const HChar
* f
)
465 SysRes res
= VG_(stat
)(f
, &buf
);
466 return sr_isError(res
) ? False
467 : VKI_S_ISDIR(buf
.mode
) ? True
: False
;
470 SysRes
VG_(dup
) ( Int oldfd
)
472 # if defined(VGO_linux) || defined(VGO_darwin)
473 return VG_(do_syscall1
)(__NR_dup
, oldfd
);
474 # elif defined(VGO_solaris)
475 return VG_(do_syscall3
)(__NR_fcntl
, oldfd
, F_DUPFD
, 0);
481 SysRes
VG_(dup2
) ( Int oldfd
, Int newfd
)
483 # if defined(VGO_linux) || defined(VGO_darwin)
484 return VG_(do_syscall2
)(__NR_dup2
, oldfd
, newfd
);
485 # elif defined(VGO_solaris)
486 return VG_(do_syscall3
)(__NR_fcntl
, oldfd
, F_DUP2FD
, newfd
);
492 /* Returns -1 on error. */
493 Int
VG_(fcntl
) ( Int fd
, Int cmd
, Addr arg
)
495 # if defined(VGO_linux) || defined(VGO_solaris)
496 SysRes res
= VG_(do_syscall3
)(__NR_fcntl
, fd
, cmd
, arg
);
497 # elif defined(VGO_darwin)
498 SysRes res
= VG_(do_syscall3
)(__NR_fcntl_nocancel
, fd
, cmd
, arg
);
502 return sr_isError(res
) ? -1 : sr_Res(res
);
505 Int
VG_(rename
) ( const HChar
* old_name
, const HChar
* new_name
)
507 # if defined(VGP_tilegx_linux)
508 SysRes res
= VG_(do_syscall3
)(__NR_renameat
, VKI_AT_FDCWD
,
509 (UWord
)old_name
, (UWord
)new_name
);
510 # elif defined(VGO_linux) || defined(VGO_darwin)
511 SysRes res
= VG_(do_syscall2
)(__NR_rename
, (UWord
)old_name
, (UWord
)new_name
);
512 # elif defined(VGO_solaris)
513 SysRes res
= VG_(do_syscall4
)(__NR_renameat
, VKI_AT_FDCWD
, (UWord
)old_name
,
514 VKI_AT_FDCWD
, (UWord
)new_name
);
518 return sr_isError(res
) ? (-1) : 0;
521 Int
VG_(unlink
) ( const HChar
* file_name
)
523 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
524 SysRes res
= VG_(do_syscall2
)(__NR_unlinkat
, VKI_AT_FDCWD
,
526 # elif defined(VGO_linux) || defined(VGO_darwin)
527 SysRes res
= VG_(do_syscall1
)(__NR_unlink
, (UWord
)file_name
);
528 # elif defined(VGO_solaris)
529 SysRes res
= VG_(do_syscall3
)(__NR_unlinkat
, VKI_AT_FDCWD
,
530 (UWord
)file_name
, 0);
534 return sr_isError(res
) ? (-1) : 0;
537 /* The working directory at startup.
538 All that is really needed is to note the cwd at process startup.
539 Hence VG_(record_startup_wd) notes it (in a platform dependent way)
540 and VG_(get_startup_wd) produces the noted value. */
541 static HChar
*startup_wd
;
542 static Bool startup_wd_acquired
= False
;
544 /* Record the process' working directory at startup. Is intended to
545 be called exactly once, at startup, before the working directory
546 changes. Return True for success, False for failure, so that the
547 caller can bomb out suitably without creating module cycles if
548 there is a problem. */
549 Bool
VG_(record_startup_wd
) ( void )
551 vg_assert(!startup_wd_acquired
);
552 # if defined(VGO_linux) || defined(VGO_solaris)
553 /* Simple: just ask the kernel */
558 startup_wd
= VG_(realloc
)("startup_wd", startup_wd
, szB
);
559 VG_(memset
)(startup_wd
, 0, szB
);
560 res
= VG_(do_syscall2
)(__NR_getcwd
, (UWord
)startup_wd
, szB
-1);
561 } while (sr_isError(res
));
563 vg_assert(startup_wd
[szB
-1] == 0);
564 startup_wd_acquired
= True
;
567 # elif defined(VGO_darwin)
568 /* We can't ask the kernel, so instead rely on launcher-*.c to
569 tell us the startup path. Note the env var is keyed to the
570 parent's PID, not ours, since our parent is the launcher
572 { HChar envvar
[100]; // large enough
574 VG_(memset
)(envvar
, 0, sizeof(envvar
));
575 VG_(sprintf
)(envvar
, "VALGRIND_STARTUP_PWD_%d_XYZZY",
576 (Int
)VG_(getppid
)());
577 wd
= VG_(getenv
)( envvar
);
580 SizeT need
= VG_(strlen
)(wd
) + 1;
581 startup_wd
= VG_(malloc
)("startup_wd", need
);
582 VG_(strcpy
)(startup_wd
, wd
);
583 startup_wd_acquired
= True
;
591 /* Return the previously acquired startup_wd. */
592 const HChar
*VG_(get_startup_wd
) ( void )
594 vg_assert(startup_wd_acquired
);
599 SysRes
VG_(poll
) (struct vki_pollfd
*fds
, Int nfds
, Int timeout
)
602 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
603 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
604 struct vki_timespec timeout_ts
;
606 timeout_ts
.tv_sec
= timeout
/ 1000;
607 timeout_ts
.tv_nsec
= ((long)timeout
% 1000) * 1000000;
609 res
= VG_(do_syscall4
)(__NR_ppoll
,
611 (UWord
)(timeout
>= 0 ? &timeout_ts
: NULL
),
613 # elif defined(VGO_linux)
614 res
= VG_(do_syscall3
)(__NR_poll
, (UWord
)fds
, nfds
, timeout
);
615 # elif defined(VGO_darwin)
616 res
= VG_(do_syscall3
)(__NR_poll_nocancel
, (UWord
)fds
, nfds
, timeout
);
617 # elif defined(VGO_solaris)
618 struct vki_timespec ts
;
619 struct vki_timespec
*tsp
;
624 ts
.tv_sec
= timeout
/ 1000;
625 ts
.tv_nsec
= (timeout
% 1000) * 1000000;
629 res
= VG_(do_syscall4
)(__NR_pollsys
, (UWord
)fds
, nfds
, (UWord
)tsp
, 0);
637 /* Performs the readlink operation and puts the result into 'buf'.
638 Note, that the string in 'buf' is *not* null-terminated. The function
639 returns the number of characters put into 'buf' or -1 if an error
641 SSizeT
VG_(readlink
) (const HChar
* path
, HChar
* buf
, SizeT bufsiz
)
644 /* res = readlink( path, buf, bufsiz ); */
645 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
646 res
= VG_(do_syscall4
)(__NR_readlinkat
, VKI_AT_FDCWD
,
647 (UWord
)path
, (UWord
)buf
, bufsiz
);
648 # elif defined(VGO_linux) || defined(VGO_darwin)
649 res
= VG_(do_syscall3
)(__NR_readlink
, (UWord
)path
, (UWord
)buf
, bufsiz
);
650 # elif defined(VGO_solaris)
651 res
= VG_(do_syscall4
)(__NR_readlinkat
, VKI_AT_FDCWD
, (UWord
)path
,
656 return sr_isError(res
) ? -1 : sr_Res(res
);
659 #if defined(VGO_linux) || defined(VGO_solaris)
660 Int
VG_(getdents64
) (Int fd
, struct vki_dirent64
*dirp
, UInt count
)
663 /* res = getdents( fd, dirp, count ); */
664 # if defined(VGP_amd64_solaris)
665 /* This silently assumes that dirent64 and dirent on amd64 are same, which
666 they should always be. */
667 res
= VG_(do_syscall3
)(__NR_getdents
, fd
, (UWord
)dirp
, count
);
669 res
= VG_(do_syscall3
)(__NR_getdents64
, fd
, (UWord
)dirp
, count
);
671 return sr_isError(res
) ? -1 : sr_Res(res
);
675 /* Check accessibility of a file. Returns zero for access granted,
676 nonzero otherwise. */
677 Int
VG_(access
) ( const HChar
* path
, Bool irusr
, Bool iwusr
, Bool ixusr
)
679 # if defined(VGO_linux)
680 /* Very annoyingly, I cannot find any definition for R_OK et al in
681 the kernel interfaces. Therefore I reluctantly resort to
682 hardwiring in these magic numbers that I determined by
689 UWord w
= (irusr
? VKI_R_OK
: 0)
690 | (iwusr
? VKI_W_OK
: 0)
691 | (ixusr
? VKI_X_OK
: 0);
692 # if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
693 SysRes res
= VG_(do_syscall3
)(__NR_faccessat
, VKI_AT_FDCWD
, (UWord
)path
, w
);
694 # elif defined(VGO_linux) || defined(VGO_darwin)
695 SysRes res
= VG_(do_syscall2
)(__NR_access
, (UWord
)path
, w
);
696 # elif defined(VGO_solaris)
697 SysRes res
= VG_(do_syscall4
)(__NR_faccessat
, VKI_AT_FDCWD
, (UWord
)path
,
702 return sr_isError(res
) ? 1 : 0;
704 # if defined(VGO_linux)
712 Emulate the normal Unix permissions checking algorithm.
714 If owner matches, then use the owner permissions, else
715 if group matches, then use the group permissions, else
716 use other permissions.
718 Note that we can't deal properly with SUID/SGID. By default
719 (allow_setuid == False), we refuse to run them (otherwise the
720 executable may misbehave if it doesn't have the permissions it
721 thinks it does). However, the caller may indicate that setuid
722 executables are allowed, for example if we are going to exec them
723 but not trace into them (iow, client sys_execve when
724 clo_trace_children == False).
726 If VKI_EACCES is returned (iow, permission was refused), then
727 *is_setuid is set to True iff permission was refused because the
728 executable is setuid.
730 /* returns: 0 = success, non-0 is failure */
731 Int
VG_(check_executable
)(/*OUT*/Bool
* is_setuid
,
732 const HChar
* f
, Bool allow_setuid
)
735 SysRes res
= VG_(stat
)(f
, &st
);
740 if (sr_isError(res
)) {
744 if ( VKI_S_ISDIR (st
.mode
) ) {
748 if ( (st
.mode
& (VKI_S_ISUID
| VKI_S_ISGID
)) && !allow_setuid
) {
754 res
= VG_(getxattr
)(f
, "security.capability", (Addr
)0, 0);
755 if (!sr_isError(res
) && !allow_setuid
) {
761 if (VG_(geteuid
)() == st
.uid
) {
762 if (!(st
.mode
& VKI_S_IXUSR
))
767 if (VG_(getegid
)() == st
.gid
)
773 /* Find out # groups, allocate large enough array and fetch groups */
774 ngrp
= VG_(getgroups
)(0, NULL
);
776 groups
= VG_(malloc
)("check_executable", ngrp
* sizeof *groups
);
777 ngrp
= VG_(getgroups
)(ngrp
, groups
);
781 /* ngrp will be -1 if VG_(getgroups) failed. */
782 for (i
= 0; i
< ngrp
; i
++) {
783 if (groups
[i
] == st
.gid
) {
792 if (!(st
.mode
& VKI_S_IXGRP
)) {
795 } else if (!(st
.mode
& VKI_S_IXOTH
)) {
803 SysRes
VG_(pread
) ( Int fd
, void* buf
, Int count
, OffT offset
)
806 // on 32 bits platforms, we receive a 32 bits OffT but
807 // we must extend it to pass a long long 64 bits.
808 # if defined(VGP_x86_linux)
809 vg_assert(sizeof(OffT
) == 4);
810 res
= VG_(do_syscall5
)(__NR_pread64
, fd
, (UWord
)buf
, count
,
811 offset
, 0); // Little endian long long
813 # elif defined(VGP_arm_linux)
814 vg_assert(sizeof(OffT
) == 4);
815 res
= VG_(do_syscall5
)(__NR_pread64
, fd
, (UWord
)buf
, count
,
816 0, offset
); // Big endian long long
818 # elif defined(VGP_ppc32_linux)
819 vg_assert(sizeof(OffT
) == 4);
820 res
= VG_(do_syscall6
)(__NR_pread64
, fd
, (UWord
)buf
, count
,
821 0, // Padding needed on PPC32
822 0, offset
); // Big endian long long
824 # elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
825 vg_assert(sizeof(OffT
) == 4);
826 res
= VG_(do_syscall6
)(__NR_pread64
, fd
, (UWord
)buf
, count
,
829 # elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
830 vg_assert(sizeof(OffT
) == 4);
831 res
= VG_(do_syscall6
)(__NR_pread64
, fd
, (UWord
)buf
, count
,
834 # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
835 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
836 || defined(VGP_mips64_linux) \
837 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
838 res
= VG_(do_syscall4
)(__NR_pread64
, fd
, (UWord
)buf
, count
, offset
);
840 # elif defined(VGP_amd64_darwin)
841 vg_assert(sizeof(OffT
) == 8);
842 res
= VG_(do_syscall4
)(__NR_pread_nocancel
, fd
, (UWord
)buf
, count
, offset
);
844 # elif defined(VGP_x86_darwin)
845 vg_assert(sizeof(OffT
) == 8);
846 res
= VG_(do_syscall5
)(__NR_pread_nocancel
, fd
, (UWord
)buf
, count
,
847 offset
& 0xffffffff, offset
>> 32);
849 # elif defined(VGP_x86_solaris)
850 vg_assert(sizeof(OffT
) == 4);
851 res
= VG_(do_syscall4
)(__NR_pread
, fd
, (UWord
)buf
, count
, offset
);
853 # elif defined(VGP_amd64_solaris)
854 vg_assert(sizeof(OffT
) == 8);
855 res
= VG_(do_syscall4
)(__NR_pread
, fd
, (UWord
)buf
, count
, offset
);
858 # error "Unknown platform"
862 /* Return the name of a directory for temporary files. */
863 const HChar
*VG_(tmpdir
)(void)
867 tmpdir
= VG_(getenv
)("TMPDIR");
868 if (tmpdir
== NULL
|| *tmpdir
== '\0') tmpdir
= VG_TMPDIR
;
869 if (tmpdir
== NULL
|| *tmpdir
== '\0') tmpdir
= "/tmp"; /* fallback */
874 static const HChar mkstemp_format
[] = "%s/valgrind_%s_%08x";
876 SizeT
VG_(mkstemp_fullname_bufsz
) ( SizeT part_of_name_len
)
878 return VG_(strlen
)(mkstemp_format
)
879 + VG_(strlen
)(VG_(tmpdir
)()) - 2 // %s tmpdir
880 + part_of_name_len
- 2 // %s part_of_name
886 Int
VG_(mkstemp
) ( const HChar
* part_of_name
, /*OUT*/HChar
* fullname
)
893 vg_assert(part_of_name
);
895 n
= VG_(strlen
)(part_of_name
);
896 vg_assert(n
> 0 && n
< 100);
898 seed
= (VG_(getpid
)() << 9) ^ VG_(getppid
)();
900 /* Determine sensible location for temporary files */
901 tmpdir
= VG_(tmpdir
)();
907 VG_(sprintf
)( fullname
, mkstemp_format
,
908 tmpdir
, part_of_name
, VG_(random
)( &seed
));
910 VG_(printf
)("VG_(mkstemp): trying: %s\n", fullname
);
912 sres
= VG_(open
)(fullname
,
913 VKI_O_CREAT
|VKI_O_RDWR
|VKI_O_EXCL
|VKI_O_TRUNC
,
914 VKI_S_IRUSR
|VKI_S_IWUSR
);
915 if (sr_isError(sres
)) {
916 VG_(umsg
)("VG_(mkstemp): failed to create temp file: %s\n", fullname
);
919 /* VG_(safe_fd) doesn't return if it fails. */
920 return VG_(safe_fd
)( sr_Res(sres
) );
926 /* ---------------------------------------------------------------------
927 Socket-related stuff.
928 ------------------------------------------------------------------ */
931 Int
parse_inet_addr_and_port ( const HChar
* str
, UInt
* ip_addr
, UShort
* port
);
934 Int
my_connect ( Int sockfd
, struct vki_sockaddr_in
* serv_addr
, Int addrlen
);
936 UInt
VG_(htonl
) ( UInt x
)
938 # if defined(VG_BIGENDIAN)
942 (((x
>> 24) & 0xFF) << 0) | (((x
>> 16) & 0xFF) << 8)
943 | (((x
>> 8) & 0xFF) << 16) | (((x
>> 0) & 0xFF) << 24);
947 UInt
VG_(ntohl
) ( UInt x
)
949 # if defined(VG_BIGENDIAN)
953 (((x
>> 24) & 0xFF) << 0) | (((x
>> 16) & 0xFF) << 8)
954 | (((x
>> 8) & 0xFF) << 16) | (((x
>> 0) & 0xFF) << 24);
958 UShort
VG_(htons
) ( UShort x
)
960 # if defined(VG_BIGENDIAN)
964 (((x
>> 8) & 0xFF) << 0) | (((x
>> 0) & 0xFF) << 8);
968 UShort
VG_(ntohs
) ( UShort x
)
970 # if defined(VG_BIGENDIAN)
974 (((x
>> 8) & 0xFF) << 0) | (((x
>> 0) & 0xFF) << 8);
979 /* The main function.
981 Supplied string contains either an ip address "192.168.0.1" or
982 an ip address and port pair, "192.168.0.1:1500". Parse these,
984 -1 if there is a parse error
985 -2 if no parse error, but specified host:port cannot be opened
986 the relevant file (socket) descriptor, otherwise.
989 Int
VG_(connect_via_socket
)( const HChar
* str
)
991 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
993 struct vki_sockaddr_in servAddr
;
995 UShort port
= VG_CLO_DEFAULT_LOGPORT
;
996 Bool ok
= parse_inet_addr_and_port(str
, &ip
, &port
);
1001 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1002 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1003 // (ip >> 8) & 0xFF, ip & 0xFF,
1006 servAddr
.sin_family
= VKI_AF_INET
;
1007 servAddr
.sin_addr
.s_addr
= VG_(htonl
)(ip
);
1008 servAddr
.sin_port
= VG_(htons
)(port
);
1011 sd
= VG_(socket
)(VKI_AF_INET
, VKI_SOCK_STREAM
, 0 /* IPPROTO_IP ? */);
1013 /* this shouldn't happen ... nevertheless */
1017 /* connect to server */
1018 res
= my_connect(sd
, &servAddr
, sizeof(servAddr
));
1020 /* connection failed */
1027 # error "Unknown OS"
1032 /* Let d = one or more digits. Accept either:
1033 d.d.d.d or d.d.d.d:d
1035 static Int
parse_inet_addr_and_port ( const HChar
* str
, UInt
* ip_addr
, UShort
* port
)
1037 # define GET_CH ((*str) ? (*str++) : 0)
1038 UInt ipa
, i
, j
, c
, any
;
1040 for (i
= 0; i
< 4; i
++) {
1045 if (c
< '0' || c
> '9') break;
1046 j
= 10 * j
+ (int)(c
- '0');
1049 if (any
== 0 || j
> 255) goto syntaxerr
;
1050 ipa
= (ipa
<< 8) + j
;
1051 if (i
<= 2 && c
!= '.') goto syntaxerr
;
1053 if (c
== 0 || c
== ':')
1055 if (c
== 0) goto ok
;
1056 if (c
!= ':') goto syntaxerr
;
1061 if (c
< '0' || c
> '9') break;
1062 j
= j
* 10 + (int)(c
- '0');
1064 if (j
> 65535) goto syntaxerr
;
1066 if (any
== 0 || c
!= 0) goto syntaxerr
;
1067 if (j
< 1024) goto syntaxerr
;
1076 // GrP fixme safe_fd?
1077 Int
VG_(socket
) ( Int domain
, Int type
, Int protocol
)
1079 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1080 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1081 || defined(VGP_s390x_linux)
1087 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_SOCKET
, (UWord
)&args
);
1088 return sr_isError(res
) ? -1 : sr_Res(res
);
1090 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1091 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1092 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1094 res
= VG_(do_syscall3
)(__NR_socket
, domain
, type
, protocol
);
1095 return sr_isError(res
) ? -1 : sr_Res(res
);
1097 # elif defined(VGO_darwin)
1099 res
= VG_(do_syscall3
)(__NR_socket
, domain
, type
, protocol
);
1100 if (!sr_isError(res
)) {
1101 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
1104 res2
= VG_(do_syscall5
)(__NR_setsockopt
, sr_Res(res
), VKI_SOL_SOCKET
,
1105 VKI_SO_NOSIGPIPE
, (UWord
)&optval
,
1107 // ignore setsockopt() error
1109 return sr_isError(res
) ? -1 : sr_Res(res
);
1111 # elif defined(VGO_solaris)
1112 /* XXX There doesn't seem to be an easy way to convince the send syscall to
1113 only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
1114 SM_KERNEL is set on the socket. Without serious hackery it looks we
1115 can't set this flag.
1117 Should we wrap the send syscall below into sigprocmask calls to block
1121 res
= VG_(do_syscall5
)(__NR_so_socket
, domain
, type
, protocol
,
1122 0 /*devpath*/, VKI_SOV_DEFAULT
/*version*/);
1123 return sr_isError(res
) ? -1 : sr_Res(res
);
1126 # error "Unknown arch"
1132 Int
my_connect ( Int sockfd
, struct vki_sockaddr_in
* serv_addr
, Int addrlen
)
1134 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1135 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1136 || defined(VGP_s390x_linux)
1140 args
[1] = (UWord
)serv_addr
;
1142 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_CONNECT
, (UWord
)&args
);
1143 return sr_isError(res
) ? -1 : sr_Res(res
);
1145 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1146 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1147 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1149 res
= VG_(do_syscall3
)(__NR_connect
, sockfd
, (UWord
)serv_addr
, addrlen
);
1150 return sr_isError(res
) ? -1 : sr_Res(res
);
1152 # elif defined(VGO_darwin)
1154 res
= VG_(do_syscall3
)(__NR_connect_nocancel
,
1155 sockfd
, (UWord
)serv_addr
, addrlen
);
1156 return sr_isError(res
) ? -1 : sr_Res(res
);
1158 # elif defined(VGO_solaris)
1160 res
= VG_(do_syscall4
)(__NR_connect
, sockfd
, (UWord
)serv_addr
, addrlen
,
1161 VKI_SOV_DEFAULT
/*version*/);
1162 return sr_isError(res
) ? -1 : sr_Res(res
);
1165 # error "Unknown arch"
1169 Int
VG_(write_socket
)( Int sd
, const void *msg
, Int count
)
1171 /* This is actually send(). */
1173 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
1174 errors on stream oriented sockets when the other end breaks the
1175 connection. The EPIPE error is still returned.
1177 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1180 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1181 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1182 || defined(VGP_s390x_linux)
1186 args
[1] = (UWord
)msg
;
1188 args
[3] = VKI_MSG_NOSIGNAL
;
1189 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_SEND
, (UWord
)&args
);
1190 return sr_isError(res
) ? -1 : sr_Res(res
);
1192 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1193 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1194 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1196 res
= VG_(do_syscall6
)(__NR_sendto
, sd
, (UWord
)msg
,
1197 count
, VKI_MSG_NOSIGNAL
, 0,0);
1198 return sr_isError(res
) ? -1 : sr_Res(res
);
1200 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1202 res
= VG_(do_syscall3
)(__NR_write_nocancel
, sd
, (UWord
)msg
, count
);
1203 return sr_isError(res
) ? -1 : sr_Res(res
);
1205 # elif defined(VGO_solaris)
1207 res
= VG_(do_syscall4
)(__NR_send
, sd
, (UWord
)msg
, count
, 0 /*flags*/);
1208 return sr_isError(res
) ? -1 : sr_Res(res
);
1211 # error "Unknown platform"
1215 Int
VG_(getsockname
) ( Int sd
, struct vki_sockaddr
*name
, Int
*namelen
)
1217 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1218 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1219 || defined(VGP_s390x_linux) \
1220 || defined(VGP_mips32_linux)
1224 args
[1] = (UWord
)name
;
1225 args
[2] = (UWord
)namelen
;
1226 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_GETSOCKNAME
, (UWord
)&args
);
1227 return sr_isError(res
) ? -1 : sr_Res(res
);
1229 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1230 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1231 || defined(VGP_tilegx_linux)
1233 res
= VG_(do_syscall3
)( __NR_getsockname
,
1234 (UWord
)sd
, (UWord
)name
, (UWord
)namelen
);
1235 return sr_isError(res
) ? -1 : sr_Res(res
);
1237 # elif defined(VGO_darwin)
1239 res
= VG_(do_syscall3
)( __NR_getsockname
,
1240 (UWord
)sd
, (UWord
)name
, (UWord
)namelen
);
1241 return sr_isError(res
) ? -1 : sr_Res(res
);
1243 # elif defined(VGO_solaris)
1245 res
= VG_(do_syscall4
)(__NR_getsockname
, sd
, (UWord
)name
, (UWord
)namelen
,
1246 VKI_SOV_DEFAULT
/*version*/);
1247 return sr_isError(res
) ? -1 : sr_Res(res
);
1250 # error "Unknown platform"
1254 Int
VG_(getpeername
) ( Int sd
, struct vki_sockaddr
*name
, Int
*namelen
)
1256 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1257 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1258 || defined(VGP_s390x_linux) \
1259 || defined(VGP_mips32_linux)
1263 args
[1] = (UWord
)name
;
1264 args
[2] = (UWord
)namelen
;
1265 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_GETPEERNAME
, (UWord
)&args
);
1266 return sr_isError(res
) ? -1 : sr_Res(res
);
1268 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1269 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1270 || defined(VGP_tilegx_linux)
1272 res
= VG_(do_syscall3
)( __NR_getpeername
,
1273 (UWord
)sd
, (UWord
)name
, (UWord
)namelen
);
1274 return sr_isError(res
) ? -1 : sr_Res(res
);
1276 # elif defined(VGO_darwin)
1278 res
= VG_(do_syscall3
)( __NR_getpeername
,
1279 (UWord
)sd
, (UWord
)name
, (UWord
)namelen
);
1280 return sr_isError(res
) ? -1 : sr_Res(res
);
1282 # elif defined(VGO_solaris)
1284 res
= VG_(do_syscall4
)(__NR_getpeername
, sd
, (UWord
)name
, (UWord
)namelen
,
1285 VKI_SOV_DEFAULT
/*version*/);
1286 return sr_isError(res
) ? -1 : sr_Res(res
);
1289 # error "Unknown platform"
1293 Int
VG_(getsockopt
) ( Int sd
, Int level
, Int optname
, void *optval
,
1296 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1297 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1298 || defined(VGP_s390x_linux)
1304 args
[3] = (UWord
)optval
;
1305 args
[4] = (UWord
)optlen
;
1306 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_GETSOCKOPT
, (UWord
)&args
);
1307 return sr_isError(res
) ? -1 : sr_Res(res
);
1309 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1310 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1311 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1313 res
= VG_(do_syscall5
)( __NR_getsockopt
,
1314 (UWord
)sd
, (UWord
)level
, (UWord
)optname
,
1315 (UWord
)optval
, (UWord
)optlen
);
1316 return sr_isError(res
) ? -1 : sr_Res(res
);
1318 # elif defined(VGO_darwin)
1320 res
= VG_(do_syscall5
)( __NR_getsockopt
,
1321 (UWord
)sd
, (UWord
)level
, (UWord
)optname
,
1322 (UWord
)optval
, (UWord
)optlen
);
1323 return sr_isError(res
) ? -1 : sr_Res(res
);
1325 # elif defined(VGO_solaris)
1327 res
= VG_(do_syscall6
)(__NR_getsockopt
, sd
, level
, optname
, (UWord
)optval
,
1328 (UWord
)optlen
, VKI_SOV_DEFAULT
/*version*/);
1329 return sr_isError(res
) ? -1 : sr_Res(res
);
1332 # error "Unknown platform"
1337 Int
VG_(setsockopt
) ( Int sd
, Int level
, Int optname
, void *optval
,
1340 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1341 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1342 || defined(VGP_s390x_linux)
1348 args
[3] = (UWord
)optval
;
1349 args
[4] = (UWord
)optlen
;
1350 res
= VG_(do_syscall2
)(__NR_socketcall
, VKI_SYS_SETSOCKOPT
, (UWord
)&args
);
1351 return sr_isError(res
) ? -1 : sr_Res(res
);
1353 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1354 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1355 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1357 res
= VG_(do_syscall5
)( __NR_setsockopt
,
1358 (UWord
)sd
, (UWord
)level
, (UWord
)optname
,
1359 (UWord
)optval
, (UWord
)optlen
);
1360 return sr_isError(res
) ? -1 : sr_Res(res
);
1362 # elif defined(VGO_darwin)
1364 res
= VG_(do_syscall5
)( __NR_setsockopt
,
1365 (UWord
)sd
, (UWord
)level
, (UWord
)optname
,
1366 (UWord
)optval
, (UWord
)optlen
);
1367 return sr_isError(res
) ? -1 : sr_Res(res
);
1369 # elif defined(VGO_solaris)
1371 res
= VG_(do_syscall6
)( __NR_setsockopt
,
1372 (UWord
)sd
, (UWord
)level
, (UWord
)optname
,
1373 (UWord
)optval
, (UWord
)optlen
,
1374 VKI_SOV_DEFAULT
/*version*/ );
1375 return sr_isError(res
) ? -1 : sr_Res(res
);
1378 # error "Unknown platform"
1383 const HChar
*VG_(basename
)(const HChar
*path
)
1385 static HChar
*buf
= NULL
;
1386 static SizeT buf_len
= 0;
1387 const HChar
*p
, *end
;
1390 0 == VG_(strcmp
)(path
, ""))
1395 p
= path
+ VG_(strlen
)(path
);
1396 while (p
> path
&& *p
== '/') {
1397 // skip all trailing '/'
1401 if (p
== path
&& *p
== '/') return "/"; // all slashes
1405 while (p
> path
&& *p
!= '/') {
1412 SizeT need
= end
-p
+1 + 1;
1413 if (need
> buf_len
) {
1414 buf_len
= (buf_len
== 0) ? 500 : need
;
1415 buf
= VG_(realloc
)("basename", buf
, buf_len
);
1417 VG_(strncpy
)(buf
, p
, end
-p
+1);
1418 buf
[end
-p
+1] = '\0';
1424 const HChar
*VG_(dirname
)(const HChar
*path
)
1426 static HChar
*buf
= NULL
;
1427 static SizeT buf_len
= 0;
1432 0 == VG_(strcmp
)(path
, "") ||
1433 0 == VG_(strcmp
)(path
, "/"))
1438 p
= path
+ VG_(strlen
)(path
);
1439 while (p
> path
&& *p
== '/') {
1440 // skip all trailing '/'
1444 while (p
> path
&& *p
!= '/') {
1450 if (*p
== '/') return "/"; // all slashes
1451 else return "."; // no slashes
1454 while (p
> path
&& *p
== '/') {
1459 SizeT need
= p
-path
+1 + 1;
1460 if (need
> buf_len
) {
1461 buf_len
= (buf_len
== 0) ? 500 : need
;
1462 buf
= VG_(realloc
)("dirname", buf
, buf_len
);
1464 VG_(strncpy
)(buf
, path
, p
-path
+1);
1465 buf
[p
-path
+1] = '\0';
1471 /*--------------------------------------------------------------------*/
1473 /*--------------------------------------------------------------------*/