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