1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 Contributed by CodeSourcery.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22 #include "gdb/fileio.h"
28 extern int remote_debug
;
36 static struct fd_list
*open_fds
;
39 safe_fromhex (char a
, int *nibble
)
41 if (a
>= '0' && a
<= '9')
43 else if (a
>= 'a' && a
<= 'f')
44 *nibble
= a
- 'a' + 10;
45 else if (a
>= 'A' && a
<= 'F')
46 *nibble
= a
- 'A' + 10;
54 require_filename (char **pp
, char *filename
)
62 while (*p
&& *p
!= ',')
66 /* Don't allow overflow. */
67 if (count
>= PATH_MAX
- 1)
70 if (safe_fromhex (p
[0], &nib1
)
71 || safe_fromhex (p
[1], &nib2
))
74 filename
[count
++] = nib1
* 16 + nib2
;
78 filename
[count
] = '\0';
84 require_int (char **pp
, int *value
)
93 while (*p
&& *p
!= ',')
97 /* Don't allow overflow. */
101 if (safe_fromhex (p
[0], &nib
))
103 *value
= *value
* 16 + nib
;
113 require_data (char *p
, int p_len
, char **data
, int *data_len
)
115 int input_index
, output_index
, escaped
;
117 *data
= xmalloc (p_len
);
121 for (input_index
= 0; input_index
< p_len
; input_index
++)
123 char b
= p
[input_index
];
127 (*data
)[output_index
++] = b
^ 0x20;
133 (*data
)[output_index
++] = b
;
142 *data_len
= output_index
;
147 require_comma (char **pp
)
159 require_end (char *p
)
168 require_valid_fd (int fd
)
170 struct fd_list
*fd_ptr
;
172 for (fd_ptr
= open_fds
; fd_ptr
!= NULL
; fd_ptr
= fd_ptr
->next
)
173 if (fd_ptr
->fd
== fd
)
179 /* Fill in own_buf with the last hostio error packet, however it
180 suitable for the target. */
182 hostio_error (char *own_buf
)
184 the_target
->hostio_last_error (own_buf
);
188 hostio_packet_error (char *own_buf
)
190 sprintf (own_buf
, "F-1,%x", FILEIO_EINVAL
);
194 hostio_reply (char *own_buf
, int result
)
196 sprintf (own_buf
, "F%x", result
);
200 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
203 int input_index
, output_index
, out_maxlen
;
205 sprintf (own_buf
, "F%x;", len
);
206 output_index
= strlen (own_buf
);
208 out_maxlen
= PBUFSIZ
;
210 for (input_index
= 0; input_index
< len
; input_index
++)
212 char b
= buffer
[input_index
];
214 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
216 /* These must be escaped. */
217 if (output_index
+ 2 > out_maxlen
)
219 own_buf
[output_index
++] = '}';
220 own_buf
[output_index
++] = b
^ 0x20;
224 if (output_index
+ 1 > out_maxlen
)
226 own_buf
[output_index
++] = b
;
230 *new_packet_len
= output_index
;
235 fileio_open_flags_to_host (int fileio_open_flags
, int *open_flags_p
)
239 if (fileio_open_flags
& ~FILEIO_O_SUPPORTED
)
242 if (fileio_open_flags
& FILEIO_O_CREAT
)
243 open_flags
|= O_CREAT
;
244 if (fileio_open_flags
& FILEIO_O_EXCL
)
245 open_flags
|= O_EXCL
;
246 if (fileio_open_flags
& FILEIO_O_TRUNC
)
247 open_flags
|= O_TRUNC
;
248 if (fileio_open_flags
& FILEIO_O_APPEND
)
249 open_flags
|= O_APPEND
;
250 if (fileio_open_flags
& FILEIO_O_RDONLY
)
251 open_flags
|= O_RDONLY
;
252 if (fileio_open_flags
& FILEIO_O_WRONLY
)
253 open_flags
|= O_WRONLY
;
254 if (fileio_open_flags
& FILEIO_O_RDWR
)
255 open_flags
|= O_RDWR
;
256 /* On systems supporting binary and text mode, always open files in
259 open_flags
|= O_BINARY
;
262 *open_flags_p
= open_flags
;
267 handle_open (char *own_buf
)
269 char filename
[PATH_MAX
];
271 int fileio_flags
, mode
, flags
, fd
;
272 struct fd_list
*new_fd
;
274 p
= own_buf
+ strlen ("vFile:open:");
276 if (require_filename (&p
, filename
)
277 || require_comma (&p
)
278 || require_int (&p
, &fileio_flags
)
279 || require_comma (&p
)
280 || require_int (&p
, &mode
)
282 || fileio_open_flags_to_host (fileio_flags
, &flags
))
284 hostio_packet_error (own_buf
);
288 /* We do not need to convert MODE, since the fileio protocol
289 uses the standard values. */
290 fd
= open (filename
, flags
, mode
);
294 hostio_error (own_buf
);
298 /* Record the new file descriptor. */
299 new_fd
= xmalloc (sizeof (struct fd_list
));
301 new_fd
->next
= open_fds
;
304 hostio_reply (own_buf
, fd
);
308 handle_pread (char *own_buf
, int *new_packet_len
)
310 int fd
, ret
, len
, offset
, bytes_sent
;
313 p
= own_buf
+ strlen ("vFile:pread:");
315 if (require_int (&p
, &fd
)
316 || require_comma (&p
)
317 || require_valid_fd (fd
)
318 || require_int (&p
, &len
)
319 || require_comma (&p
)
320 || require_int (&p
, &offset
)
323 hostio_packet_error (own_buf
);
327 data
= xmalloc (len
);
329 ret
= pread (fd
, data
, len
, offset
);
331 ret
= lseek (fd
, offset
, SEEK_SET
);
333 ret
= read (fd
, data
, len
);
338 hostio_error (own_buf
);
343 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
345 /* If we were using read, and the data did not all fit in the reply,
346 we would have to back up using lseek here. With pread it does
347 not matter. But we still have a problem; the return value in the
348 packet might be wrong, so we must fix it. This time it will
350 if (bytes_sent
< ret
)
351 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
358 handle_pwrite (char *own_buf
, int packet_len
)
360 int fd
, ret
, len
, offset
;
363 p
= own_buf
+ strlen ("vFile:pwrite:");
365 if (require_int (&p
, &fd
)
366 || require_comma (&p
)
367 || require_valid_fd (fd
)
368 || require_int (&p
, &offset
)
369 || require_comma (&p
)
370 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
372 hostio_packet_error (own_buf
);
377 ret
= pwrite (fd
, data
, len
, offset
);
379 ret
= lseek (fd
, offset
, SEEK_SET
);
381 ret
= write (fd
, data
, len
);
386 hostio_error (own_buf
);
391 hostio_reply (own_buf
, ret
);
396 handle_close (char *own_buf
)
400 struct fd_list
**open_fd_p
, *old_fd
;
402 p
= own_buf
+ strlen ("vFile:close:");
404 if (require_int (&p
, &fd
)
405 || require_valid_fd (fd
)
408 hostio_packet_error (own_buf
);
416 hostio_error (own_buf
);
420 open_fd_p
= &open_fds
;
421 /* We know that fd is in the list, thanks to require_valid_fd. */
422 while ((*open_fd_p
)->fd
!= fd
)
423 open_fd_p
= &(*open_fd_p
)->next
;
426 *open_fd_p
= (*open_fd_p
)->next
;
429 hostio_reply (own_buf
, ret
);
433 handle_unlink (char *own_buf
)
435 char filename
[PATH_MAX
];
439 p
= own_buf
+ strlen ("vFile:unlink:");
441 if (require_filename (&p
, filename
)
444 hostio_packet_error (own_buf
);
448 ret
= unlink (filename
);
452 hostio_error (own_buf
);
456 hostio_reply (own_buf
, ret
);
459 /* Handle all the 'F' file transfer packets. */
462 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
464 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
465 handle_open (own_buf
);
466 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
467 handle_pread (own_buf
, new_packet_len
);
468 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
469 handle_pwrite (own_buf
, packet_len
);
470 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
471 handle_close (own_buf
);
472 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
473 handle_unlink (own_buf
);
This page took 0.052902 seconds and 4 git commands to generate.