1130803Smarcel/* Remote File-I/O communications 2130803Smarcel 3130803Smarcel Copyright 2003 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel This file is part of GDB. 6130803Smarcel 7130803Smarcel This program is free software; you can redistribute it and/or modify 8130803Smarcel it under the terms of the GNU General Public License as published by 9130803Smarcel the Free Software Foundation; either version 2 of the License, or 10130803Smarcel (at your option) any later version. 11130803Smarcel 12130803Smarcel This program is distributed in the hope that it will be useful, 13130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 14130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130803Smarcel GNU General Public License for more details. 16130803Smarcel 17130803Smarcel You should have received a copy of the GNU General Public License 18130803Smarcel along with this program; if not, write to the Free Software 19130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 20130803Smarcel Boston, MA 02111-1307, USA. */ 21130803Smarcel 22130803Smarcel/* See the GDB User Guide for details of the GDB remote protocol. */ 23130803Smarcel 24130803Smarcel#include "defs.h" 25130803Smarcel#include "gdb_string.h" 26130803Smarcel#include "gdbcmd.h" 27130803Smarcel#include "remote.h" 28130803Smarcel#include "gdb/fileio.h" 29130803Smarcel#include "gdb_wait.h" 30130803Smarcel#include "gdb_stat.h" 31130803Smarcel#include "remote-fileio.h" 32130803Smarcel 33130803Smarcel#include <fcntl.h> 34130803Smarcel#include <sys/time.h> 35130803Smarcel#ifdef __CYGWIN__ 36130803Smarcel#include <sys/cygwin.h> /* For cygwin_conv_to_full_posix_path. */ 37130803Smarcel#endif 38130803Smarcel#include <signal.h> 39130803Smarcel 40130803Smarcelstatic struct { 41130803Smarcel int *fd_map; 42130803Smarcel int fd_map_size; 43130803Smarcel} remote_fio_data; 44130803Smarcel 45130803Smarcel#define FIO_FD_INVALID -1 46130803Smarcel#define FIO_FD_CONSOLE_IN -2 47130803Smarcel#define FIO_FD_CONSOLE_OUT -3 48130803Smarcel 49130803Smarcelstatic int remote_fio_system_call_allowed = 0; 50130803Smarcel 51130803Smarcelstatic int 52130803Smarcelremote_fileio_init_fd_map (void) 53130803Smarcel{ 54130803Smarcel int i; 55130803Smarcel 56130803Smarcel if (!remote_fio_data.fd_map) 57130803Smarcel { 58130803Smarcel remote_fio_data.fd_map = (int *) xmalloc (10 * sizeof (int)); 59130803Smarcel remote_fio_data.fd_map_size = 10; 60130803Smarcel remote_fio_data.fd_map[0] = FIO_FD_CONSOLE_IN; 61130803Smarcel remote_fio_data.fd_map[1] = FIO_FD_CONSOLE_OUT; 62130803Smarcel remote_fio_data.fd_map[2] = FIO_FD_CONSOLE_OUT; 63130803Smarcel for (i = 3; i < 10; ++i) 64130803Smarcel remote_fio_data.fd_map[i] = FIO_FD_INVALID; 65130803Smarcel } 66130803Smarcel return 3; 67130803Smarcel} 68130803Smarcel 69130803Smarcelstatic int 70130803Smarcelremote_fileio_resize_fd_map (void) 71130803Smarcel{ 72130803Smarcel if (!remote_fio_data.fd_map) 73130803Smarcel return remote_fileio_init_fd_map (); 74130803Smarcel remote_fio_data.fd_map_size += 10; 75130803Smarcel remote_fio_data.fd_map = 76130803Smarcel (int *) xrealloc (remote_fio_data.fd_map, 77130803Smarcel remote_fio_data.fd_map_size * sizeof (int)); 78130803Smarcel return remote_fio_data.fd_map_size - 10; 79130803Smarcel} 80130803Smarcel 81130803Smarcelstatic int 82130803Smarcelremote_fileio_next_free_fd (void) 83130803Smarcel{ 84130803Smarcel int i; 85130803Smarcel 86130803Smarcel for (i = 0; i < remote_fio_data.fd_map_size; ++i) 87130803Smarcel if (remote_fio_data.fd_map[i] == FIO_FD_INVALID) 88130803Smarcel return i; 89130803Smarcel return remote_fileio_resize_fd_map (); 90130803Smarcel} 91130803Smarcel 92130803Smarcelstatic int 93130803Smarcelremote_fileio_fd_to_targetfd (int fd) 94130803Smarcel{ 95130803Smarcel int target_fd = remote_fileio_next_free_fd (); 96130803Smarcel remote_fio_data.fd_map[target_fd] = fd; 97130803Smarcel return target_fd; 98130803Smarcel} 99130803Smarcel 100130803Smarcelstatic int 101130803Smarcelremote_fileio_map_fd (int target_fd) 102130803Smarcel{ 103130803Smarcel remote_fileio_init_fd_map (); 104130803Smarcel if (target_fd < 0 || target_fd >= remote_fio_data.fd_map_size) 105130803Smarcel return FIO_FD_INVALID; 106130803Smarcel return remote_fio_data.fd_map[target_fd]; 107130803Smarcel} 108130803Smarcel 109130803Smarcelstatic void 110130803Smarcelremote_fileio_close_target_fd (int target_fd) 111130803Smarcel{ 112130803Smarcel remote_fileio_init_fd_map (); 113130803Smarcel if (target_fd >= 0 && target_fd < remote_fio_data.fd_map_size) 114130803Smarcel remote_fio_data.fd_map[target_fd] = FIO_FD_INVALID; 115130803Smarcel} 116130803Smarcel 117130803Smarcelstatic int 118130803Smarcelremote_fileio_oflags_to_host (long flags) 119130803Smarcel{ 120130803Smarcel int hflags = 0; 121130803Smarcel 122130803Smarcel if (flags & FILEIO_O_CREAT) 123130803Smarcel hflags |= O_CREAT; 124130803Smarcel if (flags & FILEIO_O_EXCL) 125130803Smarcel hflags |= O_EXCL; 126130803Smarcel if (flags & FILEIO_O_TRUNC) 127130803Smarcel hflags |= O_TRUNC; 128130803Smarcel if (flags & FILEIO_O_APPEND) 129130803Smarcel hflags |= O_APPEND; 130130803Smarcel if (flags & FILEIO_O_RDONLY) 131130803Smarcel hflags |= O_RDONLY; 132130803Smarcel if (flags & FILEIO_O_WRONLY) 133130803Smarcel hflags |= O_WRONLY; 134130803Smarcel if (flags & FILEIO_O_RDWR) 135130803Smarcel hflags |= O_RDWR; 136130803Smarcel/* On systems supporting binary and text mode, always open files in 137130803Smarcel binary mode. */ 138130803Smarcel#ifdef O_BINARY 139130803Smarcel hflags |= O_BINARY; 140130803Smarcel#endif 141130803Smarcel return hflags; 142130803Smarcel} 143130803Smarcel 144130803Smarcelstatic mode_t 145130803Smarcelremote_fileio_mode_to_host (long mode, int open_call) 146130803Smarcel{ 147130803Smarcel mode_t hmode = 0; 148130803Smarcel 149130803Smarcel if (!open_call) 150130803Smarcel { 151130803Smarcel if (mode & FILEIO_S_IFREG) 152130803Smarcel hmode |= S_IFREG; 153130803Smarcel if (mode & FILEIO_S_IFDIR) 154130803Smarcel hmode |= S_IFDIR; 155130803Smarcel if (mode & FILEIO_S_IFCHR) 156130803Smarcel hmode |= S_IFCHR; 157130803Smarcel } 158130803Smarcel if (mode & FILEIO_S_IRUSR) 159130803Smarcel hmode |= S_IRUSR; 160130803Smarcel if (mode & FILEIO_S_IWUSR) 161130803Smarcel hmode |= S_IWUSR; 162130803Smarcel if (mode & FILEIO_S_IXUSR) 163130803Smarcel hmode |= S_IXUSR; 164130803Smarcel if (mode & FILEIO_S_IRGRP) 165130803Smarcel hmode |= S_IRGRP; 166130803Smarcel if (mode & FILEIO_S_IWGRP) 167130803Smarcel hmode |= S_IWGRP; 168130803Smarcel if (mode & FILEIO_S_IXGRP) 169130803Smarcel hmode |= S_IXGRP; 170130803Smarcel if (mode & FILEIO_S_IROTH) 171130803Smarcel hmode |= S_IROTH; 172130803Smarcel if (mode & FILEIO_S_IWOTH) 173130803Smarcel hmode |= S_IWOTH; 174130803Smarcel if (mode & FILEIO_S_IXOTH) 175130803Smarcel hmode |= S_IXOTH; 176130803Smarcel return hmode; 177130803Smarcel} 178130803Smarcel 179130803Smarcelstatic LONGEST 180130803Smarcelremote_fileio_mode_to_target (mode_t mode) 181130803Smarcel{ 182130803Smarcel mode_t tmode = 0; 183130803Smarcel 184130803Smarcel if (mode & S_IFREG) 185130803Smarcel tmode |= FILEIO_S_IFREG; 186130803Smarcel if (mode & S_IFDIR) 187130803Smarcel tmode |= FILEIO_S_IFDIR; 188130803Smarcel if (mode & S_IFCHR) 189130803Smarcel tmode |= FILEIO_S_IFCHR; 190130803Smarcel if (mode & S_IRUSR) 191130803Smarcel tmode |= FILEIO_S_IRUSR; 192130803Smarcel if (mode & S_IWUSR) 193130803Smarcel tmode |= FILEIO_S_IWUSR; 194130803Smarcel if (mode & S_IXUSR) 195130803Smarcel tmode |= FILEIO_S_IXUSR; 196130803Smarcel if (mode & S_IRGRP) 197130803Smarcel tmode |= FILEIO_S_IRGRP; 198130803Smarcel if (mode & S_IWGRP) 199130803Smarcel tmode |= FILEIO_S_IWGRP; 200130803Smarcel if (mode & S_IXGRP) 201130803Smarcel tmode |= FILEIO_S_IXGRP; 202130803Smarcel if (mode & S_IROTH) 203130803Smarcel tmode |= FILEIO_S_IROTH; 204130803Smarcel if (mode & S_IWOTH) 205130803Smarcel tmode |= FILEIO_S_IWOTH; 206130803Smarcel if (mode & S_IXOTH) 207130803Smarcel tmode |= FILEIO_S_IXOTH; 208130803Smarcel return tmode; 209130803Smarcel} 210130803Smarcel 211130803Smarcelstatic int 212130803Smarcelremote_fileio_errno_to_target (int error) 213130803Smarcel{ 214130803Smarcel switch (error) 215130803Smarcel { 216130803Smarcel case EPERM: 217130803Smarcel return FILEIO_EPERM; 218130803Smarcel case ENOENT: 219130803Smarcel return FILEIO_ENOENT; 220130803Smarcel case EINTR: 221130803Smarcel return FILEIO_EINTR; 222130803Smarcel case EIO: 223130803Smarcel return FILEIO_EIO; 224130803Smarcel case EBADF: 225130803Smarcel return FILEIO_EBADF; 226130803Smarcel case EACCES: 227130803Smarcel return FILEIO_EACCES; 228130803Smarcel case EFAULT: 229130803Smarcel return FILEIO_EFAULT; 230130803Smarcel case EBUSY: 231130803Smarcel return FILEIO_EBUSY; 232130803Smarcel case EEXIST: 233130803Smarcel return FILEIO_EEXIST; 234130803Smarcel case ENODEV: 235130803Smarcel return FILEIO_ENODEV; 236130803Smarcel case ENOTDIR: 237130803Smarcel return FILEIO_ENOTDIR; 238130803Smarcel case EISDIR: 239130803Smarcel return FILEIO_EISDIR; 240130803Smarcel case EINVAL: 241130803Smarcel return FILEIO_EINVAL; 242130803Smarcel case ENFILE: 243130803Smarcel return FILEIO_ENFILE; 244130803Smarcel case EMFILE: 245130803Smarcel return FILEIO_EMFILE; 246130803Smarcel case EFBIG: 247130803Smarcel return FILEIO_EFBIG; 248130803Smarcel case ENOSPC: 249130803Smarcel return FILEIO_ENOSPC; 250130803Smarcel case ESPIPE: 251130803Smarcel return FILEIO_ESPIPE; 252130803Smarcel case EROFS: 253130803Smarcel return FILEIO_EROFS; 254130803Smarcel case ENOSYS: 255130803Smarcel return FILEIO_ENOSYS; 256130803Smarcel case ENAMETOOLONG: 257130803Smarcel return FILEIO_ENAMETOOLONG; 258130803Smarcel } 259130803Smarcel return FILEIO_EUNKNOWN; 260130803Smarcel} 261130803Smarcel 262130803Smarcelstatic int 263130803Smarcelremote_fileio_seek_flag_to_host (long num, int *flag) 264130803Smarcel{ 265130803Smarcel if (!flag) 266130803Smarcel return 0; 267130803Smarcel switch (num) 268130803Smarcel { 269130803Smarcel case FILEIO_SEEK_SET: 270130803Smarcel *flag = SEEK_SET; 271130803Smarcel break; 272130803Smarcel case FILEIO_SEEK_CUR: 273130803Smarcel *flag = SEEK_CUR; 274130803Smarcel break; 275130803Smarcel case FILEIO_SEEK_END: 276130803Smarcel *flag = SEEK_END; 277130803Smarcel break; 278130803Smarcel default: 279130803Smarcel return -1; 280130803Smarcel } 281130803Smarcel return 0; 282130803Smarcel} 283130803Smarcel 284130803Smarcelstatic int 285130803Smarcelremote_fileio_extract_long (char **buf, LONGEST *retlong) 286130803Smarcel{ 287130803Smarcel char *c; 288130803Smarcel int sign = 1; 289130803Smarcel 290130803Smarcel if (!buf || !*buf || !**buf || !retlong) 291130803Smarcel return -1; 292130803Smarcel c = strchr (*buf, ','); 293130803Smarcel if (c) 294130803Smarcel *c++ = '\0'; 295130803Smarcel else 296130803Smarcel c = strchr (*buf, '\0'); 297130803Smarcel while (strchr ("+-", **buf)) 298130803Smarcel { 299130803Smarcel if (**buf == '-') 300130803Smarcel sign = -sign; 301130803Smarcel ++*buf; 302130803Smarcel } 303130803Smarcel for (*retlong = 0; **buf; ++*buf) 304130803Smarcel { 305130803Smarcel *retlong <<= 4; 306130803Smarcel if (**buf >= '0' && **buf <= '9') 307130803Smarcel *retlong += **buf - '0'; 308130803Smarcel else if (**buf >= 'a' && **buf <= 'f') 309130803Smarcel *retlong += **buf - 'a' + 10; 310130803Smarcel else if (**buf >= 'A' && **buf <= 'F') 311130803Smarcel *retlong += **buf - 'A' + 10; 312130803Smarcel else 313130803Smarcel return -1; 314130803Smarcel } 315130803Smarcel *retlong *= sign; 316130803Smarcel *buf = c; 317130803Smarcel return 0; 318130803Smarcel} 319130803Smarcel 320130803Smarcelstatic int 321130803Smarcelremote_fileio_extract_int (char **buf, long *retint) 322130803Smarcel{ 323130803Smarcel int ret; 324130803Smarcel LONGEST retlong; 325130803Smarcel 326130803Smarcel if (!retint) 327130803Smarcel return -1; 328130803Smarcel ret = remote_fileio_extract_long (buf, &retlong); 329130803Smarcel if (!ret) 330130803Smarcel *retint = (long) retlong; 331130803Smarcel return ret; 332130803Smarcel} 333130803Smarcel 334130803Smarcelstatic int 335130803Smarcelremote_fileio_extract_ptr_w_len (char **buf, CORE_ADDR *ptrval, int *length) 336130803Smarcel{ 337130803Smarcel char *c; 338130803Smarcel LONGEST retlong; 339130803Smarcel 340130803Smarcel if (!buf || !*buf || !**buf || !ptrval || !length) 341130803Smarcel return -1; 342130803Smarcel c = strchr (*buf, '/'); 343130803Smarcel if (!c) 344130803Smarcel return -1; 345130803Smarcel *c++ = '\0'; 346130803Smarcel if (remote_fileio_extract_long (buf, &retlong)) 347130803Smarcel return -1; 348130803Smarcel *ptrval = (CORE_ADDR) retlong; 349130803Smarcel *buf = c; 350130803Smarcel if (remote_fileio_extract_long (buf, &retlong)) 351130803Smarcel return -1; 352130803Smarcel *length = (int) retlong; 353130803Smarcel return 0; 354130803Smarcel} 355130803Smarcel 356130803Smarcel/* Convert to big endian */ 357130803Smarcelstatic void 358130803Smarcelremote_fileio_to_be (LONGEST num, char *buf, int bytes) 359130803Smarcel{ 360130803Smarcel int i; 361130803Smarcel 362130803Smarcel for (i = 0; i < bytes; ++i) 363130803Smarcel buf[i] = (num >> (8 * (bytes - i - 1))) & 0xff; 364130803Smarcel} 365130803Smarcel 366130803Smarcelstatic void 367130803Smarcelremote_fileio_to_fio_uint (long num, fio_uint_t fnum) 368130803Smarcel{ 369130803Smarcel remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4); 370130803Smarcel} 371130803Smarcel 372130803Smarcelstatic void 373130803Smarcelremote_fileio_to_fio_mode (mode_t num, fio_mode_t fnum) 374130803Smarcel{ 375130803Smarcel remote_fileio_to_be (remote_fileio_mode_to_target(num), (char *) fnum, 4); 376130803Smarcel} 377130803Smarcel 378130803Smarcelstatic void 379130803Smarcelremote_fileio_to_fio_time (time_t num, fio_time_t fnum) 380130803Smarcel{ 381130803Smarcel remote_fileio_to_be ((LONGEST) num, (char *) fnum, 4); 382130803Smarcel} 383130803Smarcel 384130803Smarcelstatic void 385130803Smarcelremote_fileio_to_fio_long (LONGEST num, fio_long_t fnum) 386130803Smarcel{ 387130803Smarcel remote_fileio_to_be (num, (char *) fnum, 8); 388130803Smarcel} 389130803Smarcel 390130803Smarcelstatic void 391130803Smarcelremote_fileio_to_fio_ulong (LONGEST num, fio_ulong_t fnum) 392130803Smarcel{ 393130803Smarcel remote_fileio_to_be (num, (char *) fnum, 8); 394130803Smarcel} 395130803Smarcel 396130803Smarcelstatic void 397130803Smarcelremote_fileio_to_fio_stat (struct stat *st, struct fio_stat *fst) 398130803Smarcel{ 399130803Smarcel /* `st_dev' is set in the calling function */ 400130803Smarcel remote_fileio_to_fio_uint ((long) st->st_ino, fst->fst_ino); 401130803Smarcel remote_fileio_to_fio_mode (st->st_mode, fst->fst_mode); 402130803Smarcel remote_fileio_to_fio_uint ((long) st->st_nlink, fst->fst_nlink); 403130803Smarcel remote_fileio_to_fio_uint ((long) st->st_uid, fst->fst_uid); 404130803Smarcel remote_fileio_to_fio_uint ((long) st->st_gid, fst->fst_gid); 405130803Smarcel remote_fileio_to_fio_uint ((long) st->st_rdev, fst->fst_rdev); 406130803Smarcel remote_fileio_to_fio_ulong ((LONGEST) st->st_size, fst->fst_size); 407130803Smarcel remote_fileio_to_fio_ulong ((LONGEST) st->st_blksize, fst->fst_blksize); 408130803Smarcel#if HAVE_STRUCT_STAT_ST_BLOCKS 409130803Smarcel remote_fileio_to_fio_ulong ((LONGEST) st->st_blocks, fst->fst_blocks); 410130803Smarcel#else 411130803Smarcel /* FIXME: This is correct for DJGPP, but other systems that don't 412130803Smarcel have st_blocks, if any, might prefer 512 instead of st_blksize. 413130803Smarcel (eliz, 30-12-2003) */ 414130803Smarcel remote_fileio_to_fio_ulong (((LONGEST) st->st_size + st->st_blksize - 1) 415130803Smarcel / (LONGEST) st->st_blksize, 416130803Smarcel fst->fst_blocks); 417130803Smarcel#endif 418130803Smarcel remote_fileio_to_fio_time (st->st_atime, fst->fst_atime); 419130803Smarcel remote_fileio_to_fio_time (st->st_mtime, fst->fst_mtime); 420130803Smarcel remote_fileio_to_fio_time (st->st_ctime, fst->fst_ctime); 421130803Smarcel} 422130803Smarcel 423130803Smarcelstatic void 424130803Smarcelremote_fileio_to_fio_timeval (struct timeval *tv, struct fio_timeval *ftv) 425130803Smarcel{ 426130803Smarcel remote_fileio_to_fio_time (tv->tv_sec, ftv->ftv_sec); 427130803Smarcel remote_fileio_to_fio_long (tv->tv_usec, ftv->ftv_usec); 428130803Smarcel} 429130803Smarcel 430130803Smarcelstatic int remote_fio_ctrl_c_flag = 0; 431130803Smarcelstatic int remote_fio_no_longjmp = 0; 432130803Smarcel 433130803Smarcel#if defined (HAVE_SIGACTION) && defined (SA_RESTART) 434130803Smarcelstatic struct sigaction remote_fio_sa; 435130803Smarcelstatic struct sigaction remote_fio_osa; 436130803Smarcel#else 437130803Smarcelstatic void (*remote_fio_ofunc)(int); 438130803Smarcel#endif 439130803Smarcel 440130803Smarcelstatic void 441130803Smarcelremote_fileio_sig_init (void) 442130803Smarcel{ 443130803Smarcel#if defined (HAVE_SIGACTION) && defined (SA_RESTART) 444130803Smarcel remote_fio_sa.sa_handler = SIG_IGN; 445130803Smarcel sigemptyset (&remote_fio_sa.sa_mask); 446130803Smarcel remote_fio_sa.sa_flags = 0; 447130803Smarcel sigaction (SIGINT, &remote_fio_sa, &remote_fio_osa); 448130803Smarcel#else 449130803Smarcel remote_fio_ofunc = signal (SIGINT, SIG_IGN); 450130803Smarcel#endif 451130803Smarcel} 452130803Smarcel 453130803Smarcelstatic void 454130803Smarcelremote_fileio_sig_set (void (*sigint_func)(int)) 455130803Smarcel{ 456130803Smarcel#if defined (HAVE_SIGACTION) && defined (SA_RESTART) 457130803Smarcel remote_fio_sa.sa_handler = sigint_func; 458130803Smarcel sigemptyset (&remote_fio_sa.sa_mask); 459130803Smarcel remote_fio_sa.sa_flags = 0; 460130803Smarcel sigaction (SIGINT, &remote_fio_sa, NULL); 461130803Smarcel#else 462130803Smarcel signal (SIGINT, sigint_func); 463130803Smarcel#endif 464130803Smarcel} 465130803Smarcel 466130803Smarcelstatic void 467130803Smarcelremote_fileio_sig_exit (void) 468130803Smarcel{ 469130803Smarcel#if defined (HAVE_SIGACTION) && defined (SA_RESTART) 470130803Smarcel sigaction (SIGINT, &remote_fio_osa, NULL); 471130803Smarcel#else 472130803Smarcel signal (SIGINT, remote_fio_ofunc); 473130803Smarcel#endif 474130803Smarcel} 475130803Smarcel 476130803Smarcelstatic void 477130803Smarcelremote_fileio_ctrl_c_signal_handler (int signo) 478130803Smarcel{ 479130803Smarcel remote_fileio_sig_set (SIG_IGN); 480130803Smarcel remote_fio_ctrl_c_flag = 1; 481130803Smarcel if (!remote_fio_no_longjmp) 482130803Smarcel throw_exception (RETURN_QUIT); 483130803Smarcel remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); 484130803Smarcel} 485130803Smarcel 486130803Smarcelstatic void 487130803Smarcelremote_fileio_reply (int retcode, int error) 488130803Smarcel{ 489130803Smarcel char buf[32]; 490130803Smarcel 491130803Smarcel remote_fileio_sig_set (SIG_IGN); 492130803Smarcel strcpy (buf, "F"); 493130803Smarcel if (retcode < 0) 494130803Smarcel { 495130803Smarcel strcat (buf, "-"); 496130803Smarcel retcode = -retcode; 497130803Smarcel } 498130803Smarcel sprintf (buf + strlen (buf), "%x", retcode); 499130803Smarcel if (error || remote_fio_ctrl_c_flag) 500130803Smarcel { 501130803Smarcel if (error && remote_fio_ctrl_c_flag) 502130803Smarcel error = FILEIO_EINTR; 503130803Smarcel if (error < 0) 504130803Smarcel { 505130803Smarcel strcat (buf, "-"); 506130803Smarcel error = -error; 507130803Smarcel } 508130803Smarcel sprintf (buf + strlen (buf), ",%x", error); 509130803Smarcel if (remote_fio_ctrl_c_flag) 510130803Smarcel strcat (buf, ",C"); 511130803Smarcel } 512130803Smarcel remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); 513130803Smarcel putpkt (buf); 514130803Smarcel} 515130803Smarcel 516130803Smarcelstatic void 517130803Smarcelremote_fileio_ioerror (void) 518130803Smarcel{ 519130803Smarcel remote_fileio_reply (-1, FILEIO_EIO); 520130803Smarcel} 521130803Smarcel 522130803Smarcelstatic void 523130803Smarcelremote_fileio_badfd (void) 524130803Smarcel{ 525130803Smarcel remote_fileio_reply (-1, FILEIO_EBADF); 526130803Smarcel} 527130803Smarcel 528130803Smarcelstatic void 529130803Smarcelremote_fileio_return_errno (int retcode) 530130803Smarcel{ 531130803Smarcel remote_fileio_reply (retcode, 532130803Smarcel retcode < 0 ? remote_fileio_errno_to_target (errno) : 0); 533130803Smarcel} 534130803Smarcel 535130803Smarcelstatic void 536130803Smarcelremote_fileio_return_success (int retcode) 537130803Smarcel{ 538130803Smarcel remote_fileio_reply (retcode, 0); 539130803Smarcel} 540130803Smarcel 541130803Smarcel/* Wrapper function for remote_write_bytes() which has the disadvantage to 542130803Smarcel write only one packet, regardless of the requested number of bytes to 543130803Smarcel transfer. This wrapper calls remote_write_bytes() as often as needed. */ 544130803Smarcelstatic int 545130803Smarcelremote_fileio_write_bytes (CORE_ADDR memaddr, char *myaddr, int len) 546130803Smarcel{ 547130803Smarcel int ret = 0, written; 548130803Smarcel 549130803Smarcel while (len > 0 && (written = remote_write_bytes (memaddr, myaddr, len)) > 0) 550130803Smarcel { 551130803Smarcel len -= written; 552130803Smarcel memaddr += written; 553130803Smarcel myaddr += written; 554130803Smarcel ret += written; 555130803Smarcel } 556130803Smarcel return ret; 557130803Smarcel} 558130803Smarcel 559130803Smarcelstatic void 560130803Smarcelremote_fileio_func_open (char *buf) 561130803Smarcel{ 562130803Smarcel CORE_ADDR ptrval; 563130803Smarcel int length, retlength; 564130803Smarcel long num; 565130803Smarcel int flags, fd; 566130803Smarcel mode_t mode; 567130803Smarcel char *pathname; 568130803Smarcel struct stat st; 569130803Smarcel 570130803Smarcel /* 1. Parameter: Ptr to pathname / length incl. trailing zero */ 571130803Smarcel if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) 572130803Smarcel { 573130803Smarcel remote_fileio_ioerror (); 574130803Smarcel return; 575130803Smarcel } 576130803Smarcel /* 2. Parameter: open flags */ 577130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 578130803Smarcel { 579130803Smarcel remote_fileio_ioerror (); 580130803Smarcel return; 581130803Smarcel } 582130803Smarcel flags = remote_fileio_oflags_to_host (num); 583130803Smarcel /* 3. Parameter: open mode */ 584130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 585130803Smarcel { 586130803Smarcel remote_fileio_ioerror (); 587130803Smarcel return; 588130803Smarcel } 589130803Smarcel mode = remote_fileio_mode_to_host (num, 1); 590130803Smarcel 591130803Smarcel /* Request pathname using 'm' packet */ 592130803Smarcel pathname = alloca (length); 593130803Smarcel retlength = remote_read_bytes (ptrval, pathname, length); 594130803Smarcel if (retlength != length) 595130803Smarcel { 596130803Smarcel remote_fileio_ioerror (); 597130803Smarcel return; 598130803Smarcel } 599130803Smarcel 600130803Smarcel /* Check if pathname exists and is not a regular file or directory. If so, 601130803Smarcel return an appropriate error code. Same for trying to open directories 602130803Smarcel for writing. */ 603130803Smarcel if (!stat (pathname, &st)) 604130803Smarcel { 605130803Smarcel if (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) 606130803Smarcel { 607130803Smarcel remote_fileio_reply (-1, FILEIO_ENODEV); 608130803Smarcel return; 609130803Smarcel } 610130803Smarcel if (S_ISDIR (st.st_mode) 611130803Smarcel && ((flags & O_WRONLY) == O_WRONLY || (flags & O_RDWR) == O_RDWR)) 612130803Smarcel { 613130803Smarcel remote_fileio_reply (-1, FILEIO_EISDIR); 614130803Smarcel return; 615130803Smarcel } 616130803Smarcel } 617130803Smarcel 618130803Smarcel remote_fio_no_longjmp = 1; 619130803Smarcel fd = open (pathname, flags, mode); 620130803Smarcel if (fd < 0) 621130803Smarcel { 622130803Smarcel remote_fileio_return_errno (-1); 623130803Smarcel return; 624130803Smarcel } 625130803Smarcel 626130803Smarcel fd = remote_fileio_fd_to_targetfd (fd); 627130803Smarcel remote_fileio_return_success (fd); 628130803Smarcel} 629130803Smarcel 630130803Smarcelstatic void 631130803Smarcelremote_fileio_func_close (char *buf) 632130803Smarcel{ 633130803Smarcel long num; 634130803Smarcel int fd; 635130803Smarcel 636130803Smarcel /* Parameter: file descriptor */ 637130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 638130803Smarcel { 639130803Smarcel remote_fileio_ioerror (); 640130803Smarcel return; 641130803Smarcel } 642130803Smarcel fd = remote_fileio_map_fd ((int) num); 643130803Smarcel if (fd == FIO_FD_INVALID) 644130803Smarcel { 645130803Smarcel remote_fileio_badfd (); 646130803Smarcel return; 647130803Smarcel } 648130803Smarcel 649130803Smarcel remote_fio_no_longjmp = 1; 650130803Smarcel if (fd != FIO_FD_CONSOLE_IN && fd != FIO_FD_CONSOLE_OUT && close (fd)) 651130803Smarcel remote_fileio_return_errno (-1); 652130803Smarcel remote_fileio_close_target_fd ((int) num); 653130803Smarcel remote_fileio_return_success (0); 654130803Smarcel} 655130803Smarcel 656130803Smarcelstatic void 657130803Smarcelremote_fileio_func_read (char *buf) 658130803Smarcel{ 659130803Smarcel long target_fd, num; 660130803Smarcel LONGEST lnum; 661130803Smarcel CORE_ADDR ptrval; 662130803Smarcel int fd, ret, retlength; 663130803Smarcel char *buffer; 664130803Smarcel size_t length; 665130803Smarcel off_t old_offset, new_offset; 666130803Smarcel 667130803Smarcel /* 1. Parameter: file descriptor */ 668130803Smarcel if (remote_fileio_extract_int (&buf, &target_fd)) 669130803Smarcel { 670130803Smarcel remote_fileio_ioerror (); 671130803Smarcel return; 672130803Smarcel } 673130803Smarcel fd = remote_fileio_map_fd ((int) target_fd); 674130803Smarcel if (fd == FIO_FD_INVALID) 675130803Smarcel { 676130803Smarcel remote_fileio_badfd (); 677130803Smarcel return; 678130803Smarcel } 679130803Smarcel /* 2. Parameter: buffer pointer */ 680130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 681130803Smarcel { 682130803Smarcel remote_fileio_ioerror (); 683130803Smarcel return; 684130803Smarcel } 685130803Smarcel ptrval = (CORE_ADDR) lnum; 686130803Smarcel /* 3. Parameter: buffer length */ 687130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 688130803Smarcel { 689130803Smarcel remote_fileio_ioerror (); 690130803Smarcel return; 691130803Smarcel } 692130803Smarcel length = (size_t) num; 693130803Smarcel 694130803Smarcel switch (fd) 695130803Smarcel { 696130803Smarcel case FIO_FD_CONSOLE_OUT: 697130803Smarcel remote_fileio_badfd (); 698130803Smarcel return; 699130803Smarcel case FIO_FD_CONSOLE_IN: 700130803Smarcel { 701130803Smarcel static char *remaining_buf = NULL; 702130803Smarcel static int remaining_length = 0; 703130803Smarcel 704130803Smarcel buffer = (char *) xmalloc (32768); 705130803Smarcel if (remaining_buf) 706130803Smarcel { 707130803Smarcel remote_fio_no_longjmp = 1; 708130803Smarcel if (remaining_length > length) 709130803Smarcel { 710130803Smarcel memcpy (buffer, remaining_buf, length); 711130803Smarcel memmove (remaining_buf, remaining_buf + length, 712130803Smarcel remaining_length - length); 713130803Smarcel remaining_length -= length; 714130803Smarcel ret = length; 715130803Smarcel } 716130803Smarcel else 717130803Smarcel { 718130803Smarcel memcpy (buffer, remaining_buf, remaining_length); 719130803Smarcel xfree (remaining_buf); 720130803Smarcel remaining_buf = NULL; 721130803Smarcel ret = remaining_length; 722130803Smarcel } 723130803Smarcel } 724130803Smarcel else 725130803Smarcel { 726130803Smarcel ret = ui_file_read (gdb_stdtargin, buffer, 32767); 727130803Smarcel remote_fio_no_longjmp = 1; 728130803Smarcel if (ret > 0 && (size_t)ret > length) 729130803Smarcel { 730130803Smarcel remaining_buf = (char *) xmalloc (ret - length); 731130803Smarcel remaining_length = ret - length; 732130803Smarcel memcpy (remaining_buf, buffer + length, remaining_length); 733130803Smarcel ret = length; 734130803Smarcel } 735130803Smarcel } 736130803Smarcel } 737130803Smarcel break; 738130803Smarcel default: 739130803Smarcel buffer = (char *) xmalloc (length); 740130803Smarcel /* POSIX defines EINTR behaviour of read in a weird way. It's allowed 741130803Smarcel for read() to return -1 even if "some" bytes have been read. It 742130803Smarcel has been corrected in SUSv2 but that doesn't help us much... 743130803Smarcel Therefore a complete solution must check how many bytes have been 744130803Smarcel read on EINTR to return a more reliable value to the target */ 745130803Smarcel old_offset = lseek (fd, 0, SEEK_CUR); 746130803Smarcel remote_fio_no_longjmp = 1; 747130803Smarcel ret = read (fd, buffer, length); 748130803Smarcel if (ret < 0 && errno == EINTR) 749130803Smarcel { 750130803Smarcel new_offset = lseek (fd, 0, SEEK_CUR); 751130803Smarcel /* If some data has been read, return the number of bytes read. 752130803Smarcel The Ctrl-C flag is set in remote_fileio_reply() anyway */ 753130803Smarcel if (old_offset != new_offset) 754130803Smarcel ret = new_offset - old_offset; 755130803Smarcel } 756130803Smarcel break; 757130803Smarcel } 758130803Smarcel 759130803Smarcel if (ret > 0) 760130803Smarcel { 761130803Smarcel retlength = remote_fileio_write_bytes (ptrval, buffer, ret); 762130803Smarcel if (retlength != ret) 763130803Smarcel ret = -1; /* errno has been set to EIO in remote_fileio_write_bytes() */ 764130803Smarcel } 765130803Smarcel 766130803Smarcel if (ret < 0) 767130803Smarcel remote_fileio_return_errno (-1); 768130803Smarcel else 769130803Smarcel remote_fileio_return_success (ret); 770130803Smarcel 771130803Smarcel xfree (buffer); 772130803Smarcel} 773130803Smarcel 774130803Smarcelstatic void 775130803Smarcelremote_fileio_func_write (char *buf) 776130803Smarcel{ 777130803Smarcel long target_fd, num; 778130803Smarcel LONGEST lnum; 779130803Smarcel CORE_ADDR ptrval; 780130803Smarcel int fd, ret, retlength; 781130803Smarcel char *buffer; 782130803Smarcel size_t length; 783130803Smarcel 784130803Smarcel /* 1. Parameter: file descriptor */ 785130803Smarcel if (remote_fileio_extract_int (&buf, &target_fd)) 786130803Smarcel { 787130803Smarcel remote_fileio_ioerror (); 788130803Smarcel return; 789130803Smarcel } 790130803Smarcel fd = remote_fileio_map_fd ((int) target_fd); 791130803Smarcel if (fd == FIO_FD_INVALID) 792130803Smarcel { 793130803Smarcel remote_fileio_badfd (); 794130803Smarcel return; 795130803Smarcel } 796130803Smarcel /* 2. Parameter: buffer pointer */ 797130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 798130803Smarcel { 799130803Smarcel remote_fileio_ioerror (); 800130803Smarcel return; 801130803Smarcel } 802130803Smarcel ptrval = (CORE_ADDR) lnum; 803130803Smarcel /* 3. Parameter: buffer length */ 804130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 805130803Smarcel { 806130803Smarcel remote_fileio_ioerror (); 807130803Smarcel return; 808130803Smarcel } 809130803Smarcel length = (size_t) num; 810130803Smarcel 811130803Smarcel buffer = (char *) xmalloc (length); 812130803Smarcel retlength = remote_read_bytes (ptrval, buffer, length); 813130803Smarcel if (retlength != length) 814130803Smarcel { 815130803Smarcel xfree (buffer); 816130803Smarcel remote_fileio_ioerror (); 817130803Smarcel return; 818130803Smarcel } 819130803Smarcel 820130803Smarcel remote_fio_no_longjmp = 1; 821130803Smarcel switch (fd) 822130803Smarcel { 823130803Smarcel case FIO_FD_CONSOLE_IN: 824130803Smarcel remote_fileio_badfd (); 825130803Smarcel return; 826130803Smarcel case FIO_FD_CONSOLE_OUT: 827130803Smarcel ui_file_write (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr, buffer, 828130803Smarcel length); 829130803Smarcel gdb_flush (target_fd == 1 ? gdb_stdtarg : gdb_stdtargerr); 830130803Smarcel ret = length; 831130803Smarcel break; 832130803Smarcel default: 833130803Smarcel ret = write (fd, buffer, length); 834130803Smarcel if (ret < 0 && errno == EACCES) 835130803Smarcel errno = EBADF; /* Cygwin returns EACCESS when writing to a R/O file.*/ 836130803Smarcel break; 837130803Smarcel } 838130803Smarcel 839130803Smarcel if (ret < 0) 840130803Smarcel remote_fileio_return_errno (-1); 841130803Smarcel else 842130803Smarcel remote_fileio_return_success (ret); 843130803Smarcel 844130803Smarcel xfree (buffer); 845130803Smarcel} 846130803Smarcel 847130803Smarcelstatic void 848130803Smarcelremote_fileio_func_lseek (char *buf) 849130803Smarcel{ 850130803Smarcel long num; 851130803Smarcel LONGEST lnum; 852130803Smarcel int fd, flag; 853130803Smarcel off_t offset, ret; 854130803Smarcel 855130803Smarcel /* 1. Parameter: file descriptor */ 856130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 857130803Smarcel { 858130803Smarcel remote_fileio_ioerror (); 859130803Smarcel return; 860130803Smarcel } 861130803Smarcel fd = remote_fileio_map_fd ((int) num); 862130803Smarcel if (fd == FIO_FD_INVALID) 863130803Smarcel { 864130803Smarcel remote_fileio_badfd (); 865130803Smarcel return; 866130803Smarcel } 867130803Smarcel else if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT) 868130803Smarcel { 869130803Smarcel remote_fileio_reply (-1, FILEIO_ESPIPE); 870130803Smarcel return; 871130803Smarcel } 872130803Smarcel 873130803Smarcel /* 2. Parameter: offset */ 874130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 875130803Smarcel { 876130803Smarcel remote_fileio_ioerror (); 877130803Smarcel return; 878130803Smarcel } 879130803Smarcel offset = (off_t) lnum; 880130803Smarcel /* 3. Parameter: flag */ 881130803Smarcel if (remote_fileio_extract_int (&buf, &num)) 882130803Smarcel { 883130803Smarcel remote_fileio_ioerror (); 884130803Smarcel return; 885130803Smarcel } 886130803Smarcel if (remote_fileio_seek_flag_to_host (num, &flag)) 887130803Smarcel { 888130803Smarcel remote_fileio_reply (-1, FILEIO_EINVAL); 889130803Smarcel return; 890130803Smarcel } 891130803Smarcel 892130803Smarcel remote_fio_no_longjmp = 1; 893130803Smarcel ret = lseek (fd, offset, flag); 894130803Smarcel 895130803Smarcel if (ret == (off_t) -1) 896130803Smarcel remote_fileio_return_errno (-1); 897130803Smarcel else 898130803Smarcel remote_fileio_return_success (ret); 899130803Smarcel} 900130803Smarcel 901130803Smarcelstatic void 902130803Smarcelremote_fileio_func_rename (char *buf) 903130803Smarcel{ 904130803Smarcel CORE_ADDR ptrval; 905130803Smarcel int length, retlength; 906130803Smarcel char *oldpath, *newpath; 907130803Smarcel int ret, of, nf; 908130803Smarcel struct stat ost, nst; 909130803Smarcel 910130803Smarcel /* 1. Parameter: Ptr to oldpath / length incl. trailing zero */ 911130803Smarcel if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) 912130803Smarcel { 913130803Smarcel remote_fileio_ioerror (); 914130803Smarcel return; 915130803Smarcel } 916130803Smarcel /* Request oldpath using 'm' packet */ 917130803Smarcel oldpath = alloca (length); 918130803Smarcel retlength = remote_read_bytes (ptrval, oldpath, length); 919130803Smarcel if (retlength != length) 920130803Smarcel { 921130803Smarcel remote_fileio_ioerror (); 922130803Smarcel return; 923130803Smarcel } 924130803Smarcel /* 2. Parameter: Ptr to newpath / length incl. trailing zero */ 925130803Smarcel if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) 926130803Smarcel { 927130803Smarcel remote_fileio_ioerror (); 928130803Smarcel return; 929130803Smarcel } 930130803Smarcel /* Request newpath using 'm' packet */ 931130803Smarcel newpath = alloca (length); 932130803Smarcel retlength = remote_read_bytes (ptrval, newpath, length); 933130803Smarcel if (retlength != length) 934130803Smarcel { 935130803Smarcel remote_fileio_ioerror (); 936130803Smarcel return; 937130803Smarcel } 938130803Smarcel 939130803Smarcel /* Only operate on regular files and directories */ 940130803Smarcel of = stat (oldpath, &ost); 941130803Smarcel nf = stat (newpath, &nst); 942130803Smarcel if ((!of && !S_ISREG (ost.st_mode) && !S_ISDIR (ost.st_mode)) 943130803Smarcel || (!nf && !S_ISREG (nst.st_mode) && !S_ISDIR (nst.st_mode))) 944130803Smarcel { 945130803Smarcel remote_fileio_reply (-1, FILEIO_EACCES); 946130803Smarcel return; 947130803Smarcel } 948130803Smarcel 949130803Smarcel remote_fio_no_longjmp = 1; 950130803Smarcel ret = rename (oldpath, newpath); 951130803Smarcel 952130803Smarcel if (ret == -1) 953130803Smarcel { 954130803Smarcel /* Special case: newpath is a non-empty directory. Some systems 955130803Smarcel return ENOTEMPTY, some return EEXIST. We coerce that to be 956130803Smarcel always EEXIST. */ 957130803Smarcel if (errno == ENOTEMPTY) 958130803Smarcel errno = EEXIST; 959130803Smarcel#ifdef __CYGWIN__ 960130803Smarcel /* Workaround some Cygwin problems with correct errnos. */ 961130803Smarcel if (errno == EACCES) 962130803Smarcel { 963130803Smarcel if (!of && !nf && S_ISDIR (nst.st_mode)) 964130803Smarcel { 965130803Smarcel if (S_ISREG (ost.st_mode)) 966130803Smarcel errno = EISDIR; 967130803Smarcel else 968130803Smarcel { 969130803Smarcel char oldfullpath[PATH_MAX + 1]; 970130803Smarcel char newfullpath[PATH_MAX + 1]; 971130803Smarcel int len; 972130803Smarcel 973130803Smarcel cygwin_conv_to_full_posix_path (oldpath, oldfullpath); 974130803Smarcel cygwin_conv_to_full_posix_path (newpath, newfullpath); 975130803Smarcel len = strlen (oldfullpath); 976130803Smarcel if (newfullpath[len] == '/' 977130803Smarcel && !strncmp (oldfullpath, newfullpath, len)) 978130803Smarcel errno = EINVAL; 979130803Smarcel else 980130803Smarcel errno = EEXIST; 981130803Smarcel } 982130803Smarcel } 983130803Smarcel } 984130803Smarcel#endif 985130803Smarcel 986130803Smarcel remote_fileio_return_errno (-1); 987130803Smarcel } 988130803Smarcel else 989130803Smarcel remote_fileio_return_success (ret); 990130803Smarcel} 991130803Smarcel 992130803Smarcelstatic void 993130803Smarcelremote_fileio_func_unlink (char *buf) 994130803Smarcel{ 995130803Smarcel CORE_ADDR ptrval; 996130803Smarcel int length, retlength; 997130803Smarcel char *pathname; 998130803Smarcel int ret; 999130803Smarcel struct stat st; 1000130803Smarcel 1001130803Smarcel /* Parameter: Ptr to pathname / length incl. trailing zero */ 1002130803Smarcel if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) 1003130803Smarcel { 1004130803Smarcel remote_fileio_ioerror (); 1005130803Smarcel return; 1006130803Smarcel } 1007130803Smarcel /* Request pathname using 'm' packet */ 1008130803Smarcel pathname = alloca (length); 1009130803Smarcel retlength = remote_read_bytes (ptrval, pathname, length); 1010130803Smarcel if (retlength != length) 1011130803Smarcel { 1012130803Smarcel remote_fileio_ioerror (); 1013130803Smarcel return; 1014130803Smarcel } 1015130803Smarcel 1016130803Smarcel /* Only operate on regular files (and directories, which allows to return 1017130803Smarcel the correct return code) */ 1018130803Smarcel if (!stat (pathname, &st) && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) 1019130803Smarcel { 1020130803Smarcel remote_fileio_reply (-1, FILEIO_ENODEV); 1021130803Smarcel return; 1022130803Smarcel } 1023130803Smarcel 1024130803Smarcel remote_fio_no_longjmp = 1; 1025130803Smarcel ret = unlink (pathname); 1026130803Smarcel 1027130803Smarcel if (ret == -1) 1028130803Smarcel remote_fileio_return_errno (-1); 1029130803Smarcel else 1030130803Smarcel remote_fileio_return_success (ret); 1031130803Smarcel} 1032130803Smarcel 1033130803Smarcelstatic void 1034130803Smarcelremote_fileio_func_stat (char *buf) 1035130803Smarcel{ 1036130803Smarcel CORE_ADDR ptrval; 1037130803Smarcel int ret, length, retlength; 1038130803Smarcel char *pathname; 1039130803Smarcel LONGEST lnum; 1040130803Smarcel struct stat st; 1041130803Smarcel struct fio_stat fst; 1042130803Smarcel 1043130803Smarcel /* 1. Parameter: Ptr to pathname / length incl. trailing zero */ 1044130803Smarcel if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) 1045130803Smarcel { 1046130803Smarcel remote_fileio_ioerror (); 1047130803Smarcel return; 1048130803Smarcel } 1049130803Smarcel /* Request pathname using 'm' packet */ 1050130803Smarcel pathname = alloca (length); 1051130803Smarcel retlength = remote_read_bytes (ptrval, pathname, length); 1052130803Smarcel if (retlength != length) 1053130803Smarcel { 1054130803Smarcel remote_fileio_ioerror (); 1055130803Smarcel return; 1056130803Smarcel } 1057130803Smarcel 1058130803Smarcel /* 2. Parameter: Ptr to struct stat */ 1059130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 1060130803Smarcel { 1061130803Smarcel remote_fileio_ioerror (); 1062130803Smarcel return; 1063130803Smarcel } 1064130803Smarcel ptrval = (CORE_ADDR) lnum; 1065130803Smarcel 1066130803Smarcel remote_fio_no_longjmp = 1; 1067130803Smarcel ret = stat (pathname, &st); 1068130803Smarcel 1069130803Smarcel if (ret == -1) 1070130803Smarcel { 1071130803Smarcel remote_fileio_return_errno (-1); 1072130803Smarcel return; 1073130803Smarcel } 1074130803Smarcel /* Only operate on regular files and directories */ 1075130803Smarcel if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode)) 1076130803Smarcel { 1077130803Smarcel remote_fileio_reply (-1, FILEIO_EACCES); 1078130803Smarcel return; 1079130803Smarcel } 1080130803Smarcel if (ptrval) 1081130803Smarcel { 1082130803Smarcel remote_fileio_to_fio_stat (&st, &fst); 1083130803Smarcel remote_fileio_to_fio_uint (0, fst.fst_dev); 1084130803Smarcel 1085130803Smarcel retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst); 1086130803Smarcel if (retlength != sizeof fst) 1087130803Smarcel { 1088130803Smarcel remote_fileio_return_errno (-1); 1089130803Smarcel return; 1090130803Smarcel } 1091130803Smarcel } 1092130803Smarcel remote_fileio_return_success (ret); 1093130803Smarcel} 1094130803Smarcel 1095130803Smarcelstatic void 1096130803Smarcelremote_fileio_func_fstat (char *buf) 1097130803Smarcel{ 1098130803Smarcel CORE_ADDR ptrval; 1099130803Smarcel int fd, ret, retlength; 1100130803Smarcel long target_fd; 1101130803Smarcel LONGEST lnum; 1102130803Smarcel struct stat st; 1103130803Smarcel struct fio_stat fst; 1104130803Smarcel struct timeval tv; 1105130803Smarcel 1106130803Smarcel /* 1. Parameter: file descriptor */ 1107130803Smarcel if (remote_fileio_extract_int (&buf, &target_fd)) 1108130803Smarcel { 1109130803Smarcel remote_fileio_ioerror (); 1110130803Smarcel return; 1111130803Smarcel } 1112130803Smarcel fd = remote_fileio_map_fd ((int) target_fd); 1113130803Smarcel if (fd == FIO_FD_INVALID) 1114130803Smarcel { 1115130803Smarcel remote_fileio_badfd (); 1116130803Smarcel return; 1117130803Smarcel } 1118130803Smarcel /* 2. Parameter: Ptr to struct stat */ 1119130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 1120130803Smarcel { 1121130803Smarcel remote_fileio_ioerror (); 1122130803Smarcel return; 1123130803Smarcel } 1124130803Smarcel ptrval = (CORE_ADDR) lnum; 1125130803Smarcel 1126130803Smarcel remote_fio_no_longjmp = 1; 1127130803Smarcel if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT) 1128130803Smarcel { 1129130803Smarcel remote_fileio_to_fio_uint (1, fst.fst_dev); 1130130803Smarcel st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR); 1131130803Smarcel st.st_nlink = 1; 1132130803Smarcel st.st_uid = getuid (); 1133130803Smarcel st.st_gid = getgid (); 1134130803Smarcel st.st_rdev = 0; 1135130803Smarcel st.st_size = 0; 1136130803Smarcel st.st_blksize = 512; 1137130803Smarcel#if HAVE_STRUCT_STAT_ST_BLOCKS 1138130803Smarcel st.st_blocks = 0; 1139130803Smarcel#endif 1140130803Smarcel if (!gettimeofday (&tv, NULL)) 1141130803Smarcel st.st_atime = st.st_mtime = st.st_ctime = tv.tv_sec; 1142130803Smarcel else 1143130803Smarcel st.st_atime = st.st_mtime = st.st_ctime = (time_t) 0; 1144130803Smarcel ret = 0; 1145130803Smarcel } 1146130803Smarcel else 1147130803Smarcel ret = fstat (fd, &st); 1148130803Smarcel 1149130803Smarcel if (ret == -1) 1150130803Smarcel { 1151130803Smarcel remote_fileio_return_errno (-1); 1152130803Smarcel return; 1153130803Smarcel } 1154130803Smarcel if (ptrval) 1155130803Smarcel { 1156130803Smarcel remote_fileio_to_fio_stat (&st, &fst); 1157130803Smarcel 1158130803Smarcel retlength = remote_fileio_write_bytes (ptrval, (char *) &fst, sizeof fst); 1159130803Smarcel if (retlength != sizeof fst) 1160130803Smarcel { 1161130803Smarcel remote_fileio_return_errno (-1); 1162130803Smarcel return; 1163130803Smarcel } 1164130803Smarcel } 1165130803Smarcel remote_fileio_return_success (ret); 1166130803Smarcel} 1167130803Smarcel 1168130803Smarcelstatic void 1169130803Smarcelremote_fileio_func_gettimeofday (char *buf) 1170130803Smarcel{ 1171130803Smarcel LONGEST lnum; 1172130803Smarcel CORE_ADDR ptrval; 1173130803Smarcel int ret, retlength; 1174130803Smarcel struct timeval tv; 1175130803Smarcel struct fio_timeval ftv; 1176130803Smarcel 1177130803Smarcel /* 1. Parameter: struct timeval pointer */ 1178130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 1179130803Smarcel { 1180130803Smarcel remote_fileio_ioerror (); 1181130803Smarcel return; 1182130803Smarcel } 1183130803Smarcel ptrval = (CORE_ADDR) lnum; 1184130803Smarcel /* 2. Parameter: some pointer value... */ 1185130803Smarcel if (remote_fileio_extract_long (&buf, &lnum)) 1186130803Smarcel { 1187130803Smarcel remote_fileio_ioerror (); 1188130803Smarcel return; 1189130803Smarcel } 1190130803Smarcel /* ...which has to be NULL */ 1191130803Smarcel if (lnum) 1192130803Smarcel { 1193130803Smarcel remote_fileio_reply (-1, FILEIO_EINVAL); 1194130803Smarcel return; 1195130803Smarcel } 1196130803Smarcel 1197130803Smarcel remote_fio_no_longjmp = 1; 1198130803Smarcel ret = gettimeofday (&tv, NULL); 1199130803Smarcel 1200130803Smarcel if (ret == -1) 1201130803Smarcel { 1202130803Smarcel remote_fileio_return_errno (-1); 1203130803Smarcel return; 1204130803Smarcel } 1205130803Smarcel 1206130803Smarcel if (ptrval) 1207130803Smarcel { 1208130803Smarcel remote_fileio_to_fio_timeval (&tv, &ftv); 1209130803Smarcel 1210130803Smarcel retlength = remote_fileio_write_bytes (ptrval, (char *) &ftv, sizeof ftv); 1211130803Smarcel if (retlength != sizeof ftv) 1212130803Smarcel { 1213130803Smarcel remote_fileio_return_errno (-1); 1214130803Smarcel return; 1215130803Smarcel } 1216130803Smarcel } 1217130803Smarcel remote_fileio_return_success (ret); 1218130803Smarcel} 1219130803Smarcel 1220130803Smarcelstatic void 1221130803Smarcelremote_fileio_func_isatty (char *buf) 1222130803Smarcel{ 1223130803Smarcel long target_fd; 1224130803Smarcel int fd; 1225130803Smarcel 1226130803Smarcel /* Parameter: file descriptor */ 1227130803Smarcel if (remote_fileio_extract_int (&buf, &target_fd)) 1228130803Smarcel { 1229130803Smarcel remote_fileio_ioerror (); 1230130803Smarcel return; 1231130803Smarcel } 1232130803Smarcel remote_fio_no_longjmp = 1; 1233130803Smarcel fd = remote_fileio_map_fd ((int) target_fd); 1234130803Smarcel remote_fileio_return_success (fd == FIO_FD_CONSOLE_IN || 1235130803Smarcel fd == FIO_FD_CONSOLE_OUT ? 1 : 0); 1236130803Smarcel} 1237130803Smarcel 1238130803Smarcelstatic void 1239130803Smarcelremote_fileio_func_system (char *buf) 1240130803Smarcel{ 1241130803Smarcel CORE_ADDR ptrval; 1242130803Smarcel int ret, length, retlength; 1243130803Smarcel char *cmdline; 1244130803Smarcel 1245130803Smarcel /* Check if system(3) has been explicitely allowed using the 1246130803Smarcel `set remote system-call-allowed 1' command. If not, return 1247130803Smarcel EPERM */ 1248130803Smarcel if (!remote_fio_system_call_allowed) 1249130803Smarcel { 1250130803Smarcel remote_fileio_reply (-1, FILEIO_EPERM); 1251130803Smarcel return; 1252130803Smarcel } 1253130803Smarcel 1254130803Smarcel /* Parameter: Ptr to commandline / length incl. trailing zero */ 1255130803Smarcel if (remote_fileio_extract_ptr_w_len (&buf, &ptrval, &length)) 1256130803Smarcel { 1257130803Smarcel remote_fileio_ioerror (); 1258130803Smarcel return; 1259130803Smarcel } 1260130803Smarcel /* Request commandline using 'm' packet */ 1261130803Smarcel cmdline = alloca (length); 1262130803Smarcel retlength = remote_read_bytes (ptrval, cmdline, length); 1263130803Smarcel if (retlength != length) 1264130803Smarcel { 1265130803Smarcel remote_fileio_ioerror (); 1266130803Smarcel return; 1267130803Smarcel } 1268130803Smarcel 1269130803Smarcel remote_fio_no_longjmp = 1; 1270130803Smarcel ret = system (cmdline); 1271130803Smarcel 1272130803Smarcel if (ret == -1) 1273130803Smarcel remote_fileio_return_errno (-1); 1274130803Smarcel else 1275130803Smarcel remote_fileio_return_success (WEXITSTATUS (ret)); 1276130803Smarcel} 1277130803Smarcel 1278130803Smarcelstatic struct { 1279130803Smarcel char *name; 1280130803Smarcel void (*func)(char *); 1281130803Smarcel} remote_fio_func_map[] = { 1282130803Smarcel "open", remote_fileio_func_open, 1283130803Smarcel "close", remote_fileio_func_close, 1284130803Smarcel "read", remote_fileio_func_read, 1285130803Smarcel "write", remote_fileio_func_write, 1286130803Smarcel "lseek", remote_fileio_func_lseek, 1287130803Smarcel "rename", remote_fileio_func_rename, 1288130803Smarcel "unlink", remote_fileio_func_unlink, 1289130803Smarcel "stat", remote_fileio_func_stat, 1290130803Smarcel "fstat", remote_fileio_func_fstat, 1291130803Smarcel "gettimeofday", remote_fileio_func_gettimeofday, 1292130803Smarcel "isatty", remote_fileio_func_isatty, 1293130803Smarcel "system", remote_fileio_func_system, 1294130803Smarcel NULL, NULL 1295130803Smarcel}; 1296130803Smarcel 1297130803Smarcelstatic int 1298130803Smarceldo_remote_fileio_request (struct ui_out *uiout, void *buf_arg) 1299130803Smarcel{ 1300130803Smarcel char *buf = buf_arg; 1301130803Smarcel char *c; 1302130803Smarcel int idx; 1303130803Smarcel 1304130803Smarcel remote_fileio_sig_set (remote_fileio_ctrl_c_signal_handler); 1305130803Smarcel 1306130803Smarcel c = strchr (++buf, ','); 1307130803Smarcel if (c) 1308130803Smarcel *c++ = '\0'; 1309130803Smarcel else 1310130803Smarcel c = strchr (buf, '\0'); 1311130803Smarcel for (idx = 0; remote_fio_func_map[idx].name; ++idx) 1312130803Smarcel if (!strcmp (remote_fio_func_map[idx].name, buf)) 1313130803Smarcel break; 1314130803Smarcel if (!remote_fio_func_map[idx].name) /* ERROR: No such function. */ 1315130803Smarcel return RETURN_ERROR; 1316130803Smarcel remote_fio_func_map[idx].func (c); 1317130803Smarcel return 0; 1318130803Smarcel} 1319130803Smarcel 1320130803Smarcelvoid 1321130803Smarcelremote_fileio_request (char *buf) 1322130803Smarcel{ 1323130803Smarcel int ex; 1324130803Smarcel 1325130803Smarcel remote_fileio_sig_init (); 1326130803Smarcel 1327130803Smarcel remote_fio_ctrl_c_flag = 0; 1328130803Smarcel remote_fio_no_longjmp = 0; 1329130803Smarcel 1330130803Smarcel ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf, 1331130803Smarcel NULL, RETURN_MASK_ALL); 1332130803Smarcel switch (ex) 1333130803Smarcel { 1334130803Smarcel case RETURN_ERROR: 1335130803Smarcel remote_fileio_reply (-1, FILEIO_ENOSYS); 1336130803Smarcel break; 1337130803Smarcel case RETURN_QUIT: 1338130803Smarcel remote_fileio_reply (-1, FILEIO_EINTR); 1339130803Smarcel break; 1340130803Smarcel default: 1341130803Smarcel break; 1342130803Smarcel } 1343130803Smarcel 1344130803Smarcel remote_fileio_sig_exit (); 1345130803Smarcel} 1346130803Smarcel 1347130803Smarcelstatic void 1348130803Smarcelset_system_call_allowed (char *args, int from_tty) 1349130803Smarcel{ 1350130803Smarcel if (args) 1351130803Smarcel { 1352130803Smarcel char *arg_end; 1353130803Smarcel int val = strtoul (args, &arg_end, 10); 1354130803Smarcel if (*args && *arg_end == '\0') 1355130803Smarcel { 1356130803Smarcel remote_fio_system_call_allowed = !!val; 1357130803Smarcel return; 1358130803Smarcel } 1359130803Smarcel } 1360130803Smarcel error ("Illegal argument for \"set remote system-call-allowed\" command"); 1361130803Smarcel} 1362130803Smarcel 1363130803Smarcelstatic void 1364130803Smarcelshow_system_call_allowed (char *args, int from_tty) 1365130803Smarcel{ 1366130803Smarcel if (args) 1367130803Smarcel error ("Garbage after \"show remote system-call-allowed\" command: `%s'", args); 1368130803Smarcel printf_unfiltered ("Calling host system(3) call from target is %sallowed\n", 1369130803Smarcel remote_fio_system_call_allowed ? "" : "not "); 1370130803Smarcel} 1371130803Smarcel 1372130803Smarcelvoid 1373130803Smarcelinitialize_remote_fileio (struct cmd_list_element *remote_set_cmdlist, 1374130803Smarcel struct cmd_list_element *remote_show_cmdlist) 1375130803Smarcel{ 1376130803Smarcel add_cmd ("system-call-allowed", no_class, 1377130803Smarcel set_system_call_allowed, 1378130803Smarcel "Set if the host system(3) call is allowed for the target.\n", 1379130803Smarcel &remote_set_cmdlist); 1380130803Smarcel add_cmd ("system-call-allowed", no_class, 1381130803Smarcel show_system_call_allowed, 1382130803Smarcel "Show if the host system(3) call is allowed for the target.\n", 1383130803Smarcel &remote_show_cmdlist); 1384130803Smarcel} 1385