drd: Add a consistency check
[valgrind.git] / coregrind / m_libcfile.c
blob210d49b00d14a2510791f38dbc0aa28504012f1f
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-2013 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, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
29 The GNU General Public License is contained in the file COPYING.
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_debuglog.h"
36 #include "pub_core_libcbase.h"
37 #include "pub_core_libcassert.h"
38 #include "pub_core_libcfile.h"
39 #include "pub_core_libcprint.h" // VG_(sprintf)
40 #include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
41 #include "pub_core_clientstate.h" // VG_(fd_hard_limit)
42 #include "pub_core_mallocfree.h" // VG_(realloc)
43 #include "pub_core_syscall.h"
45 /* 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. */
50 /* ---------------------------------------------------------------------
51 File stuff
52 ------------------------------------------------------------------ */
54 /* Move an fd into the Valgrind-safe range */
55 Int VG_(safe_fd)(Int oldfd)
57 Int newfd;
59 vg_assert(VG_(fd_hard_limit) != -1);
61 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
62 if (newfd != -1)
63 VG_(close)(oldfd);
65 /* Set the close-on-exec flag for this fd. */
66 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
68 vg_assert(newfd >= VG_(fd_hard_limit));
69 return newfd;
72 /* 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,
74 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. */
79 Bool VG_(resolve_filename) ( Int fd, const HChar** result )
81 # if defined(VGO_linux)
82 static HChar *buf = NULL;
83 static SizeT bufsiz = 0;
85 if (buf == NULL) { // first time
86 bufsiz = 500;
87 buf = VG_(malloc)("resolve_filename", bufsiz);
90 HChar tmp[64]; // large enough
91 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
93 while (42) {
94 SSizeT res = VG_(readlink)(tmp, buf, bufsiz);
95 if (res < 0) break;
96 if (res == bufsiz) { // buffer too small; increase and retry
97 bufsiz += 500;
98 buf = VG_(realloc)("resolve_filename", buf, bufsiz);
99 continue;
101 vg_assert(bufsiz > res); // paranoia
102 if (buf[0] != '/') break;
104 buf[res] = '\0';
105 *result = buf;
106 return True;
108 // Failure
109 *result = NULL;
110 return False;
112 # elif defined(VGO_darwin)
113 HChar tmp[VKI_MAXPATHLEN+1];
114 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
115 static HChar *buf = NULL;
117 if (buf == NULL)
118 buf = VG_(malloc)("resolve_filename", VKI_MAXPATHLEN+1);
119 VG_(strcpy)( buf, tmp );
121 *result = buf;
122 if (buf[0] == '/') return True;
124 // Failure
125 *result = NULL;
126 return False;
128 # else
129 # error Unknown OS
130 # endif
133 SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
135 # if defined(VGP_arm64_linux)
136 /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
137 SysRes res = VG_(do_syscall4)(__NR_mknodat,
138 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
139 # elif defined(VGO_linux) || defined(VGO_darwin)
140 SysRes res = VG_(do_syscall3)(__NR_mknod,
141 (UWord)pathname, mode, dev);
142 # else
143 # error Unknown OS
144 # endif
145 return res;
148 SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
150 # if defined(VGP_arm64_linux)
151 /* ARM64 wants to use __NR_openat rather than __NR_open. */
152 SysRes res = VG_(do_syscall4)(__NR_openat,
153 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
154 # elif defined(VGO_linux)
155 SysRes res = VG_(do_syscall3)(__NR_open,
156 (UWord)pathname, flags, mode);
157 # elif defined(VGO_darwin)
158 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
159 (UWord)pathname, flags, mode);
160 # else
161 # error Unknown OS
162 # endif
163 return res;
166 Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
168 SysRes sr;
169 sr = VG_(open) (pathname, flags, mode);
170 if (sr_isError (sr))
171 return -1;
172 else
173 return sr_Res (sr);
176 void VG_(close) ( Int fd )
178 /* Hmm. Return value is not checked. That's uncool. */
179 # if defined(VGO_linux)
180 (void)VG_(do_syscall1)(__NR_close, fd);
181 # elif defined(VGO_darwin)
182 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
183 # else
184 # error Unknown OS
185 # endif
188 Int VG_(read) ( Int fd, void* buf, Int count)
190 Int ret;
191 # if defined(VGO_linux)
192 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
193 # elif defined(VGO_darwin)
194 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
195 # else
196 # error Unknown OS
197 # endif
198 if (sr_isError(res)) {
199 ret = - (Int)(Word)sr_Err(res);
200 vg_assert(ret < 0);
201 } else {
202 ret = (Int)(Word)sr_Res(res);
203 vg_assert(ret >= 0);
205 return ret;
208 Int VG_(write) ( Int fd, const void* buf, Int count)
210 Int ret;
211 # if defined(VGO_linux)
212 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
213 # elif defined(VGO_darwin)
214 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
215 # else
216 # error "Unknown OS"
217 # endif
218 if (sr_isError(res)) {
219 ret = - (Int)(Word)sr_Err(res);
220 vg_assert(ret < 0);
221 } else {
222 ret = (Int)(Word)sr_Res(res);
223 vg_assert(ret >= 0);
225 return ret;
229 Int VG_(pipe) ( Int fd[2] )
231 # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
232 /* __NR_pipe has a strange return convention on mips32-linux. */
233 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
234 if (!sr_isError(res)) {
235 fd[0] = (Int)sr_Res(res);
236 fd[1] = (Int)sr_ResEx(res);
237 return 0;
238 } else {
239 return -1;
241 # elif defined(VGP_arm64_linux)
242 SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
243 return sr_isError(res) ? -1 : 0;
244 # elif defined(VGO_linux)
245 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
246 return sr_isError(res) ? -1 : 0;
247 # elif defined(VGO_darwin)
248 /* __NR_pipe is UX64, so produces a double-word result */
249 SysRes res = VG_(do_syscall0)(__NR_pipe);
250 if (!sr_isError(res)) {
251 fd[0] = (Int)sr_Res(res);
252 fd[1] = (Int)sr_ResHI(res);
254 return sr_isError(res) ? -1 : 0;
255 # else
256 # error "Unknown OS"
257 # endif
260 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
262 # if defined(VGO_linux) || defined(VGP_amd64_darwin)
263 # if defined(__NR__llseek)
264 Off64T result;
265 SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
266 offset >> 32, offset & 0xffffffff,
267 (UWord)&result, whence);
268 return sr_isError(res) ? (-1) : result;
269 # else
270 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
271 vg_assert(sizeof(Off64T) == sizeof(Word));
272 return sr_isError(res) ? (-1) : sr_Res(res);
273 # endif
274 # elif defined(VGP_x86_darwin)
275 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
276 offset & 0xffffffff, offset >> 32, whence);
277 return sr_isError(res) ? (-1) : sr_Res(res);
278 # else
279 # error "Unknown plat"
280 # endif
281 /* if you change the error-reporting conventions of this, also
282 change all usage points. */
286 /* stat/fstat support. It's uggerly. We have impedance-match into a
287 'struct vg_stat' in order to have a single structure that callers
288 can use consistently on all platforms. */
290 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
291 do { \
292 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
293 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
294 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
295 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
296 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
297 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
298 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
299 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
300 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
301 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
302 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
303 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
304 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
305 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
306 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
307 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
308 } while (0)
310 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
312 SysRes res;
313 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
315 # if defined(VGO_linux) || defined(VGO_darwin)
316 /* First try with stat64. If that doesn't work out, fall back to
317 the vanilla version. */
318 # if defined(__NR_stat64)
319 { struct vki_stat64 buf64;
320 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
321 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
322 /* Success, or any failure except ENOSYS */
323 if (!sr_isError(res))
324 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
325 return res;
328 # endif /* defined(__NR_stat64) */
329 /* This is the fallback ("vanilla version"). */
330 { struct vki_stat buf;
331 # if defined(VGP_arm64_linux)
332 res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
333 (UWord)file_name, (UWord)&buf);
334 # else
335 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
336 # endif
337 if (!sr_isError(res))
338 TRANSLATE_TO_vg_stat(vgbuf, &buf);
339 return res;
342 # else
343 # error Unknown OS
344 # endif
347 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
349 SysRes res;
350 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
352 # if defined(VGO_linux) || defined(VGO_darwin)
353 /* First try with fstat64. If that doesn't work out, fall back to
354 the vanilla version. */
355 # if defined(__NR_fstat64)
356 { struct vki_stat64 buf64;
357 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
358 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
359 /* Success, or any failure except ENOSYS */
360 if (!sr_isError(res))
361 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
362 return sr_isError(res) ? (-1) : 0;
365 # endif /* if defined(__NR_fstat64) */
366 { struct vki_stat buf;
367 res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf);
368 if (!sr_isError(res))
369 TRANSLATE_TO_vg_stat(vgbuf, &buf);
370 return sr_isError(res) ? (-1) : 0;
373 # else
374 # error Unknown OS
375 # endif
378 #undef TRANSLATE_TO_vg_stat
381 Long VG_(fsize) ( Int fd )
383 struct vg_stat buf;
384 Int res = VG_(fstat)( fd, &buf );
385 return (res == -1) ? (-1LL) : buf.size;
388 SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
390 SysRes res;
391 #if defined(VGO_linux)
392 res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
393 attr_value, attr_value_len);
394 #else
395 res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
396 #endif
397 return res;
400 Bool VG_(is_dir) ( const HChar* f )
402 struct vg_stat buf;
403 SysRes res = VG_(stat)(f, &buf);
404 return sr_isError(res) ? False
405 : VKI_S_ISDIR(buf.mode) ? True : False;
408 SysRes VG_(dup) ( Int oldfd )
410 return VG_(do_syscall1)(__NR_dup, oldfd);
413 SysRes VG_(dup2) ( Int oldfd, Int newfd )
415 # if defined(VGO_linux) || defined(VGO_darwin)
416 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
417 # else
418 # error Unknown OS
419 # endif
422 /* Returns -1 on error. */
423 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
425 # if defined(VGO_linux)
426 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
427 # elif defined(VGO_darwin)
428 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
429 # else
430 # error "Unknown OS"
431 # endif
432 return sr_isError(res) ? -1 : sr_Res(res);
435 Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
437 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
438 return sr_isError(res) ? (-1) : 0;
441 Int VG_(unlink) ( const HChar* file_name )
443 # if defined(VGP_arm64_linux)
444 SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
445 (UWord)file_name);
446 # else
447 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
448 # endif
449 return sr_isError(res) ? (-1) : 0;
452 /* The working directory at startup.
453 All that is really needed is to note the cwd at process startup.
454 Hence VG_(record_startup_wd) notes it (in a platform dependent way)
455 and VG_(get_startup_wd) produces the noted value. */
456 static HChar *startup_wd;
457 static Bool startup_wd_acquired = False;
459 /* Record the process' working directory at startup. Is intended to
460 be called exactly once, at startup, before the working directory
461 changes. Return True for success, False for failure, so that the
462 caller can bomb out suitably without creating module cycles if
463 there is a problem. */
464 Bool VG_(record_startup_wd) ( void )
466 vg_assert(!startup_wd_acquired);
468 # if defined(VGO_linux)
469 /* Simple: just ask the kernel */
470 SysRes res;
471 SizeT szB = 0;
472 do {
473 szB += 500;
474 startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
475 VG_(memset)(startup_wd, 0, szB);
476 res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
477 } while (sr_isError(res));
479 vg_assert(startup_wd[szB-1] == 0);
480 startup_wd_acquired = True;
481 return True;
483 # elif defined(VGO_darwin)
484 /* We can't ask the kernel, so instead rely on launcher-*.c to
485 tell us the startup path. Note the env var is keyed to the
486 parent's PID, not ours, since our parent is the launcher
487 process. */
488 { HChar envvar[100]; // large enough
489 HChar* wd;
490 VG_(memset)(envvar, 0, sizeof(envvar));
491 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
492 (Int)VG_(getppid)());
493 wd = VG_(getenv)( envvar );
494 if (wd == NULL)
495 return False;
496 SizeT need = VG_(strlen)(wd) + 1;
497 startup_wd = VG_(malloc)("startup_wd", need);
498 VG_(strcpy)(startup_wd, wd);
499 startup_wd_acquired = True;
500 return True;
502 # else
503 # error Unknown OS
504 # endif
507 /* Return the previously acquired startup_wd. */
508 const HChar *VG_(get_startup_wd) ( void )
510 vg_assert(startup_wd_acquired);
512 return startup_wd;
515 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
517 SysRes res;
518 # if defined(VGP_arm64_linux)
519 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
520 struct vki_timespec timeout_ts;
521 if (timeout >= 0) {
522 timeout_ts.tv_sec = timeout / 1000;
523 timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
525 res = VG_(do_syscall4)(__NR_ppoll,
526 (UWord)fds, nfds,
527 (UWord)(timeout >= 0 ? &timeout_ts : NULL),
528 (UWord)NULL);
529 # elif defined(VGO_linux)
530 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
531 # elif defined(VGO_darwin)
532 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
533 # else
534 # error "Unknown OS"
535 # endif
536 return res;
540 /* Performs the readlink operation and puts the result into 'buf'.
541 Note, that the string in 'buf' is *not* null-terminated. The function
542 returns the number of characters put into 'buf' or -1 if an error
543 occurred. */
544 SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
546 SysRes res;
547 /* res = readlink( path, buf, bufsiz ); */
548 # if defined(VGP_arm64_linux)
549 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
550 (UWord)path, (UWord)buf, bufsiz);
551 # else
552 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
553 # endif
554 return sr_isError(res) ? -1 : sr_Res(res);
557 #if defined(VGO_linux)
558 Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
560 SysRes res;
561 /* res = getdents( fd, dirp, count ); */
562 res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
563 return sr_isError(res) ? -1 : sr_Res(res);
565 #endif
567 /* Check accessibility of a file. Returns zero for access granted,
568 nonzero otherwise. */
569 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
571 # if defined(VGO_linux)
572 /* Very annoyingly, I cannot find any definition for R_OK et al in
573 the kernel interfaces. Therefore I reluctantly resort to
574 hardwiring in these magic numbers that I determined by
575 experimentation. */
576 # define VKI_R_OK 4
577 # define VKI_W_OK 2
578 # define VKI_X_OK 1
579 # endif
581 UWord w = (irusr ? VKI_R_OK : 0)
582 | (iwusr ? VKI_W_OK : 0)
583 | (ixusr ? VKI_X_OK : 0);
584 # if defined(VGP_arm64_linux)
585 SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
586 # else
587 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
588 # endif
589 return sr_isError(res) ? 1 : 0;
591 # if defined(VGO_linux)
592 # undef VKI_R_OK
593 # undef VKI_W_OK
594 # undef VKI_X_OK
595 # endif
599 Emulate the normal Unix permissions checking algorithm.
601 If owner matches, then use the owner permissions, else
602 if group matches, then use the group permissions, else
603 use other permissions.
605 Note that we can't deal properly with SUID/SGID. By default
606 (allow_setuid == False), we refuse to run them (otherwise the
607 executable may misbehave if it doesn't have the permissions it
608 thinks it does). However, the caller may indicate that setuid
609 executables are allowed, for example if we are going to exec them
610 but not trace into them (iow, client sys_execve when
611 clo_trace_children == False).
613 If VKI_EACCES is returned (iow, permission was refused), then
614 *is_setuid is set to True iff permission was refused because the
615 executable is setuid.
617 /* returns: 0 = success, non-0 is failure */
618 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
619 const HChar* f, Bool allow_setuid)
621 struct vg_stat st;
622 SysRes res = VG_(stat)(f, &st);
624 if (is_setuid)
625 *is_setuid = False;
627 if (sr_isError(res)) {
628 return sr_Err(res);
631 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
632 if (is_setuid)
633 *is_setuid = True;
634 return VKI_EACCES;
637 res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
638 if (!sr_isError(res) && !allow_setuid) {
639 if (is_setuid)
640 *is_setuid = True;
641 return VKI_EACCES;
644 if (VG_(geteuid)() == st.uid) {
645 if (!(st.mode & VKI_S_IXUSR))
646 return VKI_EACCES;
647 } else {
648 Int grpmatch = 0;
650 if (VG_(getegid)() == st.gid)
651 grpmatch = 1;
652 else {
653 UInt *groups = NULL;
654 Int ngrp;
656 /* Find out # groups, allocate large enough array and fetch groups */
657 ngrp = VG_(getgroups)(0, NULL);
658 if (ngrp != -1) {
659 groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
660 ngrp = VG_(getgroups)(ngrp, groups);
663 Int i;
664 /* ngrp will be -1 if VG_(getgroups) failed. */
665 for (i = 0; i < ngrp; i++) {
666 if (groups[i] == st.gid) {
667 grpmatch = 1;
668 break;
671 VG_(free)(groups);
674 if (grpmatch) {
675 if (!(st.mode & VKI_S_IXGRP)) {
676 return VKI_EACCES;
678 } else if (!(st.mode & VKI_S_IXOTH)) {
679 return VKI_EACCES;
683 return 0;
686 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
688 SysRes res;
689 // on 32 bits platforms, we receive a 32 bits OffT but
690 // we must extend it to pass a long long 64 bits.
691 # if defined(VGP_x86_linux)
692 vg_assert(sizeof(OffT) == 4);
693 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
694 offset, 0); // Little endian long long
695 return res;
696 # elif defined(VGP_arm_linux)
697 vg_assert(sizeof(OffT) == 4);
698 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
699 0, offset); // Big endian long long
700 return res;
701 # elif defined(VGP_ppc32_linux)
702 vg_assert(sizeof(OffT) == 4);
703 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
704 0, // Padding needed on PPC32
705 0, offset); // Big endian long long
706 return res;
707 # elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN)
708 vg_assert(sizeof(OffT) == 4);
709 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
710 0, offset, 0);
711 return res;
712 # elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN)
713 vg_assert(sizeof(OffT) == 4);
714 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
715 0, 0, offset);
716 return res;
717 # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
718 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
719 || defined(VGP_mips64_linux) \
720 || defined(VGP_arm64_linux)
721 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
722 return res;
723 # elif defined(VGP_amd64_darwin)
724 vg_assert(sizeof(OffT) == 8);
725 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
726 return res;
727 # elif defined(VGP_x86_darwin)
728 vg_assert(sizeof(OffT) == 8);
729 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
730 offset & 0xffffffff, offset >> 32);
731 return res;
732 # else
733 # error "Unknown platform"
734 # endif
737 /* Return the name of a directory for temporary files. */
738 const HChar *VG_(tmpdir)(void)
740 const HChar *tmpdir;
742 tmpdir = VG_(getenv)("TMPDIR");
743 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
744 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */
746 return tmpdir;
749 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
751 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
753 return VG_(strlen)(mkstemp_format)
754 + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
755 + part_of_name_len - 2 // %s part_of_name
756 + 8 - 4 // %08x
757 + 1; // trailing 0
761 Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
763 Int n, tries;
764 UInt seed;
765 SysRes sres;
766 const HChar *tmpdir;
768 vg_assert(part_of_name);
769 vg_assert(fullname);
770 n = VG_(strlen)(part_of_name);
771 vg_assert(n > 0 && n < 100);
773 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
775 /* Determine sensible location for temporary files */
776 tmpdir = VG_(tmpdir)();
778 tries = 0;
779 while (True) {
780 if (tries++ > 10)
781 return -1;
782 VG_(sprintf)( fullname, mkstemp_format,
783 tmpdir, part_of_name, VG_(random)( &seed ));
784 if (0)
785 VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
787 sres = VG_(open)(fullname,
788 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
789 VKI_S_IRUSR|VKI_S_IWUSR);
790 if (sr_isError(sres)) {
791 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
792 continue;
794 /* VG_(safe_fd) doesn't return if it fails. */
795 return VG_(safe_fd)( sr_Res(sres) );
797 /* NOTREACHED */
801 /* ---------------------------------------------------------------------
802 Socket-related stuff.
803 ------------------------------------------------------------------ */
805 static
806 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
808 static
809 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
811 UInt VG_(htonl) ( UInt x )
813 # if defined(VG_BIGENDIAN)
814 return x;
815 # else
816 return
817 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
818 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
819 # endif
822 UInt VG_(ntohl) ( UInt x )
824 # if defined(VG_BIGENDIAN)
825 return x;
826 # else
827 return
828 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
829 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
830 # endif
833 UShort VG_(htons) ( UShort x )
835 # if defined(VG_BIGENDIAN)
836 return x;
837 # else
838 return
839 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
840 # endif
843 UShort VG_(ntohs) ( UShort x )
845 # if defined(VG_BIGENDIAN)
846 return x;
847 # else
848 return
849 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
850 # endif
854 /* The main function.
856 Supplied string contains either an ip address "192.168.0.1" or
857 an ip address and port pair, "192.168.0.1:1500". Parse these,
858 and return:
859 -1 if there is a parse error
860 -2 if no parse error, but specified host:port cannot be opened
861 the relevant file (socket) descriptor, otherwise.
862 is used.
864 Int VG_(connect_via_socket)( const HChar* str )
866 # if defined(VGO_linux) || defined(VGO_darwin)
867 Int sd, res;
868 struct vki_sockaddr_in servAddr;
869 UInt ip = 0;
870 UShort port = VG_CLO_DEFAULT_LOGPORT;
871 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
872 if (!ok)
873 return -1;
875 //if (0)
876 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
877 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
878 // (ip >> 8) & 0xFF, ip & 0xFF,
879 // (UInt)port );
881 servAddr.sin_family = VKI_AF_INET;
882 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
883 servAddr.sin_port = VG_(htons)(port);
885 /* create socket */
886 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
887 if (sd < 0) {
888 /* this shouldn't happen ... nevertheless */
889 return -2;
892 /* connect to server */
893 res = my_connect(sd, &servAddr, sizeof(servAddr));
894 if (res < 0) {
895 /* connection failed */
896 return -2;
899 return sd;
901 # else
902 # error "Unknown OS"
903 # endif
907 /* Let d = one or more digits. Accept either:
908 d.d.d.d or d.d.d.d:d
910 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
912 # define GET_CH ((*str) ? (*str++) : 0)
913 UInt ipa, i, j, c, any;
914 ipa = 0;
915 for (i = 0; i < 4; i++) {
916 j = 0;
917 any = 0;
918 while (1) {
919 c = GET_CH;
920 if (c < '0' || c > '9') break;
921 j = 10 * j + (int)(c - '0');
922 any = 1;
924 if (any == 0 || j > 255) goto syntaxerr;
925 ipa = (ipa << 8) + j;
926 if (i <= 2 && c != '.') goto syntaxerr;
928 if (c == 0 || c == ':')
929 *ip_addr = ipa;
930 if (c == 0) goto ok;
931 if (c != ':') goto syntaxerr;
932 j = 0;
933 any = 0;
934 while (1) {
935 c = GET_CH;
936 if (c < '0' || c > '9') break;
937 j = j * 10 + (int)(c - '0');
938 any = 1;
939 if (j > 65535) goto syntaxerr;
941 if (any == 0 || c != 0) goto syntaxerr;
942 if (j < 1024) goto syntaxerr;
943 *port = (UShort)j;
945 return 1;
946 syntaxerr:
947 return 0;
948 # undef GET_CH
951 // GrP fixme safe_fd?
952 Int VG_(socket) ( Int domain, Int type, Int protocol )
954 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
955 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
956 || defined(VGP_s390x_linux)
957 SysRes res;
958 UWord args[3];
959 args[0] = domain;
960 args[1] = type;
961 args[2] = protocol;
962 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
963 return sr_isError(res) ? -1 : sr_Res(res);
965 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
966 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
967 || defined(VGP_arm64_linux)
968 SysRes res;
969 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
970 return sr_isError(res) ? -1 : sr_Res(res);
972 # elif defined(VGO_darwin)
973 SysRes res;
974 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
975 if (!sr_isError(res)) {
976 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
977 Int optval = 1;
978 SysRes res2;
979 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
980 VKI_SO_NOSIGPIPE, (UWord)&optval,
981 sizeof(optval));
982 // ignore setsockopt() error
984 return sr_isError(res) ? -1 : sr_Res(res);
986 # else
987 # error "Unknown arch"
988 # endif
992 static
993 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
995 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
996 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
997 || defined(VGP_s390x_linux)
998 SysRes res;
999 UWord args[3];
1000 args[0] = sockfd;
1001 args[1] = (UWord)serv_addr;
1002 args[2] = addrlen;
1003 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
1004 return sr_isError(res) ? -1 : sr_Res(res);
1006 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1007 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1008 || defined(VGP_arm64_linux)
1009 SysRes res;
1010 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
1011 return sr_isError(res) ? -1 : sr_Res(res);
1013 # elif defined(VGO_darwin)
1014 SysRes res;
1015 res = VG_(do_syscall3)(__NR_connect_nocancel,
1016 sockfd, (UWord)serv_addr, addrlen);
1017 return sr_isError(res) ? -1 : sr_Res(res);
1019 # else
1020 # error "Unknown arch"
1021 # endif
1024 Int VG_(write_socket)( Int sd, const void *msg, Int count )
1026 /* This is actually send(). */
1028 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
1029 errors on stream oriented sockets when the other end breaks the
1030 connection. The EPIPE error is still returned.
1032 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1033 SIGPIPE */
1035 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1036 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1037 || defined(VGP_s390x_linux)
1038 SysRes res;
1039 UWord args[4];
1040 args[0] = sd;
1041 args[1] = (UWord)msg;
1042 args[2] = count;
1043 args[3] = VKI_MSG_NOSIGNAL;
1044 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
1045 return sr_isError(res) ? -1 : sr_Res(res);
1047 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1048 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1049 || defined(VGP_arm64_linux)
1050 SysRes res;
1051 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
1052 count, VKI_MSG_NOSIGNAL, 0,0);
1053 return sr_isError(res) ? -1 : sr_Res(res);
1055 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1056 SysRes res;
1057 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
1058 return sr_isError(res) ? -1 : sr_Res(res);
1060 # else
1061 # error "Unknown platform"
1062 # endif
1065 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1067 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1068 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1069 || defined(VGP_s390x_linux) \
1070 || defined(VGP_mips32_linux)
1071 SysRes res;
1072 UWord args[3];
1073 args[0] = sd;
1074 args[1] = (UWord)name;
1075 args[2] = (UWord)namelen;
1076 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
1077 return sr_isError(res) ? -1 : sr_Res(res);
1079 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1080 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
1081 SysRes res;
1082 res = VG_(do_syscall3)( __NR_getsockname,
1083 (UWord)sd, (UWord)name, (UWord)namelen );
1084 return sr_isError(res) ? -1 : sr_Res(res);
1086 # elif defined(VGO_darwin)
1087 SysRes res;
1088 res = VG_(do_syscall3)( __NR_getsockname,
1089 (UWord)sd, (UWord)name, (UWord)namelen );
1090 return sr_isError(res) ? -1 : sr_Res(res);
1092 # else
1093 # error "Unknown platform"
1094 # endif
1097 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1099 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1100 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1101 || defined(VGP_s390x_linux) \
1102 || defined(VGP_mips32_linux)
1103 SysRes res;
1104 UWord args[3];
1105 args[0] = sd;
1106 args[1] = (UWord)name;
1107 args[2] = (UWord)namelen;
1108 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
1109 return sr_isError(res) ? -1 : sr_Res(res);
1111 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1112 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
1113 SysRes res;
1114 res = VG_(do_syscall3)( __NR_getpeername,
1115 (UWord)sd, (UWord)name, (UWord)namelen );
1116 return sr_isError(res) ? -1 : sr_Res(res);
1118 # elif defined(VGO_darwin)
1119 SysRes res;
1120 res = VG_(do_syscall3)( __NR_getpeername,
1121 (UWord)sd, (UWord)name, (UWord)namelen );
1122 return sr_isError(res) ? -1 : sr_Res(res);
1124 # else
1125 # error "Unknown platform"
1126 # endif
1129 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1130 Int *optlen)
1132 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1133 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1134 || defined(VGP_s390x_linux)
1135 SysRes res;
1136 UWord args[5];
1137 args[0] = sd;
1138 args[1] = level;
1139 args[2] = optname;
1140 args[3] = (UWord)optval;
1141 args[4] = (UWord)optlen;
1142 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
1143 return sr_isError(res) ? -1 : sr_Res(res);
1145 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1146 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1147 || defined(VGP_arm64_linux)
1148 SysRes res;
1149 res = VG_(do_syscall5)( __NR_getsockopt,
1150 (UWord)sd, (UWord)level, (UWord)optname,
1151 (UWord)optval, (UWord)optlen );
1152 return sr_isError(res) ? -1 : sr_Res(res);
1154 # elif defined(VGO_darwin)
1155 SysRes res;
1156 res = VG_(do_syscall5)( __NR_getsockopt,
1157 (UWord)sd, (UWord)level, (UWord)optname,
1158 (UWord)optval, (UWord)optlen );
1159 return sr_isError(res) ? -1 : sr_Res(res);
1161 # else
1162 # error "Unknown platform"
1163 # endif
1167 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
1168 Int optlen)
1170 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1171 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1172 || defined(VGP_s390x_linux)
1173 SysRes res;
1174 UWord args[5];
1175 args[0] = sd;
1176 args[1] = level;
1177 args[2] = optname;
1178 args[3] = (UWord)optval;
1179 args[4] = (UWord)optlen;
1180 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
1181 return sr_isError(res) ? -1 : sr_Res(res);
1183 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1184 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1185 || defined(VGP_arm64_linux)
1186 SysRes res;
1187 res = VG_(do_syscall5)( __NR_setsockopt,
1188 (UWord)sd, (UWord)level, (UWord)optname,
1189 (UWord)optval, (UWord)optlen );
1190 return sr_isError(res) ? -1 : sr_Res(res);
1192 # elif defined(VGO_darwin)
1193 SysRes res;
1194 res = VG_(do_syscall5)( __NR_setsockopt,
1195 (UWord)sd, (UWord)level, (UWord)optname,
1196 (UWord)optval, (UWord)optlen );
1197 return sr_isError(res) ? -1 : sr_Res(res);
1199 # else
1200 # error "Unknown platform"
1201 # endif
1205 const HChar *VG_(basename)(const HChar *path)
1207 static HChar *buf = NULL;
1208 static SizeT buf_len = 0;
1209 const HChar *p, *end;
1211 if (path == NULL ||
1212 0 == VG_(strcmp)(path, ""))
1214 return ".";
1217 p = path + VG_(strlen)(path);
1218 while (p > path && *p == '/') {
1219 // skip all trailing '/'
1220 p--;
1223 if (p == path && *p == '/') return "/"; // all slashes
1225 end = p;
1227 while (p > path && *p != '/') {
1228 // now skip non '/'
1229 p--;
1232 if (*p == '/') p++;
1234 SizeT need = end-p+1 + 1;
1235 if (need > buf_len) {
1236 buf_len = (buf_len == 0) ? 500 : need;
1237 buf = VG_(realloc)("basename", buf, buf_len);
1239 VG_(strncpy)(buf, p, end-p+1);
1240 buf[end-p+1] = '\0';
1242 return buf;
1246 const HChar *VG_(dirname)(const HChar *path)
1248 static HChar *buf = NULL;
1249 static SizeT buf_len = 0;
1251 const HChar *p;
1253 if (path == NULL ||
1254 0 == VG_(strcmp)(path, "") ||
1255 0 == VG_(strcmp)(path, "/"))
1257 return ".";
1260 p = path + VG_(strlen)(path);
1261 while (p > path && *p == '/') {
1262 // skip all trailing '/'
1263 p--;
1266 while (p > path && *p != '/') {
1267 // now skip non '/'
1268 p--;
1271 if (p == path) {
1272 if (*p == '/') return "/"; // all slashes
1273 else return "."; // no slashes
1276 while (p > path && *p == '/') {
1277 // skip '/' again
1278 p--;
1281 SizeT need = p-path+1 + 1;
1282 if (need > buf_len) {
1283 buf_len = (buf_len == 0) ? 500 : need;
1284 buf = VG_(realloc)("dirname", buf, buf_len);
1286 VG_(strncpy)(buf, path, p-path+1);
1287 buf[p-path+1] = '\0';
1289 return buf;
1293 /*--------------------------------------------------------------------*/
1294 /*--- end ---*/
1295 /*--------------------------------------------------------------------*/