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