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 10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2000-2012 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{ 197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGP_mips32_linux) 198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* __NR_pipe has a strange return convention on mips32-linux. */ 199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng SysRes res = VG_(do_syscall0)(__NR_pipe); 200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (!sr_isError(res)) { 201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fd[0] = (Int)sr_Res(res); 202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fd[1] = (Int)sr_ResEx(res); 203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return 0; 204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return -1; 206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGO_linux) 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd); 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : 0; 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* __NR_pipe is UX64, so produces a double-word result */ 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall0)(__NR_pipe); 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) { 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd[0] = (Int)sr_Res(res); 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd[1] = (Int)sr_ResHI(res); 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : 0; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovOff64T VG_(lseek) ( Int fd, Off64T offset, Int whence ) 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) || defined(VGP_amd64_darwin) 226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(__NR__llseek) 227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Off64T result; 228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes res = VG_(do_syscall5)(__NR__llseek, fd, 229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov offset >> 32, offset & 0xffffffff, 230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (UWord)&result, whence); 231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? (-1) : result; 232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# else 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence); 234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(sizeof(Off64T) == sizeof(Word)); 235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? (-1) : sr_Res(res); 236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall4)(__NR_lseek, fd, 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset & 0xffffffff, offset >> 32, whence); 240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? (-1) : sr_Res(res); 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown plat" 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* if you change the error-reporting conventions of this, also 245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng change all usage points. */ 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* stat/fstat support. It's uggerly. We have impedance-match into a 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'struct vg_stat' in order to have a single structure that callers 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown can use consistently on all platforms. */ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \ 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \ 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \ 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \ 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \ 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \ 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \ 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \ 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \ 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \ 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \ 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \ 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \ 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \ 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \ 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(stat) ( const Char* file_name, struct vg_stat* vgbuf ) 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) || defined(VGO_darwin) 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First try with stat64. If that doesn't work out, fall back to 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the vanilla version. */ 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__NR_stat64) 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat64 buf64; 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64); 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) { 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Success, or any failure except ENOSYS */ 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf64); 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif /* defined(__NR_stat64) */ 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat buf; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf); 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(fstat) ( Int fd, struct vg_stat* vgbuf ) 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(vgbuf, 0, sizeof(*vgbuf)); 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) || defined(VGO_darwin) 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First try with fstat64. If that doesn't work out, fall back to 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the vanilla version. */ 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(__NR_fstat64) 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat64 buf64; 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) { 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Success, or any failure except ENOSYS */ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf64); 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif /* if defined(__NR_fstat64) */ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { struct vki_stat buf; 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf); 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRANSLATE_TO_vg_stat(vgbuf, &buf); 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef TRANSLATE_TO_vg_stat 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong VG_(fsize) ( Int fd ) 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat buf; 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int res = VG_(fstat)( fd, &buf ); 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (res == -1) ? (-1LL) : buf.size; 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(is_dir) ( const HChar* f ) 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat buf; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(stat)(f, &buf); 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? False 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : VKI_S_ISDIR(buf.mode) ? True : False; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(dup) ( Int oldfd ) 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(do_syscall1)(__NR_dup, oldfd); 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(dup2) ( Int oldfd, Int newfd ) 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) || defined(VGO_darwin) 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(do_syscall2)(__NR_dup2, oldfd, newfd); 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Returns -1 on error. */ 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(fcntl) ( Int fd, Int cmd, Addr arg ) 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg); 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(rename) ( const Char* old_name, const Char* new_name ) 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(unlink) ( const Char* file_name ) 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? (-1) : 0; 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The working directory at startup. AIX doesn't provide an easy 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown system call to do getcwd, but fortunately we don't need arbitrary 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown getcwd support. All that is really needed is to note the cwd at 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process startup. Hence VG_(record_startup_wd) notes it (in a 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform dependent way) and VG_(get_startup_wd) produces the noted 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown value. Hence: */ 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar startup_wd[VKI_PATH_MAX]; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool startup_wd_acquired = False; 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Record the process' working directory at startup. Is intended to 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be called exactly once, at startup, before the working directory 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown changes. Return True for success, False for failure, so that the 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown caller can bomb out suitably without creating module cycles if 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown there is a problem. */ 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(record_startup_wd) ( void ) 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Int szB = sizeof(startup_wd); 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!startup_wd_acquired); 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(szB >= 512 && szB <= 16384/*let's say*/); /* stay sane */ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(startup_wd, 0, szB); 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Simple: just ask the kernel */ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { SysRes res 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1); 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd[szB-1] == 0); 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown startup_wd_acquired = True; 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# elif defined(VGO_darwin) 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We can't ask the kernel, so instead rely on launcher-*.c to 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tell us the startup path. Note the env var is keyed to the 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parent's PID, not ours, since our parent is the launcher 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown process. */ 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Char envvar[100]; 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* wd = NULL; 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(envvar, 0, sizeof(envvar)); 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY", 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)VG_(getppid)()); 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wd = VG_(getenv)( envvar ); 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (wd == NULL || (1+VG_(strlen)(wd) >= szB)) 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(startup_wd, wd, szB); 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd[szB-1] == 0); 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown startup_wd_acquired = True; 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy the previously acquired startup_wd into buf[0 .. size-1], 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or return False if buf isn't big enough. */ 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(get_startup_wd) ( Char* buf, SizeT size ) 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd_acquired); 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(startup_wd[ sizeof(startup_wd)-1 ] == 0); 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (1+VG_(strlen)(startup_wd) >= size) 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy_safely)(buf, startup_wd, size); 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 459663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengInt VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout) 460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes res; 462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGO_linux) 463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout); 464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGO_darwin) 465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout); 466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# else 467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# error "Unknown OS" 468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? -1 : sr_Res(res); 470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(readlink) (const Char* path, Char* buf, UInt bufsiz) 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = readlink( path, buf, bufsiz ); */ 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getdents) (Int fd, struct vki_dirent *dirp, UInt count) 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = getdents( fd, dirp, count ); */ 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Check accessibility of a file. Returns zero for access granted, 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nonzero otherwise. */ 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr ) 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Very annoyingly, I cannot find any definition for R_OK et al in 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the kernel interfaces. Therefore I reluctantly resort to 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hardwiring in these magic numbers that I determined by 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown experimentation. */ 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_R_OK 4 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_W_OK 2 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VKI_X_OK 1 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord w = (irusr ? VKI_R_OK : 0) 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (iwusr ? VKI_W_OK : 0) 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (ixusr ? VKI_X_OK : 0); 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w); 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? 1 : 0; 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef VKI_R_OK 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef VKI_W_OK 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef VKI_X_OK 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Emulate the normal Unix permissions checking algorithm. 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If owner matches, then use the owner permissions, else 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if group matches, then use the group permissions, else 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown use other permissions. 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that we can't deal properly with SUID/SGID. By default 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (allow_setuid == False), we refuse to run them (otherwise the 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable may misbehave if it doesn't have the permissions it 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thinks it does). However, the caller may indicate that setuid 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executables are allowed, for example if we are going to exec them 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but not trace into them (iow, client sys_execve when 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clo_trace_children == False). 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If VKI_EACCES is returned (iow, permission was refused), then 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *is_setuid is set to True iff permission was refused because the 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown executable is setuid. 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* returns: 0 = success, non-0 is failure */ 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(check_executable)(/*OUT*/Bool* is_setuid, 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const HChar* f, Bool allow_setuid) 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_stat st; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(stat)(f, &st); 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_setuid) 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *is_setuid = False; 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) { 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Err(res); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) { 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_setuid) 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *is_setuid = True; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(geteuid)() == st.uid) { 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(st.mode & VKI_S_IXUSR)) 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int grpmatch = 0; 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(getegid)() == st.gid) 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown grpmatch = 1; 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt groups[32]; 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ngrp = VG_(getgroups)(32, groups); 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ngrp will be -1 if VG_(getgroups) failed. */ 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < ngrp; i++) { 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (groups[i] == st.gid) { 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown grpmatch = 1; 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (grpmatch) { 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(st.mode & VKI_S_IXGRP)) { 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (!(st.mode & VKI_S_IXOTH)) { 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VKI_EACCES; 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ) 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // on 32 bits platforms, we receive a 32 bits OffT but 598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // we must extend it to pass a long long 64 bits. 599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGP_x86_linux) 600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 4); 601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count, 602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng offset, 0); // Little endian long long 603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return res; 604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_arm_linux) 605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 4); 606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count, 607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0, offset); // Big endian long long 608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return res; 609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_ppc32_linux) 610663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 4); 611663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 612663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0, // Padding needed on PPC32 613663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0, offset); // Big endian long long 614663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return res; 615663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_mips32_linux) && VKI_LITTLE_ENDIAN 616663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 4); 617663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 618663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0, offset, 0); 619663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return res; 620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_mips32_linux) && VKI_BIG_ENDIAN 621663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 4); 622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 623663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 0, 0, offset); 624663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return res; 625663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_amd64_linux) \ 626663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 627663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_darwin) 630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 8); 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset); 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 634663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(sizeof(OffT) == 8); 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count, 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown offset & 0xffffffff, offset >> 32); 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return res; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Return the name of a directory for temporary files. */ 644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovconst HChar *VG_(tmpdir)(void) 645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const HChar *tmpdir; 647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tmpdir = VG_(getenv)("TMPDIR"); 649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR; 650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */ 651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return tmpdir; 653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create and open (-rw------) a tmp file name incorporating said arg. 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Returns -1 on failure, else the fd of the file. If fullname is 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-NULL, the file's name is written into it. The number of bytes 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown written is guaranteed not to exceed 64+strlen(part_of_name). */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname ) 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[200]; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int n, tries, fd; 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt seed; 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const HChar *tmpdir; 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(part_of_name); 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = VG_(strlen)(part_of_name); 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(n > 0 && n < 100); 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown seed = (VG_(getpid)() << 9) ^ VG_(getppid)(); 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Determine sensible location for temporary files */ 675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tmpdir = VG_(tmpdir)(); 676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tries = 0; 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (tries++ > 10) 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 6813c9a34449a790ad8bf7b827aa85e90db8b5c08dcKenny Root VG_(sprintf)( buf, "%s/valgrind_%s_%08x", 682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tmpdir, part_of_name, VG_(random)( &seed )); 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("VG_(mkstemp): trying: %s\n", buf); 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(open)(buf, 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC, 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_S_IRUSR|VKI_S_IWUSR); 689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (sr_isError(sres)) { 690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", buf); 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* VG_(safe_fd) doesn't return if it fails. */ 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fd = VG_(safe_fd)( sr_Res(sres) ); 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fullname) 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)( fullname, buf ); 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return fd; 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Socket-related stuff. 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ); 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ); 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt VG_(htonl) ( UInt x ) 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt VG_(ntohl) ( UInt x ) 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUShort VG_(htons) ( UShort x ) 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUShort VG_(ntohs) ( UShort x ) 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VG_BIGENDIAN) 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return x; 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The main function. 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Supplied string contains either an ip address "192.168.0.1" or 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown an ip address and port pair, "192.168.0.1:1500". Parse these, 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and return: 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -1 if there is a parse error 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -2 if no parse error, but specified host:port cannot be opened 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the relevant file (socket) descriptor, otherwise. 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is used. 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(connect_via_socket)( UChar* str ) 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) || defined(VGO_darwin) 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int sd, res; 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_sockaddr_in servAddr; 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ip = 0; 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort port = VG_CLO_DEFAULT_LOGPORT; 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = parse_inet_addr_and_port(str, &ip, &port); 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!ok) 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //if (0) 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(printf)("ip = %d.%d.%d.%d, port %d\n", 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (ip >> 8) & 0xFF, ip & 0xFF, 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (UInt)port ); 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown servAddr.sin_family = VKI_AF_INET; 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown servAddr.sin_addr.s_addr = VG_(htonl)(ip); 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown servAddr.sin_port = VG_(htons)(port); 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* create socket */ 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */); 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sd < 0) { 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this shouldn't happen ... nevertheless */ 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -2; 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* connect to server */ 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = my_connect(sd, &servAddr, sizeof(servAddr)); 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (res < 0) { 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* connection failed */ 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -2; 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sd; 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let d = one or more digits. Accept either: 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown d.d.d.d or d.d.d.d:d 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port ) 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define GET_CH ((*str) ? (*str++) : 0) 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ipa, i, j, c, any; 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ipa = 0; 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 4; i++) { 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 0; 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c = GET_CH; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c < '0' || c > '9') break; 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 10 * j + (int)(c - '0'); 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 1; 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (any == 0 || j > 255) goto syntaxerr; 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ipa = (ipa << 8) + j; 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i <= 2 && c != '.') goto syntaxerr; 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c == 0 || c == ':') 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ip_addr = ipa; 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c == 0) goto ok; 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c != ':') goto syntaxerr; 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = 0; 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 0; 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (1) { 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown c = GET_CH; 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c < '0' || c > '9') break; 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j = j * 10 + (int)(c - '0'); 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown any = 1; 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j > 65535) goto syntaxerr; 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (any == 0 || c != 0) goto syntaxerr; 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j < 1024) goto syntaxerr; 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *port = (UShort)j; 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ok: 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1; 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syntaxerr: 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# undef GET_CH 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// GrP fixme safe_fd? 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(socket) ( Int domain, Int type, Int protocol ) 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = domain; 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = type; 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = protocol; 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args); 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_socket, domain, type, protocol); 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res)) { 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int optval = 1; 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res2; 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET, 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_SO_NOSIGPIPE, (UWord)&optval, 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(optval)); 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // ignore setsockopt() error 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown arch" 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sockfd; 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)serv_addr; 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = addrlen; 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 905663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 906663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_connect_nocancel, 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sockfd, (UWord)serv_addr, addrlen); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown arch" 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(write_socket)( Int sd, void *msg, Int count ) 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is actually send(). */ 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errors on stream oriented sockets when the other end breaks the 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown connection. The EPIPE error is still returned. 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SIGPIPE */ 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[4]; 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)msg; 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = count; 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[3] = VKI_MSG_NOSIGNAL; 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 945663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown count, VKI_MSG_NOSIGNAL, 0,0); 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count); 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \ 965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)name; 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = (UWord)namelen; 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getsockname, 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getsockname, 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 994663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \ 995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[3]; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = (UWord)name; 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = (UWord)namelen; 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getpeername, 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)( __NR_getpeername, 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)name, (UWord)namelen ); 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int *optlen) 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord args[5]; 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[0] = sd; 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[1] = level; 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[2] = optname; 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[3] = (UWord)optval; 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown args[4] = (UWord)optlen; 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)( __NR_getsockopt, 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)level, (UWord)optname, 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)optval, (UWord)optlen ); 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall5)( __NR_getsockopt, 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)sd, (UWord)level, (UWord)optname, 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)optval, (UWord)optlen ); 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown platform" 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *VG_(basename)(const Char *path) 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char buf[VKI_PATH_MAX]; 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char *p, *end; 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (path == NULL || 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 if (p == path && *p == '/') return "/"; // all slashes 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown end = p; 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p != '/') { 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // now skip non '/' 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == '/') p++; 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(buf, p, end-p+1); 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[end-p+1] = '\0'; 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *VG_(dirname)(const Char *path) 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char buf[VKI_PATH_MAX]; 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Char *p; 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (path == NULL || 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0 == VG_(strcmp)(path, "") || 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0 == VG_(strcmp)(path, "/")) 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return "."; 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = path + VG_(strlen)(path); 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p == '/') { 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // skip all trailing '/' 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p != '/') { 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // now skip non '/' 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p == path) { 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*p == '/') return "/"; // all slashes 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else return "."; // no slashes 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (p > path && *p == '/') { 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // skip '/' again 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p--; 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strncpy)(buf, path, p-path+1); 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf[p-path+1] = '\0'; 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return buf; 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1137