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"
30 extern int remote_debug
;
38 static struct fd_list
*open_fds
;
41 safe_fromhex (char a
, int *nibble
)
43 if (a
>= '0' && a
<= '9')
45 else if (a
>= 'a' && a
<= 'f')
46 *nibble
= a
- 'a' + 10;
47 else if (a
>= 'A' && a
<= 'F')
48 *nibble
= a
- 'A' + 10;
56 require_filename (char **pp
, char *filename
)
64 while (*p
&& *p
!= ',')
68 /* Don't allow overflow. */
69 if (count
>= PATH_MAX
- 1)
72 if (safe_fromhex (p
[0], &nib1
)
73 || safe_fromhex (p
[1], &nib2
))
76 filename
[count
++] = nib1
* 16 + nib2
;
80 filename
[count
] = '\0';
86 require_int (char **pp
, int *value
)
95 while (*p
&& *p
!= ',')
99 /* Don't allow overflow. */
103 if (safe_fromhex (p
[0], &nib
))
105 *value
= *value
* 16 + nib
;
115 require_data (char *p
, int p_len
, char **data
, int *data_len
)
117 int input_index
, output_index
, escaped
;
119 *data
= malloc (p_len
);
123 for (input_index
= 0; input_index
< p_len
; input_index
++)
125 char b
= p
[input_index
];
129 (*data
)[output_index
++] = b
^ 0x20;
135 (*data
)[output_index
++] = b
;
141 *data_len
= output_index
;
146 require_comma (char **pp
)
158 require_end (char *p
)
167 require_valid_fd (int fd
)
169 struct fd_list
*fd_ptr
;
171 for (fd_ptr
= open_fds
; fd_ptr
!= NULL
; fd_ptr
= fd_ptr
->next
)
172 if (fd_ptr
->fd
== fd
)
178 /* Fill in own_buf with the last hostio error packet, however it
179 suitable for the target. */
181 hostio_error (char *own_buf
)
183 the_target
->hostio_last_error (own_buf
);
187 hostio_packet_error (char *own_buf
)
189 sprintf (own_buf
, "F-1,%x", FILEIO_EINVAL
);
193 hostio_reply (char *own_buf
, int result
)
195 sprintf (own_buf
, "F%x", result
);
199 hostio_reply_with_data (char *own_buf
, char *buffer
, int len
,
202 int input_index
, output_index
, out_maxlen
;
204 sprintf (own_buf
, "F%x;", len
);
205 output_index
= strlen (own_buf
);
207 out_maxlen
= PBUFSIZ
;
209 for (input_index
= 0; input_index
< len
; input_index
++)
211 char b
= buffer
[input_index
];
213 if (b
== '$' || b
== '#' || b
== '}' || b
== '*')
215 /* These must be escaped. */
216 if (output_index
+ 2 > out_maxlen
)
218 own_buf
[output_index
++] = '}';
219 own_buf
[output_index
++] = b
^ 0x20;
223 if (output_index
+ 1 > out_maxlen
)
225 own_buf
[output_index
++] = b
;
229 *new_packet_len
= output_index
;
234 fileio_open_flags_to_host (int fileio_open_flags
, int *open_flags_p
)
238 if (fileio_open_flags
& ~FILEIO_O_SUPPORTED
)
241 if (fileio_open_flags
& FILEIO_O_CREAT
)
242 open_flags
|= O_CREAT
;
243 if (fileio_open_flags
& FILEIO_O_EXCL
)
244 open_flags
|= O_EXCL
;
245 if (fileio_open_flags
& FILEIO_O_TRUNC
)
246 open_flags
|= O_TRUNC
;
247 if (fileio_open_flags
& FILEIO_O_APPEND
)
248 open_flags
|= O_APPEND
;
249 if (fileio_open_flags
& FILEIO_O_RDONLY
)
250 open_flags
|= O_RDONLY
;
251 if (fileio_open_flags
& FILEIO_O_WRONLY
)
252 open_flags
|= O_WRONLY
;
253 if (fileio_open_flags
& FILEIO_O_RDWR
)
254 open_flags
|= O_RDWR
;
255 /* On systems supporting binary and text mode, always open files in
258 open_flags
|= O_BINARY
;
261 *open_flags_p
= open_flags
;
266 handle_open (char *own_buf
)
268 char filename
[PATH_MAX
];
270 int fileio_flags
, mode
, flags
, fd
;
271 struct fd_list
*new_fd
;
273 p
= own_buf
+ strlen ("vFile:open:");
275 if (require_filename (&p
, filename
)
276 || require_comma (&p
)
277 || require_int (&p
, &fileio_flags
)
278 || require_comma (&p
)
279 || require_int (&p
, &mode
)
281 || fileio_open_flags_to_host (fileio_flags
, &flags
))
283 hostio_packet_error (own_buf
);
287 /* We do not need to convert MODE, since the fileio protocol
288 uses the standard values. */
289 fd
= open (filename
, flags
, mode
);
293 hostio_error (own_buf
);
297 /* Record the new file descriptor. */
298 new_fd
= malloc (sizeof (struct fd_list
));
300 new_fd
->next
= open_fds
;
303 hostio_reply (own_buf
, fd
);
307 handle_pread (char *own_buf
, int *new_packet_len
)
309 int fd
, ret
, len
, offset
, bytes_sent
;
312 p
= own_buf
+ strlen ("vFile:pread:");
314 if (require_int (&p
, &fd
)
315 || require_comma (&p
)
316 || require_valid_fd (fd
)
317 || require_int (&p
, &len
)
318 || require_comma (&p
)
319 || require_int (&p
, &offset
)
322 hostio_packet_error (own_buf
);
328 ret
= pread (fd
, data
, len
, offset
);
330 ret
= lseek (fd
, offset
, SEEK_SET
);
332 ret
= read (fd
, data
, len
);
337 hostio_error (own_buf
);
342 bytes_sent
= hostio_reply_with_data (own_buf
, data
, ret
, new_packet_len
);
344 /* If we were using read, and the data did not all fit in the reply,
345 we would have to back up using lseek here. With pread it does
346 not matter. But we still have a problem; the return value in the
347 packet might be wrong, so we must fix it. This time it will
349 if (bytes_sent
< ret
)
350 bytes_sent
= hostio_reply_with_data (own_buf
, data
, bytes_sent
,
357 handle_pwrite (char *own_buf
, int packet_len
)
359 int fd
, ret
, len
, offset
;
362 p
= own_buf
+ strlen ("vFile:pwrite:");
364 if (require_int (&p
, &fd
)
365 || require_comma (&p
)
366 || require_valid_fd (fd
)
367 || require_int (&p
, &offset
)
368 || require_comma (&p
)
369 || require_data (p
, packet_len
- (p
- own_buf
), &data
, &len
))
371 hostio_packet_error (own_buf
);
376 ret
= pwrite (fd
, data
, len
, offset
);
378 ret
= lseek (fd
, offset
, SEEK_SET
);
380 ret
= write (fd
, data
, len
);
385 hostio_error (own_buf
);
390 hostio_reply (own_buf
, ret
);
395 handle_close (char *own_buf
)
399 struct fd_list
**open_fd_p
, *old_fd
;
401 p
= own_buf
+ strlen ("vFile:close:");
403 if (require_int (&p
, &fd
)
404 || require_valid_fd (fd
)
407 hostio_packet_error (own_buf
);
415 hostio_error (own_buf
);
419 open_fd_p
= &open_fds
;
420 while (*open_fd_p
&& (*open_fd_p
)->fd
!= fd
)
421 open_fd_p
= &(*open_fd_p
)->next
;
424 *open_fd_p
= (*open_fd_p
)->next
;
427 hostio_reply (own_buf
, ret
);
431 handle_unlink (char *own_buf
)
433 char filename
[PATH_MAX
];
437 p
= own_buf
+ strlen ("vFile:unlink:");
439 if (require_filename (&p
, filename
)
442 hostio_packet_error (own_buf
);
446 ret
= unlink (filename
);
450 hostio_error (own_buf
);
454 hostio_reply (own_buf
, ret
);
457 /* Handle all the 'F' file transfer packets. */
460 handle_vFile (char *own_buf
, int packet_len
, int *new_packet_len
)
462 if (strncmp (own_buf
, "vFile:open:", 11) == 0)
463 handle_open (own_buf
);
464 else if (strncmp (own_buf
, "vFile:pread:", 11) == 0)
465 handle_pread (own_buf
, new_packet_len
);
466 else if (strncmp (own_buf
, "vFile:pwrite:", 12) == 0)
467 handle_pwrite (own_buf
, packet_len
);
468 else if (strncmp (own_buf
, "vFile:close:", 12) == 0)
469 handle_close (own_buf
);
470 else if (strncmp (own_buf
, "vFile:unlink:", 13) == 0)
471 handle_unlink (own_buf
);
This page took 0.046111 seconds and 4 git commands to generate.