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-2017 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) 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) 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) 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) 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(VGP_arm64_linux) 484 /* We only have dup3, that means we have to mimic dup2. 485 The only real difference is when oldfd == newfd. 486 dup3 always returns an error, but dup2 returns only an 487 error if the fd is invalid, otherwise it returns newfd. */ 488 if (oldfd == newfd) { 489 if (VG_(fcntl)(oldfd, VKI_F_GETFL, 0) == -1) 490 return VG_(mk_SysRes_Error)(VKI_EBADF); 491 return VG_(mk_SysRes_Success)(newfd); 492 } 493 return VG_(do_syscall3)(__NR_dup3, oldfd, newfd, 0); 494 # elif defined(VGO_linux) || defined(VGO_darwin) 495 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd); 496 # elif defined(VGO_solaris) 497 return VG_(do_syscall3)(__NR_fcntl, oldfd, F_DUP2FD, newfd); 498 # else 499 # error Unknown OS 500 # endif 501 } 502 503 /* Returns -1 on error. */ 504 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg ) 505 { 506 # if defined(VGO_linux) || defined(VGO_solaris) 507 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg); 508 # elif defined(VGO_darwin) 509 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg); 510 # else 511 # error "Unknown OS" 512 # endif 513 return sr_isError(res) ? -1 : sr_Res(res); 514 } 515 516 Int VG_(rename) ( const HChar* old_name, const HChar* new_name ) 517 { 518 # if defined(VGO_solaris) || defined(VGP_arm64_linux) 519 SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name, 520 VKI_AT_FDCWD, (UWord)new_name); 521 # elif defined(VGO_linux) || defined(VGO_darwin) 522 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name); 523 # else 524 # error "Unknown OS" 525 # endif 526 return sr_isError(res) ? (-1) : 0; 527 } 528 529 Int VG_(unlink) ( const HChar* file_name ) 530 { 531 # if defined(VGP_arm64_linux) 532 SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD, 533 (UWord)file_name); 534 # elif defined(VGO_linux) || defined(VGO_darwin) 535 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name); 536 # elif defined(VGO_solaris) 537 SysRes res = VG_(do_syscall3)(__NR_unlinkat, VKI_AT_FDCWD, 538 (UWord)file_name, 0); 539 # else 540 # error "Unknown OS" 541 # endif 542 return sr_isError(res) ? (-1) : 0; 543 } 544 545 /* The working directory at startup. 546 All that is really needed is to note the cwd at process startup. 547 Hence VG_(record_startup_wd) notes it (in a platform dependent way) 548 and VG_(get_startup_wd) produces the noted value. */ 549 static HChar *startup_wd; 550 551 /* Record the process' working directory at startup. Is intended to 552 be called exactly once, at startup, before the working directory 553 changes. */ 554 void VG_(record_startup_wd) ( void ) 555 { 556 # if defined(VGO_linux) || defined(VGO_solaris) 557 /* Simple: just ask the kernel */ 558 SysRes res; 559 SizeT szB = 0; 560 do { 561 szB += 500; 562 startup_wd = VG_(realloc)("startup_wd", startup_wd, szB); 563 VG_(memset)(startup_wd, 0, szB); 564 res = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1); 565 } while (sr_isError(res) && sr_Err(res) == VKI_ERANGE); 566 567 if (sr_isError(res)) { 568 VG_(free)(startup_wd); 569 startup_wd = NULL; 570 return; 571 } 572 573 vg_assert(startup_wd[szB-1] == 0); 574 575 # elif defined(VGO_darwin) 576 /* We can't ask the kernel, so instead rely on launcher-*.c to 577 tell us the startup path. Note the env var is keyed to the 578 parent's PID, not ours, since our parent is the launcher 579 process. */ 580 { HChar envvar[100]; // large enough 581 HChar* wd; 582 VG_(memset)(envvar, 0, sizeof(envvar)); 583 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY", 584 (Int)VG_(getppid)()); 585 wd = VG_(getenv)( envvar ); 586 if (wd == NULL) 587 return; 588 SizeT need = VG_(strlen)(wd) + 1; 589 startup_wd = VG_(malloc)("startup_wd", need); 590 VG_(strcpy)(startup_wd, wd); 591 } 592 # else 593 # error Unknown OS 594 # endif 595 } 596 597 /* Return the previously acquired startup_wd or NULL. */ 598 const HChar *VG_(get_startup_wd) ( void ) 599 { 600 return startup_wd; 601 } 602 603 SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout) 604 { 605 SysRes res; 606 # if defined(VGP_arm64_linux) 607 /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */ 608 struct vki_timespec timeout_ts; 609 if (timeout >= 0) { 610 timeout_ts.tv_sec = timeout / 1000; 611 timeout_ts.tv_nsec = ((long)timeout % 1000) * 1000000; 612 } 613 res = VG_(do_syscall4)(__NR_ppoll, 614 (UWord)fds, nfds, 615 (UWord)(timeout >= 0 ? &timeout_ts : NULL), 616 (UWord)NULL); 617 # elif defined(VGO_linux) 618 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout); 619 # elif defined(VGO_darwin) 620 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout); 621 # elif defined(VGO_solaris) 622 struct vki_timespec ts; 623 struct vki_timespec *tsp; 624 625 if (timeout < 0) 626 tsp = NULL; 627 else { 628 ts.tv_sec = timeout / 1000; 629 ts.tv_nsec = (timeout % 1000) * 1000000; 630 tsp = &ts; 631 } 632 633 res = VG_(do_syscall4)(__NR_pollsys, (UWord)fds, nfds, (UWord)tsp, 0); 634 # else 635 # error "Unknown OS" 636 # endif 637 return res; 638 } 639 640 641 /* Performs the readlink operation and puts the result into 'buf'. 642 Note, that the string in 'buf' is *not* null-terminated. The function 643 returns the number of characters put into 'buf' or -1 if an error 644 occurred. */ 645 SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz) 646 { 647 SysRes res; 648 /* res = readlink( path, buf, bufsiz ); */ 649 # if defined(VGP_arm64_linux) 650 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, 651 (UWord)path, (UWord)buf, bufsiz); 652 # elif defined(VGO_linux) || defined(VGO_darwin) 653 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz); 654 # elif defined(VGO_solaris) 655 res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path, 656 (UWord)buf, bufsiz); 657 # else 658 # error "Unknown OS" 659 # endif 660 return sr_isError(res) ? -1 : sr_Res(res); 661 } 662 663 #if defined(VGO_linux) || defined(VGO_solaris) 664 Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count) 665 { 666 SysRes res; 667 /* res = getdents( fd, dirp, count ); */ 668 # if defined(VGP_amd64_solaris) 669 /* This silently assumes that dirent64 and dirent on amd64 are same, which 670 they should always be. */ 671 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); 672 # else 673 res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count); 674 # if defined(VGA_mips64) 675 /* The MIPS64 getdents64() system call is only present in 3.10+ kernels. 676 If the getdents64() system call is not available fall back to using 677 getdents() and modify the result to be compatible with getdents64(). */ 678 if (sr_isError(res) && (sr_Err(res) == VKI_ENOSYS)) { 679 int r; 680 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); 681 r = sr_Res(res); 682 if (r > 0) { 683 char *p; 684 char type; 685 union dirents { 686 struct vki_dirent m; 687 struct vki_dirent64 d; 688 } *u; 689 p = (char *)dirp; 690 do { 691 u = (union dirents *)p; 692 /* This should not happen, but just in case... */ 693 if (p + u->m.d_reclen > (char *)dirp + r) 694 break; 695 /* shuffle the dirent */ 696 type = *(p + u->m.d_reclen - 1); 697 VG_(memmove)(u->d.d_name, u->m.d_name, 698 u->m.d_reclen - 2 699 - offsetof(struct vki_dirent, d_name) + 1); 700 u->d.d_type = type; 701 p += u->m.d_reclen; 702 } while (p < (char *)dirp + r); 703 } 704 } 705 # endif 706 # endif 707 return sr_isError(res) ? -1 : sr_Res(res); 708 } 709 #endif 710 711 /* Check accessibility of a file. Returns zero for access granted, 712 nonzero otherwise. */ 713 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr ) 714 { 715 # if defined(VGO_linux) 716 /* Very annoyingly, I cannot find any definition for R_OK et al in 717 the kernel interfaces. Therefore I reluctantly resort to 718 hardwiring in these magic numbers that I determined by 719 experimentation. */ 720 # define VKI_R_OK 4 721 # define VKI_W_OK 2 722 # define VKI_X_OK 1 723 # endif 724 725 UWord w = (irusr ? VKI_R_OK : 0) 726 | (iwusr ? VKI_W_OK : 0) 727 | (ixusr ? VKI_X_OK : 0); 728 # if defined(VGP_arm64_linux) 729 SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w); 730 # elif defined(VGO_linux) || defined(VGO_darwin) 731 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w); 732 # elif defined(VGO_solaris) 733 SysRes res = VG_(do_syscall4)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, 734 w, 0); 735 # else 736 # error "Unknown OS" 737 # endif 738 return sr_isError(res) ? 1 : 0; 739 740 # if defined(VGO_linux) 741 # undef VKI_R_OK 742 # undef VKI_W_OK 743 # undef VKI_X_OK 744 # endif 745 } 746 747 /* 748 Emulate the normal Unix permissions checking algorithm. 749 750 If owner matches, then use the owner permissions, else 751 if group matches, then use the group permissions, else 752 use other permissions. 753 754 Note that we can't deal properly with SUID/SGID. By default 755 (allow_setuid == False), we refuse to run them (otherwise the 756 executable may misbehave if it doesn't have the permissions it 757 thinks it does). However, the caller may indicate that setuid 758 executables are allowed, for example if we are going to exec them 759 but not trace into them (iow, client sys_execve when 760 clo_trace_children == False). 761 762 If VKI_EACCES is returned (iow, permission was refused), then 763 *is_setuid is set to True iff permission was refused because the 764 executable is setuid. 765 */ 766 /* returns: 0 = success, non-0 is failure */ 767 Int VG_(check_executable)(/*OUT*/Bool* is_setuid, 768 const HChar* f, Bool allow_setuid) 769 { 770 struct vg_stat st; 771 SysRes res = VG_(stat)(f, &st); 772 773 if (is_setuid) 774 *is_setuid = False; 775 776 if (sr_isError(res)) { 777 return sr_Err(res); 778 } 779 780 if ( VKI_S_ISDIR (st.mode) ) { 781 return VKI_EACCES; 782 } 783 784 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) { 785 if (is_setuid) 786 *is_setuid = True; 787 return VKI_EACCES; 788 } 789 790 res = VG_(getxattr)(f, "security.capability", (Addr)0, 0); 791 if (!sr_isError(res) && !allow_setuid) { 792 if (is_setuid) 793 *is_setuid = True; 794 return VKI_EACCES; 795 } 796 797 if (VG_(geteuid)() == st.uid) { 798 if (!(st.mode & VKI_S_IXUSR)) 799 return VKI_EACCES; 800 } else { 801 Int grpmatch = 0; 802 803 if (VG_(getegid)() == st.gid) 804 grpmatch = 1; 805 else { 806 UInt *groups = NULL; 807 Int ngrp; 808 809 /* Find out # groups, allocate large enough array and fetch groups */ 810 ngrp = VG_(getgroups)(0, NULL); 811 if (ngrp != -1) { 812 groups = VG_(malloc)("check_executable", ngrp * sizeof *groups); 813 ngrp = VG_(getgroups)(ngrp, groups); 814 } 815 816 Int i; 817 /* ngrp will be -1 if VG_(getgroups) failed. */ 818 for (i = 0; i < ngrp; i++) { 819 if (groups[i] == st.gid) { 820 grpmatch = 1; 821 break; 822 } 823 } 824 VG_(free)(groups); 825 } 826 827 if (grpmatch) { 828 if (!(st.mode & VKI_S_IXGRP)) { 829 return VKI_EACCES; 830 } 831 } else if (!(st.mode & VKI_S_IXOTH)) { 832 return VKI_EACCES; 833 } 834 } 835 836 return 0; 837 } 838 839 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset ) 840 { 841 SysRes res; 842 // on 32 bits platforms, we receive a 32 bits OffT but 843 // we must extend it to pass a long long 64 bits. 844 # if defined(VGP_x86_linux) 845 vg_assert(sizeof(OffT) == 4); 846 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count, 847 offset, 0); // Little endian long long 848 return res; 849 # elif defined(VGP_arm_linux) 850 vg_assert(sizeof(OffT) == 4); 851 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count, 852 0, offset); // Big endian long long 853 return res; 854 # elif defined(VGP_ppc32_linux) 855 vg_assert(sizeof(OffT) == 4); 856 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 857 0, // Padding needed on PPC32 858 0, offset); // Big endian long long 859 return res; 860 # elif defined(VGP_mips32_linux) && (VKI_LITTLE_ENDIAN) 861 vg_assert(sizeof(OffT) == 4); 862 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 863 0, offset, 0); 864 return res; 865 # elif defined(VGP_mips32_linux) && (VKI_BIG_ENDIAN) 866 vg_assert(sizeof(OffT) == 4); 867 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count, 868 0, 0, offset); 869 return res; 870 # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \ 871 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 872 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) 873 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset); 874 return res; 875 # elif defined(VGP_amd64_darwin) 876 vg_assert(sizeof(OffT) == 8); 877 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset); 878 return res; 879 # elif defined(VGP_x86_darwin) 880 vg_assert(sizeof(OffT) == 8); 881 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count, 882 offset & 0xffffffff, offset >> 32); 883 return res; 884 # elif defined(VGP_x86_solaris) 885 vg_assert(sizeof(OffT) == 4); 886 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset); 887 return res; 888 # elif defined(VGP_amd64_solaris) 889 vg_assert(sizeof(OffT) == 8); 890 res = VG_(do_syscall4)(__NR_pread, fd, (UWord)buf, count, offset); 891 return res; 892 # else 893 # error "Unknown platform" 894 # endif 895 } 896 897 /* Return the name of a directory for temporary files. */ 898 const HChar *VG_(tmpdir)(void) 899 { 900 const HChar *tmpdir; 901 902 tmpdir = VG_(getenv)("TMPDIR"); 903 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR; 904 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */ 905 906 return tmpdir; 907 } 908 909 static const HChar mkstemp_format[] = "%s/valgrind_%s_%08x"; 910 911 SizeT VG_(mkstemp_fullname_bufsz) ( SizeT part_of_name_len ) 912 { 913 return VG_(strlen)(mkstemp_format) 914 + VG_(strlen)(VG_(tmpdir)()) - 2 // %s tmpdir 915 + part_of_name_len - 2 // %s part_of_name 916 + 8 - 4 // %08x 917 + 1; // trailing 0 918 } 919 920 921 Int VG_(mkstemp) ( const HChar* part_of_name, /*OUT*/HChar* fullname ) 922 { 923 Int n, tries; 924 UInt seed; 925 SysRes sres; 926 const HChar *tmpdir; 927 928 vg_assert(part_of_name); 929 vg_assert(fullname); 930 n = VG_(strlen)(part_of_name); 931 vg_assert(n > 0 && n < 100); 932 933 seed = (VG_(getpid)() << 9) ^ VG_(getppid)(); 934 935 /* Determine sensible location for temporary files */ 936 tmpdir = VG_(tmpdir)(); 937 938 tries = 0; 939 while (True) { 940 if (tries++ > 10) 941 return -1; 942 VG_(sprintf)( fullname, mkstemp_format, 943 tmpdir, part_of_name, VG_(random)( &seed )); 944 if (0) 945 VG_(printf)("VG_(mkstemp): trying: %s\n", fullname); 946 947 sres = VG_(open)(fullname, 948 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC, 949 VKI_S_IRUSR|VKI_S_IWUSR); 950 if (sr_isError(sres)) { 951 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", fullname); 952 continue; 953 } 954 /* VG_(safe_fd) doesn't return if it fails. */ 955 return VG_(safe_fd)( sr_Res(sres) ); 956 } 957 /* NOTREACHED */ 958 } 959 960 961 /* --------------------------------------------------------------------- 962 Socket-related stuff. 963 ------------------------------------------------------------------ */ 964 965 static 966 Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port ); 967 968 static 969 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ); 970 971 UInt VG_(htonl) ( UInt x ) 972 { 973 # if defined(VG_BIGENDIAN) 974 return x; 975 # else 976 return 977 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) 978 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); 979 # endif 980 } 981 982 UInt VG_(ntohl) ( UInt x ) 983 { 984 # if defined(VG_BIGENDIAN) 985 return x; 986 # else 987 return 988 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8) 989 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24); 990 # endif 991 } 992 993 UShort VG_(htons) ( UShort x ) 994 { 995 # if defined(VG_BIGENDIAN) 996 return x; 997 # else 998 return 999 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); 1000 # endif 1001 } 1002 1003 UShort VG_(ntohs) ( UShort x ) 1004 { 1005 # if defined(VG_BIGENDIAN) 1006 return x; 1007 # else 1008 return 1009 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8); 1010 # endif 1011 } 1012 1013 1014 /* The main function. 1015 1016 Supplied string contains either an ip address "192.168.0.1" or 1017 an ip address and port pair, "192.168.0.1:1500". Parse these, 1018 and return: 1019 -1 if there is a parse error 1020 -2 if no parse error, but specified host:port cannot be opened 1021 the relevant file (socket) descriptor, otherwise. 1022 is used. 1023 */ 1024 Int VG_(connect_via_socket)( const HChar* str ) 1025 { 1026 # if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_solaris) 1027 Int sd, res; 1028 struct vki_sockaddr_in servAddr; 1029 UInt ip = 0; 1030 UShort port = VG_CLO_DEFAULT_LOGPORT; 1031 Bool ok = parse_inet_addr_and_port(str, &ip, &port); 1032 if (!ok) 1033 return -1; 1034 1035 //if (0) 1036 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n", 1037 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, 1038 // (ip >> 8) & 0xFF, ip & 0xFF, 1039 // (UInt)port ); 1040 1041 servAddr.sin_family = VKI_AF_INET; 1042 servAddr.sin_addr.s_addr = VG_(htonl)(ip); 1043 servAddr.sin_port = VG_(htons)(port); 1044 1045 /* create socket */ 1046 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */); 1047 if (sd < 0) { 1048 /* this shouldn't happen ... nevertheless */ 1049 return -2; 1050 } 1051 1052 /* connect to server */ 1053 res = my_connect(sd, &servAddr, sizeof(servAddr)); 1054 if (res < 0) { 1055 /* connection failed */ 1056 return -2; 1057 } 1058 1059 return sd; 1060 1061 # else 1062 # error "Unknown OS" 1063 # endif 1064 } 1065 1066 1067 /* Let d = one or more digits. Accept either: 1068 d.d.d.d or d.d.d.d:d 1069 */ 1070 static Int parse_inet_addr_and_port ( const HChar* str, UInt* ip_addr, UShort* port ) 1071 { 1072 # define GET_CH ((*str) ? (*str++) : 0) 1073 UInt ipa, i, j, c, any; 1074 ipa = 0; 1075 for (i = 0; i < 4; i++) { 1076 j = 0; 1077 any = 0; 1078 while (1) { 1079 c = GET_CH; 1080 if (c < '0' || c > '9') break; 1081 j = 10 * j + (int)(c - '0'); 1082 any = 1; 1083 } 1084 if (any == 0 || j > 255) goto syntaxerr; 1085 ipa = (ipa << 8) + j; 1086 if (i <= 2 && c != '.') goto syntaxerr; 1087 } 1088 if (c == 0 || c == ':') 1089 *ip_addr = ipa; 1090 if (c == 0) goto ok; 1091 if (c != ':') goto syntaxerr; 1092 j = 0; 1093 any = 0; 1094 while (1) { 1095 c = GET_CH; 1096 if (c < '0' || c > '9') break; 1097 j = j * 10 + (int)(c - '0'); 1098 any = 1; 1099 if (j > 65535) goto syntaxerr; 1100 } 1101 if (any == 0 || c != 0) goto syntaxerr; 1102 if (j < 1024) goto syntaxerr; 1103 *port = (UShort)j; 1104 ok: 1105 return 1; 1106 syntaxerr: 1107 return 0; 1108 # undef GET_CH 1109 } 1110 1111 // GrP fixme safe_fd? 1112 Int VG_(socket) ( Int domain, Int type, Int protocol ) 1113 { 1114 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1115 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1116 || defined(VGP_s390x_linux) 1117 SysRes res; 1118 UWord args[3]; 1119 args[0] = domain; 1120 args[1] = type; 1121 args[2] = protocol; 1122 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args); 1123 return sr_isError(res) ? -1 : sr_Res(res); 1124 1125 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1126 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ 1127 || defined(VGP_arm64_linux) 1128 SysRes res; 1129 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol ); 1130 return sr_isError(res) ? -1 : sr_Res(res); 1131 1132 # elif defined(VGO_darwin) 1133 SysRes res; 1134 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol); 1135 if (!sr_isError(res)) { 1136 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE 1137 Int optval = 1; 1138 SysRes res2; 1139 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET, 1140 VKI_SO_NOSIGPIPE, (UWord)&optval, 1141 sizeof(optval)); 1142 // ignore setsockopt() error 1143 } 1144 return sr_isError(res) ? -1 : sr_Res(res); 1145 1146 # elif defined(VGO_solaris) 1147 /* XXX There doesn't seem to be an easy way to convince the send syscall to 1148 only return EPIPE instead of raising SIGPIPE. EPIPE is only returned if 1149 SM_KERNEL is set on the socket. Without serious hackery it looks we 1150 can't set this flag. 1151 1152 Should we wrap the send syscall below into sigprocmask calls to block 1153 SIGPIPE? 1154 */ 1155 SysRes res; 1156 res = VG_(do_syscall5)(__NR_so_socket, domain, type, protocol, 1157 0 /*devpath*/, VKI_SOV_DEFAULT /*version*/); 1158 return sr_isError(res) ? -1 : sr_Res(res); 1159 1160 # else 1161 # error "Unknown arch" 1162 # endif 1163 } 1164 1165 1166 static 1167 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen ) 1168 { 1169 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1170 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1171 || defined(VGP_s390x_linux) 1172 SysRes res; 1173 UWord args[3]; 1174 args[0] = sockfd; 1175 args[1] = (UWord)serv_addr; 1176 args[2] = addrlen; 1177 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args); 1178 return sr_isError(res) ? -1 : sr_Res(res); 1179 1180 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1181 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ 1182 || defined(VGP_arm64_linux) 1183 SysRes res; 1184 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen); 1185 return sr_isError(res) ? -1 : sr_Res(res); 1186 1187 # elif defined(VGO_darwin) 1188 SysRes res; 1189 res = VG_(do_syscall3)(__NR_connect_nocancel, 1190 sockfd, (UWord)serv_addr, addrlen); 1191 return sr_isError(res) ? -1 : sr_Res(res); 1192 1193 # elif defined(VGO_solaris) 1194 SysRes res; 1195 res = VG_(do_syscall4)(__NR_connect, sockfd, (UWord)serv_addr, addrlen, 1196 VKI_SOV_DEFAULT /*version*/); 1197 return sr_isError(res) ? -1 : sr_Res(res); 1198 1199 # else 1200 # error "Unknown arch" 1201 # endif 1202 } 1203 1204 Int VG_(write_socket)( Int sd, const void *msg, Int count ) 1205 { 1206 /* This is actually send(). */ 1207 1208 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on 1209 errors on stream oriented sockets when the other end breaks the 1210 connection. The EPIPE error is still returned. 1211 1212 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of 1213 SIGPIPE */ 1214 1215 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1216 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1217 || defined(VGP_s390x_linux) 1218 SysRes res; 1219 UWord args[4]; 1220 args[0] = sd; 1221 args[1] = (UWord)msg; 1222 args[2] = count; 1223 args[3] = VKI_MSG_NOSIGNAL; 1224 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args); 1225 return sr_isError(res) ? -1 : sr_Res(res); 1226 1227 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1228 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ 1229 || defined(VGP_arm64_linux) 1230 SysRes res; 1231 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg, 1232 count, VKI_MSG_NOSIGNAL, 0,0); 1233 return sr_isError(res) ? -1 : sr_Res(res); 1234 1235 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin) 1236 SysRes res; 1237 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count); 1238 return sr_isError(res) ? -1 : sr_Res(res); 1239 1240 # elif defined(VGO_solaris) 1241 SysRes res; 1242 res = VG_(do_syscall4)(__NR_send, sd, (UWord)msg, count, 0 /*flags*/); 1243 return sr_isError(res) ? -1 : sr_Res(res); 1244 1245 # else 1246 # error "Unknown platform" 1247 # endif 1248 } 1249 1250 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen) 1251 { 1252 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1253 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1254 || defined(VGP_s390x_linux) \ 1255 || defined(VGP_mips32_linux) 1256 SysRes res; 1257 UWord args[3]; 1258 args[0] = sd; 1259 args[1] = (UWord)name; 1260 args[2] = (UWord)namelen; 1261 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args); 1262 return sr_isError(res) ? -1 : sr_Res(res); 1263 1264 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1265 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) 1266 SysRes res; 1267 res = VG_(do_syscall3)( __NR_getsockname, 1268 (UWord)sd, (UWord)name, (UWord)namelen ); 1269 return sr_isError(res) ? -1 : sr_Res(res); 1270 1271 # elif defined(VGO_darwin) 1272 SysRes res; 1273 res = VG_(do_syscall3)( __NR_getsockname, 1274 (UWord)sd, (UWord)name, (UWord)namelen ); 1275 return sr_isError(res) ? -1 : sr_Res(res); 1276 1277 # elif defined(VGO_solaris) 1278 SysRes res; 1279 res = VG_(do_syscall4)(__NR_getsockname, sd, (UWord)name, (UWord)namelen, 1280 VKI_SOV_DEFAULT /*version*/); 1281 return sr_isError(res) ? -1 : sr_Res(res); 1282 1283 # else 1284 # error "Unknown platform" 1285 # endif 1286 } 1287 1288 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen) 1289 { 1290 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1291 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1292 || defined(VGP_s390x_linux) \ 1293 || defined(VGP_mips32_linux) 1294 SysRes res; 1295 UWord args[3]; 1296 args[0] = sd; 1297 args[1] = (UWord)name; 1298 args[2] = (UWord)namelen; 1299 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args); 1300 return sr_isError(res) ? -1 : sr_Res(res); 1301 1302 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1303 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) 1304 SysRes res; 1305 res = VG_(do_syscall3)( __NR_getpeername, 1306 (UWord)sd, (UWord)name, (UWord)namelen ); 1307 return sr_isError(res) ? -1 : sr_Res(res); 1308 1309 # elif defined(VGO_darwin) 1310 SysRes res; 1311 res = VG_(do_syscall3)( __NR_getpeername, 1312 (UWord)sd, (UWord)name, (UWord)namelen ); 1313 return sr_isError(res) ? -1 : sr_Res(res); 1314 1315 # elif defined(VGO_solaris) 1316 SysRes res; 1317 res = VG_(do_syscall4)(__NR_getpeername, sd, (UWord)name, (UWord)namelen, 1318 VKI_SOV_DEFAULT /*version*/); 1319 return sr_isError(res) ? -1 : sr_Res(res); 1320 1321 # else 1322 # error "Unknown platform" 1323 # endif 1324 } 1325 1326 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval, 1327 Int *optlen) 1328 { 1329 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1330 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1331 || defined(VGP_s390x_linux) 1332 SysRes res; 1333 UWord args[5]; 1334 args[0] = sd; 1335 args[1] = level; 1336 args[2] = optname; 1337 args[3] = (UWord)optval; 1338 args[4] = (UWord)optlen; 1339 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args); 1340 return sr_isError(res) ? -1 : sr_Res(res); 1341 1342 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1343 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ 1344 || defined(VGP_arm64_linux) 1345 SysRes res; 1346 res = VG_(do_syscall5)( __NR_getsockopt, 1347 (UWord)sd, (UWord)level, (UWord)optname, 1348 (UWord)optval, (UWord)optlen ); 1349 return sr_isError(res) ? -1 : sr_Res(res); 1350 1351 # elif defined(VGO_darwin) 1352 SysRes res; 1353 res = VG_(do_syscall5)( __NR_getsockopt, 1354 (UWord)sd, (UWord)level, (UWord)optname, 1355 (UWord)optval, (UWord)optlen ); 1356 return sr_isError(res) ? -1 : sr_Res(res); 1357 1358 # elif defined(VGO_solaris) 1359 SysRes res; 1360 res = VG_(do_syscall6)(__NR_getsockopt, sd, level, optname, (UWord)optval, 1361 (UWord)optlen, VKI_SOV_DEFAULT /*version*/); 1362 return sr_isError(res) ? -1 : sr_Res(res); 1363 1364 # else 1365 # error "Unknown platform" 1366 # endif 1367 } 1368 1369 1370 Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval, 1371 Int optlen) 1372 { 1373 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \ 1374 || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \ 1375 || defined(VGP_s390x_linux) 1376 SysRes res; 1377 UWord args[5]; 1378 args[0] = sd; 1379 args[1] = level; 1380 args[2] = optname; 1381 args[3] = (UWord)optval; 1382 args[4] = (UWord)optlen; 1383 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SETSOCKOPT, (UWord)&args); 1384 return sr_isError(res) ? -1 : sr_Res(res); 1385 1386 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \ 1387 || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \ 1388 || defined(VGP_arm64_linux) 1389 SysRes res; 1390 res = VG_(do_syscall5)( __NR_setsockopt, 1391 (UWord)sd, (UWord)level, (UWord)optname, 1392 (UWord)optval, (UWord)optlen ); 1393 return sr_isError(res) ? -1 : sr_Res(res); 1394 1395 # elif defined(VGO_darwin) 1396 SysRes res; 1397 res = VG_(do_syscall5)( __NR_setsockopt, 1398 (UWord)sd, (UWord)level, (UWord)optname, 1399 (UWord)optval, (UWord)optlen ); 1400 return sr_isError(res) ? -1 : sr_Res(res); 1401 1402 # elif defined(VGO_solaris) 1403 SysRes res; 1404 res = VG_(do_syscall6)( __NR_setsockopt, 1405 (UWord)sd, (UWord)level, (UWord)optname, 1406 (UWord)optval, (UWord)optlen, 1407 VKI_SOV_DEFAULT /*version*/ ); 1408 return sr_isError(res) ? -1 : sr_Res(res); 1409 1410 # else 1411 # error "Unknown platform" 1412 # endif 1413 } 1414 1415 1416 const HChar *VG_(basename)(const HChar *path) 1417 { 1418 static HChar *buf = NULL; 1419 static SizeT buf_len = 0; 1420 const HChar *p, *end; 1421 1422 if (path == NULL || 1423 0 == VG_(strcmp)(path, "")) 1424 { 1425 return "."; 1426 } 1427 1428 p = path + VG_(strlen)(path); 1429 while (p > path && *p == '/') { 1430 // skip all trailing '/' 1431 p--; 1432 } 1433 1434 if (p == path && *p == '/') return "/"; // all slashes 1435 1436 end = p; 1437 1438 while (p > path && *p != '/') { 1439 // now skip non '/' 1440 p--; 1441 } 1442 1443 if (*p == '/') p++; 1444 1445 SizeT need = end-p+1 + 1; 1446 if (need > buf_len) { 1447 buf_len = (buf_len == 0) ? 500 : need; 1448 buf = VG_(realloc)("basename", buf, buf_len); 1449 } 1450 VG_(strncpy)(buf, p, end-p+1); 1451 buf[end-p+1] = '\0'; 1452 1453 return buf; 1454 } 1455 1456 1457 const HChar *VG_(dirname)(const HChar *path) 1458 { 1459 static HChar *buf = NULL; 1460 static SizeT buf_len = 0; 1461 1462 const HChar *p; 1463 1464 if (path == NULL || 1465 0 == VG_(strcmp)(path, "") || 1466 0 == VG_(strcmp)(path, "/")) 1467 { 1468 return "."; 1469 } 1470 1471 p = path + VG_(strlen)(path); 1472 while (p > path && *p == '/') { 1473 // skip all trailing '/' 1474 p--; 1475 } 1476 1477 while (p > path && *p != '/') { 1478 // now skip non '/' 1479 p--; 1480 } 1481 1482 if (p == path) { 1483 if (*p == '/') return "/"; // all slashes 1484 else return "."; // no slashes 1485 } 1486 1487 while (p > path && *p == '/') { 1488 // skip '/' again 1489 p--; 1490 } 1491 1492 SizeT need = p-path+1 + 1; 1493 if (need > buf_len) { 1494 buf_len = (buf_len == 0) ? 500 : need; 1495 buf = VG_(realloc)("dirname", buf, buf_len); 1496 } 1497 VG_(strncpy)(buf, path, p-path+1); 1498 buf[p-path+1] = '\0'; 1499 1500 return buf; 1501 } 1502 1503 1504 /*--------------------------------------------------------------------*/ 1505 /*--- end ---*/ 1506 /*--------------------------------------------------------------------*/ 1507