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 */
55Int VG_(safe_fd)(Int oldfd)
56{
57   Int newfd;
58
59   vg_assert(VG_(fd_hard_limit) != -1);
60
61   newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
62   if (newfd != -1)
63      VG_(close)(oldfd);
64
65   /* Set the close-on-exec flag for this fd. */
66   VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
67
68   vg_assert(newfd >= VG_(fd_hard_limit));
69   return newfd;
70}
71
72/* Given a file descriptor, attempt to deduce its filename.  To do
73   this, we use /proc/self/fd/<FD>.  If this doesn't point to a file,
74   or if it doesn't exist, we return False.
75   Upon successful completion *result contains the filename. The
76   filename will be overwritten with the next invocation so callers
77   need to copy the filename if needed. *result is NULL if the filename
78   cannot be deduced. */
79Bool VG_(resolve_filename) ( Int fd, const HChar** result )
80{
81#  if defined(VGO_linux)
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
133SysRes 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
148SysRes 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
166Int 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
176void 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
188Int 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
208Int 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
229Int 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
260Off64T 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
310SysRes 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
347Int 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
381Long 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
388SysRes 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
400Bool 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
408SysRes VG_(dup) ( Int oldfd )
409{
410   return VG_(do_syscall1)(__NR_dup, oldfd);
411}
412
413SysRes 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. */
423Int 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
435Int 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
446Int 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. */
461static HChar *startup_wd;
462static 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. */
469Bool 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. */
513const HChar *VG_(get_startup_wd) ( void )
514{
515   vg_assert(startup_wd_acquired);
516
517   return startup_wd;
518}
519
520SysRes 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. */
549SSizeT 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)
563Int 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. */
574Int 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 */
623Int 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
695SysRes 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. */
747const 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
758static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
759
760SizeT 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
770Int 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
814static
815Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
816
817static
818Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
819
820UInt 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
831UInt 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
842UShort 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
852UShort 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*/
873Int 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*/
919static 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?
961Int 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
1001static
1002Int 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
1033Int 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
1074Int 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
1107Int 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
1140Int 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
1178Int 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
1216const 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
1257const 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