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