mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-27 04:52:05 +08:00
dda83cd783
Many spots incorrectly use only spaces for indentation (for example, there are a lot of spots in ada-lang.c). I've always found it awkward when I needed to edit one of these spots: do I keep the original wrong indentation, or do I fix it? What if the lines around it are also wrong, do I fix them too? I probably don't want to fix them in the same patch, to avoid adding noise to my patch. So I propose to fix as much as possible once and for all (hopefully). One typical counter argument for this is that it makes code archeology more difficult, because git-blame will show this commit as the last change for these lines. My counter counter argument is: when git-blaming, you often need to do "blame the file at the parent commit" anyway, to go past some other refactor that touched the line you are interested in, but is not the change you are looking for. So you already need a somewhat efficient way to do this. Using some interactive tool, rather than plain git-blame, makes this trivial. For example, I use "tig blame <file>", where going back past the commit that changed the currently selected line is one keystroke. It looks like Magit in Emacs does it too (though I've never used it). Web viewers of Github and Gitlab do it too. My point is that it won't really make archeology more difficult. The other typical counter argument is that it will cause conflicts with existing patches. That's true... but it's a one time cost, and those are not conflicts that are difficult to resolve. I have also tried "git rebase --ignore-whitespace", it seems to work well. Although that will re-introduce the faulty indentation, so one needs to take care of fixing the indentation in the patch after that (which is easy). gdb/ChangeLog: * aarch64-linux-tdep.c: Fix indentation. * aarch64-ravenscar-thread.c: Fix indentation. * aarch64-tdep.c: Fix indentation. * aarch64-tdep.h: Fix indentation. * ada-lang.c: Fix indentation. * ada-lang.h: Fix indentation. * ada-tasks.c: Fix indentation. * ada-typeprint.c: Fix indentation. * ada-valprint.c: Fix indentation. * ada-varobj.c: Fix indentation. * addrmap.c: Fix indentation. * addrmap.h: Fix indentation. * agent.c: Fix indentation. * aix-thread.c: Fix indentation. * alpha-bsd-nat.c: Fix indentation. * alpha-linux-tdep.c: Fix indentation. * alpha-mdebug-tdep.c: Fix indentation. * alpha-nbsd-tdep.c: Fix indentation. * alpha-obsd-tdep.c: Fix indentation. * alpha-tdep.c: Fix indentation. * amd64-bsd-nat.c: Fix indentation. * amd64-darwin-tdep.c: Fix indentation. * amd64-linux-nat.c: Fix indentation. * amd64-linux-tdep.c: Fix indentation. * amd64-nat.c: Fix indentation. * amd64-obsd-tdep.c: Fix indentation. * amd64-tdep.c: Fix indentation. * amd64-windows-tdep.c: Fix indentation. * annotate.c: Fix indentation. * arc-tdep.c: Fix indentation. * arch-utils.c: Fix indentation. * arch/arm-get-next-pcs.c: Fix indentation. * arch/arm.c: Fix indentation. * arm-linux-nat.c: Fix indentation. * arm-linux-tdep.c: Fix indentation. * arm-nbsd-tdep.c: Fix indentation. * arm-pikeos-tdep.c: Fix indentation. * arm-tdep.c: Fix indentation. * arm-tdep.h: Fix indentation. * arm-wince-tdep.c: Fix indentation. * auto-load.c: Fix indentation. * auxv.c: Fix indentation. * avr-tdep.c: Fix indentation. * ax-gdb.c: Fix indentation. * ax-general.c: Fix indentation. * bfin-linux-tdep.c: Fix indentation. * block.c: Fix indentation. * block.h: Fix indentation. * blockframe.c: Fix indentation. * bpf-tdep.c: Fix indentation. * break-catch-sig.c: Fix indentation. * break-catch-syscall.c: Fix indentation. * break-catch-throw.c: Fix indentation. * breakpoint.c: Fix indentation. * breakpoint.h: Fix indentation. * bsd-uthread.c: Fix indentation. * btrace.c: Fix indentation. * build-id.c: Fix indentation. * buildsym-legacy.h: Fix indentation. * buildsym.c: Fix indentation. * c-typeprint.c: Fix indentation. * c-valprint.c: Fix indentation. * c-varobj.c: Fix indentation. * charset.c: Fix indentation. * cli/cli-cmds.c: Fix indentation. * cli/cli-decode.c: Fix indentation. * cli/cli-decode.h: Fix indentation. * cli/cli-script.c: Fix indentation. * cli/cli-setshow.c: Fix indentation. * coff-pe-read.c: Fix indentation. * coffread.c: Fix indentation. * compile/compile-cplus-types.c: Fix indentation. * compile/compile-object-load.c: Fix indentation. * compile/compile-object-run.c: Fix indentation. * completer.c: Fix indentation. * corefile.c: Fix indentation. * corelow.c: Fix indentation. * cp-abi.h: Fix indentation. * cp-namespace.c: Fix indentation. * cp-support.c: Fix indentation. * cp-valprint.c: Fix indentation. * cris-linux-tdep.c: Fix indentation. * cris-tdep.c: Fix indentation. * darwin-nat-info.c: Fix indentation. * darwin-nat.c: Fix indentation. * darwin-nat.h: Fix indentation. * dbxread.c: Fix indentation. * dcache.c: Fix indentation. * disasm.c: Fix indentation. * dtrace-probe.c: Fix indentation. * dwarf2/abbrev.c: Fix indentation. * dwarf2/attribute.c: Fix indentation. * dwarf2/expr.c: Fix indentation. * dwarf2/frame.c: Fix indentation. * dwarf2/index-cache.c: Fix indentation. * dwarf2/index-write.c: Fix indentation. * dwarf2/line-header.c: Fix indentation. * dwarf2/loc.c: Fix indentation. * dwarf2/macro.c: Fix indentation. * dwarf2/read.c: Fix indentation. * dwarf2/read.h: Fix indentation. * elfread.c: Fix indentation. * eval.c: Fix indentation. * event-top.c: Fix indentation. * exec.c: Fix indentation. * exec.h: Fix indentation. * expprint.c: Fix indentation. * f-lang.c: Fix indentation. * f-typeprint.c: Fix indentation. * f-valprint.c: Fix indentation. * fbsd-nat.c: Fix indentation. * fbsd-tdep.c: Fix indentation. * findvar.c: Fix indentation. * fork-child.c: Fix indentation. * frame-unwind.c: Fix indentation. * frame-unwind.h: Fix indentation. * frame.c: Fix indentation. * frv-linux-tdep.c: Fix indentation. * frv-tdep.c: Fix indentation. * frv-tdep.h: Fix indentation. * ft32-tdep.c: Fix indentation. * gcore.c: Fix indentation. * gdb_bfd.c: Fix indentation. * gdbarch.sh: Fix indentation. * gdbarch.c: Re-generate * gdbarch.h: Re-generate. * gdbcore.h: Fix indentation. * gdbthread.h: Fix indentation. * gdbtypes.c: Fix indentation. * gdbtypes.h: Fix indentation. * glibc-tdep.c: Fix indentation. * gnu-nat.c: Fix indentation. * gnu-nat.h: Fix indentation. * gnu-v2-abi.c: Fix indentation. * gnu-v3-abi.c: Fix indentation. * go32-nat.c: Fix indentation. * guile/guile-internal.h: Fix indentation. * guile/scm-cmd.c: Fix indentation. * guile/scm-frame.c: Fix indentation. * guile/scm-iterator.c: Fix indentation. * guile/scm-math.c: Fix indentation. * guile/scm-ports.c: Fix indentation. * guile/scm-pretty-print.c: Fix indentation. * guile/scm-value.c: Fix indentation. * h8300-tdep.c: Fix indentation. * hppa-linux-nat.c: Fix indentation. * hppa-linux-tdep.c: Fix indentation. * hppa-nbsd-nat.c: Fix indentation. * hppa-nbsd-tdep.c: Fix indentation. * hppa-obsd-nat.c: Fix indentation. * hppa-tdep.c: Fix indentation. * hppa-tdep.h: Fix indentation. * i386-bsd-nat.c: Fix indentation. * i386-darwin-nat.c: Fix indentation. * i386-darwin-tdep.c: Fix indentation. * i386-dicos-tdep.c: Fix indentation. * i386-gnu-nat.c: Fix indentation. * i386-linux-nat.c: Fix indentation. * i386-linux-tdep.c: Fix indentation. * i386-nto-tdep.c: Fix indentation. * i386-obsd-tdep.c: Fix indentation. * i386-sol2-nat.c: Fix indentation. * i386-tdep.c: Fix indentation. * i386-tdep.h: Fix indentation. * i386-windows-tdep.c: Fix indentation. * i387-tdep.c: Fix indentation. * i387-tdep.h: Fix indentation. * ia64-libunwind-tdep.c: Fix indentation. * ia64-libunwind-tdep.h: Fix indentation. * ia64-linux-nat.c: Fix indentation. * ia64-linux-tdep.c: Fix indentation. * ia64-tdep.c: Fix indentation. * ia64-tdep.h: Fix indentation. * ia64-vms-tdep.c: Fix indentation. * infcall.c: Fix indentation. * infcmd.c: Fix indentation. * inferior.c: Fix indentation. * infrun.c: Fix indentation. * iq2000-tdep.c: Fix indentation. * language.c: Fix indentation. * linespec.c: Fix indentation. * linux-fork.c: Fix indentation. * linux-nat.c: Fix indentation. * linux-tdep.c: Fix indentation. * linux-thread-db.c: Fix indentation. * lm32-tdep.c: Fix indentation. * m2-lang.c: Fix indentation. * m2-typeprint.c: Fix indentation. * m2-valprint.c: Fix indentation. * m32c-tdep.c: Fix indentation. * m32r-linux-tdep.c: Fix indentation. * m32r-tdep.c: Fix indentation. * m68hc11-tdep.c: Fix indentation. * m68k-bsd-nat.c: Fix indentation. * m68k-linux-nat.c: Fix indentation. * m68k-linux-tdep.c: Fix indentation. * m68k-tdep.c: Fix indentation. * machoread.c: Fix indentation. * macrocmd.c: Fix indentation. * macroexp.c: Fix indentation. * macroscope.c: Fix indentation. * macrotab.c: Fix indentation. * macrotab.h: Fix indentation. * main.c: Fix indentation. * mdebugread.c: Fix indentation. * mep-tdep.c: Fix indentation. * mi/mi-cmd-catch.c: Fix indentation. * mi/mi-cmd-disas.c: Fix indentation. * mi/mi-cmd-env.c: Fix indentation. * mi/mi-cmd-stack.c: Fix indentation. * mi/mi-cmd-var.c: Fix indentation. * mi/mi-cmds.c: Fix indentation. * mi/mi-main.c: Fix indentation. * mi/mi-parse.c: Fix indentation. * microblaze-tdep.c: Fix indentation. * minidebug.c: Fix indentation. * minsyms.c: Fix indentation. * mips-linux-nat.c: Fix indentation. * mips-linux-tdep.c: Fix indentation. * mips-nbsd-tdep.c: Fix indentation. * mips-tdep.c: Fix indentation. * mn10300-linux-tdep.c: Fix indentation. * mn10300-tdep.c: Fix indentation. * moxie-tdep.c: Fix indentation. * msp430-tdep.c: Fix indentation. * namespace.h: Fix indentation. * nat/fork-inferior.c: Fix indentation. * nat/gdb_ptrace.h: Fix indentation. * nat/linux-namespaces.c: Fix indentation. * nat/linux-osdata.c: Fix indentation. * nat/netbsd-nat.c: Fix indentation. * nat/x86-dregs.c: Fix indentation. * nbsd-nat.c: Fix indentation. * nbsd-tdep.c: Fix indentation. * nios2-linux-tdep.c: Fix indentation. * nios2-tdep.c: Fix indentation. * nto-procfs.c: Fix indentation. * nto-tdep.c: Fix indentation. * objfiles.c: Fix indentation. * objfiles.h: Fix indentation. * opencl-lang.c: Fix indentation. * or1k-tdep.c: Fix indentation. * osabi.c: Fix indentation. * osabi.h: Fix indentation. * osdata.c: Fix indentation. * p-lang.c: Fix indentation. * p-typeprint.c: Fix indentation. * p-valprint.c: Fix indentation. * parse.c: Fix indentation. * ppc-linux-nat.c: Fix indentation. * ppc-linux-tdep.c: Fix indentation. * ppc-nbsd-nat.c: Fix indentation. * ppc-nbsd-tdep.c: Fix indentation. * ppc-obsd-nat.c: Fix indentation. * ppc-ravenscar-thread.c: Fix indentation. * ppc-sysv-tdep.c: Fix indentation. * ppc64-tdep.c: Fix indentation. * printcmd.c: Fix indentation. * proc-api.c: Fix indentation. * producer.c: Fix indentation. * producer.h: Fix indentation. * prologue-value.c: Fix indentation. * prologue-value.h: Fix indentation. * psymtab.c: Fix indentation. * python/py-arch.c: Fix indentation. * python/py-bpevent.c: Fix indentation. * python/py-event.c: Fix indentation. * python/py-event.h: Fix indentation. * python/py-finishbreakpoint.c: Fix indentation. * python/py-frame.c: Fix indentation. * python/py-framefilter.c: Fix indentation. * python/py-inferior.c: Fix indentation. * python/py-infthread.c: Fix indentation. * python/py-objfile.c: Fix indentation. * python/py-prettyprint.c: Fix indentation. * python/py-registers.c: Fix indentation. * python/py-signalevent.c: Fix indentation. * python/py-stopevent.c: Fix indentation. * python/py-stopevent.h: Fix indentation. * python/py-threadevent.c: Fix indentation. * python/py-tui.c: Fix indentation. * python/py-unwind.c: Fix indentation. * python/py-value.c: Fix indentation. * python/py-xmethods.c: Fix indentation. * python/python-internal.h: Fix indentation. * python/python.c: Fix indentation. * ravenscar-thread.c: Fix indentation. * record-btrace.c: Fix indentation. * record-full.c: Fix indentation. * record.c: Fix indentation. * reggroups.c: Fix indentation. * regset.h: Fix indentation. * remote-fileio.c: Fix indentation. * remote.c: Fix indentation. * reverse.c: Fix indentation. * riscv-linux-tdep.c: Fix indentation. * riscv-ravenscar-thread.c: Fix indentation. * riscv-tdep.c: Fix indentation. * rl78-tdep.c: Fix indentation. * rs6000-aix-tdep.c: Fix indentation. * rs6000-lynx178-tdep.c: Fix indentation. * rs6000-nat.c: Fix indentation. * rs6000-tdep.c: Fix indentation. * rust-lang.c: Fix indentation. * rx-tdep.c: Fix indentation. * s12z-tdep.c: Fix indentation. * s390-linux-tdep.c: Fix indentation. * score-tdep.c: Fix indentation. * ser-base.c: Fix indentation. * ser-mingw.c: Fix indentation. * ser-uds.c: Fix indentation. * ser-unix.c: Fix indentation. * serial.c: Fix indentation. * sh-linux-tdep.c: Fix indentation. * sh-nbsd-tdep.c: Fix indentation. * sh-tdep.c: Fix indentation. * skip.c: Fix indentation. * sol-thread.c: Fix indentation. * solib-aix.c: Fix indentation. * solib-darwin.c: Fix indentation. * solib-frv.c: Fix indentation. * solib-svr4.c: Fix indentation. * solib.c: Fix indentation. * source.c: Fix indentation. * sparc-linux-tdep.c: Fix indentation. * sparc-nbsd-tdep.c: Fix indentation. * sparc-obsd-tdep.c: Fix indentation. * sparc-ravenscar-thread.c: Fix indentation. * sparc-tdep.c: Fix indentation. * sparc64-linux-tdep.c: Fix indentation. * sparc64-nbsd-tdep.c: Fix indentation. * sparc64-obsd-tdep.c: Fix indentation. * sparc64-tdep.c: Fix indentation. * stabsread.c: Fix indentation. * stack.c: Fix indentation. * stap-probe.c: Fix indentation. * stubs/ia64vms-stub.c: Fix indentation. * stubs/m32r-stub.c: Fix indentation. * stubs/m68k-stub.c: Fix indentation. * stubs/sh-stub.c: Fix indentation. * stubs/sparc-stub.c: Fix indentation. * symfile-mem.c: Fix indentation. * symfile.c: Fix indentation. * symfile.h: Fix indentation. * symmisc.c: Fix indentation. * symtab.c: Fix indentation. * symtab.h: Fix indentation. * target-float.c: Fix indentation. * target.c: Fix indentation. * target.h: Fix indentation. * tic6x-tdep.c: Fix indentation. * tilegx-linux-tdep.c: Fix indentation. * tilegx-tdep.c: Fix indentation. * top.c: Fix indentation. * tracefile-tfile.c: Fix indentation. * tracepoint.c: Fix indentation. * tui/tui-disasm.c: Fix indentation. * tui/tui-io.c: Fix indentation. * tui/tui-regs.c: Fix indentation. * tui/tui-stack.c: Fix indentation. * tui/tui-win.c: Fix indentation. * tui/tui-winsource.c: Fix indentation. * tui/tui.c: Fix indentation. * typeprint.c: Fix indentation. * ui-out.h: Fix indentation. * unittests/copy_bitwise-selftests.c: Fix indentation. * unittests/memory-map-selftests.c: Fix indentation. * utils.c: Fix indentation. * v850-tdep.c: Fix indentation. * valarith.c: Fix indentation. * valops.c: Fix indentation. * valprint.c: Fix indentation. * valprint.h: Fix indentation. * value.c: Fix indentation. * value.h: Fix indentation. * varobj.c: Fix indentation. * vax-tdep.c: Fix indentation. * windows-nat.c: Fix indentation. * windows-tdep.c: Fix indentation. * xcoffread.c: Fix indentation. * xml-syscall.c: Fix indentation. * xml-tdesc.c: Fix indentation. * xstormy16-tdep.c: Fix indentation. * xtensa-config.c: Fix indentation. * xtensa-linux-nat.c: Fix indentation. * xtensa-linux-tdep.c: Fix indentation. * xtensa-tdep.c: Fix indentation. gdbserver/ChangeLog: * ax.cc: Fix indentation. * dll.cc: Fix indentation. * inferiors.h: Fix indentation. * linux-low.cc: Fix indentation. * linux-nios2-low.cc: Fix indentation. * linux-ppc-ipa.cc: Fix indentation. * linux-ppc-low.cc: Fix indentation. * linux-x86-low.cc: Fix indentation. * linux-xtensa-low.cc: Fix indentation. * regcache.cc: Fix indentation. * server.cc: Fix indentation. * tracepoint.cc: Fix indentation. gdbsupport/ChangeLog: * common-exceptions.h: Fix indentation. * event-loop.cc: Fix indentation. * fileio.cc: Fix indentation. * filestuff.cc: Fix indentation. * gdb-dlfcn.cc: Fix indentation. * gdb_string_view.h: Fix indentation. * job-control.cc: Fix indentation. * signals.cc: Fix indentation. Change-Id: I4bad7ae6be0fbe14168b8ebafb98ffe14964a695
1310 lines
31 KiB
C
1310 lines
31 KiB
C
/* Remote File-I/O communications
|
||
|
||
Copyright (C) 2003-2020 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 3 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, see <http://www.gnu.org/licenses/>. */
|
||
|
||
/* See the GDB User Guide for details of the GDB remote protocol. */
|
||
|
||
#include "defs.h"
|
||
#include "gdbcmd.h"
|
||
#include "remote.h"
|
||
#include "gdbsupport/gdb_wait.h"
|
||
#include <sys/stat.h>
|
||
#include "remote-fileio.h"
|
||
#include "gdbsupport/event-loop.h"
|
||
#include "target.h"
|
||
#include "filenames.h"
|
||
#include "gdbsupport/filestuff.h"
|
||
|
||
#include <fcntl.h>
|
||
#include "gdbsupport/gdb_sys_time.h"
|
||
#ifdef __CYGWIN__
|
||
#include <sys/cygwin.h> /* For cygwin_conv_path. */
|
||
#endif
|
||
#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 (void)
|
||
{
|
||
int i;
|
||
|
||
if (!remote_fio_data.fd_map)
|
||
{
|
||
remote_fio_data.fd_map = XNEWVEC (int, 10);
|
||
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 (void)
|
||
{
|
||
int i = remote_fio_data.fd_map_size;
|
||
|
||
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));
|
||
for (; i < remote_fio_data.fd_map_size; i++)
|
||
remote_fio_data.fd_map[i] = FIO_FD_INVALID;
|
||
return remote_fio_data.fd_map_size - 10;
|
||
}
|
||
|
||
static int
|
||
remote_fileio_next_free_fd (void)
|
||
{
|
||
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;
|
||
#ifdef S_IRGRP
|
||
if (mode & FILEIO_S_IRGRP)
|
||
hmode |= S_IRGRP;
|
||
#endif
|
||
#ifdef S_IWGRP
|
||
if (mode & FILEIO_S_IWGRP)
|
||
hmode |= S_IWGRP;
|
||
#endif
|
||
#ifdef S_IXGRP
|
||
if (mode & FILEIO_S_IXGRP)
|
||
hmode |= S_IXGRP;
|
||
#endif
|
||
if (mode & FILEIO_S_IROTH)
|
||
hmode |= S_IROTH;
|
||
#ifdef S_IWOTH
|
||
if (mode & FILEIO_S_IWOTH)
|
||
hmode |= S_IWOTH;
|
||
#endif
|
||
#ifdef S_IXOTH
|
||
if (mode & FILEIO_S_IXOTH)
|
||
hmode |= S_IXOTH;
|
||
#endif
|
||
return hmode;
|
||
}
|
||
|
||
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, LONGEST *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;
|
||
LONGEST retlong;
|
||
|
||
if (!retint)
|
||
return -1;
|
||
ret = remote_fileio_extract_long (buf, &retlong);
|
||
if (!ret)
|
||
*retint = (long) retlong;
|
||
return ret;
|
||
}
|
||
|
||
static int
|
||
remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length)
|
||
{
|
||
char *c;
|
||
LONGEST 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;
|
||
}
|
||
|
||
static void
|
||
remote_fileio_to_fio_long (LONGEST num, fio_long_t fnum)
|
||
{
|
||
host_to_bigendian (num, (char *) fnum, 8);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv)
|
||
{
|
||
host_to_fileio_time (tv->tv_sec, ftv->ftv_sec);
|
||
remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec);
|
||
}
|
||
|
||
/* The quit handler originally installed. */
|
||
static quit_handler_ftype *remote_fileio_o_quit_handler;
|
||
|
||
/* What to do on a QUIT call while handling a file I/O request. We
|
||
throw a quit exception, which is caught by remote_fileio_request
|
||
and translated to an EINTR reply back to the target. */
|
||
|
||
static void
|
||
remote_fileio_quit_handler (void)
|
||
{
|
||
if (check_quit_flag ())
|
||
quit ();
|
||
}
|
||
|
||
static void
|
||
remote_fileio_reply (remote_target *remote, int retcode, int error)
|
||
{
|
||
char buf[32];
|
||
int ctrl_c = check_quit_flag ();
|
||
|
||
strcpy (buf, "F");
|
||
if (retcode < 0)
|
||
{
|
||
strcat (buf, "-");
|
||
retcode = -retcode;
|
||
}
|
||
sprintf (buf + strlen (buf), "%x", retcode);
|
||
if (error || ctrl_c)
|
||
{
|
||
if (error && ctrl_c)
|
||
error = FILEIO_EINTR;
|
||
if (error < 0)
|
||
{
|
||
strcat (buf, "-");
|
||
error = -error;
|
||
}
|
||
sprintf (buf + strlen (buf), ",%x", error);
|
||
if (ctrl_c)
|
||
strcat (buf, ",C");
|
||
}
|
||
quit_handler = remote_fileio_o_quit_handler;
|
||
putpkt (remote, buf);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_ioerror (remote_target *remote)
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EIO);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_badfd (remote_target *remote)
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EBADF);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_return_errno (remote_target *remote, int retcode)
|
||
{
|
||
remote_fileio_reply (remote, retcode, retcode < 0
|
||
? host_to_fileio_error (errno) : 0);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_return_success (remote_target *remote, int retcode)
|
||
{
|
||
remote_fileio_reply (remote, retcode, 0);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_open (remote_target *remote, char *buf)
|
||
{
|
||
CORE_ADDR ptrval;
|
||
int length;
|
||
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 (remote);
|
||
return;
|
||
}
|
||
/* 2. Parameter: open flags */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
flags = remote_fileio_oflags_to_host (num);
|
||
/* 3. Parameter: open mode */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
mode = remote_fileio_mode_to_host (num, 1);
|
||
|
||
/* Request pathname. */
|
||
pathname = (char *) alloca (length);
|
||
if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0)
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
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 (remote, -1, FILEIO_ENODEV);
|
||
return;
|
||
}
|
||
if (S_ISDIR (st.st_mode)
|
||
&& ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR))
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EISDIR);
|
||
return;
|
||
}
|
||
}
|
||
|
||
fd = gdb_open_cloexec (pathname, flags, mode);
|
||
if (fd < 0)
|
||
{
|
||
remote_fileio_return_errno (remote, -1);
|
||
return;
|
||
}
|
||
|
||
fd = remote_fileio_fd_to_targetfd (fd);
|
||
remote_fileio_return_success (remote, fd);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_close (remote_target *remote, char *buf)
|
||
{
|
||
long num;
|
||
int fd;
|
||
|
||
/* Parameter: file descriptor */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
fd = remote_fileio_map_fd ((int) num);
|
||
if (fd == FIO_FD_INVALID)
|
||
{
|
||
remote_fileio_badfd (remote);
|
||
return;
|
||
}
|
||
|
||
if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd))
|
||
remote_fileio_return_errno (remote, -1);
|
||
remote_fileio_close_target_fd ((int) num);
|
||
remote_fileio_return_success (remote, 0);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_read (remote_target *remote, char *buf)
|
||
{
|
||
long target_fd, num;
|
||
LONGEST lnum;
|
||
CORE_ADDR ptrval;
|
||
int fd, ret;
|
||
gdb_byte *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 (remote);
|
||
return;
|
||
}
|
||
fd = remote_fileio_map_fd ((int) target_fd);
|
||
if (fd == FIO_FD_INVALID)
|
||
{
|
||
remote_fileio_badfd (remote);
|
||
return;
|
||
}
|
||
/* 2. Parameter: buffer pointer */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
ptrval = (CORE_ADDR) lnum;
|
||
/* 3. Parameter: buffer length */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
length = (size_t) num;
|
||
|
||
switch (fd)
|
||
{
|
||
case FIO_FD_CONSOLE_OUT:
|
||
remote_fileio_badfd (remote);
|
||
return;
|
||
case FIO_FD_CONSOLE_IN:
|
||
{
|
||
static char *remaining_buf = NULL;
|
||
static int remaining_length = 0;
|
||
|
||
buffer = (gdb_byte *) xmalloc (16384);
|
||
if (remaining_buf)
|
||
{
|
||
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
|
||
{
|
||
/* Windows (at least XP and Server 2003) has difficulty
|
||
with large reads from consoles. If a handle is
|
||
backed by a real console device, overly large reads
|
||
from the handle will fail and set errno == ENOMEM.
|
||
On a Windows Server 2003 system where I tested,
|
||
reading 26608 bytes from the console was OK, but
|
||
anything above 26609 bytes would fail. The limit has
|
||
been observed to vary on different systems. So, we
|
||
limit this read to something smaller than that - by a
|
||
safe margin, in case the limit depends on system
|
||
resources or version. */
|
||
ret = gdb_stdtargin->read ((char *) buffer, 16383);
|
||
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 = (gdb_byte *) 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);
|
||
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)
|
||
{
|
||
errno = target_write_memory (ptrval, buffer, ret);
|
||
if (errno != 0)
|
||
ret = -1;
|
||
}
|
||
|
||
if (ret < 0)
|
||
remote_fileio_return_errno (remote, -1);
|
||
else
|
||
remote_fileio_return_success (remote, ret);
|
||
|
||
xfree (buffer);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_write (remote_target *remote, char *buf)
|
||
{
|
||
long target_fd, num;
|
||
LONGEST lnum;
|
||
CORE_ADDR ptrval;
|
||
int fd, ret;
|
||
gdb_byte *buffer;
|
||
size_t length;
|
||
|
||
/* 1. Parameter: file descriptor */
|
||
if (remote_fileio_extract_int (&buf, &target_fd))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
fd = remote_fileio_map_fd ((int) target_fd);
|
||
if (fd == FIO_FD_INVALID)
|
||
{
|
||
remote_fileio_badfd (remote);
|
||
return;
|
||
}
|
||
/* 2. Parameter: buffer pointer */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
ptrval = (CORE_ADDR) lnum;
|
||
/* 3. Parameter: buffer length */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
length = (size_t) num;
|
||
|
||
buffer = (gdb_byte *) xmalloc (length);
|
||
if (target_read_memory (ptrval, buffer, length) != 0)
|
||
{
|
||
xfree (buffer);
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
switch (fd)
|
||
{
|
||
case FIO_FD_CONSOLE_IN:
|
||
remote_fileio_badfd (remote);
|
||
xfree (buffer);
|
||
return;
|
||
case FIO_FD_CONSOLE_OUT:
|
||
{
|
||
ui_file *file = target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr;
|
||
file->write ((char *) buffer, length);
|
||
file->flush ();
|
||
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 (remote, -1);
|
||
else
|
||
remote_fileio_return_success (remote, ret);
|
||
|
||
xfree (buffer);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_lseek (remote_target *remote, char *buf)
|
||
{
|
||
long num;
|
||
LONGEST lnum;
|
||
int fd, flag;
|
||
off_t offset, ret;
|
||
|
||
/* 1. Parameter: file descriptor */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
fd = remote_fileio_map_fd ((int) num);
|
||
if (fd == FIO_FD_INVALID)
|
||
{
|
||
remote_fileio_badfd (remote);
|
||
return;
|
||
}
|
||
else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_ESPIPE);
|
||
return;
|
||
}
|
||
|
||
/* 2. Parameter: offset */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
offset = (off_t) lnum;
|
||
/* 3. Parameter: flag */
|
||
if (remote_fileio_extract_int (&buf, &num))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
if (remote_fileio_seek_flag_to_host (num, &flag))
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EINVAL);
|
||
return;
|
||
}
|
||
|
||
ret = lseek (fd, offset, flag);
|
||
|
||
if (ret == (off_t) -1)
|
||
remote_fileio_return_errno (remote, -1);
|
||
else
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_rename (remote_target *remote, char *buf)
|
||
{
|
||
CORE_ADDR old_ptr, new_ptr;
|
||
int old_len, new_len;
|
||
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, &old_ptr, &old_len))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
/* 2. Parameter: Ptr to newpath / length incl. trailing zero */
|
||
if (remote_fileio_extract_ptr_w_len (&buf, &new_ptr, &new_len))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
/* Request oldpath using 'm' packet */
|
||
oldpath = (char *) alloca (old_len);
|
||
if (target_read_memory (old_ptr, (gdb_byte *) oldpath, old_len) != 0)
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
/* Request newpath using 'm' packet */
|
||
newpath = (char *) alloca (new_len);
|
||
if (target_read_memory (new_ptr, (gdb_byte *) newpath, new_len) != 0)
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
/* Only operate on regular files and directories. */
|
||
of = stat (oldpath, &ost);
|
||
nf = stat (newpath, &nst);
|
||
if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
|
||
|| (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EACCES);
|
||
return;
|
||
}
|
||
|
||
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];
|
||
char newfullpath[PATH_MAX];
|
||
int len;
|
||
|
||
cygwin_conv_path (CCP_WIN_A_TO_POSIX, oldpath, oldfullpath,
|
||
PATH_MAX);
|
||
cygwin_conv_path (CCP_WIN_A_TO_POSIX, newpath, newfullpath,
|
||
PATH_MAX);
|
||
len = strlen (oldfullpath);
|
||
if (IS_DIR_SEPARATOR (newfullpath[len])
|
||
&& !filename_ncmp (oldfullpath, newfullpath, len))
|
||
errno = EINVAL;
|
||
else
|
||
errno = EEXIST;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
remote_fileio_return_errno (remote, -1);
|
||
}
|
||
else
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_unlink (remote_target *remote, char *buf)
|
||
{
|
||
CORE_ADDR ptrval;
|
||
int length;
|
||
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 (remote);
|
||
return;
|
||
}
|
||
/* Request pathname using 'm' packet */
|
||
pathname = (char *) alloca (length);
|
||
if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0)
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
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 (remote, -1, FILEIO_ENODEV);
|
||
return;
|
||
}
|
||
|
||
ret = unlink (pathname);
|
||
|
||
if (ret == -1)
|
||
remote_fileio_return_errno (remote, -1);
|
||
else
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_stat (remote_target *remote, char *buf)
|
||
{
|
||
CORE_ADDR statptr, nameptr;
|
||
int ret, namelength;
|
||
char *pathname;
|
||
LONGEST 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, &nameptr, &namelength))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
/* 2. Parameter: Ptr to struct stat */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
statptr = (CORE_ADDR) lnum;
|
||
|
||
/* Request pathname using 'm' packet */
|
||
pathname = (char *) alloca (namelength);
|
||
if (target_read_memory (nameptr, (gdb_byte *) pathname, namelength) != 0)
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
ret = stat (pathname, &st);
|
||
|
||
if (ret == -1)
|
||
{
|
||
remote_fileio_return_errno (remote, -1);
|
||
return;
|
||
}
|
||
/* Only operate on regular files and directories. */
|
||
if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EACCES);
|
||
return;
|
||
}
|
||
if (statptr)
|
||
{
|
||
host_to_fileio_stat (&st, &fst);
|
||
host_to_fileio_uint (0, fst.fst_dev);
|
||
|
||
errno = target_write_memory (statptr, (gdb_byte *) &fst, sizeof fst);
|
||
if (errno != 0)
|
||
{
|
||
remote_fileio_return_errno (remote, -1);
|
||
return;
|
||
}
|
||
}
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_fstat (remote_target *remote, char *buf)
|
||
{
|
||
CORE_ADDR ptrval;
|
||
int fd, ret;
|
||
long target_fd;
|
||
LONGEST 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 (remote);
|
||
return;
|
||
}
|
||
fd = remote_fileio_map_fd ((int) target_fd);
|
||
if (fd == FIO_FD_INVALID)
|
||
{
|
||
remote_fileio_badfd (remote);
|
||
return;
|
||
}
|
||
/* 2. Parameter: Ptr to struct stat */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
ptrval = (CORE_ADDR) lnum;
|
||
|
||
if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
|
||
{
|
||
host_to_fileio_uint (1, fst.fst_dev);
|
||
memset (&st, 0, sizeof (st));
|
||
st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
|
||
st.st_nlink = 1;
|
||
#ifdef HAVE_GETUID
|
||
st.st_uid = getuid ();
|
||
#endif
|
||
#ifdef HAVE_GETGID
|
||
st.st_gid = getgid ();
|
||
#endif
|
||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||
st.st_blksize = 512;
|
||
#endif
|
||
#if HAVE_STRUCT_STAT_ST_BLOCKS
|
||
st.st_blocks = 0;
|
||
#endif
|
||
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 (remote, -1);
|
||
return;
|
||
}
|
||
if (ptrval)
|
||
{
|
||
host_to_fileio_stat (&st, &fst);
|
||
|
||
errno = target_write_memory (ptrval, (gdb_byte *) &fst, sizeof fst);
|
||
if (errno != 0)
|
||
{
|
||
remote_fileio_return_errno (remote, -1);
|
||
return;
|
||
}
|
||
}
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_gettimeofday (remote_target *remote, char *buf)
|
||
{
|
||
LONGEST lnum;
|
||
CORE_ADDR ptrval;
|
||
int ret;
|
||
struct timeval tv;
|
||
struct fio_timeval ftv;
|
||
|
||
/* 1. Parameter: struct timeval pointer */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
ptrval = (CORE_ADDR) lnum;
|
||
/* 2. Parameter: some pointer value... */
|
||
if (remote_fileio_extract_long (&buf, &lnum))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
/* ...which has to be NULL. */
|
||
if (lnum)
|
||
{
|
||
remote_fileio_reply (remote, -1, FILEIO_EINVAL);
|
||
return;
|
||
}
|
||
|
||
ret = gettimeofday (&tv, NULL);
|
||
|
||
if (ret == -1)
|
||
{
|
||
remote_fileio_return_errno (remote, -1);
|
||
return;
|
||
}
|
||
|
||
if (ptrval)
|
||
{
|
||
remote_fileio_to_fio_timeval (&tv, &ftv);
|
||
|
||
errno = target_write_memory (ptrval, (gdb_byte *) &ftv, sizeof ftv);
|
||
if (errno != 0)
|
||
{
|
||
remote_fileio_return_errno (remote, -1);
|
||
return;
|
||
}
|
||
}
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_isatty (remote_target *remote, char *buf)
|
||
{
|
||
long target_fd;
|
||
int fd;
|
||
|
||
/* Parameter: file descriptor */
|
||
if (remote_fileio_extract_int (&buf, &target_fd))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
fd = remote_fileio_map_fd ((int) target_fd);
|
||
int ret = fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT ? 1 : 0;
|
||
remote_fileio_return_success (remote, ret);
|
||
}
|
||
|
||
static void
|
||
remote_fileio_func_system (remote_target *remote, char *buf)
|
||
{
|
||
CORE_ADDR ptrval;
|
||
int ret, length;
|
||
char *cmdline = NULL;
|
||
|
||
/* Parameter: Ptr to commandline / length incl. trailing zero */
|
||
if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
|
||
if (length)
|
||
{
|
||
/* Request commandline using 'm' packet */
|
||
cmdline = (char *) alloca (length);
|
||
if (target_read_memory (ptrval, (gdb_byte *) cmdline, length) != 0)
|
||
{
|
||
remote_fileio_ioerror (remote);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* Check if system(3) has been explicitly allowed using the
|
||
`set remote system-call-allowed 1' command. If length is 0,
|
||
indicating a NULL parameter to the system call, return zero to
|
||
indicate a shell is not available. Otherwise fail with EPERM. */
|
||
if (!remote_fio_system_call_allowed)
|
||
{
|
||
if (!length)
|
||
remote_fileio_return_success (remote, 0);
|
||
else
|
||
remote_fileio_reply (remote, -1, FILEIO_EPERM);
|
||
return;
|
||
}
|
||
|
||
ret = system (cmdline);
|
||
|
||
if (!length)
|
||
remote_fileio_return_success (remote, ret);
|
||
else if (ret == -1)
|
||
remote_fileio_return_errno (remote, -1);
|
||
else
|
||
remote_fileio_return_success (remote, WEXITSTATUS (ret));
|
||
}
|
||
|
||
static struct {
|
||
const char *name;
|
||
void (*func)(remote_target *remote, 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 void
|
||
do_remote_fileio_request (remote_target *remote, char *buf)
|
||
{
|
||
char *c;
|
||
int idx;
|
||
|
||
quit_handler = remote_fileio_quit_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)
|
||
remote_fileio_reply (remote, -1, FILEIO_ENOSYS);
|
||
else
|
||
remote_fio_func_map[idx].func (remote, c);
|
||
}
|
||
|
||
/* Close any open descriptors, and reinitialize the file mapping. */
|
||
|
||
void
|
||
remote_fileio_reset (void)
|
||
{
|
||
int ix;
|
||
|
||
for (ix = 0; ix != remote_fio_data.fd_map_size; ix++)
|
||
{
|
||
int fd = remote_fio_data.fd_map[ix];
|
||
|
||
if (fd >= 0)
|
||
close (fd);
|
||
}
|
||
if (remote_fio_data.fd_map)
|
||
{
|
||
xfree (remote_fio_data.fd_map);
|
||
remote_fio_data.fd_map = NULL;
|
||
remote_fio_data.fd_map_size = 0;
|
||
}
|
||
}
|
||
|
||
/* 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
|
||
acknowledged the Ctrl-C sent asynchronously earlier. */
|
||
|
||
void
|
||
remote_fileio_request (remote_target *remote, char *buf, int ctrlc_pending_p)
|
||
{
|
||
/* Save the previous quit handler, so we can restore it. No need
|
||
for a cleanup since we catch all exceptions below. Note that the
|
||
quit handler is also restored by remote_fileio_reply just before
|
||
pushing a packet. */
|
||
remote_fileio_o_quit_handler = quit_handler;
|
||
|
||
if (ctrlc_pending_p)
|
||
{
|
||
/* If the target hasn't responded to the Ctrl-C sent
|
||
asynchronously earlier, take this opportunity to send the
|
||
Ctrl-C synchronously. */
|
||
set_quit_flag ();
|
||
remote_fileio_reply (remote, -1, FILEIO_EINTR);
|
||
}
|
||
else
|
||
{
|
||
try
|
||
{
|
||
do_remote_fileio_request (remote, buf);
|
||
}
|
||
catch (const gdb_exception &ex)
|
||
{
|
||
if (ex.reason == RETURN_QUIT)
|
||
remote_fileio_reply (remote, -1, FILEIO_EINTR);
|
||
else
|
||
remote_fileio_reply (remote, -1, FILEIO_EIO);
|
||
}
|
||
}
|
||
|
||
quit_handler = remote_fileio_o_quit_handler;
|
||
}
|
||
|
||
|
||
/* Unpack an fio_uint_t. */
|
||
|
||
static unsigned int
|
||
remote_fileio_to_host_uint (fio_uint_t fnum)
|
||
{
|
||
return extract_unsigned_integer ((gdb_byte *) fnum, 4,
|
||
BFD_ENDIAN_BIG);
|
||
}
|
||
|
||
/* Unpack an fio_ulong_t. */
|
||
|
||
static ULONGEST
|
||
remote_fileio_to_host_ulong (fio_ulong_t fnum)
|
||
{
|
||
return extract_unsigned_integer ((gdb_byte *) fnum, 8,
|
||
BFD_ENDIAN_BIG);
|
||
}
|
||
|
||
/* Unpack an fio_mode_t. */
|
||
|
||
static mode_t
|
||
remote_fileio_to_host_mode (fio_mode_t fnum)
|
||
{
|
||
return remote_fileio_mode_to_host (remote_fileio_to_host_uint (fnum),
|
||
0);
|
||
}
|
||
|
||
/* Unpack an fio_time_t. */
|
||
|
||
static time_t
|
||
remote_fileio_to_host_time (fio_time_t fnum)
|
||
{
|
||
return remote_fileio_to_host_uint (fnum);
|
||
}
|
||
|
||
|
||
/* See remote-fileio.h. */
|
||
|
||
void
|
||
remote_fileio_to_host_stat (struct fio_stat *fst, struct stat *st)
|
||
{
|
||
memset (st, 0, sizeof (struct stat));
|
||
|
||
st->st_dev = remote_fileio_to_host_uint (fst->fst_dev);
|
||
st->st_ino = remote_fileio_to_host_uint (fst->fst_ino);
|
||
st->st_mode = remote_fileio_to_host_mode (fst->fst_mode);
|
||
st->st_nlink = remote_fileio_to_host_uint (fst->fst_nlink);
|
||
st->st_uid = remote_fileio_to_host_uint (fst->fst_uid);
|
||
st->st_gid = remote_fileio_to_host_uint (fst->fst_gid);
|
||
st->st_rdev = remote_fileio_to_host_uint (fst->fst_rdev);
|
||
st->st_size = remote_fileio_to_host_ulong (fst->fst_size);
|
||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||
st->st_blksize = remote_fileio_to_host_ulong (fst->fst_blksize);
|
||
#endif
|
||
#if HAVE_STRUCT_STAT_ST_BLOCKS
|
||
st->st_blocks = remote_fileio_to_host_ulong (fst->fst_blocks);
|
||
#endif
|
||
st->st_atime = remote_fileio_to_host_time (fst->fst_atime);
|
||
st->st_mtime = remote_fileio_to_host_time (fst->fst_mtime);
|
||
st->st_ctime = remote_fileio_to_host_time (fst->fst_ctime);
|
||
}
|
||
|
||
|
||
static void
|
||
set_system_call_allowed (const 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 (const 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."),
|
||
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."),
|
||
remote_show_cmdlist);
|
||
}
|