1
2 /*--------------------------------------------------------------------*/
3 /*--- File- and socket-related libc stuff. m_libcfile.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2012 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_vkiscnums.h"
34 #include "pub_core_debuglog.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcassert.h"
37 #include "pub_core_libcfile.h"
38 #include "pub_core_libcprint.h" // VG_(sprintf)
39 #include "pub_core_libcproc.h" // VG_(getpid), VG_(getppid)
40 #include "pub_core_xarray.h"
41 #include "pub_core_clientstate.h" // VG_(fd_hard_limit)
42 #include "pub_core_syscall.h"
43
44 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
45 of syscalls rather than the vanilla version, if a _nocancel version
46 is available. See docs/internals/Darwin-notes.txt for the reason
47 why. */
48
49 /* ---------------------------------------------------------------------
50 File stuff
51 ------------------------------------------------------------------ */
52
fd_exists(Int fd)53 static inline Bool fd_exists(Int fd)
54 {
55 struct vg_stat st;
56 return VG_(fstat)(fd, &st) == 0;
57 }
58
59 /* Move an fd into the Valgrind-safe range */
VG_(safe_fd)60 Int VG_(safe_fd)(Int oldfd)
61 {
62 Int newfd;
63
64 vg_assert(VG_(fd_hard_limit) != -1);
65
66 newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
67 if (newfd != -1)
68 VG_(close)(oldfd);
69
70 /* Set the close-on-exec flag for this fd. */
71 VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
72
73 vg_assert(newfd >= VG_(fd_hard_limit));
74 return newfd;
75 }
76
77 /* Given a file descriptor, attempt to deduce its filename. To do
78 this, we use /proc/self/fd/<FD>. If this doesn't point to a file,
79 or if it doesn't exist, we return False. */
VG_(resolve_filename)80 Bool VG_(resolve_filename) ( Int fd, HChar* buf, Int n_buf )
81 {
82 # if defined(VGO_linux)
83 HChar tmp[64];
84 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
85 VG_(memset)(buf, 0, n_buf);
86 if (VG_(readlink)(tmp, buf, n_buf) > 0 && buf[0] == '/')
87 return True;
88 else
89 return False;
90
91 # elif defined(VGO_darwin)
92 HChar tmp[VKI_MAXPATHLEN+1];
93 if (0 == VG_(fcntl)(fd, VKI_F_GETPATH, (UWord)tmp)) {
94 if (n_buf > 0) {
95 VG_(strncpy)( buf, tmp, n_buf < sizeof(tmp) ? n_buf : sizeof(tmp) );
96 buf[n_buf-1] = 0;
97 }
98 if (tmp[0] == '/') return True;
99 }
100 return False;
101
102 # else
103 # error Unknown OS
104 # endif
105 }
106
VG_(mknod)107 SysRes VG_(mknod) ( const Char* pathname, Int mode, UWord dev )
108 {
109 # if defined(VGO_linux) || defined(VGO_darwin)
110 SysRes res = VG_(do_syscall3)(__NR_mknod,
111 (UWord)pathname, mode, dev);
112 # else
113 # error Unknown OS
114 # endif
115 return res;
116 }
117
VG_(open)118 SysRes VG_(open) ( const Char* pathname, Int flags, Int mode )
119 {
120 # if defined(VGO_linux)
121 SysRes res = VG_(do_syscall3)(__NR_open,
122 (UWord)pathname, flags, mode);
123 # elif defined(VGO_darwin)
124 SysRes res = VG_(do_syscall3)(__NR_open_nocancel,
125 (UWord)pathname, flags, mode);
126 # else
127 # error Unknown OS
128 # endif
129 return res;
130 }
131
VG_(fd_open)132 Int VG_(fd_open) (const Char* pathname, Int flags, Int mode)
133 {
134 SysRes sr;
135 sr = VG_(open) (pathname, flags, mode);
136 if (sr_isError (sr))
137 return -1;
138 else
139 return sr_Res (sr);
140 }
141
VG_(close)142 void VG_(close) ( Int fd )
143 {
144 /* Hmm. Return value is not checked. That's uncool. */
145 # if defined(VGO_linux)
146 (void)VG_(do_syscall1)(__NR_close, fd);
147 # elif defined(VGO_darwin)
148 (void)VG_(do_syscall1)(__NR_close_nocancel, fd);
149 # else
150 # error Unknown OS
151 # endif
152 }
153
VG_(read)154 Int VG_(read) ( Int fd, void* buf, Int count)
155 {
156 Int ret;
157 # if defined(VGO_linux)
158 SysRes res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
159 # elif defined(VGO_darwin)
160 SysRes res = VG_(do_syscall3)(__NR_read_nocancel, fd, (UWord)buf, count);
161 # else
162 # error Unknown OS
163 # endif
164 if (sr_isError(res)) {
165 ret = - (Int)(Word)sr_Err(res);
166 vg_assert(ret < 0);
167 } else {
168 ret = (Int)(Word)sr_Res(res);
169 vg_assert(ret >= 0);
170 }
171 return ret;
172 }
173
VG_(write)174 Int VG_(write) ( Int fd, const void* buf, Int count)
175 {
176 Int ret;
177 # if defined(VGO_linux)
178 SysRes res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
179 # elif defined(VGO_darwin)
180 SysRes res = VG_(do_syscall3)(__NR_write_nocancel, fd, (UWord)buf, count);
181 # else
182 # error "Unknown OS"
183 # endif
184 if (sr_isError(res)) {
185 ret = - (Int)(Word)sr_Err(res);
186 vg_assert(ret < 0);
187 } else {
188 ret = (Int)(Word)sr_Res(res);
189 vg_assert(ret >= 0);
190 }
191 return ret;
192 }
193
194
VG_(pipe)195 Int VG_(pipe) ( Int fd[2] )
196 {
197 # if defined(VGP_mips32_linux)
198 /* __NR_pipe has a strange return convention on mips32-linux. */
199 SysRes res = VG_(do_syscall0)(__NR_pipe);
200 if (!sr_isError(res)) {
201 fd[0] = (Int)sr_Res(res);
202 fd[1] = (Int)sr_ResEx(res);
203 return 0;
204 } else {
205 return -1;
206 }
207 # elif defined(VGO_linux)
208 SysRes res = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
209 return sr_isError(res) ? -1 : 0;
210 # elif defined(VGO_darwin)
211 /* __NR_pipe is UX64, so produces a double-word result */
212 SysRes res = VG_(do_syscall0)(__NR_pipe);
213 if (!sr_isError(res)) {
214 fd[0] = (Int)sr_Res(res);
215 fd[1] = (Int)sr_ResHI(res);
216 }
217 return sr_isError(res) ? -1 : 0;
218 # else
219 # error "Unknown OS"
220 # endif
221 }
222
VG_(lseek)223 Off64T VG_(lseek) ( Int fd, Off64T offset, Int whence )
224 {
225 # if defined(VGO_linux) || defined(VGP_amd64_darwin)
226 # if defined(__NR__llseek)
227 Off64T result;
228 SysRes res = VG_(do_syscall5)(__NR__llseek, fd,
229 offset >> 32, offset & 0xffffffff,
230 (UWord)&result, whence);
231 return sr_isError(res) ? (-1) : result;
232 # else
233 SysRes res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
234 vg_assert(sizeof(Off64T) == sizeof(Word));
235 return sr_isError(res) ? (-1) : sr_Res(res);
236 # endif
237 # elif defined(VGP_x86_darwin)
238 SysRes res = VG_(do_syscall4)(__NR_lseek, fd,
239 offset & 0xffffffff, offset >> 32, whence);
240 return sr_isError(res) ? (-1) : sr_Res(res);
241 # else
242 # error "Unknown plat"
243 # endif
244 /* if you change the error-reporting conventions of this, also
245 change all usage points. */
246 }
247
248
249 /* stat/fstat support. It's uggerly. We have impedance-match into a
250 'struct vg_stat' in order to have a single structure that callers
251 can use consistently on all platforms. */
252
253 #define TRANSLATE_TO_vg_stat(_p_vgstat, _p_vkistat) \
254 do { \
255 (_p_vgstat)->dev = (ULong)( (_p_vkistat)->st_dev ); \
256 (_p_vgstat)->ino = (ULong)( (_p_vkistat)->st_ino ); \
257 (_p_vgstat)->nlink = (ULong)( (_p_vkistat)->st_nlink ); \
258 (_p_vgstat)->mode = (UInt) ( (_p_vkistat)->st_mode ); \
259 (_p_vgstat)->uid = (UInt) ( (_p_vkistat)->st_uid ); \
260 (_p_vgstat)->gid = (UInt) ( (_p_vkistat)->st_gid ); \
261 (_p_vgstat)->rdev = (ULong)( (_p_vkistat)->st_rdev ); \
262 (_p_vgstat)->size = (Long) ( (_p_vkistat)->st_size ); \
263 (_p_vgstat)->blksize = (ULong)( (_p_vkistat)->st_blksize ); \
264 (_p_vgstat)->blocks = (ULong)( (_p_vkistat)->st_blocks ); \
265 (_p_vgstat)->atime = (ULong)( (_p_vkistat)->st_atime ); \
266 (_p_vgstat)->atime_nsec = (ULong)( (_p_vkistat)->st_atime_nsec ); \
267 (_p_vgstat)->mtime = (ULong)( (_p_vkistat)->st_mtime ); \
268 (_p_vgstat)->mtime_nsec = (ULong)( (_p_vkistat)->st_mtime_nsec ); \
269 (_p_vgstat)->ctime = (ULong)( (_p_vkistat)->st_ctime ); \
270 (_p_vgstat)->ctime_nsec = (ULong)( (_p_vkistat)->st_ctime_nsec ); \
271 } while (0)
272
VG_(stat)273 SysRes VG_(stat) ( const Char* file_name, struct vg_stat* vgbuf )
274 {
275 SysRes res;
276 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
277
278 # if defined(VGO_linux) || defined(VGO_darwin)
279 /* First try with stat64. If that doesn't work out, fall back to
280 the vanilla version. */
281 # if defined(__NR_stat64)
282 { struct vki_stat64 buf64;
283 res = VG_(do_syscall2)(__NR_stat64, (UWord)file_name, (UWord)&buf64);
284 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
285 /* Success, or any failure except ENOSYS */
286 if (!sr_isError(res))
287 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
288 return res;
289 }
290 }
291 # endif /* defined(__NR_stat64) */
292 { struct vki_stat buf;
293 res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)&buf);
294 if (!sr_isError(res))
295 TRANSLATE_TO_vg_stat(vgbuf, &buf);
296 return res;
297 }
298
299 # else
300 # error Unknown OS
301 # endif
302 }
303
VG_(fstat)304 Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
305 {
306 SysRes res;
307 VG_(memset)(vgbuf, 0, sizeof(*vgbuf));
308
309 # if defined(VGO_linux) || defined(VGO_darwin)
310 /* First try with fstat64. If that doesn't work out, fall back to
311 the vanilla version. */
312 # if defined(__NR_fstat64)
313 { struct vki_stat64 buf64;
314 res = VG_(do_syscall2)(__NR_fstat64, (UWord)fd, (UWord)&buf64);
315 if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
316 /* Success, or any failure except ENOSYS */
317 if (!sr_isError(res))
318 TRANSLATE_TO_vg_stat(vgbuf, &buf64);
319 return sr_isError(res) ? (-1) : 0;
320 }
321 }
322 # endif /* if defined(__NR_fstat64) */
323 { struct vki_stat buf;
324 res = VG_(do_syscall2)(__NR_fstat, (UWord)fd, (UWord)&buf);
325 if (!sr_isError(res))
326 TRANSLATE_TO_vg_stat(vgbuf, &buf);
327 return sr_isError(res) ? (-1) : 0;
328 }
329
330 # else
331 # error Unknown OS
332 # endif
333 }
334
335 #undef TRANSLATE_TO_vg_stat
336
337
VG_(fsize)338 Long VG_(fsize) ( Int fd )
339 {
340 struct vg_stat buf;
341 Int res = VG_(fstat)( fd, &buf );
342 return (res == -1) ? (-1LL) : buf.size;
343 }
344
VG_(is_dir)345 Bool VG_(is_dir) ( const HChar* f )
346 {
347 struct vg_stat buf;
348 SysRes res = VG_(stat)(f, &buf);
349 return sr_isError(res) ? False
350 : VKI_S_ISDIR(buf.mode) ? True : False;
351 }
352
VG_(dup)353 SysRes VG_(dup) ( Int oldfd )
354 {
355 return VG_(do_syscall1)(__NR_dup, oldfd);
356 }
357
VG_(dup2)358 SysRes VG_(dup2) ( Int oldfd, Int newfd )
359 {
360 # if defined(VGO_linux) || defined(VGO_darwin)
361 return VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
362 # else
363 # error Unknown OS
364 # endif
365 }
366
367 /* Returns -1 on error. */
VG_(fcntl)368 Int VG_(fcntl) ( Int fd, Int cmd, Addr arg )
369 {
370 # if defined(VGO_linux)
371 SysRes res = VG_(do_syscall3)(__NR_fcntl, fd, cmd, arg);
372 # elif defined(VGO_darwin)
373 SysRes res = VG_(do_syscall3)(__NR_fcntl_nocancel, fd, cmd, arg);
374 # else
375 # error "Unknown OS"
376 # endif
377 return sr_isError(res) ? -1 : sr_Res(res);
378 }
379
VG_(rename)380 Int VG_(rename) ( const Char* old_name, const Char* new_name )
381 {
382 SysRes res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
383 return sr_isError(res) ? (-1) : 0;
384 }
385
VG_(unlink)386 Int VG_(unlink) ( const Char* file_name )
387 {
388 SysRes res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
389 return sr_isError(res) ? (-1) : 0;
390 }
391
392 /* The working directory at startup. AIX doesn't provide an easy
393 system call to do getcwd, but fortunately we don't need arbitrary
394 getcwd support. All that is really needed is to note the cwd at
395 process startup. Hence VG_(record_startup_wd) notes it (in a
396 platform dependent way) and VG_(get_startup_wd) produces the noted
397 value. Hence: */
398 static HChar startup_wd[VKI_PATH_MAX];
399 static Bool startup_wd_acquired = False;
400
401 /* Record the process' working directory at startup. Is intended to
402 be called exactly once, at startup, before the working directory
403 changes. Return True for success, False for failure, so that the
404 caller can bomb out suitably without creating module cycles if
405 there is a problem. */
VG_(record_startup_wd)406 Bool VG_(record_startup_wd) ( void )
407 {
408 const Int szB = sizeof(startup_wd);
409 vg_assert(!startup_wd_acquired);
410 vg_assert(szB >= 512 && szB <= 16384/*let's say*/); /* stay sane */
411 VG_(memset)(startup_wd, 0, szB);
412 # if defined(VGO_linux)
413 /* Simple: just ask the kernel */
414 { SysRes res
415 = VG_(do_syscall2)(__NR_getcwd, (UWord)startup_wd, szB-1);
416 vg_assert(startup_wd[szB-1] == 0);
417 if (sr_isError(res)) {
418 return False;
419 } else {
420 startup_wd_acquired = True;
421 return True;
422 }
423 }
424 # elif defined(VGO_darwin)
425 /* We can't ask the kernel, so instead rely on launcher-*.c to
426 tell us the startup path. Note the env var is keyed to the
427 parent's PID, not ours, since our parent is the launcher
428 process. */
429 { Char envvar[100];
430 Char* wd = NULL;
431 VG_(memset)(envvar, 0, sizeof(envvar));
432 VG_(sprintf)(envvar, "VALGRIND_STARTUP_PWD_%d_XYZZY",
433 (Int)VG_(getppid)());
434 wd = VG_(getenv)( envvar );
435 if (wd == NULL || (1+VG_(strlen)(wd) >= szB))
436 return False;
437 VG_(strncpy_safely)(startup_wd, wd, szB);
438 vg_assert(startup_wd[szB-1] == 0);
439 startup_wd_acquired = True;
440 return True;
441 }
442 # else
443 # error Unknown OS
444 # endif
445 }
446
447 /* Copy the previously acquired startup_wd into buf[0 .. size-1],
448 or return False if buf isn't big enough. */
VG_(get_startup_wd)449 Bool VG_(get_startup_wd) ( Char* buf, SizeT size )
450 {
451 vg_assert(startup_wd_acquired);
452 vg_assert(startup_wd[ sizeof(startup_wd)-1 ] == 0);
453 if (1+VG_(strlen)(startup_wd) >= size)
454 return False;
455 VG_(strncpy_safely)(buf, startup_wd, size);
456 return True;
457 }
458
VG_(poll)459 Int VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
460 {
461 SysRes res;
462 # if defined(VGO_linux)
463 res = VG_(do_syscall3)(__NR_poll, (UWord)fds, nfds, timeout);
464 # elif defined(VGO_darwin)
465 res = VG_(do_syscall3)(__NR_poll_nocancel, (UWord)fds, nfds, timeout);
466 # else
467 # error "Unknown OS"
468 # endif
469 return sr_isError(res) ? -1 : sr_Res(res);
470 }
471
472
VG_(readlink)473 Int VG_(readlink) (const Char* path, Char* buf, UInt bufsiz)
474 {
475 SysRes res;
476 /* res = readlink( path, buf, bufsiz ); */
477 res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
478 return sr_isError(res) ? -1 : sr_Res(res);
479 }
480
VG_(getdents)481 Int VG_(getdents) (Int fd, struct vki_dirent *dirp, UInt count)
482 {
483 # if defined(VGO_linux)
484 SysRes res;
485 /* res = getdents( fd, dirp, count ); */
486 res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
487 return sr_isError(res) ? -1 : sr_Res(res);
488 # elif defined(VGO_darwin)
489 I_die_here;
490 # else
491 # error "Unknown OS"
492 # endif
493 }
494
495 /* Check accessibility of a file. Returns zero for access granted,
496 nonzero otherwise. */
VG_(access)497 Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
498 {
499 # if defined(VGO_linux)
500 /* Very annoyingly, I cannot find any definition for R_OK et al in
501 the kernel interfaces. Therefore I reluctantly resort to
502 hardwiring in these magic numbers that I determined by
503 experimentation. */
504 # define VKI_R_OK 4
505 # define VKI_W_OK 2
506 # define VKI_X_OK 1
507 # endif
508
509 UWord w = (irusr ? VKI_R_OK : 0)
510 | (iwusr ? VKI_W_OK : 0)
511 | (ixusr ? VKI_X_OK : 0);
512 SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
513 return sr_isError(res) ? 1 : 0;
514
515 # if defined(VGO_linux)
516 # undef VKI_R_OK
517 # undef VKI_W_OK
518 # undef VKI_X_OK
519 # endif
520 }
521
522 /*
523 Emulate the normal Unix permissions checking algorithm.
524
525 If owner matches, then use the owner permissions, else
526 if group matches, then use the group permissions, else
527 use other permissions.
528
529 Note that we can't deal properly with SUID/SGID. By default
530 (allow_setuid == False), we refuse to run them (otherwise the
531 executable may misbehave if it doesn't have the permissions it
532 thinks it does). However, the caller may indicate that setuid
533 executables are allowed, for example if we are going to exec them
534 but not trace into them (iow, client sys_execve when
535 clo_trace_children == False).
536
537 If VKI_EACCES is returned (iow, permission was refused), then
538 *is_setuid is set to True iff permission was refused because the
539 executable is setuid.
540 */
541 /* returns: 0 = success, non-0 is failure */
VG_(check_executable)542 Int VG_(check_executable)(/*OUT*/Bool* is_setuid,
543 const HChar* f, Bool allow_setuid)
544 {
545 struct vg_stat st;
546 SysRes res = VG_(stat)(f, &st);
547
548 if (is_setuid)
549 *is_setuid = False;
550
551 if (sr_isError(res)) {
552 return sr_Err(res);
553 }
554
555 if ( (st.mode & (VKI_S_ISUID | VKI_S_ISGID)) && !allow_setuid ) {
556 if (is_setuid)
557 *is_setuid = True;
558 return VKI_EACCES;
559 }
560
561 if (VG_(geteuid)() == st.uid) {
562 if (!(st.mode & VKI_S_IXUSR))
563 return VKI_EACCES;
564 } else {
565 Int grpmatch = 0;
566
567 if (VG_(getegid)() == st.gid)
568 grpmatch = 1;
569 else {
570 UInt groups[32];
571 Int ngrp = VG_(getgroups)(32, groups);
572 Int i;
573 /* ngrp will be -1 if VG_(getgroups) failed. */
574 for (i = 0; i < ngrp; i++) {
575 if (groups[i] == st.gid) {
576 grpmatch = 1;
577 break;
578 }
579 }
580 }
581
582 if (grpmatch) {
583 if (!(st.mode & VKI_S_IXGRP)) {
584 return VKI_EACCES;
585 }
586 } else if (!(st.mode & VKI_S_IXOTH)) {
587 return VKI_EACCES;
588 }
589 }
590
591 return 0;
592 }
593
VG_(pread)594 SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
595 {
596 SysRes res;
597 // on 32 bits platforms, we receive a 32 bits OffT but
598 // we must extend it to pass a long long 64 bits.
599 # if defined(VGP_x86_linux)
600 vg_assert(sizeof(OffT) == 4);
601 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
602 offset, 0); // Little endian long long
603 return res;
604 # elif defined(VGP_arm_linux)
605 vg_assert(sizeof(OffT) == 4);
606 res = VG_(do_syscall5)(__NR_pread64, fd, (UWord)buf, count,
607 0, offset); // Big endian long long
608 return res;
609 # elif defined(VGP_ppc32_linux)
610 vg_assert(sizeof(OffT) == 4);
611 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
612 0, // Padding needed on PPC32
613 0, offset); // Big endian long long
614 return res;
615 # elif defined(VGP_mips32_linux) && VKI_LITTLE_ENDIAN
616 vg_assert(sizeof(OffT) == 4);
617 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
618 0, offset, 0);
619 return res;
620 # elif defined(VGP_mips32_linux) && VKI_BIG_ENDIAN
621 vg_assert(sizeof(OffT) == 4);
622 res = VG_(do_syscall6)(__NR_pread64, fd, (UWord)buf, count,
623 0, 0, offset);
624 return res;
625 # elif defined(VGP_amd64_linux) \
626 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
627 res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
628 return res;
629 # elif defined(VGP_amd64_darwin)
630 vg_assert(sizeof(OffT) == 8);
631 res = VG_(do_syscall4)(__NR_pread_nocancel, fd, (UWord)buf, count, offset);
632 return res;
633 # elif defined(VGP_x86_darwin)
634 vg_assert(sizeof(OffT) == 8);
635 res = VG_(do_syscall5)(__NR_pread_nocancel, fd, (UWord)buf, count,
636 offset & 0xffffffff, offset >> 32);
637 return res;
638 # else
639 # error "Unknown platform"
640 # endif
641 }
642
643 /* Return the name of a directory for temporary files. */
VG_(tmpdir)644 const HChar *VG_(tmpdir)(void)
645 {
646 const HChar *tmpdir;
647
648 tmpdir = VG_(getenv)("TMPDIR");
649 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = VG_TMPDIR;
650 if (tmpdir == NULL || *tmpdir == '\0') tmpdir = "/tmp"; /* fallback */
651
652 return tmpdir;
653 }
654
655 /* Create and open (-rw------) a tmp file name incorporating said arg.
656 Returns -1 on failure, else the fd of the file. If fullname is
657 non-NULL, the file's name is written into it. The number of bytes
658 written is guaranteed not to exceed 64+strlen(part_of_name). */
659
VG_(mkstemp)660 Int VG_(mkstemp) ( HChar* part_of_name, /*OUT*/HChar* fullname )
661 {
662 HChar buf[200];
663 Int n, tries, fd;
664 UInt seed;
665 SysRes sres;
666 const HChar *tmpdir;
667
668 vg_assert(part_of_name);
669 n = VG_(strlen)(part_of_name);
670 vg_assert(n > 0 && n < 100);
671
672 seed = (VG_(getpid)() << 9) ^ VG_(getppid)();
673
674 /* Determine sensible location for temporary files */
675 tmpdir = VG_(tmpdir)();
676
677 tries = 0;
678 while (True) {
679 if (tries++ > 10)
680 return -1;
681 VG_(sprintf)( buf, "%s/valgrind_%s_%08x",
682 tmpdir, part_of_name, VG_(random)( &seed ));
683 if (0)
684 VG_(printf)("VG_(mkstemp): trying: %s\n", buf);
685
686 sres = VG_(open)(buf,
687 VKI_O_CREAT|VKI_O_RDWR|VKI_O_EXCL|VKI_O_TRUNC,
688 VKI_S_IRUSR|VKI_S_IWUSR);
689 if (sr_isError(sres)) {
690 VG_(umsg)("VG_(mkstemp): failed to create temp file: %s\n", buf);
691 continue;
692 }
693 /* VG_(safe_fd) doesn't return if it fails. */
694 fd = VG_(safe_fd)( sr_Res(sres) );
695 if (fullname)
696 VG_(strcpy)( fullname, buf );
697 return fd;
698 }
699 /* NOTREACHED */
700 }
701
702
703 /* ---------------------------------------------------------------------
704 Socket-related stuff.
705 ------------------------------------------------------------------ */
706
707 static
708 Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
709
710 static
711 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen );
712
VG_(htonl)713 UInt VG_(htonl) ( UInt x )
714 {
715 # if defined(VG_BIGENDIAN)
716 return x;
717 # else
718 return
719 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
720 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
721 # endif
722 }
723
VG_(ntohl)724 UInt VG_(ntohl) ( UInt x )
725 {
726 # if defined(VG_BIGENDIAN)
727 return x;
728 # else
729 return
730 (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
731 | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
732 # endif
733 }
734
VG_(htons)735 UShort VG_(htons) ( UShort x )
736 {
737 # if defined(VG_BIGENDIAN)
738 return x;
739 # else
740 return
741 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
742 # endif
743 }
744
VG_(ntohs)745 UShort VG_(ntohs) ( UShort x )
746 {
747 # if defined(VG_BIGENDIAN)
748 return x;
749 # else
750 return
751 (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
752 # endif
753 }
754
755
756 /* The main function.
757
758 Supplied string contains either an ip address "192.168.0.1" or
759 an ip address and port pair, "192.168.0.1:1500". Parse these,
760 and return:
761 -1 if there is a parse error
762 -2 if no parse error, but specified host:port cannot be opened
763 the relevant file (socket) descriptor, otherwise.
764 is used.
765 */
VG_(connect_via_socket)766 Int VG_(connect_via_socket)( UChar* str )
767 {
768 # if defined(VGO_linux) || defined(VGO_darwin)
769 Int sd, res;
770 struct vki_sockaddr_in servAddr;
771 UInt ip = 0;
772 UShort port = VG_CLO_DEFAULT_LOGPORT;
773 Bool ok = parse_inet_addr_and_port(str, &ip, &port);
774 if (!ok)
775 return -1;
776
777 //if (0)
778 // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
779 // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
780 // (ip >> 8) & 0xFF, ip & 0xFF,
781 // (UInt)port );
782
783 servAddr.sin_family = VKI_AF_INET;
784 servAddr.sin_addr.s_addr = VG_(htonl)(ip);
785 servAddr.sin_port = VG_(htons)(port);
786
787 /* create socket */
788 sd = VG_(socket)(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
789 if (sd < 0) {
790 /* this shouldn't happen ... nevertheless */
791 return -2;
792 }
793
794 /* connect to server */
795 res = my_connect(sd, &servAddr, sizeof(servAddr));
796 if (res < 0) {
797 /* connection failed */
798 return -2;
799 }
800
801 return sd;
802
803 # else
804 # error "Unknown OS"
805 # endif
806 }
807
808
809 /* Let d = one or more digits. Accept either:
810 d.d.d.d or d.d.d.d:d
811 */
parse_inet_addr_and_port(UChar * str,UInt * ip_addr,UShort * port)812 static Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
813 {
814 # define GET_CH ((*str) ? (*str++) : 0)
815 UInt ipa, i, j, c, any;
816 ipa = 0;
817 for (i = 0; i < 4; i++) {
818 j = 0;
819 any = 0;
820 while (1) {
821 c = GET_CH;
822 if (c < '0' || c > '9') break;
823 j = 10 * j + (int)(c - '0');
824 any = 1;
825 }
826 if (any == 0 || j > 255) goto syntaxerr;
827 ipa = (ipa << 8) + j;
828 if (i <= 2 && c != '.') goto syntaxerr;
829 }
830 if (c == 0 || c == ':')
831 *ip_addr = ipa;
832 if (c == 0) goto ok;
833 if (c != ':') goto syntaxerr;
834 j = 0;
835 any = 0;
836 while (1) {
837 c = GET_CH;
838 if (c < '0' || c > '9') break;
839 j = j * 10 + (int)(c - '0');
840 any = 1;
841 if (j > 65535) goto syntaxerr;
842 }
843 if (any == 0 || c != 0) goto syntaxerr;
844 if (j < 1024) goto syntaxerr;
845 *port = (UShort)j;
846 ok:
847 return 1;
848 syntaxerr:
849 return 0;
850 # undef GET_CH
851 }
852
853 // GrP fixme safe_fd?
VG_(socket)854 Int VG_(socket) ( Int domain, Int type, Int protocol )
855 {
856 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
857 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
858 SysRes res;
859 UWord args[3];
860 args[0] = domain;
861 args[1] = type;
862 args[2] = protocol;
863 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
864 return sr_isError(res) ? -1 : sr_Res(res);
865
866 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
867 || defined(VGP_mips32_linux)
868 SysRes res;
869 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
870 return sr_isError(res) ? -1 : sr_Res(res);
871
872 # elif defined(VGO_darwin)
873 SysRes res;
874 res = VG_(do_syscall3)(__NR_socket, domain, type, protocol);
875 if (!sr_isError(res)) {
876 // Set SO_NOSIGPIPE so write() returns EPIPE instead of raising SIGPIPE
877 Int optval = 1;
878 SysRes res2;
879 res2 = VG_(do_syscall5)(__NR_setsockopt, sr_Res(res), VKI_SOL_SOCKET,
880 VKI_SO_NOSIGPIPE, (UWord)&optval,
881 sizeof(optval));
882 // ignore setsockopt() error
883 }
884 return sr_isError(res) ? -1 : sr_Res(res);
885
886 # else
887 # error "Unknown arch"
888 # endif
889 }
890
891
892 static
my_connect(Int sockfd,struct vki_sockaddr_in * serv_addr,Int addrlen)893 Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
894 {
895 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
896 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
897 SysRes res;
898 UWord args[3];
899 args[0] = sockfd;
900 args[1] = (UWord)serv_addr;
901 args[2] = addrlen;
902 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
903 return sr_isError(res) ? -1 : sr_Res(res);
904
905 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
906 || defined(VGP_mips32_linux)
907 SysRes res;
908 res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
909 return sr_isError(res) ? -1 : sr_Res(res);
910
911 # elif defined(VGO_darwin)
912 SysRes res;
913 res = VG_(do_syscall3)(__NR_connect_nocancel,
914 sockfd, (UWord)serv_addr, addrlen);
915 return sr_isError(res) ? -1 : sr_Res(res);
916
917 # else
918 # error "Unknown arch"
919 # endif
920 }
921
VG_(write_socket)922 Int VG_(write_socket)( Int sd, void *msg, Int count )
923 {
924 /* This is actually send(). */
925
926 /* For Linux, VKI_MSG_NOSIGNAL is a request not to send SIGPIPE on
927 errors on stream oriented sockets when the other end breaks the
928 connection. The EPIPE error is still returned.
929
930 For Darwin, VG_(socket)() sets SO_NOSIGPIPE to get EPIPE instead of
931 SIGPIPE */
932
933 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
934 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
935 SysRes res;
936 UWord args[4];
937 args[0] = sd;
938 args[1] = (UWord)msg;
939 args[2] = count;
940 args[3] = VKI_MSG_NOSIGNAL;
941 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
942 return sr_isError(res) ? -1 : sr_Res(res);
943
944 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
945 || defined(VGP_mips32_linux)
946 SysRes res;
947 res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
948 count, VKI_MSG_NOSIGNAL, 0,0);
949 return sr_isError(res) ? -1 : sr_Res(res);
950
951 # elif defined(VGP_x86_darwin) || defined(VGP_amd64_darwin)
952 SysRes res;
953 res = VG_(do_syscall3)(__NR_write_nocancel, sd, (UWord)msg, count);
954 return sr_isError(res) ? -1 : sr_Res(res);
955
956 # else
957 # error "Unknown platform"
958 # endif
959 }
960
VG_(getsockname)961 Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
962 {
963 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
964 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
965 || defined(VGP_mips32_linux)
966 SysRes res;
967 UWord args[3];
968 args[0] = sd;
969 args[1] = (UWord)name;
970 args[2] = (UWord)namelen;
971 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
972 return sr_isError(res) ? -1 : sr_Res(res);
973
974 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
975 SysRes res;
976 res = VG_(do_syscall3)( __NR_getsockname,
977 (UWord)sd, (UWord)name, (UWord)namelen );
978 return sr_isError(res) ? -1 : sr_Res(res);
979
980 # elif defined(VGO_darwin)
981 SysRes res;
982 res = VG_(do_syscall3)( __NR_getsockname,
983 (UWord)sd, (UWord)name, (UWord)namelen );
984 return sr_isError(res) ? -1 : sr_Res(res);
985
986 # else
987 # error "Unknown platform"
988 # endif
989 }
990
VG_(getpeername)991 Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
992 {
993 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
994 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux) \
995 || defined(VGP_mips32_linux)
996 SysRes res;
997 UWord args[3];
998 args[0] = sd;
999 args[1] = (UWord)name;
1000 args[2] = (UWord)namelen;
1001 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
1002 return sr_isError(res) ? -1 : sr_Res(res);
1003
1004 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux)
1005 SysRes res;
1006 res = VG_(do_syscall3)( __NR_getpeername,
1007 (UWord)sd, (UWord)name, (UWord)namelen );
1008 return sr_isError(res) ? -1 : sr_Res(res);
1009
1010 # elif defined(VGO_darwin)
1011 SysRes res;
1012 res = VG_(do_syscall3)( __NR_getpeername,
1013 (UWord)sd, (UWord)name, (UWord)namelen );
1014 return sr_isError(res) ? -1 : sr_Res(res);
1015
1016 # else
1017 # error "Unknown platform"
1018 # endif
1019 }
1020
VG_(getsockopt)1021 Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
1022 Int *optlen)
1023 {
1024 # if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
1025 || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
1026 SysRes res;
1027 UWord args[5];
1028 args[0] = sd;
1029 args[1] = level;
1030 args[2] = optname;
1031 args[3] = (UWord)optval;
1032 args[4] = (UWord)optlen;
1033 res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
1034 return sr_isError(res) ? -1 : sr_Res(res);
1035
1036 # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
1037 || defined(VGP_mips32_linux)
1038 SysRes res;
1039 res = VG_(do_syscall5)( __NR_getsockopt,
1040 (UWord)sd, (UWord)level, (UWord)optname,
1041 (UWord)optval, (UWord)optlen );
1042 return sr_isError(res) ? -1 : sr_Res(res);
1043
1044 # elif defined(VGO_darwin)
1045 SysRes res;
1046 res = VG_(do_syscall5)( __NR_getsockopt,
1047 (UWord)sd, (UWord)level, (UWord)optname,
1048 (UWord)optval, (UWord)optlen );
1049 return sr_isError(res) ? -1 : sr_Res(res);
1050
1051 # else
1052 # error "Unknown platform"
1053 # endif
1054 }
1055
1056
VG_(basename)1057 Char *VG_(basename)(const Char *path)
1058 {
1059 static Char buf[VKI_PATH_MAX];
1060
1061 const Char *p, *end;
1062
1063 if (path == NULL ||
1064 0 == VG_(strcmp)(path, ""))
1065 {
1066 return ".";
1067 }
1068
1069 p = path + VG_(strlen)(path);
1070 while (p > path && *p == '/') {
1071 // skip all trailing '/'
1072 p--;
1073 }
1074
1075 if (p == path && *p == '/') return "/"; // all slashes
1076
1077 end = p;
1078
1079 while (p > path && *p != '/') {
1080 // now skip non '/'
1081 p--;
1082 }
1083
1084 if (*p == '/') p++;
1085
1086 VG_(strncpy)(buf, p, end-p+1);
1087 buf[end-p+1] = '\0';
1088
1089 return buf;
1090 }
1091
1092
VG_(dirname)1093 Char *VG_(dirname)(const Char *path)
1094 {
1095 static Char buf[VKI_PATH_MAX];
1096
1097 const Char *p;
1098
1099 if (path == NULL ||
1100 0 == VG_(strcmp)(path, "") ||
1101 0 == VG_(strcmp)(path, "/"))
1102 {
1103 return ".";
1104 }
1105
1106 p = path + VG_(strlen)(path);
1107 while (p > path && *p == '/') {
1108 // skip all trailing '/'
1109 p--;
1110 }
1111
1112 while (p > path && *p != '/') {
1113 // now skip non '/'
1114 p--;
1115 }
1116
1117 if (p == path) {
1118 if (*p == '/') return "/"; // all slashes
1119 else return "."; // no slashes
1120 }
1121
1122 while (p > path && *p == '/') {
1123 // skip '/' again
1124 p--;
1125 }
1126
1127 VG_(strncpy)(buf, path, p-path+1);
1128 buf[p-path+1] = '\0';
1129
1130 return buf;
1131 }
1132
1133
1134 /*--------------------------------------------------------------------*/
1135 /*--- end ---*/
1136 /*--------------------------------------------------------------------*/
1137