1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007-2014 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"
29 extern int remote_debug
;
37 static struct fd_list
*open_fds
;
40 safe_fromhex (char a
, int *nibble
)
42 if (a
>= '0' && a
<= '9')
44 else if (a
>= 'a' && a
<= 'f')
45 *nibble
= a
- 'a' + 10;
46 else if (a
>= 'A' && a
<= 'F')
47 *nibble
= a
- 'A' + 10;
54 /* Filenames are hex encoded, so the maximum we can handle is half the
55 packet buffer size. Cap to PATH_MAX, if it is shorter. */
56 #if !defined (PATH_MAX) || (PATH_MAX > (PBUFSIZ / 2 + 1))
57 # define HOSTIO_PATH_MAX (PBUFSIZ / 2 + 1)
59 # define HOSTIO_PATH_MAX PATH_MAX
63 require_filename (char **pp
, char *filename
)
71 while (*p
&& *p
!= ',')
75 /* Don't allow overflow. */
76 if (count
>= HOSTIO_PATH_MAX
- 1)
79 if (safe_fromhex (p
[0], &nib1
)
80 || safe_fromhex (p
[1], &nib2
))
83 filename
[count
++] = nib1
* 16 + nib2
;
87 filename
[count
] = '\0';
93 require_int (char **pp
, int *value
)
102 while (*p
&& *p
!= ',')
106 /* Don't allow overflow. */
110 if (safe_fromhex (p
[0], &nib
))
112 *value
= *value
* 16 + nib
;
122 require_data (char *p
, int p_len
, char **data
, int *data_len
)
124 int input_index
, output_index
, escaped
;
126 *data
= xmalloc (p_len
);
130 for (input_index
= 0; input_index
< p_len
; input_index
++)
132 char b
= p
[input_index
];
136 (*data
)[output_index
++] = b
^ 0x20;
142 (*data
)[output_index
++] = b
;
151 *data_len
= output_index
;
156 require_comma (char **pp
)
168 require_end (char *p
)
177 require_valid_fd (int fd
)
179 struct fd_list
*fd_ptr
;
181 for (fd_ptr
= open_fds
; fd_ptr
!= NULL
; fd_ptr
= fd_ptr
->next
)
182 if (fd_ptr
->fd
== fd
)
188 /* Fill in own_buf with the last hostio error packet, however it
189 suitable for the target. */
191 hostio_error (char *own_buf
)
193 the_target
->hostio_last_error (own_buf
);
197 hostio_packet_error (char *own_buf
)
199 sprintf (own_buf
, "F-1,%x", FILEIO_EINVAL
);
203 hostio_reply (char *own_buf
, int result
)
205 sprintf (own_buf
, "F%x", result
);
209 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
212 int input_index
, output_index
, out_maxlen
;
214 sprintf (own_buf
, "F%x;", len
);
215 output_index
= strlen (own_buf
);
217 out_maxlen
= PBUFSIZ
;
219 for (input_index
= 0; input_index
< len
; input_index
++)
221 char b
= buffer
[input_index
];
223 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
225 /* These must be escaped. */
226 if (output_index
+ 2 > out_maxlen
)
228 own_buf
[output_index
++] = '}';
229 own_buf
[output_index
++] = b
^ 0x20;
233 if (output_index
+ 1 > out_maxlen
)
235 own_buf
[output_index
++] = b
;
239 *new_packet_len
= output_index
;
244 fileio_open_flags_to_host (int fileio_open_flags
, int *open_flags_p
)
248 if (fileio_open_flags
& ~FILEIO_O_SUPPORTED
)
251 if (fileio_open_flags
& FILEIO_O_CREAT
)
252 open_flags
|= O_CREAT
;
253 if (fileio_open_flags
& FILEIO_O_EXCL
)
254 open_flags
|= O_EXCL
;
255 if (fileio_open_flags
& FILEIO_O_TRUNC
)
256 open_flags
|= O_TRUNC
;
257 if (fileio_open_flags
& FILEIO_O_APPEND
)
258 open_flags
|= O_APPEND
;
259 if (fileio_open_flags
& FILEIO_O_RDONLY
)
260 open_flags
|= O_RDONLY
;
261 if (fileio_open_flags
& FILEIO_O_WRONLY
)
262 open_flags
|= O_WRONLY
;
263 if (fileio_open_flags
& FILEIO_O_RDWR
)
264 open_flags
|= O_RDWR
;
265 /* On systems supporting binary and text mode, always open files in
268 open_flags
|= O_BINARY
;
271 *open_flags_p
= open_flags
;
276 handle_open (char *own_buf
)
278 char filename
[HOSTIO_PATH_MAX
];
280 int fileio_flags
, mode
, flags
, fd
;
281 struct fd_list
*new_fd
;
283 p
= own_buf
+ strlen ("vFile:open:");
285 if (require_filename (&p
, filename
)
286 || require_comma (&p
)
287 || require_int (&p
, &fileio_flags
)
288 || require_comma (&p
)
289 || require_int (&p
, &mode
)
291 || fileio_open_flags_to_host (fileio_flags
, &flags
))
293 hostio_packet_error (own_buf
);
297 /* We do not need to convert MODE, since the fileio protocol
298 uses the standard values. */
299 fd
= open (filename
, flags
, mode
);
303 hostio_error (own_buf
);
307 /* Record the new file descriptor. */
308 new_fd
= xmalloc (sizeof (struct fd_list
));
310 new_fd
->next
= open_fds
;
313 hostio_reply (own_buf
, fd
);
317 handle_pread (char *own_buf
, int *new_packet_len
)
319 int fd
, ret
, len
, offset
, bytes_sent
;
322 p
= own_buf
+ strlen ("vFile:pread:");
324 if (require_int (&p
, &fd
)
325 || require_comma (&p
)
326 || require_valid_fd (fd
)
327 || require_int (&p
, &len
)
328 || require_comma (&p
)
329 || require_int (&p
, &offset
)
332 hostio_packet_error (own_buf
);
336 data
= xmalloc (len
);
338 ret
= pread (fd
, data
, len
, offset
);
342 /* If we have no pread or it failed for this file, use lseek/read. */
345 ret
= lseek (fd
, offset
, SEEK_SET
);
347 ret
= read (fd
, data
, len
);
352 hostio_error (own_buf
);
357 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
359 /* If we were using read, and the data did not all fit in the reply,
360 we would have to back up using lseek here. With pread it does
361 not matter. But we still have a problem; the return value in the
362 packet might be wrong, so we must fix it. This time it will
364 if (bytes_sent
< ret
)
365 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
372 handle_pwrite (char *own_buf
, int packet_len
)
374 int fd
, ret
, len
, offset
;
377 p
= own_buf
+ strlen ("vFile:pwrite:");
379 if (require_int (&p
, &fd
)
380 || require_comma (&p
)
381 || require_valid_fd (fd
)
382 || require_int (&p
, &offset
)
383 || require_comma (&p
)
384 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
386 hostio_packet_error (own_buf
);
391 ret
= pwrite (fd
, data
, len
, offset
);
395 /* If we have no pwrite or it failed for this file, use lseek/write. */
398 ret
= lseek (fd
, offset
, SEEK_SET
);
400 ret
= write (fd
, data
, len
);
405 hostio_error (own_buf
);
410 hostio_reply (own_buf
, ret
);
415 handle_close (char *own_buf
)
419 struct fd_list
**open_fd_p
, *old_fd
;
421 p
= own_buf
+ strlen ("vFile:close:");
423 if (require_int (&p
, &fd
)
424 || require_valid_fd (fd
)
427 hostio_packet_error (own_buf
);
435 hostio_error (own_buf
);
439 open_fd_p
= &open_fds
;
440 /* We know that fd is in the list, thanks to require_valid_fd. */
441 while ((*open_fd_p
)->fd
!= fd
)
442 open_fd_p
= &(*open_fd_p
)->next
;
445 *open_fd_p
= (*open_fd_p
)->next
;
448 hostio_reply (own_buf
, ret
);
452 handle_unlink (char *own_buf
)
454 char filename
[HOSTIO_PATH_MAX
];
458 p
= own_buf
+ strlen ("vFile:unlink:");
460 if (require_filename (&p
, filename
)
463 hostio_packet_error (own_buf
);
467 ret
= unlink (filename
);
471 hostio_error (own_buf
);
475 hostio_reply (own_buf
, ret
);
479 handle_readlink (char *own_buf
, int *new_packet_len
)
481 #if defined (HAVE_READLINK)
482 char filename
[HOSTIO_PATH_MAX
], linkname
[HOSTIO_PATH_MAX
];
486 p
= own_buf
+ strlen ("vFile:readlink:");
488 if (require_filename (&p
, filename
)
491 hostio_packet_error (own_buf
);
495 ret
= readlink (filename
, linkname
, sizeof (linkname
) - 1);
498 hostio_error (own_buf
);
502 bytes_sent
= hostio_reply_with_data (own_buf
, linkname
, ret
, new_packet_len
);
504 /* If the response does not fit into a single packet, do not attempt
505 to return a partial response, but simply fail. */
506 if (bytes_sent
< ret
)
507 sprintf (own_buf
, "F-1,%x", FILEIO_ENAMETOOLONG
);
508 #else /* ! HAVE_READLINK */
509 sprintf (own_buf
, "F-1,%x", FILEIO_ENOSYS
);
513 /* Handle all the 'F' file transfer packets. */
516 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
518 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
519 handle_open (own_buf
);
520 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
521 handle_pread (own_buf
, new_packet_len
);
522 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
523 handle_pwrite (own_buf
, packet_len
);
524 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
525 handle_close (own_buf
);
526 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
527 handle_unlink (own_buf
);
528 else if (strncmp (own_buf
, "vFile:readlink:", 15) == 0)
529 handle_readlink (own_buf
, new_packet_len
);
This page took 0.045019 seconds and 4 git commands to generate.