This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA]: File-I/O patch


On Fri, Mar 07, 2003 at 02:30:56PM -0500, Andrew Cagney wrote:
> I think the basic file io implementation should be moved out of 
> "remote.c" and into "fileio.[hc]" so that both remote.c and remote-sim.c 
> can share it.

Ok.  New ChangeLog and patch attached.

Corinna


2003-03-10  Corinna Vinschen  <vinschen at redhat dot com>

	* 
        * fileio.c: New file implementing the remote File-I/O protocol.
	* fileio.h: New header file defining remote File-I/O interface.
        * remote.c (remote_write_bytes, remote_read_bytes): Remove
	static storage class.
	(remote_wait, remote_async_wait): Call remote_fileio_request() on
        'F' packet.
        (_initialize_remote): Call initialize_remote_fileio().
	* remote.h: Declare remote_write_bytes() and remote_read_bytes().

2002-11-21  Martin M. Hunt  <hunt at redhat dot com>

	* Makefile.in (REMOTE_OBS): Add fileio.o
	(SFILES): Add fileio.c.
	Add dependencies for building fileio.o.  Add fileio.h to
	dependencies for building remote.o.
        * defs.h: Declare gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
        * main.c: New ui_file gdb_stdin, gdb_stdtargerr and gdb_stdtargin.
        (captured_main): Initialize new ui_files.
        * ui-file.c: Add read and fgets input functions.
        (ui_file_new): set ui_file_fputs and ui_file_read to null functions.
        (null_file_read): New function.
        (ui_file_read): New function.
        (set_ui_file_read): New function.
        (stdio_file_read): New function.
        * ui-file.h: New type ui_file_read_ftype.
        (set_ui_file_read): Declare.
        (ui_file_read): Declare.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.341
diff -u -p -r1.341 Makefile.in
--- Makefile.in	5 Mar 2003 18:07:15 -0000	1.341
+++ Makefile.in	10 Mar 2003 18:07:16 -0000
@@ -400,7 +400,7 @@ SER_HARDWIRE = @SER_HARDWIRE@
 
 # The `remote' debugging target is supported for most architectures,
 # but not all (e.g. 960)
-REMOTE_OBS = remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o
+REMOTE_OBS = remote.o dcache.o remote-utils.o tracepoint.o ax-general.o ax-gdb.o fileio.o
 
 # This is remote-sim.o if a simulator is to be linked in.
 SIM_OBS =
@@ -516,8 +516,8 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	dbxread.c demangle.c disasm.c doublest.c \
 	dummy-frame.c dwarfread.c dwarf2expr.c dwarf2loc.c dwarf2read.c \
 	elfread.c environ.c eval.c event-loop.c event-top.c expprint.c \
-	f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c frame.c \
-	frame-unwind.c \
+	f-exp.y f-lang.c f-typeprint.c f-valprint.c fileio.c findvar.c \
+	frame.c frame-unwind.c \
 	gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
 	hpacc-abi.c \
 	inf-loop.c infcmd.c inflow.c infrun.c \
@@ -636,6 +636,7 @@ event_loop_h = event-loop.h
 event_top_h = event-top.h
 expression_h = expression.h $(symtab_h) $(doublest_h)
 f_lang_h = f-lang.h
+fileio_h = fileio.h
 frame_h = frame.h
 frame_unwind_h = frame-unwind.h
 gdb_events_h = gdb-events.h
@@ -1682,6 +1683,7 @@ f-valprint.o: f-valprint.c $(defs_h) $(g
 	$(f_lang_h) $(frame_h) $(gdbcore_h) $(command_h) $(block_h)
 fbsd-proc.o: fbsd-proc.c $(defs_h) $(gdbcore_h) $(inferior_h) \
 	$(gdb_string_h) $(elf_bfd_h) $(gregset_h)
+fileio.o: fileio.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) $(remote_h)
 findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \
 	$(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \
@@ -2098,7 +2100,7 @@ remote.o: remote.c $(defs_h) $(gdb_strin
 	$(symfile_h) $(target_h) $(gdbcmd_h) $(objfiles_h) $(gdb_stabs_h) \
 	$(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) $(gdb_assert_h) \
 	$(event_loop_h) $(event_top_h) $(inf_loop_h) $(serial_h) \
-	$(gdbcore_h)
+	$(gdbcore_h) $(fileio_h)
 rom68k-rom.o: rom68k-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
 	$(serial_h) $(regcache_h) $(value_h) $(m68k_tdep_h)
 rs6000-nat.o: rs6000-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdbcore_h) \
Index: defs.h
===================================================================
RCS file: /cvs/src/src/gdb/defs.h,v
retrieving revision 1.116
diff -u -p -r1.116 defs.h
--- defs.h	3 Mar 2003 20:50:18 -0000	1.116
+++ defs.h	10 Mar 2003 18:07:17 -0000
@@ -404,6 +404,8 @@ extern void reinitialize_more_filter (vo
 
 /* Normal results */
 extern struct ui_file *gdb_stdout;
+/* Input stream */
+extern struct ui_file *gdb_stdin;
 /* Serious error notifications */
 extern struct ui_file *gdb_stderr;
 /* Log/debug/trace messages that should bypass normal stdout/stderr
@@ -416,6 +418,8 @@ extern struct ui_file *gdb_stdlog;
    very near future that restriction shall be removed - either call
    shall be unfiltered. (cagney 1999-07-02). */
 extern struct ui_file *gdb_stdtarg;
+extern struct ui_file *gdb_stdtargerr;
+extern struct ui_file *gdb_stdtargin;
 
 #if defined(TUI)
 #include "tui.h"
Index: fileio.c
===================================================================
RCS file: fileio.c
diff -N fileio.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fileio.c	10 Mar 2003 18:07:17 -0000
@@ -0,0 +1,1377 @@
+/* Remote File-I/O communications
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* See the GDB User Guide for details of the GDB remote protocol. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include "remote.h"
+#include "gdb-fileio.h"
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#ifdef USG
+#include <sys/types.h>
+#endif
+#include <sys/stat.h>
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+#include <setjmp.h>
+#include <signal.h>
+
+static struct {
+  int *fd_map;
+  int fd_map_size;
+} remote_fio_data;
+
+#define FIO_FD_INVALID		-1
+#define FIO_FD_CONSOLE_IN	-2
+#define FIO_FD_CONSOLE_OUT	-3
+
+static int remote_fio_system_call_allowed = 0;
+
+static int
+remote_fileio_init_fd_map ()
+{
+  int i;
+
+  if (!remote_fio_data.fd_map)
+    {
+      remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int));
+      remote_fio_data.fd_map_size = 10;
+      remote_fio_data.fd_map[0] = FIO_FD_CONSOLE_IN;
+      remote_fio_data.fd_map[1] = FIO_FD_CONSOLE_OUT;
+      remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT;
+      for (i = 3; i < 10; ++i)
+        remote_fio_data.fd_map[i] = FIO_FD_INVALID;
+    }
+  return 3;
+}
+
+static int
+remote_fileio_resize_fd_map ()
+{
+  if (!remote_fio_data.fd_map)
+    return remote_fileio_init_fd_map ();
+  remote_fio_data.fd_map_size += 10;
+  remote_fio_data.fd_map =
+    (int *) xrealloc (remote_fio_data.fd_map,
+		      remote_fio_data.fd_map_size * sizeof (int));
+  return remote_fio_data.fd_map_size - 10;
+}
+
+static int
+remote_fileio_next_free_fd ()
+{
+  int i;
+
+  for (i = 0; i < remote_fio_data.fd_map_size; ++i)
+    if (remote_fio_data.fd_map[i] == FIO_FD_INVALID)
+      return i;
+  return remote_fileio_resize_fd_map ();
+}
+
+static int
+remote_fileio_fd_to_targetfd (int fd)
+{
+  int target_fd = remote_fileio_next_free_fd ();
+  remote_fio_data.fd_map[target_fd] = fd;
+  return target_fd;
+}
+
+static int
+remote_fileio_map_fd (int target_fd)
+{
+  remote_fileio_init_fd_map ();
+  if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size)
+    return FIO_FD_INVALID;
+  return remote_fio_data.fd_map[target_fd];
+}
+
+static void
+remote_fileio_close_target_fd (int target_fd)
+{
+  remote_fileio_init_fd_map ();
+  if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size)
+    remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID;
+}
+
+static int
+remote_fileio_oflags_to_host (long flags)
+{
+  int hflags = 0;
+
+  if (flags & FILEIO_O_CREAT)
+    hflags |= O_CREAT;
+  if (flags & FILEIO_O_EXCL)
+    hflags |= O_EXCL;
+  if (flags & FILEIO_O_TRUNC)
+    hflags |= O_TRUNC;
+  if (flags & FILEIO_O_APPEND)
+    hflags |= O_APPEND;
+  if (flags & FILEIO_O_RDONLY)
+    hflags |= O_RDONLY;
+  if (flags & FILEIO_O_WRONLY)
+    hflags |= O_WRONLY;
+  if (flags & FILEIO_O_RDWR)
+    hflags |= O_RDWR;
+/* On systems supporting binary and text mode, always open files in
+   binary mode. */
+#ifdef O_BINARY
+  hflags |= O_BINARY;
+#endif
+  return hflags;
+}
+
+static mode_t
+remote_fileio_mode_to_host (long mode, int open_call)
+{
+  mode_t hmode = 0;
+
+  if (!open_call)
+    {
+      if (mode & FILEIO_S_IFREG)
+	hmode |= S_IFREG;
+      if (mode & FILEIO_S_IFDIR)
+	hmode |= S_IFDIR;
+      if (mode & FILEIO_S_IFCHR)
+	hmode |= S_IFCHR;
+    }
+  if (mode & FILEIO_S_IRUSR)
+    hmode |= S_IRUSR;
+  if (mode & FILEIO_S_IWUSR)
+    hmode |= S_IWUSR;
+  if (mode & FILEIO_S_IXUSR)
+    hmode |= S_IXUSR;
+  if (mode & FILEIO_S_IRGRP)
+    hmode |= S_IRGRP;
+  if (mode & FILEIO_S_IWGRP)
+    hmode |= S_IWGRP;
+  if (mode & FILEIO_S_IXGRP)
+    hmode |= S_IXGRP;
+  if (mode & FILEIO_S_IROTH)
+    hmode |= S_IROTH;
+  if (mode & FILEIO_S_IWOTH)
+    hmode |= S_IWOTH;
+  if (mode & FILEIO_S_IXOTH)
+    hmode |= S_IXOTH;
+  return hmode;
+}
+
+static long long
+remote_fileio_mode_to_target (mode_t mode)
+{
+  mode_t tmode = 0;
+
+  if (mode & S_IFREG)
+    tmode |= FILEIO_S_IFREG;
+  if (mode & S_IFDIR)
+    tmode |= FILEIO_S_IFDIR;
+  if (mode & S_IFCHR)
+    tmode |= FILEIO_S_IFCHR;
+  if (mode & S_IRUSR)
+    tmode |= FILEIO_S_IRUSR;
+  if (mode & S_IWUSR)
+    tmode |= FILEIO_S_IWUSR;
+  if (mode & S_IXUSR)
+    tmode |= FILEIO_S_IXUSR;
+  if (mode & S_IRGRP)
+    tmode |= FILEIO_S_IRGRP;
+  if (mode & S_IWGRP)
+    tmode |= FILEIO_S_IWGRP;
+  if (mode & S_IXGRP)
+    tmode |= FILEIO_S_IXGRP;
+  if (mode & S_IROTH)
+    tmode |= FILEIO_S_IROTH;
+  if (mode & S_IWOTH)
+    tmode |= FILEIO_S_IWOTH;
+  if (mode & S_IXOTH)
+    tmode |= FILEIO_S_IXOTH;
+  return tmode;
+}
+
+static int
+remote_fileio_errno_to_target (int error)
+{
+  switch (error)
+    {
+      case EPERM:
+        return FILEIO_EPERM;
+      case ENOENT:
+        return FILEIO_ENOENT;
+      case EINTR:
+        return FILEIO_EINTR;
+      case EIO:
+        return FILEIO_EIO;
+      case EBADF:
+        return FILEIO_EBADF;
+      case EACCES:
+        return FILEIO_EACCES;
+      case EFAULT:
+        return FILEIO_EFAULT;
+      case EBUSY:
+        return FILEIO_EBUSY;
+      case EEXIST:
+        return FILEIO_EEXIST;
+      case ENODEV:
+        return FILEIO_ENODEV;
+      case ENOTDIR:
+        return FILEIO_ENOTDIR;
+      case EISDIR:
+        return FILEIO_EISDIR;
+      case EINVAL:
+        return FILEIO_EINVAL;
+      case ENFILE:
+        return FILEIO_ENFILE;
+      case EMFILE:
+        return FILEIO_EMFILE;
+      case EFBIG:
+        return FILEIO_EFBIG;
+      case ENOSPC:
+        return FILEIO_ENOSPC;
+      case ESPIPE:
+        return FILEIO_ESPIPE;
+      case EROFS:
+        return FILEIO_EROFS;
+      case ENOSYS:
+        return FILEIO_ENOSYS;
+      case ENAMETOOLONG:
+        return FILEIO_ENAMETOOLONG;
+    }
+  return FILEIO_EUNKNOWN;
+}
+
+static int
+remote_fileio_seek_flag_to_host (long num, int *flag)
+{
+  if (!flag)
+    return 0;
+  switch (num)
+    {
+      case FILEIO_SEEK_SET:
+        *flag = SEEK_SET;
+	break;
+      case FILEIO_SEEK_CUR:
+        *flag =  SEEK_CUR;
+	break;
+      case FILEIO_SEEK_END:
+        *flag =  SEEK_END;
+	break;
+      default:
+        return -1;
+    }
+  return 0;
+}
+
+static int
+remote_fileio_extract_long (char **buf, long long *retlong)
+{
+  char *c;
+  int sign = 1;
+
+  if (!buf || !*buf || !**buf || !retlong)
+    return -1;
+  c = strchr (*buf, ',');
+  if (c)
+    *c++ = '\0';
+  else
+    c = strchr (*buf, '\0');
+  while (strchr ("+-", **buf))
+    {
+      if (**buf == '-')
+	sign = -sign;
+      ++*buf;
+    }
+  for (*retlong = 0; **buf; ++*buf)
+    {
+      *retlong <<= 4;
+      if (**buf >= '0' && **buf <= '9')
+        *retlong += **buf - '0';
+      else if (**buf >= 'a' && **buf <= 'f')
+        *retlong += **buf - 'a' + 10;
+      else if (**buf >= 'A' && **buf <= 'F')
+        *retlong += **buf - 'A' + 10;
+      else
+        return -1;
+    }
+  *retlong *= sign;
+  *buf = c;
+  return 0;
+}
+
+static int
+remote_fileio_extract_int (char **buf, long *retint)
+{
+  int ret;
+  long long retlong;
+
+  if (!retint)
+    return -1;
+  if (!(ret = remote_fileio_extract_long (buf, &retlong)))
+    *retint = (long) retlong;
+  return ret;
+}
+
+static int
+remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length)
+{
+  char *c;
+  long long retlong;
+
+  if (!buf || !*buf || !**buf || !ptrval || !length)
+    return -1;
+  c = strchr (*buf, '/');
+  if (!c)
+    return -1;
+  *c++ = '\0';
+  if (remote_fileio_extract_long (buf, &retlong))
+    return -1;
+  *ptrval = (CORE_ADDR) retlong;
+  *buf = c;
+  if (remote_fileio_extract_long (buf, &retlong))
+    return -1;
+  *length = (int) retlong;
+  return 0;
+}
+
+/* Convert to big endian */
+static void
+remote_fileio_to_be (long long num, char *buf, int bytes)
+{
+  int i;
+
+  for (i = 0; i < bytes; ++i)
+    buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff;
+}
+
+static void
+remote_fileio_to_fio_int (long num, fio_int_t fnum)
+{
+  remote_fileio_to_be ((long long) num, (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_uint (long num, fio_uint_t fnum)
+{
+  remote_fileio_to_be ((long long) num, (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_mode (mode_t num, fio_mode_t fnum)
+{
+  remote_fileio_to_be (remote_fileio_mode_to_target(num), (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_time (time_t num, fio_time_t fnum)
+{
+  remote_fileio_to_be ((long long) num, (char *) fnum, 4);
+}
+
+static void
+remote_fileio_to_fio_long (long long num, fio_long_t fnum)
+{
+  remote_fileio_to_be (num, (char *) fnum, 8);
+}
+
+static void
+remote_fileio_to_fio_ulong (long long num, fio_ulong_t fnum)
+{
+  remote_fileio_to_be (num, (char *) fnum, 8);
+}
+
+static void
+remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst)
+{
+  /* `st_dev' is set in the calling function */
+  remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino);
+  remote_fileio_to_fio_mode (st->st_mode, fst->fst_mode);
+  remote_fileio_to_fio_uint ((long) st->st_nlink, fst->fst_nlink);
+  remote_fileio_to_fio_uint ((long) st->st_uid, fst->fst_uid);
+  remote_fileio_to_fio_uint ((long) st->st_gid, fst->fst_gid);
+  remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev);
+  remote_fileio_to_fio_ulong ((long long) st->st_size, fst->fst_size);
+  remote_fileio_to_fio_ulong ((long long) st->st_blksize, fst->fst_blksize);
+  remote_fileio_to_fio_ulong ((long long) st->st_blocks, fst->fst_blocks);
+  remote_fileio_to_fio_time (st->st_atime, fst->fst_atime);
+  remote_fileio_to_fio_time (st->st_mtime, fst->fst_mtime);
+  remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime);
+}
+
+static void
+remote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv)
+{
+  remote_fileio_to_fio_time (tv->tv_sec, ftv->ftv_sec);
+  remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec);
+}
+
+static int remote_fio_ctrl_c_flag = 0;
+static int remote_fio_no_longjmp = 0;
+jmp_buf remote_fio_jmp_buf;
+
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+static struct sigaction remote_fio_sa;
+static struct sigaction remote_fio_osa;
+#else
+static void (*remote_fio_ofunc)(int);
+#endif
+
+static void
+remote_fileio_sig_init ()
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  remote_fio_sa.sa_handler = SIG_IGN;
+  sigemptyset (&remote_fio_sa.sa_mask);
+  remote_fio_sa.sa_flags = 0;
+  sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa);
+#else
+  remote_fio_ofunc = signal (SIGINT, SIG_IGN);
+#endif
+}
+
+static void
+remote_fileio_sig_set (void (*sigint_func)(int))
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  remote_fio_sa.sa_handler = sigint_func;
+  sigemptyset (&remote_fio_sa.sa_mask);
+  remote_fio_sa.sa_flags = 0;
+  sigaction (SIGINT, &remote_fio_sa, NULL);
+#else
+  signal (SIGINT, sigint_func);
+#endif
+}
+
+static void
+remote_fileio_sig_exit ()
+{
+#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
+  sigaction (SIGINT, &remote_fio_osa, NULL);
+#else
+  signal (SIGINT, remote_fio_ofunc);
+#endif
+}
+
+static void
+remote_fileio_ctrl_c_signal_handler (int signo)
+{
+  remote_fileio_sig_set (SIG_IGN);
+  remote_fio_ctrl_c_flag = 1;
+  if (!remote_fio_no_longjmp)
+    throw_exception (RETURN_QUIT);
+  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
+}
+
+static void
+remote_fileio_reply (int retcode, int error)
+{
+  char buf[32];
+
+  remote_fileio_sig_set (SIG_IGN);
+  strcpy (buf, "F");
+  if (retcode < 0)
+    {
+      strcat (buf, "-");
+      retcode = -retcode;
+    }
+  sprintf (buf + strlen (buf), "%x", retcode);
+  if (error || remote_fio_ctrl_c_flag)
+    {
+      if (error && remote_fio_ctrl_c_flag)
+        error = FILEIO_EINTR;
+      if (error < 0)
+        {
+	  strcat (buf, "-");
+	  error = -error;
+	}
+      sprintf (buf + strlen (buf), ",%x", error);
+      if (remote_fio_ctrl_c_flag)
+        strcat (buf, ",C");
+    }
+  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
+  putpkt (buf);
+}
+
+static void
+remote_fileio_ioerror ()
+{
+  remote_fileio_reply (-1, FILEIO_EIO);
+}
+
+static void
+remote_fileio_badfd ()
+{
+  remote_fileio_reply (-1, FILEIO_EBADF);
+}
+
+static void
+remote_fileio_return_errno (int retcode)
+{
+  remote_fileio_reply (retcode,
+		       retcode < 0 ? remote_fileio_errno_to_target (errno) : 0);
+}
+
+static void
+remote_fileio_return_success (int retcode)
+{
+  remote_fileio_reply (retcode, 0);
+}
+
+/* Wrapper function for remote_write_bytes() which has the disadvantage to
+   write only one packet, regardless of the requested number of bytes to
+   transfer.  This wrapper calls remote_write_bytes() as often as needed. */
+static int
+remote_fileio_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
+{
+  int ret = 0, written;
+
+  while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0)
+    {
+      len -= written;
+      memaddr += written;
+      myaddr += written;
+      ret += written;
+    }
+  return ret;
+}
+
+static void
+remote_fileio_func_open (char *buf)
+{
+  CORE_ADDR ptrval;
+  int length, retlength;
+  long num;
+  int flags, fd;
+  mode_t mode;
+  char *pathname;
+  struct stat st;
+
+  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* 2. Parameter: open flags */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  flags = remote_fileio_oflags_to_host (num);
+  /* 3. Parameter: open mode */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  mode = remote_fileio_mode_to_host (num, 1);
+
+  /* Request pathname using 'm' packet */
+  pathname = alloca (length);
+  retlength = remote_read_bytes (ptrval, pathname, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  /* Check if pathname exists and is not a regular file or directory.  If so,
+     return an appropriate error code.  Same for trying to open directories
+     for writing. */
+  if (!stat (pathname, &st))
+    {
+      if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
+	{
+	  remote_fileio_reply (-1, FILEIO_ENODEV);
+	  return;
+	}
+      if (S_ISDIR (st.st_mode)
+	  && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR))
+	{
+	  remote_fileio_reply (-1, FILEIO_EISDIR);
+	  return;
+	}
+    }
+
+  remote_fio_no_longjmp = 1;
+  fd = open (pathname, flags, mode);
+  if (fd < 0)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+
+  fd = remote_fileio_fd_to_targetfd (fd);
+  remote_fileio_return_success (fd);
+}
+
+static void
+remote_fileio_func_close (char *buf)
+{
+  long num;
+  int fd;
+
+  /* Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if ((fd = remote_fileio_map_fd ((int) num)) == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd))
+    remote_fileio_return_errno (-1);
+  remote_fileio_close_target_fd ((int) num);
+  remote_fileio_return_success (0);
+}
+
+static void
+remote_fileio_func_read (char *buf)
+{
+  long target_fd, num;
+  long long lnum;
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  char *buffer;
+  size_t length;
+  off_t old_offset, new_offset;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if ((fd = remote_fileio_map_fd ((int) target_fd)) == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  /* 2. Parameter: buffer pointer */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+  /* 3. Parameter: buffer length */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  length = (size_t) num;
+
+  switch (fd)
+    {
+      case FIO_FD_CONSOLE_OUT:
+	remote_fileio_badfd ();
+	return;
+      case FIO_FD_CONSOLE_IN:
+	{
+	  static char *remaining_buf = NULL;
+	  static int remaining_length = 0;
+
+	  buffer = (char *) xmalloc (32768);
+	  if (remaining_buf)
+	    {
+	      remote_fio_no_longjmp = 1;
+	      if (remaining_length > length)
+		{
+		  memcpy (buffer, remaining_buf, length);
+		  memmove (remaining_buf, remaining_buf + length,
+			   remaining_length - length);
+		  remaining_length -= length;
+		  ret = length;
+		}
+	      else
+		{
+		  memcpy (buffer, remaining_buf, remaining_length);
+		  xfree (remaining_buf);
+		  remaining_buf = NULL;
+		  ret = remaining_length;
+		}
+	    }
+	  else
+	    {
+	      ret = ui_file_read (gdb_stdtargin, buffer, 32767);
+	      remote_fio_no_longjmp = 1;
+	      if (ret > 0 && (size_t)ret > length)
+		{
+		  remaining_buf = (char *) xmalloc (ret - length);
+		  remaining_length = ret - length;
+		  memcpy (remaining_buf, buffer + length, remaining_length);
+		  ret = length;
+		}
+	    }
+	}
+	break;
+      default:
+	buffer = (char *) xmalloc (length);
+	/* POSIX defines EINTR behaviour of read in a weird way.  It's allowed
+	   for read() to return -1 even if "some" bytes have been read.  It
+	   has been corrected in SUSv2 but that doesn't help us much...
+	   Therefore a complete solution must check how many bytes have been
+	   read on EINTR to return a more reliable value to the target */
+	old_offset = lseek (fd, 0, SEEK_CUR);
+	remote_fio_no_longjmp = 1;
+	ret = read (fd, buffer, length);
+	if (ret < 0 && errno == EINTR)
+	  {
+	    new_offset = lseek (fd, 0, SEEK_CUR);
+	    /* If some data has been read, return the number of bytes read.
+	       The Ctrl-C flag is set in remote_fileio_reply() anyway */
+	    if (old_offset != new_offset)
+	      ret = new_offset - old_offset;
+	  }
+	break;
+    }
+
+  if (ret > 0)
+    {
+      retlength = remote_fileio_write_bytes (ptrval, buffer, ret);
+      if (retlength != ret)
+	ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */
+    }
+
+  if (ret < 0)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+
+  xfree (buffer);
+}
+
+static void
+remote_fileio_func_write (char *buf)
+{
+  long target_fd, num;
+  long long lnum;
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  char *buffer;
+  size_t length;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if ((fd = remote_fileio_map_fd ((int) target_fd)) == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  /* 2. Parameter: buffer pointer */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+  /* 3. Parameter: buffer length */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  length = (size_t) num;
+    
+  buffer = (char *) xmalloc (length);
+  retlength = remote_read_bytes (ptrval, buffer, length);
+  if (retlength != length)
+    {
+      xfree (buffer);
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  switch (fd)
+    {
+      case FIO_FD_CONSOLE_IN:
+	remote_fileio_badfd ();
+	return;
+      case FIO_FD_CONSOLE_OUT:
+	ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr, buffer,
+		       length);
+	gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr);
+	ret = length;
+	break;
+      default:
+	ret = write (fd, buffer, length);
+	if (ret < 0 && errno == EACCES)
+	  errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/
+	break;
+    }
+
+  if (ret < 0)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+
+  xfree (buffer);
+}
+
+static void
+remote_fileio_func_lseek (char *buf)
+{
+  long num;
+  long long lnum;
+  int fd, flag;
+  off_t offset, ret;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if ((fd = remote_fileio_map_fd ((int) num)) == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
+    {
+      remote_fileio_reply (-1, FILEIO_ESPIPE);
+      return;
+    }
+
+  /* 2. Parameter: offset */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  offset = (off_t) lnum;
+  /* 3. Parameter: flag */
+  if (remote_fileio_extract_int (&buf, &num))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if (remote_fileio_seek_flag_to_host (num, &flag))
+    {
+      remote_fileio_reply (-1, FILEIO_EINVAL);
+      return;
+    }
+  
+  remote_fio_no_longjmp = 1;
+  ret = lseek (fd, offset, flag);
+
+  if (ret == (off_t) -1)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_rename (char *buf)
+{
+  CORE_ADDR ptrval;
+  int length, retlength;
+  char *oldpath, *newpath;
+  int ret, of, nf;
+  struct stat ost, nst;
+
+  /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request oldpath using 'm' packet */
+  oldpath = alloca (length);
+  retlength = remote_read_bytes (ptrval, oldpath, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* 2. Parameter: Ptr to newpath / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request newpath using 'm' packet */
+  newpath = alloca (length);
+  retlength = remote_read_bytes (ptrval, newpath, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  
+  /* Only operate on regular files and directories */
+  if ((!(of = stat (oldpath, &ost))
+       && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
+      || (!(nf = stat (newpath, &nst))
+          && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
+    {
+      remote_fileio_reply (-1, FILEIO_EACCES);
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = rename (oldpath, newpath);
+
+  if (ret == -1)
+    {
+      /* Special case: newpath is a non-empty directory.  Some systems
+         return ENOTEMPTY, some return EEXIST.  We coerce that to be
+	 always EEXIST. */
+      if (errno == ENOTEMPTY)
+        errno = EEXIST;
+#ifdef __CYGWIN__
+      /* Workaround some Cygwin problems with correct errnos. */
+      if (errno == EACCES)
+        {
+	  if (!of && !nf && S_ISDIR (nst.st_mode))
+	    {
+	      if (S_ISREG (ost.st_mode))
+		errno = EISDIR;
+	      else
+		{
+		  char oldfullpath[PATH_MAX + 1];
+		  char newfullpath[PATH_MAX + 1];
+		  int len;
+
+		  cygwin_conv_to_full_posix_path (oldpath, oldfullpath);
+		  cygwin_conv_to_full_posix_path (newpath, newfullpath);
+		  len = strlen (oldfullpath);
+		  if (newfullpath[len] == '/'
+		      && !strncmp (oldfullpath, newfullpath, len))
+		    errno = EINVAL;
+		  else
+		    errno = EEXIST;
+		}
+	    }
+	}
+#endif
+
+      remote_fileio_return_errno (-1);
+    }
+  else
+    remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_unlink (char *buf)
+{
+  CORE_ADDR ptrval;
+  int length, retlength;
+  char *pathname;
+  int ret;
+  struct stat st;
+
+  /* Parameter: Ptr to pathname / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request pathname using 'm' packet */
+  pathname = alloca (length);
+  retlength = remote_read_bytes (ptrval, pathname, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  /* Only operate on regular files (and directories, which allows to return
+     the correct return code) */
+  if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
+    {
+      remote_fileio_reply (-1, FILEIO_ENODEV);
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = unlink (pathname);
+
+  if (ret == -1)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_stat (char *buf)
+{
+  CORE_ADDR ptrval;
+  int ret, length, retlength;
+  char *pathname;
+  long long lnum;
+  struct stat st;
+  struct fio_stat fst;
+
+  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request pathname using 'm' packet */
+  pathname = alloca (length);
+  retlength = remote_read_bytes (ptrval, pathname, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  /* 2. Parameter: Ptr to struct stat */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+
+  remote_fio_no_longjmp = 1;
+  ret = stat (pathname, &st);
+
+  if (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+  /* Only operate on regular files and directories */
+  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
+    {
+      remote_fileio_reply (-1, FILEIO_EACCES);
+      return;
+    }
+  if (ptrval)
+    {
+      remote_fileio_to_fio_stat (&st, &fst);
+      remote_fileio_to_fio_uint (0, fst.fst_dev);
+      
+      retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst);
+      if (retlength != sizeof fst)
+	{
+	  remote_fileio_return_errno (-1);
+	  return;
+	}
+    }
+  remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_fstat (char *buf)
+{
+  CORE_ADDR ptrval;
+  int fd, ret, retlength;
+  long target_fd;
+  long long lnum;
+  struct stat st;
+  struct fio_stat fst;
+  struct timeval tv;
+
+  /* 1. Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  if ((fd = remote_fileio_map_fd ((int) target_fd)) == FIO_FD_INVALID)
+    {
+      remote_fileio_badfd ();
+      return;
+    }
+  /* 2. Parameter: Ptr to struct stat */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+
+  remote_fio_no_longjmp = 1;
+  if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
+    {
+      remote_fileio_to_fio_uint (1, fst.fst_dev);
+      st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
+      st.st_nlink = 1;
+      st.st_uid = getuid ();
+      st.st_gid = getgid ();
+      st.st_rdev = 0;
+      st.st_size = 0;
+      st.st_blksize = 512;
+      st.st_blocks = 0;
+      if (!gettimeofday (&tv, NULL))
+	st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
+      else
+        st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
+      ret = 0;
+    }
+  else
+    ret = fstat (fd, &st);
+
+  if (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+  if (ptrval)
+    {
+      remote_fileio_to_fio_stat (&st, &fst);
+
+      retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst);
+      if (retlength != sizeof fst)
+	{
+	  remote_fileio_return_errno (-1);
+	  return;
+	}
+    }
+  remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_gettimeofday (char *buf)
+{
+  long long lnum;
+  CORE_ADDR ptrval;
+  int ret, retlength;
+  struct timeval tv;
+  struct fio_timeval ftv;
+
+  /* 1. Parameter: struct timeval pointer */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  ptrval = (CORE_ADDR) lnum;
+  /* 2. Parameter: some pointer value... */
+  if (remote_fileio_extract_long (&buf, &lnum))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* ...which has to be NULL */
+  if (lnum)
+    {
+      remote_fileio_reply (-1, FILEIO_EINVAL);
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = gettimeofday (&tv, NULL);
+
+  if (ret == -1)
+    {
+      remote_fileio_return_errno (-1);
+      return;
+    }
+
+  if (ptrval)
+    {
+      remote_fileio_to_fio_timeval (&tv, &ftv);
+
+      retlength = remote_fileio_write_bytes (ptrval, (char *) &ftv, sizeof ftv);
+      if (retlength != sizeof ftv)
+	{
+	  remote_fileio_return_errno (-1);
+	  return;
+	}
+    }
+  remote_fileio_return_success (ret);
+}
+
+static void
+remote_fileio_func_isatty (char *buf)
+{
+  long target_fd;
+  int fd;
+
+  /* Parameter: file descriptor */
+  if (remote_fileio_extract_int (&buf, &target_fd))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  remote_fio_no_longjmp = 1;
+  fd = remote_fileio_map_fd ((int) target_fd);
+  remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN ||
+  				fd == FIO_FD_CONSOLE_OUT ? 1 : 0);
+}
+
+static void
+remote_fileio_func_system (char *buf)
+{
+  CORE_ADDR ptrval;
+  int ret, length, retlength;
+  char *cmdline;
+
+  /* Check if system(3) has been explicitely allowed using the
+     `set remote system-call-allowed 1' command.  If not, return
+     EPERM */
+  if (!remote_fio_system_call_allowed)
+    {
+      remote_fileio_reply (-1, FILEIO_EPERM);
+      return;
+    }
+
+  /* Parameter: Ptr to commandline / length incl. trailing zero */
+  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+  /* Request commandline using 'm' packet */
+  cmdline = alloca (length);
+  retlength = remote_read_bytes (ptrval, cmdline, length);
+  if (retlength != length)
+    {
+      remote_fileio_ioerror ();
+      return;
+    }
+
+  remote_fio_no_longjmp = 1;
+  ret = system (cmdline);
+
+  if (ret == -1)
+    remote_fileio_return_errno (-1);
+  else
+    remote_fileio_return_success (WEXITSTATUS (ret));
+}
+
+static struct {
+  char *name;
+  void (*func)(char *);
+} remote_fio_func_map[] = {
+  "open", remote_fileio_func_open,
+  "close", remote_fileio_func_close,
+  "read", remote_fileio_func_read,
+  "write", remote_fileio_func_write,
+  "lseek", remote_fileio_func_lseek,
+  "rename", remote_fileio_func_rename,
+  "unlink", remote_fileio_func_unlink,
+  "stat", remote_fileio_func_stat,
+  "fstat", remote_fileio_func_fstat,
+  "gettimeofday", remote_fileio_func_gettimeofday,
+  "isatty", remote_fileio_func_isatty,
+  "system", remote_fileio_func_system,
+  NULL, NULL
+};
+
+static int
+do_remote_fileio_request (struct ui_out *uiout, void *buf_arg)
+{
+  char *buf = buf_arg;
+  char *c;
+  int idx;
+
+  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
+
+  c = strchr (++buf, ',');
+  if (c)
+    *c++ = '\0';
+  else
+    c = strchr (buf, '\0');
+  for (idx = 0; remote_fio_func_map[idx].name; ++idx)
+    if (!strcmp (remote_fio_func_map[idx].name, buf))
+      break;
+  if (!remote_fio_func_map[idx].name)	/* ERROR: No such function. */
+    return RETURN_ERROR;
+  remote_fio_func_map[idx].func (c);
+  return 0;
+}
+
+void
+remote_fileio_request (char *buf)
+{
+  int ex;
+
+  remote_fileio_sig_init ();
+
+  remote_fio_ctrl_c_flag = 0;
+  remote_fio_no_longjmp = 0;
+
+  ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf,
+			 NULL, RETURN_MASK_ALL);
+  switch (ex)
+    {
+      case RETURN_ERROR:
+	remote_fileio_reply (-1, FILEIO_ENOSYS);
+        break;
+      case RETURN_QUIT:
+        remote_fileio_reply (-1, FILEIO_EINTR);
+	break;
+      default:
+        break;
+    }
+
+  remote_fileio_sig_exit ();
+}
+
+static void
+set_system_call_allowed (char *args, int from_tty)
+{
+  if (args)
+    {
+      char *arg_end;
+      int val = strtoul (args, &arg_end, 10);
+      if (*args && *arg_end == '\0')
+        {
+	  remote_fio_system_call_allowed = !!val;
+	  return;
+	}
+    }
+  error ("Illegal argument for \"set remote system-call-allowed\" command");
+}
+
+static void
+show_system_call_allowed (char *args, int from_tty)
+{
+  if (args)
+    error ("Garbage after \"show remote system-call-allowed\" command: `%s'", args);
+  printf_unfiltered ("Calling host system(3) call from target is %sallowed\n",
+		     remote_fio_system_call_allowed ? "" : "not ");
+}
+
+void
+initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
+			  struct cmd_list_element *remote_show_cmdlist)
+{
+  add_cmd ("system-call-allowed", no_class,
+	   set_system_call_allowed,
+	   "Set if the host system(3) call is allowed for the target.\n",
+	   &remote_set_cmdlist);
+  add_cmd ("system-call-allowed", no_class,
+	   show_system_call_allowed,
+	   "Show if the host system(3) call is allowed for the target.\n",
+	   &remote_show_cmdlist);
+}
Index: fileio.h
===================================================================
RCS file: fileio.h
diff -N fileio.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ fileio.h	10 Mar 2003 18:07:17 -0000
@@ -0,0 +1,36 @@
+/* Remote File-I/O communications
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.  */
+
+/* See the GDB User Guide for details of the GDB remote protocol. */
+
+#ifndef FILEIO_H
+#define FILEIO_H
+
+/* Unified interface to remote fileio, called in remote.c from
+   remote_wait () and remote_async_wait () */
+extern void remote_fileio_request (char *buf);
+
+/* Called from _initialize_remote () */
+extern void initialize_remote_fileio (
+  struct cmd_list_element *remote_set_cmdlist,
+  struct cmd_list_element *remote_show_cmdlist);
+
+#endif
Index: main.c
===================================================================
RCS file: /cvs/src/src/gdb/main.c,v
retrieving revision 1.31
diff -u -p -r1.31 main.c
--- main.c	2 Mar 2003 02:07:12 -0000	1.31
+++ main.c	10 Mar 2003 18:07:18 -0000
@@ -73,6 +73,10 @@ struct ui_file *gdb_stdout;
 struct ui_file *gdb_stderr;
 struct ui_file *gdb_stdlog;
 struct ui_file *gdb_stdtarg;
+struct ui_file *gdb_stdin;
+/* target IO streams */
+struct ui_file *gdb_stdtargin;
+struct ui_file *gdb_stdtargerr;
 
 /* Used to initialize error() - defined in utils.c */
 
@@ -193,6 +197,9 @@ captured_main (void *data)
   gdb_stderr = stdio_fileopen (stderr);
   gdb_stdlog = gdb_stderr;	/* for moment */
   gdb_stdtarg = gdb_stderr;	/* for moment */
+  gdb_stdin = stdio_fileopen (stdin);
+  gdb_stdtargerr = gdb_stderr;	/* for moment */
+  gdb_stdtargin = gdb_stdin;	/* for moment */
 
   /* initialize error() */
   error_init ();
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.95
diff -u -p -r1.95 remote.c
--- remote.c	20 Feb 2003 13:43:14 -0000	1.95
+++ remote.c	10 Mar 2003 18:07:21 -0000
@@ -55,6 +55,8 @@
 
 #include "gdbcore.h" /* for exec_bfd */
 
+#include "fileio.h"
+
 /* Prototypes for local functions */
 static void cleanup_sigint_signal_handler (void *dummy);
 static void initialize_sigint_signal_handler (void);
@@ -67,10 +69,6 @@ void async_remote_interrupt_twice (gdb_c
 
 static void build_remote_gdbarch_data (void);
 
-static int remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len);
-
-static int remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len);
-
 static void remote_files_info (struct target_ops *ignore);
 
 static int remote_xfer_memory (CORE_ADDR memaddr, char *myaddr,
@@ -2945,6 +2943,9 @@ remote_wait (ptid_t ptid, struct target_
 	case 'E':		/* Error of some sort */
 	  warning ("Remote failure reply: %s", buf);
 	  continue;
+	case 'F':		/* File-I/O request */
+	  remote_fileio_request (buf);
+	  continue;
 	case 'T':		/* Status with PC, SP, FP, ... */
 	  {
 	    int i;
@@ -3196,6 +3197,9 @@ remote_async_wait (ptid_t ptid, struct t
 	case 'E':		/* Error of some sort */
 	  warning ("Remote failure reply: %s", buf);
 	  continue;
+	case 'F':		/* File-I/O request */
+	  remote_fileio_request (buf);
+	  continue;
 	case 'T':		/* Status with PC, SP, FP, ... */
 	  {
 	    int i;
@@ -3750,7 +3754,7 @@ check_binary_download (CORE_ADDR addr)
    Returns number of bytes transferred, or 0 (setting errno) for
    error.  Only transfer a single packet. */
 
-static int
+int
 remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
 {
   unsigned char *buf;
@@ -3894,7 +3898,7 @@ remote_write_bytes (CORE_ADDR memaddr, c
    caller and its callers caller ;-) already contains code for
    handling partial reads. */
 
-static int
+int
 remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len)
 {
   char *buf;
@@ -6267,4 +6271,7 @@ Set use of remote protocol `Z' packets",
 				set_remote_protocol_Z_packet_cmd,
 				show_remote_protocol_Z_packet_cmd,
 				&remote_set_cmdlist, &remote_show_cmdlist);
+
+  /* Eventually initialize fileio.  See fileio.c */
+  initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);
 }
Index: remote.h
===================================================================
RCS file: /cvs/src/src/gdb/remote.h,v
retrieving revision 1.2
diff -u -p -r1.2 remote.h
--- remote.h	6 Mar 2001 08:21:16 -0000	1.2
+++ remote.h	10 Mar 2003 18:07:21 -0000
@@ -54,4 +54,8 @@ extern void remote_cisco_objfile_relocat
 
 extern void async_remote_interrupt_twice (void *arg);
 
+extern int remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len);
+
+extern int remote_read_bytes (CORE_ADDR memaddr, char *myaddr, int len);
+
 #endif
Index: ui-file.c
===================================================================
RCS file: /cvs/src/src/gdb/ui-file.c,v
retrieving revision 1.9
diff -u -p -r1.9 ui-file.c
--- ui-file.c	25 Jul 2002 03:14:28 -0000	1.9
+++ ui-file.c	10 Mar 2003 18:07:21 -0000
@@ -25,9 +25,12 @@
 #include "ui-file.h"
 #include "gdb_string.h"
 
+#include <errno.h>
+
 static ui_file_isatty_ftype null_file_isatty;
 static ui_file_write_ftype null_file_write;
 static ui_file_fputs_ftype null_file_fputs;
+static ui_file_read_ftype null_file_read;
 static ui_file_flush_ftype null_file_flush;
 static ui_file_delete_ftype null_file_delete;
 static ui_file_rewind_ftype null_file_rewind;
@@ -39,6 +42,7 @@ struct ui_file
     ui_file_flush_ftype *to_flush;
     ui_file_write_ftype *to_write;
     ui_file_fputs_ftype *to_fputs;
+    ui_file_read_ftype *to_read;
     ui_file_delete_ftype *to_delete;
     ui_file_isatty_ftype *to_isatty;
     ui_file_rewind_ftype *to_rewind;
@@ -56,6 +60,7 @@ ui_file_new (void)
   set_ui_file_flush (file, null_file_flush);
   set_ui_file_write (file, null_file_write);
   set_ui_file_fputs (file, null_file_fputs);
+  set_ui_file_read (file, null_file_read);
   set_ui_file_isatty (file, null_file_isatty);
   set_ui_file_rewind (file, null_file_rewind);
   set_ui_file_put (file, null_file_put);
@@ -123,6 +128,15 @@ null_file_write (struct ui_file *file,
     }
 }
 
+static long
+null_file_read (struct ui_file *file,
+		char *buf,
+		long sizeof_buf)
+{
+  errno = EBADF;
+  return 0;
+}
+
 static void
 null_file_fputs (const char *buf, struct ui_file *file)
 {
@@ -186,6 +200,12 @@ ui_file_write (struct ui_file *file,
   file->to_write (file, buf, length_buf);
 }
 
+long
+ui_file_read (struct ui_file *file, char *buf, long length_buf)
+{
+  return file->to_read (file, buf, length_buf); 
+}
+
 void
 fputs_unfiltered (const char *buf, struct ui_file *file)
 {
@@ -224,6 +244,12 @@ set_ui_file_write (struct ui_file *file,
 }
 
 void
+set_ui_file_read (struct ui_file *file, ui_file_read_ftype *read)
+{
+  file->to_read = read;
+}
+
+void
 set_ui_file_fputs (struct ui_file *file, ui_file_fputs_ftype *fputs)
 {
   file->to_fputs = fputs;
@@ -383,6 +409,7 @@ mem_file_write (struct ui_file *file,
 
 static ui_file_write_ftype stdio_file_write;
 static ui_file_fputs_ftype stdio_file_fputs;
+static ui_file_read_ftype stdio_file_read;
 static ui_file_isatty_ftype stdio_file_isatty;
 static ui_file_delete_ftype stdio_file_delete;
 static struct ui_file *stdio_file_new (FILE * file, int close_p);
@@ -409,6 +436,7 @@ stdio_file_new (FILE *file, int close_p)
   set_ui_file_flush (ui_file, stdio_file_flush);
   set_ui_file_write (ui_file, stdio_file_write);
   set_ui_file_fputs (ui_file, stdio_file_fputs);
+  set_ui_file_read (ui_file, stdio_file_read);
   set_ui_file_isatty (ui_file, stdio_file_isatty);
   return ui_file;
 }
@@ -435,6 +463,16 @@ stdio_file_flush (struct ui_file *file)
     internal_error (__FILE__, __LINE__,
 		    "stdio_file_flush: bad magic number");
   fflush (stdio->file);
+}
+
+static long
+stdio_file_read (struct ui_file *file, char *buf, long length_buf)
+{
+  struct stdio_file *stdio = ui_file_data (file);
+  if (stdio->magic != &stdio_file_magic)
+    internal_error (__FILE__, __LINE__,
+		    "stdio_file_read: bad magic number");
+  return read (fileno (stdio->file), buf, length_buf);
 }
 
 static void
Index: ui-file.h
===================================================================
RCS file: /cvs/src/src/gdb/ui-file.h,v
retrieving revision 1.3
diff -u -p -r1.3 ui-file.h
--- ui-file.h	25 Jul 2002 03:14:28 -0000	1.3
+++ ui-file.h	10 Mar 2003 18:07:21 -0000
@@ -41,6 +41,9 @@ extern void set_ui_file_write (struct ui
 typedef void (ui_file_fputs_ftype) (const char *, struct ui_file * stream);
 extern void set_ui_file_fputs (struct ui_file *stream, ui_file_fputs_ftype * fputs);
 
+typedef long (ui_file_read_ftype) (struct ui_file * stream, char *buf, long length_buf);
+extern void set_ui_file_read (struct ui_file *stream, ui_file_read_ftype *fread);
+
 typedef int (ui_file_isatty_ftype) (struct ui_file * stream);
 extern void set_ui_file_isatty (struct ui_file *stream, ui_file_isatty_ftype * isatty);
 
@@ -77,6 +80,8 @@ extern void ui_file_put (struct ui_file 
 extern char *ui_file_xstrdup (struct ui_file *file, long *length);
 
 
+
+extern long ui_file_read (struct ui_file *file, char *buf, long length_buf);
 
 /* Create/open a memory based file. Can be used as a scratch buffer
    for collecting output. */


-- 
Corinna Vinschen
Cygwin Developer
Red Hat, Inc.
mailto:vinschen at redhat dot com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]