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 */
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) || 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 
VG_(open)157 SysRes 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 
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) || 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 
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) || 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 
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(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. */
VG_(fcntl)493 Int 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 
VG_(rename)505 Int 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 
VG_(unlink)521 Int 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. */
541 static HChar *startup_wd;
542 static 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. */
VG_(record_startup_wd)549 Bool 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. */
VG_(get_startup_wd)592 const HChar *VG_(get_startup_wd) ( void )
593 {
594    vg_assert(startup_wd_acquired);
595 
596    return startup_wd;
597 }
598 
VG_(poll)599 SysRes 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. */
VG_(readlink)641 SSizeT 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)
VG_(getdents64)660 Int 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. */
VG_(access)677 Int 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 */
VG_(check_executable)731 Int 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 
VG_(pread)803 SysRes 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. */
VG_(tmpdir)863 const 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 
874 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
875 
VG_(mkstemp_fullname_bufsz)876 SizeT 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 
VG_(mkstemp)886 Int 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 
930 static
931 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
932 
933 static
934 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
935 
VG_(htonl)936 UInt 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 
VG_(ntohl)947 UInt 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 
VG_(htons)958 UShort 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 
VG_(ntohs)968 UShort 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 */
VG_(connect_via_socket)989 Int 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 */
parse_inet_addr_and_port(const HChar * str,UInt * ip_addr,UShort * port)1035 static 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?
VG_(socket)1077 Int 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 
1131 static
my_connect(Int sockfd,struct vki_sockaddr_in * serv_addr,Int addrlen)1132 Int 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 
VG_(write_socket)1169 Int 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 
VG_(getsockname)1215 Int 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 
VG_(getpeername)1254 Int 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 
VG_(getsockopt)1293 Int 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 
VG_(setsockopt)1337 Int 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 
VG_(basename)1383 const 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 
VG_(dirname)1424 const 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