From: Petar Jovanovic Date: Fri, 29 Jan 2016 17:47:43 +0000 (+0000) Subject: mips64: use getdents() if getdents64() is not available X-Git-Tag: svn/VALGRIND_3_12_0~245 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=525050c47aeff06cf896fe9c6c2383fa59d42175;p=thirdparty%2Fvalgrind.git mips64: use getdents() if getdents64() is not available The MIPS64 getdents64() system call is only present in 3.10+ kernels. If the getdents64() system call is not available fall back to using getdents() and modify the result to be compatible with getdents64(). This matters only when --track-fds=yes is set. This change fixes none/tests/fdleak* failures on MIPS64 platforms with kernel versions older than 3.10. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15778 --- diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index 68fc434385..7e94ce36c9 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -667,6 +667,38 @@ Int VG_(getdents64) (Int fd, struct vki_dirent64 *dirp, UInt count) res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); # else res = VG_(do_syscall3)(__NR_getdents64, fd, (UWord)dirp, count); +# if defined(VGA_mips64) + /* The MIPS64 getdents64() system call is only present in 3.10+ kernels. + If the getdents64() system call is not available fall back to using + getdents() and modify the result to be compatible with getdents64(). */ + if (sr_isError(res) && (sr_Err(res) == VKI_ENOSYS)) { + int r; + res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count); + r = sr_Res(res); + if (r > 0) { + char *p; + char type; + union dirents { + struct vki_dirent m; + struct vki_dirent64 d; + } *u; + p = (char *)dirp; + do { + u = (union dirents *)p; + /* This should not happen, but just in case... */ + if (p + u->m.d_reclen > (char *)dirp + r) + break; + /* shuffle the dirent */ + type = *(p + u->m.d_reclen - 1); + VG_(memmove)(u->d.d_name, u->m.d_name, + u->m.d_reclen - 2 + - offsetof(struct vki_dirent, d_name) + 1); + u->d.d_type = type; + p += u->m.d_reclen; + } while (p < (char *)dirp + r); + } + } +# endif # endif return sr_isError(res) ? -1 : sr_Res(res); }