1/* Remote File-I/O communications
2
3   Copyright 2003 Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330,
20   Boston, MA 02111-1307, USA.  */
21
22/* See the GDB User Guide for details of the GDB remote protocol. */
23
24#include "defs.h"
25#include "gdb_string.h"
26#include "gdbcmd.h"
27#include "remote.h"
28#include "gdb/fileio.h"
29#include "gdb_wait.h"
30#include "gdb_stat.h"
31#include "remote-fileio.h"
32
33#include <fcntl.h>
34#include <sys/time.h>
35#ifdef __CYGWIN__
36#include <sys/cygwin.h>		/* For cygwin_conv_to_full_posix_path.  */
37#endif
38#include <signal.h>
39
40static struct {
41  int *fd_map;
42  int fd_map_size;
43} remote_fio_data;
44
45#define FIO_FD_INVALID		-1
46#define FIO_FD_CONSOLE_IN	-2
47#define FIO_FD_CONSOLE_OUT	-3
48
49static int remote_fio_system_call_allowed = 0;
50
51static int
52remote_fileio_init_fd_map (void)
53{
54  int i;
55
56  if (!remote_fio_data.fd_map)
57    {
58      remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int));
59      remote_fio_data.fd_map_size = 10;
60      remote_fio_data.fd_map[0] = FIO_FD_CONSOLE_IN;
61      remote_fio_data.fd_map[1] = FIO_FD_CONSOLE_OUT;
62      remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT;
63      for (i = 3; i < 10; ++i)
64        remote_fio_data.fd_map[i] = FIO_FD_INVALID;
65    }
66  return 3;
67}
68
69static int
70remote_fileio_resize_fd_map (void)
71{
72  if (!remote_fio_data.fd_map)
73    return remote_fileio_init_fd_map ();
74  remote_fio_data.fd_map_size += 10;
75  remote_fio_data.fd_map =
76    (int *) xrealloc (remote_fio_data.fd_map,
77		      remote_fio_data.fd_map_size * sizeof (int));
78  return remote_fio_data.fd_map_size - 10;
79}
80
81static int
82remote_fileio_next_free_fd (void)
83{
84  int i;
85
86  for (i = 0; i < remote_fio_data.fd_map_size; ++i)
87    if (remote_fio_data.fd_map[i] == FIO_FD_INVALID)
88      return i;
89  return remote_fileio_resize_fd_map ();
90}
91
92static int
93remote_fileio_fd_to_targetfd (int fd)
94{
95  int target_fd = remote_fileio_next_free_fd ();
96  remote_fio_data.fd_map[target_fd] = fd;
97  return target_fd;
98}
99
100static int
101remote_fileio_map_fd (int target_fd)
102{
103  remote_fileio_init_fd_map ();
104  if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size)
105    return FIO_FD_INVALID;
106  return remote_fio_data.fd_map[target_fd];
107}
108
109static void
110remote_fileio_close_target_fd (int target_fd)
111{
112  remote_fileio_init_fd_map ();
113  if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size)
114    remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID;
115}
116
117static int
118remote_fileio_oflags_to_host (long flags)
119{
120  int hflags = 0;
121
122  if (flags & FILEIO_O_CREAT)
123    hflags |= O_CREAT;
124  if (flags & FILEIO_O_EXCL)
125    hflags |= O_EXCL;
126  if (flags & FILEIO_O_TRUNC)
127    hflags |= O_TRUNC;
128  if (flags & FILEIO_O_APPEND)
129    hflags |= O_APPEND;
130  if (flags & FILEIO_O_RDONLY)
131    hflags |= O_RDONLY;
132  if (flags & FILEIO_O_WRONLY)
133    hflags |= O_WRONLY;
134  if (flags & FILEIO_O_RDWR)
135    hflags |= O_RDWR;
136/* On systems supporting binary and text mode, always open files in
137   binary mode. */
138#ifdef O_BINARY
139  hflags |= O_BINARY;
140#endif
141  return hflags;
142}
143
144static mode_t
145remote_fileio_mode_to_host (long mode, int open_call)
146{
147  mode_t hmode = 0;
148
149  if (!open_call)
150    {
151      if (mode & FILEIO_S_IFREG)
152	hmode |= S_IFREG;
153      if (mode & FILEIO_S_IFDIR)
154	hmode |= S_IFDIR;
155      if (mode & FILEIO_S_IFCHR)
156	hmode |= S_IFCHR;
157    }
158  if (mode & FILEIO_S_IRUSR)
159    hmode |= S_IRUSR;
160  if (mode & FILEIO_S_IWUSR)
161    hmode |= S_IWUSR;
162  if (mode & FILEIO_S_IXUSR)
163    hmode |= S_IXUSR;
164  if (mode & FILEIO_S_IRGRP)
165    hmode |= S_IRGRP;
166  if (mode & FILEIO_S_IWGRP)
167    hmode |= S_IWGRP;
168  if (mode & FILEIO_S_IXGRP)
169    hmode |= S_IXGRP;
170  if (mode & FILEIO_S_IROTH)
171    hmode |= S_IROTH;
172  if (mode & FILEIO_S_IWOTH)
173    hmode |= S_IWOTH;
174  if (mode & FILEIO_S_IXOTH)
175    hmode |= S_IXOTH;
176  return hmode;
177}
178
179static LONGEST
180remote_fileio_mode_to_target (mode_t mode)
181{
182  mode_t tmode = 0;
183
184  if (mode & S_IFREG)
185    tmode |= FILEIO_S_IFREG;
186  if (mode & S_IFDIR)
187    tmode |= FILEIO_S_IFDIR;
188  if (mode & S_IFCHR)
189    tmode |= FILEIO_S_IFCHR;
190  if (mode & S_IRUSR)
191    tmode |= FILEIO_S_IRUSR;
192  if (mode & S_IWUSR)
193    tmode |= FILEIO_S_IWUSR;
194  if (mode & S_IXUSR)
195    tmode |= FILEIO_S_IXUSR;
196  if (mode & S_IRGRP)
197    tmode |= FILEIO_S_IRGRP;
198  if (mode & S_IWGRP)
199    tmode |= FILEIO_S_IWGRP;
200  if (mode & S_IXGRP)
201    tmode |= FILEIO_S_IXGRP;
202  if (mode & S_IROTH)
203    tmode |= FILEIO_S_IROTH;
204  if (mode & S_IWOTH)
205    tmode |= FILEIO_S_IWOTH;
206  if (mode & S_IXOTH)
207    tmode |= FILEIO_S_IXOTH;
208  return tmode;
209}
210
211static int
212remote_fileio_errno_to_target (int error)
213{
214  switch (error)
215    {
216      case EPERM:
217        return FILEIO_EPERM;
218      case ENOENT:
219        return FILEIO_ENOENT;
220      case EINTR:
221        return FILEIO_EINTR;
222      case EIO:
223        return FILEIO_EIO;
224      case EBADF:
225        return FILEIO_EBADF;
226      case EACCES:
227        return FILEIO_EACCES;
228      case EFAULT:
229        return FILEIO_EFAULT;
230      case EBUSY:
231        return FILEIO_EBUSY;
232      case EEXIST:
233        return FILEIO_EEXIST;
234      case ENODEV:
235        return FILEIO_ENODEV;
236      case ENOTDIR:
237        return FILEIO_ENOTDIR;
238      case EISDIR:
239        return FILEIO_EISDIR;
240      case EINVAL:
241        return FILEIO_EINVAL;
242      case ENFILE:
243        return FILEIO_ENFILE;
244      case EMFILE:
245        return FILEIO_EMFILE;
246      case EFBIG:
247        return FILEIO_EFBIG;
248      case ENOSPC:
249        return FILEIO_ENOSPC;
250      case ESPIPE:
251        return FILEIO_ESPIPE;
252      case EROFS:
253        return FILEIO_EROFS;
254      case ENOSYS:
255        return FILEIO_ENOSYS;
256      case ENAMETOOLONG:
257        return FILEIO_ENAMETOOLONG;
258    }
259  return FILEIO_EUNKNOWN;
260}
261
262static int
263remote_fileio_seek_flag_to_host (long num, int *flag)
264{
265  if (!flag)
266    return 0;
267  switch (num)
268    {
269      case FILEIO_SEEK_SET:
270        *flag = SEEK_SET;
271	break;
272      case FILEIO_SEEK_CUR:
273        *flag =  SEEK_CUR;
274	break;
275      case FILEIO_SEEK_END:
276        *flag =  SEEK_END;
277	break;
278      default:
279        return -1;
280    }
281  return 0;
282}
283
284static int
285remote_fileio_extract_long (char **buf, LONGEST *retlong)
286{
287  char *c;
288  int sign = 1;
289
290  if (!buf || !*buf || !**buf || !retlong)
291    return -1;
292  c = strchr (*buf, ',');
293  if (c)
294    *c++ = '\0';
295  else
296    c = strchr (*buf, '\0');
297  while (strchr ("+-", **buf))
298    {
299      if (**buf == '-')
300	sign = -sign;
301      ++*buf;
302    }
303  for (*retlong = 0; **buf; ++*buf)
304    {
305      *retlong <<= 4;
306      if (**buf >= '0' && **buf <= '9')
307        *retlong += **buf - '0';
308      else if (**buf >= 'a' && **buf <= 'f')
309        *retlong += **buf - 'a' + 10;
310      else if (**buf >= 'A' && **buf <= 'F')
311        *retlong += **buf - 'A' + 10;
312      else
313        return -1;
314    }
315  *retlong *= sign;
316  *buf = c;
317  return 0;
318}
319
320static int
321remote_fileio_extract_int (char **buf, long *retint)
322{
323  int ret;
324  LONGEST retlong;
325
326  if (!retint)
327    return -1;
328  ret = remote_fileio_extract_long (buf, &retlong);
329  if (!ret)
330    *retint = (long) retlong;
331  return ret;
332}
333
334static int
335remote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length)
336{
337  char *c;
338  LONGEST retlong;
339
340  if (!buf || !*buf || !**buf || !ptrval || !length)
341    return -1;
342  c = strchr (*buf, '/');
343  if (!c)
344    return -1;
345  *c++ = '\0';
346  if (remote_fileio_extract_long (buf, &retlong))
347    return -1;
348  *ptrval = (CORE_ADDR) retlong;
349  *buf = c;
350  if (remote_fileio_extract_long (buf, &retlong))
351    return -1;
352  *length = (int) retlong;
353  return 0;
354}
355
356/* Convert to big endian */
357static void
358remote_fileio_to_be (LONGEST num, char *buf, int bytes)
359{
360  int i;
361
362  for (i = 0; i < bytes; ++i)
363    buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff;
364}
365
366static void
367remote_fileio_to_fio_uint (long num, fio_uint_t fnum)
368{
369  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
370}
371
372static void
373remote_fileio_to_fio_mode (mode_t num, fio_mode_t fnum)
374{
375  remote_fileio_to_be (remote_fileio_mode_to_target(num), (char *) fnum, 4);
376}
377
378static void
379remote_fileio_to_fio_time (time_t num, fio_time_t fnum)
380{
381  remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4);
382}
383
384static void
385remote_fileio_to_fio_long (LONGEST num, fio_long_t fnum)
386{
387  remote_fileio_to_be (num, (char *) fnum, 8);
388}
389
390static void
391remote_fileio_to_fio_ulong (LONGEST num, fio_ulong_t fnum)
392{
393  remote_fileio_to_be (num, (char *) fnum, 8);
394}
395
396static void
397remote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst)
398{
399  /* `st_dev' is set in the calling function */
400  remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino);
401  remote_fileio_to_fio_mode (st->st_mode, fst->fst_mode);
402  remote_fileio_to_fio_uint ((long) st->st_nlink, fst->fst_nlink);
403  remote_fileio_to_fio_uint ((long) st->st_uid, fst->fst_uid);
404  remote_fileio_to_fio_uint ((long) st->st_gid, fst->fst_gid);
405  remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev);
406  remote_fileio_to_fio_ulong ((LONGEST) st->st_size, fst->fst_size);
407  remote_fileio_to_fio_ulong ((LONGEST) st->st_blksize, fst->fst_blksize);
408#if HAVE_STRUCT_STAT_ST_BLOCKS
409  remote_fileio_to_fio_ulong ((LONGEST) st->st_blocks, fst->fst_blocks);
410#else
411  /* FIXME: This is correct for DJGPP, but other systems that don't
412     have st_blocks, if any, might prefer 512 instead of st_blksize.
413     (eliz, 30-12-2003)  */
414  remote_fileio_to_fio_ulong (((LONGEST) st->st_size + st->st_blksize - 1)
415			      / (LONGEST) st->st_blksize,
416			      fst->fst_blocks);
417#endif
418  remote_fileio_to_fio_time (st->st_atime, fst->fst_atime);
419  remote_fileio_to_fio_time (st->st_mtime, fst->fst_mtime);
420  remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime);
421}
422
423static void
424remote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv)
425{
426  remote_fileio_to_fio_time (tv->tv_sec, ftv->ftv_sec);
427  remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec);
428}
429
430static int remote_fio_ctrl_c_flag = 0;
431static int remote_fio_no_longjmp = 0;
432
433#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
434static struct sigaction remote_fio_sa;
435static struct sigaction remote_fio_osa;
436#else
437static void (*remote_fio_ofunc)(int);
438#endif
439
440static void
441remote_fileio_sig_init (void)
442{
443#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
444  remote_fio_sa.sa_handler = SIG_IGN;
445  sigemptyset (&remote_fio_sa.sa_mask);
446  remote_fio_sa.sa_flags = 0;
447  sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa);
448#else
449  remote_fio_ofunc = signal (SIGINT, SIG_IGN);
450#endif
451}
452
453static void
454remote_fileio_sig_set (void (*sigint_func)(int))
455{
456#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
457  remote_fio_sa.sa_handler = sigint_func;
458  sigemptyset (&remote_fio_sa.sa_mask);
459  remote_fio_sa.sa_flags = 0;
460  sigaction (SIGINT, &remote_fio_sa, NULL);
461#else
462  signal (SIGINT, sigint_func);
463#endif
464}
465
466static void
467remote_fileio_sig_exit (void)
468{
469#if defined (HAVE_SIGACTION) && defined (SA_RESTART)
470  sigaction (SIGINT, &remote_fio_osa, NULL);
471#else
472  signal (SIGINT, remote_fio_ofunc);
473#endif
474}
475
476static void
477remote_fileio_ctrl_c_signal_handler (int signo)
478{
479  remote_fileio_sig_set (SIG_IGN);
480  remote_fio_ctrl_c_flag = 1;
481  if (!remote_fio_no_longjmp)
482    throw_exception (RETURN_QUIT);
483  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
484}
485
486static void
487remote_fileio_reply (int retcode, int error)
488{
489  char buf[32];
490
491  remote_fileio_sig_set (SIG_IGN);
492  strcpy (buf, "F");
493  if (retcode < 0)
494    {
495      strcat (buf, "-");
496      retcode = -retcode;
497    }
498  sprintf (buf + strlen (buf), "%x", retcode);
499  if (error || remote_fio_ctrl_c_flag)
500    {
501      if (error && remote_fio_ctrl_c_flag)
502        error = FILEIO_EINTR;
503      if (error < 0)
504        {
505	  strcat (buf, "-");
506	  error = -error;
507	}
508      sprintf (buf + strlen (buf), ",%x", error);
509      if (remote_fio_ctrl_c_flag)
510        strcat (buf, ",C");
511    }
512  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
513  putpkt (buf);
514}
515
516static void
517remote_fileio_ioerror (void)
518{
519  remote_fileio_reply (-1, FILEIO_EIO);
520}
521
522static void
523remote_fileio_badfd (void)
524{
525  remote_fileio_reply (-1, FILEIO_EBADF);
526}
527
528static void
529remote_fileio_return_errno (int retcode)
530{
531  remote_fileio_reply (retcode,
532		       retcode < 0 ? remote_fileio_errno_to_target (errno) : 0);
533}
534
535static void
536remote_fileio_return_success (int retcode)
537{
538  remote_fileio_reply (retcode, 0);
539}
540
541/* Wrapper function for remote_write_bytes() which has the disadvantage to
542   write only one packet, regardless of the requested number of bytes to
543   transfer.  This wrapper calls remote_write_bytes() as often as needed. */
544static int
545remote_fileio_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
546{
547  int ret = 0, written;
548
549  while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0)
550    {
551      len -= written;
552      memaddr += written;
553      myaddr += written;
554      ret += written;
555    }
556  return ret;
557}
558
559static void
560remote_fileio_func_open (char *buf)
561{
562  CORE_ADDR ptrval;
563  int length, retlength;
564  long num;
565  int flags, fd;
566  mode_t mode;
567  char *pathname;
568  struct stat st;
569
570  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
571  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
572    {
573      remote_fileio_ioerror ();
574      return;
575    }
576  /* 2. Parameter: open flags */
577  if (remote_fileio_extract_int (&buf, &num))
578    {
579      remote_fileio_ioerror ();
580      return;
581    }
582  flags = remote_fileio_oflags_to_host (num);
583  /* 3. Parameter: open mode */
584  if (remote_fileio_extract_int (&buf, &num))
585    {
586      remote_fileio_ioerror ();
587      return;
588    }
589  mode = remote_fileio_mode_to_host (num, 1);
590
591  /* Request pathname using 'm' packet */
592  pathname = alloca (length);
593  retlength = remote_read_bytes (ptrval, pathname, length);
594  if (retlength != length)
595    {
596      remote_fileio_ioerror ();
597      return;
598    }
599
600  /* Check if pathname exists and is not a regular file or directory.  If so,
601     return an appropriate error code.  Same for trying to open directories
602     for writing. */
603  if (!stat (pathname, &st))
604    {
605      if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
606	{
607	  remote_fileio_reply (-1, FILEIO_ENODEV);
608	  return;
609	}
610      if (S_ISDIR (st.st_mode)
611	  && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR))
612	{
613	  remote_fileio_reply (-1, FILEIO_EISDIR);
614	  return;
615	}
616    }
617
618  remote_fio_no_longjmp = 1;
619  fd = open (pathname, flags, mode);
620  if (fd < 0)
621    {
622      remote_fileio_return_errno (-1);
623      return;
624    }
625
626  fd = remote_fileio_fd_to_targetfd (fd);
627  remote_fileio_return_success (fd);
628}
629
630static void
631remote_fileio_func_close (char *buf)
632{
633  long num;
634  int fd;
635
636  /* Parameter: file descriptor */
637  if (remote_fileio_extract_int (&buf, &num))
638    {
639      remote_fileio_ioerror ();
640      return;
641    }
642  fd = remote_fileio_map_fd ((int) num);
643  if (fd == FIO_FD_INVALID)
644    {
645      remote_fileio_badfd ();
646      return;
647    }
648
649  remote_fio_no_longjmp = 1;
650  if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd))
651    remote_fileio_return_errno (-1);
652  remote_fileio_close_target_fd ((int) num);
653  remote_fileio_return_success (0);
654}
655
656static void
657remote_fileio_func_read (char *buf)
658{
659  long target_fd, num;
660  LONGEST lnum;
661  CORE_ADDR ptrval;
662  int fd, ret, retlength;
663  char *buffer;
664  size_t length;
665  off_t old_offset, new_offset;
666
667  /* 1. Parameter: file descriptor */
668  if (remote_fileio_extract_int (&buf, &target_fd))
669    {
670      remote_fileio_ioerror ();
671      return;
672    }
673  fd = remote_fileio_map_fd ((int) target_fd);
674  if (fd == FIO_FD_INVALID)
675    {
676      remote_fileio_badfd ();
677      return;
678    }
679  /* 2. Parameter: buffer pointer */
680  if (remote_fileio_extract_long (&buf, &lnum))
681    {
682      remote_fileio_ioerror ();
683      return;
684    }
685  ptrval = (CORE_ADDR) lnum;
686  /* 3. Parameter: buffer length */
687  if (remote_fileio_extract_int (&buf, &num))
688    {
689      remote_fileio_ioerror ();
690      return;
691    }
692  length = (size_t) num;
693
694  switch (fd)
695    {
696      case FIO_FD_CONSOLE_OUT:
697	remote_fileio_badfd ();
698	return;
699      case FIO_FD_CONSOLE_IN:
700	{
701	  static char *remaining_buf = NULL;
702	  static int remaining_length = 0;
703
704	  buffer = (char *) xmalloc (32768);
705	  if (remaining_buf)
706	    {
707	      remote_fio_no_longjmp = 1;
708	      if (remaining_length > length)
709		{
710		  memcpy (buffer, remaining_buf, length);
711		  memmove (remaining_buf, remaining_buf + length,
712			   remaining_length - length);
713		  remaining_length -= length;
714		  ret = length;
715		}
716	      else
717		{
718		  memcpy (buffer, remaining_buf, remaining_length);
719		  xfree (remaining_buf);
720		  remaining_buf = NULL;
721		  ret = remaining_length;
722		}
723	    }
724	  else
725	    {
726	      ret = ui_file_read (gdb_stdtargin, buffer, 32767);
727	      remote_fio_no_longjmp = 1;
728	      if (ret > 0 && (size_t)ret > length)
729		{
730		  remaining_buf = (char *) xmalloc (ret - length);
731		  remaining_length = ret - length;
732		  memcpy (remaining_buf, buffer + length, remaining_length);
733		  ret = length;
734		}
735	    }
736	}
737	break;
738      default:
739	buffer = (char *) xmalloc (length);
740	/* POSIX defines EINTR behaviour of read in a weird way.  It's allowed
741	   for read() to return -1 even if "some" bytes have been read.  It
742	   has been corrected in SUSv2 but that doesn't help us much...
743	   Therefore a complete solution must check how many bytes have been
744	   read on EINTR to return a more reliable value to the target */
745	old_offset = lseek (fd, 0, SEEK_CUR);
746	remote_fio_no_longjmp = 1;
747	ret = read (fd, buffer, length);
748	if (ret < 0 && errno == EINTR)
749	  {
750	    new_offset = lseek (fd, 0, SEEK_CUR);
751	    /* If some data has been read, return the number of bytes read.
752	       The Ctrl-C flag is set in remote_fileio_reply() anyway */
753	    if (old_offset != new_offset)
754	      ret = new_offset - old_offset;
755	  }
756	break;
757    }
758
759  if (ret > 0)
760    {
761      retlength = remote_fileio_write_bytes (ptrval, buffer, ret);
762      if (retlength != ret)
763	ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */
764    }
765
766  if (ret < 0)
767    remote_fileio_return_errno (-1);
768  else
769    remote_fileio_return_success (ret);
770
771  xfree (buffer);
772}
773
774static void
775remote_fileio_func_write (char *buf)
776{
777  long target_fd, num;
778  LONGEST lnum;
779  CORE_ADDR ptrval;
780  int fd, ret, retlength;
781  char *buffer;
782  size_t length;
783
784  /* 1. Parameter: file descriptor */
785  if (remote_fileio_extract_int (&buf, &target_fd))
786    {
787      remote_fileio_ioerror ();
788      return;
789    }
790  fd = remote_fileio_map_fd ((int) target_fd);
791  if (fd == FIO_FD_INVALID)
792    {
793      remote_fileio_badfd ();
794      return;
795    }
796  /* 2. Parameter: buffer pointer */
797  if (remote_fileio_extract_long (&buf, &lnum))
798    {
799      remote_fileio_ioerror ();
800      return;
801    }
802  ptrval = (CORE_ADDR) lnum;
803  /* 3. Parameter: buffer length */
804  if (remote_fileio_extract_int (&buf, &num))
805    {
806      remote_fileio_ioerror ();
807      return;
808    }
809  length = (size_t) num;
810
811  buffer = (char *) xmalloc (length);
812  retlength = remote_read_bytes (ptrval, buffer, length);
813  if (retlength != length)
814    {
815      xfree (buffer);
816      remote_fileio_ioerror ();
817      return;
818    }
819
820  remote_fio_no_longjmp = 1;
821  switch (fd)
822    {
823      case FIO_FD_CONSOLE_IN:
824	remote_fileio_badfd ();
825	return;
826      case FIO_FD_CONSOLE_OUT:
827	ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr, buffer,
828		       length);
829	gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr);
830	ret = length;
831	break;
832      default:
833	ret = write (fd, buffer, length);
834	if (ret < 0 && errno == EACCES)
835	  errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/
836	break;
837    }
838
839  if (ret < 0)
840    remote_fileio_return_errno (-1);
841  else
842    remote_fileio_return_success (ret);
843
844  xfree (buffer);
845}
846
847static void
848remote_fileio_func_lseek (char *buf)
849{
850  long num;
851  LONGEST lnum;
852  int fd, flag;
853  off_t offset, ret;
854
855  /* 1. Parameter: file descriptor */
856  if (remote_fileio_extract_int (&buf, &num))
857    {
858      remote_fileio_ioerror ();
859      return;
860    }
861  fd = remote_fileio_map_fd ((int) num);
862  if (fd == FIO_FD_INVALID)
863    {
864      remote_fileio_badfd ();
865      return;
866    }
867  else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
868    {
869      remote_fileio_reply (-1, FILEIO_ESPIPE);
870      return;
871    }
872
873  /* 2. Parameter: offset */
874  if (remote_fileio_extract_long (&buf, &lnum))
875    {
876      remote_fileio_ioerror ();
877      return;
878    }
879  offset = (off_t) lnum;
880  /* 3. Parameter: flag */
881  if (remote_fileio_extract_int (&buf, &num))
882    {
883      remote_fileio_ioerror ();
884      return;
885    }
886  if (remote_fileio_seek_flag_to_host (num, &flag))
887    {
888      remote_fileio_reply (-1, FILEIO_EINVAL);
889      return;
890    }
891
892  remote_fio_no_longjmp = 1;
893  ret = lseek (fd, offset, flag);
894
895  if (ret == (off_t) -1)
896    remote_fileio_return_errno (-1);
897  else
898    remote_fileio_return_success (ret);
899}
900
901static void
902remote_fileio_func_rename (char *buf)
903{
904  CORE_ADDR ptrval;
905  int length, retlength;
906  char *oldpath, *newpath;
907  int ret, of, nf;
908  struct stat ost, nst;
909
910  /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */
911  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
912    {
913      remote_fileio_ioerror ();
914      return;
915    }
916  /* Request oldpath using 'm' packet */
917  oldpath = alloca (length);
918  retlength = remote_read_bytes (ptrval, oldpath, length);
919  if (retlength != length)
920    {
921      remote_fileio_ioerror ();
922      return;
923    }
924  /* 2. Parameter: Ptr to newpath / length incl. trailing zero */
925  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
926    {
927      remote_fileio_ioerror ();
928      return;
929    }
930  /* Request newpath using 'm' packet */
931  newpath = alloca (length);
932  retlength = remote_read_bytes (ptrval, newpath, length);
933  if (retlength != length)
934    {
935      remote_fileio_ioerror ();
936      return;
937    }
938
939  /* Only operate on regular files and directories */
940  of = stat (oldpath, &ost);
941  nf = stat (newpath, &nst);
942  if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
943      || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
944    {
945      remote_fileio_reply (-1, FILEIO_EACCES);
946      return;
947    }
948
949  remote_fio_no_longjmp = 1;
950  ret = rename (oldpath, newpath);
951
952  if (ret == -1)
953    {
954      /* Special case: newpath is a non-empty directory.  Some systems
955         return ENOTEMPTY, some return EEXIST.  We coerce that to be
956	 always EEXIST. */
957      if (errno == ENOTEMPTY)
958        errno = EEXIST;
959#ifdef __CYGWIN__
960      /* Workaround some Cygwin problems with correct errnos. */
961      if (errno == EACCES)
962        {
963	  if (!of && !nf && S_ISDIR (nst.st_mode))
964	    {
965	      if (S_ISREG (ost.st_mode))
966		errno = EISDIR;
967	      else
968		{
969		  char oldfullpath[PATH_MAX + 1];
970		  char newfullpath[PATH_MAX + 1];
971		  int len;
972
973		  cygwin_conv_to_full_posix_path (oldpath, oldfullpath);
974		  cygwin_conv_to_full_posix_path (newpath, newfullpath);
975		  len = strlen (oldfullpath);
976		  if (newfullpath[len] == '/'
977		      && !strncmp (oldfullpath, newfullpath, len))
978		    errno = EINVAL;
979		  else
980		    errno = EEXIST;
981		}
982	    }
983	}
984#endif
985
986      remote_fileio_return_errno (-1);
987    }
988  else
989    remote_fileio_return_success (ret);
990}
991
992static void
993remote_fileio_func_unlink (char *buf)
994{
995  CORE_ADDR ptrval;
996  int length, retlength;
997  char *pathname;
998  int ret;
999  struct stat st;
1000
1001  /* Parameter: Ptr to pathname / length incl. trailing zero */
1002  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
1003    {
1004      remote_fileio_ioerror ();
1005      return;
1006    }
1007  /* Request pathname using 'm' packet */
1008  pathname = alloca (length);
1009  retlength = remote_read_bytes (ptrval, pathname, length);
1010  if (retlength != length)
1011    {
1012      remote_fileio_ioerror ();
1013      return;
1014    }
1015
1016  /* Only operate on regular files (and directories, which allows to return
1017     the correct return code) */
1018  if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
1019    {
1020      remote_fileio_reply (-1, FILEIO_ENODEV);
1021      return;
1022    }
1023
1024  remote_fio_no_longjmp = 1;
1025  ret = unlink (pathname);
1026
1027  if (ret == -1)
1028    remote_fileio_return_errno (-1);
1029  else
1030    remote_fileio_return_success (ret);
1031}
1032
1033static void
1034remote_fileio_func_stat (char *buf)
1035{
1036  CORE_ADDR ptrval;
1037  int ret, length, retlength;
1038  char *pathname;
1039  LONGEST lnum;
1040  struct stat st;
1041  struct fio_stat fst;
1042
1043  /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
1044  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
1045    {
1046      remote_fileio_ioerror ();
1047      return;
1048    }
1049  /* Request pathname using 'm' packet */
1050  pathname = alloca (length);
1051  retlength = remote_read_bytes (ptrval, pathname, length);
1052  if (retlength != length)
1053    {
1054      remote_fileio_ioerror ();
1055      return;
1056    }
1057
1058  /* 2. Parameter: Ptr to struct stat */
1059  if (remote_fileio_extract_long (&buf, &lnum))
1060    {
1061      remote_fileio_ioerror ();
1062      return;
1063    }
1064  ptrval = (CORE_ADDR) lnum;
1065
1066  remote_fio_no_longjmp = 1;
1067  ret = stat (pathname, &st);
1068
1069  if (ret == -1)
1070    {
1071      remote_fileio_return_errno (-1);
1072      return;
1073    }
1074  /* Only operate on regular files and directories */
1075  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
1076    {
1077      remote_fileio_reply (-1, FILEIO_EACCES);
1078      return;
1079    }
1080  if (ptrval)
1081    {
1082      remote_fileio_to_fio_stat (&st, &fst);
1083      remote_fileio_to_fio_uint (0, fst.fst_dev);
1084
1085      retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst);
1086      if (retlength != sizeof fst)
1087	{
1088	  remote_fileio_return_errno (-1);
1089	  return;
1090	}
1091    }
1092  remote_fileio_return_success (ret);
1093}
1094
1095static void
1096remote_fileio_func_fstat (char *buf)
1097{
1098  CORE_ADDR ptrval;
1099  int fd, ret, retlength;
1100  long target_fd;
1101  LONGEST lnum;
1102  struct stat st;
1103  struct fio_stat fst;
1104  struct timeval tv;
1105
1106  /* 1. Parameter: file descriptor */
1107  if (remote_fileio_extract_int (&buf, &target_fd))
1108    {
1109      remote_fileio_ioerror ();
1110      return;
1111    }
1112  fd = remote_fileio_map_fd ((int) target_fd);
1113  if (fd == FIO_FD_INVALID)
1114    {
1115      remote_fileio_badfd ();
1116      return;
1117    }
1118  /* 2. Parameter: Ptr to struct stat */
1119  if (remote_fileio_extract_long (&buf, &lnum))
1120    {
1121      remote_fileio_ioerror ();
1122      return;
1123    }
1124  ptrval = (CORE_ADDR) lnum;
1125
1126  remote_fio_no_longjmp = 1;
1127  if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
1128    {
1129      remote_fileio_to_fio_uint (1, fst.fst_dev);
1130      st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
1131      st.st_nlink = 1;
1132      st.st_uid = getuid ();
1133      st.st_gid = getgid ();
1134      st.st_rdev = 0;
1135      st.st_size = 0;
1136      st.st_blksize = 512;
1137#if HAVE_STRUCT_STAT_ST_BLOCKS
1138      st.st_blocks = 0;
1139#endif
1140      if (!gettimeofday (&tv, NULL))
1141	st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
1142      else
1143        st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
1144      ret = 0;
1145    }
1146  else
1147    ret = fstat (fd, &st);
1148
1149  if (ret == -1)
1150    {
1151      remote_fileio_return_errno (-1);
1152      return;
1153    }
1154  if (ptrval)
1155    {
1156      remote_fileio_to_fio_stat (&st, &fst);
1157
1158      retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst);
1159      if (retlength != sizeof fst)
1160	{
1161	  remote_fileio_return_errno (-1);
1162	  return;
1163	}
1164    }
1165  remote_fileio_return_success (ret);
1166}
1167
1168static void
1169remote_fileio_func_gettimeofday (char *buf)
1170{
1171  LONGEST lnum;
1172  CORE_ADDR ptrval;
1173  int ret, retlength;
1174  struct timeval tv;
1175  struct fio_timeval ftv;
1176
1177  /* 1. Parameter: struct timeval pointer */
1178  if (remote_fileio_extract_long (&buf, &lnum))
1179    {
1180      remote_fileio_ioerror ();
1181      return;
1182    }
1183  ptrval = (CORE_ADDR) lnum;
1184  /* 2. Parameter: some pointer value... */
1185  if (remote_fileio_extract_long (&buf, &lnum))
1186    {
1187      remote_fileio_ioerror ();
1188      return;
1189    }
1190  /* ...which has to be NULL */
1191  if (lnum)
1192    {
1193      remote_fileio_reply (-1, FILEIO_EINVAL);
1194      return;
1195    }
1196
1197  remote_fio_no_longjmp = 1;
1198  ret = gettimeofday (&tv, NULL);
1199
1200  if (ret == -1)
1201    {
1202      remote_fileio_return_errno (-1);
1203      return;
1204    }
1205
1206  if (ptrval)
1207    {
1208      remote_fileio_to_fio_timeval (&tv, &ftv);
1209
1210      retlength = remote_fileio_write_bytes (ptrval, (char *) &ftv, sizeof ftv);
1211      if (retlength != sizeof ftv)
1212	{
1213	  remote_fileio_return_errno (-1);
1214	  return;
1215	}
1216    }
1217  remote_fileio_return_success (ret);
1218}
1219
1220static void
1221remote_fileio_func_isatty (char *buf)
1222{
1223  long target_fd;
1224  int fd;
1225
1226  /* Parameter: file descriptor */
1227  if (remote_fileio_extract_int (&buf, &target_fd))
1228    {
1229      remote_fileio_ioerror ();
1230      return;
1231    }
1232  remote_fio_no_longjmp = 1;
1233  fd = remote_fileio_map_fd ((int) target_fd);
1234  remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN ||
1235  				fd == FIO_FD_CONSOLE_OUT ? 1 : 0);
1236}
1237
1238static void
1239remote_fileio_func_system (char *buf)
1240{
1241  CORE_ADDR ptrval;
1242  int ret, length, retlength;
1243  char *cmdline;
1244
1245  /* Check if system(3) has been explicitely allowed using the
1246     `set remote system-call-allowed 1' command.  If not, return
1247     EPERM */
1248  if (!remote_fio_system_call_allowed)
1249    {
1250      remote_fileio_reply (-1, FILEIO_EPERM);
1251      return;
1252    }
1253
1254  /* Parameter: Ptr to commandline / length incl. trailing zero */
1255  if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
1256    {
1257      remote_fileio_ioerror ();
1258      return;
1259    }
1260  /* Request commandline using 'm' packet */
1261  cmdline = alloca (length);
1262  retlength = remote_read_bytes (ptrval, cmdline, length);
1263  if (retlength != length)
1264    {
1265      remote_fileio_ioerror ();
1266      return;
1267    }
1268
1269  remote_fio_no_longjmp = 1;
1270  ret = system (cmdline);
1271
1272  if (ret == -1)
1273    remote_fileio_return_errno (-1);
1274  else
1275    remote_fileio_return_success (WEXITSTATUS (ret));
1276}
1277
1278static struct {
1279  char *name;
1280  void (*func)(char *);
1281} remote_fio_func_map[] = {
1282  "open", remote_fileio_func_open,
1283  "close", remote_fileio_func_close,
1284  "read", remote_fileio_func_read,
1285  "write", remote_fileio_func_write,
1286  "lseek", remote_fileio_func_lseek,
1287  "rename", remote_fileio_func_rename,
1288  "unlink", remote_fileio_func_unlink,
1289  "stat", remote_fileio_func_stat,
1290  "fstat", remote_fileio_func_fstat,
1291  "gettimeofday", remote_fileio_func_gettimeofday,
1292  "isatty", remote_fileio_func_isatty,
1293  "system", remote_fileio_func_system,
1294  NULL, NULL
1295};
1296
1297static int
1298do_remote_fileio_request (struct ui_out *uiout, void *buf_arg)
1299{
1300  char *buf = buf_arg;
1301  char *c;
1302  int idx;
1303
1304  remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler);
1305
1306  c = strchr (++buf, ',');
1307  if (c)
1308    *c++ = '\0';
1309  else
1310    c = strchr (buf, '\0');
1311  for (idx = 0; remote_fio_func_map[idx].name; ++idx)
1312    if (!strcmp (remote_fio_func_map[idx].name, buf))
1313      break;
1314  if (!remote_fio_func_map[idx].name)	/* ERROR: No such function. */
1315    return RETURN_ERROR;
1316  remote_fio_func_map[idx].func (c);
1317  return 0;
1318}
1319
1320void
1321remote_fileio_request (char *buf)
1322{
1323  int ex;
1324
1325  remote_fileio_sig_init ();
1326
1327  remote_fio_ctrl_c_flag = 0;
1328  remote_fio_no_longjmp = 0;
1329
1330  ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf,
1331			 NULL, RETURN_MASK_ALL);
1332  switch (ex)
1333    {
1334      case RETURN_ERROR:
1335	remote_fileio_reply (-1, FILEIO_ENOSYS);
1336        break;
1337      case RETURN_QUIT:
1338        remote_fileio_reply (-1, FILEIO_EINTR);
1339	break;
1340      default:
1341        break;
1342    }
1343
1344  remote_fileio_sig_exit ();
1345}
1346
1347static void
1348set_system_call_allowed (char *args, int from_tty)
1349{
1350  if (args)
1351    {
1352      char *arg_end;
1353      int val = strtoul (args, &arg_end, 10);
1354      if (*args && *arg_end == '\0')
1355        {
1356	  remote_fio_system_call_allowed = !!val;
1357	  return;
1358	}
1359    }
1360  error ("Illegal argument for \"set remote system-call-allowed\" command");
1361}
1362
1363static void
1364show_system_call_allowed (char *args, int from_tty)
1365{
1366  if (args)
1367    error ("Garbage after \"show remote system-call-allowed\" command: `%s'", args);
1368  printf_unfiltered ("Calling host system(3) call from target is %sallowed\n",
1369		     remote_fio_system_call_allowed ? "" : "not ");
1370}
1371
1372void
1373initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
1374			  struct cmd_list_element *remote_show_cmdlist)
1375{
1376  add_cmd ("system-call-allowed", no_class,
1377	   set_system_call_allowed,
1378	   "Set if the host system(3) call is allowed for the target.\n",
1379	   &remote_set_cmdlist);
1380  add_cmd ("system-call-allowed", no_class,
1381	   show_system_call_allowed,
1382	   "Show if the host system(3) call is allowed for the target.\n",
1383	   &remote_show_cmdlist);
1384}
1385