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