Home | History | Annotate | Download | only in coregrind
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 
      3 /*--------------------------------------------------------------------*/
      4 /*--- File- and socket-related libc stuff.            m_libcfile.c ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8    This file is part of Valgrind, a dynamic binary instrumentation
      9    framework.
     10 
     11    Copyright (C) 2000-2017 Julian Seward
     12       jseward (at) acm.org
     13 
     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.
     18 
     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.
     23 
     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
     27    02111-1307, USA.
     28 
     29    The GNU General Public License is contained in the file COPYING.
     30 */
     31 
     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"
     44 
     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
     48    why. */
     49 
     50 /* ---------------------------------------------------------------------
     51    File stuff
     52    ------------------------------------------------------------------ */
     53 
     54 /* Move an fd into the Valgrind-safe range */
     55 Int VG_(safe_fd)(Int oldfd)
     56 {
     57    Int newfd;
     58 
     59    vg_assert(VG_(fd_hard_limit) != -1);
     60 
     61    newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
     62    if (newfd != -1)
     63       VG_(close)(oldfd);
     64 
     65    /* Set the close-on-exec flag for this fd. */
     66    VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
     67 
     68    vg_assert(newfd >= VG_(fd_hard_limit));
     69    return newfd;
     70 }
     71 
     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
     78    cannot be deduced. */
     79 Bool VG_(resolve_filename) ( Int fd, const HChar** result )
     80 {
     81 #  if defined(VGO_linux) || defined(VGO_solaris)
     82    static HChar *buf = NULL;
     83    static SizeT  bufsiz = 0;
     84 
     85    if (buf == NULL) {   // first time
     86       bufsiz = 500;
     87       buf = VG_(malloc)("resolve_filename", bufsiz);
     88    }
     89 
     90    HChar tmp[64];   // large enough
     91    {
     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);
     96 #     endif
     97    }
     98 
     99    while (42) {
    100       SSizeT res = VG_(readlink)(tmp, buf, bufsiz);
    101       if (res < 0) break;
    102       if (res == bufsiz) {  // buffer too small; increase and retry
    103          bufsiz += 500;
    104          buf = VG_(realloc)("resolve_filename", buf, bufsiz);
    105          continue;
    106       }
    107       vg_assert(bufsiz > res);  // paranoia
    108       if (buf[0] != '/') break;
    109 
    110       buf[res] = '\0';
    111       *result = buf;
    112       return True;
    113    }
    114    // Failure
    115    *result = NULL;
    116    return False;
    117 
    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;
    122 
    123       if (buf == NULL)
    124          buf = VG_(malloc)("resolve_filename", VKI_MAXPATHLEN+1);
    125       VG_(strcpy)( buf, tmp );
    126 
    127       *result = buf;
    128       if (buf[0] == '/') return True;
    129    }
    130    // Failure
    131    *result = NULL;
    132    return False;
    133 
    134 #  else
    135 #     error Unknown OS
    136 #  endif
    137 }
    138 
    139 SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
    140 {
    141 #  if defined(VGP_arm64_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);
    151 #  else
    152 #    error Unknown OS
    153 #  endif
    154    return res;
    155 }
    156 
    157 SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
    158 {
    159 #  if defined(VGP_arm64_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);
    172 #  else
    173 #    error Unknown OS
    174 #  endif
    175    return res;
    176 }
    177 
    178 Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
    179 {
    180    SysRes sr;
    181    sr = VG_(open) (pathname, flags, mode);
    182    if (sr_isError (sr))
    183       return -1;
    184    else
    185       return sr_Res (sr);
    186 }
    187 
    188 void VG_(close) ( Int fd )
    189 {
    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);
    195 #  else
    196 #    error Unknown OS
    197 #  endif
    198 }
    199 
    200 Int VG_(read) ( Int fd, void* buf, Int count)
    201 {
    202    Int    ret;
    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);
    207 #  else
    208 #    error Unknown OS
    209 #  endif
    210    if (sr_isError(res)) {
    211       ret = - (Int)(Word)sr_Err(res);
    212       vg_assert(ret < 0);
    213    } else {
    214       ret = (Int)(Word)sr_Res(res);
    215       vg_assert(ret >= 0);
    216    }
    217    return ret;
    218 }
    219 
    220 Int VG_(write) ( Int fd, const void* buf, Int count)
    221 {
    222    Int    ret;
    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);
    227 #  else
    228 #    error "Unknown OS"
    229 #  endif
    230    if (sr_isError(res)) {
    231       ret = - (Int)(Word)sr_Err(res);
    232       vg_assert(ret < 0);
    233    } else {
    234       ret = (Int)(Word)sr_Res(res);
    235       vg_assert(ret >= 0);
    236    }
    237    return ret;
    238 }
    239 
    240 
    241 Int VG_(pipe) ( Int fd[2] )
    242 {
    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);
    249       return 0;
    250    } else {
    251       return -1;
    252    }
    253 #  elif defined(VGP_arm64_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);
    265    }
    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;
    271 #  else
    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);
    276    }
    277    return sr_isError(res) ? -1 : 0;
    278 #  endif
    279 #  else
    280 #    error "Unknown OS"
    281 #  endif
    282 }
    283 
    284 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
    285 {
    286 #  if defined(VGO_linux) || defined(VGP_amd64_darwin)
    287 #  if defined(__NR__llseek)
    288    Off64T result;
    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;
    293 #  else
    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);
    297 #  endif
    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);
    310 #  else
    311 #    error "Unknown plat"
    312 #  endif
    313    /* if you change the error-reporting conventions of this, also
    314       change all usage points. */
    315 }
    316 
    317 
    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. */
    321 
    322 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
    323    do { \
    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 ); \
    340    } while (0)
    341 
    342 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
    343 {
    344    SysRes res;
    345    VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
    346 
    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);
    357         return res;
    358      }
    359    }
    360 #  endif /* defined(__NR_stat64) */
    361    /* This is the fallback ("vanilla version"). */
    362    { struct vki_stat buf;
    363 #    if defined(VGP_arm64_linux)
    364      res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
    365                                               (UWord)file_name, (UWord)&buf);
    366 #    else
    367      res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
    368 #    endif
    369      if (!sr_isError(res))
    370         TRANSLATE_TO_vg_stat(vgbuf, &buf);
    371      return res;
    372    }
    373 #  elif defined(VGO_solaris)
    374    {
    375 #     if defined(VGP_x86_solaris)
    376       struct vki_stat64 buf64;
    377       res = VG_(do_syscall4)(__NR_fstatat64, VKI_AT_FDCWD, (UWord)file_name,
    378                              (UWord)&buf64, 0);
    379 #     elif defined(VGP_amd64_solaris)
    380       struct vki_stat buf64;
    381       res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name,
    382                              (UWord)&buf64, 0);
    383 #     else
    384 #        error "Unknown platform"
    385 #     endif
    386       if (!sr_isError(res))
    387          TRANSLATE_TO_vg_stat(vgbuf, &buf64);
    388       return res;
    389    }
    390 #  else
    391 #    error Unknown OS
    392 #  endif
    393 }
    394 
    395 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
    396 {
    397    SysRes res;
    398    VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
    399 
    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;
    411      }
    412    }
    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;
    419    }
    420 #  elif defined(VGO_solaris)
    421    {
    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);
    428 #     else
    429 #        error "Unknown platform"
    430 #     endif
    431       if (!sr_isError(res))
    432          TRANSLATE_TO_vg_stat(vgbuf, &buf64);
    433       return sr_isError(res) ? (-1) : 0;
    434    }
    435 #  else
    436 #    error Unknown OS
    437 #  endif
    438 }
    439 
    440 #undef TRANSLATE_TO_vg_stat
    441 
    442 
    443 Long VG_(fsize) ( Int fd )
    444 {
    445    struct vg_stat buf;
    446    Int res = VG_(fstat)( fd, &buf );
    447    return (res == -1) ? (-1LL) : buf.size;
    448 }
    449 
    450 SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
    451 {
    452    SysRes res;
    453 #if defined(VGO_linux)
    454    res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
    455                           attr_value, attr_value_len);
    456 #else
    457    res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
    458 #endif
    459    return res;
    460 }
    461 
    462 Bool VG_(is_dir) ( const HChar* f )
    463 {
    464    struct vg_stat buf;
    465    SysRes res = VG_(stat)(f, &buf);
    466    return sr_isError(res) ? False
    467                       : VKI_S_ISDIR(buf.mode) ? True : False;
    468 }
    469 
    470 SysRes VG_(dup) ( Int oldfd )
    471 {
    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);
    476 #  else
    477 #    error Unknown OS
    478 #  endif
    479 }
    480 
    481 SysRes VG_(dup2) ( Int oldfd, Int newfd )
    482 {
    483 #  if defined(VGP_arm64_linux)
    484    /* We only have dup3, that means we have to mimic dup2.
    485       The only real difference is when oldfd == newfd.
    486       dup3 always returns an error, but dup2 returns only an
    487       error if the fd is invalid, otherwise it returns newfd. */
    488    if (oldfd == newfd) {
    489       if (VG_(fcntl)(oldfd, VKI_F_GETFL, 0) == -1)
    490          return VG_(mk_SysRes_Error)(VKI_EBADF);
    491       return VG_(mk_SysRes_Success)(newfd);
    492    }
    493    return VG_(do_syscall3)(__NR_dup3, oldfd, newfd, 0);
    494 #  elif defined(VGO_linux) || defined(VGO_darwin)
    495    return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
    496 #  elif defined(VGO_solaris)
    497    return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
    498 #  else
    499 #    error Unknown OS
    500 #  endif
    501 }
    502 
    503 /* Returns -1 on error. */
    504 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
    505 {
    506 #  if defined(VGO_linux) || defined(VGO_solaris)
    507    SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
    508 #  elif defined(VGO_darwin)
    509    SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
    510 #  else
    511 #    error "Unknown OS"
    512 #  endif
    513    return sr_isError(res) ? -1 : sr_Res(res);
    514 }
    515 
    516 Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
    517 {
    518 #  if defined(VGO_solaris) || defined(VGP_arm64_linux)
    519    SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
    520                                  VKI_AT_FDCWD, (UWord)new_name);
    521 #  elif defined(VGO_linux) || defined(VGO_darwin)
    522    SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
    523 #  else
    524 #    error "Unknown OS"
    525 #  endif
    526    return sr_isError(res) ? (-1) : 0;
    527 }
    528 
    529 Int VG_(unlink) ( const HChar* file_name )
    530 {
    531 #  if defined(VGP_arm64_linux)
    532    SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
    533                                                 (UWord)file_name);
    534 #  elif defined(VGO_linux) || defined(VGO_darwin)
    535    SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
    536 #  elif defined(VGO_solaris)
    537    SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
    538                                  (UWord)file_name, 0);
    539 #  else
    540 #    error "Unknown OS"
    541 #  endif
    542    return sr_isError(res) ? (-1) : 0;
    543 }
    544 
    545 /* The working directory at startup.
    546    All that is really needed is to note the cwd at process startup.
    547    Hence VG_(record_startup_wd) notes it (in a platform dependent way)
    548    and VG_(get_startup_wd) produces the noted value. */
    549 static HChar *startup_wd;
    550 
    551 /* Record the process' working directory at startup.  Is intended to
    552    be called exactly once, at startup, before the working directory
    553    changes. */
    554 void VG_(record_startup_wd) ( void )
    555 {
    556 #  if defined(VGO_linux) || defined(VGO_solaris)
    557    /* Simple: just ask the kernel */
    558    SysRes res;
    559    SizeT szB = 0;
    560    do {
    561       szB += 500;
    562       startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
    563       VG_(memset)(startup_wd, 0, szB);
    564       res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
    565    } while (sr_isError(res) && sr_Err(res) == VKI_ERANGE);
    566 
    567    if (sr_isError(res)) {
    568       VG_(free)(startup_wd);
    569       startup_wd = NULL;
    570       return;
    571    }
    572 
    573    vg_assert(startup_wd[szB-1] == 0);
    574 
    575 #  elif defined(VGO_darwin)
    576    /* We can't ask the kernel, so instead rely on launcher-*.c to
    577       tell us the startup path.  Note the env var is keyed to the
    578       parent's PID, not ours, since our parent is the launcher
    579       process. */
    580    { HChar  envvar[100];   // large enough
    581      HChar* wd;
    582      VG_(memset)(envvar, 0, sizeof(envvar));
    583      VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
    584                           (Int)VG_(getppid)());
    585      wd = VG_(getenv)( envvar );
    586      if (wd == NULL)
    587         return;
    588      SizeT need = VG_(strlen)(wd) + 1;
    589      startup_wd = VG_(malloc)("startup_wd", need);
    590      VG_(strcpy)(startup_wd, wd);
    591    }
    592 #  else
    593 #    error Unknown OS
    594 #  endif
    595 }
    596 
    597 /* Return the previously acquired startup_wd or NULL. */
    598 const HChar *VG_(get_startup_wd) ( void )
    599 {
    600    return startup_wd;
    601 }
    602 
    603 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
    604 {
    605    SysRes res;
    606 #  if defined(VGP_arm64_linux)
    607    /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
    608    struct vki_timespec timeout_ts;
    609    if (timeout >= 0) {
    610       timeout_ts.tv_sec = timeout / 1000;
    611       timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
    612    }
    613    res = VG_(do_syscall4)(__NR_ppoll,
    614                           (UWord)fds, nfds,
    615                           (UWord)(timeout >= 0 ? &timeout_ts : NULL),
    616                           (UWord)NULL);
    617 #  elif defined(VGO_linux)
    618    res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
    619 #  elif defined(VGO_darwin)
    620    res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
    621 #  elif defined(VGO_solaris)
    622    struct vki_timespec ts;
    623    struct vki_timespec *tsp;
    624 
    625    if (timeout < 0)
    626       tsp = NULL;
    627    else {
    628       ts.tv_sec = timeout / 1000;
    629       ts.tv_nsec = (timeout % 1000) * 1000000;
    630       tsp = &ts;
    631    }
    632 
    633    res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0);
    634 #  else
    635 #    error "Unknown OS"
    636 #  endif
    637    return res;
    638 }
    639 
    640 
    641 /* Performs the readlink operation and puts the result into 'buf'.
    642    Note, that the string in 'buf' is *not* null-terminated. The function
    643    returns the number of characters put into 'buf' or -1 if an error
    644    occurred. */
    645 SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
    646 {
    647    SysRes res;
    648    /* res = readlink( path, buf, bufsiz ); */
    649 #  if defined(VGP_arm64_linux)
    650    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
    651                                            (UWord)path, (UWord)buf, bufsiz);
    652 #  elif defined(VGO_linux) || defined(VGO_darwin)
    653    res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
    654 #  elif defined(VGO_solaris)
    655    res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
    656                           (UWord)buf, bufsiz);
    657 #  else
    658 #    error "Unknown OS"
    659 #  endif
    660    return sr_isError(res) ? -1 : sr_Res(res);
    661 }
    662 
    663 #if defined(VGO_linux) || defined(VGO_solaris)
    664 Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
    665 {
    666    SysRes res;
    667    /* res = getdents( fd, dirp, count ); */
    668 #  if defined(VGP_amd64_solaris)
    669    /* This silently assumes that dirent64 and dirent on amd64 are same, which
    670       they should always be. */
    671    res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
    672 #  else
    673    res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
    674 #     if defined(VGA_mips64)
    675       /* The MIPS64 getdents64() system call is only present in 3.10+ kernels.
    676          If the getdents64() system call is not available fall back to using
    677          getdents() and modify the result to be compatible with getdents64(). */
    678       if (sr_isError(res) && (sr_Err(res) == VKI_ENOSYS)) {
    679          int r;
    680          res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
    681          r = sr_Res(res);
    682          if (r > 0) {
    683             char *p;
    684             char type;
    685             union dirents {
    686                struct vki_dirent m;
    687                struct vki_dirent64 d;
    688             } *u;
    689             p = (char *)dirp;
    690             do {
    691                u = (union dirents *)p;
    692                /* This should not happen, but just in case... */
    693                if (p + u->m.d_reclen > (char *)dirp + r)
    694                   break;
    695                /* shuffle the dirent */
    696                type = *(p + u->m.d_reclen - 1);
    697                VG_(memmove)(u->d.d_name, u->m.d_name,
    698                             u->m.d_reclen - 2
    699                                - offsetof(struct vki_dirent, d_name) + 1);
    700                u->d.d_type = type;
    701                p += u->m.d_reclen;
    702             } while (p < (char *)dirp + r);
    703          }
    704       }
    705 #     endif
    706 #  endif
    707    return sr_isError(res) ? -1 : sr_Res(res);
    708 }
    709 #endif
    710 
    711 /* Check accessibility of a file.  Returns zero for access granted,
    712    nonzero otherwise. */
    713 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
    714 {
    715 #  if defined(VGO_linux)
    716    /* Very annoyingly, I cannot find any definition for R_OK et al in
    717       the kernel interfaces.  Therefore I reluctantly resort to
    718       hardwiring in these magic numbers that I determined by
    719       experimentation. */
    720 #  define VKI_R_OK 4
    721 #  define VKI_W_OK 2
    722 #  define VKI_X_OK 1
    723 #  endif
    724 
    725    UWord w = (irusr ? VKI_R_OK : 0)
    726              | (iwusr ? VKI_W_OK : 0)
    727              | (ixusr ? VKI_X_OK : 0);
    728 #  if defined(VGP_arm64_linux)
    729    SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
    730 #  elif defined(VGO_linux) || defined(VGO_darwin)
    731    SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
    732 #  elif defined(VGO_solaris)
    733    SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
    734                                  w, 0);
    735 #  else
    736 #    error "Unknown OS"
    737 #  endif
    738    return sr_isError(res) ? 1 : 0;
    739 
    740 #  if defined(VGO_linux)
    741 #  undef VKI_R_OK
    742 #  undef VKI_W_OK
    743 #  undef VKI_X_OK
    744 #  endif
    745 }
    746 
    747 /*
    748    Emulate the normal Unix permissions checking algorithm.
    749 
    750    If owner matches, then use the owner permissions, else
    751    if group matches, then use the group permissions, else
    752    use other permissions.
    753 
    754    Note that we can't deal properly with SUID/SGID.  By default
    755    (allow_setuid == False), we refuse to run them (otherwise the
    756    executable may misbehave if it doesn't have the permissions it
    757    thinks it does).  However, the caller may indicate that setuid
    758    executables are allowed, for example if we are going to exec them
    759    but not trace into them (iow, client sys_execve when
    760    clo_trace_children == False).
    761 
    762    If VKI_EACCES is returned (iow, permission was refused), then
    763    *is_setuid is set to True iff permission was refused because the
    764    executable is setuid.
    765 */
    766 /* returns: 0 = success, non-0 is failure */
    767 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
    768                           const HChar* f, Bool allow_setuid)
    769 {
    770    struct vg_stat st;
    771    SysRes res = VG_(stat)(f, &st);
    772 
    773    if (is_setuid)
    774       *is_setuid = False;
    775 
    776    if (sr_isError(res)) {
    777       return sr_Err(res);
    778    }
    779 
    780    if ( VKI_S_ISDIR (st.mode) ) {
    781       return VKI_EACCES;
    782    }
    783 
    784    if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
    785       if (is_setuid)
    786          *is_setuid = True;
    787       return VKI_EACCES;
    788    }
    789 
    790    res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
    791    if (!sr_isError(res) && !allow_setuid) {
    792       if (is_setuid)
    793          *is_setuid = True;
    794       return VKI_EACCES;
    795    }
    796 
    797    if (VG_(geteuid)() == st.uid) {
    798       if (!(st.mode & VKI_S_IXUSR))
    799          return VKI_EACCES;
    800    } else {
    801       Int grpmatch = 0;
    802 
    803       if (VG_(getegid)() == st.gid)
    804 	 grpmatch = 1;
    805       else {
    806          UInt *groups = NULL;
    807          Int   ngrp;
    808 
    809          /* Find out # groups, allocate large enough array and fetch groups */
    810          ngrp = VG_(getgroups)(0, NULL);
    811          if (ngrp != -1) {
    812             groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
    813             ngrp   = VG_(getgroups)(ngrp, groups);
    814          }
    815 
    816          Int i;
    817          /* ngrp will be -1 if VG_(getgroups) failed. */
    818          for (i = 0; i < ngrp; i++) {
    819 	    if (groups[i] == st.gid) {
    820 	       grpmatch = 1;
    821 	       break;
    822 	    }
    823          }
    824          VG_(free)(groups);
    825       }
    826 
    827       if (grpmatch) {
    828 	 if (!(st.mode & VKI_S_IXGRP)) {
    829             return VKI_EACCES;
    830          }
    831       } else if (!(st.mode & VKI_S_IXOTH)) {
    832          return VKI_EACCES;
    833       }
    834    }
    835 
    836    return 0;
    837 }
    838 
    839 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
    840 {
    841    SysRes res;
    842    // on 32 bits platforms, we receive a 32 bits OffT but
    843    // we must extend it to pass a long long 64 bits.
    844 #  if defined(VGP_x86_linux)
    845    vg_assert(sizeof(OffT) == 4);
    846    res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
    847                           offset, 0); // Little endian long long
    848    return res;
    849 #  elif defined(VGP_arm_linux)
    850    vg_assert(sizeof(OffT) == 4);
    851    res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
    852                           0, offset); // Big endian long long
    853    return res;
    854 #  elif defined(VGP_ppc32_linux)
    855    vg_assert(sizeof(OffT) == 4);
    856    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
    857                           0, // Padding needed on PPC32
    858                           0, offset); // Big endian long long
    859    return res;
    860 #  elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
    861    vg_assert(sizeof(OffT) == 4);
    862    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
    863                           0, offset, 0);
    864    return res;
    865 #  elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
    866    vg_assert(sizeof(OffT) == 4);
    867    res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
    868                           0, 0, offset);
    869    return res;
    870 #  elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
    871       || defined(VGP_ppc64be_linux)  || defined(VGP_ppc64le_linux) \
    872       || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
    873    res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
    874    return res;
    875 #  elif defined(VGP_amd64_darwin)
    876    vg_assert(sizeof(OffT) == 8);
    877    res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
    878    return res;
    879 #  elif defined(VGP_x86_darwin)
    880    vg_assert(sizeof(OffT) == 8);
    881    res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
    882                           offset & 0xffffffff, offset >> 32);
    883    return res;
    884 #  elif defined(VGP_x86_solaris)
    885    vg_assert(sizeof(OffT) == 4);
    886    res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
    887    return res;
    888 #  elif defined(VGP_amd64_solaris)
    889    vg_assert(sizeof(OffT) == 8);
    890    res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
    891    return res;
    892 #  else
    893 #    error "Unknown platform"
    894 #  endif
    895 }
    896 
    897 /* Return the name of a directory for temporary files. */
    898 const HChar *VG_(tmpdir)(void)
    899 {
    900    const HChar *tmpdir;
    901 
    902    tmpdir = VG_(getenv)("TMPDIR");
    903    if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
    904    if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp";    /* fallback */
    905 
    906    return tmpdir;
    907 }
    908 
    909 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
    910 
    911 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
    912 {
    913    return VG_(strlen)(mkstemp_format)
    914       + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
    915       + part_of_name_len - 2           // %s part_of_name
    916       + 8 - 4                          // %08x
    917       + 1;                             // trailing 0
    918 }
    919 
    920 
    921 Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
    922 {
    923    Int    n, tries;
    924    UInt   seed;
    925    SysRes sres;
    926    const HChar *tmpdir;
    927 
    928    vg_assert(part_of_name);
    929    vg_assert(fullname);
    930    n = VG_(strlen)(part_of_name);
    931    vg_assert(n > 0 && n < 100);
    932 
    933    seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
    934 
    935    /* Determine sensible location for temporary files */
    936    tmpdir = VG_(tmpdir)();
    937 
    938    tries = 0;
    939    while (True) {
    940       if (tries++ > 10)
    941          return -1;
    942       VG_(sprintf)( fullname, mkstemp_format,
    943                     tmpdir, part_of_name, VG_(random)( &seed ));
    944       if (0)
    945          VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
    946 
    947       sres = VG_(open)(fullname,
    948                        VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
    949                        VKI_S_IRUSR|VKI_S_IWUSR);
    950       if (sr_isError(sres)) {
    951          VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
    952          continue;
    953       }
    954       /* VG_(safe_fd) doesn't return if it fails. */
    955       return VG_(safe_fd)( sr_Res(sres) );
    956    }
    957    /* NOTREACHED */
    958 }
    959 
    960 
    961 /* ---------------------------------------------------------------------
    962    Socket-related stuff.
    963    ------------------------------------------------------------------ */
    964 
    965 static
    966 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
    967 
    968 static
    969 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
    970 
    971 UInt VG_(htonl) ( UInt x )
    972 {
    973 #  if defined(VG_BIGENDIAN)
    974    return x;
    975 #  else
    976    return
    977       (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
    978       | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
    979 #  endif
    980 }
    981 
    982 UInt VG_(ntohl) ( UInt x )
    983 {
    984 #  if defined(VG_BIGENDIAN)
    985    return x;
    986 #  else
    987    return
    988       (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
    989       | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
    990 #  endif
    991 }
    992 
    993 UShort VG_(htons) ( UShort x )
    994 {
    995 #  if defined(VG_BIGENDIAN)
    996    return x;
    997 #  else
    998    return
    999       (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
   1000 #  endif
   1001 }
   1002 
   1003 UShort VG_(ntohs) ( UShort x )
   1004 {
   1005 #  if defined(VG_BIGENDIAN)
   1006    return x;
   1007 #  else
   1008    return
   1009       (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
   1010 #  endif
   1011 }
   1012 
   1013 
   1014 /* The main function.
   1015 
   1016    Supplied string contains either an ip address "192.168.0.1" or
   1017    an ip address and port pair, "192.168.0.1:1500".  Parse these,
   1018    and return:
   1019      -1 if there is a parse error
   1020      -2 if no parse error, but specified host:port cannot be opened
   1021      the relevant file (socket) descriptor, otherwise.
   1022  is used.
   1023 */
   1024 Int VG_(connect_via_socket)( const HChar* str )
   1025 {
   1026 #  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
   1027    Int sd, res;
   1028    struct vki_sockaddr_in servAddr;
   1029    UInt   ip   = 0;
   1030    UShort port = VG_CLO_DEFAULT_LOGPORT;
   1031    Bool   ok   = parse_inet_addr_and_port(str, &ip, &port);
   1032    if (!ok)
   1033       return -1;
   1034 
   1035    //if (0)
   1036    //   VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
   1037    //               (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
   1038    //               (ip >> 8) & 0xFF, ip & 0xFF,
   1039    //               (UInt)port );
   1040 
   1041    servAddr.sin_family = VKI_AF_INET;
   1042    servAddr.sin_addr.s_addr = VG_(htonl)(ip);
   1043    servAddr.sin_port = VG_(htons)(port);
   1044 
   1045    /* create socket */
   1046    sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
   1047    if (sd < 0) {
   1048       /* this shouldn't happen ... nevertheless */
   1049       return -2;
   1050    }
   1051 
   1052    /* connect to server */
   1053    res = my_connect(sd, &servAddr, sizeof(servAddr));
   1054    if (res < 0) {
   1055       /* connection failed */
   1056       return -2;
   1057    }
   1058 
   1059    return sd;
   1060 
   1061 #  else
   1062 #    error "Unknown OS"
   1063 #  endif
   1064 }
   1065 
   1066 
   1067 /* Let d = one or more digits.  Accept either:
   1068    d.d.d.d  or  d.d.d.d:d
   1069 */
   1070 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
   1071 {
   1072 #  define GET_CH ((*str) ? (*str++) : 0)
   1073    UInt ipa, i, j, c, any;
   1074    ipa = 0;
   1075    for (i = 0; i < 4; i++) {
   1076       j = 0;
   1077       any = 0;
   1078       while (1) {
   1079          c = GET_CH;
   1080          if (c < '0' || c > '9') break;
   1081          j = 10 * j + (int)(c - '0');
   1082          any = 1;
   1083       }
   1084       if (any == 0 || j > 255) goto syntaxerr;
   1085       ipa = (ipa << 8) + j;
   1086       if (i <= 2 && c != '.') goto syntaxerr;
   1087    }
   1088    if (c == 0 || c == ':')
   1089       *ip_addr = ipa;
   1090    if (c == 0) goto ok;
   1091    if (c != ':') goto syntaxerr;
   1092    j = 0;
   1093    any = 0;
   1094    while (1) {
   1095       c = GET_CH;
   1096       if (c < '0' || c > '9') break;
   1097       j = j * 10 + (int)(c - '0');
   1098       any = 1;
   1099       if (j > 65535) goto syntaxerr;
   1100    }
   1101    if (any == 0 || c != 0) goto syntaxerr;
   1102    if (j < 1024) goto syntaxerr;
   1103    *port = (UShort)j;
   1104  ok:
   1105    return 1;
   1106  syntaxerr:
   1107    return 0;
   1108 #  undef GET_CH
   1109 }
   1110 
   1111 // GrP fixme safe_fd?
   1112 Int VG_(socket) ( Int domain, Int type, Int protocol )
   1113 {
   1114 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1115       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1116       || defined(VGP_s390x_linux)
   1117    SysRes res;
   1118    UWord  args[3];
   1119    args[0] = domain;
   1120    args[1] = type;
   1121    args[2] = protocol;
   1122    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
   1123    return sr_isError(res) ? -1 : sr_Res(res);
   1124 
   1125 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1126         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1127         || defined(VGP_arm64_linux)
   1128    SysRes res;
   1129    res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
   1130    return sr_isError(res) ? -1 : sr_Res(res);
   1131 
   1132 #  elif defined(VGO_darwin)
   1133    SysRes res;
   1134    res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
   1135    if (!sr_isError(res)) {
   1136        // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
   1137        Int optval = 1;
   1138        SysRes res2;
   1139        res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
   1140                                VKI_SO_NOSIGPIPE, (UWord)&optval,
   1141                                sizeof(optval));
   1142        // ignore setsockopt() error
   1143    }
   1144    return sr_isError(res) ? -1 : sr_Res(res);
   1145 
   1146 #  elif defined(VGO_solaris)
   1147    /* XXX There doesn't seem to be an easy way to convince the send syscall to
   1148       only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
   1149       SM_KERNEL is set on the socket. Without serious hackery it looks we
   1150       can't set this flag.
   1151 
   1152       Should we wrap the send syscall below into sigprocmask calls to block
   1153       SIGPIPE?
   1154     */
   1155    SysRes res;
   1156    res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol,
   1157                           0 /*devpath*/, VKI_SOV_DEFAULT /*version*/);
   1158    return sr_isError(res) ? -1 : sr_Res(res);
   1159 
   1160 #  else
   1161 #    error "Unknown arch"
   1162 #  endif
   1163 }
   1164 
   1165 
   1166 static
   1167 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
   1168 {
   1169 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1170       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1171       || defined(VGP_s390x_linux)
   1172    SysRes res;
   1173    UWord  args[3];
   1174    args[0] = sockfd;
   1175    args[1] = (UWord)serv_addr;
   1176    args[2] = addrlen;
   1177    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
   1178    return sr_isError(res) ? -1 : sr_Res(res);
   1179 
   1180 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1181         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1182         || defined(VGP_arm64_linux)
   1183    SysRes res;
   1184    res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
   1185    return sr_isError(res) ? -1 : sr_Res(res);
   1186 
   1187 #  elif defined(VGO_darwin)
   1188    SysRes res;
   1189    res = VG_(do_syscall3)(__NR_connect_nocancel,
   1190                           sockfd, (UWord)serv_addr, addrlen);
   1191    return sr_isError(res) ? -1 : sr_Res(res);
   1192 
   1193 #  elif defined(VGO_solaris)
   1194    SysRes res;
   1195    res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen,
   1196                           VKI_SOV_DEFAULT /*version*/);
   1197    return sr_isError(res) ? -1 : sr_Res(res);
   1198 
   1199 #  else
   1200 #    error "Unknown arch"
   1201 #  endif
   1202 }
   1203 
   1204 Int VG_(write_socket)( Int sd, const void *msg, Int count )
   1205 {
   1206    /* This is actually send(). */
   1207 
   1208    /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
   1209       errors on stream oriented sockets when the other end breaks the
   1210       connection. The EPIPE error is still returned.
   1211 
   1212       For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
   1213       SIGPIPE */
   1214 
   1215 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1216       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1217       || defined(VGP_s390x_linux)
   1218    SysRes res;
   1219    UWord  args[4];
   1220    args[0] = sd;
   1221    args[1] = (UWord)msg;
   1222    args[2] = count;
   1223    args[3] = VKI_MSG_NOSIGNAL;
   1224    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
   1225    return sr_isError(res) ? -1 : sr_Res(res);
   1226 
   1227 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1228         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1229         || defined(VGP_arm64_linux)
   1230    SysRes res;
   1231    res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
   1232                                        count, VKI_MSG_NOSIGNAL, 0,0);
   1233    return sr_isError(res) ? -1 : sr_Res(res);
   1234 
   1235 #  elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
   1236    SysRes res;
   1237    res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
   1238    return sr_isError(res) ? -1 : sr_Res(res);
   1239 
   1240 #  elif defined(VGO_solaris)
   1241    SysRes res;
   1242    res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/);
   1243    return sr_isError(res) ? -1 : sr_Res(res);
   1244 
   1245 #  else
   1246 #    error "Unknown platform"
   1247 #  endif
   1248 }
   1249 
   1250 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
   1251 {
   1252 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1253       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1254       || defined(VGP_s390x_linux) \
   1255       || defined(VGP_mips32_linux)
   1256    SysRes res;
   1257    UWord  args[3];
   1258    args[0] = sd;
   1259    args[1] = (UWord)name;
   1260    args[2] = (UWord)namelen;
   1261    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
   1262    return sr_isError(res) ? -1 : sr_Res(res);
   1263 
   1264 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1265         || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
   1266    SysRes res;
   1267    res = VG_(do_syscall3)( __NR_getsockname,
   1268                            (UWord)sd, (UWord)name, (UWord)namelen );
   1269    return sr_isError(res) ? -1 : sr_Res(res);
   1270 
   1271 #  elif defined(VGO_darwin)
   1272    SysRes res;
   1273    res = VG_(do_syscall3)( __NR_getsockname,
   1274                            (UWord)sd, (UWord)name, (UWord)namelen );
   1275    return sr_isError(res) ? -1 : sr_Res(res);
   1276 
   1277 #  elif defined(VGO_solaris)
   1278    SysRes res;
   1279    res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen,
   1280                           VKI_SOV_DEFAULT /*version*/);
   1281    return sr_isError(res) ? -1 : sr_Res(res);
   1282 
   1283 #  else
   1284 #    error "Unknown platform"
   1285 #  endif
   1286 }
   1287 
   1288 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
   1289 {
   1290 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1291       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1292       || defined(VGP_s390x_linux) \
   1293       || defined(VGP_mips32_linux)
   1294    SysRes res;
   1295    UWord  args[3];
   1296    args[0] = sd;
   1297    args[1] = (UWord)name;
   1298    args[2] = (UWord)namelen;
   1299    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
   1300    return sr_isError(res) ? -1 : sr_Res(res);
   1301 
   1302 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1303         || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
   1304    SysRes res;
   1305    res = VG_(do_syscall3)( __NR_getpeername,
   1306                            (UWord)sd, (UWord)name, (UWord)namelen );
   1307    return sr_isError(res) ? -1 : sr_Res(res);
   1308 
   1309 #  elif defined(VGO_darwin)
   1310    SysRes res;
   1311    res = VG_(do_syscall3)( __NR_getpeername,
   1312                            (UWord)sd, (UWord)name, (UWord)namelen );
   1313    return sr_isError(res) ? -1 : sr_Res(res);
   1314 
   1315 #  elif defined(VGO_solaris)
   1316    SysRes res;
   1317    res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen,
   1318                           VKI_SOV_DEFAULT /*version*/);
   1319    return sr_isError(res) ? -1 : sr_Res(res);
   1320 
   1321 #  else
   1322 #    error "Unknown platform"
   1323 #  endif
   1324 }
   1325 
   1326 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
   1327                       Int *optlen)
   1328 {
   1329 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1330       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1331       || defined(VGP_s390x_linux)
   1332    SysRes res;
   1333    UWord  args[5];
   1334    args[0] = sd;
   1335    args[1] = level;
   1336    args[2] = optname;
   1337    args[3] = (UWord)optval;
   1338    args[4] = (UWord)optlen;
   1339    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
   1340    return sr_isError(res) ? -1 : sr_Res(res);
   1341 
   1342 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1343         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1344         || defined(VGP_arm64_linux)
   1345    SysRes res;
   1346    res = VG_(do_syscall5)( __NR_getsockopt,
   1347                            (UWord)sd, (UWord)level, (UWord)optname,
   1348                            (UWord)optval, (UWord)optlen );
   1349    return sr_isError(res) ? -1 : sr_Res(res);
   1350 
   1351 #  elif defined(VGO_darwin)
   1352    SysRes res;
   1353    res = VG_(do_syscall5)( __NR_getsockopt,
   1354                            (UWord)sd, (UWord)level, (UWord)optname,
   1355                            (UWord)optval, (UWord)optlen );
   1356    return sr_isError(res) ? -1 : sr_Res(res);
   1357 
   1358 #  elif defined(VGO_solaris)
   1359    SysRes res;
   1360    res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval,
   1361                           (UWord)optlen, VKI_SOV_DEFAULT /*version*/);
   1362    return sr_isError(res) ? -1 : sr_Res(res);
   1363 
   1364 #  else
   1365 #    error "Unknown platform"
   1366 #  endif
   1367 }
   1368 
   1369 
   1370 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
   1371                       Int optlen)
   1372 {
   1373 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
   1374       || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
   1375       || defined(VGP_s390x_linux)
   1376    SysRes res;
   1377    UWord  args[5];
   1378    args[0] = sd;
   1379    args[1] = level;
   1380    args[2] = optname;
   1381    args[3] = (UWord)optval;
   1382    args[4] = (UWord)optlen;
   1383    res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
   1384    return sr_isError(res) ? -1 : sr_Res(res);
   1385 
   1386 #  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
   1387         || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
   1388         || defined(VGP_arm64_linux)
   1389    SysRes res;
   1390    res = VG_(do_syscall5)( __NR_setsockopt,
   1391                            (UWord)sd, (UWord)level, (UWord)optname,
   1392                            (UWord)optval, (UWord)optlen );
   1393    return sr_isError(res) ? -1 : sr_Res(res);
   1394 
   1395 #  elif defined(VGO_darwin)
   1396    SysRes res;
   1397    res = VG_(do_syscall5)( __NR_setsockopt,
   1398                            (UWord)sd, (UWord)level, (UWord)optname,
   1399                            (UWord)optval, (UWord)optlen );
   1400    return sr_isError(res) ? -1 : sr_Res(res);
   1401 
   1402 #  elif defined(VGO_solaris)
   1403    SysRes res;
   1404    res = VG_(do_syscall6)( __NR_setsockopt,
   1405                            (UWord)sd, (UWord)level, (UWord)optname,
   1406                            (UWord)optval, (UWord)optlen,
   1407                            VKI_SOV_DEFAULT /*version*/ );
   1408    return sr_isError(res) ? -1 : sr_Res(res);
   1409 
   1410 #  else
   1411 #    error "Unknown platform"
   1412 #  endif
   1413 }
   1414 
   1415 
   1416 const HChar *VG_(basename)(const HChar *path)
   1417 {
   1418    static HChar *buf = NULL;
   1419    static SizeT  buf_len = 0;
   1420    const HChar *p, *end;
   1421 
   1422    if (path == NULL  ||
   1423        0 == VG_(strcmp)(path, ""))
   1424    {
   1425       return ".";
   1426    }
   1427 
   1428    p = path + VG_(strlen)(path);
   1429    while (p > path  &&  *p == '/') {
   1430       // skip all trailing '/'
   1431       p--;
   1432    }
   1433 
   1434    if (p == path  &&  *p == '/') return "/"; // all slashes
   1435 
   1436    end = p;
   1437 
   1438    while (p > path  &&  *p != '/') {
   1439       // now skip non '/'
   1440       p--;
   1441    }
   1442 
   1443    if (*p == '/') p++;
   1444 
   1445    SizeT need = end-p+1 + 1;
   1446    if (need > buf_len) {
   1447       buf_len = (buf_len == 0) ? 500 : need;
   1448       buf = VG_(realloc)("basename", buf, buf_len);
   1449    }
   1450    VG_(strncpy)(buf, p, end-p+1);
   1451    buf[end-p+1] = '\0';
   1452 
   1453    return buf;
   1454 }
   1455 
   1456 
   1457 const HChar *VG_(dirname)(const HChar *path)
   1458 {
   1459    static HChar *buf = NULL;
   1460    static SizeT  buf_len = 0;
   1461 
   1462    const HChar *p;
   1463 
   1464    if (path == NULL  ||
   1465        0 == VG_(strcmp)(path, "")  ||
   1466        0 == VG_(strcmp)(path, "/"))
   1467    {
   1468       return ".";
   1469    }
   1470 
   1471    p = path + VG_(strlen)(path);
   1472    while (p > path  &&  *p == '/') {
   1473       // skip all trailing '/'
   1474       p--;
   1475    }
   1476 
   1477    while (p > path  &&  *p != '/') {
   1478       // now skip non '/'
   1479       p--;
   1480    }
   1481 
   1482    if (p == path) {
   1483       if (*p == '/') return "/"; // all slashes
   1484       else return "."; // no slashes
   1485    }
   1486 
   1487    while (p > path  &&  *p == '/') {
   1488       // skip '/' again
   1489       p--;
   1490    }
   1491 
   1492    SizeT need = p-path+1 + 1;
   1493    if (need > buf_len) {
   1494       buf_len = (buf_len == 0) ? 500 : need;
   1495       buf = VG_(realloc)("dirname", buf, buf_len);
   1496    }
   1497    VG_(strncpy)(buf, path, p-path+1);
   1498    buf[p-path+1] = '\0';
   1499 
   1500    return buf;
   1501 }
   1502 
   1503 
   1504 /*--------------------------------------------------------------------*/
   1505 /*--- end                                                          ---*/
   1506 /*--------------------------------------------------------------------*/
   1507