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