blob: 68fc43438597e051277e41e96951fd451629605d [file] [log] [blame]
florian58946e92014-09-27 13:29:09 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
njneb8896b2005-06-04 20:03:55 +00002
3/*--------------------------------------------------------------------*/
4/*--- File- and socket-related libc stuff. m_libcfile.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
sewardjb3a1e4b2015-08-21 11:32:26 +000011 Copyright (C) 2000-2015 Julian Seward
njneb8896b2005-06-04 20:03:55 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
njnc7561b92005-06-19 01:24:32 +000032#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
sewardj9a66bb92006-10-17 01:38:13 +000034#include "pub_core_vkiscnums.h"
sewardj26b87282006-10-17 12:49:31 +000035#include "pub_core_debuglog.h"
njneb8896b2005-06-04 20:03:55 +000036#include "pub_core_libcbase.h"
37#include "pub_core_libcassert.h"
38#include "pub_core_libcfile.h"
sewardjfdf91b42005-09-28 00:53:09 +000039#include "pub_core_libcprint.h" // VG_(sprintf)
sewardj45f4e7c2005-09-27 19:20:21 +000040#include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
sewardjfdf91b42005-09-28 00:53:09 +000041#include "pub_core_clientstate.h" // VG_(fd_hard_limit)
florian58946e92014-09-27 13:29:09 +000042#include "pub_core_mallocfree.h" // VG_(realloc)
njn9abd6082005-06-17 21:31:45 +000043#include "pub_core_syscall.h"
njneb8896b2005-06-04 20:03:55 +000044
njnf76d27a2009-05-28 01:53:07 +000045/* IMPORTANT: on Darwin it is essential to use the _nocancel versions
46 of syscalls rather than the vanilla version, if a _nocancel version
47 is available. See docs/internals/Darwin-notes.txt for the reason
48 why. */
49
njneb8896b2005-06-04 20:03:55 +000050/* ---------------------------------------------------------------------
51 File stuff
52 ------------------------------------------------------------------ */
53
njneb8896b2005-06-04 20:03:55 +000054/* Move an fd into the Valgrind-safe range */
55Int VG_(safe_fd)(Int oldfd)
56{
57 Int newfd;
58
59 vg_assert(VG_(fd_hard_limit) != -1);
60
61 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
62 if (newfd != -1)
63 VG_(close)(oldfd);
64
sewardj9a66bb92006-10-17 01:38:13 +000065 /* Set the close-on-exec flag for this fd. */
njneb8896b2005-06-04 20:03:55 +000066 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
67
68 vg_assert(newfd >= VG_(fd_hard_limit));
69 return newfd;
70}
71
njnae7359b2005-06-19 21:10:42 +000072/* Given a file descriptor, attempt to deduce its filename. To do
73 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
floriana175ffb2014-10-14 21:01:33 +000074 or if it doesn't exist, we return False.
75 Upon successful completion *result contains the filename. The
76 filename will be overwritten with the next invocation so callers
77 need to copy the filename if needed. *result is NULL if the filename
78 cannot be deduced. */
florian3130eab2014-11-14 19:25:08 +000079Bool VG_(resolve_filename) ( Int fd, const HChar** result )
njnae7359b2005-06-19 21:10:42 +000080{
sewardj8eb8bab2015-07-21 14:44:28 +000081# if defined(VGO_linux) || defined(VGO_solaris)
floriana175ffb2014-10-14 21:01:33 +000082 static HChar *buf = NULL;
83 static SizeT bufsiz = 0;
84
85 if (buf == NULL) { // first time
86 bufsiz = 500;
87 buf = VG_(malloc)("resolve_filename", bufsiz);
88 }
89
90 HChar tmp[64]; // large enough
sewardj8eb8bab2015-07-21 14:44:28 +000091 {
92# if defined(VGO_linux)
93 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
94# elif defined(VGO_solaris)
95 VG_(sprintf)(tmp, "/proc/self/path/%d", fd);
96# endif
97 }
floriana175ffb2014-10-14 21:01:33 +000098
99 while (42) {
100 SSizeT res = VG_(readlink)(tmp, buf, bufsiz);
101 if (res < 0) break;
102 if (res == bufsiz) { // buffer too small; increase and retry
103 bufsiz += 500;
104 buf = VG_(realloc)("resolve_filename", buf, bufsiz);
105 continue;
106 }
107 vg_assert(bufsiz > res); // paranoia
108 if (buf[0] != '/') break;
109
110 buf[res] = '\0';
111 *result = buf;
njnf845f8f2005-06-23 02:26:47 +0000112 return True;
floriana175ffb2014-10-14 21:01:33 +0000113 }
114 // Failure
115 *result = NULL;
116 return False;
njndad944a2009-05-04 05:55:46 +0000117
njnf76d27a2009-05-28 01:53:07 +0000118# elif defined(VGO_darwin)
119 HChar tmp[VKI_MAXPATHLEN+1];
120 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
floriana175ffb2014-10-14 21:01:33 +0000121 static HChar *buf = NULL;
122
123 if (buf == NULL)
124 buf = VG_(malloc)("resolve_filename", VKI_MAXPATHLEN+1);
125 VG_(strcpy)( buf, tmp );
126
127 *result = buf;
128 if (buf[0] == '/') return True;
njnf76d27a2009-05-28 01:53:07 +0000129 }
floriana175ffb2014-10-14 21:01:33 +0000130 // Failure
131 *result = NULL;
njnf76d27a2009-05-28 01:53:07 +0000132 return False;
133
njn81b975c2009-04-28 05:35:53 +0000134# else
njndad944a2009-05-04 05:55:46 +0000135# error Unknown OS
njn81b975c2009-04-28 05:35:53 +0000136# endif
njnae7359b2005-06-19 21:10:42 +0000137}
138
florian19f91bb2012-11-10 22:29:54 +0000139SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
sewardj112711a2015-04-10 12:30:09 +0000140{
141# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
philippe0eb0d5a2014-02-11 23:50:16 +0000142 /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
143 SysRes res = VG_(do_syscall4)(__NR_mknodat,
144 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
145# elif defined(VGO_linux) || defined(VGO_darwin)
sewardj3b290482011-05-06 21:02:55 +0000146 SysRes res = VG_(do_syscall3)(__NR_mknod,
147 (UWord)pathname, mode, dev);
sewardj8eb8bab2015-07-21 14:44:28 +0000148# elif defined(VGO_solaris)
149 SysRes res = VG_(do_syscall4)(__NR_mknodat,
150 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
sewardj3b290482011-05-06 21:02:55 +0000151# else
152# error Unknown OS
153# endif
154 return res;
155}
156
florian19f91bb2012-11-10 22:29:54 +0000157SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
sewardjf0c12502014-01-12 12:54:00 +0000158{
sewardj112711a2015-04-10 12:30:09 +0000159# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardjf0c12502014-01-12 12:54:00 +0000160 /* ARM64 wants to use __NR_openat rather than __NR_open. */
161 SysRes res = VG_(do_syscall4)(__NR_openat,
162 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
163# elif defined(VGO_linux)
njnf76d27a2009-05-28 01:53:07 +0000164 SysRes res = VG_(do_syscall3)(__NR_open,
165 (UWord)pathname, flags, mode);
166# elif defined(VGO_darwin)
167 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
168 (UWord)pathname, flags, mode);
sewardj8eb8bab2015-07-21 14:44:28 +0000169# elif defined(VGO_solaris)
170 SysRes res = VG_(do_syscall4)(__NR_openat,
171 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
njnf76d27a2009-05-28 01:53:07 +0000172# else
173# error Unknown OS
174# endif
sewardj92645592005-07-23 09:18:34 +0000175 return res;
njneb8896b2005-06-04 20:03:55 +0000176}
177
florian19f91bb2012-11-10 22:29:54 +0000178Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
sewardj3b290482011-05-06 21:02:55 +0000179{
180 SysRes sr;
181 sr = VG_(open) (pathname, flags, mode);
182 if (sr_isError (sr))
183 return -1;
184 else
185 return sr_Res (sr);
186}
187
njneb8896b2005-06-04 20:03:55 +0000188void VG_(close) ( Int fd )
189{
njnf76d27a2009-05-28 01:53:07 +0000190 /* Hmm. Return value is not checked. That's uncool. */
sewardj8eb8bab2015-07-21 14:44:28 +0000191# if defined(VGO_linux) || defined(VGO_solaris)
sewardja8d8e232005-06-07 20:04:56 +0000192 (void)VG_(do_syscall1)(__NR_close, fd);
njnf76d27a2009-05-28 01:53:07 +0000193# elif defined(VGO_darwin)
194 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
195# else
196# error Unknown OS
197# endif
njneb8896b2005-06-04 20:03:55 +0000198}
199
200Int VG_(read) ( Int fd, void* buf, Int count)
201{
sewardj9a66bb92006-10-17 01:38:13 +0000202 Int ret;
sewardj8eb8bab2015-07-21 14:44:28 +0000203# if defined(VGO_linux) || defined(VGO_solaris)
sewardja8d8e232005-06-07 20:04:56 +0000204 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
njnf76d27a2009-05-28 01:53:07 +0000205# elif defined(VGO_darwin)
206 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
207# else
208# error Unknown OS
209# endif
njncda2f0f2009-05-18 02:12:08 +0000210 if (sr_isError(res)) {
211 ret = - (Int)(Word)sr_Err(res);
sewardj9a66bb92006-10-17 01:38:13 +0000212 vg_assert(ret < 0);
213 } else {
njncda2f0f2009-05-18 02:12:08 +0000214 ret = (Int)(Word)sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000215 vg_assert(ret >= 0);
216 }
217 return ret;
njneb8896b2005-06-04 20:03:55 +0000218}
219
220Int VG_(write) ( Int fd, const void* buf, Int count)
221{
sewardj9a66bb92006-10-17 01:38:13 +0000222 Int ret;
sewardj8eb8bab2015-07-21 14:44:28 +0000223# if defined(VGO_linux) || defined(VGO_solaris)
sewardja8d8e232005-06-07 20:04:56 +0000224 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
njnf76d27a2009-05-28 01:53:07 +0000225# elif defined(VGO_darwin)
226 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
227# else
228# error "Unknown OS"
229# endif
njncda2f0f2009-05-18 02:12:08 +0000230 if (sr_isError(res)) {
231 ret = - (Int)(Word)sr_Err(res);
sewardj9a66bb92006-10-17 01:38:13 +0000232 vg_assert(ret < 0);
233 } else {
njncda2f0f2009-05-18 02:12:08 +0000234 ret = (Int)(Word)sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +0000235 vg_assert(ret >= 0);
236 }
237 return ret;
njneb8896b2005-06-04 20:03:55 +0000238}
239
njncda2f0f2009-05-18 02:12:08 +0000240
njneb8896b2005-06-04 20:03:55 +0000241Int VG_(pipe) ( Int fd[2] )
242{
petarj4df0bfc2013-02-27 23:17:33 +0000243# if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
sewardj5db15402012-06-07 09:13:21 +0000244 /* __NR_pipe has a strange return convention on mips32-linux. */
petarj4df0bfc2013-02-27 23:17:33 +0000245 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
sewardj5db15402012-06-07 09:13:21 +0000246 if (!sr_isError(res)) {
247 fd[0] = (Int)sr_Res(res);
248 fd[1] = (Int)sr_ResEx(res);
249 return 0;
250 } else {
251 return -1;
252 }
sewardj112711a2015-04-10 12:30:09 +0000253# elif defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardjf0c12502014-01-12 12:54:00 +0000254 SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
255 return sr_isError(res) ? -1 : 0;
sewardj5db15402012-06-07 09:13:21 +0000256# elif defined(VGO_linux)
sewardja8d8e232005-06-07 20:04:56 +0000257 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
njncda2f0f2009-05-18 02:12:08 +0000258 return sr_isError(res) ? -1 : 0;
njnf76d27a2009-05-28 01:53:07 +0000259# elif defined(VGO_darwin)
260 /* __NR_pipe is UX64, so produces a double-word result */
261 SysRes res = VG_(do_syscall0)(__NR_pipe);
262 if (!sr_isError(res)) {
263 fd[0] = (Int)sr_Res(res);
264 fd[1] = (Int)sr_ResHI(res);
265 }
266 return sr_isError(res) ? -1 : 0;
sewardj8eb8bab2015-07-21 14:44:28 +0000267# elif defined(VGO_solaris)
268# if defined(SOLARIS_NEW_PIPE_SYSCALL)
269 SysRes res = VG_(do_syscall2)(__NR_pipe, (UWord)fd, 0);
270 return sr_isError(res) ? -1 : 0;
271# else
272 SysRes res = VG_(do_syscall0)(__NR_pipe);
273 if (!sr_isError(res)) {
274 fd[0] = (Int)sr_Res(res);
275 fd[1] = (Int)sr_ResHI(res);
276 }
277 return sr_isError(res) ? -1 : 0;
278# endif
njncda2f0f2009-05-18 02:12:08 +0000279# else
280# error "Unknown OS"
281# endif
njneb8896b2005-06-04 20:03:55 +0000282}
283
tomc17c6ef2011-07-13 09:02:14 +0000284Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
njneb8896b2005-06-04 20:03:55 +0000285{
sewardj6e9de462011-06-28 07:25:29 +0000286# if defined(VGO_linux) || defined(VGP_amd64_darwin)
tomc17c6ef2011-07-13 09:02:14 +0000287# if defined(__NR__llseek)
288 Off64T result;
289 SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
290 offset >> 32, offset & 0xffffffff,
tomf9b1d732011-07-13 10:05:24 +0000291 (UWord)&result, whence);
tomc17c6ef2011-07-13 09:02:14 +0000292 return sr_isError(res) ? (-1) : result;
293# else
sewardja8d8e232005-06-07 20:04:56 +0000294 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
tomc17c6ef2011-07-13 09:02:14 +0000295 vg_assert(sizeof(Off64T) == sizeof(Word));
296 return sr_isError(res) ? (-1) : sr_Res(res);
297# endif
njnf76d27a2009-05-28 01:53:07 +0000298# elif defined(VGP_x86_darwin)
299 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
300 offset & 0xffffffff, offset >> 32, whence);
tomc17c6ef2011-07-13 09:02:14 +0000301 return sr_isError(res) ? (-1) : sr_Res(res);
sewardj8eb8bab2015-07-21 14:44:28 +0000302# elif defined(VGP_x86_solaris)
303 SysRes res = VG_(do_syscall4)(__NR_llseek, fd,
304 offset & 0xffffffff, offset >> 32, whence);
305 return sr_isError(res) ? (-1) : ((ULong)sr_ResHI(res) << 32 | sr_Res(res));
306# elif defined(VGP_amd64_solaris)
307 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
308 vg_assert(sizeof(Off64T) == sizeof(Word));
309 return sr_isError(res) ? (-1) : sr_Res(res);
njncda2f0f2009-05-18 02:12:08 +0000310# else
311# error "Unknown plat"
312# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000313 /* if you change the error-reporting conventions of this, also
philippe8050bb72012-04-13 23:07:29 +0000314 change all usage points. */
njneb8896b2005-06-04 20:03:55 +0000315}
316
sewardjec61b652008-08-19 07:03:04 +0000317
318/* stat/fstat support. It's uggerly. We have impedance-match into a
319 'struct vg_stat' in order to have a single structure that callers
320 can use consistently on all platforms. */
321
322#define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
323 do { \
njn9c20ece2009-05-20 02:02:30 +0000324 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
325 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
326 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
327 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
328 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
329 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
330 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
331 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
332 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
333 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
334 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
335 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
336 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
337 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
338 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
339 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
sewardjec61b652008-08-19 07:03:04 +0000340 } while (0)
341
florian19f91bb2012-11-10 22:29:54 +0000342SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
njneb8896b2005-06-04 20:03:55 +0000343{
sewardjec61b652008-08-19 07:03:04 +0000344 SysRes res;
345 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
njncda2f0f2009-05-18 02:12:08 +0000346
njnf76d27a2009-05-28 01:53:07 +0000347# if defined(VGO_linux) || defined(VGO_darwin)
njncda2f0f2009-05-18 02:12:08 +0000348 /* First try with stat64. If that doesn't work out, fall back to
349 the vanilla version. */
sewardjec61b652008-08-19 07:03:04 +0000350# if defined(__NR_stat64)
351 { struct vki_stat64 buf64;
352 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
njncda2f0f2009-05-18 02:12:08 +0000353 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
sewardjec61b652008-08-19 07:03:04 +0000354 /* Success, or any failure except ENOSYS */
njncda2f0f2009-05-18 02:12:08 +0000355 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000356 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
357 return res;
358 }
359 }
njncda2f0f2009-05-18 02:12:08 +0000360# endif /* defined(__NR_stat64) */
sewardjf0c12502014-01-12 12:54:00 +0000361 /* This is the fallback ("vanilla version"). */
sewardjec61b652008-08-19 07:03:04 +0000362 { struct vki_stat buf;
sewardj112711a2015-04-10 12:30:09 +0000363# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardjf0c12502014-01-12 12:54:00 +0000364 res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
365 (UWord)file_name, (UWord)&buf);
366# else
sewardjec61b652008-08-19 07:03:04 +0000367 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
sewardjf0c12502014-01-12 12:54:00 +0000368# endif
njncda2f0f2009-05-18 02:12:08 +0000369 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000370 TRANSLATE_TO_vg_stat(vgbuf, &buf);
371 return res;
372 }
sewardj8eb8bab2015-07-21 14:44:28 +0000373# elif defined(VGO_solaris)
374 {
375# if defined(VGP_x86_solaris)
376 struct vki_stat64 buf64;
377 res = VG_(do_syscall4)(__NR_fstatat64, VKI_AT_FDCWD, (UWord)file_name,
378 (UWord)&buf64, 0);
379# elif defined(VGP_amd64_solaris)
380 struct vki_stat buf64;
381 res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name,
382 (UWord)&buf64, 0);
383# else
384# error "Unknown platform"
385# endif
386 if (!sr_isError(res))
387 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
388 return res;
389 }
sewardj9a66bb92006-10-17 01:38:13 +0000390# else
391# error Unknown OS
392# endif
njneb8896b2005-06-04 20:03:55 +0000393}
394
sewardjec61b652008-08-19 07:03:04 +0000395Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
njneb8896b2005-06-04 20:03:55 +0000396{
sewardjec61b652008-08-19 07:03:04 +0000397 SysRes res;
398 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
njncda2f0f2009-05-18 02:12:08 +0000399
sewardj8eb8bab2015-07-21 14:44:28 +0000400# if defined(VGO_linux) || defined(VGO_darwin)
njncda2f0f2009-05-18 02:12:08 +0000401 /* First try with fstat64. If that doesn't work out, fall back to
402 the vanilla version. */
sewardjec61b652008-08-19 07:03:04 +0000403# if defined(__NR_fstat64)
404 { struct vki_stat64 buf64;
405 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
njncda2f0f2009-05-18 02:12:08 +0000406 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
sewardjec61b652008-08-19 07:03:04 +0000407 /* Success, or any failure except ENOSYS */
njncda2f0f2009-05-18 02:12:08 +0000408 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000409 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
njncda2f0f2009-05-18 02:12:08 +0000410 return sr_isError(res) ? (-1) : 0;
sewardjec61b652008-08-19 07:03:04 +0000411 }
412 }
413# endif /* if defined(__NR_fstat64) */
414 { struct vki_stat buf;
415 res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf);
njncda2f0f2009-05-18 02:12:08 +0000416 if (!sr_isError(res))
sewardjec61b652008-08-19 07:03:04 +0000417 TRANSLATE_TO_vg_stat(vgbuf, &buf);
njncda2f0f2009-05-18 02:12:08 +0000418 return sr_isError(res) ? (-1) : 0;
sewardjec61b652008-08-19 07:03:04 +0000419 }
sewardj8eb8bab2015-07-21 14:44:28 +0000420# elif defined(VGO_solaris)
421 {
422# if defined(VGP_x86_solaris)
423 struct vki_stat64 buf64;
424 res = VG_(do_syscall4)(__NR_fstatat64, (UWord)fd, 0, (UWord)&buf64, 0);
425# elif defined(VGP_amd64_solaris)
426 struct vki_stat buf64;
427 res = VG_(do_syscall4)(__NR_fstatat, (UWord)fd, 0, (UWord)&buf64, 0);
428# else
429# error "Unknown platform"
430# endif
431 if (!sr_isError(res))
432 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
433 return sr_isError(res) ? (-1) : 0;
434 }
sewardj9a66bb92006-10-17 01:38:13 +0000435# else
436# error Unknown OS
437# endif
njneb8896b2005-06-04 20:03:55 +0000438}
439
sewardjec61b652008-08-19 07:03:04 +0000440#undef TRANSLATE_TO_vg_stat
441
442
443Long VG_(fsize) ( Int fd )
njneb8896b2005-06-04 20:03:55 +0000444{
sewardjec61b652008-08-19 07:03:04 +0000445 struct vg_stat buf;
446 Int res = VG_(fstat)( fd, &buf );
njn9c20ece2009-05-20 02:02:30 +0000447 return (res == -1) ? (-1LL) : buf.size;
sewardj45f4e7c2005-09-27 19:20:21 +0000448}
449
tomb7c2f9d2014-05-22 08:57:06 +0000450SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
451{
452 SysRes res;
453#if defined(VGO_linux)
454 res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
455 attr_value, attr_value_len);
456#else
457 res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
458#endif
459 return res;
460}
461
njn63e5e6e2009-05-20 04:22:42 +0000462Bool VG_(is_dir) ( const HChar* f )
njn73750612005-10-14 03:11:30 +0000463{
sewardjec61b652008-08-19 07:03:04 +0000464 struct vg_stat buf;
sewardj9a66bb92006-10-17 01:38:13 +0000465 SysRes res = VG_(stat)(f, &buf);
njncda2f0f2009-05-18 02:12:08 +0000466 return sr_isError(res) ? False
njn9c20ece2009-05-20 02:02:30 +0000467 : VKI_S_ISDIR(buf.mode) ? True : False;
njn73750612005-10-14 03:11:30 +0000468}
469
sewardj45f4e7c2005-09-27 19:20:21 +0000470SysRes VG_(dup) ( Int oldfd )
471{
sewardj8eb8bab2015-07-21 14:44:28 +0000472# if defined(VGO_linux) || defined(VGO_darwin)
sewardj45f4e7c2005-09-27 19:20:21 +0000473 return VG_(do_syscall1)(__NR_dup, oldfd);
sewardj8eb8bab2015-07-21 14:44:28 +0000474# elif defined(VGO_solaris)
475 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUPFD, 0);
476# else
477# error Unknown OS
478# endif
njneb8896b2005-06-04 20:03:55 +0000479}
480
njnfad98372008-10-12 19:53:28 +0000481SysRes VG_(dup2) ( Int oldfd, Int newfd )
482{
sewardj6e9de462011-06-28 07:25:29 +0000483# if defined(VGO_linux) || defined(VGO_darwin)
njnfad98372008-10-12 19:53:28 +0000484 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
sewardj8eb8bab2015-07-21 14:44:28 +0000485# elif defined(VGO_solaris)
486 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
sewardj485ce162008-10-22 00:57:29 +0000487# else
488# error Unknown OS
489# endif
njnfad98372008-10-12 19:53:28 +0000490}
491
njn327fe8a2005-06-12 02:49:35 +0000492/* Returns -1 on error. */
njnbb7af3f2009-05-22 07:08:12 +0000493Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
njn327fe8a2005-06-12 02:49:35 +0000494{
sewardj8eb8bab2015-07-21 14:44:28 +0000495# if defined(VGO_linux) || defined(VGO_solaris)
njn327fe8a2005-06-12 02:49:35 +0000496 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
njnf76d27a2009-05-28 01:53:07 +0000497# elif defined(VGO_darwin)
498 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
499# else
500# error "Unknown OS"
501# endif
njncda2f0f2009-05-18 02:12:08 +0000502 return sr_isError(res) ? -1 : sr_Res(res);
njn327fe8a2005-06-12 02:49:35 +0000503}
504
florian19f91bb2012-11-10 22:29:54 +0000505Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
njneb8896b2005-06-04 20:03:55 +0000506{
sewardj112711a2015-04-10 12:30:09 +0000507# if defined(VGP_tilegx_linux)
florian4ac36212015-05-13 21:26:46 +0000508 SysRes res = VG_(do_syscall3)(__NR_renameat, VKI_AT_FDCWD,
sewardj112711a2015-04-10 12:30:09 +0000509 (UWord)old_name, (UWord)new_name);
sewardj8eb8bab2015-07-21 14:44:28 +0000510# elif defined(VGO_linux) || defined(VGO_darwin)
sewardja8d8e232005-06-07 20:04:56 +0000511 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
sewardj8eb8bab2015-07-21 14:44:28 +0000512# elif defined(VGO_solaris)
513 SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
514 VKI_AT_FDCWD, (UWord)new_name);
515# else
516# error "Unknown OS"
sewardj112711a2015-04-10 12:30:09 +0000517# endif
njncda2f0f2009-05-18 02:12:08 +0000518 return sr_isError(res) ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000519}
520
florian19f91bb2012-11-10 22:29:54 +0000521Int VG_(unlink) ( const HChar* file_name )
njneb8896b2005-06-04 20:03:55 +0000522{
sewardj112711a2015-04-10 12:30:09 +0000523# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardjf0c12502014-01-12 12:54:00 +0000524 SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
525 (UWord)file_name);
sewardj8eb8bab2015-07-21 14:44:28 +0000526# elif defined(VGO_linux) || defined(VGO_darwin)
sewardja8d8e232005-06-07 20:04:56 +0000527 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
sewardj8eb8bab2015-07-21 14:44:28 +0000528# elif defined(VGO_solaris)
529 SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
530 (UWord)file_name, 0);
531# else
532# error "Unknown OS"
sewardjf0c12502014-01-12 12:54:00 +0000533# endif
njncda2f0f2009-05-18 02:12:08 +0000534 return sr_isError(res) ? (-1) : 0;
njneb8896b2005-06-04 20:03:55 +0000535}
536
florian29d82f62014-09-27 17:42:07 +0000537/* The working directory at startup.
538 All that is really needed is to note the cwd at process startup.
539 Hence VG_(record_startup_wd) notes it (in a platform dependent way)
540 and VG_(get_startup_wd) produces the noted value. */
541static HChar *startup_wd;
542static Bool startup_wd_acquired = False;
sewardj198f34f2007-07-09 23:13:07 +0000543
544/* Record the process' working directory at startup. Is intended to
545 be called exactly once, at startup, before the working directory
546 changes. Return True for success, False for failure, so that the
547 caller can bomb out suitably without creating module cycles if
548 there is a problem. */
549Bool VG_(record_startup_wd) ( void )
njneb8896b2005-06-04 20:03:55 +0000550{
sewardj198f34f2007-07-09 23:13:07 +0000551 vg_assert(!startup_wd_acquired);
sewardj8eb8bab2015-07-21 14:44:28 +0000552# if defined(VGO_linux) || defined(VGO_solaris)
sewardj198f34f2007-07-09 23:13:07 +0000553 /* Simple: just ask the kernel */
florian29d82f62014-09-27 17:42:07 +0000554 SysRes res;
555 SizeT szB = 0;
556 do {
557 szB += 500;
558 startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
559 VG_(memset)(startup_wd, 0, szB);
560 res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
561 } while (sr_isError(res));
562
563 vg_assert(startup_wd[szB-1] == 0);
564 startup_wd_acquired = True;
565 return True;
566
sewardj6e9de462011-06-28 07:25:29 +0000567# elif defined(VGO_darwin)
njnf76d27a2009-05-28 01:53:07 +0000568 /* We can't ask the kernel, so instead rely on launcher-*.c to
sewardj198f34f2007-07-09 23:13:07 +0000569 tell us the startup path. Note the env var is keyed to the
570 parent's PID, not ours, since our parent is the launcher
571 process. */
florian29d82f62014-09-27 17:42:07 +0000572 { HChar envvar[100]; // large enough
573 HChar* wd;
sewardj198f34f2007-07-09 23:13:07 +0000574 VG_(memset)(envvar, 0, sizeof(envvar));
575 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
576 (Int)VG_(getppid)());
577 wd = VG_(getenv)( envvar );
florian29d82f62014-09-27 17:42:07 +0000578 if (wd == NULL)
sewardj198f34f2007-07-09 23:13:07 +0000579 return False;
florian29d82f62014-09-27 17:42:07 +0000580 SizeT need = VG_(strlen)(wd) + 1;
581 startup_wd = VG_(malloc)("startup_wd", need);
582 VG_(strcpy)(startup_wd, wd);
sewardj198f34f2007-07-09 23:13:07 +0000583 startup_wd_acquired = True;
584 return True;
585 }
sewardj9a66bb92006-10-17 01:38:13 +0000586# else
587# error Unknown OS
588# endif
njneb8896b2005-06-04 20:03:55 +0000589}
590
florian29d82f62014-09-27 17:42:07 +0000591/* Return the previously acquired startup_wd. */
592const HChar *VG_(get_startup_wd) ( void )
sewardj198f34f2007-07-09 23:13:07 +0000593{
594 vg_assert(startup_wd_acquired);
florian29d82f62014-09-27 17:42:07 +0000595
596 return startup_wd;
sewardj198f34f2007-07-09 23:13:07 +0000597}
598
philippe42545842013-12-05 22:10:55 +0000599SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
sewardj3b290482011-05-06 21:02:55 +0000600{
601 SysRes res;
sewardj112711a2015-04-10 12:30:09 +0000602# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
philippe0eb0d5a2014-02-11 23:50:16 +0000603 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
604 struct vki_timespec timeout_ts;
605 if (timeout >= 0) {
606 timeout_ts.tv_sec = timeout / 1000;
607 timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
608 }
609 res = VG_(do_syscall4)(__NR_ppoll,
610 (UWord)fds, nfds,
611 (UWord)(timeout >= 0 ? &timeout_ts : NULL),
612 (UWord)NULL);
613# elif defined(VGO_linux)
sewardj3b290482011-05-06 21:02:55 +0000614 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
sewardj6caac712012-08-18 06:45:07 +0000615# elif defined(VGO_darwin)
616 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
sewardj8eb8bab2015-07-21 14:44:28 +0000617# elif defined(VGO_solaris)
618 struct vki_timespec ts;
619 struct vki_timespec *tsp;
620
621 if (timeout < 0)
622 tsp = NULL;
623 else {
624 ts.tv_sec = timeout / 1000;
625 ts.tv_nsec = (timeout % 1000) * 1000000;
626 tsp = &ts;
627 }
628
629 res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0);
sewardj6caac712012-08-18 06:45:07 +0000630# else
631# error "Unknown OS"
632# endif
philippe42545842013-12-05 22:10:55 +0000633 return res;
sewardj3b290482011-05-06 21:02:55 +0000634}
635
636
floriana175ffb2014-10-14 21:01:33 +0000637/* Performs the readlink operation and puts the result into 'buf'.
638 Note, that the string in 'buf' is *not* null-terminated. The function
639 returns the number of characters put into 'buf' or -1 if an error
640 occurred. */
641SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
njneb8896b2005-06-04 20:03:55 +0000642{
sewardja8d8e232005-06-07 20:04:56 +0000643 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000644 /* res = readlink( path, buf, bufsiz ); */
sewardj112711a2015-04-10 12:30:09 +0000645# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardjf0c12502014-01-12 12:54:00 +0000646 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
647 (UWord)path, (UWord)buf, bufsiz);
sewardj8eb8bab2015-07-21 14:44:28 +0000648# elif defined(VGO_linux) || defined(VGO_darwin)
njneb8896b2005-06-04 20:03:55 +0000649 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
sewardj8eb8bab2015-07-21 14:44:28 +0000650# elif defined(VGO_solaris)
651 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
652 (UWord)buf, bufsiz);
653# else
654# error "Unknown OS"
sewardjf0c12502014-01-12 12:54:00 +0000655# endif
njncda2f0f2009-05-18 02:12:08 +0000656 return sr_isError(res) ? -1 : sr_Res(res);
njneb8896b2005-06-04 20:03:55 +0000657}
658
sewardj8eb8bab2015-07-21 14:44:28 +0000659#if defined(VGO_linux) || defined(VGO_solaris)
mjw495c6562014-08-29 14:28:30 +0000660Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
njneb8896b2005-06-04 20:03:55 +0000661{
sewardja8d8e232005-06-07 20:04:56 +0000662 SysRes res;
njneb8896b2005-06-04 20:03:55 +0000663 /* res = getdents( fd, dirp, count ); */
sewardj8eb8bab2015-07-21 14:44:28 +0000664# if defined(VGP_amd64_solaris)
665 /* This silently assumes that dirent64 and dirent on amd64 are same, which
666 they should always be. */
667 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
668# else
mjw495c6562014-08-29 14:28:30 +0000669 res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
sewardj8eb8bab2015-07-21 14:44:28 +0000670# endif
njncda2f0f2009-05-18 02:12:08 +0000671 return sr_isError(res) ? -1 : sr_Res(res);
njneb8896b2005-06-04 20:03:55 +0000672}
sewardjb69cd962014-09-01 22:26:18 +0000673#endif
njneb8896b2005-06-04 20:03:55 +0000674
sewardj45f4e7c2005-09-27 19:20:21 +0000675/* Check accessibility of a file. Returns zero for access granted,
676 nonzero otherwise. */
njn63e5e6e2009-05-20 04:22:42 +0000677Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
sewardj45f4e7c2005-09-27 19:20:21 +0000678{
sewardj9a66bb92006-10-17 01:38:13 +0000679# if defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +0000680 /* Very annoyingly, I cannot find any definition for R_OK et al in
681 the kernel interfaces. Therefore I reluctantly resort to
682 hardwiring in these magic numbers that I determined by
683 experimentation. */
njncda2f0f2009-05-18 02:12:08 +0000684# define VKI_R_OK 4
685# define VKI_W_OK 2
686# define VKI_X_OK 1
687# endif
688
sewardj9a66bb92006-10-17 01:38:13 +0000689 UWord w = (irusr ? VKI_R_OK : 0)
690 | (iwusr ? VKI_W_OK : 0)
691 | (ixusr ? VKI_X_OK : 0);
sewardj112711a2015-04-10 12:30:09 +0000692# if defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardjf0c12502014-01-12 12:54:00 +0000693 SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
sewardj8eb8bab2015-07-21 14:44:28 +0000694# elif defined(VGO_linux) || defined(VGO_darwin)
sewardj9a66bb92006-10-17 01:38:13 +0000695 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
sewardj8eb8bab2015-07-21 14:44:28 +0000696# elif defined(VGO_solaris)
697 SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
698 w, 0);
699# else
700# error "Unknown OS"
sewardjf0c12502014-01-12 12:54:00 +0000701# endif
njncda2f0f2009-05-18 02:12:08 +0000702 return sr_isError(res) ? 1 : 0;
703
704# if defined(VGO_linux)
705# undef VKI_R_OK
706# undef VKI_W_OK
707# undef VKI_X_OK
sewardj9a66bb92006-10-17 01:38:13 +0000708# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000709}
710
njn73750612005-10-14 03:11:30 +0000711/*
712 Emulate the normal Unix permissions checking algorithm.
713
714 If owner matches, then use the owner permissions, else
715 if group matches, then use the group permissions, else
716 use other permissions.
717
sewardjc74b3ba2007-11-17 21:11:57 +0000718 Note that we can't deal properly with SUID/SGID. By default
719 (allow_setuid == False), we refuse to run them (otherwise the
720 executable may misbehave if it doesn't have the permissions it
721 thinks it does). However, the caller may indicate that setuid
722 executables are allowed, for example if we are going to exec them
723 but not trace into them (iow, client sys_execve when
724 clo_trace_children == False).
725
726 If VKI_EACCES is returned (iow, permission was refused), then
727 *is_setuid is set to True iff permission was refused because the
728 executable is setuid.
njn73750612005-10-14 03:11:30 +0000729*/
730/* returns: 0 = success, non-0 is failure */
sewardjc74b3ba2007-11-17 21:11:57 +0000731Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
njn63e5e6e2009-05-20 04:22:42 +0000732 const HChar* f, Bool allow_setuid)
njn73750612005-10-14 03:11:30 +0000733{
sewardj4231a852008-08-19 08:32:03 +0000734 struct vg_stat st;
sewardj26b87282006-10-17 12:49:31 +0000735 SysRes res = VG_(stat)(f, &st);
njn73750612005-10-14 03:11:30 +0000736
sewardjc74b3ba2007-11-17 21:11:57 +0000737 if (is_setuid)
738 *is_setuid = False;
739
njncda2f0f2009-05-18 02:12:08 +0000740 if (sr_isError(res)) {
741 return sr_Err(res);
njn73750612005-10-14 03:11:30 +0000742 }
743
mjwd6edbc92015-02-09 13:27:07 +0000744 if ( VKI_S_ISDIR (st.mode) ) {
745 return VKI_EACCES;
746 }
747
njn9c20ece2009-05-20 02:02:30 +0000748 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
sewardjc74b3ba2007-11-17 21:11:57 +0000749 if (is_setuid)
750 *is_setuid = True;
njn73750612005-10-14 03:11:30 +0000751 return VKI_EACCES;
752 }
753
tomb7c2f9d2014-05-22 08:57:06 +0000754 res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
755 if (!sr_isError(res) && !allow_setuid) {
756 if (is_setuid)
757 *is_setuid = True;
758 return VKI_EACCES;
759 }
760
njn9c20ece2009-05-20 02:02:30 +0000761 if (VG_(geteuid)() == st.uid) {
762 if (!(st.mode & VKI_S_IXUSR))
njn73750612005-10-14 03:11:30 +0000763 return VKI_EACCES;
764 } else {
sewardj45406ef2006-10-18 00:33:46 +0000765 Int grpmatch = 0;
njn73750612005-10-14 03:11:30 +0000766
njn9c20ece2009-05-20 02:02:30 +0000767 if (VG_(getegid)() == st.gid)
njn73750612005-10-14 03:11:30 +0000768 grpmatch = 1;
769 else {
florian94086c72014-09-30 19:26:58 +0000770 UInt *groups = NULL;
771 Int ngrp;
772
773 /* Find out # groups, allocate large enough array and fetch groups */
774 ngrp = VG_(getgroups)(0, NULL);
775 if (ngrp != -1) {
776 groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
777 ngrp = VG_(getgroups)(ngrp, groups);
778 }
779
780 Int i;
njn73750612005-10-14 03:11:30 +0000781 /* ngrp will be -1 if VG_(getgroups) failed. */
782 for (i = 0; i < ngrp; i++) {
njn9c20ece2009-05-20 02:02:30 +0000783 if (groups[i] == st.gid) {
njn73750612005-10-14 03:11:30 +0000784 grpmatch = 1;
785 break;
786 }
787 }
florian94086c72014-09-30 19:26:58 +0000788 VG_(free)(groups);
njn73750612005-10-14 03:11:30 +0000789 }
790
791 if (grpmatch) {
njn9c20ece2009-05-20 02:02:30 +0000792 if (!(st.mode & VKI_S_IXGRP)) {
njn73750612005-10-14 03:11:30 +0000793 return VKI_EACCES;
794 }
njn9c20ece2009-05-20 02:02:30 +0000795 } else if (!(st.mode & VKI_S_IXOTH)) {
njn73750612005-10-14 03:11:30 +0000796 return VKI_EACCES;
797 }
798 }
799
800 return 0;
801}
802
njnc4431bf2009-01-15 21:29:24 +0000803SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
sewardj45f4e7c2005-09-27 19:20:21 +0000804{
njncda2f0f2009-05-18 02:12:08 +0000805 SysRes res;
philippe8050bb72012-04-13 23:07:29 +0000806 // on 32 bits platforms, we receive a 32 bits OffT but
807 // we must extend it to pass a long long 64 bits.
808# if defined(VGP_x86_linux)
809 vg_assert(sizeof(OffT) == 4);
810 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
811 offset, 0); // Little endian long long
812 return res;
813# elif defined(VGP_arm_linux)
814 vg_assert(sizeof(OffT) == 4);
815 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
816 0, offset); // Big endian long long
817 return res;
818# elif defined(VGP_ppc32_linux)
819 vg_assert(sizeof(OffT) == 4);
820 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
821 0, // Padding needed on PPC32
822 0, offset); // Big endian long long
823 return res;
petarj4df0bfc2013-02-27 23:17:33 +0000824# elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
sewardj5db15402012-06-07 09:13:21 +0000825 vg_assert(sizeof(OffT) == 4);
826 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
827 0, offset, 0);
828 return res;
petarj4df0bfc2013-02-27 23:17:33 +0000829# elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
sewardj5db15402012-06-07 09:13:21 +0000830 vg_assert(sizeof(OffT) == 4);
831 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
832 0, 0, offset);
833 return res;
carllcae0cc22014-08-07 23:17:29 +0000834# elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
835 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
sewardjf0c12502014-01-12 12:54:00 +0000836 || defined(VGP_mips64_linux) \
sewardj112711a2015-04-10 12:30:09 +0000837 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
philippe8050bb72012-04-13 23:07:29 +0000838 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
njncda2f0f2009-05-18 02:12:08 +0000839 return res;
njnf76d27a2009-05-28 01:53:07 +0000840# elif defined(VGP_amd64_darwin)
sewardj972316d2012-04-21 15:33:26 +0000841 vg_assert(sizeof(OffT) == 8);
njnf76d27a2009-05-28 01:53:07 +0000842 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
843 return res;
844# elif defined(VGP_x86_darwin)
sewardj972316d2012-04-21 15:33:26 +0000845 vg_assert(sizeof(OffT) == 8);
njnf76d27a2009-05-28 01:53:07 +0000846 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
sewardj972316d2012-04-21 15:33:26 +0000847 offset & 0xffffffff, offset >> 32);
njnf76d27a2009-05-28 01:53:07 +0000848 return res;
sewardj8eb8bab2015-07-21 14:44:28 +0000849# elif defined(VGP_x86_solaris)
850 vg_assert(sizeof(OffT) == 4);
851 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
852 return res;
853# elif defined(VGP_amd64_solaris)
854 vg_assert(sizeof(OffT) == 8);
855 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
856 return res;
njncda2f0f2009-05-18 02:12:08 +0000857# else
858# error "Unknown platform"
859# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000860}
861
florianb985e2d2011-09-29 03:03:45 +0000862/* Return the name of a directory for temporary files. */
863const HChar *VG_(tmpdir)(void)
864{
865 const HChar *tmpdir;
866
867 tmpdir = VG_(getenv)("TMPDIR");
868 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
869 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */
870
871 return tmpdir;
872}
873
florian60372262014-08-09 21:45:56 +0000874static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
philippecc648262013-05-26 21:09:20 +0000875
876SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
877{
878 return VG_(strlen)(mkstemp_format)
879 + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
880 + part_of_name_len - 2 // %s part_of_name
881 + 8 - 4 // %08x
882 + 1; // trailing 0
883}
884
885
philipped47676f2014-08-09 11:26:51 +0000886Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
sewardj45f4e7c2005-09-27 19:20:21 +0000887{
florian87c8abb2014-11-09 16:15:23 +0000888 Int n, tries;
sewardj45f4e7c2005-09-27 19:20:21 +0000889 UInt seed;
890 SysRes sres;
florian1763e812011-07-12 19:07:05 +0000891 const HChar *tmpdir;
sewardj45f4e7c2005-09-27 19:20:21 +0000892
893 vg_assert(part_of_name);
florian87c8abb2014-11-09 16:15:23 +0000894 vg_assert(fullname);
sewardj45f4e7c2005-09-27 19:20:21 +0000895 n = VG_(strlen)(part_of_name);
896 vg_assert(n > 0 && n < 100);
897
898 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
899
florian1763e812011-07-12 19:07:05 +0000900 /* Determine sensible location for temporary files */
florianb985e2d2011-09-29 03:03:45 +0000901 tmpdir = VG_(tmpdir)();
florian1763e812011-07-12 19:07:05 +0000902
sewardj45f4e7c2005-09-27 19:20:21 +0000903 tries = 0;
904 while (True) {
sewardj824b3972011-05-09 22:42:06 +0000905 if (tries++ > 10)
sewardj45f4e7c2005-09-27 19:20:21 +0000906 return -1;
florian87c8abb2014-11-09 16:15:23 +0000907 VG_(sprintf)( fullname, mkstemp_format,
florian1763e812011-07-12 19:07:05 +0000908 tmpdir, part_of_name, VG_(random)( &seed ));
sewardj45f4e7c2005-09-27 19:20:21 +0000909 if (0)
florian87c8abb2014-11-09 16:15:23 +0000910 VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
sewardj45f4e7c2005-09-27 19:20:21 +0000911
florian87c8abb2014-11-09 16:15:23 +0000912 sres = VG_(open)(fullname,
sewardj45f4e7c2005-09-27 19:20:21 +0000913 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
914 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj80fc03b2011-09-26 16:46:04 +0000915 if (sr_isError(sres)) {
florian87c8abb2014-11-09 16:15:23 +0000916 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
sewardj45f4e7c2005-09-27 19:20:21 +0000917 continue;
sewardj80fc03b2011-09-26 16:46:04 +0000918 }
sewardj45f4e7c2005-09-27 19:20:21 +0000919 /* VG_(safe_fd) doesn't return if it fails. */
florian87c8abb2014-11-09 16:15:23 +0000920 return VG_(safe_fd)( sr_Res(sres) );
sewardj45f4e7c2005-09-27 19:20:21 +0000921 }
922 /* NOTREACHED */
923}
924
925
njneb8896b2005-06-04 20:03:55 +0000926/* ---------------------------------------------------------------------
njn4bd96bd2009-05-22 00:52:14 +0000927 Socket-related stuff.
njneb8896b2005-06-04 20:03:55 +0000928 ------------------------------------------------------------------ */
929
930static
florian19f91bb2012-11-10 22:29:54 +0000931Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
njneb8896b2005-06-04 20:03:55 +0000932
933static
njn4bd96bd2009-05-22 00:52:14 +0000934Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
njneb8896b2005-06-04 20:03:55 +0000935
toma4a4f412005-11-17 12:01:56 +0000936UInt VG_(htonl) ( UInt x )
njneb8896b2005-06-04 20:03:55 +0000937{
sewardja1c4bfb2005-10-18 02:15:39 +0000938# if defined(VG_BIGENDIAN)
939 return x;
940# else
njneb8896b2005-06-04 20:03:55 +0000941 return
942 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
943 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
sewardja1c4bfb2005-10-18 02:15:39 +0000944# endif
njneb8896b2005-06-04 20:03:55 +0000945}
946
toma4a4f412005-11-17 12:01:56 +0000947UInt VG_(ntohl) ( UInt x )
948{
949# if defined(VG_BIGENDIAN)
950 return x;
951# else
952 return
953 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
954 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
955# endif
956}
957
958UShort VG_(htons) ( UShort x )
959{
960# if defined(VG_BIGENDIAN)
961 return x;
962# else
963 return
964 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
965# endif
966}
967
968UShort VG_(ntohs) ( UShort x )
njneb8896b2005-06-04 20:03:55 +0000969{
sewardja1c4bfb2005-10-18 02:15:39 +0000970# if defined(VG_BIGENDIAN)
971 return x;
972# else
njneb8896b2005-06-04 20:03:55 +0000973 return
974 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
sewardja1c4bfb2005-10-18 02:15:39 +0000975# endif
njneb8896b2005-06-04 20:03:55 +0000976}
977
978
979/* The main function.
980
981 Supplied string contains either an ip address "192.168.0.1" or
982 an ip address and port pair, "192.168.0.1:1500". Parse these,
983 and return:
984 -1 if there is a parse error
985 -2 if no parse error, but specified host:port cannot be opened
986 the relevant file (socket) descriptor, otherwise.
987 is used.
988*/
florian19f91bb2012-11-10 22:29:54 +0000989Int VG_(connect_via_socket)( const HChar* str )
njneb8896b2005-06-04 20:03:55 +0000990{
sewardj8eb8bab2015-07-21 14:44:28 +0000991# if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
njneb8896b2005-06-04 20:03:55 +0000992 Int sd, res;
993 struct vki_sockaddr_in servAddr;
994 UInt ip = 0;
995 UShort port = VG_CLO_DEFAULT_LOGPORT;
996 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
997 if (!ok)
998 return -1;
999
1000 //if (0)
1001 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1002 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1003 // (ip >> 8) & 0xFF, ip & 0xFF,
1004 // (UInt)port );
1005
1006 servAddr.sin_family = VKI_AF_INET;
toma4a4f412005-11-17 12:01:56 +00001007 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
1008 servAddr.sin_port = VG_(htons)(port);
njneb8896b2005-06-04 20:03:55 +00001009
1010 /* create socket */
njn0cd5d972009-05-22 02:00:27 +00001011 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
njneb8896b2005-06-04 20:03:55 +00001012 if (sd < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +00001013 /* this shouldn't happen ... nevertheless */
1014 return -2;
njneb8896b2005-06-04 20:03:55 +00001015 }
sewardja1c4bfb2005-10-18 02:15:39 +00001016
njneb8896b2005-06-04 20:03:55 +00001017 /* connect to server */
njnb143b272009-05-22 00:47:08 +00001018 res = my_connect(sd, &servAddr, sizeof(servAddr));
njneb8896b2005-06-04 20:03:55 +00001019 if (res < 0) {
sewardja1c4bfb2005-10-18 02:15:39 +00001020 /* connection failed */
1021 return -2;
njneb8896b2005-06-04 20:03:55 +00001022 }
1023
1024 return sd;
njncda2f0f2009-05-18 02:12:08 +00001025
njncda2f0f2009-05-18 02:12:08 +00001026# else
1027# error "Unknown OS"
1028# endif
njneb8896b2005-06-04 20:03:55 +00001029}
1030
1031
1032/* Let d = one or more digits. Accept either:
1033 d.d.d.d or d.d.d.d:d
1034*/
florian19f91bb2012-11-10 22:29:54 +00001035static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
njneb8896b2005-06-04 20:03:55 +00001036{
1037# define GET_CH ((*str) ? (*str++) : 0)
1038 UInt ipa, i, j, c, any;
1039 ipa = 0;
1040 for (i = 0; i < 4; i++) {
1041 j = 0;
1042 any = 0;
1043 while (1) {
1044 c = GET_CH;
1045 if (c < '0' || c > '9') break;
1046 j = 10 * j + (int)(c - '0');
1047 any = 1;
1048 }
1049 if (any == 0 || j > 255) goto syntaxerr;
1050 ipa = (ipa << 8) + j;
1051 if (i <= 2 && c != '.') goto syntaxerr;
1052 }
1053 if (c == 0 || c == ':')
1054 *ip_addr = ipa;
1055 if (c == 0) goto ok;
1056 if (c != ':') goto syntaxerr;
1057 j = 0;
1058 any = 0;
1059 while (1) {
1060 c = GET_CH;
1061 if (c < '0' || c > '9') break;
1062 j = j * 10 + (int)(c - '0');
1063 any = 1;
1064 if (j > 65535) goto syntaxerr;
1065 }
1066 if (any == 0 || c != 0) goto syntaxerr;
1067 if (j < 1024) goto syntaxerr;
1068 *port = (UShort)j;
1069 ok:
1070 return 1;
1071 syntaxerr:
1072 return 0;
1073# undef GET_CH
1074}
1075
njn0cd5d972009-05-22 02:00:27 +00001076// GrP fixme safe_fd?
1077Int VG_(socket) ( Int domain, Int type, Int protocol )
njneb8896b2005-06-04 20:03:55 +00001078{
njncda2f0f2009-05-18 02:12:08 +00001079# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001080 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1081 || defined(VGP_s390x_linux)
sewardja8d8e232005-06-07 20:04:56 +00001082 SysRes res;
1083 UWord args[3];
njneb8896b2005-06-04 20:03:55 +00001084 args[0] = domain;
1085 args[1] = type;
1086 args[2] = protocol;
1087 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +00001088 return sr_isError(res) ? -1 : sr_Res(res);
cerion85665ca2005-06-20 15:51:07 +00001089
sewardj5db15402012-06-07 09:13:21 +00001090# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardjf0c12502014-01-12 12:54:00 +00001091 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
sewardj112711a2015-04-10 12:30:09 +00001092 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardj1e866562005-09-28 19:58:58 +00001093 SysRes res;
1094 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
njncda2f0f2009-05-18 02:12:08 +00001095 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +00001096
njnf76d27a2009-05-28 01:53:07 +00001097# elif defined(VGO_darwin)
1098 SysRes res;
1099 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
1100 if (!sr_isError(res)) {
1101 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
1102 Int optval = 1;
1103 SysRes res2;
1104 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
1105 VKI_SO_NOSIGPIPE, (UWord)&optval,
1106 sizeof(optval));
1107 // ignore setsockopt() error
1108 }
1109 return sr_isError(res) ? -1 : sr_Res(res);
1110
sewardj8eb8bab2015-07-21 14:44:28 +00001111# elif defined(VGO_solaris)
1112 /* XXX There doesn't seem to be an easy way to convince the send syscall to
1113 only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
1114 SM_KERNEL is set on the socket. Without serious hackery it looks we
1115 can't set this flag.
1116
1117 Should we wrap the send syscall below into sigprocmask calls to block
1118 SIGPIPE?
1119 */
1120 SysRes res;
1121 res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol,
1122 0 /*devpath*/, VKI_SOV_DEFAULT /*version*/);
1123 return sr_isError(res) ? -1 : sr_Res(res);
1124
njncda2f0f2009-05-18 02:12:08 +00001125# else
1126# error "Unknown arch"
1127# endif
njneb8896b2005-06-04 20:03:55 +00001128}
1129
njncda2f0f2009-05-18 02:12:08 +00001130
njneb8896b2005-06-04 20:03:55 +00001131static
njn4bd96bd2009-05-22 00:52:14 +00001132Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
njneb8896b2005-06-04 20:03:55 +00001133{
njncda2f0f2009-05-18 02:12:08 +00001134# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001135 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1136 || defined(VGP_s390x_linux)
sewardja8d8e232005-06-07 20:04:56 +00001137 SysRes res;
1138 UWord args[3];
njneb8896b2005-06-04 20:03:55 +00001139 args[0] = sockfd;
1140 args[1] = (UWord)serv_addr;
1141 args[2] = addrlen;
1142 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +00001143 return sr_isError(res) ? -1 : sr_Res(res);
cerion85665ca2005-06-20 15:51:07 +00001144
sewardj5db15402012-06-07 09:13:21 +00001145# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardjf0c12502014-01-12 12:54:00 +00001146 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
sewardj112711a2015-04-10 12:30:09 +00001147 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardj1e866562005-09-28 19:58:58 +00001148 SysRes res;
1149 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
njncda2f0f2009-05-18 02:12:08 +00001150 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +00001151
njnf76d27a2009-05-28 01:53:07 +00001152# elif defined(VGO_darwin)
1153 SysRes res;
1154 res = VG_(do_syscall3)(__NR_connect_nocancel,
1155 sockfd, (UWord)serv_addr, addrlen);
1156 return sr_isError(res) ? -1 : sr_Res(res);
1157
sewardj8eb8bab2015-07-21 14:44:28 +00001158# elif defined(VGO_solaris)
1159 SysRes res;
1160 res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen,
1161 VKI_SOV_DEFAULT /*version*/);
1162 return sr_isError(res) ? -1 : sr_Res(res);
1163
njncda2f0f2009-05-18 02:12:08 +00001164# else
1165# error "Unknown arch"
1166# endif
njneb8896b2005-06-04 20:03:55 +00001167}
1168
floriandbb35842012-10-27 18:39:11 +00001169Int VG_(write_socket)( Int sd, const void *msg, Int count )
njneb8896b2005-06-04 20:03:55 +00001170{
njneb8896b2005-06-04 20:03:55 +00001171 /* This is actually send(). */
njnf76d27a2009-05-28 01:53:07 +00001172
1173 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
sewardj9a66bb92006-10-17 01:38:13 +00001174 errors on stream oriented sockets when the other end breaks the
njnf76d27a2009-05-28 01:53:07 +00001175 connection. The EPIPE error is still returned.
1176
1177 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1178 SIGPIPE */
njneb8896b2005-06-04 20:03:55 +00001179
njncda2f0f2009-05-18 02:12:08 +00001180# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001181 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1182 || defined(VGP_s390x_linux)
sewardja8d8e232005-06-07 20:04:56 +00001183 SysRes res;
1184 UWord args[4];
njneb8896b2005-06-04 20:03:55 +00001185 args[0] = sd;
1186 args[1] = (UWord)msg;
1187 args[2] = count;
sewardj9a66bb92006-10-17 01:38:13 +00001188 args[3] = VKI_MSG_NOSIGNAL;
njneb8896b2005-06-04 20:03:55 +00001189 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +00001190 return sr_isError(res) ? -1 : sr_Res(res);
cerion85665ca2005-06-20 15:51:07 +00001191
sewardj5db15402012-06-07 09:13:21 +00001192# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardjf0c12502014-01-12 12:54:00 +00001193 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
sewardj112711a2015-04-10 12:30:09 +00001194 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardj1e866562005-09-28 19:58:58 +00001195 SysRes res;
sewardj9a66bb92006-10-17 01:38:13 +00001196 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
1197 count, VKI_MSG_NOSIGNAL, 0,0);
njncda2f0f2009-05-18 02:12:08 +00001198 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +00001199
njnf76d27a2009-05-28 01:53:07 +00001200# elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1201 SysRes res;
1202 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
1203 return sr_isError(res) ? -1 : sr_Res(res);
1204
sewardj8eb8bab2015-07-21 14:44:28 +00001205# elif defined(VGO_solaris)
1206 SysRes res;
1207 res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/);
1208 return sr_isError(res) ? -1 : sr_Res(res);
1209
njncda2f0f2009-05-18 02:12:08 +00001210# else
1211# error "Unknown platform"
1212# endif
njneb8896b2005-06-04 20:03:55 +00001213}
1214
1215Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1216{
njncda2f0f2009-05-18 02:12:08 +00001217# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001218 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1219 || defined(VGP_s390x_linux) \
sewardj5db15402012-06-07 09:13:21 +00001220 || defined(VGP_mips32_linux)
sewardj9a66bb92006-10-17 01:38:13 +00001221 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +00001222 UWord args[3];
njneb8896b2005-06-04 20:03:55 +00001223 args[0] = sd;
1224 args[1] = (UWord)name;
1225 args[2] = (UWord)namelen;
1226 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +00001227 return sr_isError(res) ? -1 : sr_Res(res);
sewardja5c9e4a2005-06-09 13:21:58 +00001228
petarj4df0bfc2013-02-27 23:17:33 +00001229# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardj112711a2015-04-10 12:30:09 +00001230 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1231 || defined(VGP_tilegx_linux)
sewardj9a66bb92006-10-17 01:38:13 +00001232 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +00001233 res = VG_(do_syscall3)( __NR_getsockname,
1234 (UWord)sd, (UWord)name, (UWord)namelen );
njncda2f0f2009-05-18 02:12:08 +00001235 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +00001236
njnf76d27a2009-05-28 01:53:07 +00001237# elif defined(VGO_darwin)
1238 SysRes res;
1239 res = VG_(do_syscall3)( __NR_getsockname,
1240 (UWord)sd, (UWord)name, (UWord)namelen );
1241 return sr_isError(res) ? -1 : sr_Res(res);
1242
sewardj8eb8bab2015-07-21 14:44:28 +00001243# elif defined(VGO_solaris)
1244 SysRes res;
1245 res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen,
1246 VKI_SOV_DEFAULT /*version*/);
1247 return sr_isError(res) ? -1 : sr_Res(res);
1248
njncda2f0f2009-05-18 02:12:08 +00001249# else
1250# error "Unknown platform"
1251# endif
njneb8896b2005-06-04 20:03:55 +00001252}
1253
1254Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1255{
njncda2f0f2009-05-18 02:12:08 +00001256# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001257 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1258 || defined(VGP_s390x_linux) \
sewardj5db15402012-06-07 09:13:21 +00001259 || defined(VGP_mips32_linux)
sewardj9a66bb92006-10-17 01:38:13 +00001260 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +00001261 UWord args[3];
njneb8896b2005-06-04 20:03:55 +00001262 args[0] = sd;
1263 args[1] = (UWord)name;
1264 args[2] = (UWord)namelen;
1265 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +00001266 return sr_isError(res) ? -1 : sr_Res(res);
sewardja5c9e4a2005-06-09 13:21:58 +00001267
petarj4df0bfc2013-02-27 23:17:33 +00001268# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardj112711a2015-04-10 12:30:09 +00001269 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1270 || defined(VGP_tilegx_linux)
sewardj9a66bb92006-10-17 01:38:13 +00001271 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +00001272 res = VG_(do_syscall3)( __NR_getpeername,
1273 (UWord)sd, (UWord)name, (UWord)namelen );
njncda2f0f2009-05-18 02:12:08 +00001274 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +00001275
njnf76d27a2009-05-28 01:53:07 +00001276# elif defined(VGO_darwin)
1277 SysRes res;
1278 res = VG_(do_syscall3)( __NR_getpeername,
1279 (UWord)sd, (UWord)name, (UWord)namelen );
1280 return sr_isError(res) ? -1 : sr_Res(res);
1281
sewardj8eb8bab2015-07-21 14:44:28 +00001282# elif defined(VGO_solaris)
1283 SysRes res;
1284 res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen,
1285 VKI_SOV_DEFAULT /*version*/);
1286 return sr_isError(res) ? -1 : sr_Res(res);
1287
njncda2f0f2009-05-18 02:12:08 +00001288# else
1289# error "Unknown platform"
1290# endif
njneb8896b2005-06-04 20:03:55 +00001291}
1292
1293Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1294 Int *optlen)
1295{
njncda2f0f2009-05-18 02:12:08 +00001296# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001297 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1298 || defined(VGP_s390x_linux)
sewardj9a66bb92006-10-17 01:38:13 +00001299 SysRes res;
sewardja8d8e232005-06-07 20:04:56 +00001300 UWord args[5];
njneb8896b2005-06-04 20:03:55 +00001301 args[0] = sd;
1302 args[1] = level;
1303 args[2] = optname;
1304 args[3] = (UWord)optval;
1305 args[4] = (UWord)optlen;
1306 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
njncda2f0f2009-05-18 02:12:08 +00001307 return sr_isError(res) ? -1 : sr_Res(res);
sewardja5c9e4a2005-06-09 13:21:58 +00001308
sewardj5db15402012-06-07 09:13:21 +00001309# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardjf0c12502014-01-12 12:54:00 +00001310 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
sewardj112711a2015-04-10 12:30:09 +00001311 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardj9a66bb92006-10-17 01:38:13 +00001312 SysRes res;
sewardja5c9e4a2005-06-09 13:21:58 +00001313 res = VG_(do_syscall5)( __NR_getsockopt,
1314 (UWord)sd, (UWord)level, (UWord)optname,
1315 (UWord)optval, (UWord)optlen );
njncda2f0f2009-05-18 02:12:08 +00001316 return sr_isError(res) ? -1 : sr_Res(res);
sewardj9a66bb92006-10-17 01:38:13 +00001317
njnf76d27a2009-05-28 01:53:07 +00001318# elif defined(VGO_darwin)
1319 SysRes res;
1320 res = VG_(do_syscall5)( __NR_getsockopt,
1321 (UWord)sd, (UWord)level, (UWord)optname,
1322 (UWord)optval, (UWord)optlen );
1323 return sr_isError(res) ? -1 : sr_Res(res);
1324
sewardj8eb8bab2015-07-21 14:44:28 +00001325# elif defined(VGO_solaris)
1326 SysRes res;
1327 res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval,
1328 (UWord)optlen, VKI_SOV_DEFAULT /*version*/);
1329 return sr_isError(res) ? -1 : sr_Res(res);
1330
njncda2f0f2009-05-18 02:12:08 +00001331# else
1332# error "Unknown platform"
1333# endif
njneb8896b2005-06-04 20:03:55 +00001334}
1335
1336
sewardj5d616df2013-07-02 08:07:15 +00001337Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
1338 Int optlen)
njnf76d27a2009-05-28 01:53:07 +00001339{
sewardj5d616df2013-07-02 08:07:15 +00001340# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
carllcae0cc22014-08-07 23:17:29 +00001341 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1342 || defined(VGP_s390x_linux)
sewardj5d616df2013-07-02 08:07:15 +00001343 SysRes res;
1344 UWord args[5];
1345 args[0] = sd;
1346 args[1] = level;
1347 args[2] = optname;
1348 args[3] = (UWord)optval;
1349 args[4] = (UWord)optlen;
1350 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
1351 return sr_isError(res) ? -1 : sr_Res(res);
1352
1353# elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
sewardjf0c12502014-01-12 12:54:00 +00001354 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
sewardj112711a2015-04-10 12:30:09 +00001355 || defined(VGP_arm64_linux) || defined(VGP_tilegx_linux)
sewardj5d616df2013-07-02 08:07:15 +00001356 SysRes res;
1357 res = VG_(do_syscall5)( __NR_setsockopt,
1358 (UWord)sd, (UWord)level, (UWord)optname,
1359 (UWord)optval, (UWord)optlen );
1360 return sr_isError(res) ? -1 : sr_Res(res);
1361
1362# elif defined(VGO_darwin)
1363 SysRes res;
1364 res = VG_(do_syscall5)( __NR_setsockopt,
1365 (UWord)sd, (UWord)level, (UWord)optname,
1366 (UWord)optval, (UWord)optlen );
1367 return sr_isError(res) ? -1 : sr_Res(res);
1368
sewardj8eb8bab2015-07-21 14:44:28 +00001369# elif defined(VGO_solaris)
1370 SysRes res;
1371 res = VG_(do_syscall6)( __NR_setsockopt,
1372 (UWord)sd, (UWord)level, (UWord)optname,
1373 (UWord)optval, (UWord)optlen,
1374 VKI_SOV_DEFAULT /*version*/ );
1375 return sr_isError(res) ? -1 : sr_Res(res);
1376
sewardj5d616df2013-07-02 08:07:15 +00001377# else
1378# error "Unknown platform"
1379# endif
1380}
1381
1382
florian6bd9dc12012-11-23 16:17:43 +00001383const HChar *VG_(basename)(const HChar *path)
njnf76d27a2009-05-28 01:53:07 +00001384{
florian58946e92014-09-27 13:29:09 +00001385 static HChar *buf = NULL;
1386 static SizeT buf_len = 0;
florian19f91bb2012-11-10 22:29:54 +00001387 const HChar *p, *end;
njnf76d27a2009-05-28 01:53:07 +00001388
1389 if (path == NULL ||
1390 0 == VG_(strcmp)(path, ""))
1391 {
1392 return ".";
1393 }
1394
1395 p = path + VG_(strlen)(path);
1396 while (p > path && *p == '/') {
1397 // skip all trailing '/'
1398 p--;
1399 }
1400
1401 if (p == path && *p == '/') return "/"; // all slashes
1402
1403 end = p;
1404
1405 while (p > path && *p != '/') {
1406 // now skip non '/'
1407 p--;
1408 }
1409
1410 if (*p == '/') p++;
1411
florian58946e92014-09-27 13:29:09 +00001412 SizeT need = end-p+1 + 1;
1413 if (need > buf_len) {
1414 buf_len = (buf_len == 0) ? 500 : need;
1415 buf = VG_(realloc)("basename", buf, buf_len);
1416 }
njnf76d27a2009-05-28 01:53:07 +00001417 VG_(strncpy)(buf, p, end-p+1);
1418 buf[end-p+1] = '\0';
1419
1420 return buf;
1421}
1422
1423
florian6bd9dc12012-11-23 16:17:43 +00001424const HChar *VG_(dirname)(const HChar *path)
njnf76d27a2009-05-28 01:53:07 +00001425{
florian58946e92014-09-27 13:29:09 +00001426 static HChar *buf = NULL;
1427 static SizeT buf_len = 0;
njnf76d27a2009-05-28 01:53:07 +00001428
florian19f91bb2012-11-10 22:29:54 +00001429 const HChar *p;
njnf76d27a2009-05-28 01:53:07 +00001430
1431 if (path == NULL ||
1432 0 == VG_(strcmp)(path, "") ||
1433 0 == VG_(strcmp)(path, "/"))
1434 {
1435 return ".";
1436 }
1437
1438 p = path + VG_(strlen)(path);
1439 while (p > path && *p == '/') {
1440 // skip all trailing '/'
1441 p--;
1442 }
1443
1444 while (p > path && *p != '/') {
1445 // now skip non '/'
1446 p--;
1447 }
1448
1449 if (p == path) {
1450 if (*p == '/') return "/"; // all slashes
1451 else return "."; // no slashes
1452 }
1453
1454 while (p > path && *p == '/') {
1455 // skip '/' again
1456 p--;
1457 }
1458
florian58946e92014-09-27 13:29:09 +00001459 SizeT need = p-path+1 + 1;
1460 if (need > buf_len) {
1461 buf_len = (buf_len == 0) ? 500 : need;
1462 buf = VG_(realloc)("dirname", buf, buf_len);
1463 }
njnf76d27a2009-05-28 01:53:07 +00001464 VG_(strncpy)(buf, path, p-path+1);
1465 buf[p-path+1] = '\0';
1466
1467 return buf;
1468}
1469
1470
njneb8896b2005-06-04 20:03:55 +00001471/*--------------------------------------------------------------------*/
1472/*--- end ---*/
1473/*--------------------------------------------------------------------*/