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