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