xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/remote-fileio.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /* Remote File-I/O communications
2 
3    Copyright (C) 2003-2019 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 "common/gdb_wait.h"
26 #include <sys/stat.h>
27 #include "remote-fileio.h"
28 #include "event-loop.h"
29 #include "target.h"
30 #include "filenames.h"
31 #include "common/filestuff.h"
32 
33 #include <fcntl.h>
34 #include "common/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);
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 = ui_file_read (gdb_stdtargin, (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 	ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr,
643 		       (char *) buffer, length);
644 	gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr);
645 	ret = length;
646 	break;
647       default:
648 	ret = write (fd, buffer, length);
649 	if (ret < 0 && errno == EACCES)
650 	  errno = EBADF; /* Cygwin returns EACCESS when writing to a
651 			    R/O file.  */
652 	break;
653     }
654 
655   if (ret < 0)
656     remote_fileio_return_errno (remote, -1);
657   else
658     remote_fileio_return_success (remote, ret);
659 
660   xfree (buffer);
661 }
662 
663 static void
664 remote_fileio_func_lseek (remote_target *remote, char *buf)
665 {
666   long num;
667   LONGEST lnum;
668   int fd, flag;
669   off_t offset, ret;
670 
671   /* 1. Parameter: file descriptor */
672   if (remote_fileio_extract_int (&buf, &num))
673     {
674       remote_fileio_ioerror (remote);
675       return;
676     }
677   fd = remote_fileio_map_fd ((int) num);
678   if (fd == FIO_FD_INVALID)
679     {
680       remote_fileio_badfd (remote);
681       return;
682     }
683   else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
684     {
685       remote_fileio_reply (remote, -1, FILEIO_ESPIPE);
686       return;
687     }
688 
689   /* 2. Parameter: offset */
690   if (remote_fileio_extract_long (&buf, &lnum))
691     {
692       remote_fileio_ioerror (remote);
693       return;
694     }
695   offset = (off_t) lnum;
696   /* 3. Parameter: flag */
697   if (remote_fileio_extract_int (&buf, &num))
698     {
699       remote_fileio_ioerror (remote);
700       return;
701     }
702   if (remote_fileio_seek_flag_to_host (num, &flag))
703     {
704       remote_fileio_reply (remote, -1, FILEIO_EINVAL);
705       return;
706     }
707 
708   ret = lseek (fd, offset, flag);
709 
710   if (ret == (off_t) -1)
711     remote_fileio_return_errno (remote, -1);
712   else
713     remote_fileio_return_success (remote, ret);
714 }
715 
716 static void
717 remote_fileio_func_rename (remote_target *remote, char *buf)
718 {
719   CORE_ADDR old_ptr, new_ptr;
720   int old_len, new_len;
721   char *oldpath, *newpath;
722   int ret, of, nf;
723   struct stat ost, nst;
724 
725   /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */
726   if (remote_fileio_extract_ptr_w_len (&buf, &old_ptr, &old_len))
727     {
728       remote_fileio_ioerror (remote);
729       return;
730     }
731 
732   /* 2. Parameter: Ptr to newpath / length incl. trailing zero */
733   if (remote_fileio_extract_ptr_w_len (&buf, &new_ptr, &new_len))
734     {
735       remote_fileio_ioerror (remote);
736       return;
737     }
738 
739   /* Request oldpath using 'm' packet */
740   oldpath = (char *) alloca (old_len);
741   if (target_read_memory (old_ptr, (gdb_byte *) oldpath, old_len) != 0)
742     {
743       remote_fileio_ioerror (remote);
744       return;
745     }
746 
747   /* Request newpath using 'm' packet */
748   newpath = (char *) alloca (new_len);
749   if (target_read_memory (new_ptr, (gdb_byte *) newpath, new_len) != 0)
750     {
751       remote_fileio_ioerror (remote);
752       return;
753     }
754 
755   /* Only operate on regular files and directories.  */
756   of = stat (oldpath, &ost);
757   nf = stat (newpath, &nst);
758   if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode))
759       || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode)))
760     {
761       remote_fileio_reply (remote, -1, FILEIO_EACCES);
762       return;
763     }
764 
765   ret = rename (oldpath, newpath);
766 
767   if (ret == -1)
768     {
769       /* Special case: newpath is a non-empty directory.  Some systems
770          return ENOTEMPTY, some return EEXIST.  We coerce that to be
771 	 always EEXIST.  */
772       if (errno == ENOTEMPTY)
773         errno = EEXIST;
774 #ifdef __CYGWIN__
775       /* Workaround some Cygwin problems with correct errnos.  */
776       if (errno == EACCES)
777         {
778 	  if (!of && !nf && S_ISDIR (nst.st_mode))
779 	    {
780 	      if (S_ISREG (ost.st_mode))
781 		errno = EISDIR;
782 	      else
783 		{
784 		  char oldfullpath[PATH_MAX];
785 		  char newfullpath[PATH_MAX];
786 		  int len;
787 
788 		  cygwin_conv_path (CCP_WIN_A_TO_POSIX, oldpath, oldfullpath,
789 				    PATH_MAX);
790 		  cygwin_conv_path (CCP_WIN_A_TO_POSIX, newpath, newfullpath,
791 				    PATH_MAX);
792 		  len = strlen (oldfullpath);
793 		  if (IS_DIR_SEPARATOR (newfullpath[len])
794 		      && !filename_ncmp (oldfullpath, newfullpath, len))
795 		    errno = EINVAL;
796 		  else
797 		    errno = EEXIST;
798 		}
799 	    }
800 	}
801 #endif
802 
803       remote_fileio_return_errno (remote, -1);
804     }
805   else
806     remote_fileio_return_success (remote, ret);
807 }
808 
809 static void
810 remote_fileio_func_unlink (remote_target *remote, char *buf)
811 {
812   CORE_ADDR ptrval;
813   int length;
814   char *pathname;
815   int ret;
816   struct stat st;
817 
818   /* Parameter: Ptr to pathname / length incl. trailing zero */
819   if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
820     {
821       remote_fileio_ioerror (remote);
822       return;
823     }
824   /* Request pathname using 'm' packet */
825   pathname = (char *) alloca (length);
826   if (target_read_memory (ptrval, (gdb_byte *) pathname, length) != 0)
827     {
828       remote_fileio_ioerror (remote);
829       return;
830     }
831 
832   /* Only operate on regular files (and directories, which allows to return
833      the correct return code).  */
834   if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
835     {
836       remote_fileio_reply (remote, -1, FILEIO_ENODEV);
837       return;
838     }
839 
840   ret = unlink (pathname);
841 
842   if (ret == -1)
843     remote_fileio_return_errno (remote, -1);
844   else
845     remote_fileio_return_success (remote, ret);
846 }
847 
848 static void
849 remote_fileio_func_stat (remote_target *remote, char *buf)
850 {
851   CORE_ADDR statptr, nameptr;
852   int ret, namelength;
853   char *pathname;
854   LONGEST lnum;
855   struct stat st;
856   struct fio_stat fst;
857 
858   /* 1. Parameter: Ptr to pathname / length incl. trailing zero */
859   if (remote_fileio_extract_ptr_w_len (&buf, &nameptr, &namelength))
860     {
861       remote_fileio_ioerror (remote);
862       return;
863     }
864 
865   /* 2. Parameter: Ptr to struct stat */
866   if (remote_fileio_extract_long (&buf, &lnum))
867     {
868       remote_fileio_ioerror (remote);
869       return;
870     }
871   statptr = (CORE_ADDR) lnum;
872 
873   /* Request pathname using 'm' packet */
874   pathname = (char *) alloca (namelength);
875   if (target_read_memory (nameptr, (gdb_byte *) pathname, namelength) != 0)
876     {
877       remote_fileio_ioerror (remote);
878       return;
879     }
880 
881   ret = stat (pathname, &st);
882 
883   if (ret == -1)
884     {
885       remote_fileio_return_errno (remote, -1);
886       return;
887     }
888   /* Only operate on regular files and directories.  */
889   if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
890     {
891       remote_fileio_reply (remote, -1, FILEIO_EACCES);
892       return;
893     }
894   if (statptr)
895     {
896       host_to_fileio_stat (&st, &fst);
897       host_to_fileio_uint (0, fst.fst_dev);
898 
899       errno = target_write_memory (statptr, (gdb_byte *) &fst, sizeof fst);
900       if (errno != 0)
901 	{
902 	  remote_fileio_return_errno (remote, -1);
903 	  return;
904 	}
905     }
906   remote_fileio_return_success (remote, ret);
907 }
908 
909 static void
910 remote_fileio_func_fstat (remote_target *remote, char *buf)
911 {
912   CORE_ADDR ptrval;
913   int fd, ret;
914   long target_fd;
915   LONGEST lnum;
916   struct stat st;
917   struct fio_stat fst;
918   struct timeval tv;
919 
920   /* 1. Parameter: file descriptor */
921   if (remote_fileio_extract_int (&buf, &target_fd))
922     {
923       remote_fileio_ioerror (remote);
924       return;
925     }
926   fd = remote_fileio_map_fd ((int) target_fd);
927   if (fd == FIO_FD_INVALID)
928     {
929       remote_fileio_badfd (remote);
930       return;
931     }
932   /* 2. Parameter: Ptr to struct stat */
933   if (remote_fileio_extract_long (&buf, &lnum))
934     {
935       remote_fileio_ioerror (remote);
936       return;
937     }
938   ptrval = (CORE_ADDR) lnum;
939 
940   if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
941     {
942       host_to_fileio_uint (1, fst.fst_dev);
943       memset (&st, 0, sizeof (st));
944       st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
945       st.st_nlink = 1;
946 #ifdef HAVE_GETUID
947       st.st_uid = getuid ();
948 #endif
949 #ifdef HAVE_GETGID
950       st.st_gid = getgid ();
951 #endif
952 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
953       st.st_blksize = 512;
954 #endif
955 #if HAVE_STRUCT_STAT_ST_BLOCKS
956       st.st_blocks = 0;
957 #endif
958       if (!gettimeofday (&tv, NULL))
959 	st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec;
960       else
961         st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0;
962       ret = 0;
963     }
964   else
965     ret = fstat (fd, &st);
966 
967   if (ret == -1)
968     {
969       remote_fileio_return_errno (remote, -1);
970       return;
971     }
972   if (ptrval)
973     {
974       host_to_fileio_stat (&st, &fst);
975 
976       errno = target_write_memory (ptrval, (gdb_byte *) &fst, sizeof fst);
977       if (errno != 0)
978 	{
979 	  remote_fileio_return_errno (remote, -1);
980 	  return;
981 	}
982     }
983   remote_fileio_return_success (remote, ret);
984 }
985 
986 static void
987 remote_fileio_func_gettimeofday (remote_target *remote, char *buf)
988 {
989   LONGEST lnum;
990   CORE_ADDR ptrval;
991   int ret;
992   struct timeval tv;
993   struct fio_timeval ftv;
994 
995   /* 1. Parameter: struct timeval pointer */
996   if (remote_fileio_extract_long (&buf, &lnum))
997     {
998       remote_fileio_ioerror (remote);
999       return;
1000     }
1001   ptrval = (CORE_ADDR) lnum;
1002   /* 2. Parameter: some pointer value...  */
1003   if (remote_fileio_extract_long (&buf, &lnum))
1004     {
1005       remote_fileio_ioerror (remote);
1006       return;
1007     }
1008   /* ...which has to be NULL.  */
1009   if (lnum)
1010     {
1011       remote_fileio_reply (remote, -1, FILEIO_EINVAL);
1012       return;
1013     }
1014 
1015   ret = gettimeofday (&tv, NULL);
1016 
1017   if (ret == -1)
1018     {
1019       remote_fileio_return_errno (remote, -1);
1020       return;
1021     }
1022 
1023   if (ptrval)
1024     {
1025       remote_fileio_to_fio_timeval (&tv, &ftv);
1026 
1027       errno = target_write_memory (ptrval, (gdb_byte *) &ftv, sizeof ftv);
1028       if (errno != 0)
1029 	{
1030 	  remote_fileio_return_errno (remote, -1);
1031 	  return;
1032 	}
1033     }
1034   remote_fileio_return_success (remote, ret);
1035 }
1036 
1037 static void
1038 remote_fileio_func_isatty (remote_target *remote, char *buf)
1039 {
1040   long target_fd;
1041   int fd;
1042 
1043   /* Parameter: file descriptor */
1044   if (remote_fileio_extract_int (&buf, &target_fd))
1045     {
1046       remote_fileio_ioerror (remote);
1047       return;
1048     }
1049   fd = remote_fileio_map_fd ((int) target_fd);
1050   int ret = fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT ? 1 : 0;
1051   remote_fileio_return_success (remote, ret);
1052 }
1053 
1054 static void
1055 remote_fileio_func_system (remote_target *remote, char *buf)
1056 {
1057   CORE_ADDR ptrval;
1058   int ret, length;
1059   char *cmdline = NULL;
1060 
1061   /* Parameter: Ptr to commandline / length incl. trailing zero */
1062   if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length))
1063     {
1064       remote_fileio_ioerror (remote);
1065       return;
1066     }
1067 
1068   if (length)
1069     {
1070       /* Request commandline using 'm' packet */
1071       cmdline = (char *) alloca (length);
1072       if (target_read_memory (ptrval, (gdb_byte *) cmdline, length) != 0)
1073 	{
1074 	  remote_fileio_ioerror (remote);
1075 	  return;
1076 	}
1077     }
1078 
1079   /* Check if system(3) has been explicitely allowed using the
1080      `set remote system-call-allowed 1' command.  If length is 0,
1081      indicating a NULL parameter to the system call, return zero to
1082      indicate a shell is not available.  Otherwise fail with EPERM.  */
1083   if (!remote_fio_system_call_allowed)
1084     {
1085       if (!length)
1086 	remote_fileio_return_success (remote, 0);
1087       else
1088 	remote_fileio_reply (remote, -1, FILEIO_EPERM);
1089       return;
1090     }
1091 
1092   ret = system (cmdline);
1093 
1094   if (!length)
1095     remote_fileio_return_success (remote, ret);
1096   else if (ret == -1)
1097     remote_fileio_return_errno (remote, -1);
1098   else
1099     remote_fileio_return_success (remote, WEXITSTATUS (ret));
1100 }
1101 
1102 static struct {
1103   const char *name;
1104   void (*func)(remote_target *remote, char *);
1105 } remote_fio_func_map[] = {
1106   { "open", remote_fileio_func_open },
1107   { "close", remote_fileio_func_close },
1108   { "read", remote_fileio_func_read },
1109   { "write", remote_fileio_func_write },
1110   { "lseek", remote_fileio_func_lseek },
1111   { "rename", remote_fileio_func_rename },
1112   { "unlink", remote_fileio_func_unlink },
1113   { "stat", remote_fileio_func_stat },
1114   { "fstat", remote_fileio_func_fstat },
1115   { "gettimeofday", remote_fileio_func_gettimeofday },
1116   { "isatty", remote_fileio_func_isatty },
1117   { "system", remote_fileio_func_system },
1118   { NULL, NULL }
1119 };
1120 
1121 static void
1122 do_remote_fileio_request (remote_target *remote, char *buf)
1123 {
1124   char *c;
1125   int idx;
1126 
1127   quit_handler = remote_fileio_quit_handler;
1128 
1129   c = strchr (++buf, ',');
1130   if (c)
1131     *c++ = '\0';
1132   else
1133     c = strchr (buf, '\0');
1134   for (idx = 0; remote_fio_func_map[idx].name; ++idx)
1135     if (!strcmp (remote_fio_func_map[idx].name, buf))
1136       break;
1137   if (!remote_fio_func_map[idx].name)
1138     remote_fileio_reply (remote, -1, FILEIO_ENOSYS);
1139   else
1140     remote_fio_func_map[idx].func (remote, c);
1141 }
1142 
1143 /* Close any open descriptors, and reinitialize the file mapping.  */
1144 
1145 void
1146 remote_fileio_reset (void)
1147 {
1148   int ix;
1149 
1150   for (ix = 0; ix != remote_fio_data.fd_map_size; ix++)
1151     {
1152       int fd = remote_fio_data.fd_map[ix];
1153 
1154       if (fd >= 0)
1155 	close (fd);
1156     }
1157   if (remote_fio_data.fd_map)
1158     {
1159       xfree (remote_fio_data.fd_map);
1160       remote_fio_data.fd_map = NULL;
1161       remote_fio_data.fd_map_size = 0;
1162     }
1163 }
1164 
1165 /* Handle a file I/O request.  BUF points to the packet containing the
1166    request.  CTRLC_PENDING_P should be nonzero if the target has not
1167    acknowledged the Ctrl-C sent asynchronously earlier.  */
1168 
1169 void
1170 remote_fileio_request (remote_target *remote, char *buf, int ctrlc_pending_p)
1171 {
1172   /* Save the previous quit handler, so we can restore it.  No need
1173      for a cleanup since we catch all exceptions below.  Note that the
1174      quit handler is also restored by remote_fileio_reply just before
1175      pushing a packet.  */
1176   remote_fileio_o_quit_handler = quit_handler;
1177 
1178   if (ctrlc_pending_p)
1179     {
1180       /* If the target hasn't responded to the Ctrl-C sent
1181 	 asynchronously earlier, take this opportunity to send the
1182 	 Ctrl-C synchronously.  */
1183       set_quit_flag ();
1184       remote_fileio_reply (remote, -1, FILEIO_EINTR);
1185     }
1186   else
1187     {
1188       TRY
1189 	{
1190 	  do_remote_fileio_request (remote, buf);
1191 	}
1192       CATCH (ex, RETURN_MASK_ALL)
1193 	{
1194 	  if (ex.reason == RETURN_QUIT)
1195 	    remote_fileio_reply (remote, -1, FILEIO_EINTR);
1196 	  else
1197 	    remote_fileio_reply (remote, -1, FILEIO_EIO);
1198 	}
1199       END_CATCH
1200     }
1201 
1202   quit_handler = remote_fileio_o_quit_handler;
1203 }
1204 
1205 
1206 /* Unpack an fio_uint_t.  */
1207 
1208 static unsigned int
1209 remote_fileio_to_host_uint (fio_uint_t fnum)
1210 {
1211   return extract_unsigned_integer ((gdb_byte *) fnum, 4,
1212 				   BFD_ENDIAN_BIG);
1213 }
1214 
1215 /* Unpack an fio_ulong_t.  */
1216 
1217 static ULONGEST
1218 remote_fileio_to_host_ulong (fio_ulong_t fnum)
1219 {
1220   return extract_unsigned_integer ((gdb_byte *) fnum, 8,
1221 				   BFD_ENDIAN_BIG);
1222 }
1223 
1224 /* Unpack an fio_mode_t.  */
1225 
1226 static mode_t
1227 remote_fileio_to_host_mode (fio_mode_t fnum)
1228 {
1229   return remote_fileio_mode_to_host (remote_fileio_to_host_uint (fnum),
1230 				     0);
1231 }
1232 
1233 /* Unpack an fio_time_t.  */
1234 
1235 static time_t
1236 remote_fileio_to_host_time (fio_time_t fnum)
1237 {
1238   return remote_fileio_to_host_uint (fnum);
1239 }
1240 
1241 
1242 /* See remote-fileio.h.  */
1243 
1244 void
1245 remote_fileio_to_host_stat (struct fio_stat *fst, struct stat *st)
1246 {
1247   memset (st, 0, sizeof (struct stat));
1248 
1249   st->st_dev = remote_fileio_to_host_uint (fst->fst_dev);
1250   st->st_ino = remote_fileio_to_host_uint (fst->fst_ino);
1251   st->st_mode = remote_fileio_to_host_mode (fst->fst_mode);
1252   st->st_nlink = remote_fileio_to_host_uint (fst->fst_nlink);
1253   st->st_uid = remote_fileio_to_host_uint (fst->fst_uid);
1254   st->st_gid = remote_fileio_to_host_uint (fst->fst_gid);
1255   st->st_rdev = remote_fileio_to_host_uint (fst->fst_rdev);
1256   st->st_size = remote_fileio_to_host_ulong (fst->fst_size);
1257 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1258   st->st_blksize = remote_fileio_to_host_ulong (fst->fst_blksize);
1259 #endif
1260 #if HAVE_STRUCT_STAT_ST_BLOCKS
1261   st->st_blocks = remote_fileio_to_host_ulong (fst->fst_blocks);
1262 #endif
1263   st->st_atime = remote_fileio_to_host_time (fst->fst_atime);
1264   st->st_mtime = remote_fileio_to_host_time (fst->fst_mtime);
1265   st->st_ctime = remote_fileio_to_host_time (fst->fst_ctime);
1266 }
1267 
1268 
1269 static void
1270 set_system_call_allowed (const char *args, int from_tty)
1271 {
1272   if (args)
1273     {
1274       char *arg_end;
1275       int val = strtoul (args, &arg_end, 10);
1276 
1277       if (*args && *arg_end == '\0')
1278         {
1279 	  remote_fio_system_call_allowed = !!val;
1280 	  return;
1281 	}
1282     }
1283   error (_("Illegal argument for \"set remote system-call-allowed\" command"));
1284 }
1285 
1286 static void
1287 show_system_call_allowed (const char *args, int from_tty)
1288 {
1289   if (args)
1290     error (_("Garbage after \"show remote "
1291 	     "system-call-allowed\" command: `%s'"), args);
1292   printf_unfiltered ("Calling host system(3) call from target is %sallowed\n",
1293 		     remote_fio_system_call_allowed ? "" : "not ");
1294 }
1295 
1296 void
1297 initialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist,
1298 			  struct cmd_list_element *remote_show_cmdlist)
1299 {
1300   add_cmd ("system-call-allowed", no_class,
1301 	   set_system_call_allowed,
1302 	   _("Set if the host system(3) call is allowed for the target."),
1303 	   &remote_set_cmdlist);
1304   add_cmd ("system-call-allowed", no_class,
1305 	   show_system_call_allowed,
1306 	   _("Show if the host system(3) call is allowed for the target."),
1307 	   &remote_show_cmdlist);
1308 }
1309