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