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