1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007, 2008, 2009 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"
28 extern int remote_debug
;
36 static struct fd_list
*open_fds
;
39 safe_fromhex (char a
, int *nibble
)
41 if (a
>= '0' && a
<= '9')
43 else if (a
>= 'a' && a
<= 'f')
44 *nibble
= a
- 'a' + 10;
45 else if (a
>= 'A' && a
<= 'F')
46 *nibble
= a
- 'A' + 10;
54 require_filename (char **pp
, char *filename
)
62 while (*p
&& *p
!= ',')
66 /* Don't allow overflow. */
67 if (count
>= PATH_MAX
- 1)
70 if (safe_fromhex (p
[0], &nib1
)
71 || safe_fromhex (p
[1], &nib2
))
74 filename
[count
++] = nib1
* 16 + nib2
;
78 filename
[count
] = '\0';
84 require_int (char **pp
, int *value
)
93 while (*p
&& *p
!= ',')
97 /* Don't allow overflow. */
101 if (safe_fromhex (p
[0], &nib
))
103 *value
= *value
* 16 + nib
;
113 require_data (char *p
, int p_len
, char **data
, int *data_len
)
115 int input_index
, output_index
, escaped
;
117 *data
= xmalloc (p_len
);
121 for (input_index
= 0; input_index
< p_len
; input_index
++)
123 char b
= p
[input_index
];
127 (*data
)[output_index
++] = b
^ 0x20;
133 (*data
)[output_index
++] = b
;
139 *data_len
= output_index
;
144 require_comma (char **pp
)
156 require_end (char *p
)
165 require_valid_fd (int fd
)
167 struct fd_list
*fd_ptr
;
169 for (fd_ptr
= open_fds
; fd_ptr
!= NULL
; fd_ptr
= fd_ptr
->next
)
170 if (fd_ptr
->fd
== fd
)
176 /* Fill in own_buf with the last hostio error packet, however it
177 suitable for the target. */
179 hostio_error (char *own_buf
)
181 the_target
->hostio_last_error (own_buf
);
185 hostio_packet_error (char *own_buf
)
187 sprintf (own_buf
, "F-1,%x", FILEIO_EINVAL
);
191 hostio_reply (char *own_buf
, int result
)
193 sprintf (own_buf
, "F%x", result
);
197 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
200 int input_index
, output_index
, out_maxlen
;
202 sprintf (own_buf
, "F%x;", len
);
203 output_index
= strlen (own_buf
);
205 out_maxlen
= PBUFSIZ
;
207 for (input_index
= 0; input_index
< len
; input_index
++)
209 char b
= buffer
[input_index
];
211 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
213 /* These must be escaped. */
214 if (output_index
+ 2 > out_maxlen
)
216 own_buf
[output_index
++] = '}';
217 own_buf
[output_index
++] = b
^ 0x20;
221 if (output_index
+ 1 > out_maxlen
)
223 own_buf
[output_index
++] = b
;
227 *new_packet_len
= output_index
;
232 fileio_open_flags_to_host (int fileio_open_flags
, int *open_flags_p
)
236 if (fileio_open_flags
& ~FILEIO_O_SUPPORTED
)
239 if (fileio_open_flags
& FILEIO_O_CREAT
)
240 open_flags
|= O_CREAT
;
241 if (fileio_open_flags
& FILEIO_O_EXCL
)
242 open_flags
|= O_EXCL
;
243 if (fileio_open_flags
& FILEIO_O_TRUNC
)
244 open_flags
|= O_TRUNC
;
245 if (fileio_open_flags
& FILEIO_O_APPEND
)
246 open_flags
|= O_APPEND
;
247 if (fileio_open_flags
& FILEIO_O_RDONLY
)
248 open_flags
|= O_RDONLY
;
249 if (fileio_open_flags
& FILEIO_O_WRONLY
)
250 open_flags
|= O_WRONLY
;
251 if (fileio_open_flags
& FILEIO_O_RDWR
)
252 open_flags
|= O_RDWR
;
253 /* On systems supporting binary and text mode, always open files in
256 open_flags
|= O_BINARY
;
259 *open_flags_p
= open_flags
;
264 handle_open (char *own_buf
)
266 char filename
[PATH_MAX
];
268 int fileio_flags
, mode
, flags
, fd
;
269 struct fd_list
*new_fd
;
271 p
= own_buf
+ strlen ("vFile:open:");
273 if (require_filename (&p
, filename
)
274 || require_comma (&p
)
275 || require_int (&p
, &fileio_flags
)
276 || require_comma (&p
)
277 || require_int (&p
, &mode
)
279 || fileio_open_flags_to_host (fileio_flags
, &flags
))
281 hostio_packet_error (own_buf
);
285 /* We do not need to convert MODE, since the fileio protocol
286 uses the standard values. */
287 fd
= open (filename
, flags
, mode
);
291 hostio_error (own_buf
);
295 /* Record the new file descriptor. */
296 new_fd
= xmalloc (sizeof (struct fd_list
));
298 new_fd
->next
= open_fds
;
301 hostio_reply (own_buf
, fd
);
305 handle_pread (char *own_buf
, int *new_packet_len
)
307 int fd
, ret
, len
, offset
, bytes_sent
;
310 p
= own_buf
+ strlen ("vFile:pread:");
312 if (require_int (&p
, &fd
)
313 || require_comma (&p
)
314 || require_valid_fd (fd
)
315 || require_int (&p
, &len
)
316 || require_comma (&p
)
317 || require_int (&p
, &offset
)
320 hostio_packet_error (own_buf
);
324 data
= xmalloc (len
);
326 ret
= pread (fd
, data
, len
, offset
);
328 ret
= lseek (fd
, offset
, SEEK_SET
);
330 ret
= read (fd
, data
, len
);
335 hostio_error (own_buf
);
340 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
342 /* If we were using read, and the data did not all fit in the reply,
343 we would have to back up using lseek here. With pread it does
344 not matter. But we still have a problem; the return value in the
345 packet might be wrong, so we must fix it. This time it will
347 if (bytes_sent
< ret
)
348 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
355 handle_pwrite (char *own_buf
, int packet_len
)
357 int fd
, ret
, len
, offset
;
360 p
= own_buf
+ strlen ("vFile:pwrite:");
362 if (require_int (&p
, &fd
)
363 || require_comma (&p
)
364 || require_valid_fd (fd
)
365 || require_int (&p
, &offset
)
366 || require_comma (&p
)
367 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
369 hostio_packet_error (own_buf
);
374 ret
= pwrite (fd
, data
, len
, offset
);
376 ret
= lseek (fd
, offset
, SEEK_SET
);
378 ret
= write (fd
, data
, len
);
383 hostio_error (own_buf
);
388 hostio_reply (own_buf
, ret
);
393 handle_close (char *own_buf
)
397 struct fd_list
**open_fd_p
, *old_fd
;
399 p
= own_buf
+ strlen ("vFile:close:");
401 if (require_int (&p
, &fd
)
402 || require_valid_fd (fd
)
405 hostio_packet_error (own_buf
);
413 hostio_error (own_buf
);
417 open_fd_p
= &open_fds
;
418 while (*open_fd_p
&& (*open_fd_p
)->fd
!= fd
)
419 open_fd_p
= &(*open_fd_p
)->next
;
422 *open_fd_p
= (*open_fd_p
)->next
;
425 hostio_reply (own_buf
, ret
);
429 handle_unlink (char *own_buf
)
431 char filename
[PATH_MAX
];
435 p
= own_buf
+ strlen ("vFile:unlink:");
437 if (require_filename (&p
, filename
)
440 hostio_packet_error (own_buf
);
444 ret
= unlink (filename
);
448 hostio_error (own_buf
);
452 hostio_reply (own_buf
, ret
);
455 /* Handle all the 'F' file transfer packets. */
458 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
460 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
461 handle_open (own_buf
);
462 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
463 handle_pread (own_buf
, new_packet_len
);
464 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
465 handle_pwrite (own_buf
, packet_len
);
466 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
467 handle_close (own_buf
);
468 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
469 handle_unlink (own_buf
);