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
);
381 ret
= pread (fd
, data
, len
, offset
);
383 ret
= lseek (fd
, offset
, SEEK_SET
);
385 ret
= read (fd
, data
, len
);
390 hostio_error (own_buf
, errno
);
395 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
397 /* If we were using read, and the data did not all fit in the reply,
398 we would have to back up using lseek here. With pread it does
399 not matter. But we still have a problem; the return value in the
400 packet might be wrong, so we must fix it. This time it will
402 if (bytes_sent
< ret
)
403 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
410 handle_pwrite (char *own_buf
, int packet_len
)
412 int fd
, ret
, len
, offset
;
415 p
= own_buf
+ strlen ("vFile:pwrite:");
417 if (require_int (&p
, &fd
)
418 || require_comma (&p
)
419 || require_valid_fd (fd
)
420 || require_int (&p
, &offset
)
421 || require_comma (&p
)
422 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
424 hostio_packet_error (own_buf
);
429 ret
= pwrite (fd
, data
, len
, offset
);
431 ret
= lseek (fd
, offset
, SEEK_SET
);
433 ret
= write (fd
, data
, len
);
438 hostio_error (own_buf
, errno
);
443 hostio_reply (own_buf
, ret
);
448 handle_close (char *own_buf
)
452 struct fd_list
**open_fd_p
, *old_fd
;
454 p
= own_buf
+ strlen ("vFile:close:");
456 if (require_int (&p
, &fd
)
457 || require_valid_fd (fd
)
460 hostio_packet_error (own_buf
);
468 hostio_error (own_buf
, errno
);
472 open_fd_p
= &open_fds
;
473 while (*open_fd_p
&& (*open_fd_p
)->fd
!= fd
)
474 open_fd_p
= &(*open_fd_p
)->next
;
477 *open_fd_p
= (*open_fd_p
)->next
;
480 hostio_reply (own_buf
, ret
);
484 handle_unlink (char *own_buf
)
486 char filename
[PATH_MAX
];
490 p
= own_buf
+ strlen ("vFile:unlink:");
492 if (require_filename (&p
, filename
)
495 hostio_packet_error (own_buf
);
499 ret
= unlink (filename
);
503 hostio_error (own_buf
, errno
);
507 hostio_reply (own_buf
, ret
);
510 /* Handle all the 'F' file transfer packets. */
513 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
515 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
516 handle_open (own_buf
);
517 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
518 handle_pread (own_buf
, new_packet_len
);
519 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
520 handle_pwrite (own_buf
, packet_len
);
521 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
522 handle_close (own_buf
);
523 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
524 handle_unlink (own_buf
);