OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [remote-fileio.c] - Diff between revs 834 and 842

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 834 Rev 842
/* Remote File-I/O communications
/* Remote File-I/O communications
 
 
   Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010
   Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
/* See the GDB User Guide for details of the GDB remote protocol. */
/* See the GDB User Guide for details of the GDB remote protocol. */
 
 
#include "defs.h"
#include "defs.h"
#include "gdb_string.h"
#include "gdb_string.h"
#include "gdbcmd.h"
#include "gdbcmd.h"
#include "remote.h"
#include "remote.h"
#include "gdb/fileio.h"
#include "gdb/fileio.h"
#include "gdb_wait.h"
#include "gdb_wait.h"
#include "gdb_stat.h"
#include "gdb_stat.h"
#include "exceptions.h"
#include "exceptions.h"
#include "remote-fileio.h"
#include "remote-fileio.h"
#include "event-loop.h"
#include "event-loop.h"
 
 
#include <fcntl.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/time.h>
#ifdef __CYGWIN__
#ifdef __CYGWIN__
#include <sys/cygwin.h>         /* For cygwin_conv_to_full_posix_path.  */
#include <sys/cygwin.h>         /* For cygwin_conv_to_full_posix_path.  */
#endif
#endif
#include <signal.h>
#include <signal.h>
 
 
static struct {
static struct {
  int *fd_map;
  int *fd_map;
  int fd_map_size;
  int fd_map_size;
} remote_fio_data;
} remote_fio_data;
 
 
#define FIO_FD_INVALID          -1
#define FIO_FD_INVALID          -1
#define FIO_FD_CONSOLE_IN       -2
#define FIO_FD_CONSOLE_IN       -2
#define FIO_FD_CONSOLE_OUT      -3
#define FIO_FD_CONSOLE_OUT      -3
 
 
static int remote_fio_system_call_allowed = 0;
static int remote_fio_system_call_allowed = 0;
 
 
static struct async_signal_handler *sigint_fileio_token;
static struct async_signal_handler *sigint_fileio_token;
 
 
static int
static int
remote_fileio_init_fd_map (void)
remote_fileio_init_fd_map (void)
{
{
  int i;
  int i;
 
 
  if (!remote_fio_data.fd_map)
  if (!remote_fio_data.fd_map)
    {
    {
      remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int));
      remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int));
      remote_fio_data.fd_map_size = 10;
      remote_fio_data.fd_map_size = 10;
      remote_fio_data.fd_map[0] = FIO_FD_CONSOLE_IN;
      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[1] = FIO_FD_CONSOLE_OUT;
      remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT;
      remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT;
      for (i = 3; i < 10; ++i)
      for (i = 3; i < 10; ++i)
        remote_fio_data.fd_map[i] = FIO_FD_INVALID;
        remote_fio_data.fd_map[i] = FIO_FD_INVALID;
    }
    }
  return 3;
  return 3;
}
}
 
 
static int
static int
remote_fileio_resize_fd_map (void)
remote_fileio_resize_fd_map (void)
{
{
  int i = remote_fio_data.fd_map_size;
  int i = remote_fio_data.fd_map_size;
 
 
  if (!remote_fio_data.fd_map)
  if (!remote_fio_data.fd_map)
    return remote_fileio_init_fd_map ();
    return remote_fileio_init_fd_map ();
  remote_fio_data.fd_map_size += 10;
  remote_fio_data.fd_map_size += 10;
  remote_fio_data.fd_map =
  remote_fio_data.fd_map =
    (int *) xrealloc (remote_fio_data.fd_map,
    (int *) xrealloc (remote_fio_data.fd_map,
                      remote_fio_data.fd_map_size * sizeof (int));
                      remote_fio_data.fd_map_size * sizeof (int));
  for (; i < remote_fio_data.fd_map_size; i++)
  for (; i < remote_fio_data.fd_map_size; i++)
    remote_fio_data.fd_map[i] = FIO_FD_INVALID;
    remote_fio_data.fd_map[i] = FIO_FD_INVALID;
  return remote_fio_data.fd_map_size - 10;
  return remote_fio_data.fd_map_size - 10;
}
}
 
 
static int
static int
remote_fileio_next_free_fd (void)
remote_fileio_next_free_fd (void)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < remote_fio_data.fd_map_size; ++i)
  for (i = 0; i < remote_fio_data.fd_map_size; ++i)
    if (remote_fio_data.fd_map[i] == FIO_FD_INVALID)
    if (remote_fio_data.fd_map[i] == FIO_FD_INVALID)
      return i;
      return i;
  return remote_fileio_resize_fd_map ();
  return remote_fileio_resize_fd_map ();
}
}
 
 
static int
static int
remote_fileio_fd_to_targetfd (int fd)
remote_fileio_fd_to_targetfd (int fd)
{
{
  int target_fd = remote_fileio_next_free_fd ();
  int target_fd = remote_fileio_next_free_fd ();
  remote_fio_data.fd_map[target_fd] = fd;
  remote_fio_data.fd_map[target_fd] = fd;
  return target_fd;
  return target_fd;
}
}
 
 
static int
static int
remote_fileio_map_fd (int target_fd)
remote_fileio_map_fd (int target_fd)
{
{
  remote_fileio_init_fd_map ();
  remote_fileio_init_fd_map ();
  if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size)
  if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size)
    return FIO_FD_INVALID;
    return FIO_FD_INVALID;
  return remote_fio_data.fd_map[target_fd];
  return remote_fio_data.fd_map[target_fd];
}
}
 
 
static void
static void
remote_fileio_close_target_fd (int target_fd)
remote_fileio_close_target_fd (int target_fd)
{
{
  remote_fileio_init_fd_map ();
  remote_fileio_init_fd_map ();
  if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size)
  if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size)
    remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID;
    remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID;
}
}
 
 
static int
static int
remote_fileio_oflags_to_host (long flags)
remote_fileio_oflags_to_host (long flags)
{
{
  int hflags = 0;
  int hflags = 0;
 
 
  if (flags & FILEIO_O_CREAT)
  if (flags & FILEIO_O_CREAT)
    hflags |= O_CREAT;
    hflags |= O_CREAT;
  if (flags & FILEIO_O_EXCL)
  if (flags & FILEIO_O_EXCL)
    hflags |= O_EXCL;
    hflags |= O_EXCL;
  if (flags & FILEIO_O_TRUNC)
  if (flags & FILEIO_O_TRUNC)
    hflags |= O_TRUNC;
    hflags |= O_TRUNC;
  if (flags & FILEIO_O_APPEND)
  if (flags & FILEIO_O_APPEND)
    hflags |= O_APPEND;
    hflags |= O_APPEND;
  if (flags & FILEIO_O_RDONLY)
  if (flags & FILEIO_O_RDONLY)
    hflags |= O_RDONLY;
    hflags |= O_RDONLY;
  if (flags & FILEIO_O_WRONLY)
  if (flags & FILEIO_O_WRONLY)
    hflags |= O_WRONLY;
    hflags |= O_WRONLY;
  if (flags & FILEIO_O_RDWR)
  if (flags & FILEIO_O_RDWR)
    hflags |= O_RDWR;
    hflags |= O_RDWR;
/* On systems supporting binary and text mode, always open files in
/* On systems supporting binary and text mode, always open files in
   binary mode. */
   binary mode. */
#ifdef O_BINARY
#ifdef O_BINARY
  hflags |= O_BINARY;
  hflags |= O_BINARY;
#endif
#endif
  return hflags;
  return hflags;
}
}
 
 
static mode_t
static mode_t
remote_fileio_mode_to_host (long mode, int open_call)
remote_fileio_mode_to_host (long mode, int open_call)
{
{
  mode_t hmode = 0;
  mode_t hmode = 0;
 
 
  if (!open_call)
  if (!open_call)
    {
    {
      if (mode & FILEIO_S_IFREG)
      if (mode & FILEIO_S_IFREG)
        hmode |= S_IFREG;
        hmode |= S_IFREG;
      if (mode & FILEIO_S_IFDIR)
      if (mode & FILEIO_S_IFDIR)
        hmode |= S_IFDIR;
        hmode |= S_IFDIR;
      if (mode & FILEIO_S_IFCHR)
      if (mode & FILEIO_S_IFCHR)
        hmode |= S_IFCHR;
        hmode |= S_IFCHR;
    }
    }
  if (mode & FILEIO_S_IRUSR)
  if (mode & FILEIO_S_IRUSR)
    hmode |= S_IRUSR;
    hmode |= S_IRUSR;
  if (mode & FILEIO_S_IWUSR)
  if (mode & FILEIO_S_IWUSR)
    hmode |= S_IWUSR;
    hmode |= S_IWUSR;
  if (mode & FILEIO_S_IXUSR)
  if (mode & FILEIO_S_IXUSR)
    hmode |= S_IXUSR;
    hmode |= S_IXUSR;
#ifdef S_IRGRP
#ifdef S_IRGRP
  if (mode & FILEIO_S_IRGRP)
  if (mode & FILEIO_S_IRGRP)
    hmode |= S_IRGRP;
    hmode |= S_IRGRP;
#endif
#endif
#ifdef S_IWGRP
#ifdef S_IWGRP
  if (mode & FILEIO_S_IWGRP)
  if (mode & FILEIO_S_IWGRP)
    hmode |= S_IWGRP;
    hmode |= S_IWGRP;
#endif
#endif
#ifdef S_IXGRP
#ifdef S_IXGRP
  if (mode & FILEIO_S_IXGRP)
  if (mode & FILEIO_S_IXGRP)
    hmode |= S_IXGRP;
    hmode |= S_IXGRP;
#endif
#endif
  if (mode & FILEIO_S_IROTH)
  if (mode & FILEIO_S_IROTH)
    hmode |= S_IROTH;
    hmode |= S_IROTH;
#ifdef S_IWOTH
#ifdef S_IWOTH
  if (mode & FILEIO_S_IWOTH)
  if (mode & FILEIO_S_IWOTH)
    hmode |= S_IWOTH;
    hmode |= S_IWOTH;
#endif
#endif
#ifdef S_IXOTH
#ifdef S_IXOTH
  if (mode & FILEIO_S_IXOTH)
  if (mode & FILEIO_S_IXOTH)
    hmode |= S_IXOTH;
    hmode |= S_IXOTH;
#endif
#endif
  return hmode;
  return hmode;
}
}
 
 
static LONGEST
static LONGEST
remote_fileio_mode_to_target (mode_t mode)
remote_fileio_mode_to_target (mode_t mode)
{
{
  mode_t tmode = 0;
  mode_t tmode = 0;
 
 
  if (S_ISREG(mode))
  if (S_ISREG(mode))
    tmode |= FILEIO_S_IFREG;
    tmode |= FILEIO_S_IFREG;
  if (S_ISDIR(mode))
  if (S_ISDIR(mode))
    tmode |= FILEIO_S_IFDIR;
    tmode |= FILEIO_S_IFDIR;
  if (S_ISCHR(mode))
  if (S_ISCHR(mode))
    tmode |= FILEIO_S_IFCHR;
    tmode |= FILEIO_S_IFCHR;
  if (mode & S_IRUSR)
  if (mode & S_IRUSR)
    tmode |= FILEIO_S_IRUSR;
    tmode |= FILEIO_S_IRUSR;
  if (mode & S_IWUSR)
  if (mode & S_IWUSR)
    tmode |= FILEIO_S_IWUSR;
    tmode |= FILEIO_S_IWUSR;
  if (mode & S_IXUSR)
  if (mode & S_IXUSR)
    tmode |= FILEIO_S_IXUSR;
    tmode |= FILEIO_S_IXUSR;
#ifdef S_IRGRP
#ifdef S_IRGRP
  if (mode & S_IRGRP)
  if (mode & S_IRGRP)
    tmode |= FILEIO_S_IRGRP;
    tmode |= FILEIO_S_IRGRP;
#endif
#endif
#ifdef S_IWRGRP
#ifdef S_IWRGRP
  if (mode & S_IWGRP)
  if (mode & S_IWGRP)
    tmode |= FILEIO_S_IWGRP;
    tmode |= FILEIO_S_IWGRP;
#endif
#endif
#ifdef S_IXGRP
#ifdef S_IXGRP
  if (mode & S_IXGRP)
  if (mode & S_IXGRP)
    tmode |= FILEIO_S_IXGRP;
    tmode |= FILEIO_S_IXGRP;
#endif
#endif
  if (mode & S_IROTH)
  if (mode & S_IROTH)
    tmode |= FILEIO_S_IROTH;
    tmode |= FILEIO_S_IROTH;
#ifdef S_IWOTH
#ifdef S_IWOTH
  if (mode & S_IWOTH)
  if (mode & S_IWOTH)
    tmode |= FILEIO_S_IWOTH;
    tmode |= FILEIO_S_IWOTH;
#endif
#endif
#ifdef S_IXOTH
#ifdef S_IXOTH
  if (mode & S_IXOTH)
  if (mode & S_IXOTH)
    tmode |= FILEIO_S_IXOTH;
    tmode |= FILEIO_S_IXOTH;
#endif
#endif
  return tmode;
  return tmode;
}
}
 
 
static int
static int
remote_fileio_errno_to_target (int error)
remote_fileio_errno_to_target (int error)
{
{
  switch (error)
  switch (error)
    {
    {
      case EPERM:
      case EPERM:
        return FILEIO_EPERM;
        return FILEIO_EPERM;
      case ENOENT:
      case ENOENT:
        return FILEIO_ENOENT;
        return FILEIO_ENOENT;
      case EINTR:
      case EINTR:
        return FILEIO_EINTR;
        return FILEIO_EINTR;
      case EIO:
      case EIO:
        return FILEIO_EIO;
        return FILEIO_EIO;
      case EBADF:
      case EBADF:
        return FILEIO_EBADF;
        return FILEIO_EBADF;
      case EACCES:
      case EACCES:
        return FILEIO_EACCES;
        return FILEIO_EACCES;
      case EFAULT:
      case EFAULT:
        return FILEIO_EFAULT;
        return FILEIO_EFAULT;
      case EBUSY:
      case EBUSY:
        return FILEIO_EBUSY;
        return FILEIO_EBUSY;
      case EEXIST:
      case EEXIST:
        return FILEIO_EEXIST;
        return FILEIO_EEXIST;
      case ENODEV:
      case ENODEV:
        return FILEIO_ENODEV;
        return FILEIO_ENODEV;
      case ENOTDIR:
      case ENOTDIR:
        return FILEIO_ENOTDIR;
        return FILEIO_ENOTDIR;
      case EISDIR:
      case EISDIR:
        return FILEIO_EISDIR;
        return FILEIO_EISDIR;
      case EINVAL:
      case EINVAL:
        return FILEIO_EINVAL;
        return FILEIO_EINVAL;
      case ENFILE:
      case ENFILE:
        return FILEIO_ENFILE;
        return FILEIO_ENFILE;
      case EMFILE:
      case EMFILE:
        return FILEIO_EMFILE;
        return FILEIO_EMFILE;
      case EFBIG:
      case EFBIG:
        return FILEIO_EFBIG;
        return FILEIO_EFBIG;
      case ENOSPC:
      case ENOSPC:
        return FILEIO_ENOSPC;
        return FILEIO_ENOSPC;
      case ESPIPE:
      case ESPIPE:
        return FILEIO_ESPIPE;
        return FILEIO_ESPIPE;
      case EROFS:
      case EROFS:
        return FILEIO_EROFS;
        return FILEIO_EROFS;
      case ENOSYS:
      case ENOSYS:
        return FILEIO_ENOSYS;
        return FILEIO_ENOSYS;
      case ENAMETOOLONG:
      case ENAMETOOLONG:
        return FILEIO_ENAMETOOLONG;
        return FILEIO_ENAMETOOLONG;
    }
    }
  return FILEIO_EUNKNOWN;
  return FILEIO_EUNKNOWN;
}
}
 
 
static int
static int
remote_fileio_seek_flag_to_host (long num, int *flag)
remote_fileio_seek_flag_to_host (long num, int *flag)
{
{
  if (!flag)
  if (!flag)
    return 0;
    return 0;
  switch (num)
  switch (num)
    {
    {
      case FILEIO_SEEK_SET:
      case FILEIO_SEEK_SET:
        *flag = SEEK_SET;
        *flag = SEEK_SET;
        break;
        break;
      case FILEIO_SEEK_CUR:
      case FILEIO_SEEK_CUR:
        *flag =  SEEK_CUR;
        *flag =  SEEK_CUR;
        break;
        break;
      case FILEIO_SEEK_END:
      case FILEIO_SEEK_END:
        *flag =  SEEK_END;
        *flag =  SEEK_END;
        break;
        break;
      default:
      default:
        return -1;
        return -1;
    }
    }
  return 0;
  return 0;
}
}
 
 
static int
static int
remote_fileio_extract_long (char **buf, LONGEST *retlong)
remote_fileio_extract_long (char **buf, LONGEST *retlong)
{
{
  char *c;
  char *c;
  int sign = 1;
  int sign = 1;
 
 
  if (!buf || !*buf || !**buf || !retlong)
  if (!buf || !*buf || !**buf || !retlong)
    return -1;
    return -1;
  c = strchr (*buf, ',');
  c = strchr (*buf, ',');
  if (c)
  if (c)
    *c++ = '\0';
    *c++ = '\0';
  else
  else
    c = strchr (*buf, '\0');
    c = strchr (*buf, '\0');
  while (strchr ("+-", **buf))
  while (strchr ("+-", **buf))
    {
    {
      if (**buf == '-')
      if (**buf == '-')
        sign = -sign;
        sign = -sign;
      ++*buf;
      ++*buf;
    }
    }
  for (*retlong = 0; **buf; ++*buf)
  for (*retlong = 0; **buf; ++*buf)
    {
    {
      *retlong <<= 4;
      *retlong <<= 4;
      if (**buf >= '0' && **buf <= '9')
      if (**buf >= '0' && **buf <= '9')
        *retlong += **buf - '0';
        *retlong += **buf - '0';
      else if (**buf >= 'a' && **buf <= 'f')
      else if (**buf >= 'a' && **buf <= 'f')
        *retlong += **buf - 'a' + 10;
        *retlong += **buf - 'a' + 10;
      else if (**buf >= 'A' && **buf <= 'F')
      else if (**buf >= 'A' && **buf <= 'F')
        *retlong += **buf - 'A' + 10;
        *retlong += **buf - 'A' + 10;
      else
      else
        return -1;
        return -1;
    }
    }
  *retlong *= sign;
  *retlong *= sign;
  *buf = c;
  *buf = c;
  return 0;
  return 0;
}
}
 
 
static int
static int
remote_fileio_extract_int (char **buf, long *retint)
remote_fileio_extract_int (char **buf, long *retint)
{
{
  int ret;
  int ret;
  LONGEST retlong;
  LONGEST retlong;
 
 
  if (!retint)
  if (!retint)
    return -1;
    return -1;
  ret = remote_fileio_extract_long (buf, &retlong);
  ret = remote_fileio_extract_long (buf, &retlong);
  if (!ret)
  if (!ret)
    *retint = (long) retlong;
    *retint = (long) retlong;
  return ret;
  return ret;
}
}
 
 
static int
static int
remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length)
remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length)
{
{
  char *c;
  char *c;
  LONGEST retlong;
  LONGEST retlong;
 
 
  if (!buf || !*buf || !**buf || !ptrval || !length)
  if (!buf || !*buf || !**buf || !ptrval || !length)
    return -1;
    return -1;
  c = strchr (*buf, '/');
  c = strchr (*buf, '/');
  if (!c)
  if (!c)
    return -1;
    return -1;
  *c++ = '\0';
  *c++ = '\0';
  if (remote_fileio_extract_long (buf, &retlong))
  if (remote_fileio_extract_long (buf, &retlong))
    return -1;
    return -1;
  *ptrval = (CORE_ADDR) retlong;
  *ptrval = (CORE_ADDR) retlong;
  *buf = c;
  *buf = c;
  if (remote_fileio_extract_long (buf, &retlong))
  if (remote_fileio_extract_long (buf, &retlong))
    return -1;
    return -1;
  *length = (int) retlong;
  *length = (int) retlong;
  return 0;
  return 0;
}
}
 
 
/* Convert to big endian */
/* Convert to big endian */
static void
static void
remote_fileio_to_be (LONGEST num, char *buf, int bytes)
remote_fileio_to_be (LONGEST num, char *buf, int bytes)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < bytes; ++i)
  for (i = 0; i < bytes; ++i)
    buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff;
    buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff;
}
}
 
 
static void
static void
remote_fileio_to_fio_uint (long num, fio_uint_t fnum)
remote_fileio_to_fio_uint (long num, fio_uint_t fnum)
{
{
  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
}
}
 
 
static void
static void
remote_fileio_to_fio_mode (mode_t num, fio_mode_t fnum)
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);
  remote_fileio_to_be (remote_fileio_mode_to_target(num), (char *) fnum, 4);
}
}
 
 
static void
static void
remote_fileio_to_fio_time (time_t num, fio_time_t fnum)
remote_fileio_to_fio_time (time_t num, fio_time_t fnum)
{
{
  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
}
}
 
 
static void
static void
remote_fileio_to_fio_long (LONGEST num, fio_long_t fnum)
remote_fileio_to_fio_long (LONGEST num, fio_long_t fnum)
{
{
  remote_fileio_to_be (num, (char *) fnum, 8);
  remote_fileio_to_be (num, (char *) fnum, 8);
}
}
 
 
static void
static void
remote_fileio_to_fio_ulong (LONGEST num, fio_ulong_t fnum)
remote_fileio_to_fio_ulong (LONGEST num, fio_ulong_t fnum)
{
{
  remote_fileio_to_be (num, (char *) fnum, 8);
  remote_fileio_to_be (num, (char *) fnum, 8);
}
}
 
 
static void
static void
remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst)
remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst)
{
{
  LONGEST blksize;
  LONGEST blksize;
 
 
  /* `st_dev' is set in the calling function */
  /* `st_dev' is set in the calling function */
  remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino);
  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_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_nlink, fst->fst_nlink);
  remote_fileio_to_fio_uint ((long) st->st_uid, fst->fst_uid);
  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_gid, fst->fst_gid);
  remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev);
  remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev);
  remote_fileio_to_fio_ulong ((LONGEST) st->st_size, fst->fst_size);
  remote_fileio_to_fio_ulong ((LONGEST) st->st_size, fst->fst_size);
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  blksize = st->st_blksize;
  blksize = st->st_blksize;
#else
#else
  blksize = 512;
  blksize = 512;
#endif
#endif
  remote_fileio_to_fio_ulong (blksize, fst->fst_blksize);
  remote_fileio_to_fio_ulong (blksize, fst->fst_blksize);
#if HAVE_STRUCT_STAT_ST_BLOCKS
#if HAVE_STRUCT_STAT_ST_BLOCKS
  remote_fileio_to_fio_ulong ((LONGEST) st->st_blocks, fst->fst_blocks);
  remote_fileio_to_fio_ulong ((LONGEST) st->st_blocks, fst->fst_blocks);
#else
#else
  /* FIXME: This is correct for DJGPP, but other systems that don't
  /* FIXME: This is correct for DJGPP, but other systems that don't
     have st_blocks, if any, might prefer 512 instead of st_blksize.
     have st_blocks, if any, might prefer 512 instead of st_blksize.
     (eliz, 30-12-2003)  */
     (eliz, 30-12-2003)  */
  remote_fileio_to_fio_ulong (((LONGEST) st->st_size + blksize - 1)
  remote_fileio_to_fio_ulong (((LONGEST) st->st_size + blksize - 1)
                              / blksize,
                              / blksize,
                              fst->fst_blocks);
                              fst->fst_blocks);
#endif
#endif
  remote_fileio_to_fio_time (st->st_atime, fst->fst_atime);
  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_mtime, fst->fst_mtime);
  remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime);
  remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime);
}
}
 
 
static void
static void
remote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv)
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_time (tv->tv_sec, ftv->ftv_sec);
  remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec);
  remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec);
}
}
 
 
static int remote_fio_ctrl_c_flag = 0;
static int remote_fio_ctrl_c_flag = 0;
static int remote_fio_no_longjmp = 0;
static int remote_fio_no_longjmp = 0;
 
 
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
static struct sigaction remote_fio_sa;
static struct sigaction remote_fio_sa;
static struct sigaction remote_fio_osa;
static struct sigaction remote_fio_osa;
#else
#else
static void (*remote_fio_ofunc)(int);
static void (*remote_fio_ofunc)(int);
#endif
#endif
 
 
static void
static void
remote_fileio_sig_init (void)
remote_fileio_sig_init (void)
{
{
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
  remote_fio_sa.sa_handler = SIG_IGN;
  remote_fio_sa.sa_handler = SIG_IGN;
  sigemptyset (&remote_fio_sa.sa_mask);
  sigemptyset (&remote_fio_sa.sa_mask);
  remote_fio_sa.sa_flags = 0;
  remote_fio_sa.sa_flags = 0;
  sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa);
  sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa);
#else
#else
  remote_fio_ofunc = signal (SIGINT, SIG_IGN);
  remote_fio_ofunc = signal (SIGINT, SIG_IGN);
#endif
#endif
}
}
 
 
static void
static void
remote_fileio_sig_set (void (*sigint_func)(int))
remote_fileio_sig_set (void (*sigint_func)(int))
{
{
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
  remote_fio_sa.sa_handler = sigint_func;
  remote_fio_sa.sa_handler = sigint_func;
  sigemptyset (&remote_fio_sa.sa_mask);
  sigemptyset (&remote_fio_sa.sa_mask);
  remote_fio_sa.sa_flags = 0;
  remote_fio_sa.sa_flags = 0;
  sigaction (SIGINT, &remote_fio_sa, NULL);
  sigaction (SIGINT, &remote_fio_sa, NULL);
#else
#else
  signal (SIGINT, sigint_func);
  signal (SIGINT, sigint_func);
#endif
#endif
}
}
 
 
static void
static void
remote_fileio_sig_exit (void)
remote_fileio_sig_exit (void)
{
{
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
  sigaction (SIGINT, &remote_fio_osa, NULL);
  sigaction (SIGINT, &remote_fio_osa, NULL);
#else
#else
  signal (SIGINT, remote_fio_ofunc);
  signal (SIGINT, remote_fio_ofunc);
#endif
#endif
}
}
 
 
static void
static void
async_remote_fileio_interrupt (gdb_client_data arg)
async_remote_fileio_interrupt (gdb_client_data arg)
{
{
  deprecated_throw_reason (RETURN_QUIT);
  deprecated_throw_reason (RETURN_QUIT);
}
}
 
 
static void
static void
remote_fileio_ctrl_c_signal_handler (int signo)
remote_fileio_ctrl_c_signal_handler (int signo)
{
{
  remote_fileio_sig_set (SIG_IGN);
  remote_fileio_sig_set (SIG_IGN);
  remote_fio_ctrl_c_flag = 1;
  remote_fio_ctrl_c_flag = 1;
  if (!remote_fio_no_longjmp)
  if (!remote_fio_no_longjmp)
    gdb_call_async_signal_handler (sigint_fileio_token, 1);
    gdb_call_async_signal_handler (sigint_fileio_token, 1);
  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
}
}
 
 
static void
static void
remote_fileio_reply (int retcode, int error)
remote_fileio_reply (int retcode, int error)
{
{
  char buf[32];
  char buf[32];
 
 
  remote_fileio_sig_set (SIG_IGN);
  remote_fileio_sig_set (SIG_IGN);
  strcpy (buf, "F");
  strcpy (buf, "F");
  if (retcode < 0)
  if (retcode < 0)
    {
    {
      strcat (buf, "-");
      strcat (buf, "-");
      retcode = -retcode;
      retcode = -retcode;
    }
    }
  sprintf (buf + strlen (buf), "%x", retcode);
  sprintf (buf + strlen (buf), "%x", retcode);
  if (error || remote_fio_ctrl_c_flag)
  if (error || remote_fio_ctrl_c_flag)
    {
    {
      if (error && remote_fio_ctrl_c_flag)
      if (error && remote_fio_ctrl_c_flag)
        error = FILEIO_EINTR;
        error = FILEIO_EINTR;
      if (error < 0)
      if (error < 0)
        {
        {
          strcat (buf, "-");
          strcat (buf, "-");
          error = -error;
          error = -error;
        }
        }
      sprintf (buf + strlen (buf), ",%x", error);
      sprintf (buf + strlen (buf), ",%x", error);
      if (remote_fio_ctrl_c_flag)
      if (remote_fio_ctrl_c_flag)
        strcat (buf, ",C");
        strcat (buf, ",C");
    }
    }
  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
  putpkt (buf);
  putpkt (buf);
}
}
 
 
static void
static void
remote_fileio_ioerror (void)
remote_fileio_ioerror (void)
{
{
  remote_fileio_reply (-1, FILEIO_EIO);
  remote_fileio_reply (-1, FILEIO_EIO);
}
}
 
 
static void
static void
remote_fileio_badfd (void)
remote_fileio_badfd (void)
{
{
  remote_fileio_reply (-1, FILEIO_EBADF);
  remote_fileio_reply (-1, FILEIO_EBADF);
}
}
 
 
static void
static void
remote_fileio_return_errno (int retcode)
remote_fileio_return_errno (int retcode)
{
{
  remote_fileio_reply (retcode,
  remote_fileio_reply (retcode,
                       retcode < 0 ? remote_fileio_errno_to_target (errno) : 0);
                       retcode < 0 ? remote_fileio_errno_to_target (errno) : 0);
}
}
 
 
static void
static void
remote_fileio_return_success (int retcode)
remote_fileio_return_success (int retcode)
{
{
  remote_fileio_reply (retcode, 0);
  remote_fileio_reply (retcode, 0);
}
}
 
 
/* Wrapper function for remote_write_bytes() which has the disadvantage to
/* Wrapper function for remote_write_bytes() which has the disadvantage to
   write only one packet, regardless of the requested number of bytes to
   write only one packet, regardless of the requested number of bytes to
   transfer.  This wrapper calls remote_write_bytes() as often as needed. */
   transfer.  This wrapper calls remote_write_bytes() as often as needed. */
static int
static int
remote_fileio_write_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
remote_fileio_write_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
{
{
  int ret = 0, written;
  int ret = 0, written;
 
 
  while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0)
  while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0)
    {
    {
      len -= written;
      len -= written;
      memaddr += written;
      memaddr += written;
      myaddr += written;
      myaddr += written;
      ret += written;
      ret += written;
    }
    }
  return ret;
  return ret;
}
}
 
 
static void
static void
remote_fileio_func_open (char *buf)
remote_fileio_func_open (char *buf)
{
{
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int length, retlength;
  int length, retlength;
  long num;
  long num;
  int flags, fd;
  int flags, fd;
  mode_t mode;
  mode_t mode;
  char *pathname;
  char *pathname;
  struct stat st;
  struct stat st;
 
 
  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  /* 2. Parameter: open flags */
  /* 2. Parameter: open flags */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  flags = remote_fileio_oflags_to_host (num);
  flags = remote_fileio_oflags_to_host (num);
  /* 3. Parameter: open mode */
  /* 3. Parameter: open mode */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  mode = remote_fileio_mode_to_host (num, 1);
  mode = remote_fileio_mode_to_host (num, 1);
 
 
  /* Request pathname using 'm' packet */
  /* Request pathname using 'm' packet */
  pathname = alloca (length);
  pathname = alloca (length);
  retlength = remote_read_bytes (ptrval, (gdb_byte *) pathname, length);
  retlength = remote_read_bytes (ptrval, (gdb_byte *) pathname, length);
  if (retlength != length)
  if (retlength != length)
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* Check if pathname exists and is not a regular file or directory.  If so,
  /* 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
     return an appropriate error code.  Same for trying to open directories
     for writing. */
     for writing. */
  if (!stat (pathname, &st))
  if (!stat (pathname, &st))
    {
    {
      if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
      if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
        {
        {
          remote_fileio_reply (-1, FILEIO_ENODEV);
          remote_fileio_reply (-1, FILEIO_ENODEV);
          return;
          return;
        }
        }
      if (S_ISDIR (st.st_mode)
      if (S_ISDIR (st.st_mode)
          && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR))
          && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR))
        {
        {
          remote_fileio_reply (-1, FILEIO_EISDIR);
          remote_fileio_reply (-1, FILEIO_EISDIR);
          return;
          return;
        }
        }
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  fd = open (pathname, flags, mode);
  fd = open (pathname, flags, mode);
  if (fd < 0)
  if (fd < 0)
    {
    {
      remote_fileio_return_errno (-1);
      remote_fileio_return_errno (-1);
      return;
      return;
    }
    }
 
 
  fd = remote_fileio_fd_to_targetfd (fd);
  fd = remote_fileio_fd_to_targetfd (fd);
  remote_fileio_return_success (fd);
  remote_fileio_return_success (fd);
}
}
 
 
static void
static void
remote_fileio_func_close (char *buf)
remote_fileio_func_close (char *buf)
{
{
  long num;
  long num;
  int fd;
  int fd;
 
 
  /* Parameter: file descriptor */
  /* Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  fd = remote_fileio_map_fd ((int) num);
  fd = remote_fileio_map_fd ((int) num);
  if (fd == FIO_FD_INVALID)
  if (fd == FIO_FD_INVALID)
    {
    {
      remote_fileio_badfd ();
      remote_fileio_badfd ();
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd))
  if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd))
    remote_fileio_return_errno (-1);
    remote_fileio_return_errno (-1);
  remote_fileio_close_target_fd ((int) num);
  remote_fileio_close_target_fd ((int) num);
  remote_fileio_return_success (0);
  remote_fileio_return_success (0);
}
}
 
 
static void
static void
remote_fileio_func_read (char *buf)
remote_fileio_func_read (char *buf)
{
{
  long target_fd, num;
  long target_fd, num;
  LONGEST lnum;
  LONGEST lnum;
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int fd, ret, retlength;
  int fd, ret, retlength;
  gdb_byte *buffer;
  gdb_byte *buffer;
  size_t length;
  size_t length;
  off_t old_offset, new_offset;
  off_t old_offset, new_offset;
 
 
  /* 1. Parameter: file descriptor */
  /* 1. Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &target_fd))
  if (remote_fileio_extract_int (&buf, &target_fd))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  fd = remote_fileio_map_fd ((int) target_fd);
  fd = remote_fileio_map_fd ((int) target_fd);
  if (fd == FIO_FD_INVALID)
  if (fd == FIO_FD_INVALID)
    {
    {
      remote_fileio_badfd ();
      remote_fileio_badfd ();
      return;
      return;
    }
    }
  /* 2. Parameter: buffer pointer */
  /* 2. Parameter: buffer pointer */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  ptrval = (CORE_ADDR) lnum;
  ptrval = (CORE_ADDR) lnum;
  /* 3. Parameter: buffer length */
  /* 3. Parameter: buffer length */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  length = (size_t) num;
  length = (size_t) num;
 
 
  switch (fd)
  switch (fd)
    {
    {
      case FIO_FD_CONSOLE_OUT:
      case FIO_FD_CONSOLE_OUT:
        remote_fileio_badfd ();
        remote_fileio_badfd ();
        return;
        return;
      case FIO_FD_CONSOLE_IN:
      case FIO_FD_CONSOLE_IN:
        {
        {
          static char *remaining_buf = NULL;
          static char *remaining_buf = NULL;
          static int remaining_length = 0;
          static int remaining_length = 0;
 
 
          buffer = (gdb_byte *) xmalloc (16384);
          buffer = (gdb_byte *) xmalloc (16384);
          if (remaining_buf)
          if (remaining_buf)
            {
            {
              remote_fio_no_longjmp = 1;
              remote_fio_no_longjmp = 1;
              if (remaining_length > length)
              if (remaining_length > length)
                {
                {
                  memcpy (buffer, remaining_buf, length);
                  memcpy (buffer, remaining_buf, length);
                  memmove (remaining_buf, remaining_buf + length,
                  memmove (remaining_buf, remaining_buf + length,
                           remaining_length - length);
                           remaining_length - length);
                  remaining_length -= length;
                  remaining_length -= length;
                  ret = length;
                  ret = length;
                }
                }
              else
              else
                {
                {
                  memcpy (buffer, remaining_buf, remaining_length);
                  memcpy (buffer, remaining_buf, remaining_length);
                  xfree (remaining_buf);
                  xfree (remaining_buf);
                  remaining_buf = NULL;
                  remaining_buf = NULL;
                  ret = remaining_length;
                  ret = remaining_length;
                }
                }
            }
            }
          else
          else
            {
            {
              /* Windows (at least XP and Server 2003) has difficulty
              /* Windows (at least XP and Server 2003) has difficulty
                 with large reads from consoles.  If a handle is
                 with large reads from consoles.  If a handle is
                 backed by a real console device, overly large reads
                 backed by a real console device, overly large reads
                 from the handle will fail and set errno == ENOMEM.
                 from the handle will fail and set errno == ENOMEM.
                 On a Windows Server 2003 system where I tested,
                 On a Windows Server 2003 system where I tested,
                 reading 26608 bytes from the console was OK, but
                 reading 26608 bytes from the console was OK, but
                 anything above 26609 bytes would fail.  The limit has
                 anything above 26609 bytes would fail.  The limit has
                 been observed to vary on different systems.  So, we
                 been observed to vary on different systems.  So, we
                 limit this read to something smaller than that - by a
                 limit this read to something smaller than that - by a
                 safe margin, in case the limit depends on system
                 safe margin, in case the limit depends on system
                 resources or version.  */
                 resources or version.  */
              ret = ui_file_read (gdb_stdtargin, (char *) buffer, 16383);
              ret = ui_file_read (gdb_stdtargin, (char *) buffer, 16383);
              remote_fio_no_longjmp = 1;
              remote_fio_no_longjmp = 1;
              if (ret > 0 && (size_t)ret > length)
              if (ret > 0 && (size_t)ret > length)
                {
                {
                  remaining_buf = (char *) xmalloc (ret - length);
                  remaining_buf = (char *) xmalloc (ret - length);
                  remaining_length = ret - length;
                  remaining_length = ret - length;
                  memcpy (remaining_buf, buffer + length, remaining_length);
                  memcpy (remaining_buf, buffer + length, remaining_length);
                  ret = length;
                  ret = length;
                }
                }
            }
            }
        }
        }
        break;
        break;
      default:
      default:
        buffer = (gdb_byte *) xmalloc (length);
        buffer = (gdb_byte *) xmalloc (length);
        /* POSIX defines EINTR behaviour of read in a weird way.  It's allowed
        /* 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
           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...
           has been corrected in SUSv2 but that doesn't help us much...
           Therefore a complete solution must check how many bytes have been
           Therefore a complete solution must check how many bytes have been
           read on EINTR to return a more reliable value to the target */
           read on EINTR to return a more reliable value to the target */
        old_offset = lseek (fd, 0, SEEK_CUR);
        old_offset = lseek (fd, 0, SEEK_CUR);
        remote_fio_no_longjmp = 1;
        remote_fio_no_longjmp = 1;
        ret = read (fd, buffer, length);
        ret = read (fd, buffer, length);
        if (ret < 0 && errno == EINTR)
        if (ret < 0 && errno == EINTR)
          {
          {
            new_offset = lseek (fd, 0, SEEK_CUR);
            new_offset = lseek (fd, 0, SEEK_CUR);
            /* If some data has been read, return the number of bytes read.
            /* If some data has been read, return the number of bytes read.
               The Ctrl-C flag is set in remote_fileio_reply() anyway */
               The Ctrl-C flag is set in remote_fileio_reply() anyway */
            if (old_offset != new_offset)
            if (old_offset != new_offset)
              ret = new_offset - old_offset;
              ret = new_offset - old_offset;
          }
          }
        break;
        break;
    }
    }
 
 
  if (ret > 0)
  if (ret > 0)
    {
    {
      retlength = remote_fileio_write_bytes (ptrval, buffer, ret);
      retlength = remote_fileio_write_bytes (ptrval, buffer, ret);
      if (retlength != ret)
      if (retlength != ret)
        ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */
        ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */
    }
    }
 
 
  if (ret < 0)
  if (ret < 0)
    remote_fileio_return_errno (-1);
    remote_fileio_return_errno (-1);
  else
  else
    remote_fileio_return_success (ret);
    remote_fileio_return_success (ret);
 
 
  xfree (buffer);
  xfree (buffer);
}
}
 
 
static void
static void
remote_fileio_func_write (char *buf)
remote_fileio_func_write (char *buf)
{
{
  long target_fd, num;
  long target_fd, num;
  LONGEST lnum;
  LONGEST lnum;
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int fd, ret, retlength;
  int fd, ret, retlength;
  gdb_byte *buffer;
  gdb_byte *buffer;
  size_t length;
  size_t length;
 
 
  /* 1. Parameter: file descriptor */
  /* 1. Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &target_fd))
  if (remote_fileio_extract_int (&buf, &target_fd))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  fd = remote_fileio_map_fd ((int) target_fd);
  fd = remote_fileio_map_fd ((int) target_fd);
  if (fd == FIO_FD_INVALID)
  if (fd == FIO_FD_INVALID)
    {
    {
      remote_fileio_badfd ();
      remote_fileio_badfd ();
      return;
      return;
    }
    }
  /* 2. Parameter: buffer pointer */
  /* 2. Parameter: buffer pointer */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  ptrval = (CORE_ADDR) lnum;
  ptrval = (CORE_ADDR) lnum;
  /* 3. Parameter: buffer length */
  /* 3. Parameter: buffer length */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  length = (size_t) num;
  length = (size_t) num;
 
 
  buffer = (gdb_byte *) xmalloc (length);
  buffer = (gdb_byte *) xmalloc (length);
  retlength = remote_read_bytes (ptrval, buffer, length);
  retlength = remote_read_bytes (ptrval, buffer, length);
  if (retlength != length)
  if (retlength != length)
    {
    {
      xfree (buffer);
      xfree (buffer);
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  switch (fd)
  switch (fd)
    {
    {
      case FIO_FD_CONSOLE_IN:
      case FIO_FD_CONSOLE_IN:
        remote_fileio_badfd ();
        remote_fileio_badfd ();
        xfree (buffer);
        xfree (buffer);
        return;
        return;
      case FIO_FD_CONSOLE_OUT:
      case FIO_FD_CONSOLE_OUT:
        ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr,
        ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr,
                       (char *) buffer, length);
                       (char *) buffer, length);
        gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr);
        gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr);
        ret = length;
        ret = length;
        break;
        break;
      default:
      default:
        ret = write (fd, buffer, length);
        ret = write (fd, buffer, length);
        if (ret < 0 && errno == EACCES)
        if (ret < 0 && errno == EACCES)
          errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/
          errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/
        break;
        break;
    }
    }
 
 
  if (ret < 0)
  if (ret < 0)
    remote_fileio_return_errno (-1);
    remote_fileio_return_errno (-1);
  else
  else
    remote_fileio_return_success (ret);
    remote_fileio_return_success (ret);
 
 
  xfree (buffer);
  xfree (buffer);
}
}
 
 
static void
static void
remote_fileio_func_lseek (char *buf)
remote_fileio_func_lseek (char *buf)
{
{
  long num;
  long num;
  LONGEST lnum;
  LONGEST lnum;
  int fd, flag;
  int fd, flag;
  off_t offset, ret;
  off_t offset, ret;
 
 
  /* 1. Parameter: file descriptor */
  /* 1. Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  fd = remote_fileio_map_fd ((int) num);
  fd = remote_fileio_map_fd ((int) num);
  if (fd == FIO_FD_INVALID)
  if (fd == FIO_FD_INVALID)
    {
    {
      remote_fileio_badfd ();
      remote_fileio_badfd ();
      return;
      return;
    }
    }
  else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
  else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
    {
    {
      remote_fileio_reply (-1, FILEIO_ESPIPE);
      remote_fileio_reply (-1, FILEIO_ESPIPE);
      return;
      return;
    }
    }
 
 
  /* 2. Parameter: offset */
  /* 2. Parameter: offset */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  offset = (off_t) lnum;
  offset = (off_t) lnum;
  /* 3. Parameter: flag */
  /* 3. Parameter: flag */
  if (remote_fileio_extract_int (&buf, &num))
  if (remote_fileio_extract_int (&buf, &num))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  if (remote_fileio_seek_flag_to_host (num, &flag))
  if (remote_fileio_seek_flag_to_host (num, &flag))
    {
    {
      remote_fileio_reply (-1, FILEIO_EINVAL);
      remote_fileio_reply (-1, FILEIO_EINVAL);
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  ret = lseek (fd, offset, flag);
  ret = lseek (fd, offset, flag);
 
 
  if (ret == (off_t) -1)
  if (ret == (off_t) -1)
    remote_fileio_return_errno (-1);
    remote_fileio_return_errno (-1);
  else
  else
    remote_fileio_return_success (ret);
    remote_fileio_return_success (ret);
}
}
 
 
static void
static void
remote_fileio_func_rename (char *buf)
remote_fileio_func_rename (char *buf)
{
{
  CORE_ADDR old_ptr, new_ptr;
  CORE_ADDR old_ptr, new_ptr;
  int old_len, new_len, retlength;
  int old_len, new_len, retlength;
  char *oldpath, *newpath;
  char *oldpath, *newpath;
  int ret, of, nf;
  int ret, of, nf;
  struct stat ost, nst;
  struct stat ost, nst;
 
 
  /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */
  /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &old_ptr, &old_len))
  if (remote_fileio_extract_ptr_w_len (&buf, &old_ptr, &old_len))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* 2. Parameter: Ptr to newpath / length incl. trailing zero */
  /* 2. Parameter: Ptr to newpath / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &new_ptr, &new_len))
  if (remote_fileio_extract_ptr_w_len (&buf, &new_ptr, &new_len))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* Request oldpath using 'm' packet */
  /* Request oldpath using 'm' packet */
  oldpath = alloca (old_len);
  oldpath = alloca (old_len);
  retlength = remote_read_bytes (old_ptr, (gdb_byte *) oldpath, old_len);
  retlength = remote_read_bytes (old_ptr, (gdb_byte *) oldpath, old_len);
  if (retlength != old_len)
  if (retlength != old_len)
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* Request newpath using 'm' packet */
  /* Request newpath using 'm' packet */
  newpath = alloca (new_len);
  newpath = alloca (new_len);
  retlength = remote_read_bytes (new_ptr, (gdb_byte *) newpath, new_len);
  retlength = remote_read_bytes (new_ptr, (gdb_byte *) newpath, new_len);
  if (retlength != new_len)
  if (retlength != new_len)
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* Only operate on regular files and directories */
  /* Only operate on regular files and directories */
  of = stat (oldpath, &ost);
  of = stat (oldpath, &ost);
  nf = stat (newpath, &nst);
  nf = stat (newpath, &nst);
  if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
  if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
      || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
      || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
    {
    {
      remote_fileio_reply (-1, FILEIO_EACCES);
      remote_fileio_reply (-1, FILEIO_EACCES);
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  ret = rename (oldpath, newpath);
  ret = rename (oldpath, newpath);
 
 
  if (ret == -1)
  if (ret == -1)
    {
    {
      /* Special case: newpath is a non-empty directory.  Some systems
      /* Special case: newpath is a non-empty directory.  Some systems
         return ENOTEMPTY, some return EEXIST.  We coerce that to be
         return ENOTEMPTY, some return EEXIST.  We coerce that to be
         always EEXIST. */
         always EEXIST. */
      if (errno == ENOTEMPTY)
      if (errno == ENOTEMPTY)
        errno = EEXIST;
        errno = EEXIST;
#ifdef __CYGWIN__
#ifdef __CYGWIN__
      /* Workaround some Cygwin problems with correct errnos. */
      /* Workaround some Cygwin problems with correct errnos. */
      if (errno == EACCES)
      if (errno == EACCES)
        {
        {
          if (!of && !nf && S_ISDIR (nst.st_mode))
          if (!of && !nf && S_ISDIR (nst.st_mode))
            {
            {
              if (S_ISREG (ost.st_mode))
              if (S_ISREG (ost.st_mode))
                errno = EISDIR;
                errno = EISDIR;
              else
              else
                {
                {
                  char oldfullpath[PATH_MAX + 1];
                  char oldfullpath[PATH_MAX + 1];
                  char newfullpath[PATH_MAX + 1];
                  char newfullpath[PATH_MAX + 1];
                  int len;
                  int len;
 
 
                  cygwin_conv_to_full_posix_path (oldpath, oldfullpath);
                  cygwin_conv_to_full_posix_path (oldpath, oldfullpath);
                  cygwin_conv_to_full_posix_path (newpath, newfullpath);
                  cygwin_conv_to_full_posix_path (newpath, newfullpath);
                  len = strlen (oldfullpath);
                  len = strlen (oldfullpath);
                  if (newfullpath[len] == '/'
                  if (newfullpath[len] == '/'
                      && !strncmp (oldfullpath, newfullpath, len))
                      && !strncmp (oldfullpath, newfullpath, len))
                    errno = EINVAL;
                    errno = EINVAL;
                  else
                  else
                    errno = EEXIST;
                    errno = EEXIST;
                }
                }
            }
            }
        }
        }
#endif
#endif
 
 
      remote_fileio_return_errno (-1);
      remote_fileio_return_errno (-1);
    }
    }
  else
  else
    remote_fileio_return_success (ret);
    remote_fileio_return_success (ret);
}
}
 
 
static void
static void
remote_fileio_func_unlink (char *buf)
remote_fileio_func_unlink (char *buf)
{
{
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int length, retlength;
  int length, retlength;
  char *pathname;
  char *pathname;
  int ret;
  int ret;
  struct stat st;
  struct stat st;
 
 
  /* Parameter: Ptr to pathname / length incl. trailing zero */
  /* Parameter: Ptr to pathname / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  /* Request pathname using 'm' packet */
  /* Request pathname using 'm' packet */
  pathname = alloca (length);
  pathname = alloca (length);
  retlength = remote_read_bytes (ptrval, (gdb_byte *) pathname, length);
  retlength = remote_read_bytes (ptrval, (gdb_byte *) pathname, length);
  if (retlength != length)
  if (retlength != length)
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* Only operate on regular files (and directories, which allows to return
  /* Only operate on regular files (and directories, which allows to return
     the correct return code) */
     the correct return code) */
  if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
  if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
    {
    {
      remote_fileio_reply (-1, FILEIO_ENODEV);
      remote_fileio_reply (-1, FILEIO_ENODEV);
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  ret = unlink (pathname);
  ret = unlink (pathname);
 
 
  if (ret == -1)
  if (ret == -1)
    remote_fileio_return_errno (-1);
    remote_fileio_return_errno (-1);
  else
  else
    remote_fileio_return_success (ret);
    remote_fileio_return_success (ret);
}
}
 
 
static void
static void
remote_fileio_func_stat (char *buf)
remote_fileio_func_stat (char *buf)
{
{
  CORE_ADDR statptr, nameptr;
  CORE_ADDR statptr, nameptr;
  int ret, namelength, retlength;
  int ret, namelength, retlength;
  char *pathname;
  char *pathname;
  LONGEST lnum;
  LONGEST lnum;
  struct stat st;
  struct stat st;
  struct fio_stat fst;
  struct fio_stat fst;
 
 
  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &nameptr, &namelength))
  if (remote_fileio_extract_ptr_w_len (&buf, &nameptr, &namelength))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  /* 2. Parameter: Ptr to struct stat */
  /* 2. Parameter: Ptr to struct stat */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  statptr = (CORE_ADDR) lnum;
  statptr = (CORE_ADDR) lnum;
 
 
  /* Request pathname using 'm' packet */
  /* Request pathname using 'm' packet */
  pathname = alloca (namelength);
  pathname = alloca (namelength);
  retlength = remote_read_bytes (nameptr, (gdb_byte *) pathname, namelength);
  retlength = remote_read_bytes (nameptr, (gdb_byte *) pathname, namelength);
  if (retlength != namelength)
  if (retlength != namelength)
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  ret = stat (pathname, &st);
  ret = stat (pathname, &st);
 
 
  if (ret == -1)
  if (ret == -1)
    {
    {
      remote_fileio_return_errno (-1);
      remote_fileio_return_errno (-1);
      return;
      return;
    }
    }
  /* Only operate on regular files and directories */
  /* Only operate on regular files and directories */
  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
    {
    {
      remote_fileio_reply (-1, FILEIO_EACCES);
      remote_fileio_reply (-1, FILEIO_EACCES);
      return;
      return;
    }
    }
  if (statptr)
  if (statptr)
    {
    {
      remote_fileio_to_fio_stat (&st, &fst);
      remote_fileio_to_fio_stat (&st, &fst);
      remote_fileio_to_fio_uint (0, fst.fst_dev);
      remote_fileio_to_fio_uint (0, fst.fst_dev);
 
 
      retlength = remote_fileio_write_bytes (statptr,
      retlength = remote_fileio_write_bytes (statptr,
                                             (gdb_byte *) &fst, sizeof fst);
                                             (gdb_byte *) &fst, sizeof fst);
      if (retlength != sizeof fst)
      if (retlength != sizeof fst)
        {
        {
          remote_fileio_return_errno (-1);
          remote_fileio_return_errno (-1);
          return;
          return;
        }
        }
    }
    }
  remote_fileio_return_success (ret);
  remote_fileio_return_success (ret);
}
}
 
 
static void
static void
remote_fileio_func_fstat (char *buf)
remote_fileio_func_fstat (char *buf)
{
{
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int fd, ret, retlength;
  int fd, ret, retlength;
  long target_fd;
  long target_fd;
  LONGEST lnum;
  LONGEST lnum;
  struct stat st;
  struct stat st;
  struct fio_stat fst;
  struct fio_stat fst;
  struct timeval tv;
  struct timeval tv;
 
 
  /* 1. Parameter: file descriptor */
  /* 1. Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &target_fd))
  if (remote_fileio_extract_int (&buf, &target_fd))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  fd = remote_fileio_map_fd ((int) target_fd);
  fd = remote_fileio_map_fd ((int) target_fd);
  if (fd == FIO_FD_INVALID)
  if (fd == FIO_FD_INVALID)
    {
    {
      remote_fileio_badfd ();
      remote_fileio_badfd ();
      return;
      return;
    }
    }
  /* 2. Parameter: Ptr to struct stat */
  /* 2. Parameter: Ptr to struct stat */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  ptrval = (CORE_ADDR) lnum;
  ptrval = (CORE_ADDR) lnum;
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
  if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
    {
    {
      remote_fileio_to_fio_uint (1, fst.fst_dev);
      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_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
      st.st_nlink = 1;
      st.st_nlink = 1;
#ifdef HAVE_GETUID
#ifdef HAVE_GETUID
      st.st_uid = getuid ();
      st.st_uid = getuid ();
#else
#else
      st.st_uid = 0;
      st.st_uid = 0;
#endif
#endif
#ifdef HAVE_GETGID
#ifdef HAVE_GETGID
      st.st_gid = getgid ();
      st.st_gid = getgid ();
#else
#else
      st.st_gid = 0;
      st.st_gid = 0;
#endif
#endif
      st.st_rdev = 0;
      st.st_rdev = 0;
      st.st_size = 0;
      st.st_size = 0;
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
      st.st_blksize = 512;
      st.st_blksize = 512;
#endif
#endif
#if HAVE_STRUCT_STAT_ST_BLOCKS
#if HAVE_STRUCT_STAT_ST_BLOCKS
      st.st_blocks = 0;
      st.st_blocks = 0;
#endif
#endif
      if (!gettimeofday (&tv, NULL))
      if (!gettimeofday (&tv, NULL))
        st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
        st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
      else
      else
        st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
        st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
      ret = 0;
      ret = 0;
    }
    }
  else
  else
    ret = fstat (fd, &st);
    ret = fstat (fd, &st);
 
 
  if (ret == -1)
  if (ret == -1)
    {
    {
      remote_fileio_return_errno (-1);
      remote_fileio_return_errno (-1);
      return;
      return;
    }
    }
  if (ptrval)
  if (ptrval)
    {
    {
      remote_fileio_to_fio_stat (&st, &fst);
      remote_fileio_to_fio_stat (&st, &fst);
 
 
      retlength = remote_fileio_write_bytes (ptrval, (gdb_byte *) &fst, sizeof fst);
      retlength = remote_fileio_write_bytes (ptrval, (gdb_byte *) &fst, sizeof fst);
      if (retlength != sizeof fst)
      if (retlength != sizeof fst)
        {
        {
          remote_fileio_return_errno (-1);
          remote_fileio_return_errno (-1);
          return;
          return;
        }
        }
    }
    }
  remote_fileio_return_success (ret);
  remote_fileio_return_success (ret);
}
}
 
 
static void
static void
remote_fileio_func_gettimeofday (char *buf)
remote_fileio_func_gettimeofday (char *buf)
{
{
  LONGEST lnum;
  LONGEST lnum;
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int ret, retlength;
  int ret, retlength;
  struct timeval tv;
  struct timeval tv;
  struct fio_timeval ftv;
  struct fio_timeval ftv;
 
 
  /* 1. Parameter: struct timeval pointer */
  /* 1. Parameter: struct timeval pointer */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  ptrval = (CORE_ADDR) lnum;
  ptrval = (CORE_ADDR) lnum;
  /* 2. Parameter: some pointer value... */
  /* 2. Parameter: some pointer value... */
  if (remote_fileio_extract_long (&buf, &lnum))
  if (remote_fileio_extract_long (&buf, &lnum))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  /* ...which has to be NULL */
  /* ...which has to be NULL */
  if (lnum)
  if (lnum)
    {
    {
      remote_fileio_reply (-1, FILEIO_EINVAL);
      remote_fileio_reply (-1, FILEIO_EINVAL);
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  ret = gettimeofday (&tv, NULL);
  ret = gettimeofday (&tv, NULL);
 
 
  if (ret == -1)
  if (ret == -1)
    {
    {
      remote_fileio_return_errno (-1);
      remote_fileio_return_errno (-1);
      return;
      return;
    }
    }
 
 
  if (ptrval)
  if (ptrval)
    {
    {
      remote_fileio_to_fio_timeval (&tv, &ftv);
      remote_fileio_to_fio_timeval (&tv, &ftv);
 
 
      retlength = remote_fileio_write_bytes (ptrval, (gdb_byte *) &ftv, sizeof ftv);
      retlength = remote_fileio_write_bytes (ptrval, (gdb_byte *) &ftv, sizeof ftv);
      if (retlength != sizeof ftv)
      if (retlength != sizeof ftv)
        {
        {
          remote_fileio_return_errno (-1);
          remote_fileio_return_errno (-1);
          return;
          return;
        }
        }
    }
    }
  remote_fileio_return_success (ret);
  remote_fileio_return_success (ret);
}
}
 
 
static void
static void
remote_fileio_func_isatty (char *buf)
remote_fileio_func_isatty (char *buf)
{
{
  long target_fd;
  long target_fd;
  int fd;
  int fd;
 
 
  /* Parameter: file descriptor */
  /* Parameter: file descriptor */
  if (remote_fileio_extract_int (&buf, &target_fd))
  if (remote_fileio_extract_int (&buf, &target_fd))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  fd = remote_fileio_map_fd ((int) target_fd);
  fd = remote_fileio_map_fd ((int) target_fd);
  remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN ||
  remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN ||
                                fd == FIO_FD_CONSOLE_OUT ? 1 : 0);
                                fd == FIO_FD_CONSOLE_OUT ? 1 : 0);
}
}
 
 
static void
static void
remote_fileio_func_system (char *buf)
remote_fileio_func_system (char *buf)
{
{
  CORE_ADDR ptrval;
  CORE_ADDR ptrval;
  int ret, length, retlength;
  int ret, length, retlength;
  char *cmdline = NULL;
  char *cmdline = NULL;
 
 
  /* Parameter: Ptr to commandline / length incl. trailing zero */
  /* Parameter: Ptr to commandline / length incl. trailing zero */
  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
    {
    {
      remote_fileio_ioerror ();
      remote_fileio_ioerror ();
      return;
      return;
    }
    }
 
 
  if (length)
  if (length)
    {
    {
      /* Request commandline using 'm' packet */
      /* Request commandline using 'm' packet */
      cmdline = alloca (length);
      cmdline = alloca (length);
      retlength = remote_read_bytes (ptrval, (gdb_byte *) cmdline, length);
      retlength = remote_read_bytes (ptrval, (gdb_byte *) cmdline, length);
      if (retlength != length)
      if (retlength != length)
        {
        {
          remote_fileio_ioerror ();
          remote_fileio_ioerror ();
          return;
          return;
        }
        }
    }
    }
 
 
  /* Check if system(3) has been explicitely allowed using the
  /* Check if system(3) has been explicitely allowed using the
     `set remote system-call-allowed 1' command.  If length is 0,
     `set remote system-call-allowed 1' command.  If length is 0,
     indicating a NULL parameter to the system call, return zero to
     indicating a NULL parameter to the system call, return zero to
     indicate a shell is not available.  Otherwise fail with EPERM.  */
     indicate a shell is not available.  Otherwise fail with EPERM.  */
  if (!remote_fio_system_call_allowed)
  if (!remote_fio_system_call_allowed)
    {
    {
      if (!length)
      if (!length)
        remote_fileio_return_success (0);
        remote_fileio_return_success (0);
      else
      else
        remote_fileio_reply (-1, FILEIO_EPERM);
        remote_fileio_reply (-1, FILEIO_EPERM);
      return;
      return;
    }
    }
 
 
  remote_fio_no_longjmp = 1;
  remote_fio_no_longjmp = 1;
  ret = system (cmdline);
  ret = system (cmdline);
 
 
  if (!length)
  if (!length)
    remote_fileio_return_success (ret);
    remote_fileio_return_success (ret);
  else if (ret == -1)
  else if (ret == -1)
    remote_fileio_return_errno (-1);
    remote_fileio_return_errno (-1);
  else
  else
    remote_fileio_return_success (WEXITSTATUS (ret));
    remote_fileio_return_success (WEXITSTATUS (ret));
}
}
 
 
static struct {
static struct {
  char *name;
  char *name;
  void (*func)(char *);
  void (*func)(char *);
} remote_fio_func_map[] = {
} remote_fio_func_map[] = {
  { "open", remote_fileio_func_open },
  { "open", remote_fileio_func_open },
  { "close", remote_fileio_func_close },
  { "close", remote_fileio_func_close },
  { "read", remote_fileio_func_read },
  { "read", remote_fileio_func_read },
  { "write", remote_fileio_func_write },
  { "write", remote_fileio_func_write },
  { "lseek", remote_fileio_func_lseek },
  { "lseek", remote_fileio_func_lseek },
  { "rename", remote_fileio_func_rename },
  { "rename", remote_fileio_func_rename },
  { "unlink", remote_fileio_func_unlink },
  { "unlink", remote_fileio_func_unlink },
  { "stat", remote_fileio_func_stat },
  { "stat", remote_fileio_func_stat },
  { "fstat", remote_fileio_func_fstat },
  { "fstat", remote_fileio_func_fstat },
  { "gettimeofday", remote_fileio_func_gettimeofday },
  { "gettimeofday", remote_fileio_func_gettimeofday },
  { "isatty", remote_fileio_func_isatty },
  { "isatty", remote_fileio_func_isatty },
  { "system", remote_fileio_func_system },
  { "system", remote_fileio_func_system },
  { NULL, NULL }
  { NULL, NULL }
};
};
 
 
static int
static int
do_remote_fileio_request (struct ui_out *uiout, void *buf_arg)
do_remote_fileio_request (struct ui_out *uiout, void *buf_arg)
{
{
  char *buf = buf_arg;
  char *buf = buf_arg;
  char *c;
  char *c;
  int idx;
  int idx;
 
 
  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
 
 
  c = strchr (++buf, ',');
  c = strchr (++buf, ',');
  if (c)
  if (c)
    *c++ = '\0';
    *c++ = '\0';
  else
  else
    c = strchr (buf, '\0');
    c = strchr (buf, '\0');
  for (idx = 0; remote_fio_func_map[idx].name; ++idx)
  for (idx = 0; remote_fio_func_map[idx].name; ++idx)
    if (!strcmp (remote_fio_func_map[idx].name, buf))
    if (!strcmp (remote_fio_func_map[idx].name, buf))
      break;
      break;
  if (!remote_fio_func_map[idx].name)   /* ERROR: No such function. */
  if (!remote_fio_func_map[idx].name)   /* ERROR: No such function. */
    return RETURN_ERROR;
    return RETURN_ERROR;
  remote_fio_func_map[idx].func (c);
  remote_fio_func_map[idx].func (c);
  return 0;
  return 0;
}
}
 
 
/* Close any open descriptors, and reinitialize the file mapping.  */
/* Close any open descriptors, and reinitialize the file mapping.  */
 
 
void
void
remote_fileio_reset (void)
remote_fileio_reset (void)
{
{
  int ix;
  int ix;
 
 
  for (ix = 0; ix != remote_fio_data.fd_map_size; ix++)
  for (ix = 0; ix != remote_fio_data.fd_map_size; ix++)
    {
    {
      int fd = remote_fio_data.fd_map[ix];
      int fd = remote_fio_data.fd_map[ix];
 
 
      if (fd >= 0)
      if (fd >= 0)
        close (fd);
        close (fd);
    }
    }
  if (remote_fio_data.fd_map)
  if (remote_fio_data.fd_map)
    {
    {
      xfree (remote_fio_data.fd_map);
      xfree (remote_fio_data.fd_map);
      remote_fio_data.fd_map = NULL;
      remote_fio_data.fd_map = NULL;
      remote_fio_data.fd_map_size = 0;
      remote_fio_data.fd_map_size = 0;
    }
    }
}
}
 
 
/* Handle a file I/O request. BUF points to the packet containing the
/* Handle a file I/O request. BUF points to the packet containing the
   request. CTRLC_PENDING_P should be nonzero if the target has not
   request. CTRLC_PENDING_P should be nonzero if the target has not
   acknowledged the Ctrl-C sent asynchronously earlier.  */
   acknowledged the Ctrl-C sent asynchronously earlier.  */
 
 
void
void
remote_fileio_request (char *buf, int ctrlc_pending_p)
remote_fileio_request (char *buf, int ctrlc_pending_p)
{
{
  int ex;
  int ex;
 
 
  remote_fileio_sig_init ();
  remote_fileio_sig_init ();
 
 
  if (ctrlc_pending_p)
  if (ctrlc_pending_p)
    {
    {
      /* If the target hasn't responded to the Ctrl-C sent
      /* If the target hasn't responded to the Ctrl-C sent
         asynchronously earlier, take this opportunity to send the
         asynchronously earlier, take this opportunity to send the
         Ctrl-C synchronously.  */
         Ctrl-C synchronously.  */
      remote_fio_ctrl_c_flag = 1;
      remote_fio_ctrl_c_flag = 1;
      remote_fio_no_longjmp = 0;
      remote_fio_no_longjmp = 0;
      remote_fileio_reply (-1, FILEIO_EINTR);
      remote_fileio_reply (-1, FILEIO_EINTR);
    }
    }
  else
  else
    {
    {
      remote_fio_ctrl_c_flag = 0;
      remote_fio_ctrl_c_flag = 0;
      remote_fio_no_longjmp = 0;
      remote_fio_no_longjmp = 0;
 
 
      ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf,
      ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf,
                             RETURN_MASK_ALL);
                             RETURN_MASK_ALL);
      switch (ex)
      switch (ex)
        {
        {
        case RETURN_ERROR:
        case RETURN_ERROR:
          remote_fileio_reply (-1, FILEIO_ENOSYS);
          remote_fileio_reply (-1, FILEIO_ENOSYS);
          break;
          break;
        case RETURN_QUIT:
        case RETURN_QUIT:
          remote_fileio_reply (-1, FILEIO_EINTR);
          remote_fileio_reply (-1, FILEIO_EINTR);
          break;
          break;
        default:
        default:
          break;
          break;
        }
        }
    }
    }
 
 
  remote_fileio_sig_exit ();
  remote_fileio_sig_exit ();
}
}
 
 
static void
static void
set_system_call_allowed (char *args, int from_tty)
set_system_call_allowed (char *args, int from_tty)
{
{
  if (args)
  if (args)
    {
    {
      char *arg_end;
      char *arg_end;
      int val = strtoul (args, &arg_end, 10);
      int val = strtoul (args, &arg_end, 10);
      if (*args && *arg_end == '\0')
      if (*args && *arg_end == '\0')
        {
        {
          remote_fio_system_call_allowed = !!val;
          remote_fio_system_call_allowed = !!val;
          return;
          return;
        }
        }
    }
    }
  error (_("Illegal argument for \"set remote system-call-allowed\" command"));
  error (_("Illegal argument for \"set remote system-call-allowed\" command"));
}
}
 
 
static void
static void
show_system_call_allowed (char *args, int from_tty)
show_system_call_allowed (char *args, int from_tty)
{
{
  if (args)
  if (args)
    error (_("Garbage after \"show remote system-call-allowed\" command: `%s'"), args);
    error (_("Garbage after \"show remote system-call-allowed\" command: `%s'"), args);
  printf_unfiltered ("Calling host system(3) call from target is %sallowed\n",
  printf_unfiltered ("Calling host system(3) call from target is %sallowed\n",
                     remote_fio_system_call_allowed ? "" : "not ");
                     remote_fio_system_call_allowed ? "" : "not ");
}
}
 
 
void
void
initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
                          struct cmd_list_element *remote_show_cmdlist)
                          struct cmd_list_element *remote_show_cmdlist)
{
{
  sigint_fileio_token =
  sigint_fileio_token =
    create_async_signal_handler (async_remote_fileio_interrupt, NULL);
    create_async_signal_handler (async_remote_fileio_interrupt, NULL);
 
 
  add_cmd ("system-call-allowed", no_class,
  add_cmd ("system-call-allowed", no_class,
           set_system_call_allowed,
           set_system_call_allowed,
           _("Set if the host system(3) call is allowed for the target."),
           _("Set if the host system(3) call is allowed for the target."),
           &remote_set_cmdlist);
           &remote_set_cmdlist);
  add_cmd ("system-call-allowed", no_class,
  add_cmd ("system-call-allowed", no_class,
           show_system_call_allowed,
           show_system_call_allowed,
           _("Show if the host system(3) call is allowed for the target."),
           _("Show if the host system(3) call is allowed for the target."),
           &remote_show_cmdlist);
           &remote_show_cmdlist);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.