1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007-2013 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
);
333 /* If we have no pread or it failed for this file, use lseek/read. */
336 ret
= lseek (fd
, offset
, SEEK_SET
);
338 ret
= read (fd
, data
, len
);
343 hostio_error (own_buf
);
348 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
350 /* If we were using read, and the data did not all fit in the reply,
351 we would have to back up using lseek here. With pread it does
352 not matter. But we still have a problem; the return value in the
353 packet might be wrong, so we must fix it. This time it will
355 if (bytes_sent
< ret
)
356 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
363 handle_pwrite (char *own_buf
, int packet_len
)
365 int fd
, ret
, len
, offset
;
368 p
= own_buf
+ strlen ("vFile:pwrite:");
370 if (require_int (&p
, &fd
)
371 || require_comma (&p
)
372 || require_valid_fd (fd
)
373 || require_int (&p
, &offset
)
374 || require_comma (&p
)
375 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
377 hostio_packet_error (own_buf
);
382 ret
= pwrite (fd
, data
, len
, offset
);
386 /* If we have no pwrite or it failed for this file, use lseek/write. */
389 ret
= lseek (fd
, offset
, SEEK_SET
);
391 ret
= write (fd
, data
, len
);
396 hostio_error (own_buf
);
401 hostio_reply (own_buf
, ret
);
406 handle_close (char *own_buf
)
410 struct fd_list
**open_fd_p
, *old_fd
;
412 p
= own_buf
+ strlen ("vFile:close:");
414 if (require_int (&p
, &fd
)
415 || require_valid_fd (fd
)
418 hostio_packet_error (own_buf
);
426 hostio_error (own_buf
);
430 open_fd_p
= &open_fds
;
431 /* We know that fd is in the list, thanks to require_valid_fd. */
432 while ((*open_fd_p
)->fd
!= fd
)
433 open_fd_p
= &(*open_fd_p
)->next
;
436 *open_fd_p
= (*open_fd_p
)->next
;
439 hostio_reply (own_buf
, ret
);
443 handle_unlink (char *own_buf
)
445 char filename
[PATH_MAX
];
449 p
= own_buf
+ strlen ("vFile:unlink:");
451 if (require_filename (&p
, filename
)
454 hostio_packet_error (own_buf
);
458 ret
= unlink (filename
);
462 hostio_error (own_buf
);
466 hostio_reply (own_buf
, ret
);
470 handle_readlink (char *own_buf
, int *new_packet_len
)
472 #if defined (HAVE_READLINK)
473 char filename
[PATH_MAX
], linkname
[PATH_MAX
];
477 p
= own_buf
+ strlen ("vFile:readlink:");
479 if (require_filename (&p
, filename
)
482 hostio_packet_error (own_buf
);
486 ret
= readlink (filename
, linkname
, sizeof (linkname
) - 1);
489 hostio_error (own_buf
);
493 bytes_sent
= hostio_reply_with_data (own_buf
, linkname
, ret
, new_packet_len
);
495 /* If the response does not fit into a single packet, do not attempt
496 to return a partial response, but simply fail. */
497 if (bytes_sent
< ret
)
498 sprintf (own_buf
, "F-1,%x", FILEIO_ENAMETOOLONG
);
499 #else /* ! HAVE_READLINK */
500 sprintf (own_buf
, "F-1,%x", FILEIO_ENOSYS
);
504 /* Handle all the 'F' file transfer packets. */
507 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
509 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
510 handle_open (own_buf
);
511 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
512 handle_pread (own_buf
, new_packet_len
);
513 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
514 handle_pwrite (own_buf
, packet_len
);
515 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
516 handle_close (own_buf
);
517 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
518 handle_unlink (own_buf
);
519 else if (strncmp (own_buf
, "vFile:readlink:", 15) == 0)
520 handle_readlink (own_buf
, new_packet_len
);