1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007-2023 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 "gdbsupport/fileio.h"
28 #include <sys/types.h>
30 #include "gdbsupport/fileio.h"
38 static struct fd_list
*open_fds
;
41 safe_fromhex (char a
, int *nibble
)
43 if (a
>= '0' && a
<= '9')
45 else if (a
>= 'a' && a
<= 'f')
46 *nibble
= a
- 'a' + 10;
47 else if (a
>= 'A' && a
<= 'F')
48 *nibble
= a
- 'A' + 10;
55 /* Filenames are hex encoded, so the maximum we can handle is half the
56 packet buffer size. Cap to PATH_MAX, if it is shorter. */
57 #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1))
58 # define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1)
60 # define HOSTIO_PATH_MAX PATH_MAX
64 require_filename (char **pp
, char *filename
)
72 while (*p
&& *p
!= ',')
76 /* Don't allow overflow. */
77 if (count
>= HOSTIO_PATH_MAX
- 1)
80 if (safe_fromhex (p
[0], &nib1
)
81 || safe_fromhex (p
[1], &nib2
))
84 filename
[count
++] = nib1
* 16 + nib2
;
88 filename
[count
] = '\0';
94 require_int (char **pp
, int *value
)
97 int count
, firstdigit
;
104 while (*p
&& *p
!= ',')
108 if (safe_fromhex (p
[0], &nib
))
111 if (firstdigit
== -1)
114 /* Don't allow overflow. */
115 if (count
>= 8 || (count
== 7 && firstdigit
>= 0x8))
118 *value
= *value
* 16 + nib
;
128 require_data (char *p
, int p_len
, char **data
, int *data_len
)
130 int input_index
, output_index
, escaped
;
132 *data
= (char *) xmalloc (p_len
);
136 for (input_index
= 0; input_index
< p_len
; input_index
++)
138 char b
= p
[input_index
];
142 (*data
)[output_index
++] = b
^ 0x20;
148 (*data
)[output_index
++] = b
;
157 *data_len
= output_index
;
162 require_comma (char **pp
)
174 require_end (char *p
)
183 require_valid_fd (int fd
)
185 struct fd_list
*fd_ptr
;
187 for (fd_ptr
= open_fds
; fd_ptr
!= NULL
; fd_ptr
= fd_ptr
->next
)
188 if (fd_ptr
->fd
== fd
)
194 /* Fill BUF with an hostio error packet representing the last hostio
195 error, from errno. */
198 hostio_error (char *own_buf
)
200 int fileio_error
= host_to_fileio_error (errno
);
201 sprintf (own_buf
, "F-1,%x", fileio_error
);
205 hostio_packet_error (char *own_buf
)
207 sprintf (own_buf
, "F-1,%x", FILEIO_EINVAL
);
211 hostio_reply (char *own_buf
, int result
)
213 sprintf (own_buf
, "F%x", result
);
217 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
220 int input_index
, output_index
, out_maxlen
;
222 sprintf (own_buf
, "F%x;", len
);
223 output_index
= strlen (own_buf
);
225 out_maxlen
= PBUFSIZ
;
227 for (input_index
= 0; input_index
< len
; input_index
++)
229 char b
= buffer
[input_index
];
231 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
233 /* These must be escaped. */
234 if (output_index
+ 2 > out_maxlen
)
236 own_buf
[output_index
++] = '}';
237 own_buf
[output_index
++] = b
^ 0x20;
241 if (output_index
+ 1 > out_maxlen
)
243 own_buf
[output_index
++] = b
;
247 *new_packet_len
= output_index
;
251 /* Process ID of inferior whose filesystem hostio functions
252 that take FILENAME arguments will use. Zero means to use
253 our own filesystem. */
255 static int hostio_fs_pid
;
260 hostio_handle_new_gdb_connection (void)
265 /* Handle a "vFile:setfs:" packet. */
268 handle_setfs (char *own_buf
)
273 /* If the target doesn't have any of the in-filesystem-of methods
274 then there's no point in GDB sending "vFile:setfs:" packets. We
275 reply with an empty packet (i.e. we pretend we don't understand
276 "vFile:setfs:") and that should stop GDB sending any more. */
277 if (!the_target
->supports_multifs ())
283 p
= own_buf
+ strlen ("vFile:setfs:");
285 if (require_int (&p
, &pid
)
289 hostio_packet_error (own_buf
);
295 hostio_reply (own_buf
, 0);
299 handle_open (char *own_buf
)
301 char filename
[HOSTIO_PATH_MAX
];
303 int fileio_flags
, fileio_mode
, flags
, fd
;
305 struct fd_list
*new_fd
;
307 p
= own_buf
+ strlen ("vFile:open:");
309 if (require_filename (&p
, filename
)
310 || require_comma (&p
)
311 || require_int (&p
, &fileio_flags
)
312 || require_comma (&p
)
313 || require_int (&p
, &fileio_mode
)
315 || fileio_to_host_openflags (fileio_flags
, &flags
)
316 || fileio_to_host_mode (fileio_mode
, &mode
))
318 hostio_packet_error (own_buf
);
322 /* We do not need to convert MODE, since the fileio protocol
323 uses the standard values. */
324 if (hostio_fs_pid
!= 0)
325 fd
= the_target
->multifs_open (hostio_fs_pid
, filename
, flags
, mode
);
327 fd
= open (filename
, flags
, mode
);
331 hostio_error (own_buf
);
335 /* Record the new file descriptor. */
336 new_fd
= XNEW (struct fd_list
);
338 new_fd
->next
= open_fds
;
341 hostio_reply (own_buf
, fd
);
345 handle_pread (char *own_buf
, int *new_packet_len
)
347 int fd
, ret
, len
, offset
, bytes_sent
;
349 static int max_reply_size
= -1;
351 p
= own_buf
+ strlen ("vFile:pread:");
353 if (require_int (&p
, &fd
)
354 || require_comma (&p
)
355 || require_valid_fd (fd
)
356 || require_int (&p
, &len
)
357 || require_comma (&p
)
358 || require_int (&p
, &offset
)
361 hostio_packet_error (own_buf
);
365 /* Do not attempt to read more than the maximum number of bytes
366 hostio_reply_with_data can fit in a packet. We may still read
367 too much because of escaping, but this is handled below. */
368 if (max_reply_size
== -1)
370 sprintf (own_buf
, "F%x;", PBUFSIZ
);
371 max_reply_size
= PBUFSIZ
- strlen (own_buf
);
373 if (len
> max_reply_size
)
374 len
= max_reply_size
;
376 data
= (char *) xmalloc (len
);
378 ret
= pread (fd
, data
, len
, offset
);
382 /* If we have no pread or it failed for this file, use lseek/read. */
385 ret
= lseek (fd
, offset
, SEEK_SET
);
387 ret
= read (fd
, data
, len
);
392 hostio_error (own_buf
);
397 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
399 /* If we were using read, and the data did not all fit in the reply,
400 we would have to back up using lseek here. With pread it does
401 not matter. But we still have a problem; the return value in the
402 packet might be wrong, so we must fix it. This time it will
404 if (bytes_sent
< ret
)
405 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
412 handle_pwrite (char *own_buf
, int packet_len
)
414 int fd
, ret
, len
, offset
;
417 p
= own_buf
+ strlen ("vFile:pwrite:");
419 if (require_int (&p
, &fd
)
420 || require_comma (&p
)
421 || require_valid_fd (fd
)
422 || require_int (&p
, &offset
)
423 || require_comma (&p
)
424 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
426 hostio_packet_error (own_buf
);
431 ret
= pwrite (fd
, data
, len
, offset
);
435 /* If we have no pwrite or it failed for this file, use lseek/write. */
438 ret
= lseek (fd
, offset
, SEEK_SET
);
440 ret
= write (fd
, data
, len
);
445 hostio_error (own_buf
);
450 hostio_reply (own_buf
, ret
);
455 handle_fstat (char *own_buf
, int *new_packet_len
)
462 p
= own_buf
+ strlen ("vFile:fstat:");
464 if (require_int (&p
, &fd
)
465 || require_valid_fd (fd
)
468 hostio_packet_error (own_buf
);
472 if (fstat (fd
, &st
) == -1)
474 hostio_error (own_buf
);
478 host_to_fileio_stat (&st
, &fst
);
480 bytes_sent
= hostio_reply_with_data (own_buf
,
481 (char *) &fst
, sizeof (fst
),
484 /* If the response does not fit into a single packet, do not attempt
485 to return a partial response, but simply fail. */
486 if (bytes_sent
< sizeof (fst
))
491 handle_close (char *own_buf
)
495 struct fd_list
**open_fd_p
, *old_fd
;
497 p
= own_buf
+ strlen ("vFile:close:");
499 if (require_int (&p
, &fd
)
500 || require_valid_fd (fd
)
503 hostio_packet_error (own_buf
);
511 hostio_error (own_buf
);
515 open_fd_p
= &open_fds
;
516 /* We know that fd is in the list, thanks to require_valid_fd. */
517 while ((*open_fd_p
)->fd
!= fd
)
518 open_fd_p
= &(*open_fd_p
)->next
;
521 *open_fd_p
= (*open_fd_p
)->next
;
524 hostio_reply (own_buf
, ret
);
528 handle_unlink (char *own_buf
)
530 char filename
[HOSTIO_PATH_MAX
];
534 p
= own_buf
+ strlen ("vFile:unlink:");
536 if (require_filename (&p
, filename
)
539 hostio_packet_error (own_buf
);
543 if (hostio_fs_pid
!= 0)
544 ret
= the_target
->multifs_unlink (hostio_fs_pid
, filename
);
546 ret
= unlink (filename
);
550 hostio_error (own_buf
);
554 hostio_reply (own_buf
, ret
);
558 handle_readlink (char *own_buf
, int *new_packet_len
)
560 char filename
[HOSTIO_PATH_MAX
], linkname
[HOSTIO_PATH_MAX
];
564 p
= own_buf
+ strlen ("vFile:readlink:");
566 if (require_filename (&p
, filename
)
569 hostio_packet_error (own_buf
);
573 if (hostio_fs_pid
!= 0)
574 ret
= the_target
->multifs_readlink (hostio_fs_pid
, filename
,
576 sizeof (linkname
) - 1);
578 ret
= readlink (filename
, linkname
, sizeof (linkname
) - 1);
582 hostio_error (own_buf
);
586 bytes_sent
= hostio_reply_with_data (own_buf
, linkname
, ret
, new_packet_len
);
588 /* If the response does not fit into a single packet, do not attempt
589 to return a partial response, but simply fail. */
590 if (bytes_sent
< ret
)
591 sprintf (own_buf
, "F-1,%x", FILEIO_ENAMETOOLONG
);
594 /* Handle all the 'F' file transfer packets. */
597 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
599 if (startswith (own_buf
, "vFile:open:"))
600 handle_open (own_buf
);
601 else if (startswith (own_buf
, "vFile:pread:"))
602 handle_pread (own_buf
, new_packet_len
);
603 else if (startswith (own_buf
, "vFile:pwrite:"))
604 handle_pwrite (own_buf
, packet_len
);
605 else if (startswith (own_buf
, "vFile:fstat:"))
606 handle_fstat (own_buf
, new_packet_len
);
607 else if (startswith (own_buf
, "vFile:close:"))
608 handle_close (own_buf
);
609 else if (startswith (own_buf
, "vFile:unlink:"))
610 handle_unlink (own_buf
);
611 else if (startswith (own_buf
, "vFile:readlink:"))
612 handle_readlink (own_buf
, new_packet_len
);
613 else if (startswith (own_buf
, "vFile:setfs:"))
614 handle_setfs (own_buf
);