1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- File- and socket-related libc stuff. m_libcfile.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" // VG_(sprintf) 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid) 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" // VG_(fd_hard_limit) 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IMPORTANT: on Darwin it is essential to use the _nocancel versions 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of syscalls rather than the vanilla version, if a _nocancel version 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is available. See docs/internals/Darwin-notes.txt for the reason 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why. */ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown File stuff 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline Bool fd_exists(Int fd) 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat st; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(fstat)(fd, &st) == 0; 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Move an fd into the Valgrind-safe range */ 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(safe_fd)(Int oldfd) 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int newfd; 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(fd_hard_limit) != -1); 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit)); 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (newfd != -1) 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(close)(oldfd); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Set the close-on-exec flag for this fd. */ 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC); 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(newfd >= VG_(fd_hard_limit)); 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return newfd; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Given a file descriptor, attempt to deduce its filename. To do 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this, we use /proc/self/fd/<FD>. If this doesn't point to a file, 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or if it doesn't exist, we return False. */ 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf ) 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar tmp[64]; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(tmp, "/proc/self/fd/%d", fd); 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(buf, 0, n_buf); 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/') 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar tmp[VKI_MAXPATHLEN+1]; 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) { 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n_buf > 0) { 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)( buf, tmp, n_buf < sizeof(tmp) ? n_buf : sizeof(tmp) ); 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[n_buf-1] = 0; 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tmp[0] == '/') return True; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovSysRes VG_(mknod) ( const Char* pathname, Int mode, UWord dev ) 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) || defined(VGO_darwin) 110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes res = VG_(do_syscall3)(__NR_mknod, 111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (UWord)pathname, mode, dev); 112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# error Unknown OS 114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return res; 116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(open) ( const Char* pathname, Int flags, Int mode ) 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_open, 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)pathname, flags, mode); 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_open_nocancel, 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)pathname, flags, mode); 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovInt VG_(fd_open) (const Char* pathname, Int flags, Int mode) 133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes sr; 135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov sr = VG_(open) (pathname, flags, mode); 136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sr_isError (sr)) 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return -1; 138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_Res (sr); 140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(close) ( Int fd ) 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Hmm. Return value is not checked. That's uncool. */ 145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void)VG_(do_syscall1)(__NR_close, fd); 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void)VG_(do_syscall1)(__NR_close_nocancel, fd); 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(read) ( Int fd, void* buf, Int count) 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count); 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count); 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = - (Int)(Word)sr_Err(res); 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret < 0); 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = (Int)(Word)sr_Res(res); 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret >= 0); 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(write) ( Int fd, const void* buf, Int count) 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ret; 177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count); 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count); 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = - (Int)(Word)sr_Err(res); 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret < 0); 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret = (Int)(Word)sr_Res(res); 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ret >= 0); 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(pipe) ( Int fd[2] ) 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : 0; 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* __NR_pipe is UX64, so produces a double-word result */ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall0)(__NR_pipe); 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) { 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd[0] = (Int)sr_Res(res); 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd[1] = (Int)sr_ResHI(res); 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : 0; 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovOff64T VG_(lseek) ( Int fd, Off64T offset, Int whence ) 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) || defined(VGP_amd64_darwin) 216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(__NR__llseek) 217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Off64T result; 218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes res = VG_(do_syscall5)(__NR__llseek, fd, 219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov offset >> 32, offset & 0xffffffff, 220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (UWord)&result, whence); 221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? (-1) : result; 222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); 224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(sizeof(Off64T) == sizeof(Word)); 225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? (-1) : sr_Res(res); 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall4)(__NR_lseek, fd, 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset & 0xffffffff, offset >> 32, whence); 230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? (-1) : sr_Res(res); 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown plat" 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if you change the error-reporting conventions of this, also 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown change VG_(pread) and all other usage points. */ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 238f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovextern Int VG_(ftruncate) ( Int fd, OffT length ) { 239f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#if defined (VGO_linux) 240f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov SysRes res = VG_(do_syscall2)(__NR_ftruncate, fd, length); 241f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov return sr_isError(res) ? (-1) : sr_Res(res); 242f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#else 243f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov return -1; /*UNIMPLEMENTED*/ 244f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov#endif 245f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov} 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* stat/fstat support. It's uggerly. We have impedance-match into a 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'struct vg_stat' in order to have a single structure that callers 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown can use consistently on all platforms. */ 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \ 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \ 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \ 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \ 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \ 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \ 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \ 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \ 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(stat) ( const Char* file_name, struct vg_stat* vgbuf ) 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) || defined(VGO_darwin) 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First try with stat64. If that doesn't work out, fall back to 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the vanilla version. */ 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__NR_stat64) 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat64 buf64; 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64); 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) { 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Success, or any failure except ENOSYS */ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf64); 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif /* defined(__NR_stat64) */ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat buf; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf); 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(fstat) ( Int fd, struct vg_stat* vgbuf ) 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) || defined(VGO_darwin) 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First try with fstat64. If that doesn't work out, fall back to 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the vanilla version. */ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__NR_fstat64) 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat64 buf64; 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64); 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) { 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Success, or any failure except ENOSYS */ 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf64); 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif /* if defined(__NR_fstat64) */ 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat buf; 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf); 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf); 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef TRANSLATE_TO_vg_stat 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong VG_(fsize) ( Int fd ) 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat buf; 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int res = VG_(fstat)( fd, &buf ); 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (res == -1) ? (-1LL) : buf.size; 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(is_dir) ( const HChar* f ) 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat buf; 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(stat)(f, &buf); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? False 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : VKI_S_ISDIR(buf.mode) ? True : False; 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(dup) ( Int oldfd ) 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(do_syscall1)(__NR_dup, oldfd); 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(dup2) ( Int oldfd, Int newfd ) 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) || defined(VGO_darwin) 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(do_syscall2)(__NR_dup2, oldfd, newfd); 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Returns -1 on error. */ 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(fcntl) ( Int fd, Int cmd, Addr arg ) 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg); 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(rename) ( const Char* old_name, const Char* new_name ) 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(unlink) ( const Char* file_name ) 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The working directory at startup. AIX doesn't provide an easy 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown system call to do getcwd, but fortunately we don't need arbitrary 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getcwd support. All that is really needed is to note the cwd at 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process startup. Hence VG_(record_startup_wd) notes it (in a 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform dependent way) and VG_(get_startup_wd) produces the noted 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value. Hence: */ 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar startup_wd[VKI_PATH_MAX]; 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool startup_wd_acquired = False; 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Record the process' working directory at startup. Is intended to 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be called exactly once, at startup, before the working directory 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown changes. Return True for success, False for failure, so that the 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller can bomb out suitably without creating module cycles if 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown there is a problem. */ 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(record_startup_wd) ( void ) 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Int szB = sizeof(startup_wd); 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!startup_wd_acquired); 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(szB >= 512 && szB <= 16384/*let's say*/); /* stay sane */ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(startup_wd, 0, szB); 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Simple: just ask the kernel */ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { SysRes res 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1); 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd[szB-1] == 0); 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown startup_wd_acquired = True; 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGO_darwin) 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We can't ask the kernel, so instead rely on launcher-*.c to 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tell us the startup path. Note the env var is keyed to the 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parent's PID, not ours, since our parent is the launcher 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process. */ 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Char envvar[100]; 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* wd = NULL; 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(envvar, 0, sizeof(envvar)); 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY", 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)VG_(getppid)()); 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wd = VG_(getenv)( envvar ); 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (wd == NULL || (1+VG_(strlen)(wd) >= szB)) 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(startup_wd, wd, szB); 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd[szB-1] == 0); 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown startup_wd_acquired = True; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy the previously acquired startup_wd into buf[0 .. size-1], 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or return False if buf isn't big enough. */ 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_startup_wd) ( Char* buf, SizeT size ) 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd_acquired); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd[ sizeof(startup_wd)-1 ] == 0); 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (1+VG_(strlen)(startup_wd) >= size) 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(buf, startup_wd, size); 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovInt VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout) 458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes res; 460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout); 461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? -1 : sr_Res(res); 462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(readlink) (const Char* path, Char* buf, UInt bufsiz) 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = readlink( path, buf, bufsiz ); */ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getdents) (Int fd, struct vki_dirent *dirp, UInt count) 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = getdents( fd, dirp, count ); */ 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Check accessibility of a file. Returns zero for access granted, 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nonzero otherwise. */ 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr ) 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Very annoyingly, I cannot find any definition for R_OK et al in 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the kernel interfaces. Therefore I reluctantly resort to 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hardwiring in these magic numbers that I determined by 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown experimentation. */ 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_R_OK 4 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_W_OK 2 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_X_OK 1 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord w = (irusr ? VKI_R_OK : 0) 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (iwusr ? VKI_W_OK : 0) 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (ixusr ? VKI_X_OK : 0); 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w); 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? 1 : 0; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef VKI_R_OK 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef VKI_W_OK 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef VKI_X_OK 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Emulate the normal Unix permissions checking algorithm. 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If owner matches, then use the owner permissions, else 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if group matches, then use the group permissions, else 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown use other permissions. 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that we can't deal properly with SUID/SGID. By default 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (allow_setuid == False), we refuse to run them (otherwise the 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable may misbehave if it doesn't have the permissions it 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thinks it does). However, the caller may indicate that setuid 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executables are allowed, for example if we are going to exec them 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but not trace into them (iow, client sys_execve when 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clo_trace_children == False). 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If VKI_EACCES is returned (iow, permission was refused), then 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *is_setuid is set to True iff permission was refused because the 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable is setuid. 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* returns: 0 = success, non-0 is failure */ 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(check_executable)(/*OUT*/Bool* is_setuid, 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar* f, Bool allow_setuid) 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat st; 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(stat)(f, &st); 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_setuid) 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *is_setuid = False; 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Err(res); 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) { 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_setuid) 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *is_setuid = True; 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(geteuid)() == st.uid) { 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(st.mode & VKI_S_IXUSR)) 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int grpmatch = 0; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(getegid)() == st.gid) 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown grpmatch = 1; 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt groups[32]; 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ngrp = VG_(getgroups)(32, groups); 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ngrp will be -1 if VG_(getgroups) failed. */ 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < ngrp; i++) { 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (groups[i] == st.gid) { 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown grpmatch = 1; 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (grpmatch) { 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(st.mode & VKI_S_IXGRP)) { 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (!(st.mode & VKI_S_IXOTH)) { 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* DDD: Note this moves (or at least, is believed to move) the file 587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pointer on Linux but doesn't on Darwin. This inconsistency should 588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov be fixed. (In other words, why isn't the Linux version implemented 589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov in terms of pread()?) */ 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ) 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OffT off = VG_(lseek)( fd, offset, VKI_SEEK_SET); 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (off < 0) 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(mk_SysRes_Error)( VKI_EINVAL ); 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count ); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ppc32-darwin is the same, but with the args inverted */ 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count, 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset & 0xffffffff, offset >> 32); 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the name of a directory for temporary files. */ 613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovconst HChar *VG_(tmpdir)(void) 614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const HChar *tmpdir; 616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tmpdir = VG_(getenv)("TMPDIR"); 618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR; 619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */ 620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return tmpdir; 622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create and open (-rw------) a tmp file name incorporating said arg. 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns -1 on failure, else the fd of the file. If fullname is 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-NULL, the file's name is written into it. The number of bytes 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown written is guaranteed not to exceed 64+strlen(part_of_name). */ 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname ) 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[200]; 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n, tries, fd; 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt seed; 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const HChar *tmpdir; 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(part_of_name); 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = VG_(strlen)(part_of_name); 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n > 0 && n < 100); 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seed = (VG_(getpid)() << 9) ^ VG_(getppid)(); 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Determine sensible location for temporary files */ 644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tmpdir = VG_(tmpdir)(); 645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tries = 0; 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tries++ > 10) 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 6503c9a34449a790ad8bf7b827aa85e90db8b5c08dcKenny Root VG_(sprintf)( buf, "%s/valgrind_%s_%08x", 651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tmpdir, part_of_name, VG_(random)( &seed )); 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VG_(mkstemp): trying: %s\n", buf); 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(open)(buf, 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC, 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_S_IRUSR|VKI_S_IWUSR); 658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sr_isError(sres)) { 659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", buf); 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(safe_fd) doesn't return if it fails. */ 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd = VG_(safe_fd)( sr_Res(sres) ); 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fullname) 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)( fullname, buf ); 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fd; 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Socket-related stuff. 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ); 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ); 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt VG_(htonl) ( UInt x ) 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt VG_(ntohl) ( UInt x ) 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUShort VG_(htons) ( UShort x ) 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUShort VG_(ntohs) ( UShort x ) 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The main function. 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Supplied string contains either an ip address "192.168.0.1" or 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an ip address and port pair, "192.168.0.1:1500". Parse these, 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and return: 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -1 if there is a parse error 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -2 if no parse error, but specified host:port cannot be opened 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the relevant file (socket) descriptor, otherwise. 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is used. 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(connect_via_socket)( UChar* str ) 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) || defined(VGO_darwin) 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sd, res; 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_in servAddr; 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ip = 0; 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort port = VG_CLO_DEFAULT_LOGPORT; 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = parse_inet_addr_and_port(str, &ip, &port); 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //if (0) 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(printf)("ip = %d.%d.%d.%d, port %d\n", 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (ip >> 8) & 0xFF, ip & 0xFF, 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (UInt)port ); 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown servAddr.sin_family = VKI_AF_INET; 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown servAddr.sin_addr.s_addr = VG_(htonl)(ip); 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown servAddr.sin_port = VG_(htons)(port); 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* create socket */ 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */); 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sd < 0) { 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this shouldn't happen ... nevertheless */ 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -2; 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* connect to server */ 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = my_connect(sd, &servAddr, sizeof(servAddr)); 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res < 0) { 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* connection failed */ 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -2; 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sd; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let d = one or more digits. Accept either: 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d.d.d.d or d.d.d.d:d 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ) 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define GET_CH ((*str) ? (*str++) : 0) 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ipa, i, j, c, any; 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ipa = 0; 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 4; i++) { 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 0; 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c = GET_CH; 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c < '0' || c > '9') break; 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 10 * j + (int)(c - '0'); 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 1; 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (any == 0 || j > 255) goto syntaxerr; 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ipa = (ipa << 8) + j; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i <= 2 && c != '.') goto syntaxerr; 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c == 0 || c == ':') 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ip_addr = ipa; 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c == 0) goto ok; 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c != ':') goto syntaxerr; 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 0; 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c = GET_CH; 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c < '0' || c > '9') break; 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = j * 10 + (int)(c - '0'); 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 1; 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j > 65535) goto syntaxerr; 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (any == 0 || c != 0) goto syntaxerr; 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j < 1024) goto syntaxerr; 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *port = (UShort)j; 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok: 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1; 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syntaxerr: 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef GET_CH 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// GrP fixme safe_fd? 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(socket) ( Int domain, Int type, Int protocol ) 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = domain; 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = type; 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = protocol; 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args); 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_socket, domain, type, protocol); 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) { 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int optval = 1; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res2; 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET, 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_SO_NOSIGPIPE, (UWord)&optval, 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(optval)); 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ignore setsockopt() error 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown arch" 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sockfd; 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)serv_addr; 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = addrlen; 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args); 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_connect_nocancel, 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sockfd, (UWord)serv_addr, addrlen); 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown arch" 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(write_socket)( Int sd, void *msg, Int count ) 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is actually send(). */ 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errors on stream oriented sockets when the other end breaks the 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown connection. The EPIPE error is still returned. 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SIGPIPE */ 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[4]; 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)msg; 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = count; 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[3] = VKI_MSG_NOSIGNAL; 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count, VKI_MSG_NOSIGNAL, 0,0); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count); 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)name; 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = (UWord)namelen; 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getsockname, 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getsockname, 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)name; 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = (UWord)namelen; 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getpeername, 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getpeername, 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int *optlen) 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[5]; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = level; 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = optname; 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[3] = (UWord)optval; 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[4] = (UWord)optlen; 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)( __NR_getsockopt, 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)level, (UWord)optname, 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)optval, (UWord)optlen ); 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)( __NR_getsockopt, 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)level, (UWord)optname, 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)optval, (UWord)optlen ); 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *VG_(basename)(const Char *path) 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char buf[VKI_PATH_MAX]; 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char *p, *end; 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (path == NULL || 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0 == VG_(strcmp)(path, "")) 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return "."; 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = path + VG_(strlen)(path); 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p == '/') { 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // skip all trailing '/' 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p == path && *p == '/') return "/"; // all slashes 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end = p; 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p != '/') { 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // now skip non '/' 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == '/') p++; 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(buf, p, end-p+1); 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[end-p+1] = '\0'; 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *VG_(dirname)(const Char *path) 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char buf[VKI_PATH_MAX]; 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char *p; 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (path == NULL || 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0 == VG_(strcmp)(path, "") || 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0 == VG_(strcmp)(path, "/")) 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return "."; 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = path + VG_(strlen)(path); 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p == '/') { 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // skip all trailing '/' 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p != '/') { 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // now skip non '/' 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p == path) { 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == '/') return "/"; // all slashes 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else return "."; // no slashes 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p == '/') { 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // skip '/' again 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(buf, path, p-path+1); 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[p-path+1] = '\0'; 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1100