drd/tests/swapcontext: Improve the portability of this test further
[valgrind.git] / coregrind / m_libcfile.c
blob3a8fed85d9f6daf63ca06ae5f5887b23b7215572
1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- File- and socket-related libc stuff. m_libcfile.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2017 Julian Seward
12 jseward@acm.org
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #include "pub_core_basics.h"
31 #include "pub_core_vki.h"
32 #include "pub_core_vkiscnums.h"
33 #include "pub_core_debuglog.h"
34 #include "pub_core_libcbase.h"
35 #include "pub_core_libcassert.h"
36 #include "pub_core_libcfile.h"
37 #include "pub_core_libcprint.h" // VG_(sprintf)
38 #include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
39 #include "pub_core_clientstate.h" // VG_(fd_hard_limit)
40 #include "pub_core_mallocfree.h" // VG_(realloc)
41 #include "pub_core_syscall.h"
43 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
44 of syscalls rather than the vanilla version, if a _nocancel version
45 is available. See docs/internals/Darwin-notes.txt for the reason
46 why. */
48 /* ---------------------------------------------------------------------
49 File stuff
50 ------------------------------------------------------------------ */
52 /* Move an fd into the Valgrind-safe range */
53 Int VG_(safe_fd)(Int oldfd)
55 Int newfd;
57 vg_assert(VG_(fd_hard_limit) != -1);
59 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
60 if (newfd != -1)
61 VG_(close)(oldfd);
63 /* Set the close-on-exec flag for this fd. */
64 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
66 vg_assert(newfd >= VG_(fd_hard_limit));
67 return newfd;
70 /* Given a file descriptor, attempt to deduce its filename. To do
71 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
72 or if it doesn't exist, we return False.
73 Upon successful completion *result contains the filename. The
74 filename will be overwritten with the next invocation so callers
75 need to copy the filename if needed. *result is NULL if the filename
76 cannot be deduced. */
77 Bool VG_(resolve_filename) ( Int fd, const HChar** result )
79 # if defined(VGO_linux) || defined(VGO_solaris)
80 static HChar *buf = NULL;
81 static SizeT bufsiz = 0;
83 if (buf == NULL) { // first time
84 bufsiz = 500;
85 buf = VG_(malloc)("resolve_filename", bufsiz);
88 HChar tmp[64]; // large enough
90 # if defined(VGO_linux)
91 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
92 # elif defined(VGO_solaris)
93 VG_(sprintf)(tmp, "/proc/self/path/%d", fd);
94 # endif
97 while (42) {
98 SSizeT res = VG_(readlink)(tmp, buf, bufsiz);
99 if (res < 0) break;
100 if (res == bufsiz) { // buffer too small; increase and retry
101 bufsiz += 500;
102 buf = VG_(realloc)("resolve_filename", buf, bufsiz);
103 continue;
105 vg_assert(bufsiz > res); // paranoia
106 if (buf[0] != '/') break;
108 buf[res] = '\0';
109 *result = buf;
110 return True;
112 // Failure
113 *result = NULL;
114 return False;
116 # elif defined(VGO_darwin)
117 HChar tmp[VKI_MAXPATHLEN+1];
118 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
119 static HChar *buf = NULL;
121 if (buf == NULL)
122 buf = VG_(malloc)("resolve_filename", VKI_MAXPATHLEN+1);
123 VG_(strcpy)( buf, tmp );
125 *result = buf;
126 if (buf[0] == '/') return True;
128 // Failure
129 *result = NULL;
130 return False;
132 # else
133 # error Unknown OS
134 # endif
137 SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
139 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
140 /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
141 SysRes res = VG_(do_syscall4)(__NR_mknodat,
142 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
143 # elif defined(VGO_linux) || defined(VGO_darwin)
144 SysRes res = VG_(do_syscall3)(__NR_mknod,
145 (UWord)pathname, mode, dev);
146 # elif defined(VGO_solaris)
147 SysRes res = VG_(do_syscall4)(__NR_mknodat,
148 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
149 # else
150 # error Unknown OS
151 # endif
152 return res;
155 SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
157 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
158 /* ARM64 wants to use __NR_openat rather than __NR_open. */
159 SysRes res = VG_(do_syscall4)(__NR_openat,
160 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
161 # elif defined(VGO_linux)
162 SysRes res = VG_(do_syscall3)(__NR_open,
163 (UWord)pathname, flags, mode);
164 # elif defined(VGO_darwin)
165 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
166 (UWord)pathname, flags, mode);
167 # elif defined(VGO_solaris)
168 SysRes res = VG_(do_syscall4)(__NR_openat,
169 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
170 # else
171 # error Unknown OS
172 # endif
173 return res;
176 Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
178 SysRes sr;
179 sr = VG_(open) (pathname, flags, mode);
180 if (sr_isError (sr))
181 return -1;
182 else
183 return sr_Res (sr);
186 void VG_(close) ( Int fd )
188 /* Hmm. Return value is not checked. That's uncool. */
189 # if defined(VGO_linux) || defined(VGO_solaris)
190 (void)VG_(do_syscall1)(__NR_close, fd);
191 # elif defined(VGO_darwin)
192 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
193 # else
194 # error Unknown OS
195 # endif
198 Int VG_(read) ( Int fd, void* buf, Int count)
200 Int ret;
201 # if defined(VGO_linux) || defined(VGO_solaris)
202 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
203 # elif defined(VGO_darwin)
204 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
205 # else
206 # error Unknown OS
207 # endif
208 if (sr_isError(res)) {
209 ret = - (Int)(Word)sr_Err(res);
210 vg_assert(ret < 0);
211 } else {
212 ret = (Int)(Word)sr_Res(res);
213 vg_assert(ret >= 0);
215 return ret;
218 Int VG_(write) ( Int fd, const void* buf, Int count)
220 Int ret;
221 # if defined(VGO_linux) || defined(VGO_solaris)
222 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
223 # elif defined(VGO_darwin)
224 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
225 # else
226 # error "Unknown OS"
227 # endif
228 if (sr_isError(res)) {
229 ret = - (Int)(Word)sr_Err(res);
230 vg_assert(ret < 0);
231 } else {
232 ret = (Int)(Word)sr_Res(res);
233 vg_assert(ret >= 0);
235 return ret;
239 Int VG_(pipe) ( Int fd[2] )
241 # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
242 /* __NR_pipe has a strange return convention on mips32-linux. */
243 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
244 if (!sr_isError(res)) {
245 fd[0] = (Int)sr_Res(res);
246 fd[1] = (Int)sr_ResEx(res);
247 return 0;
248 } else {
249 return -1;
251 # elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
252 SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
253 return sr_isError(res) ? -1 : 0;
254 # elif defined(VGO_linux)
255 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
256 return sr_isError(res) ? -1 : 0;
257 # elif defined(VGO_darwin)
258 /* __NR_pipe is UX64, so produces a double-word result */
259 SysRes res = VG_(do_syscall0)(__NR_pipe);
260 if (!sr_isError(res)) {
261 fd[0] = (Int)sr_Res(res);
262 fd[1] = (Int)sr_ResHI(res);
264 return sr_isError(res) ? -1 : 0;
265 # elif defined(VGO_solaris)
266 # if defined(SOLARIS_NEW_PIPE_SYSCALL)
267 SysRes res = VG_(do_syscall2)(__NR_pipe, (UWord)fd, 0);
268 return sr_isError(res) ? -1 : 0;
269 # else
270 SysRes res = VG_(do_syscall0)(__NR_pipe);
271 if (!sr_isError(res)) {
272 fd[0] = (Int)sr_Res(res);
273 fd[1] = (Int)sr_ResHI(res);
275 return sr_isError(res) ? -1 : 0;
276 # endif
277 # else
278 # error "Unknown OS"
279 # endif
282 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
284 # if defined(VGO_linux) || defined(VGP_amd64_darwin)
285 # if defined(__NR__llseek)
286 Off64T result;
287 SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
288 offset >> 32, offset & 0xffffffff,
289 (UWord)&result, whence);
290 return sr_isError(res) ? (-1) : result;
291 # else
292 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
293 vg_assert(sizeof(Off64T) == sizeof(sr_Res(res)));
294 return sr_isError(res) ? (-1) : sr_Res(res);
295 # endif
296 # elif defined(VGP_x86_darwin)
297 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
298 offset & 0xffffffff, offset >> 32, whence);
299 return sr_isError(res) ? (-1) : sr_Res(res);
300 # elif defined(VGP_x86_solaris)
301 SysRes res = VG_(do_syscall4)(__NR_llseek, fd,
302 offset & 0xffffffff, offset >> 32, whence);
303 return sr_isError(res) ? (-1) : ((ULong)sr_ResHI(res) << 32 | sr_Res(res));
304 # elif defined(VGP_amd64_solaris)
305 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
306 vg_assert(sizeof(Off64T) == sizeof(Word));
307 return sr_isError(res) ? (-1) : sr_Res(res);
308 # else
309 # error "Unknown plat"
310 # endif
311 /* if you change the error-reporting conventions of this, also
312 change all usage points. */
316 /* stat/fstat support. It's uggerly. We have impedance-match into a
317 'struct vg_stat' in order to have a single structure that callers
318 can use consistently on all platforms. */
320 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
321 do { \
322 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
323 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
324 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
325 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
326 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
327 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
328 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
329 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
330 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
331 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
332 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
333 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
334 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
335 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
336 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
337 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
338 } while (0)
340 #define TRANSLATE_statx_TO_vg_stat(_p_vgstat, _p_vkistat) \
341 do { \
342 (_p_vgstat)->dev = VG_MAKEDEV( (_p_vkistat)->stx_dev_major, \
343 (_p_vkistat)->stx_dev_minor ); \
344 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->stx_ino ); \
345 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->stx_nlink ); \
346 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->stx_mode ); \
347 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->stx_uid ); \
348 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->stx_gid ); \
349 (_p_vgstat)->rdev = VG_MAKEDEV( (_p_vkistat)->stx_rdev_major, \
350 (_p_vkistat)->stx_rdev_minor ); \
351 (_p_vgstat)->size = (Long) ( (_p_vkistat)->stx_size ); \
352 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->stx_blksize ); \
353 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->stx_blocks ); \
354 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->stx_atime.tv_sec ); \
355 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->stx_atime.tv_nsec ); \
356 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->stx_mtime.tv_sec ); \
357 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->stx_mtime.tv_nsec ); \
358 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->stx_ctime.tv_sec ); \
359 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->stx_ctime.tv_nsec ); \
360 } while (0)
362 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
364 SysRes res;
365 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
367 # if defined(VGO_linux)
368 /* On Linux, first try with statx. If that doesn't work out, fall back to
369 the stat64 or vanilla version. */
370 { struct vki_statx buf;
371 res = VG_(do_syscall5)(__NR_statx, VKI_AT_FDCWD, (UWord)file_name, 0,
372 VKI_STATX_ALL, (UWord)&buf);
373 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
374 /* Success, or any failure except ENOSYS */
375 if (!sr_isError(res))
376 TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
377 return res;
380 # endif
381 # if defined(VGO_linux) || defined(VGO_darwin)
382 /* Try with stat64. This is the second candidate on Linux, and the first
383 one on Darwin. If that doesn't work out, fall back to vanilla version.
385 # if defined(__NR_stat64)
386 { struct vki_stat64 buf64;
387 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
388 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
389 /* Success, or any failure except ENOSYS */
390 if (!sr_isError(res))
391 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
392 return res;
395 # endif /* defined(__NR_stat64) */
396 # if defined(__NR_stat) || defined(VGP_arm64_linux)
397 /* This is the fallback ("vanilla version"). */
398 { struct vki_stat buf;
399 # if defined(VGP_arm64_linux)
400 res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
401 (UWord)file_name, (UWord)&buf);
402 # else
403 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
404 # endif
405 if (!sr_isError(res))
406 TRANSLATE_TO_vg_stat(vgbuf, &buf);
407 return res;
409 # endif
410 # elif defined(VGO_solaris)
412 # if defined(VGP_x86_solaris)
413 struct vki_stat64 buf64;
414 res = VG_(do_syscall4)(__NR_fstatat64, VKI_AT_FDCWD, (UWord)file_name,
415 (UWord)&buf64, 0);
416 # elif defined(VGP_amd64_solaris)
417 struct vki_stat buf64;
418 res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name,
419 (UWord)&buf64, 0);
420 # else
421 # error "Unknown platform"
422 # endif
423 if (!sr_isError(res))
424 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
425 return res;
427 # else
428 # error Unknown OS
429 # endif
432 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
434 SysRes res;
435 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
437 # if defined(VGO_linux)
438 /* On Linux, first try with statx. If that doesn't work out, fall back to
439 the fstat64 or vanilla version. */
440 { struct vki_statx buf;
441 const char* file_name = "";
442 res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
443 VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&buf);
444 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
445 /* Success, or any failure except ENOSYS */
446 if (!sr_isError(res))
447 TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
448 return sr_isError(res) ? (-1) : 0;
451 #endif
452 # if defined(VGO_linux) || defined(VGO_darwin)
453 /* Try with fstat64. This is the second candidate on Linux, and the first
454 one on Darwin. If that doesn't work out, fall back to vanilla version.
456 # if defined(__NR_fstat64)
457 { struct vki_stat64 buf64;
458 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
459 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
460 /* Success, or any failure except ENOSYS */
461 if (!sr_isError(res))
462 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
463 return sr_isError(res) ? (-1) : 0;
466 # endif /* defined(__NR_fstat64) */
467 # if defined(__NR_fstat)
468 { struct vki_stat buf;
469 res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
470 if (!sr_isError(res))
471 TRANSLATE_TO_vg_stat(vgbuf, &buf);
472 return sr_isError(res) ? (-1) : 0;
474 # endif
475 # elif defined(VGO_solaris)
477 # if defined(VGP_x86_solaris)
478 struct vki_stat64 buf64;
479 res = VG_(do_syscall4)(__NR_fstatat64, (UWord)fd, 0, (UWord)&buf64, 0);
480 # elif defined(VGP_amd64_solaris)
481 struct vki_stat buf64;
482 res = VG_(do_syscall4)(__NR_fstatat, (UWord)fd, 0, (UWord)&buf64, 0);
483 # else
484 # error "Unknown platform"
485 # endif
486 if (!sr_isError(res))
487 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
488 return sr_isError(res) ? (-1) : 0;
490 # else
491 # error Unknown OS
492 # endif
495 #undef TRANSLATE_TO_vg_stat
496 #undef TRANSLATE_statx_TO_vg_stat
498 Long VG_(fsize) ( Int fd )
500 struct vg_stat buf;
501 Int res = VG_(fstat)( fd, &buf );
502 return (res == -1) ? (-1LL) : buf.size;
505 SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
507 SysRes res;
508 #if defined(VGO_linux)
509 res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
510 attr_value, attr_value_len);
511 #else
512 res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
513 #endif
514 return res;
517 Bool VG_(is_dir) ( const HChar* f )
519 struct vg_stat buf;
520 SysRes res = VG_(stat)(f, &buf);
521 return sr_isError(res) ? False
522 : VKI_S_ISDIR(buf.mode) ? True : False;
525 SysRes VG_(dup) ( Int oldfd )
527 # if defined(VGO_linux) || defined(VGO_darwin)
528 return VG_(do_syscall1)(__NR_dup, oldfd);
529 # elif defined(VGO_solaris)
530 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUPFD, 0);
531 # else
532 # error Unknown OS
533 # endif
536 SysRes VG_(dup2) ( Int oldfd, Int newfd )
538 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
539 /* We only have dup3, that means we have to mimic dup2.
540 The only real difference is when oldfd == newfd.
541 dup3 always returns an error, but dup2 returns only an
542 error if the fd is invalid, otherwise it returns newfd. */
543 if (oldfd == newfd) {
544 if (VG_(fcntl)(oldfd, VKI_F_GETFL, 0) == -1)
545 return VG_(mk_SysRes_Error)(VKI_EBADF);
546 return VG_(mk_SysRes_Success)(newfd);
548 return VG_(do_syscall3)(__NR_dup3, oldfd, newfd, 0);
549 # elif defined(VGO_linux) || defined(VGO_darwin)
550 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
551 # elif defined(VGO_solaris)
552 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
553 # else
554 # error Unknown OS
555 # endif
558 /* Returns -1 on error. */
559 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
561 # if defined(VGO_linux) || defined(VGO_solaris)
562 # if defined(VGP_nanomips_linux)
563 SysRes res = VG_(do_syscall3)(__NR_fcntl64, fd, cmd, arg);
564 # else
565 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
566 # endif
567 # elif defined(VGO_darwin)
568 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
569 # else
570 # error "Unknown OS"
571 # endif
572 return sr_isError(res) ? -1 : sr_Res(res);
575 Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
577 # if defined(VGO_solaris) || defined(VGP_arm64_linux)
578 SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
579 VKI_AT_FDCWD, (UWord)new_name);
580 # elif defined(VGP_nanomips_linux)
581 SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name,
582 VKI_AT_FDCWD, (UWord)new_name, 0);
584 # elif defined(VGO_linux) || defined(VGO_darwin)
585 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
586 # else
587 # error "Unknown OS"
588 # endif
589 return sr_isError(res) ? (-1) : 0;
592 Int VG_(unlink) ( const HChar* file_name )
594 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
595 SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
596 (UWord)file_name);
597 # elif defined(VGO_linux) || defined(VGO_darwin)
598 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
599 # elif defined(VGO_solaris)
600 SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
601 (UWord)file_name, 0);
602 # else
603 # error "Unknown OS"
604 # endif
605 return sr_isError(res) ? (-1) : 0;
608 /* The working directory at startup.
609 All that is really needed is to note the cwd at process startup.
610 Hence VG_(record_startup_wd) notes it (in a platform dependent way)
611 and VG_(get_startup_wd) produces the noted value. */
612 static HChar *startup_wd;
614 /* Record the process' working directory at startup. Is intended to
615 be called exactly once, at startup, before the working directory
616 changes. */
617 void VG_(record_startup_wd) ( void )
619 # if defined(VGO_linux) || defined(VGO_solaris)
620 /* Simple: just ask the kernel */
621 SysRes res;
622 SizeT szB = 0;
623 do {
624 szB += 500;
625 startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
626 VG_(memset)(startup_wd, 0, szB);
627 res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
628 } while (sr_isError(res) && sr_Err(res) == VKI_ERANGE);
630 if (sr_isError(res)) {
631 VG_(free)(startup_wd);
632 startup_wd = NULL;
633 return;
636 vg_assert(startup_wd[szB-1] == 0);
638 # elif defined(VGO_darwin)
639 /* We can't ask the kernel, so instead rely on launcher-*.c to
640 tell us the startup path. Note the env var is keyed to the
641 parent's PID, not ours, since our parent is the launcher
642 process. */
643 { HChar envvar[100]; // large enough
644 HChar* wd;
645 VG_(memset)(envvar, 0, sizeof(envvar));
646 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
647 (Int)VG_(getppid)());
648 wd = VG_(getenv)( envvar );
649 if (wd == NULL)
650 return;
651 SizeT need = VG_(strlen)(wd) + 1;
652 startup_wd = VG_(malloc)("startup_wd", need);
653 VG_(strcpy)(startup_wd, wd);
655 # else
656 # error Unknown OS
657 # endif
660 /* Return the previously acquired startup_wd or NULL. */
661 const HChar *VG_(get_startup_wd) ( void )
663 return startup_wd;
666 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
668 SysRes res;
669 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
670 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
671 struct vki_timespec timeout_ts;
672 if (timeout >= 0) {
673 timeout_ts.tv_sec = timeout / 1000;
674 timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
676 res = VG_(do_syscall4)(__NR_ppoll,
677 (UWord)fds, nfds,
678 (UWord)(timeout >= 0 ? &timeout_ts : NULL),
679 (UWord)NULL);
680 # elif defined(VGO_linux)
681 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
682 # elif defined(VGO_darwin)
683 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
684 # elif defined(VGO_solaris)
685 struct vki_timespec ts;
686 struct vki_timespec *tsp;
688 if (timeout < 0)
689 tsp = NULL;
690 else {
691 ts.tv_sec = timeout / 1000;
692 ts.tv_nsec = (timeout % 1000) * 1000000;
693 tsp = &ts;
696 res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0);
697 # else
698 # error "Unknown OS"
699 # endif
700 return res;
704 /* Performs the readlink operation and puts the result into 'buf'.
705 Note, that the string in 'buf' is *not* null-terminated. The function
706 returns the number of characters put into 'buf' or -1 if an error
707 occurred. */
708 SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
710 SysRes res;
711 /* res = readlink( path, buf, bufsiz ); */
712 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
713 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
714 (UWord)path, (UWord)buf, bufsiz);
715 # elif defined(VGO_linux) || defined(VGO_darwin)
716 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
717 # elif defined(VGO_solaris)
718 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
719 (UWord)buf, bufsiz);
720 # else
721 # error "Unknown OS"
722 # endif
723 return sr_isError(res) ? -1 : sr_Res(res);
726 #if defined(VGO_linux) || defined(VGO_solaris)
727 Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
729 SysRes res;
730 /* res = getdents( fd, dirp, count ); */
731 # if defined(VGP_amd64_solaris)
732 /* This silently assumes that dirent64 and dirent on amd64 are same, which
733 they should always be. */
734 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
735 # else
736 res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
737 # if defined(VGA_mips64)
738 /* The MIPS64 getdents64() system call is only present in 3.10+ kernels.
739 If the getdents64() system call is not available fall back to using
740 getdents() and modify the result to be compatible with getdents64(). */
741 if (sr_isError(res) && (sr_Err(res) == VKI_ENOSYS)) {
742 int r;
743 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
744 r = sr_Res(res);
745 if (r > 0) {
746 char *p;
747 char type;
748 union dirents {
749 struct vki_dirent m;
750 struct vki_dirent64 d;
751 } *u;
752 p = (char *)dirp;
753 do {
754 u = (union dirents *)p;
755 /* This should not happen, but just in case... */
756 if (p + u->m.d_reclen > (char *)dirp + r)
757 break;
758 /* shuffle the dirent */
759 type = *(p + u->m.d_reclen - 1);
760 VG_(memmove)(u->d.d_name, u->m.d_name,
761 u->m.d_reclen - 2
762 - offsetof(struct vki_dirent, d_name) + 1);
763 u->d.d_type = type;
764 p += u->m.d_reclen;
765 } while (p < (char *)dirp + r);
768 # endif
769 # endif
770 return sr_isError(res) ? -1 : sr_Res(res);
772 #endif
774 /* Check accessibility of a file. Returns zero for access granted,
775 nonzero otherwise. */
776 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
778 # if defined(VGO_linux)
779 /* Very annoyingly, I cannot find any definition for R_OK et al in
780 the kernel interfaces. Therefore I reluctantly resort to
781 hardwiring in these magic numbers that I determined by
782 experimentation. */
783 # define VKI_R_OK 4
784 # define VKI_W_OK 2
785 # define VKI_X_OK 1
786 # endif
788 UWord w = (irusr ? VKI_R_OK : 0)
789 | (iwusr ? VKI_W_OK : 0)
790 | (ixusr ? VKI_X_OK : 0);
791 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
792 SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
793 # elif defined(VGO_linux) || defined(VGO_darwin)
794 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
795 # elif defined(VGO_solaris)
796 SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
797 w, 0);
798 # else
799 # error "Unknown OS"
800 # endif
801 return sr_isError(res) ? 1 : 0;
803 # if defined(VGO_linux)
804 # undef VKI_R_OK
805 # undef VKI_W_OK
806 # undef VKI_X_OK
807 # endif
811 Emulate the normal Unix permissions checking algorithm.
813 If owner matches, then use the owner permissions, else
814 if group matches, then use the group permissions, else
815 use other permissions.
817 Note that we can't deal properly with SUID/SGID. By default
818 (allow_setuid == False), we refuse to run them (otherwise the
819 executable may misbehave if it doesn't have the permissions it
820 thinks it does). However, the caller may indicate that setuid
821 executables are allowed, for example if we are going to exec them
822 but not trace into them (iow, client sys_execve when
823 clo_trace_children == False).
825 If VKI_EACCES is returned (iow, permission was refused), then
826 *is_setuid is set to True iff permission was refused because the
827 executable is setuid.
829 /* returns: 0 = success, non-0 is failure */
830 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
831 const HChar* f, Bool allow_setuid)
833 struct vg_stat st;
834 SysRes res = VG_(stat)(f, &st);
836 if (is_setuid)
837 *is_setuid = False;
839 if (sr_isError(res)) {
840 return sr_Err(res);
843 if ( VKI_S_ISDIR (st.mode) ) {
844 return VKI_EACCES;
847 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
848 if (is_setuid)
849 *is_setuid = True;
850 return VKI_EACCES;
853 res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
854 if (!sr_isError(res) && !allow_setuid) {
855 if (is_setuid)
856 *is_setuid = True;
857 return VKI_EACCES;
860 if (VG_(geteuid)() == st.uid) {
861 if (!(st.mode & VKI_S_IXUSR))
862 return VKI_EACCES;
863 } else {
864 Int grpmatch = 0;
866 if (VG_(getegid)() == st.gid)
867 grpmatch = 1;
868 else {
869 UInt *groups = NULL;
870 Int ngrp;
872 /* Find out # groups, allocate large enough array and fetch groups */
873 ngrp = VG_(getgroups)(0, NULL);
874 if (ngrp != -1) {
875 groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
876 ngrp = VG_(getgroups)(ngrp, groups);
879 Int i;
880 /* ngrp will be -1 if VG_(getgroups) failed. */
881 for (i = 0; i < ngrp; i++) {
882 if (groups[i] == st.gid) {
883 grpmatch = 1;
884 break;
887 VG_(free)(groups);
890 if (grpmatch) {
891 if (!(st.mode & VKI_S_IXGRP)) {
892 return VKI_EACCES;
894 } else if (!(st.mode & VKI_S_IXOTH)) {
895 return VKI_EACCES;
899 return 0;
902 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
904 SysRes res;
905 // on 32 bits platforms, we receive a 32 bits OffT but
906 // we must extend it to pass a long long 64 bits.
907 # if defined(VGP_x86_linux)
908 vg_assert(sizeof(OffT) == 4);
909 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
910 offset, 0); // Little endian long long
911 return res;
912 # elif defined(VGP_arm_linux)
913 vg_assert(sizeof(OffT) == 4);
914 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
915 0, offset); // Big endian long long
916 return res;
917 # elif defined(VGP_ppc32_linux)
918 vg_assert(sizeof(OffT) == 4);
919 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
920 0, // Padding needed on PPC32
921 0, offset); // Big endian long long
922 return res;
923 # elif (defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)) \
924 && (VKI_LITTLE_ENDIAN)
925 vg_assert(sizeof(OffT) == 4);
926 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
927 0, offset, 0);
928 return res;
929 # elif (defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)) \
930 && (VKI_BIG_ENDIAN)
931 vg_assert(sizeof(OffT) == 4);
932 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
933 0, 0, offset);
934 return res;
935 # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
936 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
937 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
938 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
939 return res;
940 # elif defined(VGP_amd64_darwin)
941 vg_assert(sizeof(OffT) == 8);
942 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
943 return res;
944 # elif defined(VGP_x86_darwin)
945 vg_assert(sizeof(OffT) == 8);
946 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
947 offset & 0xffffffff, offset >> 32);
948 return res;
949 # elif defined(VGP_x86_solaris)
950 vg_assert(sizeof(OffT) == 4);
951 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
952 return res;
953 # elif defined(VGP_amd64_solaris)
954 vg_assert(sizeof(OffT) == 8);
955 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
956 return res;
957 # else
958 # error "Unknown platform"
959 # endif
962 /* Return the name of a directory for temporary files. */
963 const HChar *VG_(tmpdir)(void)
965 const HChar *tmpdir;
967 tmpdir = VG_(getenv)("TMPDIR");
968 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
969 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */
971 return tmpdir;
974 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
976 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
978 return VG_(strlen)(mkstemp_format)
979 + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
980 + part_of_name_len - 2 // %s part_of_name
981 + 8 - 4 // %08x
982 + 1; // trailing 0
986 Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
988 Int n, tries;
989 UInt seed;
990 SysRes sres;
991 const HChar *tmpdir;
993 vg_assert(part_of_name);
994 vg_assert(fullname);
995 n = VG_(strlen)(part_of_name);
996 vg_assert(n > 0 && n < 100);
998 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
1000 /* Determine sensible location for temporary files */
1001 tmpdir = VG_(tmpdir)();
1003 tries = 0;
1004 while (True) {
1005 if (tries++ > 10)
1006 return -1;
1007 VG_(sprintf)( fullname, mkstemp_format,
1008 tmpdir, part_of_name, VG_(random)( &seed ));
1009 if (0)
1010 VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
1012 sres = VG_(open)(fullname,
1013 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
1014 VKI_S_IRUSR|VKI_S_IWUSR);
1015 if (sr_isError(sres)) {
1016 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
1017 continue;
1019 /* VG_(safe_fd) doesn't return if it fails. */
1020 return VG_(safe_fd)( sr_Res(sres) );
1022 /* NOTREACHED */
1026 /* ---------------------------------------------------------------------
1027 Socket-related stuff.
1028 ------------------------------------------------------------------ */
1030 static
1031 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
1033 static
1034 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
1036 UInt VG_(htonl) ( UInt x )
1038 # if defined(VG_BIGENDIAN)
1039 return x;
1040 # else
1041 return
1042 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1043 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1044 # endif
1047 UInt VG_(ntohl) ( UInt x )
1049 # if defined(VG_BIGENDIAN)
1050 return x;
1051 # else
1052 return
1053 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1054 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1055 # endif
1058 UShort VG_(htons) ( UShort x )
1060 # if defined(VG_BIGENDIAN)
1061 return x;
1062 # else
1063 return
1064 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1065 # endif
1068 UShort VG_(ntohs) ( UShort x )
1070 # if defined(VG_BIGENDIAN)
1071 return x;
1072 # else
1073 return
1074 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1075 # endif
1079 /* The main function.
1081 Supplied string contains either an ip address "192.168.0.1" or
1082 an ip address and port pair, "192.168.0.1:1500". Parse these,
1083 and return:
1084 -1 if there is a parse error
1085 -2 if no parse error, but specified host:port cannot be opened
1086 the relevant file (socket) descriptor, otherwise.
1087 is used.
1089 Int VG_(connect_via_socket)( const HChar* str )
1091 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris)
1092 Int sd, res;
1093 struct vki_sockaddr_in servAddr;
1094 UInt ip = 0;
1095 UShort port = VG_CLO_DEFAULT_LOGPORT;
1096 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1097 if (!ok)
1098 return -1;
1100 //if (0)
1101 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1102 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1103 // (ip >> 8) & 0xFF, ip & 0xFF,
1104 // (UInt)port );
1106 servAddr.sin_family = VKI_AF_INET;
1107 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
1108 servAddr.sin_port = VG_(htons)(port);
1110 /* create socket */
1111 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1112 if (sd < 0) {
1113 /* this shouldn't happen ... nevertheless */
1114 return -2;
1117 /* connect to server */
1118 res = my_connect(sd, &servAddr, sizeof(servAddr));
1119 if (res < 0) {
1120 /* connection failed */
1121 return -2;
1124 return sd;
1126 # else
1127 # error "Unknown OS"
1128 # endif
1132 /* Let d = one or more digits. Accept either:
1133 d.d.d.d or d.d.d.d:d
1135 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
1137 # define GET_CH ((*str) ? (*str++) : 0)
1138 UInt ipa, i, j, c, any;
1139 ipa = 0;
1140 for (i = 0; i < 4; i++) {
1141 j = 0;
1142 any = 0;
1143 while (1) {
1144 c = GET_CH;
1145 if (c < '0' || c > '9') break;
1146 j = 10 * j + (int)(c - '0');
1147 any = 1;
1149 if (any == 0 || j > 255) goto syntaxerr;
1150 ipa = (ipa << 8) + j;
1151 if (i <= 2 && c != '.') goto syntaxerr;
1153 if (c == 0 || c == ':')
1154 *ip_addr = ipa;
1155 if (c == 0) goto ok;
1156 if (c != ':') goto syntaxerr;
1157 j = 0;
1158 any = 0;
1159 while (1) {
1160 c = GET_CH;
1161 if (c < '0' || c > '9') break;
1162 j = j * 10 + (int)(c - '0');
1163 any = 1;
1164 if (j > 65535) goto syntaxerr;
1166 if (any == 0 || c != 0) goto syntaxerr;
1167 if (j < 1024) goto syntaxerr;
1168 *port = (UShort)j;
1170 return 1;
1171 syntaxerr:
1172 return 0;
1173 # undef GET_CH
1176 // GrP fixme safe_fd?
1177 Int VG_(socket) ( Int domain, Int type, Int protocol )
1179 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1180 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1181 || defined(VGP_s390x_linux)
1182 SysRes res;
1183 UWord args[3];
1184 args[0] = domain;
1185 args[1] = type;
1186 args[2] = protocol;
1187 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
1188 return sr_isError(res) ? -1 : sr_Res(res);
1190 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1191 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1192 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1193 SysRes res;
1194 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
1195 return sr_isError(res) ? -1 : sr_Res(res);
1197 # elif defined(VGO_darwin)
1198 SysRes res;
1199 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
1200 if (!sr_isError(res)) {
1201 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
1202 Int optval = 1;
1203 SysRes res2;
1204 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
1205 VKI_SO_NOSIGPIPE, (UWord)&optval,
1206 sizeof(optval));
1207 // ignore setsockopt() error
1209 return sr_isError(res) ? -1 : sr_Res(res);
1211 # elif defined(VGO_solaris)
1212 /* XXX There doesn't seem to be an easy way to convince the send syscall to
1213 only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
1214 SM_KERNEL is set on the socket. Without serious hackery it looks we
1215 can't set this flag.
1217 Should we wrap the send syscall below into sigprocmask calls to block
1218 SIGPIPE?
1220 SysRes res;
1221 res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol,
1222 0 /*devpath*/, VKI_SOV_DEFAULT /*version*/);
1223 return sr_isError(res) ? -1 : sr_Res(res);
1225 # else
1226 # error "Unknown arch"
1227 # endif
1231 static
1232 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
1234 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1235 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1236 || defined(VGP_s390x_linux)
1237 SysRes res;
1238 UWord args[3];
1239 args[0] = sockfd;
1240 args[1] = (UWord)serv_addr;
1241 args[2] = addrlen;
1242 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
1243 return sr_isError(res) ? -1 : sr_Res(res);
1245 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1246 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1247 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1248 SysRes res;
1249 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
1250 return sr_isError(res) ? -1 : sr_Res(res);
1252 # elif defined(VGO_darwin)
1253 SysRes res;
1254 res = VG_(do_syscall3)(__NR_connect_nocancel,
1255 sockfd, (UWord)serv_addr, addrlen);
1256 return sr_isError(res) ? -1 : sr_Res(res);
1258 # elif defined(VGO_solaris)
1259 SysRes res;
1260 res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen,
1261 VKI_SOV_DEFAULT /*version*/);
1262 return sr_isError(res) ? -1 : sr_Res(res);
1264 # else
1265 # error "Unknown arch"
1266 # endif
1269 Int VG_(write_socket)( Int sd, const void *msg, Int count )
1271 /* This is actually send(). */
1273 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
1274 errors on stream oriented sockets when the other end breaks the
1275 connection. The EPIPE error is still returned.
1277 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1278 SIGPIPE */
1280 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1281 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1282 || defined(VGP_s390x_linux)
1283 SysRes res;
1284 UWord args[4];
1285 args[0] = sd;
1286 args[1] = (UWord)msg;
1287 args[2] = count;
1288 args[3] = VKI_MSG_NOSIGNAL;
1289 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
1290 return sr_isError(res) ? -1 : sr_Res(res);
1292 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1293 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1294 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1295 SysRes res;
1296 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
1297 count, VKI_MSG_NOSIGNAL, 0,0);
1298 return sr_isError(res) ? -1 : sr_Res(res);
1300 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1301 SysRes res;
1302 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
1303 return sr_isError(res) ? -1 : sr_Res(res);
1305 # elif defined(VGO_solaris)
1306 SysRes res;
1307 res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/);
1308 return sr_isError(res) ? -1 : sr_Res(res);
1310 # else
1311 # error "Unknown platform"
1312 # endif
1315 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1317 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1318 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1319 || defined(VGP_s390x_linux) \
1320 || defined(VGP_mips32_linux)
1321 SysRes res;
1322 UWord args[3];
1323 args[0] = sd;
1324 args[1] = (UWord)name;
1325 args[2] = (UWord)namelen;
1326 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
1327 return sr_isError(res) ? -1 : sr_Res(res);
1329 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1330 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1331 || defined(VGP_nanomips_linux)
1332 SysRes res;
1333 res = VG_(do_syscall3)( __NR_getsockname,
1334 (UWord)sd, (UWord)name, (UWord)namelen );
1335 return sr_isError(res) ? -1 : sr_Res(res);
1337 # elif defined(VGO_darwin)
1338 SysRes res;
1339 res = VG_(do_syscall3)( __NR_getsockname,
1340 (UWord)sd, (UWord)name, (UWord)namelen );
1341 return sr_isError(res) ? -1 : sr_Res(res);
1343 # elif defined(VGO_solaris)
1344 SysRes res;
1345 res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen,
1346 VKI_SOV_DEFAULT /*version*/);
1347 return sr_isError(res) ? -1 : sr_Res(res);
1349 # else
1350 # error "Unknown platform"
1351 # endif
1354 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1356 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1357 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1358 || defined(VGP_s390x_linux) \
1359 || defined(VGP_mips32_linux)
1360 SysRes res;
1361 UWord args[3];
1362 args[0] = sd;
1363 args[1] = (UWord)name;
1364 args[2] = (UWord)namelen;
1365 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
1366 return sr_isError(res) ? -1 : sr_Res(res);
1368 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1369 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1370 || defined(VGP_nanomips_linux)
1371 SysRes res;
1372 res = VG_(do_syscall3)( __NR_getpeername,
1373 (UWord)sd, (UWord)name, (UWord)namelen );
1374 return sr_isError(res) ? -1 : sr_Res(res);
1376 # elif defined(VGO_darwin)
1377 SysRes res;
1378 res = VG_(do_syscall3)( __NR_getpeername,
1379 (UWord)sd, (UWord)name, (UWord)namelen );
1380 return sr_isError(res) ? -1 : sr_Res(res);
1382 # elif defined(VGO_solaris)
1383 SysRes res;
1384 res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen,
1385 VKI_SOV_DEFAULT /*version*/);
1386 return sr_isError(res) ? -1 : sr_Res(res);
1388 # else
1389 # error "Unknown platform"
1390 # endif
1393 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1394 Int *optlen)
1396 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1397 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1398 || defined(VGP_s390x_linux)
1399 SysRes res;
1400 UWord args[5];
1401 args[0] = sd;
1402 args[1] = level;
1403 args[2] = optname;
1404 args[3] = (UWord)optval;
1405 args[4] = (UWord)optlen;
1406 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
1407 return sr_isError(res) ? -1 : sr_Res(res);
1409 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1410 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1411 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1412 SysRes res;
1413 res = VG_(do_syscall5)( __NR_getsockopt,
1414 (UWord)sd, (UWord)level, (UWord)optname,
1415 (UWord)optval, (UWord)optlen );
1416 return sr_isError(res) ? -1 : sr_Res(res);
1418 # elif defined(VGO_darwin)
1419 SysRes res;
1420 res = VG_(do_syscall5)( __NR_getsockopt,
1421 (UWord)sd, (UWord)level, (UWord)optname,
1422 (UWord)optval, (UWord)optlen );
1423 return sr_isError(res) ? -1 : sr_Res(res);
1425 # elif defined(VGO_solaris)
1426 SysRes res;
1427 res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval,
1428 (UWord)optlen, VKI_SOV_DEFAULT /*version*/);
1429 return sr_isError(res) ? -1 : sr_Res(res);
1431 # else
1432 # error "Unknown platform"
1433 # endif
1437 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
1438 Int optlen)
1440 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1441 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1442 || defined(VGP_s390x_linux)
1443 SysRes res;
1444 UWord args[5];
1445 args[0] = sd;
1446 args[1] = level;
1447 args[2] = optname;
1448 args[3] = (UWord)optval;
1449 args[4] = (UWord)optlen;
1450 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
1451 return sr_isError(res) ? -1 : sr_Res(res);
1453 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1454 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1455 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1456 SysRes res;
1457 res = VG_(do_syscall5)( __NR_setsockopt,
1458 (UWord)sd, (UWord)level, (UWord)optname,
1459 (UWord)optval, (UWord)optlen );
1460 return sr_isError(res) ? -1 : sr_Res(res);
1462 # elif defined(VGO_darwin)
1463 SysRes res;
1464 res = VG_(do_syscall5)( __NR_setsockopt,
1465 (UWord)sd, (UWord)level, (UWord)optname,
1466 (UWord)optval, (UWord)optlen );
1467 return sr_isError(res) ? -1 : sr_Res(res);
1469 # elif defined(VGO_solaris)
1470 SysRes res;
1471 res = VG_(do_syscall6)( __NR_setsockopt,
1472 (UWord)sd, (UWord)level, (UWord)optname,
1473 (UWord)optval, (UWord)optlen,
1474 VKI_SOV_DEFAULT /*version*/ );
1475 return sr_isError(res) ? -1 : sr_Res(res);
1477 # else
1478 # error "Unknown platform"
1479 # endif
1483 const HChar *VG_(basename)(const HChar *path)
1485 static HChar *buf = NULL;
1486 static SizeT buf_len = 0;
1487 const HChar *p, *end;
1489 if (path == NULL ||
1490 0 == VG_(strcmp)(path, ""))
1492 return ".";
1495 p = path + VG_(strlen)(path);
1496 while (p > path && *p == '/') {
1497 // skip all trailing '/'
1498 p--;
1501 if (p == path && *p == '/') return "/"; // all slashes
1503 end = p;
1505 while (p > path && *p != '/') {
1506 // now skip non '/'
1507 p--;
1510 if (*p == '/') p++;
1512 SizeT need = end-p+1 + 1;
1513 if (need > buf_len) {
1514 buf_len = (buf_len == 0) ? 500 : need;
1515 buf = VG_(realloc)("basename", buf, buf_len);
1517 VG_(strncpy)(buf, p, end-p+1);
1518 buf[end-p+1] = '\0';
1520 return buf;
1524 const HChar *VG_(dirname)(const HChar *path)
1526 static HChar *buf = NULL;
1527 static SizeT buf_len = 0;
1529 const HChar *p;
1531 if (path == NULL ||
1532 0 == VG_(strcmp)(path, "") ||
1533 0 == VG_(strcmp)(path, "/"))
1535 return ".";
1538 p = path + VG_(strlen)(path);
1539 while (p > path && *p == '/') {
1540 // skip all trailing '/'
1541 p--;
1544 while (p > path && *p != '/') {
1545 // now skip non '/'
1546 p--;
1549 if (p == path) {
1550 if (*p == '/') return "/"; // all slashes
1551 else return "."; // no slashes
1554 while (p > path && *p == '/') {
1555 // skip '/' again
1556 p--;
1559 SizeT need = p-path+1 + 1;
1560 if (need > buf_len) {
1561 buf_len = (buf_len == 0) ? 500 : need;
1562 buf = VG_(realloc)("dirname", buf, buf_len);
1564 VG_(strncpy)(buf, path, p-path+1);
1565 buf[p-path+1] = '\0';
1567 return buf;
1571 /*--------------------------------------------------------------------*/
1572 /*--- end ---*/
1573 /*--------------------------------------------------------------------*/