1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007, 2008 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 2 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, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
24 #include "gdb/fileio.h"
31 extern int remote_debug
;
39 static struct fd_list
*open_fds
;
42 safe_fromhex (char a
, int *nibble
)
44 if (a
>= '0' && a
<= '9')
46 else if (a
>= 'a' && a
<= 'f')
47 *nibble
= a
- 'a' + 10;
48 else if (a
>= 'A' && a
<= 'F')
49 *nibble
= a
- 'A' + 10;
57 require_filename (char **pp
, char *filename
)
65 while (*p
&& *p
!= ',')
69 /* Don't allow overflow. */
70 if (count
>= PATH_MAX
- 1)
73 if (safe_fromhex (p
[0], &nib1
)
74 || safe_fromhex (p
[1], &nib2
))
77 filename
[count
++] = nib1
* 16 + nib2
;
81 filename
[count
] = '\0';
87 require_int (char **pp
, int *value
)
96 while (*p
&& *p
!= ',')
100 /* Don't allow overflow. */
104 if (safe_fromhex (p
[0], &nib
))
106 *value
= *value
* 16 + nib
;
116 require_data (char *p
, int p_len
, char **data
, int *data_len
)
118 int input_index
, output_index
, escaped
;
120 *data
= malloc (p_len
);
124 for (input_index
= 0; input_index
< p_len
; input_index
++)
126 char b
= p
[input_index
];
130 (*data
)[output_index
++] = b
^ 0x20;
136 (*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
)
180 errno_to_fileio_errno (int error
)
187 return FILEIO_ENOENT
;
195 return FILEIO_EACCES
;
197 return FILEIO_EFAULT
;
201 return FILEIO_EEXIST
;
203 return FILEIO_ENODEV
;
205 return FILEIO_ENOTDIR
;
207 return FILEIO_EISDIR
;
209 return FILEIO_EINVAL
;
211 return FILEIO_ENFILE
;
213 return FILEIO_EMFILE
;
217 return FILEIO_ENOSPC
;
219 return FILEIO_ESPIPE
;
223 return FILEIO_ENOSYS
;
225 return FILEIO_ENAMETOOLONG
;
227 return FILEIO_EUNKNOWN
;
231 hostio_error (char *own_buf
, int error
)
233 int fileio_error
= errno_to_fileio_errno (error
);
235 sprintf (own_buf
, "F-1,%x", fileio_error
);
239 hostio_packet_error (char *own_buf
)
241 hostio_error (own_buf
, EINVAL
);
245 hostio_reply (char *own_buf
, int result
)
247 sprintf (own_buf
, "F%x", result
);
251 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
254 int input_index
, output_index
, out_maxlen
;
256 sprintf (own_buf
, "F%x;", len
);
257 output_index
= strlen (own_buf
);
259 out_maxlen
= PBUFSIZ
;
261 for (input_index
= 0; input_index
< len
; input_index
++)
263 char b
= buffer
[input_index
];
265 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
267 /* These must be escaped. */
268 if (output_index
+ 2 > out_maxlen
)
270 own_buf
[output_index
++] = '}';
271 own_buf
[output_index
++] = b
^ 0x20;
275 if (output_index
+ 1 > out_maxlen
)
277 own_buf
[output_index
++] = b
;
281 *new_packet_len
= output_index
;
286 fileio_open_flags_to_host (int fileio_open_flags
, int *open_flags_p
)
290 if (fileio_open_flags
& ~FILEIO_O_SUPPORTED
)
293 if (fileio_open_flags
& FILEIO_O_CREAT
)
294 open_flags
|= O_CREAT
;
295 if (fileio_open_flags
& FILEIO_O_EXCL
)
296 open_flags
|= O_EXCL
;
297 if (fileio_open_flags
& FILEIO_O_TRUNC
)
298 open_flags
|= O_TRUNC
;
299 if (fileio_open_flags
& FILEIO_O_APPEND
)
300 open_flags
|= O_APPEND
;
301 if (fileio_open_flags
& FILEIO_O_RDONLY
)
302 open_flags
|= O_RDONLY
;
303 if (fileio_open_flags
& FILEIO_O_WRONLY
)
304 open_flags
|= O_WRONLY
;
305 if (fileio_open_flags
& FILEIO_O_RDWR
)
306 open_flags
|= O_RDWR
;
307 /* On systems supporting binary and text mode, always open files in
310 open_flags
|= O_BINARY
;
313 *open_flags_p
= open_flags
;
318 handle_open (char *own_buf
)
320 char filename
[PATH_MAX
];
322 int fileio_flags
, mode
, flags
, fd
;
323 struct fd_list
*new_fd
;
325 p
= own_buf
+ strlen ("vFile:open:");
327 if (require_filename (&p
, filename
)
328 || require_comma (&p
)
329 || require_int (&p
, &fileio_flags
)
330 || require_comma (&p
)
331 || require_int (&p
, &mode
)
333 || fileio_open_flags_to_host (fileio_flags
, &flags
))
335 hostio_packet_error (own_buf
);
339 /* We do not need to convert MODE, since the fileio protocol
340 uses the standard values. */
341 fd
= open (filename
, flags
, mode
);
345 hostio_error (own_buf
, errno
);
349 /* Record the new file descriptor. */
350 new_fd
= malloc (sizeof (struct fd_list
));
352 new_fd
->next
= open_fds
;
355 hostio_reply (own_buf
, fd
);
359 handle_pread (char *own_buf
, int *new_packet_len
)
361 int fd
, ret
, len
, offset
, bytes_sent
;
364 p
= own_buf
+ strlen ("vFile:pread:");
366 if (require_int (&p
, &fd
)
367 || require_comma (&p
)
368 || require_valid_fd (fd
)
369 || require_int (&p
, &len
)
370 || require_comma (&p
)
371 || require_int (&p
, &offset
)
374 hostio_packet_error (own_buf
);
380 ret
= pread (fd
, data
, len
, offset
);
382 ret
= lseek (fd
, offset
, SEEK_SET
);
384 ret
= read (fd
, data
, len
);
389 hostio_error (own_buf
, errno
);
394 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
396 /* If we were using read, and the data did not all fit in the reply,
397 we would have to back up using lseek here. With pread it does
398 not matter. But we still have a problem; the return value in the
399 packet might be wrong, so we must fix it. This time it will
401 if (bytes_sent
< ret
)
402 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
409 handle_pwrite (char *own_buf
, int packet_len
)
411 int fd
, ret
, len
, offset
;
414 p
= own_buf
+ strlen ("vFile:pwrite:");
416 if (require_int (&p
, &fd
)
417 || require_comma (&p
)
418 || require_valid_fd (fd
)
419 || require_int (&p
, &offset
)
420 || require_comma (&p
)
421 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
423 hostio_packet_error (own_buf
);
428 ret
= pwrite (fd
, data
, len
, offset
);
430 ret
= lseek (fd
, offset
, SEEK_SET
);
432 ret
= write (fd
, data
, len
);
437 hostio_error (own_buf
, errno
);
442 hostio_reply (own_buf
, ret
);
447 handle_close (char *own_buf
)
451 struct fd_list
**open_fd_p
, *old_fd
;
453 p
= own_buf
+ strlen ("vFile:close:");
455 if (require_int (&p
, &fd
)
456 || require_valid_fd (fd
)
459 hostio_packet_error (own_buf
);
467 hostio_error (own_buf
, errno
);
471 open_fd_p
= &open_fds
;
472 while (*open_fd_p
&& (*open_fd_p
)->fd
!= fd
)
473 open_fd_p
= &(*open_fd_p
)->next
;
476 *open_fd_p
= (*open_fd_p
)->next
;
479 hostio_reply (own_buf
, ret
);
483 handle_unlink (char *own_buf
)
485 char filename
[PATH_MAX
];
489 p
= own_buf
+ strlen ("vFile:unlink:");
491 if (require_filename (&p
, filename
)
494 hostio_packet_error (own_buf
);
498 ret
= unlink (filename
);
502 hostio_error (own_buf
, errno
);
506 hostio_reply (own_buf
, ret
);
509 /* Handle all the 'F' file transfer packets. */
512 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
514 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
515 handle_open (own_buf
);
516 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
517 handle_pread (own_buf
, new_packet_len
);
518 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
519 handle_pwrite (own_buf
, packet_len
);
520 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
521 handle_close (own_buf
);
522 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
523 handle_unlink (own_buf
);