vgdb: Handle EAGAIN in read_buf
[valgrind.git] / coregrind / m_libcfile.c
blob5d3a349f2bb2cc23d85a82f03e9fd87fa7cd723d
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));
61 if (newfd == -1) {
62 VG_(debugLog)(0, "libcfile", "Valgrind: FATAL: "
63 "Private file creation failed.\n"
64 " The current file descriptor limit is %d.\n"
65 " If you are running in Docker please consider\n"
66 " lowering this limit with the shell built-in limit command.\n",
67 VG_(fd_hard_limit));
68 VG_(debugLog)(0, "libcfile", "Exiting now.\n");
69 VG_(exit)(1);
72 vg_assert(newfd >= VG_(fd_hard_limit));
74 VG_(close)(oldfd);
76 /* Set the close-on-exec flag for this fd. */
77 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
79 return newfd;
82 #if defined(VGO_freebsd)
83 #define M_FILEDESC_BUF 1000000
84 static Char filedesc_buf[M_FILEDESC_BUF];
85 #endif
87 /* Given a file descriptor, attempt to deduce its filename. To do
88 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
89 or if it doesn't exist, we return False.
90 Upon successful completion *result contains the filename. The
91 filename will be overwritten with the next invocation so callers
92 need to copy the filename if needed. *result is NULL if the filename
93 cannot be deduced. */
94 Bool VG_(resolve_filename) ( Int fd, const HChar** result )
96 # if defined(VGO_linux) || defined(VGO_solaris)
97 static HChar *buf = NULL;
98 static SizeT bufsiz = 0;
100 if (buf == NULL) { // first time
101 bufsiz = 500;
102 buf = VG_(malloc)("resolve_filename", bufsiz);
105 HChar tmp[64]; // large enough
107 # if defined(VGO_linux)
108 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
109 # elif defined(VGO_solaris)
110 VG_(sprintf)(tmp, "/proc/self/path/%d", fd);
111 # endif
114 while (42) {
115 SSizeT res = VG_(readlink)(tmp, buf, bufsiz);
116 if (res < 0) break;
117 if (res == bufsiz) { // buffer too small; increase and retry
118 bufsiz += 500;
119 buf = VG_(realloc)("resolve_filename", buf, bufsiz);
120 continue;
122 vg_assert(bufsiz > res); // paranoia
123 if (buf[0] != '/') break;
125 buf[res] = '\0';
126 *result = buf;
127 return True;
129 // Failure
130 *result = NULL;
131 return False;
133 #elif defined(VGO_freebsd)
135 #if (1)
136 Int mib[4];
137 SysRes sres;
138 vki_size_t len;
139 Char *bp;
140 Char *eb;
141 struct vki_kinfo_file *kf;
142 static HChar *buf = NULL;
143 static SizeT bufsiz = 0;
145 if (buf == NULL) { // first time
146 bufsiz = 500;
147 buf = VG_(malloc)("resolve_filename", bufsiz);
150 mib[0] = VKI_CTL_KERN;
151 mib[1] = VKI_KERN_PROC;
152 mib[2] = VKI_KERN_PROC_FILEDESC;
153 mib[3] = sr_Res(VG_(do_syscall0)(__NR_getpid));
154 len = sizeof(filedesc_buf);
155 sres = VG_(do_syscall6)(__NR___sysctl, (UWord)mib, 4, (UWord)filedesc_buf,
156 (UWord)&len, 0, 0);
157 if (sr_isError(sres)) {
158 VG_(debugLog)(0, "sysctl(kern.proc.filedesc)", "%s\n", VG_(strerror)(sr_Err(sres)));
159 return False;
161 /* Walk though the list. */
162 bp = filedesc_buf;
163 eb = filedesc_buf + len;
164 while (bp < eb) {
165 kf = (struct vki_kinfo_file *)bp;
166 if (kf->vki_kf_fd == fd) {
167 break;
169 bp += kf->vki_kf_structsize;
171 if (bp >= eb || *kf->vki_kf_path == '\0') {
172 VG_(strncpy)( buf, "[unknown]", bufsiz );
173 } else {
174 VG_(strncpy)( buf, kf->vki_kf_path, bufsiz );
176 *result = buf;
177 return True;
178 #else
179 // PJF it will be a relief to get rid of the above bit of ugliness
180 // however it does not seem to have the same functionality
181 // regarding pipes where it profuces just an empty string
182 struct vki_kinfo_file kinfo_file;
183 kinfo_file.vki_kf_structsize = VKI_KINFO_FILE_SIZE;
184 if (0 == VG_(fcntl) ( fd, VKI_F_KINFO, (Addr)&kinfo_file )) {
185 static HChar *buf = NULL;
187 if (buf == NULL)
188 buf = VG_(malloc)("resolve_filename", VKI_PATH_MAX);
190 *result = buf;
191 VG_(strcpy)( buf, kinfo_file.vki_kf_path );
192 if (buf[0] == '/') return True;
194 *result = NULL;
195 return False;
196 #endif
198 # elif defined(VGO_darwin)
199 HChar tmp[VKI_MAXPATHLEN+1];
200 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
201 static HChar *buf = NULL;
203 if (buf == NULL)
204 buf = VG_(malloc)("resolve_filename", VKI_MAXPATHLEN+1);
205 VG_(strcpy)( buf, tmp );
207 *result = buf;
208 if (buf[0] == '/') return True;
210 // Failure
211 *result = NULL;
212 return False;
214 # else
215 # error Unknown OS
216 # endif
219 #if defined(VGO_freebsd)
222 #if (1)
223 /* This should only be called after a successful call to
224 * Bool VG_(resolve_filename) ( Int fd, const HChar** result )
225 * so that filedesc_buf is still valid for fd */
226 Bool VG_(resolve_filemode) ( Int fd, Int * result )
228 Char *bp;
229 Char *eb;
230 struct vki_kinfo_file *kf;
232 /* Walk though the list. */
233 bp = filedesc_buf;
234 eb = filedesc_buf + sizeof(filedesc_buf);
235 while (bp < eb) {
236 kf = (struct vki_kinfo_file *)bp;
237 if (kf->vki_kf_fd == fd) {
238 break;
240 bp += kf->vki_kf_structsize;
242 if (bp >= eb) {
243 *result = -1;
244 } else {
245 *result = kf->vki_kf_flags;
247 return True;
249 #else
250 /* less ugly version, no dependency on resolve_filename */
251 Bool VG_(resolve_filemode) ( Int fd, Int * result )
253 struct vki_kinfo_file kinfo_file;
254 kinfo_file.vki_kf_structsize = VKI_KINFO_FILE_SIZE;
255 if (0 == VG_(fcntl) ( fd, VKI_F_KINFO, (Addr)&kinfo_file )) {
256 *result = kinfo_file.vki_kf_flags;
257 return True;
259 return False;
261 #endif
262 #endif
265 SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
267 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
268 /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
269 SysRes res = VG_(do_syscall4)(__NR_mknodat,
270 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
271 # elif defined(VGO_linux) || defined(VGO_darwin)
272 SysRes res = VG_(do_syscall3)(__NR_mknod,
273 (UWord)pathname, mode, dev);
274 # elif defined(VGO_freebsd)
275 #if (FREEBSD_VERS < FREEBSD_12)
276 SysRes res = VG_(do_syscall3)(__NR_freebsd11_mknod,
277 (UWord)pathname, mode, dev);
278 #else
279 SysRes res = VG_(do_syscall4)(__NR_mknodat, VKI_AT_FDCWD,
280 (UWord)pathname, mode, dev);
281 #endif
282 # elif defined(VGO_solaris)
283 SysRes res = VG_(do_syscall4)(__NR_mknodat,
284 VKI_AT_FDCWD, (UWord)pathname, mode, dev);
285 # else
286 # error Unknown OS
287 # endif
288 return res;
291 SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
293 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
294 /* ARM64 wants to use __NR_openat rather than __NR_open. */
295 SysRes res = VG_(do_syscall4)(__NR_openat,
296 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
297 # elif defined(VGO_linux) || defined(VGO_freebsd)
298 SysRes res = VG_(do_syscall3)(__NR_open,
299 (UWord)pathname, flags, mode);
300 # elif defined(VGO_darwin)
301 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
302 (UWord)pathname, flags, mode);
303 # elif defined(VGO_solaris)
304 SysRes res = VG_(do_syscall4)(__NR_openat,
305 VKI_AT_FDCWD, (UWord)pathname, flags, mode);
306 # else
307 # error Unknown OS
308 # endif
309 return res;
312 Int VG_(fd_open) (const HChar* pathname, Int flags, Int mode)
314 SysRes sr;
315 sr = VG_(open) (pathname, flags, mode);
316 if (sr_isError (sr))
317 return -1;
318 else
319 return sr_Res (sr);
322 void VG_(close) ( Int fd )
324 /* Hmm. Return value is not checked. That's uncool. */
325 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
326 (void)VG_(do_syscall1)(__NR_close, fd);
327 # elif defined(VGO_darwin)
328 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
329 # else
330 # error Unknown OS
331 # endif
334 Int VG_(read) ( Int fd, void* buf, Int count)
336 Int ret;
337 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
338 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
339 # elif defined(VGO_darwin)
340 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
341 # else
342 # error Unknown OS
343 # endif
344 if (sr_isError(res)) {
345 ret = - (Int)(Word)sr_Err(res);
346 vg_assert(ret < 0);
347 } else {
348 ret = (Int)(Word)sr_Res(res);
349 vg_assert(ret >= 0);
351 return ret;
354 Int VG_(write) ( Int fd, const void* buf, Int count)
356 Int ret;
357 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
358 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
359 # elif defined(VGO_darwin)
360 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
361 # else
362 # error "Unknown OS"
363 # endif
364 if (sr_isError(res)) {
365 ret = - (Int)(Word)sr_Err(res);
366 vg_assert(ret < 0);
367 } else {
368 ret = (Int)(Word)sr_Res(res);
369 vg_assert(ret >= 0);
371 return ret;
375 Int VG_(pipe) ( Int fd[2] )
377 # if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
378 /* __NR_pipe has a strange return convention on mips32-linux. */
379 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
380 if (!sr_isError(res)) {
381 fd[0] = (Int)sr_Res(res);
382 fd[1] = (Int)sr_ResEx(res);
383 return 0;
384 } else {
385 return -1;
387 # elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
388 SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
389 return sr_isError(res) ? -1 : 0;
390 # elif defined(VGO_linux)
391 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
392 return sr_isError(res) ? -1 : 0;
393 # elif defined(VGO_freebsd)
394 #if defined(__NR_pipe2)
395 SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
396 #else
397 SysRes res = VG_(do_syscall0)(__NR_freebsd10_pipe);
398 if (!sr_isError(res)) {
399 fd[0] = sr_Res(res);
400 fd[1] = sr_ResHI(res);
402 #endif
403 return sr_isError(res) ? -1 : 0;
404 # elif defined(VGO_darwin)
405 /* __NR_pipe is UX64, so produces a double-word result */
406 SysRes res = VG_(do_syscall0)(__NR_pipe);
407 if (!sr_isError(res)) {
408 fd[0] = (Int)sr_Res(res);
409 fd[1] = (Int)sr_ResHI(res);
411 return sr_isError(res) ? -1 : 0;
412 # elif defined(VGO_solaris)
413 # if defined(SOLARIS_NEW_PIPE_SYSCALL)
414 SysRes res = VG_(do_syscall2)(__NR_pipe, (UWord)fd, 0);
415 return sr_isError(res) ? -1 : 0;
416 # else
417 SysRes res = VG_(do_syscall0)(__NR_pipe);
418 if (!sr_isError(res)) {
419 fd[0] = (Int)sr_Res(res);
420 fd[1] = (Int)sr_ResHI(res);
422 return sr_isError(res) ? -1 : 0;
423 # endif
424 # else
425 # error "Unknown OS"
426 # endif
429 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
431 # if defined(VGO_linux) || defined(VGP_amd64_darwin) || defined(VGP_amd64_freebsd)
432 # if defined(__NR__llseek)
433 Off64T result;
434 SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
435 offset >> 32, offset & 0xffffffff,
436 (UWord)&result, whence);
437 return sr_isError(res) ? (-1) : result;
438 # else
439 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
440 vg_assert(sizeof(Off64T) == sizeof(sr_Res(res)));
441 return sr_isError(res) ? (-1) : sr_Res(res);
442 # endif
443 # elif defined(VGP_x86_darwin) || defined(VGP_x86_freebsd)
444 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
445 offset & 0xffffffff, offset >> 32, whence);
446 return sr_isError(res) ? (-1) : sr_Res(res);
447 # elif defined(VGP_x86_solaris)
448 SysRes res = VG_(do_syscall4)(__NR_llseek, fd,
449 offset & 0xffffffff, offset >> 32, whence);
450 return sr_isError(res) ? (-1) : ((ULong)sr_ResHI(res) << 32 | sr_Res(res));
451 # elif defined(VGP_amd64_solaris)
452 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
453 vg_assert(sizeof(Off64T) == sizeof(Word));
454 return sr_isError(res) ? (-1) : sr_Res(res);
455 # else
456 # error "Unknown plat"
457 # endif
458 /* if you change the error-reporting conventions of this, also
459 change all usage points. */
463 /* stat/fstat support. It's uggerly. We have impedance-match into a
464 'struct vg_stat' in order to have a single structure that callers
465 can use consistently on all platforms. */
467 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
468 do { \
469 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
470 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
471 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
472 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
473 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
474 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
475 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
476 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
477 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
478 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
479 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
480 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
481 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
482 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
483 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
484 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
485 } while (0)
487 #define TRANSLATE_statx_TO_vg_stat(_p_vgstat, _p_vkistat) \
488 do { \
489 (_p_vgstat)->dev = VG_MAKEDEV( (_p_vkistat)->stx_dev_major, \
490 (_p_vkistat)->stx_dev_minor ); \
491 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->stx_ino ); \
492 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->stx_nlink ); \
493 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->stx_mode ); \
494 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->stx_uid ); \
495 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->stx_gid ); \
496 (_p_vgstat)->rdev = VG_MAKEDEV( (_p_vkistat)->stx_rdev_major, \
497 (_p_vkistat)->stx_rdev_minor ); \
498 (_p_vgstat)->size = (Long) ( (_p_vkistat)->stx_size ); \
499 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->stx_blksize ); \
500 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->stx_blocks ); \
501 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->stx_atime.tv_sec ); \
502 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->stx_atime.tv_nsec ); \
503 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->stx_mtime.tv_sec ); \
504 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->stx_mtime.tv_nsec ); \
505 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->stx_ctime.tv_sec ); \
506 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->stx_ctime.tv_nsec ); \
507 } while (0)
509 SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
511 SysRes res;
512 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
514 # if defined(VGO_linux)
515 /* On Linux, first try with statx. If that doesn't work out, fall back to
516 the stat64 or vanilla version. */
517 { struct vki_statx buf;
518 res = VG_(do_syscall5)(__NR_statx, VKI_AT_FDCWD, (UWord)file_name, 0,
519 VKI_STATX_ALL, (UWord)&buf);
520 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
521 /* Success, or any failure except ENOSYS */
522 if (!sr_isError(res))
523 TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
524 return res;
527 # endif
528 # if defined(VGO_linux) || defined(VGO_darwin)
529 /* Try with stat64. This is the second candidate on Linux, and the first
530 one on Darwin. If that doesn't work out, fall back to vanilla version.
532 # if defined(__NR_stat64)
533 { struct vki_stat64 buf64;
534 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
535 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
536 /* Success, or any failure except ENOSYS */
537 if (!sr_isError(res))
538 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
539 return res;
542 # endif /* defined(__NR_stat64) */
543 # if defined(__NR_stat) || defined(VGP_arm64_linux)
544 /* This is the fallback ("vanilla version"). */
545 { struct vki_stat buf;
546 # if defined(VGP_arm64_linux)
547 res = VG_(do_syscall3)(__NR3264_fstatat, VKI_AT_FDCWD,
548 (UWord)file_name, (UWord)&buf);
549 # else
550 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
551 # endif
552 if (!sr_isError(res))
553 TRANSLATE_TO_vg_stat(vgbuf, &buf);
554 return res;
556 # endif
557 # elif defined(VGO_solaris)
559 # if defined(VGP_x86_solaris)
560 struct vki_stat64 buf64;
561 res = VG_(do_syscall4)(__NR_fstatat64, VKI_AT_FDCWD, (UWord)file_name,
562 (UWord)&buf64, 0);
563 # elif defined(VGP_amd64_solaris)
564 struct vki_stat buf64;
565 res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name,
566 (UWord)&buf64, 0);
567 # else
568 # error "Unknown platform"
569 # endif
570 if (!sr_isError(res))
571 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
572 return res;
574 # elif defined(VGO_freebsd)
576 #if (FREEBSD_VERS < FREEBSD_12)
577 struct vki_freebsd11_stat buf;
578 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
579 #else
580 struct vki_stat buf;
581 res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name, (UWord)&buf, 0);
582 #endif
583 if (!sr_isError(res)) {
584 TRANSLATE_TO_vg_stat(vgbuf, &buf);
586 return res;
588 # else
589 # error Unknown OS
590 # endif
593 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
595 SysRes res;
596 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
598 # if defined(VGO_linux)
599 /* On Linux, first try with statx. If that doesn't work out, fall back to
600 the fstat64 or vanilla version. */
601 { struct vki_statx buf;
602 const char* file_name = "";
603 res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
604 VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&buf);
605 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
606 /* Success, or any failure except ENOSYS */
607 if (!sr_isError(res))
608 TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
609 return sr_isError(res) ? (-1) : 0;
612 #endif
613 # if defined(VGO_linux) || defined(VGO_darwin)
614 /* Try with fstat64. This is the second candidate on Linux, and the first
615 one on Darwin. If that doesn't work out, fall back to vanilla version.
617 # if defined(__NR_fstat64)
618 { struct vki_stat64 buf64;
619 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
620 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
621 /* Success, or any failure except ENOSYS */
622 if (!sr_isError(res))
623 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
624 return sr_isError(res) ? (-1) : 0;
627 # endif /* defined(__NR_fstat64) */
628 # if defined(__NR_fstat)
629 { struct vki_stat buf;
630 res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
631 if (!sr_isError(res))
632 TRANSLATE_TO_vg_stat(vgbuf, &buf);
633 return sr_isError(res) ? (-1) : 0;
635 # endif
636 # elif defined(VGO_solaris)
638 # if defined(VGP_x86_solaris)
639 struct vki_stat64 buf64;
640 res = VG_(do_syscall4)(__NR_fstatat64, (UWord)fd, 0, (UWord)&buf64, 0);
641 # elif defined(VGP_amd64_solaris)
642 struct vki_stat buf64;
643 res = VG_(do_syscall4)(__NR_fstatat, (UWord)fd, 0, (UWord)&buf64, 0);
644 # else
645 # error "Unknown platform"
646 # endif
647 if (!sr_isError(res))
648 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
649 return sr_isError(res) ? (-1) : 0;
651 # elif defined(VGO_freebsd)
653 #if (FREEBSD_VERS < FREEBSD_12)
654 struct vki_freebsd11_stat buf;
655 res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
656 #else
657 struct vki_stat buf;
658 res = VG_(do_syscall2)(__NR_fstat, (RegWord)fd, (RegWord)(Addr)&buf);
659 #endif
660 if (!sr_isError(res)) {
661 TRANSLATE_TO_vg_stat(vgbuf, &buf);
663 return sr_isError(res) ? (-1) : 0;
665 # else
666 # error Unknown OS
667 # endif
670 #if defined(VGO_freebsd)
671 /* extend this to other OSes as and when needed */
672 SysRes VG_(lstat) ( const HChar* file_name, struct vg_stat* vgbuf )
674 SysRes res;
675 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
677 #if (FREEBSD_VERS < FREEBSD_12)
678 struct vki_freebsd11_stat buf;
679 res = VG_(do_syscall2)(__NR_lstat, (UWord)file_name, (UWord)&buf);
680 #else
681 struct vki_stat buf;
682 res = VG_(do_syscall4)(__NR_fstatat, VKI_AT_FDCWD, (UWord)file_name, (UWord)&buf, VKI_AT_SYMLINK_NOFOLLOW);
683 #endif
684 if (!sr_isError(res)) {
685 TRANSLATE_TO_vg_stat(vgbuf, &buf);
687 return res;
689 #endif
691 #undef TRANSLATE_TO_vg_stat
692 #undef TRANSLATE_statx_TO_vg_stat
694 Long VG_(fsize) ( Int fd )
696 struct vg_stat buf;
697 Int res = VG_(fstat)( fd, &buf );
698 return (res == -1) ? (-1LL) : buf.size;
701 SysRes VG_(getxattr) ( const HChar* file_name, const HChar* attr_name, Addr attr_value, SizeT attr_value_len )
703 SysRes res;
704 #if defined(VGO_linux)
705 res = VG_(do_syscall4)(__NR_getxattr, (UWord)file_name, (UWord)attr_name,
706 attr_value, attr_value_len);
707 #else
708 res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
709 #endif
710 return res;
713 Bool VG_(is_dir) ( const HChar* f )
715 struct vg_stat buf;
716 SysRes res = VG_(stat)(f, &buf);
717 return sr_isError(res) ? False
718 : VKI_S_ISDIR(buf.mode) ? True : False;
721 SysRes VG_(dup) ( Int oldfd )
723 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
724 return VG_(do_syscall1)(__NR_dup, oldfd);
725 # elif defined(VGO_solaris)
726 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUPFD, 0);
727 # else
728 # error Unknown OS
729 # endif
732 SysRes VG_(dup2) ( Int oldfd, Int newfd )
734 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
735 /* We only have dup3, that means we have to mimic dup2.
736 The only real difference is when oldfd == newfd.
737 dup3 always returns an error, but dup2 returns only an
738 error if the fd is invalid, otherwise it returns newfd. */
739 if (oldfd == newfd) {
740 if (VG_(fcntl)(oldfd, VKI_F_GETFL, 0) == -1)
741 return VG_(mk_SysRes_Error)(VKI_EBADF);
742 return VG_(mk_SysRes_Success)(newfd);
744 return VG_(do_syscall3)(__NR_dup3, oldfd, newfd, 0);
745 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
746 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
747 # elif defined(VGO_solaris)
748 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd);
749 # else
750 # error Unknown OS
751 # endif
754 /* Returns -1 on error. */
755 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
757 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
758 # if defined(VGP_nanomips_linux)
759 SysRes res = VG_(do_syscall3)(__NR_fcntl64, fd, cmd, arg);
760 # else
761 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
762 # endif
763 # elif defined(VGO_darwin)
764 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
765 # else
766 # error "Unknown OS"
767 # endif
768 if (sr_isError(res)) {
769 VG_(debugLog)(1, "VG_(fcntl)", "fcntl error %lu %s\n", sr_Err(res), VG_(strerror)(sr_Err(res)));
770 return -1;
772 return (Int)sr_Res(res);
775 Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
777 # if defined(VGO_solaris) || defined(VGP_arm64_linux)
778 SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
779 VKI_AT_FDCWD, (UWord)new_name);
780 # elif defined(VGP_nanomips_linux)
781 SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name,
782 VKI_AT_FDCWD, (UWord)new_name, 0);
784 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
785 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
786 # else
787 # error "Unknown OS"
788 # endif
789 return sr_isError(res) ? (-1) : 0;
792 Int VG_(unlink) ( const HChar* file_name )
794 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
795 SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
796 (UWord)file_name);
797 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
798 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
799 # elif defined(VGO_solaris)
800 SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD,
801 (UWord)file_name, 0);
802 # else
803 # error "Unknown OS"
804 # endif
805 return sr_isError(res) ? (-1) : 0;
808 /* The working directory at startup.
809 All that is really needed is to note the cwd at process startup.
810 Hence VG_(record_startup_wd) notes it (in a platform dependent way)
811 and VG_(get_startup_wd) produces the noted value. */
812 static HChar *startup_wd;
814 /* Record the process' working directory at startup. Is intended to
815 be called exactly once, at startup, before the working directory
816 changes. */
817 void VG_(record_startup_wd) ( void )
819 # if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
820 /* Simple: just ask the kernel */
821 SysRes res;
822 SizeT szB = 0;
823 do {
824 szB += 500;
825 startup_wd = VG_(realloc)("startup_wd", startup_wd, szB);
826 VG_(memset)(startup_wd, 0, szB);
827 # if defined(VGO_linux) || defined(VGO_solaris)
828 res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
829 # elif defined(VGO_freebsd)
830 res = VG_(do_syscall2)(__NR___getcwd, (UWord)startup_wd, szB-1);
831 # endif
832 } while (sr_isError(res) && sr_Err(res) == VKI_ERANGE);
834 if (sr_isError(res)) {
835 VG_(free)(startup_wd);
836 startup_wd = NULL;
837 return;
840 vg_assert(startup_wd[szB-1] == 0);
842 # elif defined(VGO_darwin)
843 /* We can't ask the kernel, so instead rely on launcher-*.c to
844 tell us the startup path. Note the env var is keyed to the
845 parent's PID, not ours, since our parent is the launcher
846 process. */
847 { HChar envvar[100]; // large enough
848 HChar* wd;
849 VG_(memset)(envvar, 0, sizeof(envvar));
850 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
851 (Int)VG_(getppid)());
852 wd = VG_(getenv)( envvar );
853 if (wd == NULL)
854 return;
855 SizeT need = VG_(strlen)(wd) + 1;
856 startup_wd = VG_(malloc)("startup_wd", need);
857 VG_(strcpy)(startup_wd, wd);
859 # else
860 # error Unknown OS
861 # endif
864 /* Return the previously acquired startup_wd or NULL. */
865 const HChar *VG_(get_startup_wd) ( void )
867 return startup_wd;
870 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
872 SysRes res;
873 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
874 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
875 struct vki_timespec timeout_ts;
876 if (timeout >= 0) {
877 timeout_ts.tv_sec = timeout / 1000;
878 timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000;
880 res = VG_(do_syscall4)(__NR_ppoll,
881 (UWord)fds, nfds,
882 (UWord)(timeout >= 0 ? &timeout_ts : NULL),
883 (UWord)NULL);
884 # elif defined(VGO_linux)
885 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
886 # elif defined(VGO_freebsd)
887 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
888 # elif defined(VGO_darwin)
889 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
890 # elif defined(VGO_solaris)
891 struct vki_timespec ts;
892 struct vki_timespec *tsp;
894 if (timeout < 0)
895 tsp = NULL;
896 else {
897 ts.tv_sec = timeout / 1000;
898 ts.tv_nsec = (timeout % 1000) * 1000000;
899 tsp = &ts;
902 res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0);
903 # else
904 # error "Unknown OS"
905 # endif
906 return res;
910 /* Performs the readlink operation and puts the result into 'buf'.
911 Note, that the string in 'buf' is *not* null-terminated. The function
912 returns the number of characters put into 'buf' or -1 if an error
913 occurred. */
914 SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
916 SysRes res;
917 /* res = readlink( path, buf, bufsiz ); */
918 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
919 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
920 (UWord)path, (UWord)buf, bufsiz);
921 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
922 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
923 # elif defined(VGO_solaris)
924 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
925 (UWord)buf, bufsiz);
926 # else
927 # error "Unknown OS"
928 # endif
929 return sr_isError(res) ? -1 : sr_Res(res);
932 #if defined(VGO_linux) || defined(VGO_solaris)
933 Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count)
935 SysRes res;
936 /* res = getdents( fd, dirp, count ); */
937 # if defined(VGP_amd64_solaris)
938 /* This silently assumes that dirent64 and dirent on amd64 are same, which
939 they should always be. */
940 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
941 # else
942 res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count);
943 # if defined(VGA_mips64)
944 /* The MIPS64 getdents64() system call is only present in 3.10+ kernels.
945 If the getdents64() system call is not available fall back to using
946 getdents() and modify the result to be compatible with getdents64(). */
947 if (sr_isError(res) && (sr_Err(res) == VKI_ENOSYS)) {
948 int r;
949 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
950 r = sr_Res(res);
951 if (r > 0) {
952 char *p;
953 char type;
954 union dirents {
955 struct vki_dirent m;
956 struct vki_dirent64 d;
957 } *u;
958 p = (char *)dirp;
959 do {
960 u = (union dirents *)p;
961 /* This should not happen, but just in case... */
962 if (p + u->m.d_reclen > (char *)dirp + r)
963 break;
964 /* shuffle the dirent */
965 type = *(p + u->m.d_reclen - 1);
966 VG_(memmove)(u->d.d_name, u->m.d_name,
967 u->m.d_reclen - 2
968 - offsetof(struct vki_dirent, d_name) + 1);
969 u->d.d_type = type;
970 p += u->m.d_reclen;
971 } while (p < (char *)dirp + r);
974 # endif
975 # endif
976 return sr_isError(res) ? -1 : sr_Res(res);
978 #endif
980 /* Check accessibility of a file. Returns zero for access granted,
981 nonzero otherwise. */
982 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
984 # if defined(VGO_linux)
985 /* Very annoyingly, I cannot find any definition for R_OK et al in
986 the kernel interfaces. Therefore I reluctantly resort to
987 hardwiring in these magic numbers that I determined by
988 experimentation. */
989 # define VKI_R_OK 4
990 # define VKI_W_OK 2
991 # define VKI_X_OK 1
992 # endif
994 UWord w = (irusr ? VKI_R_OK : 0)
995 | (iwusr ? VKI_W_OK : 0)
996 | (ixusr ? VKI_X_OK : 0);
997 # if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
998 SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
999 # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
1000 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
1001 # elif defined(VGO_solaris)
1002 SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path,
1003 w, 0);
1004 # else
1005 # error "Unknown OS"
1006 # endif
1007 return sr_isError(res) ? 1 : 0;
1009 # if defined(VGO_linux)
1010 # undef VKI_R_OK
1011 # undef VKI_W_OK
1012 # undef VKI_X_OK
1013 # endif
1017 Emulate the normal Unix permissions checking algorithm.
1019 If owner matches, then use the owner permissions, else
1020 if group matches, then use the group permissions, else
1021 use other permissions.
1023 Note that we can't deal properly with SUID/SGID. By default
1024 (allow_setuid == False), we refuse to run them (otherwise the
1025 executable may misbehave if it doesn't have the permissions it
1026 thinks it does). However, the caller may indicate that setuid
1027 executables are allowed, for example if we are going to exec them
1028 but not trace into them (iow, client sys_execve when
1029 clo_trace_children == False).
1031 If VKI_EACCES is returned (iow, permission was refused), then
1032 *is_setuid is set to True iff permission was refused because the
1033 executable is setuid.
1035 /* returns: 0 = success, non-0 is failure */
1036 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
1037 const HChar* f, Bool allow_setuid)
1039 struct vg_stat st;
1040 SysRes res = VG_(stat)(f, &st);
1042 if (is_setuid)
1043 *is_setuid = False;
1045 if (sr_isError(res)) {
1046 return sr_Err(res);
1049 if ( VKI_S_ISDIR (st.mode) ) {
1050 return VKI_EACCES;
1053 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
1054 if (is_setuid)
1055 *is_setuid = True;
1056 return VKI_EACCES;
1059 res = VG_(getxattr)(f, "security.capability", (Addr)0, 0);
1060 if (!sr_isError(res) && !allow_setuid) {
1061 if (is_setuid)
1062 *is_setuid = True;
1063 return VKI_EACCES;
1066 if (VG_(geteuid)() == st.uid) {
1067 if (!(st.mode & VKI_S_IXUSR))
1068 return VKI_EACCES;
1069 } else {
1070 Int grpmatch = 0;
1072 if (VG_(getegid)() == st.gid)
1073 grpmatch = 1;
1074 else {
1075 UInt *groups = NULL;
1076 Int ngrp;
1078 /* Find out # groups, allocate large enough array and fetch groups */
1079 ngrp = VG_(getgroups)(0, NULL);
1080 if (ngrp != -1) {
1081 groups = VG_(malloc)("check_executable", ngrp * sizeof *groups);
1082 ngrp = VG_(getgroups)(ngrp, groups);
1085 Int i;
1086 /* ngrp will be -1 if VG_(getgroups) failed. */
1087 for (i = 0; i < ngrp; i++) {
1088 if (groups[i] == st.gid) {
1089 grpmatch = 1;
1090 break;
1093 VG_(free)(groups);
1096 if (grpmatch) {
1097 if (!(st.mode & VKI_S_IXGRP)) {
1098 return VKI_EACCES;
1100 } else if (!(st.mode & VKI_S_IXOTH)) {
1101 return VKI_EACCES;
1105 return 0;
1108 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
1110 SysRes res;
1111 // on 32 bits platforms, we receive a 32 bits OffT but
1112 // we must extend it to pass a long long 64 bits.
1113 # if defined(VGP_x86_linux)
1114 vg_assert(sizeof(OffT) == 4);
1115 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
1116 offset, 0); // Little endian long long
1117 return res;
1118 # elif defined(VGP_arm_linux)
1119 vg_assert(sizeof(OffT) == 4);
1120 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
1121 0, offset); // Big endian long long
1122 return res;
1123 # elif defined(VGP_ppc32_linux)
1124 vg_assert(sizeof(OffT) == 4);
1125 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
1126 0, // Padding needed on PPC32
1127 0, offset); // Big endian long long
1128 return res;
1129 # elif (defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)) \
1130 && (VKI_LITTLE_ENDIAN)
1131 vg_assert(sizeof(OffT) == 4);
1132 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
1133 0, offset, 0);
1134 return res;
1135 # elif (defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)) \
1136 && (VKI_BIG_ENDIAN)
1137 vg_assert(sizeof(OffT) == 4);
1138 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
1139 0, 0, offset);
1140 return res;
1141 # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
1142 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1143 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
1144 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
1145 return res;
1146 # elif defined(VGP_amd64_freebsd)
1147 vg_assert(sizeof(OffT) == 8);
1148 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
1149 return res;
1150 # elif defined(VGP_x86_freebsd)
1151 vg_assert(sizeof(OffT) == 8);
1152 res = VG_(do_syscall5)(__NR_pread, fd, (UWord)buf, count,
1153 offset & 0xffffffff, offset >> 32);
1154 return res;
1155 # elif defined(VGP_amd64_darwin)
1156 vg_assert(sizeof(OffT) == 8);
1157 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
1158 return res;
1159 # elif defined(VGP_x86_darwin)
1160 vg_assert(sizeof(OffT) == 8);
1161 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
1162 offset & 0xffffffff, offset >> 32);
1163 return res;
1164 # elif defined(VGP_x86_solaris)
1165 vg_assert(sizeof(OffT) == 4);
1166 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
1167 return res;
1168 # elif defined(VGP_amd64_solaris)
1169 vg_assert(sizeof(OffT) == 8);
1170 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset);
1171 return res;
1172 # else
1173 # error "Unknown platform"
1174 # endif
1177 /* Return the name of a directory for temporary files. */
1178 const HChar *VG_(tmpdir)(void)
1180 const HChar *tmpdir;
1182 tmpdir = VG_(getenv)("TMPDIR");
1183 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
1184 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */
1186 return tmpdir;
1189 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x";
1191 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len )
1193 return VG_(strlen)(mkstemp_format)
1194 + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir
1195 + part_of_name_len - 2 // %s part_of_name
1196 + 8 - 4 // %08x
1197 + 1; // trailing 0
1201 Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname )
1203 Int n, tries;
1204 UInt seed;
1205 SysRes sres;
1206 const HChar *tmpdir;
1208 vg_assert(part_of_name);
1209 vg_assert(fullname);
1210 n = VG_(strlen)(part_of_name);
1211 vg_assert(n > 0 && n < 100);
1213 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
1215 /* Determine sensible location for temporary files */
1216 tmpdir = VG_(tmpdir)();
1218 tries = 0;
1219 while (True) {
1220 if (tries++ > 10)
1221 return -1;
1222 VG_(sprintf)( fullname, mkstemp_format,
1223 tmpdir, part_of_name, VG_(random)( &seed ));
1224 if (0)
1225 VG_(printf)("VG_(mkstemp): trying: %s\n", fullname);
1227 sres = VG_(open)(fullname,
1228 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
1229 VKI_S_IRUSR|VKI_S_IWUSR);
1230 if (sr_isError(sres)) {
1231 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname);
1232 continue;
1234 /* VG_(safe_fd) doesn't return if it fails. */
1235 return VG_(safe_fd)( sr_Res(sres) );
1237 /* NOTREACHED */
1241 /* ---------------------------------------------------------------------
1242 Socket-related stuff.
1243 ------------------------------------------------------------------ */
1245 static
1246 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port );
1248 static
1249 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
1251 UInt VG_(htonl) ( UInt x )
1253 # if defined(VG_BIGENDIAN)
1254 return x;
1255 # else
1256 return
1257 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1258 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1259 # endif
1262 UInt VG_(ntohl) ( UInt x )
1264 # if defined(VG_BIGENDIAN)
1265 return x;
1266 # else
1267 return
1268 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
1269 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
1270 # endif
1273 UShort VG_(htons) ( UShort x )
1275 # if defined(VG_BIGENDIAN)
1276 return x;
1277 # else
1278 return
1279 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1280 # endif
1283 UShort VG_(ntohs) ( UShort x )
1285 # if defined(VG_BIGENDIAN)
1286 return x;
1287 # else
1288 return
1289 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
1290 # endif
1294 /* The main function.
1296 Supplied string contains either an ip address "192.168.0.1" or
1297 an ip address and port pair, "192.168.0.1:1500". Parse these,
1298 and return:
1299 -1 if there is a parse error
1300 -2 if no parse error, but specified host:port cannot be opened
1301 the relevant file (socket) descriptor, otherwise.
1302 is used.
1304 Int VG_(connect_via_socket)( const HChar* str )
1306 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
1307 Int sd, res;
1308 struct vki_sockaddr_in servAddr;
1309 UInt ip = 0;
1310 UShort port = VG_CLO_DEFAULT_LOGPORT;
1311 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
1312 if (!ok)
1313 return -1;
1315 //if (0)
1316 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
1317 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
1318 // (ip >> 8) & 0xFF, ip & 0xFF,
1319 // (UInt)port );
1321 servAddr.sin_family = VKI_AF_INET;
1322 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
1323 servAddr.sin_port = VG_(htons)(port);
1325 /* create socket */
1326 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
1327 if (sd < 0) {
1328 /* this shouldn't happen ... nevertheless */
1329 return -2;
1332 /* connect to server */
1333 res = my_connect(sd, &servAddr, sizeof(servAddr));
1334 if (res < 0) {
1335 /* connection failed */
1336 return -2;
1339 return sd;
1341 # else
1342 # error "Unknown OS"
1343 # endif
1347 /* Let d = one or more digits. Accept either:
1348 d.d.d.d or d.d.d.d:d
1350 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port )
1352 # define GET_CH ((*str) ? (*str++) : 0)
1353 UInt ipa, i, j, c, any;
1354 ipa = 0;
1355 for (i = 0; i < 4; i++) {
1356 j = 0;
1357 any = 0;
1358 while (1) {
1359 c = GET_CH;
1360 if (c < '0' || c > '9') break;
1361 j = 10 * j + (int)(c - '0');
1362 any = 1;
1364 if (any == 0 || j > 255) goto syntaxerr;
1365 ipa = (ipa << 8) + j;
1366 if (i <= 2 && c != '.') goto syntaxerr;
1368 if (c == 0 || c == ':')
1369 *ip_addr = ipa;
1370 if (c == 0) goto ok;
1371 if (c != ':') goto syntaxerr;
1372 j = 0;
1373 any = 0;
1374 while (1) {
1375 c = GET_CH;
1376 if (c < '0' || c > '9') break;
1377 j = j * 10 + (int)(c - '0');
1378 any = 1;
1379 if (j > 65535) goto syntaxerr;
1381 if (any == 0 || c != 0) goto syntaxerr;
1382 if (j < 1024) goto syntaxerr;
1383 *port = (UShort)j;
1385 return 1;
1386 syntaxerr:
1387 return 0;
1388 # undef GET_CH
1391 // GrP fixme safe_fd?
1392 Int VG_(socket) ( Int domain, Int type, Int protocol )
1394 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1395 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1396 || defined(VGP_s390x_linux)
1397 SysRes res;
1398 UWord args[3];
1399 args[0] = domain;
1400 args[1] = type;
1401 args[2] = protocol;
1402 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
1403 return sr_isError(res) ? -1 : sr_Res(res);
1405 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1406 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1407 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1408 SysRes res;
1409 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
1410 return sr_isError(res) ? -1 : sr_Res(res);
1412 # elif defined(VGO_darwin)
1413 SysRes res;
1414 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
1415 if (!sr_isError(res)) {
1416 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
1417 Int optval = 1;
1418 SysRes res2;
1419 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
1420 VKI_SO_NOSIGPIPE, (UWord)&optval,
1421 sizeof(optval));
1422 // ignore setsockopt() error
1424 return sr_isError(res) ? -1 : sr_Res(res);
1426 # elif defined(VGO_solaris)
1427 /* XXX There doesn't seem to be an easy way to convince the send syscall to
1428 only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if
1429 SM_KERNEL is set on the socket. Without serious hackery it looks we
1430 can't set this flag.
1432 Should we wrap the send syscall below into sigprocmask calls to block
1433 SIGPIPE?
1435 SysRes res;
1436 res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol,
1437 0 /*devpath*/, VKI_SOV_DEFAULT /*version*/);
1438 return sr_isError(res) ? -1 : sr_Res(res);
1440 # else
1441 # error "Unknown arch"
1442 # endif
1446 static
1447 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
1449 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1450 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1451 || defined(VGP_s390x_linux)
1452 SysRes res;
1453 UWord args[3];
1454 args[0] = sockfd;
1455 args[1] = (UWord)serv_addr;
1456 args[2] = addrlen;
1457 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
1458 return sr_isError(res) ? -1 : sr_Res(res);
1460 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1461 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1462 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1463 SysRes res;
1464 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
1465 return sr_isError(res) ? -1 : sr_Res(res);
1467 # elif defined(VGO_darwin)
1468 SysRes res;
1469 res = VG_(do_syscall3)(__NR_connect_nocancel,
1470 sockfd, (UWord)serv_addr, addrlen);
1471 return sr_isError(res) ? -1 : sr_Res(res);
1473 # elif defined(VGO_solaris)
1474 SysRes res;
1475 res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen,
1476 VKI_SOV_DEFAULT /*version*/);
1477 return sr_isError(res) ? -1 : sr_Res(res);
1479 # else
1480 # error "Unknown arch"
1481 # endif
1484 Int VG_(write_socket)( Int sd, const void *msg, Int count )
1486 /* This is actually send(). */
1488 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
1489 errors on stream oriented sockets when the other end breaks the
1490 connection. The EPIPE error is still returned.
1492 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
1493 SIGPIPE */
1495 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1496 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1497 || defined(VGP_s390x_linux)
1498 SysRes res;
1499 UWord args[4];
1500 args[0] = sd;
1501 args[1] = (UWord)msg;
1502 args[2] = count;
1503 args[3] = VKI_MSG_NOSIGNAL;
1504 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
1505 return sr_isError(res) ? -1 : sr_Res(res);
1507 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1508 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1509 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1510 SysRes res;
1511 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
1512 count, VKI_MSG_NOSIGNAL, 0,0);
1513 return sr_isError(res) ? -1 : sr_Res(res);
1515 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
1516 SysRes res;
1517 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
1518 return sr_isError(res) ? -1 : sr_Res(res);
1520 # elif defined(VGO_solaris)
1521 SysRes res;
1522 res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/);
1523 return sr_isError(res) ? -1 : sr_Res(res);
1525 # else
1526 # error "Unknown platform"
1527 # endif
1530 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1532 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1533 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1534 || defined(VGP_s390x_linux) \
1535 || defined(VGP_mips32_linux)
1536 SysRes res;
1537 UWord args[3];
1538 args[0] = sd;
1539 args[1] = (UWord)name;
1540 args[2] = (UWord)namelen;
1541 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
1542 return sr_isError(res) ? -1 : sr_Res(res);
1544 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1545 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1546 || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
1547 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
1548 SysRes res;
1549 res = VG_(do_syscall3)( __NR_getsockname,
1550 (UWord)sd, (UWord)name, (UWord)namelen );
1551 return sr_isError(res) ? -1 : sr_Res(res);
1553 # elif defined(VGO_darwin)
1554 SysRes res;
1555 res = VG_(do_syscall3)( __NR_getsockname,
1556 (UWord)sd, (UWord)name, (UWord)namelen );
1557 return sr_isError(res) ? -1 : sr_Res(res);
1559 # elif defined(VGO_solaris)
1560 SysRes res;
1561 res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen,
1562 VKI_SOV_DEFAULT /*version*/);
1563 return sr_isError(res) ? -1 : sr_Res(res);
1565 # else
1566 # error "Unknown platform"
1567 # endif
1570 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
1572 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1573 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1574 || defined(VGP_s390x_linux) \
1575 || defined(VGP_mips32_linux)
1576 SysRes res;
1577 UWord args[3];
1578 args[0] = sd;
1579 args[1] = (UWord)name;
1580 args[2] = (UWord)namelen;
1581 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
1582 return sr_isError(res) ? -1 : sr_Res(res);
1584 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1585 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
1586 || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
1587 SysRes res;
1588 res = VG_(do_syscall3)( __NR_getpeername,
1589 (UWord)sd, (UWord)name, (UWord)namelen );
1590 return sr_isError(res) ? -1 : sr_Res(res);
1592 # elif defined(VGO_darwin)
1593 SysRes res;
1594 res = VG_(do_syscall3)( __NR_getpeername,
1595 (UWord)sd, (UWord)name, (UWord)namelen );
1596 return sr_isError(res) ? -1 : sr_Res(res);
1598 # elif defined(VGO_solaris)
1599 SysRes res;
1600 res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen,
1601 VKI_SOV_DEFAULT /*version*/);
1602 return sr_isError(res) ? -1 : sr_Res(res);
1604 # else
1605 # error "Unknown platform"
1606 # endif
1609 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1610 Int *optlen)
1612 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1613 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1614 || defined(VGP_s390x_linux)
1615 SysRes res;
1616 UWord args[5];
1617 args[0] = sd;
1618 args[1] = level;
1619 args[2] = optname;
1620 args[3] = (UWord)optval;
1621 args[4] = (UWord)optlen;
1622 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
1623 return sr_isError(res) ? -1 : sr_Res(res);
1625 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1626 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1627 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
1628 || defined(VGO_freebsd)
1629 SysRes res;
1630 res = VG_(do_syscall5)( __NR_getsockopt,
1631 (UWord)sd, (UWord)level, (UWord)optname,
1632 (UWord)optval, (UWord)optlen );
1633 return sr_isError(res) ? -1 : sr_Res(res);
1635 # elif defined(VGO_darwin)
1636 SysRes res;
1637 res = VG_(do_syscall5)( __NR_getsockopt,
1638 (UWord)sd, (UWord)level, (UWord)optname,
1639 (UWord)optval, (UWord)optlen );
1640 return sr_isError(res) ? -1 : sr_Res(res);
1642 # elif defined(VGO_solaris)
1643 SysRes res;
1644 res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval,
1645 (UWord)optlen, VKI_SOV_DEFAULT /*version*/);
1646 return sr_isError(res) ? -1 : sr_Res(res);
1648 # else
1649 # error "Unknown platform"
1650 # endif
1654 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
1655 Int optlen)
1657 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1658 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
1659 || defined(VGP_s390x_linux)
1660 SysRes res;
1661 UWord args[5];
1662 args[0] = sd;
1663 args[1] = level;
1664 args[2] = optname;
1665 args[3] = (UWord)optval;
1666 args[4] = (UWord)optlen;
1667 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args);
1668 return sr_isError(res) ? -1 : sr_Res(res);
1670 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1671 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
1672 || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
1673 SysRes res;
1674 res = VG_(do_syscall5)( __NR_setsockopt,
1675 (UWord)sd, (UWord)level, (UWord)optname,
1676 (UWord)optval, (UWord)optlen );
1677 return sr_isError(res) ? -1 : sr_Res(res);
1679 # elif defined(VGO_darwin) || defined(VGO_freebsd)
1680 SysRes res;
1681 res = VG_(do_syscall5)( __NR_setsockopt,
1682 (UWord)sd, (UWord)level, (UWord)optname,
1683 (UWord)optval, (UWord)optlen );
1684 return sr_isError(res) ? -1 : sr_Res(res);
1686 # elif defined(VGO_solaris)
1687 SysRes res;
1688 res = VG_(do_syscall6)( __NR_setsockopt,
1689 (UWord)sd, (UWord)level, (UWord)optname,
1690 (UWord)optval, (UWord)optlen,
1691 VKI_SOV_DEFAULT /*version*/ );
1692 return sr_isError(res) ? -1 : sr_Res(res);
1694 # else
1695 # error "Unknown platform"
1696 # endif
1700 const HChar *VG_(basename)(const HChar *path)
1702 static HChar *buf = NULL;
1703 static SizeT buf_len = 0;
1704 const HChar *p, *end;
1706 if (path == NULL ||
1707 0 == VG_(strcmp)(path, ""))
1709 return ".";
1712 p = path + VG_(strlen)(path);
1713 while (p > path && *p == '/') {
1714 // skip all trailing '/'
1715 p--;
1718 if (p == path && *p == '/') return "/"; // all slashes
1720 end = p;
1722 while (p > path && *p != '/') {
1723 // now skip non '/'
1724 p--;
1727 if (*p == '/') p++;
1729 SizeT need = end-p+1 + 1;
1730 if (need > buf_len) {
1731 buf_len = (buf_len == 0) ? 500 : need;
1732 buf = VG_(realloc)("basename", buf, buf_len);
1734 VG_(strncpy)(buf, p, end-p+1);
1735 buf[end-p+1] = '\0';
1737 return buf;
1741 const HChar *VG_(dirname)(const HChar *path)
1743 static HChar *buf = NULL;
1744 static SizeT buf_len = 0;
1746 const HChar *p;
1748 if (path == NULL ||
1749 0 == VG_(strcmp)(path, "") ||
1750 0 == VG_(strcmp)(path, "/"))
1752 return ".";
1755 p = path + VG_(strlen)(path);
1756 while (p > path && *p == '/') {
1757 // skip all trailing '/'
1758 p--;
1761 while (p > path && *p != '/') {
1762 // now skip non '/'
1763 p--;
1766 if (p == path) {
1767 if (*p == '/') return "/"; // all slashes
1768 else return "."; // no slashes
1771 while (p > path && *p == '/') {
1772 // skip '/' again
1773 p--;
1776 SizeT need = p-path+1 + 1;
1777 if (need > buf_len) {
1778 buf_len = (buf_len == 0) ? 500 : need;
1779 buf = VG_(realloc)("dirname", buf, buf_len);
1781 VG_(strncpy)(buf, path, p-path+1);
1782 buf[p-path+1] = '\0';
1784 return buf;
1787 #if defined(VGO_freebsd)
1789 * I did look at nicking this from FreeBSD, it's fairly easy to port
1790 * but I was put off by the copyright and 3-clause licence
1791 * Then I looked at nicking it from glibc but that is full of
1792 * macros private functions and conditions for Windows.
1793 * So I gave up as it is only for FreeBSD 11 and 12.
1795 * It is somewhat hard-coded for sysctl_kern_proc_pathname
1796 * and PRE(sys___sysctl) assuming resolved has
1797 * VKI_PATH_MAX space.
1799 Bool VG_(realpath)(const HChar *path, HChar *resolved)
1801 vg_assert(path);
1802 vg_assert(resolved);
1803 #if (FREEBSD_VERS >= FREEBSD_13_0)
1804 return !sr_isError(VG_(do_syscall5)(__NR___realpathat, VKI_AT_FDCWD, (RegWord)path, (RegWord)resolved, VKI_PATH_MAX, 0));
1805 #else
1806 // poor man's realpath
1807 const HChar *resolved_name;
1808 HChar tmp[VKI_PATH_MAX];
1810 struct vg_stat statbuf;
1811 SysRes res = VG_(lstat)(path, &statbuf);
1813 if (sr_isError(res)) {
1814 return False;
1817 if (VKI_S_ISLNK(statbuf.mode)) {
1818 SizeT link_len = VG_(readlink)(path, tmp, VKI_PATH_MAX);
1819 tmp[link_len] = '\0';
1820 resolved_name = tmp;
1821 } else {
1822 // not a link
1823 resolved_name = path;
1826 if (resolved_name[0] != '/') {
1827 // relative path
1828 if (resolved_name[0] == '.' && resolved_name[1] == '/') {
1829 resolved_name += 2;
1831 VG_(snprintf)(resolved, VKI_PATH_MAX, "%s/%s", VG_(get_startup_wd)(), resolved_name);
1832 } else {
1833 VG_(snprintf)(resolved, VKI_PATH_MAX, "%s", resolved_name);
1836 return True;
1837 #endif
1839 #endif
1842 /*--------------------------------------------------------------------*/
1843 /*--- end ---*/
1844 /*--------------------------------------------------------------------*/