1 /* Host file transfer support for gdbserver.
3 Free Software Foundation, Inc.
5 Contributed by CodeSourcery.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
25 #include "gdb/fileio.h"
32 extern int remote_debug
;
40 static struct fd_list
*open_fds
;
43 safe_fromhex (char a
, int *nibble
)
45 if (a
>= '0' && a
<= '9')
47 else if (a
>= 'a' && a
<= 'f')
48 *nibble
= a
- 'a' + 10;
49 else if (a
>= 'A' && a
<= 'F')
50 *nibble
= a
- 'A' + 10;
58 require_filename (char **pp
, char *filename
)
66 while (*p
&& *p
!= ',')
70 /* Don't allow overflow. */
71 if (count
>= PATH_MAX
- 1)
74 if (safe_fromhex (p
[0], &nib1
)
75 || safe_fromhex (p
[1], &nib2
))
78 filename
[count
++] = nib1
* 16 + nib2
;
82 filename
[count
] = '\0';
88 require_int (char **pp
, int *value
)
97 while (*p
&& *p
!= ',')
101 /* Don't allow overflow. */
105 if (safe_fromhex (p
[0], &nib
))
107 *value
= *value
* 16 + nib
;
117 require_data (char *p
, int p_len
, char **data
, int *data_len
)
119 int input_index
, output_index
, escaped
;
121 *data
= malloc (p_len
);
125 for (input_index
= 0; input_index
< p_len
; input_index
++)
127 char b
= p
[input_index
];
131 (*data
)[output_index
++] = b
^ 0x20;
137 (*data
)[output_index
++] = b
;
143 *data_len
= output_index
;
148 require_comma (char **pp
)
160 require_end (char *p
)
169 require_valid_fd (int fd
)
171 struct fd_list
*fd_ptr
;
173 for (fd_ptr
= open_fds
; fd_ptr
!= NULL
; fd_ptr
= fd_ptr
->next
)
174 if (fd_ptr
->fd
== fd
)
181 errno_to_fileio_errno (int error
)
188 return FILEIO_ENOENT
;
196 return FILEIO_EACCES
;
198 return FILEIO_EFAULT
;
202 return FILEIO_EEXIST
;
204 return FILEIO_ENODEV
;
206 return FILEIO_ENOTDIR
;
208 return FILEIO_EISDIR
;
210 return FILEIO_EINVAL
;
212 return FILEIO_ENFILE
;
214 return FILEIO_EMFILE
;
218 return FILEIO_ENOSPC
;
220 return FILEIO_ESPIPE
;
224 return FILEIO_ENOSYS
;
226 return FILEIO_ENAMETOOLONG
;
228 return FILEIO_EUNKNOWN
;
232 hostio_error (char *own_buf
, int error
)
234 int fileio_error
= errno_to_fileio_errno (error
);
236 sprintf (own_buf
, "F-1,%x", fileio_error
);
240 hostio_packet_error (char *own_buf
)
242 hostio_error (own_buf
, EINVAL
);
246 hostio_reply (char *own_buf
, int result
)
248 sprintf (own_buf
, "F%x", result
);
252 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
255 int input_index
, output_index
, out_maxlen
;
257 sprintf (own_buf
, "F%x;", len
);
258 output_index
= strlen (own_buf
);
260 out_maxlen
= PBUFSIZ
;
262 for (input_index
= 0; input_index
< len
; input_index
++)
264 char b
= buffer
[input_index
];
266 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
268 /* These must be escaped. */
269 if (output_index
+ 2 > out_maxlen
)
271 own_buf
[output_index
++] = '}';
272 own_buf
[output_index
++] = b
^ 0x20;
276 if (output_index
+ 1 > out_maxlen
)
278 own_buf
[output_index
++] = b
;
282 *new_packet_len
= output_index
;
287 fileio_open_flags_to_host (int fileio_open_flags
, int *open_flags_p
)
291 if (fileio_open_flags
& ~FILEIO_O_SUPPORTED
)
294 if (fileio_open_flags
& FILEIO_O_CREAT
)
295 open_flags
|= O_CREAT
;
296 if (fileio_open_flags
& FILEIO_O_EXCL
)
297 open_flags
|= O_EXCL
;
298 if (fileio_open_flags
& FILEIO_O_TRUNC
)
299 open_flags
|= O_TRUNC
;
300 if (fileio_open_flags
& FILEIO_O_APPEND
)
301 open_flags
|= O_APPEND
;
302 if (fileio_open_flags
& FILEIO_O_RDONLY
)
303 open_flags
|= O_RDONLY
;
304 if (fileio_open_flags
& FILEIO_O_WRONLY
)
305 open_flags
|= O_WRONLY
;
306 if (fileio_open_flags
& FILEIO_O_RDWR
)
307 open_flags
|= O_RDWR
;
308 /* On systems supporting binary and text mode, always open files in
311 open_flags
|= O_BINARY
;
314 *open_flags_p
= open_flags
;
319 handle_open (char *own_buf
)
321 char filename
[PATH_MAX
];
323 int fileio_flags
, mode
, flags
, fd
;
324 struct fd_list
*new_fd
;
326 p
= own_buf
+ strlen ("vFile:open:");
328 if (require_filename (&p
, filename
)
329 || require_comma (&p
)
330 || require_int (&p
, &fileio_flags
)
331 || require_comma (&p
)
332 || require_int (&p
, &mode
)
334 || fileio_open_flags_to_host (fileio_flags
, &flags
))
336 hostio_packet_error (own_buf
);
340 /* We do not need to convert MODE, since the fileio protocol
341 uses the standard values. */
342 fd
= open (filename
, flags
, mode
);
346 hostio_error (own_buf
, errno
);
350 /* Record the new file descriptor. */
351 new_fd
= malloc (sizeof (struct fd_list
));
353 new_fd
->next
= open_fds
;
356 hostio_reply (own_buf
, fd
);
360 handle_pread (char *own_buf
, int *new_packet_len
)
362 int fd
, ret
, len
, offset
, bytes_sent
;
365 p
= own_buf
+ strlen ("vFile:pread:");
367 if (require_int (&p
, &fd
)
368 || require_comma (&p
)
369 || require_valid_fd (fd
)
370 || require_int (&p
, &len
)
371 || require_comma (&p
)
372 || require_int (&p
, &offset
)
375 hostio_packet_error (own_buf
);
380 ret
= pread (fd
, data
, len
, offset
);
384 hostio_error (own_buf
, errno
);
389 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
391 /* If we were using read, and the data did not all fit in the reply,
392 we would have to back up using lseek here. With pread it does
393 not matter. But we still have a problem; the return value in the
394 packet might be wrong, so we must fix it. This time it will
396 if (bytes_sent
< ret
)
397 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
404 handle_pwrite (char *own_buf
, int packet_len
)
406 int fd
, ret
, len
, offset
;
409 p
= own_buf
+ strlen ("vFile:pwrite:");
411 if (require_int (&p
, &fd
)
412 || require_comma (&p
)
413 || require_valid_fd (fd
)
414 || require_int (&p
, &offset
)
415 || require_comma (&p
)
416 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
418 hostio_packet_error (own_buf
);
422 ret
= pwrite (fd
, data
, len
, offset
);
426 hostio_error (own_buf
, errno
);
431 hostio_reply (own_buf
, ret
);
436 handle_close (char *own_buf
)
440 struct fd_list
**open_fd_p
, *old_fd
;
442 p
= own_buf
+ strlen ("vFile:close:");
444 if (require_int (&p
, &fd
)
445 || require_valid_fd (fd
)
448 hostio_packet_error (own_buf
);
456 hostio_error (own_buf
, errno
);
460 open_fd_p
= &open_fds
;
461 while (*open_fd_p
&& (*open_fd_p
)->fd
!= fd
)
462 open_fd_p
= &(*open_fd_p
)->next
;
465 *open_fd_p
= (*open_fd_p
)->next
;
468 hostio_reply (own_buf
, ret
);
472 handle_unlink (char *own_buf
)
474 char filename
[PATH_MAX
];
478 p
= own_buf
+ strlen ("vFile:unlink:");
480 if (require_filename (&p
, filename
)
483 hostio_packet_error (own_buf
);
487 ret
= unlink (filename
);
491 hostio_error (own_buf
, errno
);
495 hostio_reply (own_buf
, ret
);
498 /* Handle all the 'F' file transfer packets. */
501 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
503 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
504 handle_open (own_buf
);
505 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
506 handle_pread (own_buf
, new_packet_len
);
507 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
508 handle_pwrite (own_buf
, packet_len
);
509 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
510 handle_close (own_buf
);
511 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
512 handle_unlink (own_buf
);