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/cachegrind/cg_main.c b/cachegrind/cg_main.c
index a7bfd6b..5c7fd8b 100644
--- a/cachegrind/cg_main.c
+++ b/cachegrind/cg_main.c
@@ -34,6 +34,7 @@
 #include "pub_tool_hashtable.h"
 #include "pub_tool_libcbase.h"
 #include "pub_tool_libcassert.h"
+#include "pub_tool_libcfile.h"
 #include "pub_tool_libcprint.h"
 #include "pub_tool_mallocfree.h"
 #include "pub_tool_options.h"
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                                                          ---*/
 /*--------------------------------------------------------------------*/
diff --git a/include/Makefile.am b/include/Makefile.am
index b087a30..a38b33d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -10,6 +10,7 @@
 	pub_tool_hashtable.h 		\
 	pub_tool_libcbase.h 		\
 	pub_tool_libcassert.h 		\
+	pub_tool_libcfile.h 		\
 	pub_tool_libcprint.h 		\
 	pub_tool_mallocfree.h 		\
 	pub_tool_options.h 		\
diff --git a/include/pub_tool_libcfile.h b/include/pub_tool_libcfile.h
new file mode 100644
index 0000000..0a1b01c
--- /dev/null
+++ b/include/pub_tool_libcfile.h
@@ -0,0 +1,65 @@
+
+/*--------------------------------------------------------------------*/
+/*--- File/socket-related libc stuff.          pub_tool_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_TOOL_LIBCFILE_H
+#define __PUB_TOOL_LIBCFILE_H
+
+/* ---------------------------------------------------------------------
+   File-related functions.
+   ------------------------------------------------------------------ */
+
+extern Int  VG_(open)   ( const Char* pathname, Int flags, Int mode );
+extern void VG_(close)  ( Int fd );
+extern Int  VG_(read)   ( Int fd, void* buf, Int count);
+extern Int  VG_(write)  ( Int fd, const void* buf, Int count);
+extern Int  VG_(pipe)   ( Int fd[2] );
+extern OffT VG_(lseek)  ( Int fd, OffT offset, Int whence);
+
+extern Int  VG_(stat)   ( Char* file_name, struct vki_stat* buf );
+extern Int  VG_(fstat)  ( Int   fd,        struct vki_stat* buf );
+extern Int  VG_(dup2)   ( Int oldfd, Int newfd );
+extern Int  VG_(rename) ( Char* old_name, Char* new_name );
+extern Int  VG_(unlink) ( Char* file_name );
+
+extern Char* VG_(getcwd) ( Char* buf, SizeT size );
+
+/* Easier to use than VG_(getcwd)() -- does the buffer fiddling itself.
+   String put into 'cwd' is VG_(malloc)'d, and should be VG_(free)'d.
+   Returns False if it fails.  Will fail if the pathname is > 65535 bytes. */
+extern Bool VG_(getcwd_alloc) ( Char** cwd );
+
+extern Int  VG_(readlink)( Char* path, Char* buf, UInt bufsize );
+extern Int  VG_(getdents)( UInt fd, struct vki_dirent *dirp, UInt count );
+
+#endif   // __PUB_TOOL_LIBCFILE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/tool.h b/include/tool.h
index 795a129..ecaf3ba 100644
--- a/include/tool.h
+++ b/include/tool.h
@@ -112,11 +112,6 @@
 #endif
 
 /* ------------------------------------------------------------------ */
-/* stdio.h */
-
-extern Int  VG_(rename) ( Char* old_name, Char* new_name );
-
-/* ------------------------------------------------------------------ */
 /* stdlib.h */
 
 /* terminate everything */
@@ -142,35 +137,12 @@
 
 /* ------------------------------------------------------------------ */
 /* unistd.h, fcntl.h, sys/stat.h */
-extern Int  VG_(getdents)( UInt fd, struct vki_dirent *dirp, UInt count );
-extern Int  VG_(readlink)( Char* path, Char* buf, UInt bufsize );
 extern Int  VG_(getpid)  ( void );
 extern Int  VG_(getppid) ( void );
 extern Int  VG_(getpgrp) ( void );
 extern Int  VG_(gettid)	 ( void );
 extern Int  VG_(setpgid) ( Int pid, Int pgrp );
 
-extern Int  VG_(open)   ( const Char* pathname, Int flags, Int mode );
-extern Int  VG_(read)   ( Int fd, void* buf, Int count);
-extern Int  VG_(write)  ( Int fd, const void* buf, Int count);
-extern OffT VG_(lseek)  ( Int fd, OffT offset, Int whence);
-extern void VG_(close)  ( Int fd );
-
-extern Int  VG_(pipe)   ( Int fd[2] );
-
-/* Nb: VG_(rename)() declared in stdio.h section above */
-extern Int  VG_(unlink) ( Char* file_name );
-extern Int  VG_(stat)   ( Char* file_name, struct vki_stat* buf );
-extern Int  VG_(fstat)  ( Int   fd,        struct vki_stat* buf );
-extern Int  VG_(dup2)   ( Int oldfd, Int newfd );
-
-extern Char* VG_(getcwd) ( Char* buf, SizeT size );
-
-/* Easier to use than VG_(getcwd)() -- does the buffer fiddling itself.
-   String put into 'cwd' is VG_(malloc)'d, and should be VG_(free)'d.
-   Returns False if it fails.  Will fail if the pathname is > 65535 bytes. */
-extern Bool VG_(getcwd_alloc) ( Char** cwd );
-
 /* ------------------------------------------------------------------ */
 /* Get memory by anonymous mmap. */
 extern void* VG_(get_memory_from_mmap) ( SizeT nBytes, Char* who );
@@ -248,14 +220,6 @@
 extern Int VG_(waitpid)	    ( Int pid, Int *status, Int options );
 
 /* ------------------------------------------------------------------ */
-/* socket.h. */
-
-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);
-
-/* ------------------------------------------------------------------ */
 /* other, randomly useful functions */
 extern UInt VG_(read_millisecond_timer) ( void );
 
diff --git a/massif/ms_main.c b/massif/ms_main.c
index aebc27d..0e37aa7 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -39,6 +39,7 @@
 #include "pub_tool_hashtable.h"
 #include "pub_tool_libcbase.h"
 #include "pub_tool_libcassert.h"
+#include "pub_tool_libcfile.h"
 #include "pub_tool_libcprint.h"
 #include "pub_tool_mallocfree.h"
 #include "pub_tool_options.h"