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