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