memcheck/tests/libstdc++.supp: rename suppression
[valgrind.git] / coregrind / m_libcfile.c
blob5f9c76efe5f97f929b1dc4c182f36f415c841eae
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 #if defined(VGO_freebsd)
71 #define M_FILEDESC_BUF 1000000
72 static Char filedesc_buf[M_FILEDESC_BUF];
73 #endif
75 /* Given a file descriptor, attempt to deduce its filename. To do
76 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
77 or if it doesn't exist, we return False.
78 Upon successful completion *result contains the filename. The
79 filename will be overwritten with the next invocation so callers
80 need to copy the filename if needed. *result is NULL if the filename
81 cannot be deduced. */
82 Bool VG_(resolve_filename) ( Int fd, const HChar** result )
84 # if defined(VGO_linux) || defined(VGO_solaris)
85 static HChar *buf = NULL;
86 static SizeT bufsiz = 0;
88 if (buf == NULL) { // first time
89 bufsiz = 500;
90 buf = VG_(malloc)("resolve_filename", bufsiz);
93 HChar tmp[64]; // large enough
95 # if defined(VGO_linux)
96 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
97 # elif defined(VGO_solaris)
98 VG_(sprintf)(tmp, "/proc/self/path/%d", fd);
99 # endif
102 while (42) {
103 SSizeT res = VG_(readlink)(tmp, buf, bufsiz);
104 if (res < 0) break;
105 if (res == bufsiz) { // buffer too small; increase and retry
106 bufsiz += 500;
107 buf = VG_(realloc)("resolve_filename", buf, bufsiz);
108 continue;
110 vg_assert(bufsiz > res); // paranoia
111 if (buf[0] != '/') break;
113 buf[res] = '\0';
114 *result = buf;
115 return True;
117 // Failure
118 *result = NULL;
119 return False;
121 #elif defined(VGO_freebsd)
122 Int mib[4];
123 SysRes sres;
124 vki_size_t len;
125 Char *bp, *eb;
126 struct vki_kinfo_file *kf;
127 static HChar *buf = NULL;
128 static SizeT bufsiz = 0;
130 if (buf == NULL) { // first time
131 bufsiz = 500;
132 buf = VG_(malloc)("resolve_filename", bufsiz);
135 mib[0] = VKI_CTL_KERN;
136 mib[1] = VKI_KERN_PROC;
137 mib[2] = VKI_KERN_PROC_FILEDESC;
138 mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid));
139 len = sizeof(filedesc_buf);
140 sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf,
141 (UWord)&len, 0, 0);
142 if (sr_isError(sres)) {
143 VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres)));
144 return False;
146 /* Walk though the list. */
147 bp = filedesc_buf;
148 eb = filedesc_buf + len;
149 while (bp < eb) {
150 kf = (struct vki_kinfo_file *)bp;
151 if (kf->kf_fd == fd)
152 break;
153 bp += kf->kf_structsize;
155 if (bp >= eb || *kf->kf_path == '\0')
156 VG_(strncpy)( buf, "[unknown]", bufsiz );
157 else
158 VG_(strncpy)( buf, kf->kf_path, bufsiz );
159 *result = buf;
160 return True;
161 # elif defined(VGO_darwin)
162 HChar tmp[VKI_MAXPATHLEN+1];
163 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
164 static HChar *buf = NULL;
166 if (buf == NULL)
167 buf = VG_(malloc)("resolve_filename", VKI_MAXPATHLEN+1);
168 VG_(strcpy)( buf, tmp );
170 *result = buf;
171 if (buf[0] == '/') return True;
173 // Failure
174 *result = NULL;
175 return False;
177 # else
178 # error Unknown OS
179 # endif
182 #if defined(VGO_freebsd)
184 /* This should only be called after a successful call to
185 * Bool VG_(resolve_filename) ( Int fd, const HChar** result )
186 * so that filedesc_buf is still valid for fd */
187 Bool VG_(resolve_filemode) ( Int fd, Int * result )
189 Char *bp, *eb;
190 struct vki_kinfo_file *kf;
192 /* Walk though the list. */
193 bp = filedesc_buf;
194 eb = filedesc_buf + sizeof(filedesc_buf);
195 while (bp < eb) {
196 kf = (struct vki_kinfo_file *)bp;
197 if (kf->kf_fd == fd)
198 break;
199 bp += kf->kf_structsize;
201 if (bp >= eb)
202 *result = -1;
203 else
204 *result = kf->kf_flags;
205 return True;
207 #endif
210 SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
212 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
213 /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
214 SysRes res = VG_(do_syscall4)(__NR_mknodat,
215 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
216 # elif defined(VGO_linux) || defined(VGO_darwin)
217 SysRes res = VG_(do_syscall3)(__NR_mknod,
218 (UWord)pathname, mode, dev);
219 # elif defined(VGO_freebsd)
220 SysRes res = VG_(do_syscall3)(__NR_freebsd11_mknod,
221 (UWord)pathname, mode, dev);
222 # elif defined(VGO_solaris)
223 SysRes res = VG_(do_syscall4)(__NR_mknodat,
224 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
225 # else
226 # error Unknown OS
227 # endif
228 return res;
231 SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
233 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
234 /* ARM64 wants to use __NR_openat rather than __NR_open. */
235 SysRes res = VG_(do_syscall4)(__NR_openat,
236 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
237 # elif defined(VGO_linux) || defined(VGO_freebsd)
238 SysRes res = VG_(do_syscall3)(__NR_open,
239 (UWord)pathname, flags, mode);
240 # elif defined(VGO_darwin)
241 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
242 (UWord)pathname, flags, mode);
243 # elif defined(VGO_solaris)
244 SysRes res = VG_(do_syscall4)(__NR_openat,
245 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
246 # else
247 # error Unknown OS
248 # endif
249 return res;
252 Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
254 SysRes sr;
255 sr = VG_(open) (pathname, flags, mode);
256 if (sr_isError (sr))
257 return -1;
258 else
259 return sr_Res (sr);
262 void VG_(close) ( Int fd )
264 /* Hmm. Return value is not checked. That's uncool. */
265 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
266 (void)VG_(do_syscall1)(__NR_close, fd);
267 # elif defined(VGO_darwin)
268 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
269 # else
270 # error Unknown OS
271 # endif
274 Int VG_(read) ( Int fd, void* buf, Int count)
276 Int ret;
277 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
278 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
279 # elif defined(VGO_darwin)
280 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
281 # else
282 # error Unknown OS
283 # endif
284 if (sr_isError(res)) {
285 ret = - (Int)(Word)sr_Err(res);
286 vg_assert(ret < 0);
287 } else {
288 ret = (Int)(Word)sr_Res(res);
289 vg_assert(ret >= 0);
291 return ret;
294 Int VG_(write) ( Int fd, const void* buf, Int count)
296 Int ret;
297 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
298 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
299 # elif defined(VGO_darwin)
300 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
301 # else
302 # error "Unknown OS"
303 # endif
304 if (sr_isError(res)) {
305 ret = - (Int)(Word)sr_Err(res);
306 vg_assert(ret < 0);
307 } else {
308 ret = (Int)(Word)sr_Res(res);
309 vg_assert(ret >= 0);
311 return ret;
315 Int VG_(pipe) ( Int fd[2] )
317 # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
318 /* __NR_pipe has a strange return convention on mips32-linux. */
319 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
320 if (!sr_isError(res)) {
321 fd[0] = (Int)sr_Res(res);
322 fd[1] = (Int)sr_ResEx(res);
323 return 0;
324 } else {
325 return -1;
327 # elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
328 SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
329 return sr_isError(res) ? -1 : 0;
330 # elif defined(VGO_linux)
331 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
332 return sr_isError(res) ? -1 : 0;
333 # elif defined(VGO_freebsd)
334 SysRes res = VG_(do_syscall0)(__NR_freebsd10_pipe);
335 if (!sr_isError(res)) {
336 fd[0] = sr_Res(res);
337 fd[1] = sr_ResHI(res);
339 return sr_isError(res) ? -1 : 0;
340 # elif defined(VGO_darwin)
341 /* __NR_pipe is UX64, so produces a double-word result */
342 SysRes res = VG_(do_syscall0)(__NR_pipe);
343 if (!sr_isError(res)) {
344 fd[0] = (Int)sr_Res(res);
345 fd[1] = (Int)sr_ResHI(res);
347 return sr_isError(res) ? -1 : 0;
348 # elif defined(VGO_solaris)
349 # if defined(SOLARIS_NEW_PIPE_SYSCALL)
350 SysRes res = VG_(do_syscall2)(__NR_pipe, (UWord)fd, 0);
351 return sr_isError(res) ? -1 : 0;
352 # else
353 SysRes res = VG_(do_syscall0)(__NR_pipe);
354 if (!sr_isError(res)) {
355 fd[0] = (Int)sr_Res(res);
356 fd[1] = (Int)sr_ResHI(res);
358 return sr_isError(res) ? -1 : 0;
359 # endif
360 # else
361 # error "Unknown OS"
362 # endif
365 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
367 # if defined(VGO_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd)
368 # if defined(__NR__llseek)
369 Off64T result;
370 SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
371 offset >> 32, offset & 0xffffffff,
372 (UWord)&result, whence);
373 return sr_isError(res) ? (-1) : result;
374 # else
375 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
376 vg_assert(sizeof(Off64T) == sizeof(sr_Res(res)));
377 return sr_isError(res) ? (-1) : sr_Res(res);
378 # endif
379 # elif defined(VGP_x86_darwin) || defined(VGP_x86_freebsd)
380 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
381 offset & 0xffffffff, offset >> 32, whence);
382 return sr_isError(res) ? (-1) : sr_Res(res);
383 # elif defined(VGP_x86_solaris)
384 SysRes res = VG_(do_syscall4)(__NR_llseek, fd,
385 offset & 0xffffffff, offset >> 32, whence);
386 return sr_isError(res) ? (-1) : ((ULong)sr_ResHI(res) << 32 | sr_Res(res));
387 # elif defined(VGP_amd64_solaris)
388 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
389 vg_assert(sizeof(Off64T) == sizeof(Word));
390 return sr_isError(res) ? (-1) : sr_Res(res);
391 # else
392 # error "Unknown plat"
393 # endif
394 /* if you change the error-reporting conventions of this, also
395 change all usage points. */
399 /* stat/fstat support. It's uggerly. We have impedance-match into a
400 'struct vg_stat' in order to have a single structure that callers
401 can use consistently on all platforms. */
403 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
404 do { \
405 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
406 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
407 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
408 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
409 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
410 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
411 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
412 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
413 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
414 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
415 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
416 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
417 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
418 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
419 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
420 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
421 } while (0)
423 #define TRANSLATE_statx_TO_vg_stat(_p_vgstat, _p_vkistat) \
424 do { \
425 (_p_vgstat)->dev = VG_MAKEDEV( (_p_vkistat)->stx_dev_major, \
426 (_p_vkistat)->stx_dev_minor ); \
427 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->stx_ino ); \
428 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->stx_nlink ); \
429 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->stx_mode ); \
430 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->stx_uid ); \
431 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->stx_gid ); \
432 (_p_vgstat)->rdev = VG_MAKEDEV( (_p_vkistat)->stx_rdev_major, \
433 (_p_vkistat)->stx_rdev_minor ); \
434 (_p_vgstat)->size = (Long) ( (_p_vkistat)->stx_size ); \
435 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->stx_blksize ); \
436 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->stx_blocks ); \
437 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->stx_atime.tv_sec ); \
438 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->stx_atime.tv_nsec ); \
439 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->stx_mtime.tv_sec ); \
440 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->stx_mtime.tv_nsec ); \
441 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->stx_ctime.tv_sec ); \
442 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->stx_ctime.tv_nsec ); \
443 } while (0)
445 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
447 SysRes res;
448 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
450 # if defined(VGO_linux)
451 /* On Linux, first try with statx. If that doesn't work out, fall back to
452 the stat64 or vanilla version. */
453 { struct vki_statx buf;
454 res = VG_(do_syscall5)(__NR_statx, VKI_AT_FDCWD, (UWord)file_name, 0,
455 VKI_STATX_ALL, (UWord)&buf);
456 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
457 /* Success, or any failure except ENOSYS */
458 if (!sr_isError(res))
459 TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
460 return res;
463 # endif
464 # if defined(VGO_linux) || defined(VGO_darwin)
465 /* Try with stat64. This is the second candidate on Linux, and the first
466 one on Darwin. If that doesn't work out, fall back to vanilla version.
468 # if defined(__NR_stat64)
469 { struct vki_stat64 buf64;
470 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
471 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
472 /* Success, or any failure except ENOSYS */
473 if (!sr_isError(res))
474 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
475 return res;
478 # endif /* defined(__NR_stat64) */
479 # if defined(__NR_stat) || defined(VGP_arm64_linux)
480 /* This is the fallback ("vanilla version"). */
481 { struct vki_stat buf;
482 # if defined(VGP_arm64_linux)
483 res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
484 (UWord)file_name, (UWord)&buf);
485 # else
486 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
487 # endif
488 if (!sr_isError(res))
489 TRANSLATE_TO_vg_stat(vgbuf, &buf);
490 return res;
492 # endif
493 # elif defined(VGO_solaris)
495 # if defined(VGP_x86_solaris)
496 struct vki_stat64 buf64;
497 res = VG_(do_syscall4)(__NR_fstatat64, VKI_AT_FDCWD, (UWord)file_name,
498 (UWord)&buf64, 0);
499 # elif defined(VGP_amd64_solaris)
500 struct vki_stat buf64;
501 res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name,
502 (UWord)&buf64, 0);
503 # else
504 # error "Unknown platform"
505 # endif
506 if (!sr_isError(res))
507 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
508 return res;
510 # elif defined(VGO_freebsd)
512 struct vki_freebsd11_stat buf;
513 #if (FREEBSD_VERS >= FREEBSD_12)
514 res = VG_(do_syscall2)(__NR_freebsd11_stat, (UWord)file_name, (UWord)&buf);
515 #else
516 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
517 #endif
518 if (!sr_isError(res))
519 TRANSLATE_TO_vg_stat(vgbuf, &buf);
520 return res;
522 # else
523 # error Unknown OS
524 # endif
527 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
529 SysRes res;
530 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
532 # if defined(VGO_linux)
533 /* On Linux, first try with statx. If that doesn't work out, fall back to
534 the fstat64 or vanilla version. */
535 { struct vki_statx buf;
536 const char* file_name = "";
537 res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
538 VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&buf);
539 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
540 /* Success, or any failure except ENOSYS */
541 if (!sr_isError(res))
542 TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
543 return sr_isError(res) ? (-1) : 0;
546 #endif
547 # if defined(VGO_linux) || defined(VGO_darwin)
548 /* Try with fstat64. This is the second candidate on Linux, and the first
549 one on Darwin. If that doesn't work out, fall back to vanilla version.
551 # if defined(__NR_fstat64)
552 { struct vki_stat64 buf64;
553 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
554 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
555 /* Success, or any failure except ENOSYS */
556 if (!sr_isError(res))
557 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
558 return sr_isError(res) ? (-1) : 0;
561 # endif /* defined(__NR_fstat64) */
562 # if defined(__NR_fstat)
563 { struct vki_stat buf;
564 res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
565 if (!sr_isError(res))
566 TRANSLATE_TO_vg_stat(vgbuf, &buf);
567 return sr_isError(res) ? (-1) : 0;
569 # endif
570 # elif defined(VGO_solaris)
572 # if defined(VGP_x86_solaris)
573 struct vki_stat64 buf64;
574 res = VG_(do_syscall4)(__NR_fstatat64, (UWord)fd, 0, (UWord)&buf64, 0);
575 # elif defined(VGP_amd64_solaris)
576 struct vki_stat buf64;
577 res = VG_(do_syscall4)(__NR_fstatat, (UWord)fd, 0, (UWord)&buf64, 0);
578 # else
579 # error "Unknown platform"
580 # endif
581 if (!sr_isError(res))
582 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
583 return sr_isError(res) ? (-1) : 0;
585 # elif defined(VGO_freebsd)
587 struct vki_freebsd11_stat buf;
588 #if (FREEBSD_VERS >= FREEBSD_12)
589 res = VG_(do_syscall2)(__NR_freebsd11_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
590 #else
591 res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
592 #endif
593 if (!sr_isError(res)) {
594 TRANSLATE_TO_vg_stat(vgbuf, &buf);
596 return sr_isError(res) ? (-1) : 0;
598 # else
599 # error Unknown OS
600 # endif
603 #undef TRANSLATE_TO_vg_stat
604 #undef TRANSLATE_statx_TO_vg_stat
606 Long VG_(fsize) ( Int fd )
608 struct vg_stat buf;
609 Int res = VG_(fstat)( fd, &buf );
610 return (res == -1) ? (-1LL) : buf.size;
613 SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
615 SysRes res;
616 #if defined(VGO_linux)
617 res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
618 attr_value, attr_value_len);
619 #else
620 res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
621 #endif
622 return res;
625 Bool VG_(is_dir) ( const HChar* f )
627 struct vg_stat buf;
628 SysRes res = VG_(stat)(f, &buf);
629 return sr_isError(res) ? False
630 : VKI_S_ISDIR(buf.mode) ? True : False;
633 SysRes VG_(dup) ( Int oldfd )
635 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
636 return VG_(do_syscall1)(__NR_dup, oldfd);
637 # elif defined(VGO_solaris)
638 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUPFD, 0);
639 # else
640 # error Unknown OS
641 # endif
644 SysRes VG_(dup2) ( Int oldfd, Int newfd )
646 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
647 /* We only have dup3, that means we have to mimic dup2.
648 The only real difference is when oldfd == newfd.
649 dup3 always returns an error, but dup2 returns only an
650 error if the fd is invalid, otherwise it returns newfd. */
651 if (oldfd == newfd) {
652 if (VG_(fcntl)(oldfd, VKI_F_GETFL, 0) == -1)
653 return VG_(mk_SysRes_Error)(VKI_EBADF);
654 return VG_(mk_SysRes_Success)(newfd);
656 return VG_(do_syscall3)(__NR_dup3, oldfd, newfd, 0);
657 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
658 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
659 # elif defined(VGO_solaris)
660 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
661 # else
662 # error Unknown OS
663 # endif
666 /* Returns -1 on error. */
667 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
669 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
670 # if defined(VGP_nanomips_linux)
671 SysRes res = VG_(do_syscall3)(__NR_fcntl64, fd, cmd, arg);
672 # else
673 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
674 # endif
675 # elif defined(VGO_darwin)
676 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
677 # else
678 # error "Unknown OS"
679 # endif
680 return sr_isError(res) ? -1 : sr_Res(res);
683 Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
685 # if defined(VGO_solaris) || defined(VGP_arm64_linux)
686 SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
687 VKI_AT_FDCWD, (UWord)new_name);
688 # elif defined(VGP_nanomips_linux)
689 SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name,
690 VKI_AT_FDCWD, (UWord)new_name, 0);
692 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
693 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
694 # else
695 # error "Unknown OS"
696 # endif
697 return sr_isError(res) ? (-1) : 0;
700 Int VG_(unlink) ( const HChar* file_name )
702 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
703 SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
704 (UWord)file_name);
705 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
706 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
707 # elif defined(VGO_solaris)
708 SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
709 (UWord)file_name, 0);
710 # else
711 # error "Unknown OS"
712 # endif
713 return sr_isError(res) ? (-1) : 0;
716 /* The working directory at startup.
717 All that is really needed is to note the cwd at process startup.
718 Hence VG_(record_startup_wd) notes it (in a platform dependent way)
719 and VG_(get_startup_wd) produces the noted value. */
720 static HChar *startup_wd;
722 /* Record the process' working directory at startup. Is intended to
723 be called exactly once, at startup, before the working directory
724 changes. */
725 void VG_(record_startup_wd) ( void )
727 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
728 /* Simple: just ask the kernel */
729 SysRes res;
730 SizeT szB = 0;
731 do {
732 szB += 500;
733 startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
734 VG_(memset)(startup_wd, 0, szB);
735 # if defined(VGO_linux) || defined(VGO_solaris)
736 res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
737 # elif defined(VGO_freebsd)
738 res = VG_(do_syscall2)(__NR___getcwd, (UWord)startup_wd, szB-1);
739 # endif
740 } while (sr_isError(res) && sr_Err(res) == VKI_ERANGE);
742 if (sr_isError(res)) {
743 VG_(free)(startup_wd);
744 startup_wd = NULL;
745 return;
748 vg_assert(startup_wd[szB-1] == 0);
750 # elif defined(VGO_darwin)
751 /* We can't ask the kernel, so instead rely on launcher-*.c to
752 tell us the startup path. Note the env var is keyed to the
753 parent's PID, not ours, since our parent is the launcher
754 process. */
755 { HChar envvar[100]; // large enough
756 HChar* wd;
757 VG_(memset)(envvar, 0, sizeof(envvar));
758 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
759 (Int)VG_(getppid)());
760 wd = VG_(getenv)( envvar );
761 if (wd == NULL)
762 return;
763 SizeT need = VG_(strlen)(wd) + 1;
764 startup_wd = VG_(malloc)("startup_wd", need);
765 VG_(strcpy)(startup_wd, wd);
767 # else
768 # error Unknown OS
769 # endif
772 /* Return the previously acquired startup_wd or NULL. */
773 const HChar *VG_(get_startup_wd) ( void )
775 return startup_wd;
778 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
780 SysRes res;
781 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
782 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
783 struct vki_timespec timeout_ts;
784 if (timeout >= 0) {
785 timeout_ts.tv_sec = timeout / 1000;
786 timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
788 res = VG_(do_syscall4)(__NR_ppoll,
789 (UWord)fds, nfds,
790 (UWord)(timeout >= 0 ? &timeout_ts : NULL),
791 (UWord)NULL);
792 # elif defined(VGO_linux)
793 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
794 # elif defined(VGO_freebsd)
795 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
796 # elif defined(VGO_darwin)
797 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
798 # elif defined(VGO_solaris)
799 struct vki_timespec ts;
800 struct vki_timespec *tsp;
802 if (timeout < 0)
803 tsp = NULL;
804 else {
805 ts.tv_sec = timeout / 1000;
806 ts.tv_nsec = (timeout % 1000) * 1000000;
807 tsp = &ts;
810 res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0);
811 # else
812 # error "Unknown OS"
813 # endif
814 return res;
818 /* Performs the readlink operation and puts the result into 'buf'.
819 Note, that the string in 'buf' is *not* null-terminated. The function
820 returns the number of characters put into 'buf' or -1 if an error
821 occurred. */
822 SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
824 SysRes res;
825 /* res = readlink( path, buf, bufsiz ); */
826 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
827 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
828 (UWord)path, (UWord)buf, bufsiz);
829 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
830 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
831 # elif defined(VGO_solaris)
832 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
833 (UWord)buf, bufsiz);
834 # else
835 # error "Unknown OS"
836 # endif
837 return sr_isError(res) ? -1 : sr_Res(res);
840 #if defined(VGO_linux) || defined(VGO_solaris)
841 Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
843 SysRes res;
844 /* res = getdents( fd, dirp, count ); */
845 # if defined(VGP_amd64_solaris)
846 /* This silently assumes that dirent64 and dirent on amd64 are same, which
847 they should always be. */
848 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
849 # else
850 res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
851 # if defined(VGA_mips64)
852 /* The MIPS64 getdents64() system call is only present in 3.10+ kernels.
853 If the getdents64() system call is not available fall back to using
854 getdents() and modify the result to be compatible with getdents64(). */
855 if (sr_isError(res) && (sr_Err(res) == VKI_ENOSYS)) {
856 int r;
857 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
858 r = sr_Res(res);
859 if (r > 0) {
860 char *p;
861 char type;
862 union dirents {
863 struct vki_dirent m;
864 struct vki_dirent64 d;
865 } *u;
866 p = (char *)dirp;
867 do {
868 u = (union dirents *)p;
869 /* This should not happen, but just in case... */
870 if (p + u->m.d_reclen > (char *)dirp + r)
871 break;
872 /* shuffle the dirent */
873 type = *(p + u->m.d_reclen - 1);
874 VG_(memmove)(u->d.d_name, u->m.d_name,
875 u->m.d_reclen - 2
876 - offsetof(struct vki_dirent, d_name) + 1);
877 u->d.d_type = type;
878 p += u->m.d_reclen;
879 } while (p < (char *)dirp + r);
882 # endif
883 # endif
884 return sr_isError(res) ? -1 : sr_Res(res);
886 #endif
888 /* Check accessibility of a file. Returns zero for access granted,
889 nonzero otherwise. */
890 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
892 # if defined(VGO_linux)
893 /* Very annoyingly, I cannot find any definition for R_OK et al in
894 the kernel interfaces. Therefore I reluctantly resort to
895 hardwiring in these magic numbers that I determined by
896 experimentation. */
897 # define VKI_R_OK 4
898 # define VKI_W_OK 2
899 # define VKI_X_OK 1
900 # endif
902 UWord w = (irusr ? VKI_R_OK : 0)
903 | (iwusr ? VKI_W_OK : 0)
904 | (ixusr ? VKI_X_OK : 0);
905 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
906 SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
907 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
908 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
909 # elif defined(VGO_solaris)
910 SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
911 w, 0);
912 # else
913 # error "Unknown OS"
914 # endif
915 return sr_isError(res) ? 1 : 0;
917 # if defined(VGO_linux)
918 # undef VKI_R_OK
919 # undef VKI_W_OK
920 # undef VKI_X_OK
921 # endif
925 Emulate the normal Unix permissions checking algorithm.
927 If owner matches, then use the owner permissions, else
928 if group matches, then use the group permissions, else
929 use other permissions.
931 Note that we can't deal properly with SUID/SGID. By default
932 (allow_setuid == False), we refuse to run them (otherwise the
933 executable may misbehave if it doesn't have the permissions it
934 thinks it does). However, the caller may indicate that setuid
935 executables are allowed, for example if we are going to exec them
936 but not trace into them (iow, client sys_execve when
937 clo_trace_children == False).
939 If VKI_EACCES is returned (iow, permission was refused), then
940 *is_setuid is set to True iff permission was refused because the
941 executable is setuid.
943 /* returns: 0 = success, non-0 is failure */
944 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
945 const HChar* f, Bool allow_setuid)
947 struct vg_stat st;
948 SysRes res = VG_(stat)(f, &st);
950 if (is_setuid)
951 *is_setuid = False;
953 if (sr_isError(res)) {
954 return sr_Err(res);
957 if ( VKI_S_ISDIR (st.mode) ) {
958 return VKI_EACCES;
961 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
962 if (is_setuid)
963 *is_setuid = True;
964 return VKI_EACCES;
967 res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
968 if (!sr_isError(res) && !allow_setuid) {
969 if (is_setuid)
970 *is_setuid = True;
971 return VKI_EACCES;
974 if (VG_(geteuid)() == st.uid) {
975 if (!(st.mode & VKI_S_IXUSR))
976 return VKI_EACCES;
977 } else {
978 Int grpmatch = 0;
980 if (VG_(getegid)() == st.gid)
981 grpmatch = 1;
982 else {
983 UInt *groups = NULL;
984 Int ngrp;
986 /* Find out # groups, allocate large enough array and fetch groups */
987 ngrp = VG_(getgroups)(0, NULL);
988 if (ngrp != -1) {
989 groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
990 ngrp = VG_(getgroups)(ngrp, groups);
993 Int i;
994 /* ngrp will be -1 if VG_(getgroups) failed. */
995 for (i = 0; i < ngrp; i++) {
996 if (groups[i] == st.gid) {
997 grpmatch = 1;
998 break;
1001 VG_(free)(groups);
1004 if (grpmatch) {
1005 if (!(st.mode & VKI_S_IXGRP)) {
1006 return VKI_EACCES;
1008 } else if (!(st.mode & VKI_S_IXOTH)) {
1009 return VKI_EACCES;
1013 return 0;
1016 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
1018 SysRes res;
1019 // on 32 bits platforms, we receive a 32 bits OffT but
1020 // we must extend it to pass a long long 64 bits.
1021 # if defined(VGP_x86_linux)
1022 vg_assert(sizeof(OffT) == 4);
1023 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
1024 offset, 0); // Little endian long long
1025 return res;
1026 # elif defined(VGP_arm_linux)
1027 vg_assert(sizeof(OffT) == 4);
1028 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
1029 0, offset); // Big endian long long
1030 return res;
1031 # elif defined(VGP_ppc32_linux)
1032 vg_assert(sizeof(OffT) == 4);
1033 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
1034 0, // Padding needed on PPC32
1035 0, offset); // Big endian long long
1036 return res;
1037 # elif (defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)) \
1038 && (VKI_LITTLE_ENDIAN)
1039 vg_assert(sizeof(OffT) == 4);
1040 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
1041 0, offset, 0);
1042 return res;
1043 # elif (defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)) \
1044 && (VKI_BIG_ENDIAN)
1045 vg_assert(sizeof(OffT) == 4);
1046 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
1047 0, 0, offset);
1048 return res;
1049 # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
1050 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1051 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
1052 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
1053 return res;
1054 # elif defined(VGP_amd64_freebsd)
1055 vg_assert(sizeof(OffT) == 8);
1056 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
1057 return res;
1058 # elif defined(VGP_x86_freebsd)
1059 vg_assert(sizeof(OffT) == 8);
1060 res = VG_(do_syscall5)(__NR_pread, fd, (UWord)buf, count,
1061 offset & 0xffffffff, offset >> 32);
1062 return res;
1063 # elif defined(VGP_amd64_darwin)
1064 vg_assert(sizeof(OffT) == 8);
1065 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
1066 return res;
1067 # elif defined(VGP_x86_darwin)
1068 vg_assert(sizeof(OffT) == 8);
1069 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
1070 offset & 0xffffffff, offset >> 32);
1071 return res;
1072 # elif defined(VGP_x86_solaris)
1073 vg_assert(sizeof(OffT) == 4);
1074 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
1075 return res;
1076 # elif defined(VGP_amd64_solaris)
1077 vg_assert(sizeof(OffT) == 8);
1078 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
1079 return res;
1080 # else
1081 # error "Unknown platform"
1082 # endif
1085 /* Return the name of a directory for temporary files. */
1086 const HChar *VG_(tmpdir)(void)
1088 const HChar *tmpdir;
1090 tmpdir = VG_(getenv)("TMPDIR");
1091 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
1092 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */
1094 return tmpdir;
1097 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
1099 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
1101 return VG_(strlen)(mkstemp_format)
1102 + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
1103 + part_of_name_len - 2 // %s part_of_name
1104 + 8 - 4 // %08x
1105 + 1; // trailing 0
1109 Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
1111 Int n, tries;
1112 UInt seed;
1113 SysRes sres;
1114 const HChar *tmpdir;
1116 vg_assert(part_of_name);
1117 vg_assert(fullname);
1118 n = VG_(strlen)(part_of_name);
1119 vg_assert(n > 0 && n < 100);
1121 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
1123 /* Determine sensible location for temporary files */
1124 tmpdir = VG_(tmpdir)();
1126 tries = 0;
1127 while (True) {
1128 if (tries++ > 10)
1129 return -1;
1130 VG_(sprintf)( fullname, mkstemp_format,
1131 tmpdir, part_of_name, VG_(random)( &seed ));
1132 if (0)
1133 VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
1135 sres = VG_(open)(fullname,
1136 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
1137 VKI_S_IRUSR|VKI_S_IWUSR);
1138 if (sr_isError(sres)) {
1139 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
1140 continue;
1142 /* VG_(safe_fd) doesn't return if it fails. */
1143 return VG_(safe_fd)( sr_Res(sres) );
1145 /* NOTREACHED */
1149 /* ---------------------------------------------------------------------
1150 Socket-related stuff.
1151 ------------------------------------------------------------------ */
1153 static
1154 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
1156 static
1157 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
1159 UInt VG_(htonl) ( UInt x )
1161 # if defined(VG_BIGENDIAN)
1162 return x;
1163 # else
1164 return
1165 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1166 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1167 # endif
1170 UInt VG_(ntohl) ( UInt x )
1172 # if defined(VG_BIGENDIAN)
1173 return x;
1174 # else
1175 return
1176 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1177 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1178 # endif
1181 UShort VG_(htons) ( UShort x )
1183 # if defined(VG_BIGENDIAN)
1184 return x;
1185 # else
1186 return
1187 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1188 # endif
1191 UShort VG_(ntohs) ( UShort x )
1193 # if defined(VG_BIGENDIAN)
1194 return x;
1195 # else
1196 return
1197 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1198 # endif
1202 /* The main function.
1204 Supplied string contains either an ip address "192.168.0.1" or
1205 an ip address and port pair, "192.168.0.1:1500". Parse these,
1206 and return:
1207 -1 if there is a parse error
1208 -2 if no parse error, but specified host:port cannot be opened
1209 the relevant file (socket) descriptor, otherwise.
1210 is used.
1212 Int VG_(connect_via_socket)( const HChar* str )
1214 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
1215 Int sd, res;
1216 struct vki_sockaddr_in servAddr;
1217 UInt ip = 0;
1218 UShort port = VG_CLO_DEFAULT_LOGPORT;
1219 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1220 if (!ok)
1221 return -1;
1223 //if (0)
1224 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1225 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1226 // (ip >> 8) & 0xFF, ip & 0xFF,
1227 // (UInt)port );
1229 servAddr.sin_family = VKI_AF_INET;
1230 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
1231 servAddr.sin_port = VG_(htons)(port);
1233 /* create socket */
1234 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1235 if (sd < 0) {
1236 /* this shouldn't happen ... nevertheless */
1237 return -2;
1240 /* connect to server */
1241 res = my_connect(sd, &servAddr, sizeof(servAddr));
1242 if (res < 0) {
1243 /* connection failed */
1244 return -2;
1247 return sd;
1249 # else
1250 # error "Unknown OS"
1251 # endif
1255 /* Let d = one or more digits. Accept either:
1256 d.d.d.d or d.d.d.d:d
1258 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
1260 # define GET_CH ((*str) ? (*str++) : 0)
1261 UInt ipa, i, j, c, any;
1262 ipa = 0;
1263 for (i = 0; i < 4; i++) {
1264 j = 0;
1265 any = 0;
1266 while (1) {
1267 c = GET_CH;
1268 if (c < '0' || c > '9') break;
1269 j = 10 * j + (int)(c - '0');
1270 any = 1;
1272 if (any == 0 || j > 255) goto syntaxerr;
1273 ipa = (ipa << 8) + j;
1274 if (i <= 2 && c != '.') goto syntaxerr;
1276 if (c == 0 || c == ':')
1277 *ip_addr = ipa;
1278 if (c == 0) goto ok;
1279 if (c != ':') goto syntaxerr;
1280 j = 0;
1281 any = 0;
1282 while (1) {
1283 c = GET_CH;
1284 if (c < '0' || c > '9') break;
1285 j = j * 10 + (int)(c - '0');
1286 any = 1;
1287 if (j > 65535) goto syntaxerr;
1289 if (any == 0 || c != 0) goto syntaxerr;
1290 if (j < 1024) goto syntaxerr;
1291 *port = (UShort)j;
1293 return 1;
1294 syntaxerr:
1295 return 0;
1296 # undef GET_CH
1299 // GrP fixme safe_fd?
1300 Int VG_(socket) ( Int domain, Int type, Int protocol )
1302 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1303 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1304 || defined(VGP_s390x_linux)
1305 SysRes res;
1306 UWord args[3];
1307 args[0] = domain;
1308 args[1] = type;
1309 args[2] = protocol;
1310 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
1311 return sr_isError(res) ? -1 : sr_Res(res);
1313 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1314 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1315 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1316 SysRes res;
1317 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
1318 return sr_isError(res) ? -1 : sr_Res(res);
1320 # elif defined(VGO_darwin)
1321 SysRes res;
1322 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
1323 if (!sr_isError(res)) {
1324 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
1325 Int optval = 1;
1326 SysRes res2;
1327 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
1328 VKI_SO_NOSIGPIPE, (UWord)&optval,
1329 sizeof(optval));
1330 // ignore setsockopt() error
1332 return sr_isError(res) ? -1 : sr_Res(res);
1334 # elif defined(VGO_solaris)
1335 /* XXX There doesn't seem to be an easy way to convince the send syscall to
1336 only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
1337 SM_KERNEL is set on the socket. Without serious hackery it looks we
1338 can't set this flag.
1340 Should we wrap the send syscall below into sigprocmask calls to block
1341 SIGPIPE?
1343 SysRes res;
1344 res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol,
1345 0 /*devpath*/, VKI_SOV_DEFAULT /*version*/);
1346 return sr_isError(res) ? -1 : sr_Res(res);
1348 # else
1349 # error "Unknown arch"
1350 # endif
1354 static
1355 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
1357 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1358 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1359 || defined(VGP_s390x_linux)
1360 SysRes res;
1361 UWord args[3];
1362 args[0] = sockfd;
1363 args[1] = (UWord)serv_addr;
1364 args[2] = addrlen;
1365 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
1366 return sr_isError(res) ? -1 : sr_Res(res);
1368 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1369 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1370 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1371 SysRes res;
1372 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
1373 return sr_isError(res) ? -1 : sr_Res(res);
1375 # elif defined(VGO_darwin)
1376 SysRes res;
1377 res = VG_(do_syscall3)(__NR_connect_nocancel,
1378 sockfd, (UWord)serv_addr, addrlen);
1379 return sr_isError(res) ? -1 : sr_Res(res);
1381 # elif defined(VGO_solaris)
1382 SysRes res;
1383 res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen,
1384 VKI_SOV_DEFAULT /*version*/);
1385 return sr_isError(res) ? -1 : sr_Res(res);
1387 # else
1388 # error "Unknown arch"
1389 # endif
1392 Int VG_(write_socket)( Int sd, const void *msg, Int count )
1394 /* This is actually send(). */
1396 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
1397 errors on stream oriented sockets when the other end breaks the
1398 connection. The EPIPE error is still returned.
1400 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1401 SIGPIPE */
1403 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1404 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1405 || defined(VGP_s390x_linux)
1406 SysRes res;
1407 UWord args[4];
1408 args[0] = sd;
1409 args[1] = (UWord)msg;
1410 args[2] = count;
1411 args[3] = VKI_MSG_NOSIGNAL;
1412 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
1413 return sr_isError(res) ? -1 : sr_Res(res);
1415 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1416 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1417 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1418 SysRes res;
1419 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
1420 count, VKI_MSG_NOSIGNAL, 0,0);
1421 return sr_isError(res) ? -1 : sr_Res(res);
1423 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1424 SysRes res;
1425 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
1426 return sr_isError(res) ? -1 : sr_Res(res);
1428 # elif defined(VGO_solaris)
1429 SysRes res;
1430 res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/);
1431 return sr_isError(res) ? -1 : sr_Res(res);
1433 # else
1434 # error "Unknown platform"
1435 # endif
1438 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
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 || defined(VGP_mips32_linux)
1444 SysRes res;
1445 UWord args[3];
1446 args[0] = sd;
1447 args[1] = (UWord)name;
1448 args[2] = (UWord)namelen;
1449 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
1450 return sr_isError(res) ? -1 : sr_Res(res);
1452 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1453 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1454 || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
1455 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
1456 SysRes res;
1457 res = VG_(do_syscall3)( __NR_getsockname,
1458 (UWord)sd, (UWord)name, (UWord)namelen );
1459 return sr_isError(res) ? -1 : sr_Res(res);
1461 # elif defined(VGO_darwin)
1462 SysRes res;
1463 res = VG_(do_syscall3)( __NR_getsockname,
1464 (UWord)sd, (UWord)name, (UWord)namelen );
1465 return sr_isError(res) ? -1 : sr_Res(res);
1467 # elif defined(VGO_solaris)
1468 SysRes res;
1469 res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen,
1470 VKI_SOV_DEFAULT /*version*/);
1471 return sr_isError(res) ? -1 : sr_Res(res);
1473 # else
1474 # error "Unknown platform"
1475 # endif
1478 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1480 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1481 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1482 || defined(VGP_s390x_linux) \
1483 || defined(VGP_mips32_linux)
1484 SysRes res;
1485 UWord args[3];
1486 args[0] = sd;
1487 args[1] = (UWord)name;
1488 args[2] = (UWord)namelen;
1489 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
1490 return sr_isError(res) ? -1 : sr_Res(res);
1492 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1493 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1494 || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1495 SysRes res;
1496 res = VG_(do_syscall3)( __NR_getpeername,
1497 (UWord)sd, (UWord)name, (UWord)namelen );
1498 return sr_isError(res) ? -1 : sr_Res(res);
1500 # elif defined(VGO_darwin)
1501 SysRes res;
1502 res = VG_(do_syscall3)( __NR_getpeername,
1503 (UWord)sd, (UWord)name, (UWord)namelen );
1504 return sr_isError(res) ? -1 : sr_Res(res);
1506 # elif defined(VGO_solaris)
1507 SysRes res;
1508 res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen,
1509 VKI_SOV_DEFAULT /*version*/);
1510 return sr_isError(res) ? -1 : sr_Res(res);
1512 # else
1513 # error "Unknown platform"
1514 # endif
1517 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1518 Int *optlen)
1520 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1521 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1522 || defined(VGP_s390x_linux)
1523 SysRes res;
1524 UWord args[5];
1525 args[0] = sd;
1526 args[1] = level;
1527 args[2] = optname;
1528 args[3] = (UWord)optval;
1529 args[4] = (UWord)optlen;
1530 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
1531 return sr_isError(res) ? -1 : sr_Res(res);
1533 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1534 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1535 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
1536 || defined(VGO_freebsd)
1537 SysRes res;
1538 res = VG_(do_syscall5)( __NR_getsockopt,
1539 (UWord)sd, (UWord)level, (UWord)optname,
1540 (UWord)optval, (UWord)optlen );
1541 return sr_isError(res) ? -1 : sr_Res(res);
1543 # elif defined(VGO_darwin)
1544 SysRes res;
1545 res = VG_(do_syscall5)( __NR_getsockopt,
1546 (UWord)sd, (UWord)level, (UWord)optname,
1547 (UWord)optval, (UWord)optlen );
1548 return sr_isError(res) ? -1 : sr_Res(res);
1550 # elif defined(VGO_solaris)
1551 SysRes res;
1552 res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval,
1553 (UWord)optlen, VKI_SOV_DEFAULT /*version*/);
1554 return sr_isError(res) ? -1 : sr_Res(res);
1556 # else
1557 # error "Unknown platform"
1558 # endif
1562 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
1563 Int optlen)
1565 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1566 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1567 || defined(VGP_s390x_linux)
1568 SysRes res;
1569 UWord args[5];
1570 args[0] = sd;
1571 args[1] = level;
1572 args[2] = optname;
1573 args[3] = (UWord)optval;
1574 args[4] = (UWord)optlen;
1575 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
1576 return sr_isError(res) ? -1 : sr_Res(res);
1578 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1579 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1580 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1581 SysRes res;
1582 res = VG_(do_syscall5)( __NR_setsockopt,
1583 (UWord)sd, (UWord)level, (UWord)optname,
1584 (UWord)optval, (UWord)optlen );
1585 return sr_isError(res) ? -1 : sr_Res(res);
1587 # elif defined(VGO_darwin) || defined(VGO_freebsd)
1588 SysRes res;
1589 res = VG_(do_syscall5)( __NR_setsockopt,
1590 (UWord)sd, (UWord)level, (UWord)optname,
1591 (UWord)optval, (UWord)optlen );
1592 return sr_isError(res) ? -1 : sr_Res(res);
1594 # elif defined(VGO_solaris)
1595 SysRes res;
1596 res = VG_(do_syscall6)( __NR_setsockopt,
1597 (UWord)sd, (UWord)level, (UWord)optname,
1598 (UWord)optval, (UWord)optlen,
1599 VKI_SOV_DEFAULT /*version*/ );
1600 return sr_isError(res) ? -1 : sr_Res(res);
1602 # else
1603 # error "Unknown platform"
1604 # endif
1608 const HChar *VG_(basename)(const HChar *path)
1610 static HChar *buf = NULL;
1611 static SizeT buf_len = 0;
1612 const HChar *p, *end;
1614 if (path == NULL ||
1615 0 == VG_(strcmp)(path, ""))
1617 return ".";
1620 p = path + VG_(strlen)(path);
1621 while (p > path && *p == '/') {
1622 // skip all trailing '/'
1623 p--;
1626 if (p == path && *p == '/') return "/"; // all slashes
1628 end = p;
1630 while (p > path && *p != '/') {
1631 // now skip non '/'
1632 p--;
1635 if (*p == '/') p++;
1637 SizeT need = end-p+1 + 1;
1638 if (need > buf_len) {
1639 buf_len = (buf_len == 0) ? 500 : need;
1640 buf = VG_(realloc)("basename", buf, buf_len);
1642 VG_(strncpy)(buf, p, end-p+1);
1643 buf[end-p+1] = '\0';
1645 return buf;
1649 const HChar *VG_(dirname)(const HChar *path)
1651 static HChar *buf = NULL;
1652 static SizeT buf_len = 0;
1654 const HChar *p;
1656 if (path == NULL ||
1657 0 == VG_(strcmp)(path, "") ||
1658 0 == VG_(strcmp)(path, "/"))
1660 return ".";
1663 p = path + VG_(strlen)(path);
1664 while (p > path && *p == '/') {
1665 // skip all trailing '/'
1666 p--;
1669 while (p > path && *p != '/') {
1670 // now skip non '/'
1671 p--;
1674 if (p == path) {
1675 if (*p == '/') return "/"; // all slashes
1676 else return "."; // no slashes
1679 while (p > path && *p == '/') {
1680 // skip '/' again
1681 p--;
1684 SizeT need = p-path+1 + 1;
1685 if (need > buf_len) {
1686 buf_len = (buf_len == 0) ? 500 : need;
1687 buf = VG_(realloc)("dirname", buf, buf_len);
1689 VG_(strncpy)(buf, path, p-path+1);
1690 buf[p-path+1] = '\0';
1692 return buf;
1696 /*--------------------------------------------------------------------*/
1697 /*--- end ---*/
1698 /*--------------------------------------------------------------------*/