blob: 9c1847be95586450292069211d9e9b172610a9d0 [file] [log] [blame]
njneb8896b2005-06-04 20:03:55 +00001
2/*--------------------------------------------------------------------*/
3/*--- File- and socket-related libc stuff. m_libcfile.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 Julian Seward
njneb8896b2005-06-04 20:03:55 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
sewardj9a66bb92006-10-17 01:38:13 +000033#include "pub_core_vkiscnums.h"
sewardj26b87282006-10-17 12:49:31 +000034#include "pub_core_debuglog.h"
njneb8896b2005-06-04 20:03:55 +000035#include "pub_core_libcbase.h"
36#include "pub_core_libcassert.h"
37#include "pub_core_libcfile.h"
sewardjfdf91b42005-09-28 00:53:09 +000038#include "pub_core_libcprint.h" // VG_(sprintf)
sewardj45f4e7c2005-09-27 19:20:21 +000039#include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
sewardj14c7cc52007-02-25 15:08:24 +000040#include "pub_core_xarray.h"
sewardjfdf91b42005-09-28 00:53:09 +000041#include "pub_core_clientstate.h" // VG_(fd_hard_limit)
njn9abd6082005-06-17 21:31:45 +000042#include "pub_core_syscall.h"
njneb8896b2005-06-04 20:03:55 +000043
njnf76d27a2009-05-28 01:53:07 +000044/* IMPORTANT: on Darwin it is essential to use the _nocancel versions
45 of syscalls rather than the vanilla version, if a _nocancel version
46 is available. See docs/internals/Darwin-notes.txt for the reason
47 why. */
48
njneb8896b2005-06-04 20:03:55 +000049/* ---------------------------------------------------------------------
50 File stuff
51 ------------------------------------------------------------------ */
52
53static inline Bool fd_exists(Int fd)
54{
sewardjec61b652008-08-19 07:03:04 +000055 struct vg_stat st;
njneb8896b2005-06-04 20:03:55 +000056 return VG_(fstat)(fd, &st) == 0;
57}
58
59/* Move an fd into the Valgrind-safe range */
60Int VG_(safe_fd)(Int oldfd)
61{
62 Int newfd;
63
64 vg_assert(VG_(fd_hard_limit) != -1);
65
66 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
67 if (newfd != -1)
68 VG_(close)(oldfd);
69
sewardj9a66bb92006-10-17 01:38:13 +000070 /* Set the close-on-exec flag for this fd. */
njneb8896b2005-06-04 20:03:55 +000071 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
72
73 vg_assert(newfd >= VG_(fd_hard_limit));
74 return newfd;
75}
76
njnae7359b2005-06-19 21:10:42 +000077/* Given a file descriptor, attempt to deduce its filename. To do
78 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
njnf845f8f2005-06-23 02:26:47 +000079 or if it doesn't exist, we return False. */
80Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
njnae7359b2005-06-19 21:10:42 +000081{
njn81b975c2009-04-28 05:35:53 +000082# if defined(VGO_linux)
njnae7359b2005-06-19 21:10:42 +000083 HChar tmp[64];
njnae7359b2005-06-19 21:10:42 +000084 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
njnf845f8f2005-06-23 02:26:47 +000085 VG_(memset)(buf, 0, n_buf);
sewardj45f4e7c2005-09-27 19:20:21 +000086 if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/')
njnf845f8f2005-06-23 02:26:47 +000087 return True;
88 else
89 return False;
njndad944a2009-05-04 05:55:46 +000090
njn81b975c2009-04-28 05:35:53 +000091# elif defined(VGO_aix5)
92 I_die_here; /* maybe just return False? */
93 return False;
njndad944a2009-05-04 05:55:46 +000094
njnf76d27a2009-05-28 01:53:07 +000095# elif defined(VGO_darwin)
96 HChar tmp[VKI_MAXPATHLEN+1];
97 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
98 if (n_buf > 0) {
99 VG_(strncpy)( buf, tmp, n_buf < sizeof(tmp) ? n_buf : sizeof(tmp) );
100 buf[n_buf-1] = 0;
101 }
102 if (tmp[0] == '/') return True;
103 }
104 return False;
105
njn81b975c2009-04-28 05:35:53 +0000106# else
njndad944a2009-05-04 05:55:46 +0000107# error Unknown OS
njn81b975c2009-04-28 05:35:53 +0000108# endif
njnae7359b2005-06-19 21:10:42 +0000109}
110
sewardj92645592005-07-23 09:18:34 +0000111SysRes VG_(open) ( const Char* pathname, Int flags, Int mode )
njneb8896b2005-06-04 20:03:55 +0000112{
njnf76d27a2009-05-28 01:53:07 +0000113# if defined(VGO_linux) || defined(VGO_aix5)
114 SysRes res = VG_(do_syscall3)(__NR_open,
115 (UWord)pathname, flags, mode);
116# elif defined(VGO_darwin)
117 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
118 (UWord)pathname, flags, mode);
119# else
120# error Unknown OS
121# endif
sewardj92645592005-07-23 09:18:34 +0000122 return res;
njneb8896b2005-06-04 20:03:55 +0000123}
124
125void VG_(close) ( Int fd )
126{
njnf76d27a2009-05-28 01:53:07 +0000127 /* Hmm. Return value is not checked. That's uncool. */
128# if defined(VGO_linux) || defined(VGO_aix5)
sewardja8d8e232005-06-07 20:04:56 +0000129 (void)VG_(do_syscall1)(__NR_close, fd);
njnf76d27a2009-05-28 01:53:07 +0000130# elif defined(VGO_darwin)
131 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
132# else
133# error Unknown OS
134# endif
njneb8896b2005-06-04 20:03:55 +0000135}
136
137Int VG_(read) ( Int fd, void* buf, Int count)
138{
sewardj9a66bb92006-10-17 01:38:13 +0000139 Int ret;
njnf76d27a2009-05-28 01:53:07 +0000140# if defined(VGO_linux) || defined(VGO_aix5)
sewardja8d8e232005-06-07 20:04:56 +0000141 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
njnf76d27a2009-05-28 01:53:07 +0000142# elif defined(VGO_darwin)
143 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
144# else
145# error Unknown OS
146# endif
njncda2f0f2009-05-18 02:12:08 +0000147 if (sr_isError(res)) {
148 ret = - (Int)(Word)sr_Err(res);
sewardj9a66bb92006-10-17 01:38:13 +0000149 vg_assert(ret < 0);
150 } else {
njncda2f0f2009-05-18 02:12:08 +0000151 ret = (Int)(Word)sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000152 vg_assert(ret >= 0);
153 }
154 return ret;
njneb8896b2005-06-04 20:03:55 +0000155}
156
157Int VG_(write) ( Int fd, const void* buf, Int count)
158{
sewardj9a66bb92006-10-17 01:38:13 +0000159 Int ret;
njnf76d27a2009-05-28 01:53:07 +0000160# if defined(VGO_linux) || defined(VGO_aix5)
sewardja8d8e232005-06-07 20:04:56 +0000161 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
njnf76d27a2009-05-28 01:53:07 +0000162# elif defined(VGO_darwin)
163 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
164# else
165# error "Unknown OS"
166# endif
njncda2f0f2009-05-18 02:12:08 +0000167 if (sr_isError(res)) {
168 ret = - (Int)(Word)sr_Err(res);
sewardj9a66bb92006-10-17 01:38:13 +0000169 vg_assert(ret < 0);
170 } else {
njncda2f0f2009-05-18 02:12:08 +0000171 ret = (Int)(Word)sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000172 vg_assert(ret >= 0);
173 }
174 return ret;
njneb8896b2005-06-04 20:03:55 +0000175}
176
njncda2f0f2009-05-18 02:12:08 +0000177
njneb8896b2005-06-04 20:03:55 +0000178Int VG_(pipe) ( Int fd[2] )
179{
njncda2f0f2009-05-18 02:12:08 +0000180# if defined(VGO_linux) || defined(VGO_aix5)
sewardja8d8e232005-06-07 20:04:56 +0000181 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
njncda2f0f2009-05-18 02:12:08 +0000182 return sr_isError(res) ? -1 : 0;
njnf76d27a2009-05-28 01:53:07 +0000183# elif defined(VGO_darwin)
184 /* __NR_pipe is UX64, so produces a double-word result */
185 SysRes res = VG_(do_syscall0)(__NR_pipe);
186 if (!sr_isError(res)) {
187 fd[0] = (Int)sr_Res(res);
188 fd[1] = (Int)sr_ResHI(res);
189 }
190 return sr_isError(res) ? -1 : 0;
njncda2f0f2009-05-18 02:12:08 +0000191# else
192# error "Unknown OS"
193# endif
njneb8896b2005-06-04 20:03:55 +0000194}
195
sewardj45f4e7c2005-09-27 19:20:21 +0000196OffT VG_(lseek) ( Int fd, OffT offset, Int whence )
njneb8896b2005-06-04 20:03:55 +0000197{
njnf76d27a2009-05-28 01:53:07 +0000198# if defined(VGO_linux) || defined(VGO_aix5) || defined(VGP_amd64_darwin)
sewardja8d8e232005-06-07 20:04:56 +0000199 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
njncda2f0f2009-05-18 02:12:08 +0000200 vg_assert(sizeof(OffT) == sizeof(Word));
njnf76d27a2009-05-28 01:53:07 +0000201# elif defined(VGP_x86_darwin)
202 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
203 offset & 0xffffffff, offset >> 32, whence);
njncda2f0f2009-05-18 02:12:08 +0000204# else
205# error "Unknown plat"
206# endif
207 return sr_isError(res) ? (-1) : sr_Res(res);
sewardj45f4e7c2005-09-27 19:20:21 +0000208 /* if you change the error-reporting conventions of this, also
209 change VG_(pread) and all other usage points. */
njneb8896b2005-06-04 20:03:55 +0000210}
211
sewardjec61b652008-08-19 07:03:04 +0000212
213/* stat/fstat support. It's uggerly. We have impedance-match into a
214 'struct vg_stat' in order to have a single structure that callers
215 can use consistently on all platforms. */
216
217#define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
218 do { \
njn9c20ece2009-05-20 02:02:30 +0000219 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
220 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
221 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
222 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
223 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
224 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
225 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
226 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
227 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
228 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
229 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
230 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
231 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
232 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
233 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
234 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
sewardjec61b652008-08-19 07:03:04 +0000235 } while (0)
236
njncda2f0f2009-05-18 02:12:08 +0000237SysRes VG_(stat) ( const Char* file_name, struct vg_stat* vgbuf )
njneb8896b2005-06-04 20:03:55 +0000238{
sewardjec61b652008-08-19 07:03:04 +0000239 SysRes res;
240 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
njncda2f0f2009-05-18 02:12:08 +0000241
njnf76d27a2009-05-28 01:53:07 +0000242# if defined(VGO_linux) || defined(VGO_darwin)
njncda2f0f2009-05-18 02:12:08 +0000243 /* First try with stat64. If that doesn't work out, fall back to
244 the vanilla version. */
sewardjec61b652008-08-19 07:03:04 +0000245# if defined(__NR_stat64)
246 { struct vki_stat64 buf64;
247 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
njncda2f0f2009-05-18 02:12:08 +0000248 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
sewardjec61b652008-08-19 07:03:04 +0000249 /* Success, or any failure except ENOSYS */
njncda2f0f2009-05-18 02:12:08 +0000250 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000251 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
252 return res;
253 }
254 }
njncda2f0f2009-05-18 02:12:08 +0000255# endif /* defined(__NR_stat64) */
sewardjec61b652008-08-19 07:03:04 +0000256 { struct vki_stat buf;
257 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
njncda2f0f2009-05-18 02:12:08 +0000258 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000259 TRANSLATE_TO_vg_stat(vgbuf, &buf);
260 return res;
261 }
njncda2f0f2009-05-18 02:12:08 +0000262
sewardj9a66bb92006-10-17 01:38:13 +0000263# elif defined(VGO_aix5)
sewardj9c606bd2008-09-18 18:12:50 +0000264 { struct vki_stat buf;
265 res = VG_(do_syscall4)(__NR_AIX5_statx,
266 (UWord)file_name,
267 (UWord)&buf,
268 sizeof(struct vki_stat),
269 VKI_STX_NORMAL);
njncda2f0f2009-05-18 02:12:08 +0000270 if (!sr_isError(res)) {
sewardj9c606bd2008-09-18 18:12:50 +0000271 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
njn9c20ece2009-05-20 02:02:30 +0000272 vgbuf->dev = (ULong)buf.st_dev;
273 vgbuf->ino = (ULong)buf.st_ino;
274 vgbuf->mode = (UInt)buf.st_mode;
275 vgbuf->uid = (UInt)buf.st_uid;
276 vgbuf->gid = (UInt)buf.st_gid;
277 vgbuf->size = (Long)buf.st_size;
sewardj9c606bd2008-09-18 18:12:50 +0000278 }
279 return res;
280 }
njncda2f0f2009-05-18 02:12:08 +0000281
sewardj9a66bb92006-10-17 01:38:13 +0000282# else
283# error Unknown OS
284# endif
njneb8896b2005-06-04 20:03:55 +0000285}
286
sewardjec61b652008-08-19 07:03:04 +0000287Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
njneb8896b2005-06-04 20:03:55 +0000288{
sewardjec61b652008-08-19 07:03:04 +0000289 SysRes res;
290 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
njncda2f0f2009-05-18 02:12:08 +0000291
njnf76d27a2009-05-28 01:53:07 +0000292# if defined(VGO_linux) || defined(VGO_darwin)
njncda2f0f2009-05-18 02:12:08 +0000293 /* First try with fstat64. If that doesn't work out, fall back to
294 the vanilla version. */
sewardjec61b652008-08-19 07:03:04 +0000295# if defined(__NR_fstat64)
296 { struct vki_stat64 buf64;
297 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
njncda2f0f2009-05-18 02:12:08 +0000298 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
sewardjec61b652008-08-19 07:03:04 +0000299 /* Success, or any failure except ENOSYS */
njncda2f0f2009-05-18 02:12:08 +0000300 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000301 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
njncda2f0f2009-05-18 02:12:08 +0000302 return sr_isError(res) ? (-1) : 0;
sewardjec61b652008-08-19 07:03:04 +0000303 }
304 }
305# endif /* if defined(__NR_fstat64) */
306 { struct vki_stat buf;
307 res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf);
njncda2f0f2009-05-18 02:12:08 +0000308 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000309 TRANSLATE_TO_vg_stat(vgbuf, &buf);
njncda2f0f2009-05-18 02:12:08 +0000310 return sr_isError(res) ? (-1) : 0;
sewardjec61b652008-08-19 07:03:04 +0000311 }
njncda2f0f2009-05-18 02:12:08 +0000312
sewardj9a66bb92006-10-17 01:38:13 +0000313# elif defined(VGO_aix5)
314 I_die_here;
njncda2f0f2009-05-18 02:12:08 +0000315
sewardj9a66bb92006-10-17 01:38:13 +0000316# else
317# error Unknown OS
318# endif
njneb8896b2005-06-04 20:03:55 +0000319}
320
sewardjec61b652008-08-19 07:03:04 +0000321#undef TRANSLATE_TO_vg_stat
322
323
324Long VG_(fsize) ( Int fd )
njneb8896b2005-06-04 20:03:55 +0000325{
sewardjec61b652008-08-19 07:03:04 +0000326 struct vg_stat buf;
327 Int res = VG_(fstat)( fd, &buf );
njn9c20ece2009-05-20 02:02:30 +0000328 return (res == -1) ? (-1LL) : buf.size;
sewardj45f4e7c2005-09-27 19:20:21 +0000329}
330
njn63e5e6e2009-05-20 04:22:42 +0000331Bool VG_(is_dir) ( const HChar* f )
njn73750612005-10-14 03:11:30 +0000332{
sewardjec61b652008-08-19 07:03:04 +0000333 struct vg_stat buf;
sewardj9a66bb92006-10-17 01:38:13 +0000334 SysRes res = VG_(stat)(f, &buf);
njncda2f0f2009-05-18 02:12:08 +0000335 return sr_isError(res) ? False
njn9c20ece2009-05-20 02:02:30 +0000336 : VKI_S_ISDIR(buf.mode) ? True : False;
njn73750612005-10-14 03:11:30 +0000337}
338
sewardj45f4e7c2005-09-27 19:20:21 +0000339SysRes VG_(dup) ( Int oldfd )
340{
341 return VG_(do_syscall1)(__NR_dup, oldfd);
njneb8896b2005-06-04 20:03:55 +0000342}
343
njnfad98372008-10-12 19:53:28 +0000344SysRes VG_(dup2) ( Int oldfd, Int newfd )
345{
njnf76d27a2009-05-28 01:53:07 +0000346# if defined(VGO_linux) || defined(VGO_darwin)
njnfad98372008-10-12 19:53:28 +0000347 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
sewardj485ce162008-10-22 00:57:29 +0000348# elif defined(VGO_aix5)
349 I_die_here;
350# else
351# error Unknown OS
352# endif
njnfad98372008-10-12 19:53:28 +0000353}
354
njn327fe8a2005-06-12 02:49:35 +0000355/* Returns -1 on error. */
njnbb7af3f2009-05-22 07:08:12 +0000356Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
njn327fe8a2005-06-12 02:49:35 +0000357{
njnf76d27a2009-05-28 01:53:07 +0000358# if defined(VGO_linux) || defined(VGO_aix5)
njn327fe8a2005-06-12 02:49:35 +0000359 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
njnf76d27a2009-05-28 01:53:07 +0000360# elif defined(VGO_darwin)
361 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
362# else
363# error "Unknown OS"
364# endif
njncda2f0f2009-05-18 02:12:08 +0000365 return sr_isError(res) ? -1 : sr_Res(res);
njn327fe8a2005-06-12 02:49:35 +0000366}
367
njn63e5e6e2009-05-20 04:22:42 +0000368Int VG_(rename) ( const Char* old_name, const Char* new_name )
njneb8896b2005-06-04 20:03:55 +0000369{
sewardja8d8e232005-06-07 20:04:56 +0000370 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
njncda2f0f2009-05-18 02:12:08 +0000371 return sr_isError(res) ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000372}
373
njn63e5e6e2009-05-20 04:22:42 +0000374Int VG_(unlink) ( const Char* file_name )
njneb8896b2005-06-04 20:03:55 +0000375{
sewardja8d8e232005-06-07 20:04:56 +0000376 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
njncda2f0f2009-05-18 02:12:08 +0000377 return sr_isError(res) ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000378}
379
sewardj198f34f2007-07-09 23:13:07 +0000380/* The working directory at startup. AIX doesn't provide an easy
381 system call to do getcwd, but fortunately we don't need arbitrary
382 getcwd support. All that is really needed is to note the cwd at
383 process startup. Hence VG_(record_startup_wd) notes it (in a
384 platform dependent way) and VG_(get_startup_wd) produces the noted
385 value. Hence: */
386static HChar startup_wd[VKI_PATH_MAX];
387static Bool startup_wd_acquired = False;
388
389/* Record the process' working directory at startup. Is intended to
390 be called exactly once, at startup, before the working directory
391 changes. Return True for success, False for failure, so that the
392 caller can bomb out suitably without creating module cycles if
393 there is a problem. */
394Bool VG_(record_startup_wd) ( void )
njneb8896b2005-06-04 20:03:55 +0000395{
sewardj198f34f2007-07-09 23:13:07 +0000396 const Int szB = sizeof(startup_wd);
397 vg_assert(!startup_wd_acquired);
398 vg_assert(szB >= 512 && szB <= 16384/*let's say*/); /* stay sane */
399 VG_(memset)(startup_wd, 0, szB);
sewardj9a66bb92006-10-17 01:38:13 +0000400# if defined(VGO_linux)
sewardj198f34f2007-07-09 23:13:07 +0000401 /* Simple: just ask the kernel */
402 { SysRes res
403 = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
404 vg_assert(startup_wd[szB-1] == 0);
njncda2f0f2009-05-18 02:12:08 +0000405 if (sr_isError(res)) {
sewardj198f34f2007-07-09 23:13:07 +0000406 return False;
407 } else {
408 startup_wd_acquired = True;
409 return True;
410 }
411 }
njnf76d27a2009-05-28 01:53:07 +0000412# elif defined(VGO_aix5) || defined(VGO_darwin)
413 /* We can't ask the kernel, so instead rely on launcher-*.c to
sewardj198f34f2007-07-09 23:13:07 +0000414 tell us the startup path. Note the env var is keyed to the
415 parent's PID, not ours, since our parent is the launcher
416 process. */
417 { Char envvar[100];
418 Char* wd = NULL;
419 VG_(memset)(envvar, 0, sizeof(envvar));
420 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
421 (Int)VG_(getppid)());
422 wd = VG_(getenv)( envvar );
423 if (wd == NULL || (1+VG_(strlen)(wd) >= szB))
424 return False;
425 VG_(strncpy_safely)(startup_wd, wd, szB);
426 vg_assert(startup_wd[szB-1] == 0);
427 startup_wd_acquired = True;
428 return True;
429 }
sewardj9a66bb92006-10-17 01:38:13 +0000430# else
431# error Unknown OS
432# endif
njneb8896b2005-06-04 20:03:55 +0000433}
434
sewardj198f34f2007-07-09 23:13:07 +0000435/* Copy the previously acquired startup_wd into buf[0 .. size-1],
436 or return False if buf isn't big enough. */
437Bool VG_(get_startup_wd) ( Char* buf, SizeT size )
438{
439 vg_assert(startup_wd_acquired);
440 vg_assert(startup_wd[ sizeof(startup_wd)-1 ] == 0);
441 if (1+VG_(strlen)(startup_wd) >= size)
442 return False;
443 VG_(strncpy_safely)(buf, startup_wd, size);
444 return True;
445}
446
njn63e5e6e2009-05-20 04:22:42 +0000447Int VG_(readlink) (const Char* path, Char* buf, UInt bufsiz)
njneb8896b2005-06-04 20:03:55 +0000448{
sewardja8d8e232005-06-07 20:04:56 +0000449 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000450 /* res = readlink( path, buf, bufsiz ); */
451 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
njncda2f0f2009-05-18 02:12:08 +0000452 return sr_isError(res) ? -1 : sr_Res(res);
njneb8896b2005-06-04 20:03:55 +0000453}
454
njncda2f0f2009-05-18 02:12:08 +0000455Int VG_(getdents) (Int fd, struct vki_dirent *dirp, UInt count)
njneb8896b2005-06-04 20:03:55 +0000456{
njncda2f0f2009-05-18 02:12:08 +0000457# if defined(VGO_linux) || defined(VGO_aix5)
sewardja8d8e232005-06-07 20:04:56 +0000458 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000459 /* res = getdents( fd, dirp, count ); */
460 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
njncda2f0f2009-05-18 02:12:08 +0000461 return sr_isError(res) ? -1 : sr_Res(res);
njnf76d27a2009-05-28 01:53:07 +0000462# elif defined(VGO_darwin)
463 I_die_here;
njncda2f0f2009-05-18 02:12:08 +0000464# else
465# error "Unknown OS"
466# endif
njneb8896b2005-06-04 20:03:55 +0000467}
468
sewardj45f4e7c2005-09-27 19:20:21 +0000469/* Check accessibility of a file. Returns zero for access granted,
470 nonzero otherwise. */
njn63e5e6e2009-05-20 04:22:42 +0000471Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
sewardj45f4e7c2005-09-27 19:20:21 +0000472{
sewardj9a66bb92006-10-17 01:38:13 +0000473# if defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +0000474 /* Very annoyingly, I cannot find any definition for R_OK et al in
475 the kernel interfaces. Therefore I reluctantly resort to
476 hardwiring in these magic numbers that I determined by
477 experimentation. */
njncda2f0f2009-05-18 02:12:08 +0000478# define VKI_R_OK 4
479# define VKI_W_OK 2
480# define VKI_X_OK 1
481# endif
482
sewardj9a66bb92006-10-17 01:38:13 +0000483 UWord w = (irusr ? VKI_R_OK : 0)
484 | (iwusr ? VKI_W_OK : 0)
485 | (ixusr ? VKI_X_OK : 0);
486 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
njncda2f0f2009-05-18 02:12:08 +0000487 return sr_isError(res) ? 1 : 0;
488
489# if defined(VGO_linux)
490# undef VKI_R_OK
491# undef VKI_W_OK
492# undef VKI_X_OK
sewardj9a66bb92006-10-17 01:38:13 +0000493# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000494}
495
njn73750612005-10-14 03:11:30 +0000496/*
497 Emulate the normal Unix permissions checking algorithm.
498
499 If owner matches, then use the owner permissions, else
500 if group matches, then use the group permissions, else
501 use other permissions.
502
sewardjc74b3ba2007-11-17 21:11:57 +0000503 Note that we can't deal properly with SUID/SGID. By default
504 (allow_setuid == False), we refuse to run them (otherwise the
505 executable may misbehave if it doesn't have the permissions it
506 thinks it does). However, the caller may indicate that setuid
507 executables are allowed, for example if we are going to exec them
508 but not trace into them (iow, client sys_execve when
509 clo_trace_children == False).
510
511 If VKI_EACCES is returned (iow, permission was refused), then
512 *is_setuid is set to True iff permission was refused because the
513 executable is setuid.
njn73750612005-10-14 03:11:30 +0000514*/
515/* returns: 0 = success, non-0 is failure */
sewardjc74b3ba2007-11-17 21:11:57 +0000516Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
njn63e5e6e2009-05-20 04:22:42 +0000517 const HChar* f, Bool allow_setuid)
njn73750612005-10-14 03:11:30 +0000518{
sewardj4231a852008-08-19 08:32:03 +0000519 struct vg_stat st;
sewardj26b87282006-10-17 12:49:31 +0000520 SysRes res = VG_(stat)(f, &st);
njn73750612005-10-14 03:11:30 +0000521
sewardjc74b3ba2007-11-17 21:11:57 +0000522 if (is_setuid)
523 *is_setuid = False;
524
njncda2f0f2009-05-18 02:12:08 +0000525 if (sr_isError(res)) {
526 return sr_Err(res);
njn73750612005-10-14 03:11:30 +0000527 }
528
njn9c20ece2009-05-20 02:02:30 +0000529 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
sewardjc74b3ba2007-11-17 21:11:57 +0000530 if (is_setuid)
531 *is_setuid = True;
njn73750612005-10-14 03:11:30 +0000532 return VKI_EACCES;
533 }
534
njn9c20ece2009-05-20 02:02:30 +0000535 if (VG_(geteuid)() == st.uid) {
536 if (!(st.mode & VKI_S_IXUSR))
njn73750612005-10-14 03:11:30 +0000537 return VKI_EACCES;
538 } else {
sewardj45406ef2006-10-18 00:33:46 +0000539 Int grpmatch = 0;
njn73750612005-10-14 03:11:30 +0000540
njn9c20ece2009-05-20 02:02:30 +0000541 if (VG_(getegid)() == st.gid)
njn73750612005-10-14 03:11:30 +0000542 grpmatch = 1;
543 else {
544 UInt groups[32];
545 Int ngrp = VG_(getgroups)(32, groups);
546 Int i;
547 /* ngrp will be -1 if VG_(getgroups) failed. */
548 for (i = 0; i < ngrp; i++) {
njn9c20ece2009-05-20 02:02:30 +0000549 if (groups[i] == st.gid) {
njn73750612005-10-14 03:11:30 +0000550 grpmatch = 1;
551 break;
552 }
553 }
554 }
555
556 if (grpmatch) {
njn9c20ece2009-05-20 02:02:30 +0000557 if (!(st.mode & VKI_S_IXGRP)) {
njn73750612005-10-14 03:11:30 +0000558 return VKI_EACCES;
559 }
njn9c20ece2009-05-20 02:02:30 +0000560 } else if (!(st.mode & VKI_S_IXOTH)) {
njn73750612005-10-14 03:11:30 +0000561 return VKI_EACCES;
562 }
563 }
564
565 return 0;
566}
567
njnf76d27a2009-05-28 01:53:07 +0000568/* DDD: Note this moves (or at least, is believed to move) the file pointer
njncda2f0f2009-05-18 02:12:08 +0000569 on Linux and AIX5 but doesn't on Darwin. This inconsistency should
njnf76d27a2009-05-28 01:53:07 +0000570 be fixed. (In other words, why isn't the Linux/AIX5 version implemented in
571 terms of pread()?) */
njnc4431bf2009-01-15 21:29:24 +0000572SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
sewardj45f4e7c2005-09-27 19:20:21 +0000573{
njncda2f0f2009-05-18 02:12:08 +0000574 SysRes res;
575# if defined(VGO_linux) || defined(VGO_aix5)
576 /* Linux, AIX5 */
577 OffT off = VG_(lseek)( fd, offset, VKI_SEEK_SET);
tomf4c23102005-10-31 17:05:21 +0000578 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +0000579 return VG_(mk_SysRes_Error)( VKI_EINVAL );
njncda2f0f2009-05-18 02:12:08 +0000580 res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count );
581 return res;
njnf76d27a2009-05-28 01:53:07 +0000582# elif defined(VGP_amd64_darwin)
583 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
584 return res;
585# elif defined(VGP_x86_darwin)
586 /* ppc32-darwin is the same, but with the args inverted */
587 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
588 offset & 0xffffffff, offset >> 32);
589 return res;
njncda2f0f2009-05-18 02:12:08 +0000590# else
591# error "Unknown platform"
592# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000593}
594
595/* Create and open (-rw------) a tmp file name incorporating said arg.
596 Returns -1 on failure, else the fd of the file. If fullname is
597 non-NULL, the file's name is written into it. The number of bytes
598 written is guaranteed not to exceed 64+strlen(part_of_name). */
599
600Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
601{
602 HChar buf[200];
603 Int n, tries, fd;
604 UInt seed;
605 SysRes sres;
606
607 vg_assert(part_of_name);
608 n = VG_(strlen)(part_of_name);
609 vg_assert(n > 0 && n < 100);
610
611 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
612
613 tries = 0;
614 while (True) {
615 if (tries > 10)
616 return -1;
617 VG_(sprintf)( buf, "/tmp/valgrind_%s_%08x",
618 part_of_name, VG_(random)( &seed ));
619 if (0)
620 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
621
622 sres = VG_(open)(buf,
623 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
624 VKI_S_IRUSR|VKI_S_IWUSR);
njncda2f0f2009-05-18 02:12:08 +0000625 if (sr_isError(sres))
sewardj45f4e7c2005-09-27 19:20:21 +0000626 continue;
627 /* VG_(safe_fd) doesn't return if it fails. */
njncda2f0f2009-05-18 02:12:08 +0000628 fd = VG_(safe_fd)( sr_Res(sres) );
sewardj45f4e7c2005-09-27 19:20:21 +0000629 if (fullname)
630 VG_(strcpy)( fullname, buf );
631 return fd;
632 }
633 /* NOTREACHED */
634}
635
636
njneb8896b2005-06-04 20:03:55 +0000637/* ---------------------------------------------------------------------
njn4bd96bd2009-05-22 00:52:14 +0000638 Socket-related stuff.
njneb8896b2005-06-04 20:03:55 +0000639 ------------------------------------------------------------------ */
640
njn4bd96bd2009-05-22 00:52:14 +0000641#if defined(VGO_aix5)
642struct vki_sockaddr_in;
643#endif
644
njneb8896b2005-06-04 20:03:55 +0000645static
646Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
647
648static
njn4bd96bd2009-05-22 00:52:14 +0000649Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
njneb8896b2005-06-04 20:03:55 +0000650
toma4a4f412005-11-17 12:01:56 +0000651UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000652{
sewardja1c4bfb2005-10-18 02:15:39 +0000653# if defined(VG_BIGENDIAN)
654 return x;
655# else
njneb8896b2005-06-04 20:03:55 +0000656 return
657 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
658 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000659# endif
njneb8896b2005-06-04 20:03:55 +0000660}
661
toma4a4f412005-11-17 12:01:56 +0000662UInt VG_(ntohl) ( UInt x )
663{
664# if defined(VG_BIGENDIAN)
665 return x;
666# else
667 return
668 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
669 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
670# endif
671}
672
673UShort VG_(htons) ( UShort x )
674{
675# if defined(VG_BIGENDIAN)
676 return x;
677# else
678 return
679 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
680# endif
681}
682
683UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000684{
sewardja1c4bfb2005-10-18 02:15:39 +0000685# if defined(VG_BIGENDIAN)
686 return x;
687# else
njneb8896b2005-06-04 20:03:55 +0000688 return
689 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000690# endif
njneb8896b2005-06-04 20:03:55 +0000691}
692
693
694/* The main function.
695
696 Supplied string contains either an ip address "192.168.0.1" or
697 an ip address and port pair, "192.168.0.1:1500". Parse these,
698 and return:
699 -1 if there is a parse error
700 -2 if no parse error, but specified host:port cannot be opened
701 the relevant file (socket) descriptor, otherwise.
702 is used.
703*/
704Int VG_(connect_via_socket)( UChar* str )
705{
njnf76d27a2009-05-28 01:53:07 +0000706# if defined(VGO_linux) || defined(VGO_darwin)
njneb8896b2005-06-04 20:03:55 +0000707 Int sd, res;
708 struct vki_sockaddr_in servAddr;
709 UInt ip = 0;
710 UShort port = VG_CLO_DEFAULT_LOGPORT;
711 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
712 if (!ok)
713 return -1;
714
715 //if (0)
716 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
717 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
718 // (ip >> 8) & 0xFF, ip & 0xFF,
719 // (UInt)port );
720
721 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +0000722 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
723 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +0000724
725 /* create socket */
njn0cd5d972009-05-22 02:00:27 +0000726 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
njneb8896b2005-06-04 20:03:55 +0000727 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000728 /* this shouldn't happen ... nevertheless */
729 return -2;
njneb8896b2005-06-04 20:03:55 +0000730 }
sewardja1c4bfb2005-10-18 02:15:39 +0000731
njneb8896b2005-06-04 20:03:55 +0000732 /* connect to server */
njnb143b272009-05-22 00:47:08 +0000733 res = my_connect(sd, &servAddr, sizeof(servAddr));
njneb8896b2005-06-04 20:03:55 +0000734 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +0000735 /* connection failed */
736 return -2;
njneb8896b2005-06-04 20:03:55 +0000737 }
738
739 return sd;
njncda2f0f2009-05-18 02:12:08 +0000740
741# elif defined(VGO_aix5)
742 I_die_here;
743
744# else
745# error "Unknown OS"
746# endif
njneb8896b2005-06-04 20:03:55 +0000747}
748
749
750/* Let d = one or more digits. Accept either:
751 d.d.d.d or d.d.d.d:d
752*/
sewardj9a66bb92006-10-17 01:38:13 +0000753static Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
njneb8896b2005-06-04 20:03:55 +0000754{
755# define GET_CH ((*str) ? (*str++) : 0)
756 UInt ipa, i, j, c, any;
757 ipa = 0;
758 for (i = 0; i < 4; i++) {
759 j = 0;
760 any = 0;
761 while (1) {
762 c = GET_CH;
763 if (c < '0' || c > '9') break;
764 j = 10 * j + (int)(c - '0');
765 any = 1;
766 }
767 if (any == 0 || j > 255) goto syntaxerr;
768 ipa = (ipa << 8) + j;
769 if (i <= 2 && c != '.') goto syntaxerr;
770 }
771 if (c == 0 || c == ':')
772 *ip_addr = ipa;
773 if (c == 0) goto ok;
774 if (c != ':') goto syntaxerr;
775 j = 0;
776 any = 0;
777 while (1) {
778 c = GET_CH;
779 if (c < '0' || c > '9') break;
780 j = j * 10 + (int)(c - '0');
781 any = 1;
782 if (j > 65535) goto syntaxerr;
783 }
784 if (any == 0 || c != 0) goto syntaxerr;
785 if (j < 1024) goto syntaxerr;
786 *port = (UShort)j;
787 ok:
788 return 1;
789 syntaxerr:
790 return 0;
791# undef GET_CH
792}
793
njn0cd5d972009-05-22 02:00:27 +0000794// GrP fixme safe_fd?
795Int VG_(socket) ( Int domain, Int type, Int protocol )
njneb8896b2005-06-04 20:03:55 +0000796{
njncda2f0f2009-05-18 02:12:08 +0000797# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
798 || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000799 SysRes res;
800 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000801 args[0] = domain;
802 args[1] = type;
803 args[2] = protocol;
804 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +0000805 return sr_isError(res) ? -1 : sr_Res(res);
cerion85665ca2005-06-20 15:51:07 +0000806
sewardj59570ff2010-01-01 11:59:33 +0000807# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
sewardj1e866562005-09-28 19:58:58 +0000808 SysRes res;
809 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
njncda2f0f2009-05-18 02:12:08 +0000810 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000811
njncda2f0f2009-05-18 02:12:08 +0000812# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj9a66bb92006-10-17 01:38:13 +0000813 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000814
njnf76d27a2009-05-28 01:53:07 +0000815# elif defined(VGO_darwin)
816 SysRes res;
817 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
818 if (!sr_isError(res)) {
819 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
820 Int optval = 1;
821 SysRes res2;
822 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
823 VKI_SO_NOSIGPIPE, (UWord)&optval,
824 sizeof(optval));
825 // ignore setsockopt() error
826 }
827 return sr_isError(res) ? -1 : sr_Res(res);
828
njncda2f0f2009-05-18 02:12:08 +0000829# else
830# error "Unknown arch"
831# endif
njneb8896b2005-06-04 20:03:55 +0000832}
833
njncda2f0f2009-05-18 02:12:08 +0000834
njneb8896b2005-06-04 20:03:55 +0000835static
njn4bd96bd2009-05-22 00:52:14 +0000836Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
njneb8896b2005-06-04 20:03:55 +0000837{
njncda2f0f2009-05-18 02:12:08 +0000838# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
839 || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000840 SysRes res;
841 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000842 args[0] = sockfd;
843 args[1] = (UWord)serv_addr;
844 args[2] = addrlen;
845 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +0000846 return sr_isError(res) ? -1 : sr_Res(res);
cerion85665ca2005-06-20 15:51:07 +0000847
sewardj59570ff2010-01-01 11:59:33 +0000848# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
sewardj1e866562005-09-28 19:58:58 +0000849 SysRes res;
850 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
njncda2f0f2009-05-18 02:12:08 +0000851 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000852
njncda2f0f2009-05-18 02:12:08 +0000853# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj9a66bb92006-10-17 01:38:13 +0000854 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000855
njnf76d27a2009-05-28 01:53:07 +0000856# elif defined(VGO_darwin)
857 SysRes res;
858 res = VG_(do_syscall3)(__NR_connect_nocancel,
859 sockfd, (UWord)serv_addr, addrlen);
860 return sr_isError(res) ? -1 : sr_Res(res);
861
njncda2f0f2009-05-18 02:12:08 +0000862# else
863# error "Unknown arch"
864# endif
njneb8896b2005-06-04 20:03:55 +0000865}
866
867Int VG_(write_socket)( Int sd, void *msg, Int count )
868{
njneb8896b2005-06-04 20:03:55 +0000869 /* This is actually send(). */
njnf76d27a2009-05-28 01:53:07 +0000870
871 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
sewardj9a66bb92006-10-17 01:38:13 +0000872 errors on stream oriented sockets when the other end breaks the
njnf76d27a2009-05-28 01:53:07 +0000873 connection. The EPIPE error is still returned.
874
875 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
876 SIGPIPE */
njneb8896b2005-06-04 20:03:55 +0000877
njncda2f0f2009-05-18 02:12:08 +0000878# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
879 || defined(VGP_ppc64_linux)
sewardja8d8e232005-06-07 20:04:56 +0000880 SysRes res;
881 UWord args[4];
njneb8896b2005-06-04 20:03:55 +0000882 args[0] = sd;
883 args[1] = (UWord)msg;
884 args[2] = count;
sewardj9a66bb92006-10-17 01:38:13 +0000885 args[3] = VKI_MSG_NOSIGNAL;
njneb8896b2005-06-04 20:03:55 +0000886 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +0000887 return sr_isError(res) ? -1 : sr_Res(res);
cerion85665ca2005-06-20 15:51:07 +0000888
sewardj59570ff2010-01-01 11:59:33 +0000889# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
sewardj1e866562005-09-28 19:58:58 +0000890 SysRes res;
sewardj9a66bb92006-10-17 01:38:13 +0000891 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
892 count, VKI_MSG_NOSIGNAL, 0,0);
njncda2f0f2009-05-18 02:12:08 +0000893 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000894
njncda2f0f2009-05-18 02:12:08 +0000895# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj9a66bb92006-10-17 01:38:13 +0000896 I_die_here;
cerion85665ca2005-06-20 15:51:07 +0000897
njnf76d27a2009-05-28 01:53:07 +0000898# elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
899 SysRes res;
900 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
901 return sr_isError(res) ? -1 : sr_Res(res);
902
njncda2f0f2009-05-18 02:12:08 +0000903# else
904# error "Unknown platform"
905# endif
njneb8896b2005-06-04 20:03:55 +0000906}
907
908Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
909{
njncda2f0f2009-05-18 02:12:08 +0000910# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
911 || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000912 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000913 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000914 args[0] = sd;
915 args[1] = (UWord)name;
916 args[2] = (UWord)namelen;
917 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +0000918 return sr_isError(res) ? -1 : sr_Res(res);
sewardja5c9e4a2005-06-09 13:21:58 +0000919
sewardj59570ff2010-01-01 11:59:33 +0000920# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000921 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000922 res = VG_(do_syscall3)( __NR_getsockname,
923 (UWord)sd, (UWord)name, (UWord)namelen );
njncda2f0f2009-05-18 02:12:08 +0000924 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000925
njncda2f0f2009-05-18 02:12:08 +0000926# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj9a66bb92006-10-17 01:38:13 +0000927 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000928
njnf76d27a2009-05-28 01:53:07 +0000929# elif defined(VGO_darwin)
930 SysRes res;
931 res = VG_(do_syscall3)( __NR_getsockname,
932 (UWord)sd, (UWord)name, (UWord)namelen );
933 return sr_isError(res) ? -1 : sr_Res(res);
934
njncda2f0f2009-05-18 02:12:08 +0000935# else
936# error "Unknown platform"
937# endif
njneb8896b2005-06-04 20:03:55 +0000938}
939
940Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
941{
njncda2f0f2009-05-18 02:12:08 +0000942# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
943 || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000944 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000945 UWord args[3];
njneb8896b2005-06-04 20:03:55 +0000946 args[0] = sd;
947 args[1] = (UWord)name;
948 args[2] = (UWord)namelen;
949 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +0000950 return sr_isError(res) ? -1 : sr_Res(res);
sewardja5c9e4a2005-06-09 13:21:58 +0000951
sewardj59570ff2010-01-01 11:59:33 +0000952# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000953 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000954 res = VG_(do_syscall3)( __NR_getpeername,
955 (UWord)sd, (UWord)name, (UWord)namelen );
njncda2f0f2009-05-18 02:12:08 +0000956 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000957
njncda2f0f2009-05-18 02:12:08 +0000958# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj9a66bb92006-10-17 01:38:13 +0000959 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000960
njnf76d27a2009-05-28 01:53:07 +0000961# elif defined(VGO_darwin)
962 SysRes res;
963 res = VG_(do_syscall3)( __NR_getpeername,
964 (UWord)sd, (UWord)name, (UWord)namelen );
965 return sr_isError(res) ? -1 : sr_Res(res);
966
njncda2f0f2009-05-18 02:12:08 +0000967# else
968# error "Unknown platform"
969# endif
njneb8896b2005-06-04 20:03:55 +0000970}
971
972Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
973 Int *optlen)
974{
njncda2f0f2009-05-18 02:12:08 +0000975# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
976 || defined(VGP_ppc64_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000977 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +0000978 UWord args[5];
njneb8896b2005-06-04 20:03:55 +0000979 args[0] = sd;
980 args[1] = level;
981 args[2] = optname;
982 args[3] = (UWord)optval;
983 args[4] = (UWord)optlen;
984 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +0000985 return sr_isError(res) ? -1 : sr_Res(res);
sewardja5c9e4a2005-06-09 13:21:58 +0000986
sewardj59570ff2010-01-01 11:59:33 +0000987# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
sewardj9a66bb92006-10-17 01:38:13 +0000988 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +0000989 res = VG_(do_syscall5)( __NR_getsockopt,
990 (UWord)sd, (UWord)level, (UWord)optname,
991 (UWord)optval, (UWord)optlen );
njncda2f0f2009-05-18 02:12:08 +0000992 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000993
njncda2f0f2009-05-18 02:12:08 +0000994# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj9a66bb92006-10-17 01:38:13 +0000995 I_die_here;
sewardja5c9e4a2005-06-09 13:21:58 +0000996
njnf76d27a2009-05-28 01:53:07 +0000997# elif defined(VGO_darwin)
998 SysRes res;
999 res = VG_(do_syscall5)( __NR_getsockopt,
1000 (UWord)sd, (UWord)level, (UWord)optname,
1001 (UWord)optval, (UWord)optlen );
1002 return sr_isError(res) ? -1 : sr_Res(res);
1003
njncda2f0f2009-05-18 02:12:08 +00001004# else
1005# error "Unknown platform"
1006# endif
njneb8896b2005-06-04 20:03:55 +00001007}
1008
1009
njnf76d27a2009-05-28 01:53:07 +00001010Char *VG_(basename)(const Char *path)
1011{
1012 static Char buf[VKI_PATH_MAX];
1013
1014 const Char *p, *end;
1015
1016 if (path == NULL ||
1017 0 == VG_(strcmp)(path, ""))
1018 {
1019 return ".";
1020 }
1021
1022 p = path + VG_(strlen)(path);
1023 while (p > path && *p == '/') {
1024 // skip all trailing '/'
1025 p--;
1026 }
1027
1028 if (p == path && *p == '/') return "/"; // all slashes
1029
1030 end = p;
1031
1032 while (p > path && *p != '/') {
1033 // now skip non '/'
1034 p--;
1035 }
1036
1037 if (*p == '/') p++;
1038
1039 VG_(strncpy)(buf, p, end-p+1);
1040 buf[end-p+1] = '\0';
1041
1042 return buf;
1043}
1044
1045
1046Char *VG_(dirname)(const Char *path)
1047{
1048 static Char buf[VKI_PATH_MAX];
1049
1050 const Char *p;
1051
1052 if (path == NULL ||
1053 0 == VG_(strcmp)(path, "") ||
1054 0 == VG_(strcmp)(path, "/"))
1055 {
1056 return ".";
1057 }
1058
1059 p = path + VG_(strlen)(path);
1060 while (p > path && *p == '/') {
1061 // skip all trailing '/'
1062 p--;
1063 }
1064
1065 while (p > path && *p != '/') {
1066 // now skip non '/'
1067 p--;
1068 }
1069
1070 if (p == path) {
1071 if (*p == '/') return "/"; // all slashes
1072 else return "."; // no slashes
1073 }
1074
1075 while (p > path && *p == '/') {
1076 // skip '/' again
1077 p--;
1078 }
1079
1080 VG_(strncpy)(buf, path, p-path+1);
1081 buf[p-path+1] = '\0';
1082
1083 return buf;
1084}
1085
1086
njneb8896b2005-06-04 20:03:55 +00001087/*--------------------------------------------------------------------*/
1088/*--- end ---*/
1089/*--------------------------------------------------------------------*/