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-2015 Julian Seward
12      jseward@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 */
55Int 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. */
79Bool 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
139SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
140{
141#  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
142   /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
143   SysRes res = VG_(do_syscall4)(__NR_mknodat,
144                                 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
145#  elif defined(VGO_linux) || defined(VGO_darwin)
146   SysRes res = VG_(do_syscall3)(__NR_mknod,
147                                 (UWord)pathname, mode, dev);
148#  elif defined(VGO_solaris)
149   SysRes res = VG_(do_syscall4)(__NR_mknodat,
150                                 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
151#  else
152#    error Unknown OS
153#  endif
154   return res;
155}
156
157SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
158{
159#  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
160   /* ARM64 wants to use __NR_openat rather than __NR_open. */
161   SysRes res = VG_(do_syscall4)(__NR_openat,
162                                 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
163#  elif defined(VGO_linux)
164   SysRes res = VG_(do_syscall3)(__NR_open,
165                                 (UWord)pathname, flags, mode);
166#  elif defined(VGO_darwin)
167   SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
168                                 (UWord)pathname, flags, mode);
169#  elif defined(VGO_solaris)
170   SysRes res = VG_(do_syscall4)(__NR_openat,
171                                 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
172#  else
173#    error Unknown OS
174#  endif
175   return res;
176}
177
178Int 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
188void 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
200Int 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
220Int 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
241Int 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) || defined(VGP_tilegx_linux)
254   SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
255   return sr_isError(res) ? -1 : 0;
256#  elif defined(VGO_linux)
257   SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
258   return sr_isError(res) ? -1 : 0;
259#  elif defined(VGO_darwin)
260   /* __NR_pipe is UX64, so produces a double-word result */
261   SysRes res = VG_(do_syscall0)(__NR_pipe);
262   if (!sr_isError(res)) {
263      fd[0] = (Int)sr_Res(res);
264      fd[1] = (Int)sr_ResHI(res);
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
284Off64T 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
342SysRes 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) || defined(VGP_tilegx_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
395Int 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
443Long 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
450SysRes 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
462Bool 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
470SysRes 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
481SysRes VG_(dup2) ( Int oldfd, Int newfd )
482{
483#  if defined(VGO_linux) || defined(VGO_darwin)
484   return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
485#  elif defined(VGO_solaris)
486   return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
487#  else
488#    error Unknown OS
489#  endif
490}
491
492/* Returns -1 on error. */
493Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
494{
495#  if defined(VGO_linux) || defined(VGO_solaris)
496   SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
497#  elif defined(VGO_darwin)
498   SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
499#  else
500#    error "Unknown OS"
501#  endif
502   return sr_isError(res) ? -1 : sr_Res(res);
503}
504
505Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
506{
507#  if defined(VGP_tilegx_linux)
508   SysRes res = VG_(do_syscall3)(__NR_renameat, VKI_AT_FDCWD,
509                                 (UWord)old_name, (UWord)new_name);
510#  elif defined(VGO_linux) || defined(VGO_darwin)
511   SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
512#  elif defined(VGO_solaris)
513   SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
514                                 VKI_AT_FDCWD, (UWord)new_name);
515#  else
516#    error "Unknown OS"
517#  endif
518   return sr_isError(res) ? (-1) : 0;
519}
520
521Int VG_(unlink) ( const HChar* file_name )
522{
523#  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
524   SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
525                                                (UWord)file_name);
526#  elif defined(VGO_linux) || defined(VGO_darwin)
527   SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
528#  elif defined(VGO_solaris)
529   SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
530                                 (UWord)file_name, 0);
531#  else
532#    error "Unknown OS"
533#  endif
534   return sr_isError(res) ? (-1) : 0;
535}
536
537/* The working directory at startup.
538   All that is really needed is to note the cwd at process startup.
539   Hence VG_(record_startup_wd) notes it (in a platform dependent way)
540   and VG_(get_startup_wd) produces the noted value. */
541static HChar *startup_wd;
542static Bool   startup_wd_acquired = False;
543
544/* Record the process' working directory at startup.  Is intended to
545   be called exactly once, at startup, before the working directory
546   changes.  Return True for success, False for failure, so that the
547   caller can bomb out suitably without creating module cycles if
548   there is a problem. */
549Bool VG_(record_startup_wd) ( void )
550{
551   vg_assert(!startup_wd_acquired);
552#  if defined(VGO_linux) || defined(VGO_solaris)
553   /* Simple: just ask the kernel */
554   SysRes res;
555   SizeT szB = 0;
556   do {
557      szB += 500;
558      startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
559      VG_(memset)(startup_wd, 0, szB);
560      res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
561   } while (sr_isError(res));
562
563   vg_assert(startup_wd[szB-1] == 0);
564   startup_wd_acquired = True;
565   return True;
566
567#  elif defined(VGO_darwin)
568   /* We can't ask the kernel, so instead rely on launcher-*.c to
569      tell us the startup path.  Note the env var is keyed to the
570      parent's PID, not ours, since our parent is the launcher
571      process. */
572   { HChar  envvar[100];   // large enough
573     HChar* wd;
574     VG_(memset)(envvar, 0, sizeof(envvar));
575     VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
576                          (Int)VG_(getppid)());
577     wd = VG_(getenv)( envvar );
578     if (wd == NULL)
579        return False;
580     SizeT need = VG_(strlen)(wd) + 1;
581     startup_wd = VG_(malloc)("startup_wd", need);
582     VG_(strcpy)(startup_wd, wd);
583     startup_wd_acquired = True;
584     return True;
585   }
586#  else
587#    error Unknown OS
588#  endif
589}
590
591/* Return the previously acquired startup_wd. */
592const HChar *VG_(get_startup_wd) ( void )
593{
594   vg_assert(startup_wd_acquired);
595
596   return startup_wd;
597}
598
599SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
600{
601   SysRes res;
602#  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
603   /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
604   struct vki_timespec timeout_ts;
605   if (timeout >= 0) {
606      timeout_ts.tv_sec = timeout / 1000;
607      timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
608   }
609   res = VG_(do_syscall4)(__NR_ppoll,
610                          (UWord)fds, nfds,
611                          (UWord)(timeout >= 0 ? &timeout_ts : NULL),
612                          (UWord)NULL);
613#  elif defined(VGO_linux)
614   res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
615#  elif defined(VGO_darwin)
616   res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
617#  elif defined(VGO_solaris)
618   struct vki_timespec ts;
619   struct vki_timespec *tsp;
620
621   if (timeout < 0)
622      tsp = NULL;
623   else {
624      ts.tv_sec = timeout / 1000;
625      ts.tv_nsec = (timeout % 1000) * 1000000;
626      tsp = &ts;
627   }
628
629   res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0);
630#  else
631#    error "Unknown OS"
632#  endif
633   return res;
634}
635
636
637/* Performs the readlink operation and puts the result into 'buf'.
638   Note, that the string in 'buf' is *not* null-terminated. The function
639   returns the number of characters put into 'buf' or -1 if an error
640   occurred. */
641SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
642{
643   SysRes res;
644   /* res = readlink( path, buf, bufsiz ); */
645#  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
646   res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
647                                           (UWord)path, (UWord)buf, bufsiz);
648#  elif defined(VGO_linux) || defined(VGO_darwin)
649   res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
650#  elif defined(VGO_solaris)
651   res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
652                          (UWord)buf, bufsiz);
653#  else
654#    error "Unknown OS"
655#  endif
656   return sr_isError(res) ? -1 : sr_Res(res);
657}
658
659#if defined(VGO_linux) || defined(VGO_solaris)
660Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
661{
662   SysRes res;
663   /* res = getdents( fd, dirp, count ); */
664#  if defined(VGP_amd64_solaris)
665   /* This silently assumes that dirent64 and dirent on amd64 are same, which
666      they should always be. */
667   res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
668#  else
669   res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
670#  endif
671   return sr_isError(res) ? -1 : sr_Res(res);
672}
673#endif
674
675/* Check accessibility of a file.  Returns zero for access granted,
676   nonzero otherwise. */
677Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
678{
679#  if defined(VGO_linux)
680   /* Very annoyingly, I cannot find any definition for R_OK et al in
681      the kernel interfaces.  Therefore I reluctantly resort to
682      hardwiring in these magic numbers that I determined by
683      experimentation. */
684#  define VKI_R_OK 4
685#  define VKI_W_OK 2
686#  define VKI_X_OK 1
687#  endif
688
689   UWord w = (irusr ? VKI_R_OK : 0)
690             | (iwusr ? VKI_W_OK : 0)
691             | (ixusr ? VKI_X_OK : 0);
692#  if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
693   SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
694#  elif defined(VGO_linux) || defined(VGO_darwin)
695   SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
696#  elif defined(VGO_solaris)
697   SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
698                                 w, 0);
699#  else
700#    error "Unknown OS"
701#  endif
702   return sr_isError(res) ? 1 : 0;
703
704#  if defined(VGO_linux)
705#  undef VKI_R_OK
706#  undef VKI_W_OK
707#  undef VKI_X_OK
708#  endif
709}
710
711/*
712   Emulate the normal Unix permissions checking algorithm.
713
714   If owner matches, then use the owner permissions, else
715   if group matches, then use the group permissions, else
716   use other permissions.
717
718   Note that we can't deal properly with SUID/SGID.  By default
719   (allow_setuid == False), we refuse to run them (otherwise the
720   executable may misbehave if it doesn't have the permissions it
721   thinks it does).  However, the caller may indicate that setuid
722   executables are allowed, for example if we are going to exec them
723   but not trace into them (iow, client sys_execve when
724   clo_trace_children == False).
725
726   If VKI_EACCES is returned (iow, permission was refused), then
727   *is_setuid is set to True iff permission was refused because the
728   executable is setuid.
729*/
730/* returns: 0 = success, non-0 is failure */
731Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
732                          const HChar* f, Bool allow_setuid)
733{
734   struct vg_stat st;
735   SysRes res = VG_(stat)(f, &st);
736
737   if (is_setuid)
738      *is_setuid = False;
739
740   if (sr_isError(res)) {
741      return sr_Err(res);
742   }
743
744   if ( VKI_S_ISDIR (st.mode) ) {
745      return VKI_EACCES;
746   }
747
748   if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
749      if (is_setuid)
750         *is_setuid = True;
751      return VKI_EACCES;
752   }
753
754   res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
755   if (!sr_isError(res) && !allow_setuid) {
756      if (is_setuid)
757         *is_setuid = True;
758      return VKI_EACCES;
759   }
760
761   if (VG_(geteuid)() == st.uid) {
762      if (!(st.mode & VKI_S_IXUSR))
763         return VKI_EACCES;
764   } else {
765      Int grpmatch = 0;
766
767      if (VG_(getegid)() == st.gid)
768	 grpmatch = 1;
769      else {
770         UInt *groups = NULL;
771         Int   ngrp;
772
773         /* Find out # groups, allocate large enough array and fetch groups */
774         ngrp = VG_(getgroups)(0, NULL);
775         if (ngrp != -1) {
776            groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
777            ngrp   = VG_(getgroups)(ngrp, groups);
778         }
779
780         Int i;
781         /* ngrp will be -1 if VG_(getgroups) failed. */
782         for (i = 0; i < ngrp; i++) {
783	    if (groups[i] == st.gid) {
784	       grpmatch = 1;
785	       break;
786	    }
787         }
788         VG_(free)(groups);
789      }
790
791      if (grpmatch) {
792	 if (!(st.mode & VKI_S_IXGRP)) {
793            return VKI_EACCES;
794         }
795      } else if (!(st.mode & VKI_S_IXOTH)) {
796         return VKI_EACCES;
797      }
798   }
799
800   return 0;
801}
802
803SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
804{
805   SysRes res;
806   // on 32 bits platforms, we receive a 32 bits OffT but
807   // we must extend it to pass a long long 64 bits.
808#  if defined(VGP_x86_linux)
809   vg_assert(sizeof(OffT) == 4);
810   res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
811                          offset, 0); // Little endian long long
812   return res;
813#  elif defined(VGP_arm_linux)
814   vg_assert(sizeof(OffT) == 4);
815   res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
816                          0, offset); // Big endian long long
817   return res;
818#  elif defined(VGP_ppc32_linux)
819   vg_assert(sizeof(OffT) == 4);
820   res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
821                          0, // Padding needed on PPC32
822                          0, offset); // Big endian long long
823   return res;
824#  elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
825   vg_assert(sizeof(OffT) == 4);
826   res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
827                          0, offset, 0);
828   return res;
829#  elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
830   vg_assert(sizeof(OffT) == 4);
831   res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
832                          0, 0, offset);
833   return res;
834#  elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
835      || defined(VGP_ppc64be_linux)  || defined(VGP_ppc64le_linux) \
836      || defined(VGP_mips64_linux) \
837  || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
838   res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
839   return res;
840#  elif defined(VGP_amd64_darwin)
841   vg_assert(sizeof(OffT) == 8);
842   res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
843   return res;
844#  elif defined(VGP_x86_darwin)
845   vg_assert(sizeof(OffT) == 8);
846   res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
847                          offset & 0xffffffff, offset >> 32);
848   return res;
849#  elif defined(VGP_x86_solaris)
850   vg_assert(sizeof(OffT) == 4);
851   res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
852   return res;
853#  elif defined(VGP_amd64_solaris)
854   vg_assert(sizeof(OffT) == 8);
855   res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
856   return res;
857#  else
858#    error "Unknown platform"
859#  endif
860}
861
862/* Return the name of a directory for temporary files. */
863const HChar *VG_(tmpdir)(void)
864{
865   const HChar *tmpdir;
866
867   tmpdir = VG_(getenv)("TMPDIR");
868   if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
869   if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp";    /* fallback */
870
871   return tmpdir;
872}
873
874static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
875
876SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
877{
878   return VG_(strlen)(mkstemp_format)
879      + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
880      + part_of_name_len - 2           // %s part_of_name
881      + 8 - 4                          // %08x
882      + 1;                             // trailing 0
883}
884
885
886Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
887{
888   Int    n, tries;
889   UInt   seed;
890   SysRes sres;
891   const HChar *tmpdir;
892
893   vg_assert(part_of_name);
894   vg_assert(fullname);
895   n = VG_(strlen)(part_of_name);
896   vg_assert(n > 0 && n < 100);
897
898   seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
899
900   /* Determine sensible location for temporary files */
901   tmpdir = VG_(tmpdir)();
902
903   tries = 0;
904   while (True) {
905      if (tries++ > 10)
906         return -1;
907      VG_(sprintf)( fullname, mkstemp_format,
908                    tmpdir, part_of_name, VG_(random)( &seed ));
909      if (0)
910         VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
911
912      sres = VG_(open)(fullname,
913                       VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
914                       VKI_S_IRUSR|VKI_S_IWUSR);
915      if (sr_isError(sres)) {
916         VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
917         continue;
918      }
919      /* VG_(safe_fd) doesn't return if it fails. */
920      return VG_(safe_fd)( sr_Res(sres) );
921   }
922   /* NOTREACHED */
923}
924
925
926/* ---------------------------------------------------------------------
927   Socket-related stuff.
928   ------------------------------------------------------------------ */
929
930static
931Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
932
933static
934Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
935
936UInt VG_(htonl) ( UInt x )
937{
938#  if defined(VG_BIGENDIAN)
939   return x;
940#  else
941   return
942      (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
943      | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
944#  endif
945}
946
947UInt VG_(ntohl) ( UInt x )
948{
949#  if defined(VG_BIGENDIAN)
950   return x;
951#  else
952   return
953      (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
954      | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
955#  endif
956}
957
958UShort VG_(htons) ( UShort x )
959{
960#  if defined(VG_BIGENDIAN)
961   return x;
962#  else
963   return
964      (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
965#  endif
966}
967
968UShort VG_(ntohs) ( UShort x )
969{
970#  if defined(VG_BIGENDIAN)
971   return x;
972#  else
973   return
974      (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
975#  endif
976}
977
978
979/* The main function.
980
981   Supplied string contains either an ip address "192.168.0.1" or
982   an ip address and port pair, "192.168.0.1:1500".  Parse these,
983   and return:
984     -1 if there is a parse error
985     -2 if no parse error, but specified host:port cannot be opened
986     the relevant file (socket) descriptor, otherwise.
987 is used.
988*/
989Int VG_(connect_via_socket)( const HChar* str )
990{
991#  if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
992   Int sd, res;
993   struct vki_sockaddr_in servAddr;
994   UInt   ip   = 0;
995   UShort port = VG_CLO_DEFAULT_LOGPORT;
996   Bool   ok   = parse_inet_addr_and_port(str, &ip, &port);
997   if (!ok)
998      return -1;
999
1000   //if (0)
1001   //   VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1002   //               (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1003   //               (ip >> 8) & 0xFF, ip & 0xFF,
1004   //               (UInt)port );
1005
1006   servAddr.sin_family = VKI_AF_INET;
1007   servAddr.sin_addr.s_addr = VG_(htonl)(ip);
1008   servAddr.sin_port = VG_(htons)(port);
1009
1010   /* create socket */
1011   sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1012   if (sd < 0) {
1013      /* this shouldn't happen ... nevertheless */
1014      return -2;
1015   }
1016
1017   /* connect to server */
1018   res = my_connect(sd, &servAddr, sizeof(servAddr));
1019   if (res < 0) {
1020      /* connection failed */
1021      return -2;
1022   }
1023
1024   return sd;
1025
1026#  else
1027#    error "Unknown OS"
1028#  endif
1029}
1030
1031
1032/* Let d = one or more digits.  Accept either:
1033   d.d.d.d  or  d.d.d.d:d
1034*/
1035static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
1036{
1037#  define GET_CH ((*str) ? (*str++) : 0)
1038   UInt ipa, i, j, c, any;
1039   ipa = 0;
1040   for (i = 0; i < 4; i++) {
1041      j = 0;
1042      any = 0;
1043      while (1) {
1044         c = GET_CH;
1045         if (c < '0' || c > '9') break;
1046         j = 10 * j + (int)(c - '0');
1047         any = 1;
1048      }
1049      if (any == 0 || j > 255) goto syntaxerr;
1050      ipa = (ipa << 8) + j;
1051      if (i <= 2 && c != '.') goto syntaxerr;
1052   }
1053   if (c == 0 || c == ':')
1054      *ip_addr = ipa;
1055   if (c == 0) goto ok;
1056   if (c != ':') goto syntaxerr;
1057   j = 0;
1058   any = 0;
1059   while (1) {
1060      c = GET_CH;
1061      if (c < '0' || c > '9') break;
1062      j = j * 10 + (int)(c - '0');
1063      any = 1;
1064      if (j > 65535) goto syntaxerr;
1065   }
1066   if (any == 0 || c != 0) goto syntaxerr;
1067   if (j < 1024) goto syntaxerr;
1068   *port = (UShort)j;
1069 ok:
1070   return 1;
1071 syntaxerr:
1072   return 0;
1073#  undef GET_CH
1074}
1075
1076// GrP fixme safe_fd?
1077Int VG_(socket) ( Int domain, Int type, Int protocol )
1078{
1079#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1080      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1081      || defined(VGP_s390x_linux)
1082   SysRes res;
1083   UWord  args[3];
1084   args[0] = domain;
1085   args[1] = type;
1086   args[2] = protocol;
1087   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
1088   return sr_isError(res) ? -1 : sr_Res(res);
1089
1090#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1091        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1092        || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1093   SysRes res;
1094   res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
1095   return sr_isError(res) ? -1 : sr_Res(res);
1096
1097#  elif defined(VGO_darwin)
1098   SysRes res;
1099   res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
1100   if (!sr_isError(res)) {
1101       // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
1102       Int optval = 1;
1103       SysRes res2;
1104       res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
1105                               VKI_SO_NOSIGPIPE, (UWord)&optval,
1106                               sizeof(optval));
1107       // ignore setsockopt() error
1108   }
1109   return sr_isError(res) ? -1 : sr_Res(res);
1110
1111#  elif defined(VGO_solaris)
1112   /* XXX There doesn't seem to be an easy way to convince the send syscall to
1113      only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
1114      SM_KERNEL is set on the socket. Without serious hackery it looks we
1115      can't set this flag.
1116
1117      Should we wrap the send syscall below into sigprocmask calls to block
1118      SIGPIPE?
1119    */
1120   SysRes res;
1121   res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol,
1122                          0 /*devpath*/, VKI_SOV_DEFAULT /*version*/);
1123   return sr_isError(res) ? -1 : sr_Res(res);
1124
1125#  else
1126#    error "Unknown arch"
1127#  endif
1128}
1129
1130
1131static
1132Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
1133{
1134#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1135      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1136      || defined(VGP_s390x_linux)
1137   SysRes res;
1138   UWord  args[3];
1139   args[0] = sockfd;
1140   args[1] = (UWord)serv_addr;
1141   args[2] = addrlen;
1142   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
1143   return sr_isError(res) ? -1 : sr_Res(res);
1144
1145#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1146        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1147        || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1148   SysRes res;
1149   res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
1150   return sr_isError(res) ? -1 : sr_Res(res);
1151
1152#  elif defined(VGO_darwin)
1153   SysRes res;
1154   res = VG_(do_syscall3)(__NR_connect_nocancel,
1155                          sockfd, (UWord)serv_addr, addrlen);
1156   return sr_isError(res) ? -1 : sr_Res(res);
1157
1158#  elif defined(VGO_solaris)
1159   SysRes res;
1160   res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen,
1161                          VKI_SOV_DEFAULT /*version*/);
1162   return sr_isError(res) ? -1 : sr_Res(res);
1163
1164#  else
1165#    error "Unknown arch"
1166#  endif
1167}
1168
1169Int VG_(write_socket)( Int sd, const void *msg, Int count )
1170{
1171   /* This is actually send(). */
1172
1173   /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
1174      errors on stream oriented sockets when the other end breaks the
1175      connection. The EPIPE error is still returned.
1176
1177      For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1178      SIGPIPE */
1179
1180#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1181      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1182      || defined(VGP_s390x_linux)
1183   SysRes res;
1184   UWord  args[4];
1185   args[0] = sd;
1186   args[1] = (UWord)msg;
1187   args[2] = count;
1188   args[3] = VKI_MSG_NOSIGNAL;
1189   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
1190   return sr_isError(res) ? -1 : sr_Res(res);
1191
1192#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1193        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1194        || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1195   SysRes res;
1196   res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
1197                                       count, VKI_MSG_NOSIGNAL, 0,0);
1198   return sr_isError(res) ? -1 : sr_Res(res);
1199
1200#  elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1201   SysRes res;
1202   res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
1203   return sr_isError(res) ? -1 : sr_Res(res);
1204
1205#  elif defined(VGO_solaris)
1206   SysRes res;
1207   res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/);
1208   return sr_isError(res) ? -1 : sr_Res(res);
1209
1210#  else
1211#    error "Unknown platform"
1212#  endif
1213}
1214
1215Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1216{
1217#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1218      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1219      || defined(VGP_s390x_linux) \
1220      || defined(VGP_mips32_linux)
1221   SysRes res;
1222   UWord  args[3];
1223   args[0] = sd;
1224   args[1] = (UWord)name;
1225   args[2] = (UWord)namelen;
1226   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
1227   return sr_isError(res) ? -1 : sr_Res(res);
1228
1229#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1230        || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1231        || defined(VGP_tilegx_linux)
1232   SysRes res;
1233   res = VG_(do_syscall3)( __NR_getsockname,
1234                           (UWord)sd, (UWord)name, (UWord)namelen );
1235   return sr_isError(res) ? -1 : sr_Res(res);
1236
1237#  elif defined(VGO_darwin)
1238   SysRes res;
1239   res = VG_(do_syscall3)( __NR_getsockname,
1240                           (UWord)sd, (UWord)name, (UWord)namelen );
1241   return sr_isError(res) ? -1 : sr_Res(res);
1242
1243#  elif defined(VGO_solaris)
1244   SysRes res;
1245   res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen,
1246                          VKI_SOV_DEFAULT /*version*/);
1247   return sr_isError(res) ? -1 : sr_Res(res);
1248
1249#  else
1250#    error "Unknown platform"
1251#  endif
1252}
1253
1254Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1255{
1256#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1257      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1258      || defined(VGP_s390x_linux) \
1259      || defined(VGP_mips32_linux)
1260   SysRes res;
1261   UWord  args[3];
1262   args[0] = sd;
1263   args[1] = (UWord)name;
1264   args[2] = (UWord)namelen;
1265   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
1266   return sr_isError(res) ? -1 : sr_Res(res);
1267
1268#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1269        || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1270        || defined(VGP_tilegx_linux)
1271   SysRes res;
1272   res = VG_(do_syscall3)( __NR_getpeername,
1273                           (UWord)sd, (UWord)name, (UWord)namelen );
1274   return sr_isError(res) ? -1 : sr_Res(res);
1275
1276#  elif defined(VGO_darwin)
1277   SysRes res;
1278   res = VG_(do_syscall3)( __NR_getpeername,
1279                           (UWord)sd, (UWord)name, (UWord)namelen );
1280   return sr_isError(res) ? -1 : sr_Res(res);
1281
1282#  elif defined(VGO_solaris)
1283   SysRes res;
1284   res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen,
1285                          VKI_SOV_DEFAULT /*version*/);
1286   return sr_isError(res) ? -1 : sr_Res(res);
1287
1288#  else
1289#    error "Unknown platform"
1290#  endif
1291}
1292
1293Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1294                      Int *optlen)
1295{
1296#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1297      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1298      || defined(VGP_s390x_linux)
1299   SysRes res;
1300   UWord  args[5];
1301   args[0] = sd;
1302   args[1] = level;
1303   args[2] = optname;
1304   args[3] = (UWord)optval;
1305   args[4] = (UWord)optlen;
1306   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
1307   return sr_isError(res) ? -1 : sr_Res(res);
1308
1309#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1310        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1311        || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1312   SysRes res;
1313   res = VG_(do_syscall5)( __NR_getsockopt,
1314                           (UWord)sd, (UWord)level, (UWord)optname,
1315                           (UWord)optval, (UWord)optlen );
1316   return sr_isError(res) ? -1 : sr_Res(res);
1317
1318#  elif defined(VGO_darwin)
1319   SysRes res;
1320   res = VG_(do_syscall5)( __NR_getsockopt,
1321                           (UWord)sd, (UWord)level, (UWord)optname,
1322                           (UWord)optval, (UWord)optlen );
1323   return sr_isError(res) ? -1 : sr_Res(res);
1324
1325#  elif defined(VGO_solaris)
1326   SysRes res;
1327   res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval,
1328                          (UWord)optlen, VKI_SOV_DEFAULT /*version*/);
1329   return sr_isError(res) ? -1 : sr_Res(res);
1330
1331#  else
1332#    error "Unknown platform"
1333#  endif
1334}
1335
1336
1337Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
1338                      Int optlen)
1339{
1340#  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1341      || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1342      || defined(VGP_s390x_linux)
1343   SysRes res;
1344   UWord  args[5];
1345   args[0] = sd;
1346   args[1] = level;
1347   args[2] = optname;
1348   args[3] = (UWord)optval;
1349   args[4] = (UWord)optlen;
1350   res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
1351   return sr_isError(res) ? -1 : sr_Res(res);
1352
1353#  elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1354        || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1355        || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
1356   SysRes res;
1357   res = VG_(do_syscall5)( __NR_setsockopt,
1358                           (UWord)sd, (UWord)level, (UWord)optname,
1359                           (UWord)optval, (UWord)optlen );
1360   return sr_isError(res) ? -1 : sr_Res(res);
1361
1362#  elif defined(VGO_darwin)
1363   SysRes res;
1364   res = VG_(do_syscall5)( __NR_setsockopt,
1365                           (UWord)sd, (UWord)level, (UWord)optname,
1366                           (UWord)optval, (UWord)optlen );
1367   return sr_isError(res) ? -1 : sr_Res(res);
1368
1369#  elif defined(VGO_solaris)
1370   SysRes res;
1371   res = VG_(do_syscall6)( __NR_setsockopt,
1372                           (UWord)sd, (UWord)level, (UWord)optname,
1373                           (UWord)optval, (UWord)optlen,
1374                           VKI_SOV_DEFAULT /*version*/ );
1375   return sr_isError(res) ? -1 : sr_Res(res);
1376
1377#  else
1378#    error "Unknown platform"
1379#  endif
1380}
1381
1382
1383const HChar *VG_(basename)(const HChar *path)
1384{
1385   static HChar *buf = NULL;
1386   static SizeT  buf_len = 0;
1387   const HChar *p, *end;
1388
1389   if (path == NULL  ||
1390       0 == VG_(strcmp)(path, ""))
1391   {
1392      return ".";
1393   }
1394
1395   p = path + VG_(strlen)(path);
1396   while (p > path  &&  *p == '/') {
1397      // skip all trailing '/'
1398      p--;
1399   }
1400
1401   if (p == path  &&  *p == '/') return "/"; // all slashes
1402
1403   end = p;
1404
1405   while (p > path  &&  *p != '/') {
1406      // now skip non '/'
1407      p--;
1408   }
1409
1410   if (*p == '/') p++;
1411
1412   SizeT need = end-p+1 + 1;
1413   if (need > buf_len) {
1414      buf_len = (buf_len == 0) ? 500 : need;
1415      buf = VG_(realloc)("basename", buf, buf_len);
1416   }
1417   VG_(strncpy)(buf, p, end-p+1);
1418   buf[end-p+1] = '\0';
1419
1420   return buf;
1421}
1422
1423
1424const HChar *VG_(dirname)(const HChar *path)
1425{
1426   static HChar *buf = NULL;
1427   static SizeT  buf_len = 0;
1428
1429   const HChar *p;
1430
1431   if (path == NULL  ||
1432       0 == VG_(strcmp)(path, "")  ||
1433       0 == VG_(strcmp)(path, "/"))
1434   {
1435      return ".";
1436   }
1437
1438   p = path + VG_(strlen)(path);
1439   while (p > path  &&  *p == '/') {
1440      // skip all trailing '/'
1441      p--;
1442   }
1443
1444   while (p > path  &&  *p != '/') {
1445      // now skip non '/'
1446      p--;
1447   }
1448
1449   if (p == path) {
1450      if (*p == '/') return "/"; // all slashes
1451      else return "."; // no slashes
1452   }
1453
1454   while (p > path  &&  *p == '/') {
1455      // skip '/' again
1456      p--;
1457   }
1458
1459   SizeT need = p-path+1 + 1;
1460   if (need > buf_len) {
1461      buf_len = (buf_len == 0) ? 500 : need;
1462      buf = VG_(realloc)("dirname", buf, buf_len);
1463   }
1464   VG_(strncpy)(buf, path, p-path+1);
1465   buf[p-path+1] = '\0';
1466
1467   return buf;
1468}
1469
1470
1471/*--------------------------------------------------------------------*/
1472/*--- end                                                          ---*/
1473/*--------------------------------------------------------------------*/
1474