Modularised file and socket libc stuff in m_libcfile.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3844 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 1068b7d..7e11f44 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -48,6 +48,7 @@
pub_core_hashtable.h \
pub_core_libcbase.h \
pub_core_libcassert.h \
+ pub_core_libcfile.h \
pub_core_libcprint.h \
pub_core_main.h \
pub_core_mallocfree.h \
@@ -92,6 +93,7 @@
m_hashtable.c \
m_libcbase.c \
m_libcassert.c \
+ m_libcfile.c \
m_libcprint.c \
m_main.c \
m_mallocfree.c \
diff --git a/coregrind/core.h b/coregrind/core.h
index 97ccf8b..a371342 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -112,14 +112,6 @@
extern Int VG_(mprotect_native)( void *start, SizeT length, UInt prot );
-/* Move an fd into the Valgrind-safe range */
-Int VG_(safe_fd)(Int oldfd);
-
-extern Int VG_(write_socket)( Int sd, void *msg, Int count );
-
-/* --- Connecting over the network --- */
-extern Int VG_(connect_via_socket)( UChar* str );
-
/* Environment manipulations */
extern Char **VG_(env_setenv) ( Char ***envp, const Char* varname,
const Char *val );
diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c
index ab18b87..a33032e 100644
--- a/coregrind/m_aspacemgr/aspacemgr.c
+++ b/coregrind/m_aspacemgr/aspacemgr.c
@@ -34,6 +34,7 @@
#include "pub_core_aspacemgr.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h" // For VG_(fstat)()
#include "pub_core_libcprint.h"
#include "pub_core_options.h"
#include "pub_core_syscalls.h"
diff --git a/coregrind/m_aspacemgr/read_procselfmaps.c b/coregrind/m_aspacemgr/read_procselfmaps.c
index 1797171..0e6381d 100644
--- a/coregrind/m_aspacemgr/read_procselfmaps.c
+++ b/coregrind/m_aspacemgr/read_procselfmaps.c
@@ -34,6 +34,7 @@
#include "pub_core_aspacemgr.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
/* Size of a smallish table used to read /proc/self/map entries. */
diff --git a/coregrind/m_debuginfo/symtab.c b/coregrind/m_debuginfo/symtab.c
index 43f0f4c..c0787ae 100644
--- a/coregrind/m_debuginfo/symtab.c
+++ b/coregrind/m_debuginfo/symtab.c
@@ -34,6 +34,7 @@
#include "pub_core_demangle.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_options.h"
#include "pub_core_profile.h"
diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index 71ae7ce..9f14f23 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -34,6 +34,7 @@
#include "pub_core_execontext.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_main.h" // for VG_(start_debugger)()
#include "pub_core_options.h"
@@ -1107,5 +1108,5 @@
}
/*--------------------------------------------------------------------*/
-/*--- end m_errormgr.c ---*/
+/*--- end ---*/
/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
new file mode 100644
index 0000000..974dcdb
--- /dev/null
+++ b/coregrind/m_libcfile.c
@@ -0,0 +1,446 @@
+
+/*--------------------------------------------------------------------*/
+/*--- File- and socket-related libc stuff. m_libcfile.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "core.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
+#include "pub_core_options.h"
+#include "pub_core_syscalls.h" // For VG_(is_kerror)()
+#include "vki_unistd.h"
+
+/* ---------------------------------------------------------------------
+ File stuff
+ ------------------------------------------------------------------ */
+
+static inline Bool fd_exists(Int fd)
+{
+ struct vki_stat st;
+
+ return VG_(fstat)(fd, &st) == 0;
+}
+
+/* Move an fd into the Valgrind-safe range */
+Int VG_(safe_fd)(Int oldfd)
+{
+ Int newfd;
+
+ vg_assert(VG_(fd_hard_limit) != -1);
+
+ newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
+ if (newfd != -1)
+ VG_(close)(oldfd);
+
+ VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
+
+ vg_assert(newfd >= VG_(fd_hard_limit));
+ return newfd;
+}
+
+/* Returns -1 on failure. */
+Int VG_(open) ( const Char* pathname, Int flags, Int mode )
+{
+ Int fd = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
+ return fd;
+}
+
+void VG_(close) ( Int fd )
+{
+ VG_(do_syscall1)(__NR_close, fd);
+}
+
+Int VG_(read) ( Int fd, void* buf, Int count)
+{
+ Int res;
+ res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
+ return res;
+}
+
+Int VG_(write) ( Int fd, const void* buf, Int count)
+{
+ Int res;
+ res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
+ return res;
+}
+
+Int VG_(pipe) ( Int fd[2] )
+{
+ Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
+ return VG_(is_kerror)(ret) ? -1 : 0;
+}
+
+OffT VG_(lseek) ( Int fd, OffT offset, Int whence)
+{
+ Int res;
+ res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
+ if (VG_(is_kerror)(res)) res = -1;
+ return res;
+}
+
+Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
+{
+ Int res;
+ res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
+ return res; /* return -ve error */
+}
+
+Int VG_(fstat) ( Int fd, struct vki_stat* buf )
+{
+ Int res;
+ res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
+ return VG_(is_kerror)(res) ? (-1) : 0;
+}
+
+Int VG_(dup2) ( Int oldfd, Int newfd )
+{
+ Int res;
+ res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
+ return VG_(is_kerror)(res) ? (-1) : res;
+}
+
+Int VG_(rename) ( Char* old_name, Char* new_name )
+{
+ Int res;
+ res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
+ return VG_(is_kerror)(res) ? (-1) : 0;
+}
+
+Int VG_(unlink) ( Char* file_name )
+{
+ Int res;
+ res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
+ return VG_(is_kerror)(res) ? (-1) : 0;
+}
+
+/* Nb: we do not allow the Linux extension which malloc()s memory for the
+ buffer if buf==NULL, because we don't want Linux calling malloc() */
+Char* VG_(getcwd) ( Char* buf, SizeT size )
+{
+ Word res;
+ vg_assert(buf != NULL);
+ res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
+ return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
+}
+
+/* Alternative version that does allocate the memory. Easier to use. */
+Bool VG_(getcwd_alloc) ( Char** out )
+{
+ SizeT size = 4;
+
+ *out = NULL;
+ while (True) {
+ *out = VG_(malloc)(size);
+ if (NULL == VG_(getcwd)(*out, size)) {
+ VG_(free)(*out);
+ if (size > 65535)
+ return False;
+ size *= 2;
+ } else {
+ return True;
+ }
+ }
+}
+
+Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
+{
+ Int res;
+ /* res = readlink( path, buf, bufsiz ); */
+ res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
+ if (VG_(is_kerror)(res)) res = -1;
+ return res;
+}
+
+Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
+{
+ Int res;
+ /* res = getdents( fd, dirp, count ); */
+ res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
+ if (VG_(is_kerror)(res)) res = -1;
+ return res;
+}
+
+/* ---------------------------------------------------------------------
+ Socket-related stuff. This is very Linux-kernel specific.
+ ------------------------------------------------------------------ */
+
+static
+Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
+
+static
+Int my_socket ( Int domain, Int type, Int protocol );
+
+static
+Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
+ Int addrlen );
+
+static
+UInt my_htonl ( UInt x )
+{
+ return
+ (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
+ | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
+}
+
+static
+UShort my_htons ( UShort x )
+{
+ return
+ (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
+}
+
+
+/* The main function.
+
+ Supplied string contains either an ip address "192.168.0.1" or
+ an ip address and port pair, "192.168.0.1:1500". Parse these,
+ and return:
+ -1 if there is a parse error
+ -2 if no parse error, but specified host:port cannot be opened
+ the relevant file (socket) descriptor, otherwise.
+ is used.
+*/
+Int VG_(connect_via_socket)( UChar* str )
+{
+ Int sd, res;
+ struct vki_sockaddr_in servAddr;
+ UInt ip = 0;
+ UShort port = VG_CLO_DEFAULT_LOGPORT;
+ Bool ok = parse_inet_addr_and_port(str, &ip, &port);
+ if (!ok)
+ return -1;
+
+ //if (0)
+ // VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
+ // (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
+ // (ip >> 8) & 0xFF, ip & 0xFF,
+ // (UInt)port );
+
+ servAddr.sin_family = VKI_AF_INET;
+ servAddr.sin_addr.s_addr = my_htonl(ip);
+ servAddr.sin_port = my_htons(port);
+
+ /* create socket */
+ sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
+ if (sd < 0) {
+ /* this shouldn't happen ... nevertheless */
+ return -2;
+ }
+
+ /* connect to server */
+ res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
+ sizeof(servAddr));
+ if (res < 0) {
+ /* connection failed */
+ return -2;
+ }
+
+ return sd;
+}
+
+
+/* Let d = one or more digits. Accept either:
+ d.d.d.d or d.d.d.d:d
+*/
+Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
+{
+# define GET_CH ((*str) ? (*str++) : 0)
+ UInt ipa, i, j, c, any;
+ ipa = 0;
+ for (i = 0; i < 4; i++) {
+ j = 0;
+ any = 0;
+ while (1) {
+ c = GET_CH;
+ if (c < '0' || c > '9') break;
+ j = 10 * j + (int)(c - '0');
+ any = 1;
+ }
+ if (any == 0 || j > 255) goto syntaxerr;
+ ipa = (ipa << 8) + j;
+ if (i <= 2 && c != '.') goto syntaxerr;
+ }
+ if (c == 0 || c == ':')
+ *ip_addr = ipa;
+ if (c == 0) goto ok;
+ if (c != ':') goto syntaxerr;
+ j = 0;
+ any = 0;
+ while (1) {
+ c = GET_CH;
+ if (c < '0' || c > '9') break;
+ j = j * 10 + (int)(c - '0');
+ any = 1;
+ if (j > 65535) goto syntaxerr;
+ }
+ if (any == 0 || c != 0) goto syntaxerr;
+ if (j < 1024) goto syntaxerr;
+ *port = (UShort)j;
+ ok:
+ return 1;
+ syntaxerr:
+ return 0;
+# undef GET_CH
+}
+
+
+static
+Int my_socket ( Int domain, Int type, Int protocol )
+{
+// AMD64/Linux doesn't define __NR_socketcall... see comment above
+// VG_(sigpending)() for more details.
+#ifdef __amd64__
+ I_die_here;
+#else
+ Int res;
+ UWord args[3];
+ args[0] = domain;
+ args[1] = type;
+ args[2] = protocol;
+ res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
+ if (VG_(is_kerror)(res))
+ res = -1;
+ return res;
+#endif
+}
+
+static
+Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
+ Int addrlen )
+{
+// AMD64/Linux doesn't define __NR_socketcall... see comment above
+// VG_(sigpending)() for more details.
+#ifdef __amd64__
+ I_die_here;
+#else
+ Int res;
+ UWord args[3];
+ args[0] = sockfd;
+ args[1] = (UWord)serv_addr;
+ args[2] = addrlen;
+ res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
+ if (VG_(is_kerror)(res))
+ res = -1;
+ return res;
+#endif
+}
+
+Int VG_(write_socket)( Int sd, void *msg, Int count )
+{
+// AMD64/Linux doesn't define __NR_socketcall... see comment above
+// VG_(sigpending)() for more details.
+#ifdef __amd64__
+ I_die_here;
+#else
+ /* This is actually send(). */
+
+ /* Requests not to send SIGPIPE on errors on stream oriented
+ sockets when the other end breaks the connection. The EPIPE
+ error is still returned. */
+ Int flags = VKI_MSG_NOSIGNAL;
+
+ Int res;
+ UWord args[4];
+ args[0] = sd;
+ args[1] = (UWord)msg;
+ args[2] = count;
+ args[3] = flags;
+ res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
+ if (VG_(is_kerror)(res))
+ res = -1;
+ return res;
+#endif
+}
+
+Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
+{
+// AMD64/Linux doesn't define __NR_socketcall... see comment above
+// VG_(sigpending)() for more details.
+#ifdef __amd64__
+ I_die_here;
+#else
+ Int res;
+ UWord args[3];
+ args[0] = sd;
+ args[1] = (UWord)name;
+ args[2] = (UWord)namelen;
+ res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
+ if(VG_(is_kerror)(res))
+ res = -1;
+ return res;
+#endif
+}
+
+Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
+{
+// AMD64/Linux doesn't define __NR_socketcall... see comment above
+// VG_(sigpending)() for more details.
+#ifdef __amd64__
+ I_die_here;
+#else
+ Int res;
+ UWord args[3];
+ args[0] = sd;
+ args[1] = (UWord)name;
+ args[2] = (UWord)namelen;
+ res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
+ if(VG_(is_kerror)(res))
+ res = -1;
+ return res;
+#endif
+}
+
+Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
+ Int *optlen)
+{
+// AMD64/Linux doesn't define __NR_socketcall... see comment above
+// VG_(sigpending)() for more details.
+#ifdef __amd64__
+ I_die_here;
+#else
+ Int res;
+ UWord args[5];
+ args[0] = sd;
+ args[1] = level;
+ args[2] = optname;
+ args[3] = (UWord)optval;
+ args[4] = (UWord)optlen;
+ res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
+ if(VG_(is_kerror)(res))
+ res = -1;
+ return res;
+#endif
+}
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
+
diff --git a/coregrind/m_libcprint.c b/coregrind/m_libcprint.c
index f782c48..f4ca698 100644
--- a/coregrind/m_libcprint.c
+++ b/coregrind/m_libcprint.c
@@ -32,6 +32,7 @@
#include "pub_core_debuglog.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_options.h"
#include "valgrind.h" // for RUNNING_ON_VALGRIND
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index 7a2e424..7c1d0c7 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -38,6 +38,7 @@
#include "pub_core_execontext.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_main.h"
#include "pub_core_options.h"
diff --git a/coregrind/m_scheduler/sema.c b/coregrind/m_scheduler/sema.c
index 5db9e58..dd1ba1b 100644
--- a/coregrind/m_scheduler/sema.c
+++ b/coregrind/m_scheduler/sema.c
@@ -30,6 +30,7 @@
#include "core.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "priv_sema.h"
/*
diff --git a/coregrind/m_syscalls/syscalls-linux.c b/coregrind/m_syscalls/syscalls-linux.c
index 00f5238..2d801a1 100644
--- a/coregrind/m_syscalls/syscalls-linux.c
+++ b/coregrind/m_syscalls/syscalls-linux.c
@@ -31,6 +31,7 @@
#include "core.h"
#include "pub_core_aspacemgr.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_tooliface.h"
#include "priv_syscalls.h"
diff --git a/coregrind/m_syscalls/syscalls.c b/coregrind/m_syscalls/syscalls.c
index 0a7cbee..faa6514 100644
--- a/coregrind/m_syscalls/syscalls.c
+++ b/coregrind/m_syscalls/syscalls.c
@@ -33,6 +33,7 @@
#include "pub_core_aspacemgr.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcassert.h"
+#include "pub_core_libcfile.h"
#include "pub_core_libcprint.h"
#include "pub_core_main.h"
#include "pub_core_profile.h"
diff --git a/coregrind/pub_core_libcfile.h b/coregrind/pub_core_libcfile.h
new file mode 100644
index 0000000..59386ad
--- /dev/null
+++ b/coregrind/pub_core_libcfile.h
@@ -0,0 +1,55 @@
+
+/*--------------------------------------------------------------------*/
+/*--- File/socket-related libc stuff. pub_core_libcfile.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_LIBCFILE_H
+#define __PUB_CORE_LIBCFILE_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module contains all the libc code that relates to
+// files and sockets: opening, reading, writing, etc.
+//--------------------------------------------------------------------
+
+#include "pub_tool_libcfile.h"
+
+/* Move an fd into the Valgrind-safe range */
+extern Int VG_(safe_fd)(Int oldfd);
+
+extern Int VG_(write_socket)( Int sd, void *msg, Int count );
+extern Int VG_(connect_via_socket)( UChar* str );
+extern Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen );
+extern Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen );
+extern Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
+ Int *optlen );
+
+#endif // __PUB_CORE_LIBCFILE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c
index bc00797..03effb9 100644
--- a/coregrind/vg_mylibc.c
+++ b/coregrind/vg_mylibc.c
@@ -439,142 +439,6 @@
}
/* ---------------------------------------------------------------------
- Primitive support for reading files.
- ------------------------------------------------------------------ */
-
-static inline Bool fd_exists(Int fd)
-{
- struct vki_stat st;
-
- return VG_(fstat)(fd, &st) == 0;
-}
-
-/* Move an fd into the Valgrind-safe range */
-Int VG_(safe_fd)(Int oldfd)
-{
- Int newfd;
-
- vg_assert(VG_(fd_hard_limit) != -1);
-
- newfd = VG_(fcntl)(oldfd, VKI_F_DUPFD, VG_(fd_hard_limit));
- if (newfd != -1)
- VG_(close)(oldfd);
-
- VG_(fcntl)(newfd, VKI_F_SETFD, VKI_FD_CLOEXEC);
-
- vg_assert(newfd >= VG_(fd_hard_limit));
- return newfd;
-}
-
-
-
-/* Returns -1 on failure. */
-Int VG_(open) ( const Char* pathname, Int flags, Int mode )
-{
- Int fd = VG_(do_syscall3)(__NR_open, (UWord)pathname, flags, mode);
- return fd;
-}
-
-Int VG_(pipe) ( Int fd[2] )
-{
- Int ret = VG_(do_syscall1)(__NR_pipe, (UWord)fd);
- return VG_(is_kerror)(ret) ? -1 : 0;
-}
-
-void VG_(close) ( Int fd )
-{
- VG_(do_syscall1)(__NR_close, fd);
-}
-
-
-Int VG_(read) ( Int fd, void* buf, Int count)
-{
- Int res;
- res = VG_(do_syscall3)(__NR_read, fd, (UWord)buf, count);
- return res;
-}
-
-Int VG_(write) ( Int fd, const void* buf, Int count)
-{
- Int res;
- res = VG_(do_syscall3)(__NR_write, fd, (UWord)buf, count);
- return res;
-}
-
-OffT VG_(lseek) ( Int fd, OffT offset, Int whence)
-{
- Int res;
- res = VG_(do_syscall3)(__NR_lseek, fd, offset, whence);
- if (VG_(is_kerror)(res)) res = -1;
- return res;
-}
-
-Int VG_(stat) ( Char* file_name, struct vki_stat* buf )
-{
- Int res;
- res = VG_(do_syscall2)(__NR_stat, (UWord)file_name, (UWord)buf);
- return res; /* return -ve error */
-}
-
-Int VG_(fstat) ( Int fd, struct vki_stat* buf )
-{
- Int res;
- res = VG_(do_syscall2)(__NR_fstat, fd, (UWord)buf);
- return VG_(is_kerror)(res) ? (-1) : 0;
-}
-
-Int VG_(dup2) ( Int oldfd, Int newfd )
-{
- Int res;
- res = VG_(do_syscall2)(__NR_dup2, oldfd, newfd);
- return VG_(is_kerror)(res) ? (-1) : res;
-}
-
-Int VG_(rename) ( Char* old_name, Char* new_name )
-{
- Int res;
- res = VG_(do_syscall2)(__NR_rename, (UWord)old_name, (UWord)new_name);
- return VG_(is_kerror)(res) ? (-1) : 0;
-}
-
-Int VG_(unlink) ( Char* file_name )
-{
- Int res;
- res = VG_(do_syscall1)(__NR_unlink, (UWord)file_name);
- return VG_(is_kerror)(res) ? (-1) : 0;
-}
-
-/* Nb: we do not allow the Linux extension which malloc()s memory for the
- buffer if buf==NULL, because we don't want Linux calling malloc() */
-Char* VG_(getcwd) ( Char* buf, SizeT size )
-{
- Word res;
- vg_assert(buf != NULL);
- res = VG_(do_syscall2)(__NR_getcwd, (UWord)buf, size);
- return VG_(is_kerror)(res) ? ((Char*)NULL) : (Char*)res;
-}
-
-/* Alternative version that does allocate the memory. Easier to use. */
-Bool VG_(getcwd_alloc) ( Char** out )
-{
- SizeT size = 4;
-
- *out = NULL;
- while (True) {
- *out = VG_(malloc)(size);
- if (NULL == VG_(getcwd)(*out, size)) {
- VG_(free)(*out);
- if (size > 65535)
- return False;
- size *= 2;
- } else {
- return True;
- }
- }
-}
-
-
-/* ---------------------------------------------------------------------
Misc functions looking for a proper home.
------------------------------------------------------------------ */
@@ -702,26 +566,6 @@
}
-/* Support for getdents. */
-Int VG_(getdents) (UInt fd, struct vki_dirent *dirp, UInt count)
-{
- Int res;
- /* res = getdents( fd, dirp, count ); */
- res = VG_(do_syscall3)(__NR_getdents, fd, (UWord)dirp, count);
- if (VG_(is_kerror)(res)) res = -1;
- return res;
-}
-
-/* Support for a readlink. */
-Int VG_(readlink) (Char* path, Char* buf, UInt bufsiz)
-{
- Int res;
- /* res = readlink( path, buf, bufsiz ); */
- res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
- if (VG_(is_kerror)(res)) res = -1;
- return res;
-}
-
/* You'd be amazed how many places need to know the current pid. */
Int VG_(getpid) ( void )
{
@@ -951,259 +795,6 @@
VG_(exit)(1);
}
-/* ---------------------------------------------------------------------
- Gruesome hackery for connecting to a logging server over the network.
- This is all very Linux-kernel specific.
- ------------------------------------------------------------------ */
-
-static
-Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port );
-
-static
-Int my_socket ( Int domain, Int type, Int protocol );
-
-static
-Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
- Int addrlen );
-
-static
-UInt my_htonl ( UInt x )
-{
- return
- (((x >> 24) & 0xFF) << 0) | (((x >> 16) & 0xFF) << 8)
- | (((x >> 8) & 0xFF) << 16) | (((x >> 0) & 0xFF) << 24);
-}
-
-static
-UShort my_htons ( UShort x )
-{
- return
- (((x >> 8) & 0xFF) << 0) | (((x >> 0) & 0xFF) << 8);
-}
-
-
-/* The main function.
-
- Supplied string contains either an ip address "192.168.0.1" or
- an ip address and port pair, "192.168.0.1:1500". Parse these,
- and return:
- -1 if there is a parse error
- -2 if no parse error, but specified host:port cannot be opened
- the relevant file (socket) descriptor, otherwise.
- is used.
-*/
-Int VG_(connect_via_socket)( UChar* str )
-{
- Int sd, res;
- struct vki_sockaddr_in servAddr;
- UInt ip = 0;
- UShort port = VG_CLO_DEFAULT_LOGPORT;
- Bool ok = parse_inet_addr_and_port(str, &ip, &port);
- if (!ok)
- return -1;
-
- if (0)
- VG_(printf)("ip = %d.%d.%d.%d, port %d\n",
- (ip >> 24) & 0xFF, (ip >> 16) & 0xFF,
- (ip >> 8) & 0xFF, ip & 0xFF,
- (UInt)port );
-
- servAddr.sin_family = VKI_AF_INET;
- servAddr.sin_addr.s_addr = my_htonl(ip);
- servAddr.sin_port = my_htons(port);
-
- /* create socket */
- sd = my_socket(VKI_AF_INET, VKI_SOCK_STREAM, 0 /* IPPROTO_IP ? */);
- if (sd < 0) {
- /* this shouldn't happen ... nevertheless */
- return -2;
- }
-
- /* connect to server */
- res = my_connect(sd, (struct vki_sockaddr_in *) &servAddr,
- sizeof(servAddr));
- if (res < 0) {
- /* connection failed */
- return -2;
- }
-
- return sd;
-}
-
-
-/* Let d = one or more digits. Accept either:
- d.d.d.d or d.d.d.d:d
-*/
-Int parse_inet_addr_and_port ( UChar* str, UInt* ip_addr, UShort* port )
-{
-# define GET_CH ((*str) ? (*str++) : 0)
- UInt ipa, i, j, c, any;
- ipa = 0;
- for (i = 0; i < 4; i++) {
- j = 0;
- any = 0;
- while (1) {
- c = GET_CH;
- if (c < '0' || c > '9') break;
- j = 10 * j + (int)(c - '0');
- any = 1;
- }
- if (any == 0 || j > 255) goto syntaxerr;
- ipa = (ipa << 8) + j;
- if (i <= 2 && c != '.') goto syntaxerr;
- }
- if (c == 0 || c == ':')
- *ip_addr = ipa;
- if (c == 0) goto ok;
- if (c != ':') goto syntaxerr;
- j = 0;
- any = 0;
- while (1) {
- c = GET_CH;
- if (c < '0' || c > '9') break;
- j = j * 10 + (int)(c - '0');
- any = 1;
- if (j > 65535) goto syntaxerr;
- }
- if (any == 0 || c != 0) goto syntaxerr;
- if (j < 1024) goto syntaxerr;
- *port = (UShort)j;
- ok:
- return 1;
- syntaxerr:
- return 0;
-# undef GET_CH
-}
-
-
-static
-Int my_socket ( Int domain, Int type, Int protocol )
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
- I_die_here;
-#else
- Int res;
- UWord args[3];
- args[0] = domain;
- args[1] = type;
- args[2] = protocol;
- res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SOCKET, (UWord)&args);
- if (VG_(is_kerror)(res))
- res = -1;
- return res;
-#endif
-}
-
-static
-Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr,
- Int addrlen )
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
- I_die_here;
-#else
- Int res;
- UWord args[3];
- args[0] = sockfd;
- args[1] = (UWord)serv_addr;
- args[2] = addrlen;
- res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_CONNECT, (UWord)&args);
- if (VG_(is_kerror)(res))
- res = -1;
- return res;
-#endif
-}
-
-Int VG_(write_socket)( Int sd, void *msg, Int count )
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
- I_die_here;
-#else
- /* This is actually send(). */
-
- /* Requests not to send SIGPIPE on errors on stream oriented
- sockets when the other end breaks the connection. The EPIPE
- error is still returned. */
- Int flags = VKI_MSG_NOSIGNAL;
-
- Int res;
- UWord args[4];
- args[0] = sd;
- args[1] = (UWord)msg;
- args[2] = count;
- args[3] = flags;
- res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_SEND, (UWord)&args);
- if (VG_(is_kerror)(res))
- res = -1;
- return res;
-#endif
-}
-
-Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
- I_die_here;
-#else
- Int res;
- UWord args[3];
- args[0] = sd;
- args[1] = (UWord)name;
- args[2] = (UWord)namelen;
- res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKNAME, (UWord)&args);
- if(VG_(is_kerror)(res))
- res = -1;
- return res;
-#endif
-}
-
-Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
- I_die_here;
-#else
- Int res;
- UWord args[3];
- args[0] = sd;
- args[1] = (UWord)name;
- args[2] = (UWord)namelen;
- res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETPEERNAME, (UWord)&args);
- if(VG_(is_kerror)(res))
- res = -1;
- return res;
-#endif
-}
-
-Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
- Int *optlen)
-{
-// AMD64/Linux doesn't define __NR_socketcall... see comment above
-// VG_(sigpending)() for more details.
-#ifdef __amd64__
- I_die_here;
-#else
- Int res;
- UWord args[5];
- args[0] = sd;
- args[1] = level;
- args[2] = optname;
- args[3] = (UWord)optval;
- args[4] = (UWord)optlen;
- res = VG_(do_syscall2)(__NR_socketcall, VKI_SYS_GETSOCKOPT, (UWord)&args);
- if(VG_(is_kerror)(res))
- res = -1;
- return res;
-#endif
-}
-
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/