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