Home | History | Annotate | Download | only in coregrind
      1 
      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-2013 Julian Seward
     11       jseward (at) 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 
     31 #include "pub_core_basics.h"
     32 #include "pub_core_vki.h"
     33 #include "pub_core_vkiscnums.h"
     34 #include "pub_core_debuglog.h"
     35 #include "pub_core_libcbase.h"
     36 #include "pub_core_libcassert.h"
     37 #include "pub_core_libcfile.h"
     38 #include "pub_core_libcprint.h"     // VG_(sprintf)
     39 #include "pub_core_libcproc.h"      // VG_(getpid), VG_(getppid)
     40 #include "pub_core_xarray.h"
     41 #include "pub_core_clientstate.h"   // VG_(fd_hard_limit)
     42 #include "pub_core_syscall.h"
     43 
     44 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
     45    of syscalls rather than the vanilla version, if a _nocancel version
     46    is available.  See docs/internals/Darwin-notes.txt for the reason
     47    why. */
     48 
     49 /* ---------------------------------------------------------------------
     50    File stuff
     51    ------------------------------------------------------------------ */
     52 
     53 static inline Bool fd_exists(Int fd)
     54 {
     55    struct vg_stat st;
     56    return VG_(fstat)(fd, &st) == 0;
     57 }
     58 
     59 /* Move an fd into the Valgrind-safe range */
     60 Int VG_(safe_fd)(Int oldfd)
     61 {
     62    Int newfd;
     63 
     64    vg_assert(VG_(fd_hard_limit) != -1);
     65 
     66    newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
     67    if (newfd != -1)
     68       VG_(close)(oldfd);
     69 
     70    /* Set the close-on-exec flag for this fd. */
     71    VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
     72 
     73    vg_assert(newfd >= VG_(fd_hard_limit));
     74    return newfd;
     75 }
     76 
     77 /* Given a file descriptor, attempt to deduce its filename.  To do
     78    this, we use /proc/self/fd/<FD>.  If this doesn't point to a file,
     79    or if it doesn't exist, we return False. */
     80 Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
     81 {
     82 #  if defined(VGO_linux)
     83    HChar tmp[64];
     84    VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
     85    VG_(memset)(buf, 0, n_buf);
     86    if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/')
     87       return True;
     88    else
     89       return False;
     90 
     91 #  elif defined(VGO_darwin)
     92    HChar tmp[VKI_MAXPATHLEN+1];
     93    if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
     94       if (n_buf > 0) {
     95          VG_(strncpy)( buf, tmp, n_buf < sizeof(tmp) ? n_buf : sizeof(tmp) );
     96          buf[n_buf-1] = 0;
     97       }
     98       if (tmp[0] == '/') return True;
     99    }
    100    return False;
    101 
    102 #  else
    103 #     error Unknown OS
    104 #  endif
    105 }
    106 
    107 SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
    108 {
    109 #  if defined(VGP_arm64_linux)
    110    /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
    111    SysRes res = VG_(do_syscall4)(__NR_mknodat,
    112                                  VKI_AT_FDCWD, (UWord)pathname, mode, dev);
    113 #  elif defined(VGO_linux) || defined(VGO_darwin)
    114    SysRes res = VG_(do_syscall3)(__NR_mknod,
    115                                  (UWord)pathname, mode, dev);
    116 #  else
    117 #    error Unknown OS
    118 #  endif
    119    return res;
    120 }
    121 
    122 SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
    123 {
    124 #  if defined(VGP_arm64_linux)
    125    /* ARM64 wants to use __NR_openat rather than __NR_open. */
    126    SysRes res = VG_(do_syscall4)(__NR_openat,
    127                                  VKI_AT_FDCWD, (UWord)pathname, flags, mode);
    128 #  elif defined(VGO_linux)
    129    SysRes res = VG_(do_syscall3)(__NR_open,
    130                                  (UWord)pathname, flags, mode);
    131 #  elif defined(VGO_darwin)
    132    SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
    133                                  (UWord)pathname, flags, mode);
    134 #  else
    135 #    error Unknown OS
    136 #  endif
    137    return res;
    138 }
    139 
    140 Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
    141 {
    142    SysRes sr;
    143    sr = VG_(open) (pathname, flags, mode);
    144    if (sr_isError (sr))
    145       return -1;
    146    else
    147       return sr_Res (sr);
    148 }
    149 
    150 void VG_(close) ( Int fd )
    151 {
    152    /* Hmm.  Return value is not checked.  That's uncool. */
    153 #  if defined(VGO_linux)
    154    (void)VG_(do_syscall1)(__NR_close, fd);
    155 #  elif defined(VGO_darwin)
    156    (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
    157 #  else
    158 #    error Unknown OS
    159 #  endif
    160 }
    161 
    162 Int VG_(read) ( Int fd, void* buf, Int count)
    163 {
    164    Int    ret;
    165 #  if defined(VGO_linux)
    166    SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
    167 #  elif defined(VGO_darwin)
    168    SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
    169 #  else
    170 #    error Unknown OS
    171 #  endif
    172    if (sr_isError(res)) {
    173       ret = - (Int)(Word)sr_Err(res);
    174       vg_assert(ret < 0);
    175    } else {
    176       ret = (Int)(Word)sr_Res(res);
    177       vg_assert(ret >= 0);
    178    }
    179    return ret;
    180 }
    181 
    182 Int VG_(write) ( Int fd, const void* buf, Int count)
    183 {
    184    Int    ret;
    185 #  if defined(VGO_linux)
    186    SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
    187 #  elif defined(VGO_darwin)
    188    SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
    189 #  else
    190 #    error "Unknown OS"
    191 #  endif
    192    if (sr_isError(res)) {
    193       ret = - (Int)(Word)sr_Err(res);
    194       vg_assert(ret < 0);
    195    } else {
    196       ret = (Int)(Word)sr_Res(res);
    197       vg_assert(ret >= 0);
    198    }
    199    return ret;
    200 }
    201 
    202 
    203 Int VG_(pipe) ( Int fd[2] )
    204 {
    205 #  if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
    206    /* __NR_pipe has a strange return convention on mips32-linux. */
    207    SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
    208    if (!sr_isError(res)) {
    209       fd[0] = (Int)sr_Res(res);
    210       fd[1] = (Int)sr_ResEx(res);
    211       return 0;
    212    } else {
    213       return -1;
    214    }
    215 #  elif defined(VGP_arm64_linux)
    216    SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
    217    return sr_isError(res) ? -1 : 0;
    218 #  elif defined(VGO_linux)
    219    SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
    220    return sr_isError(res) ? -1 : 0;
    221 #  elif defined(VGO_darwin)
    222    /* __NR_pipe is UX64, so produces a double-word result */
    223    SysRes res = VG_(do_syscall0)(__NR_pipe);
    224    if (!sr_isError(res)) {
    225       fd[0] = (Int)sr_Res(res);
    226       fd[1] = (Int)sr_ResHI(res);
    227    }
    228    return sr_isError(res) ? -1 : 0;
    229 #  else
    230 #    error "Unknown OS"
    231 #  endif
    232 }
    233 
    234 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
    235 {
    236 #  if defined(VGO_linux) || defined(VGP_amd64_darwin)
    237 #  if defined(__NR__llseek)
    238    Off64T result;
    239    SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
    240                                  offset >> 32, offset & 0xffffffff,
    241                                  (UWord)&result, whence);
    242    return sr_isError(res) ? (-1) : result;
    243 #  else
    244    SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
    245    vg_assert(sizeof(Off64T) == sizeof(Word));
    246    return sr_isError(res) ? (-1) : sr_Res(res);
    247 #  endif
    248 #  elif defined(VGP_x86_darwin)
    249    SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
    250                                  offset & 0xffffffff, offset >> 32, whence);
    251    return sr_isError(res) ? (-1) : sr_Res(res);
    252 #  else
    253 #    error "Unknown plat"
    254 #  endif
    255    /* if you change the error-reporting conventions of this, also
    256       change all usage points. */
    257 }
    258 
    259 
    260 /* stat/fstat support.  It's uggerly.  We have impedance-match into a
    261    'struct vg_stat' in order to have a single structure that callers
    262    can use consistently on all platforms. */
    263 
    264 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
    265    do { \
    266       (_p_vgstat)->dev        = (ULong)( (_p_vkistat)->st_dev ); \
    267       (_p_vgstat)->ino        = (ULong)( (_p_vkistat)->st_ino ); \
    268       (_p_vgstat)->nlink      = (ULong)( (_p_vkistat)->st_nlink ); \
    269       (_p_vgstat)->mode       = (UInt) ( (_p_vkistat)->st_mode ); \
    270       (_p_vgstat)->uid        = (UInt) ( (_p_vkistat)->st_uid ); \
    271       (_p_vgstat)->gid        = (UInt) ( (_p_vkistat)->st_gid ); \
    272       (_p_vgstat)->rdev       = (ULong)( (_p_vkistat)->st_rdev ); \
    273       (_p_vgstat)->size       = (Long) ( (_p_vkistat)->st_size ); \
    274       (_p_vgstat)->blksize    = (ULong)( (_p_vkistat)->st_blksize ); \
    275       (_p_vgstat)->blocks     = (ULong)( (_p_vkistat)->st_blocks ); \
    276       (_p_vgstat)->atime      = (ULong)( (_p_vkistat)->st_atime ); \
    277       (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
    278       (_p_vgstat)->mtime      = (ULong)( (_p_vkistat)->st_mtime ); \
    279       (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
    280       (_p_vgstat)->ctime      = (ULong)( (_p_vkistat)->st_ctime ); \
    281       (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
    282    } while (0)
    283 
    284 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
    285 {
    286    SysRes res;
    287    VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
    288 
    289 #  if defined(VGO_linux) || defined(VGO_darwin)
    290    /* First try with stat64.  If that doesn't work out, fall back to
    291       the vanilla version. */
    292 #  if defined(__NR_stat64)
    293    { struct vki_stat64 buf64;
    294      res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
    295      if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
    296         /* Success, or any failure except ENOSYS */
    297         if (!sr_isError(res))
    298            TRANSLATE_TO_vg_stat(vgbuf, &buf64);
    299         return res;
    300      }
    301    }
    302 #  endif /* defined(__NR_stat64) */
    303    /* This is the fallback ("vanilla version"). */
    304    { struct vki_stat buf;
    305 #    if defined(VGP_arm64_linux)
    306      res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
    307                                               (UWord)file_name, (UWord)&buf);
    308 #    else
    309      res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
    310 #    endif
    311      if (!sr_isError(res))
    312         TRANSLATE_TO_vg_stat(vgbuf, &buf);
    313      return res;
    314    }
    315 
    316 #  else
    317 #    error Unknown OS
    318 #  endif
    319 }
    320 
    321 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
    322 {
    323    SysRes res;
    324    VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
    325 
    326 #  if defined(VGO_linux)  ||  defined(VGO_darwin)
    327    /* First try with fstat64.  If that doesn't work out, fall back to
    328       the vanilla version. */
    329 #  if defined(__NR_fstat64)
    330    { struct vki_stat64 buf64;
    331      res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
    332      if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
    333         /* Success, or any failure except ENOSYS */
    334         if (!sr_isError(res))
    335            TRANSLATE_TO_vg_stat(vgbuf, &buf64);
    336         return sr_isError(res) ? (-1) : 0;
    337      }
    338    }
    339 #  endif /* if defined(__NR_fstat64) */
    340    { struct vki_stat buf;
    341      res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf);
    342      if (!sr_isError(res))
    343         TRANSLATE_TO_vg_stat(vgbuf, &buf);
    344      return sr_isError(res) ? (-1) : 0;
    345    }
    346 
    347 #  else
    348 #    error Unknown OS
    349 #  endif
    350 }
    351 
    352 #undef TRANSLATE_TO_vg_stat
    353 
    354 
    355 Long VG_(fsize) ( Int fd )
    356 {
    357    struct vg_stat buf;
    358    Int res = VG_(fstat)( fd, &buf );
    359    return (res == -1) ? (-1LL) : buf.size;
    360 }
    361 
    362 SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
    363 {
    364    SysRes res;
    365 #if defined(VGO_linux)
    366    res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
    367                           attr_value, attr_value_len);
    368 #else
    369    res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
    370 #endif
    371    return res;
    372 }
    373 
    374 Bool VG_(is_dir) ( const HChar* f )
    375 {
    376    struct vg_stat buf;
    377    SysRes res = VG_(stat)(f, &buf);
    378    return sr_isError(res) ? False
    379                       : VKI_S_ISDIR(buf.mode) ? True : False;
    380 }
    381 
    382 SysRes VG_(dup) ( Int oldfd )
    383 {
    384    return VG_(do_syscall1)(__NR_dup, oldfd);
    385 }
    386 
    387 SysRes VG_(dup2) ( Int oldfd, Int newfd )
    388 {
    389 #  if defined(VGO_linux) || defined(VGO_darwin)
    390    return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
    391 #  else
    392 #    error Unknown OS
    393 #  endif
    394 }
    395 
    396 /* Returns -1 on error. */
    397 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
    398 {
    399 #  if defined(VGO_linux)
    400    SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
    401 #  elif defined(VGO_darwin)
    402    SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
    403 #  else
    404 #    error "Unknown OS"
    405 #  endif
    406    return sr_isError(res) ? -1 : sr_Res(res);
    407 }
    408 
    409 Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
    410 {
    411    SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
    412    return sr_isError(res) ? (-1) : 0;
    413 }
    414 
    415 Int VG_(unlink) ( const HChar* file_name )
    416 {
    417 #  if defined(VGP_arm64_linux)
    418    SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
    419                                                 (UWord)file_name);
    420 #  else
    421    SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
    422 #  endif
    423    return sr_isError(res) ? (-1) : 0;
    424 }
    425 
    426 /* The working directory at startup.  AIX doesn't provide an easy
    427    system call to do getcwd, but fortunately we don't need arbitrary
    428    getcwd support.  All that is really needed is to note the cwd at
    429    process startup.  Hence VG_(record_startup_wd) notes it (in a
    430    platform dependent way) and VG_(get_startup_wd) produces the noted
    431    value.  Hence: */
    432 static HChar startup_wd[VKI_PATH_MAX];
    433 static Bool  startup_wd_acquired = False;
    434 
    435 /* Record the process' working directory at startup.  Is intended to
    436    be called exactly once, at startup, before the working directory
    437    changes.  Return True for success, False for failure, so that the
    438    caller can bomb out suitably without creating module cycles if
    439    there is a problem. */
    440 Bool VG_(record_startup_wd) ( void )
    441 {
    442    const Int szB = sizeof(startup_wd);
    443    vg_assert(!startup_wd_acquired);
    444    vg_assert(szB >= 512 && szB <= 16384/*let's say*/); /* stay sane */
    445    VG_(memset)(startup_wd, 0, szB);
    446 #  if defined(VGO_linux)
    447    /* Simple: just ask the kernel */
    448    { SysRes res
    449         = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
    450      vg_assert(startup_wd[szB-1] == 0);
    451      if (sr_isError(res)) {
    452         return False;
    453      } else {
    454         startup_wd_acquired = True;
    455         return True;
    456      }
    457    }
    458 #  elif defined(VGO_darwin)
    459    /* We can't ask the kernel, so instead rely on launcher-*.c to
    460       tell us the startup path.  Note the env var is keyed to the
    461       parent's PID, not ours, since our parent is the launcher
    462       process. */
    463    { HChar  envvar[100];
    464      HChar* wd = NULL;
    465      VG_(memset)(envvar, 0, sizeof(envvar));
    466      VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
    467                           (Int)VG_(getppid)());
    468      wd = VG_(getenv)( envvar );
    469      if (wd == NULL || (1+VG_(strlen)(wd) >= szB))
    470         return False;
    471      VG_(strncpy_safely)(startup_wd, wd, szB);
    472      vg_assert(startup_wd[szB-1] == 0);
    473      startup_wd_acquired = True;
    474      return True;
    475    }
    476 #  else
    477 #    error Unknown OS
    478 #  endif
    479 }
    480 
    481 /* Copy the previously acquired startup_wd into buf[0 .. size-1],
    482    or return False if buf isn't big enough. */
    483 Bool VG_(get_startup_wd) ( HChar* buf, SizeT size )
    484 {
    485    vg_assert(startup_wd_acquired);
    486    vg_assert(startup_wd[ sizeof(startup_wd)-1 ] == 0);
    487    if (1+VG_(strlen)(startup_wd) >= size)
    488       return False;
    489    VG_(strncpy_safely)(buf, startup_wd, size);
    490    return True;
    491 }
    492 
    493 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
    494 {
    495    SysRes res;
    496 #  if defined(VGP_arm64_linux)
    497    /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
    498    struct vki_timespec timeout_ts;
    499    if (timeout >= 0) {
    500       timeout_ts.tv_sec = timeout / 1000;
    501       timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
    502    }
    503    res = VG_(do_syscall4)(__NR_ppoll,
    504                           (UWord)fds, nfds,
    505                           (UWord)(timeout >= 0 ? &timeout_ts : NULL),
    506                           (UWord)NULL);
    507 #  elif defined(VGO_linux)
    508    res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
    509 #  elif defined(VGO_darwin)
    510    res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
    511 #  else
    512 #    error "Unknown OS"
    513 #  endif
    514    return res;
    515 }
    516 
    517 
    518 Int VG_(readlink) (const HChar* path, HChar* buf, UInt bufsiz)
    519 {
    520    SysRes res;
    521    /* res = readlink( path, buf, bufsiz ); */
    522 #  if defined(VGP_arm64_linux)
    523    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
    524                                            (UWord)path, (UWord)buf, bufsiz);
    525 #  else
    526    res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
    527 #  endif
    528    return sr_isError(res) ? -1 : sr_Res(res);
    529 }
    530 
    531 Int VG_(getdents) (Int fd, struct vki_dirent *dirp, UInt count)
    532 {
    533 #  if defined(VGO_linux)
    534    SysRes res;
    535    /* res = getdents( fd, dirp, count ); */
    536    res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
    537    return sr_isError(res) ? -1 : sr_Res(res);
    538 #  elif defined(VGO_darwin)
    539    I_die_here;
    540 #  else
    541 #    error "Unknown OS"
    542 #  endif
    543 }
    544 
    545 /* Check accessibility of a file.  Returns zero for access granted,
    546    nonzero otherwise. */
    547 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
    548 {
    549 #  if defined(VGO_linux)
    550    /* Very annoyingly, I cannot find any definition for R_OK et al in
    551       the kernel interfaces.  Therefore I reluctantly resort to
    552       hardwiring in these magic numbers that I determined by
    553       experimentation. */
    554 #  define VKI_R_OK 4
    555 #  define VKI_W_OK 2
    556 #  define VKI_X_OK 1
    557 #  endif
    558 
    559    UWord w = (irusr ? VKI_R_OK : 0)
    560              | (iwusr ? VKI_W_OK : 0)
    561              | (ixusr ? VKI_X_OK : 0);
    562 #  if defined(VGP_arm64_linux)
    563    SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
    564 #  else
    565    SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
    566 #  endif
    567    return sr_isError(res) ? 1 : 0;
    568 
    569 #  if defined(VGO_linux)
    570 #  undef VKI_R_OK
    571 #  undef VKI_W_OK
    572 #  undef VKI_X_OK
    573 #  endif
    574 }
    575 
    576 /*
    577    Emulate the normal Unix permissions checking algorithm.
    578 
    579    If owner matches, then use the owner permissions, else
    580    if group matches, then use the group permissions, else
    581    use other permissions.
    582 
    583    Note that we can't deal properly with SUID/SGID.  By default
    584    (allow_setuid == False), we refuse to run them (otherwise the
    585    executable may misbehave if it doesn't have the permissions it
    586    thinks it does).  However, the caller may indicate that setuid
    587    executables are allowed, for example if we are going to exec them
    588    but not trace into them (iow, client sys_execve when
    589    clo_trace_children == False).
    590 
    591    If VKI_EACCES is returned (iow, permission was refused), then
    592    *is_setuid is set to True iff permission was refused because the
    593    executable is setuid.
    594 */
    595 /* returns: 0 = success, non-0 is failure */
    596 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
    597                           const HChar* f, Bool allow_setuid)
    598 {
    599    struct vg_stat st;
    600    SysRes res = VG_(stat)(f, &st);
    601 
    602    if (is_setuid)
    603       *is_setuid = False;
    604 
    605    if (sr_isError(res)) {
    606       return sr_Err(res);
    607    }
    608 
    609    if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
    610       if (is_setuid)
    611          *is_setuid = True;
    612       return VKI_EACCES;
    613    }
    614 
    615    res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
    616    if (!sr_isError(res) && !allow_setuid) {
    617       if (is_setuid)
    618          *is_setuid = True;
    619       return VKI_EACCES;
    620    }
    621 
    622    if (VG_(geteuid)() == st.uid) {
    623       if (!(st.mode & VKI_S_IXUSR))
    624          return VKI_EACCES;
    625    } else {
    626       Int grpmatch = 0;
    627 
    628       if (VG_(getegid)() == st.gid)
    629 	 grpmatch = 1;
    630       else {
    631 	 UInt groups[32];
    632 	 Int ngrp = VG_(getgroups)(32, groups);
    633 	 Int i;
    634          /* ngrp will be -1 if VG_(getgroups) failed. */
    635          for (i = 0; i < ngrp; i++) {
    636 	    if (groups[i] == st.gid) {
    637 	       grpmatch = 1;
    638 	       break;
    639 	    }
    640          }
    641       }
    642 
    643       if (grpmatch) {
    644 	 if (!(st.mode & VKI_S_IXGRP)) {
    645             return VKI_EACCES;
    646          }
    647       } else if (!(st.mode & VKI_S_IXOTH)) {
    648          return VKI_EACCES;
    649       }
    650    }
    651 
    652    return 0;
    653 }
    654 
    655 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
    656 {
    657    SysRes res;
    658    // on 32 bits platforms, we receive a 32 bits OffT but
    659    // we must extend it to pass a long long 64 bits.
    660 #  if defined(VGP_x86_linux)
    661    vg_assert(sizeof(OffT) == 4);
    662    res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
    663                           offset, 0); // Little endian long long
    664    return res;
    665 #  elif defined(VGP_arm_linux)
    666    vg_assert(sizeof(OffT) == 4);
    667    res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
    668                           0, offset); // Big endian long long
    669    return res;
    670 #  elif defined(VGP_ppc32_linux)
    671    vg_assert(sizeof(OffT) == 4);
    672    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
    673                           0, // Padding needed on PPC32
    674                           0, offset); // Big endian long long
    675    return res;
    676 #  elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
    677    vg_assert(sizeof(OffT) == 4);
    678    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
    679                           0, offset, 0);
    680    return res;
    681 #  elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
    682    vg_assert(sizeof(OffT) == 4);
    683    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
    684                           0, 0, offset);
    685    return res;
    686 #  elif defined(VGP_amd64_linux) \
    687       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
    688       || defined(VGP_mips64_linux) \
    689       || defined(VGP_arm64_linux)
    690    res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
    691    return res;
    692 #  elif defined(VGP_amd64_darwin)
    693    vg_assert(sizeof(OffT) == 8);
    694    res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
    695    return res;
    696 #  elif defined(VGP_x86_darwin)
    697    vg_assert(sizeof(OffT) == 8);
    698    res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
    699                           offset & 0xffffffff, offset >> 32);
    700    return res;
    701 #  else
    702 #    error "Unknown platform"
    703 #  endif
    704 }
    705 
    706 /* Return the name of a directory for temporary files. */
    707 const HChar *VG_(tmpdir)(void)
    708 {
    709    const HChar *tmpdir;
    710 
    711    tmpdir = VG_(getenv)("TMPDIR");
    712    if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
    713    if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp";    /* fallback */
    714 
    715    return tmpdir;
    716 }
    717 
    718 static const HChar *mkstemp_format = "%s/valgrind_%s_%08x";
    719 
    720 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
    721 {
    722    return VG_(strlen)(mkstemp_format)
    723       + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
    724       + part_of_name_len - 2           // %s part_of_name
    725       + 8 - 4                          // %08x
    726       + 1;                             // trailing 0
    727 }
    728 
    729 
    730 /* Create and open (-rw------) a tmp file name incorporating said arg.
    731    Returns -1 on failure, else the fd of the file.  If fullname is
    732    non-NULL, the file's name is written into it.  The number of bytes
    733    written is equal to VG_(mkstemp_fullname_bufsz)(part_of_name). */
    734 
    735 Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
    736 {
    737    HChar  buf[VG_(mkstemp_fullname_bufsz)(VG_(strlen)(part_of_name))];
    738    Int    n, tries, fd;
    739    UInt   seed;
    740    SysRes sres;
    741    const HChar *tmpdir;
    742 
    743    vg_assert(part_of_name);
    744    n = VG_(strlen)(part_of_name);
    745    vg_assert(n > 0 && n < 100);
    746 
    747    seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
    748 
    749    /* Determine sensible location for temporary files */
    750    tmpdir = VG_(tmpdir)();
    751 
    752    tries = 0;
    753    while (True) {
    754       if (tries++ > 10)
    755          return -1;
    756       VG_(sprintf)( buf, "%s/valgrind_%s_%08x",
    757                     tmpdir, part_of_name, VG_(random)( &seed ));
    758       if (0)
    759          VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
    760 
    761       sres = VG_(open)(buf,
    762                        VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
    763                        VKI_S_IRUSR|VKI_S_IWUSR);
    764       if (sr_isError(sres)) {
    765          VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", buf);
    766          continue;
    767       }
    768       /* VG_(safe_fd) doesn't return if it fails. */
    769       fd = VG_(safe_fd)( sr_Res(sres) );
    770       if (fullname)
    771          VG_(strcpy)( fullname, buf );
    772       return fd;
    773    }
    774    /* NOTREACHED */
    775 }
    776 
    777 
    778 /* ---------------------------------------------------------------------
    779    Socket-related stuff.
    780    ------------------------------------------------------------------ */
    781 
    782 static
    783 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
    784 
    785 static
    786 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
    787 
    788 UInt VG_(htonl) ( UInt x )
    789 {
    790 #  if defined(VG_BIGENDIAN)
    791    return x;
    792 #  else
    793    return
    794       (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
    795       | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
    796 #  endif
    797 }
    798 
    799 UInt VG_(ntohl) ( UInt x )
    800 {
    801 #  if defined(VG_BIGENDIAN)
    802    return x;
    803 #  else
    804    return
    805       (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
    806       | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
    807 #  endif
    808 }
    809 
    810 UShort VG_(htons) ( UShort x )
    811 {
    812 #  if defined(VG_BIGENDIAN)
    813    return x;
    814 #  else
    815    return
    816       (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
    817 #  endif
    818 }
    819 
    820 UShort VG_(ntohs) ( UShort x )
    821 {
    822 #  if defined(VG_BIGENDIAN)
    823    return x;
    824 #  else
    825    return
    826       (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
    827 #  endif
    828 }
    829 
    830 
    831 /* The main function.
    832 
    833    Supplied string contains either an ip address "192.168.0.1" or
    834    an ip address and port pair, "192.168.0.1:1500".  Parse these,
    835    and return:
    836      -1 if there is a parse error
    837      -2 if no parse error, but specified host:port cannot be opened
    838      the relevant file (socket) descriptor, otherwise.
    839  is used.
    840 */
    841 Int VG_(connect_via_socket)( const HChar* str )
    842 {
    843 #  if defined(VGO_linux) || defined(VGO_darwin)
    844    Int sd, res;
    845    struct vki_sockaddr_in servAddr;
    846    UInt   ip   = 0;
    847    UShort port = VG_CLO_DEFAULT_LOGPORT;
    848    Bool   ok   = parse_inet_addr_and_port(str, &ip, &port);
    849    if (!ok)
    850       return -1;
    851 
    852    //if (0)
    853    //   VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
    854    //               (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
    855    //               (ip >> 8) & 0xFF, ip & 0xFF,
    856    //               (UInt)port );
    857 
    858    servAddr.sin_family = VKI_AF_INET;
    859    servAddr.sin_addr.s_addr = VG_(htonl)(ip);
    860    servAddr.sin_port = VG_(htons)(port);
    861 
    862    /* create socket */
    863    sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
    864    if (sd < 0) {
    865       /* this shouldn't happen ... nevertheless */
    866       return -2;
    867    }
    868 
    869    /* connect to server */
    870    res = my_connect(sd, &servAddr, sizeof(servAddr));
    871    if (res < 0) {
    872       /* connection failed */
    873       return -2;
    874    }
    875 
    876    return sd;
    877 
    878 #  else
    879 #    error "Unknown OS"
    880 #  endif
    881 }
    882 
    883 
    884 /* Let d = one or more digits.  Accept either:
    885    d.d.d.d  or  d.d.d.d:d
    886 */
    887 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
    888 {
    889 #  define GET_CH ((*str) ? (*str++) : 0)
    890    UInt ipa, i, j, c, any;
    891    ipa = 0;
    892    for (i = 0; i < 4; i++) {
    893       j = 0;
    894       any = 0;
    895       while (1) {
    896          c = GET_CH;
    897          if (c < '0' || c > '9') break;
    898          j = 10 * j + (int)(c - '0');
    899          any = 1;
    900       }
    901       if (any == 0 || j > 255) goto syntaxerr;
    902       ipa = (ipa << 8) + j;
    903       if (i <= 2 && c != '.') goto syntaxerr;
    904    }
    905    if (c == 0 || c == ':')
    906       *ip_addr = ipa;
    907    if (c == 0) goto ok;
    908    if (c != ':') goto syntaxerr;
    909    j = 0;
    910    any = 0;
    911    while (1) {
    912       c = GET_CH;
    913       if (c < '0' || c > '9') break;
    914       j = j * 10 + (int)(c - '0');
    915       any = 1;
    916       if (j > 65535) goto syntaxerr;
    917    }
    918    if (any == 0 || c != 0) goto syntaxerr;
    919    if (j < 1024) goto syntaxerr;
    920    *port = (UShort)j;
    921  ok:
    922    return 1;
    923  syntaxerr:
    924    return 0;
    925 #  undef GET_CH
    926 }
    927 
    928 // GrP fixme safe_fd?
    929 Int VG_(socket) ( Int domain, Int type, Int protocol )
    930 {
    931 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
    932       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
    933    SysRes res;
    934    UWord  args[3];
    935    args[0] = domain;
    936    args[1] = type;
    937    args[2] = protocol;
    938    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
    939    return sr_isError(res) ? -1 : sr_Res(res);
    940 
    941 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
    942         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
    943         || defined(VGP_arm64_linux)
    944    SysRes res;
    945    res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
    946    return sr_isError(res) ? -1 : sr_Res(res);
    947 
    948 #  elif defined(VGO_darwin)
    949    SysRes res;
    950    res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
    951    if (!sr_isError(res)) {
    952        // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
    953        Int optval = 1;
    954        SysRes res2;
    955        res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
    956                                VKI_SO_NOSIGPIPE, (UWord)&optval,
    957                                sizeof(optval));
    958        // ignore setsockopt() error
    959    }
    960    return sr_isError(res) ? -1 : sr_Res(res);
    961 
    962 #  else
    963 #    error "Unknown arch"
    964 #  endif
    965 }
    966 
    967 
    968 static
    969 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
    970 {
    971 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
    972       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
    973    SysRes res;
    974    UWord  args[3];
    975    args[0] = sockfd;
    976    args[1] = (UWord)serv_addr;
    977    args[2] = addrlen;
    978    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
    979    return sr_isError(res) ? -1 : sr_Res(res);
    980 
    981 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
    982         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
    983         || defined(VGP_arm64_linux)
    984    SysRes res;
    985    res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
    986    return sr_isError(res) ? -1 : sr_Res(res);
    987 
    988 #  elif defined(VGO_darwin)
    989    SysRes res;
    990    res = VG_(do_syscall3)(__NR_connect_nocancel,
    991                           sockfd, (UWord)serv_addr, addrlen);
    992    return sr_isError(res) ? -1 : sr_Res(res);
    993 
    994 #  else
    995 #    error "Unknown arch"
    996 #  endif
    997 }
    998 
    999 Int VG_(write_socket)( Int sd, const void *msg, Int count )
   1000 {
   1001    /* This is actually send(). */
   1002 
   1003    /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
   1004       errors on stream oriented sockets when the other end breaks the
   1005       connection. The EPIPE error is still returned.
   1006 
   1007       For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
   1008       SIGPIPE */
   1009 
   1010 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1011       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
   1012    SysRes res;
   1013    UWord  args[4];
   1014    args[0] = sd;
   1015    args[1] = (UWord)msg;
   1016    args[2] = count;
   1017    args[3] = VKI_MSG_NOSIGNAL;
   1018    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
   1019    return sr_isError(res) ? -1 : sr_Res(res);
   1020 
   1021 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1022         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1023         || defined(VGP_arm64_linux)
   1024    SysRes res;
   1025    res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
   1026                                        count, VKI_MSG_NOSIGNAL, 0,0);
   1027    return sr_isError(res) ? -1 : sr_Res(res);
   1028 
   1029 #  elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
   1030    SysRes res;
   1031    res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
   1032    return sr_isError(res) ? -1 : sr_Res(res);
   1033 
   1034 #  else
   1035 #    error "Unknown platform"
   1036 #  endif
   1037 }
   1038 
   1039 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
   1040 {
   1041 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1042       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
   1043       || defined(VGP_mips32_linux)
   1044    SysRes res;
   1045    UWord  args[3];
   1046    args[0] = sd;
   1047    args[1] = (UWord)name;
   1048    args[2] = (UWord)namelen;
   1049    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
   1050    return sr_isError(res) ? -1 : sr_Res(res);
   1051 
   1052 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1053         || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
   1054    SysRes res;
   1055    res = VG_(do_syscall3)( __NR_getsockname,
   1056                            (UWord)sd, (UWord)name, (UWord)namelen );
   1057    return sr_isError(res) ? -1 : sr_Res(res);
   1058 
   1059 #  elif defined(VGO_darwin)
   1060    SysRes res;
   1061    res = VG_(do_syscall3)( __NR_getsockname,
   1062                            (UWord)sd, (UWord)name, (UWord)namelen );
   1063    return sr_isError(res) ? -1 : sr_Res(res);
   1064 
   1065 #  else
   1066 #    error "Unknown platform"
   1067 #  endif
   1068 }
   1069 
   1070 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
   1071 {
   1072 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1073       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
   1074       || defined(VGP_mips32_linux)
   1075    SysRes res;
   1076    UWord  args[3];
   1077    args[0] = sd;
   1078    args[1] = (UWord)name;
   1079    args[2] = (UWord)namelen;
   1080    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
   1081    return sr_isError(res) ? -1 : sr_Res(res);
   1082 
   1083 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1084         || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
   1085    SysRes res;
   1086    res = VG_(do_syscall3)( __NR_getpeername,
   1087                            (UWord)sd, (UWord)name, (UWord)namelen );
   1088    return sr_isError(res) ? -1 : sr_Res(res);
   1089 
   1090 #  elif defined(VGO_darwin)
   1091    SysRes res;
   1092    res = VG_(do_syscall3)( __NR_getpeername,
   1093                            (UWord)sd, (UWord)name, (UWord)namelen );
   1094    return sr_isError(res) ? -1 : sr_Res(res);
   1095 
   1096 #  else
   1097 #    error "Unknown platform"
   1098 #  endif
   1099 }
   1100 
   1101 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
   1102                       Int *optlen)
   1103 {
   1104 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1105       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
   1106    SysRes res;
   1107    UWord  args[5];
   1108    args[0] = sd;
   1109    args[1] = level;
   1110    args[2] = optname;
   1111    args[3] = (UWord)optval;
   1112    args[4] = (UWord)optlen;
   1113    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
   1114    return sr_isError(res) ? -1 : sr_Res(res);
   1115 
   1116 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1117         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1118         || defined(VGP_arm64_linux)
   1119    SysRes res;
   1120    res = VG_(do_syscall5)( __NR_getsockopt,
   1121                            (UWord)sd, (UWord)level, (UWord)optname,
   1122                            (UWord)optval, (UWord)optlen );
   1123    return sr_isError(res) ? -1 : sr_Res(res);
   1124 
   1125 #  elif defined(VGO_darwin)
   1126    SysRes res;
   1127    res = VG_(do_syscall5)( __NR_getsockopt,
   1128                            (UWord)sd, (UWord)level, (UWord)optname,
   1129                            (UWord)optval, (UWord)optlen );
   1130    return sr_isError(res) ? -1 : sr_Res(res);
   1131 
   1132 #  else
   1133 #    error "Unknown platform"
   1134 #  endif
   1135 }
   1136 
   1137 
   1138 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
   1139                       Int optlen)
   1140 {
   1141 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1142       || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
   1143    SysRes res;
   1144    UWord  args[5];
   1145    args[0] = sd;
   1146    args[1] = level;
   1147    args[2] = optname;
   1148    args[3] = (UWord)optval;
   1149    args[4] = (UWord)optlen;
   1150    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
   1151    return sr_isError(res) ? -1 : sr_Res(res);
   1152 
   1153 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1154         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1155         || defined(VGP_arm64_linux)
   1156    SysRes res;
   1157    res = VG_(do_syscall5)( __NR_setsockopt,
   1158                            (UWord)sd, (UWord)level, (UWord)optname,
   1159                            (UWord)optval, (UWord)optlen );
   1160    return sr_isError(res) ? -1 : sr_Res(res);
   1161 
   1162 #  elif defined(VGO_darwin)
   1163    SysRes res;
   1164    res = VG_(do_syscall5)( __NR_setsockopt,
   1165                            (UWord)sd, (UWord)level, (UWord)optname,
   1166                            (UWord)optval, (UWord)optlen );
   1167    return sr_isError(res) ? -1 : sr_Res(res);
   1168 
   1169 #  else
   1170 #    error "Unknown platform"
   1171 #  endif
   1172 }
   1173 
   1174 
   1175 const HChar *VG_(basename)(const HChar *path)
   1176 {
   1177    static HChar buf[VKI_PATH_MAX];
   1178 
   1179    const HChar *p, *end;
   1180 
   1181    if (path == NULL  ||
   1182        0 == VG_(strcmp)(path, ""))
   1183    {
   1184       return ".";
   1185    }
   1186 
   1187    p = path + VG_(strlen)(path);
   1188    while (p > path  &&  *p == '/') {
   1189       // skip all trailing '/'
   1190       p--;
   1191    }
   1192 
   1193    if (p == path  &&  *p == '/') return "/"; // all slashes
   1194 
   1195    end = p;
   1196 
   1197    while (p > path  &&  *p != '/') {
   1198       // now skip non '/'
   1199       p--;
   1200    }
   1201 
   1202    if (*p == '/') p++;
   1203 
   1204    VG_(strncpy)(buf, p, end-p+1);
   1205    buf[end-p+1] = '\0';
   1206 
   1207    return buf;
   1208 }
   1209 
   1210 
   1211 const HChar *VG_(dirname)(const HChar *path)
   1212 {
   1213    static HChar buf[VKI_PATH_MAX];
   1214 
   1215    const HChar *p;
   1216 
   1217    if (path == NULL  ||
   1218        0 == VG_(strcmp)(path, "")  ||
   1219        0 == VG_(strcmp)(path, "/"))
   1220    {
   1221       return ".";
   1222    }
   1223 
   1224    p = path + VG_(strlen)(path);
   1225    while (p > path  &&  *p == '/') {
   1226       // skip all trailing '/'
   1227       p--;
   1228    }
   1229 
   1230    while (p > path  &&  *p != '/') {
   1231       // now skip non '/'
   1232       p--;
   1233    }
   1234 
   1235    if (p == path) {
   1236       if (*p == '/') return "/"; // all slashes
   1237       else return "."; // no slashes
   1238    }
   1239 
   1240    while (p > path  &&  *p == '/') {
   1241       // skip '/' again
   1242       p--;
   1243    }
   1244 
   1245    VG_(strncpy)(buf, path, p-path+1);
   1246    buf[p-path+1] = '\0';
   1247 
   1248    return buf;
   1249 }
   1250 
   1251 
   1252 /*--------------------------------------------------------------------*/
   1253 /*--- end                                                          ---*/
   1254 /*--------------------------------------------------------------------*/
   1255