* config/tc-arm.c (arm_cpus): Add entry for ARM Cortex-M0.
[binutils-gdb.git] / gdb / gdbserver / hostio.c
blobb59b03abd3acda645b68ed5e2203e7a2911f7b98
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/>. */
21 #include "server.h"
22 #include "gdb/fileio.h"
24 #include <fcntl.h>
25 #include <limits.h>
26 #include <unistd.h>
28 extern int remote_debug;
30 struct fd_list
32 int fd;
33 struct fd_list *next;
36 static struct fd_list *open_fds;
38 static int
39 safe_fromhex (char a, int *nibble)
41 if (a >= '0' && a <= '9')
42 *nibble = a - '0';
43 else if (a >= 'a' && a <= 'f')
44 *nibble = a - 'a' + 10;
45 else if (a >= 'A' && a <= 'F')
46 *nibble = a - 'A' + 10;
47 else
48 return -1;
50 return 0;
53 static int
54 require_filename (char **pp, char *filename)
56 int count;
57 char *p;
59 p = *pp;
60 count = 0;
62 while (*p && *p != ',')
64 int nib1, nib2;
66 /* Don't allow overflow. */
67 if (count >= PATH_MAX - 1)
68 return -1;
70 if (safe_fromhex (p[0], &nib1)
71 || safe_fromhex (p[1], &nib2))
72 return -1;
74 filename[count++] = nib1 * 16 + nib2;
75 p += 2;
78 filename[count] = '\0';
79 *pp = p;
80 return 0;
83 static int
84 require_int (char **pp, int *value)
86 char *p;
87 int count;
89 p = *pp;
90 *value = 0;
91 count = 0;
93 while (*p && *p != ',')
95 int nib;
97 /* Don't allow overflow. */
98 if (count >= 7)
99 return -1;
101 if (safe_fromhex (p[0], &nib))
102 return -1;
103 *value = *value * 16 + nib;
104 p++;
105 count++;
108 *pp = p;
109 return 0;
112 static int
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);
119 output_index = 0;
120 escaped = 0;
121 for (input_index = 0; input_index < p_len; input_index++)
123 char b = p[input_index];
125 if (escaped)
127 (*data)[output_index++] = b ^ 0x20;
128 escaped = 0;
130 else if (b == '}')
131 escaped = 1;
132 else
133 (*data)[output_index++] = b;
136 if (escaped)
137 return -1;
139 *data_len = output_index;
140 return 0;
143 static int
144 require_comma (char **pp)
146 if (**pp == ',')
148 (*pp)++;
149 return 0;
151 else
152 return -1;
155 static int
156 require_end (char *p)
158 if (*p == '\0')
159 return 0;
160 else
161 return -1;
164 static int
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)
171 return 0;
173 return -1;
176 /* Fill in own_buf with the last hostio error packet, however it
177 suitable for the target. */
178 static void
179 hostio_error (char *own_buf)
181 the_target->hostio_last_error (own_buf);
184 static void
185 hostio_packet_error (char *own_buf)
187 sprintf (own_buf, "F-1,%x", FILEIO_EINVAL);
190 static void
191 hostio_reply (char *own_buf, int result)
193 sprintf (own_buf, "F%x", result);
196 static int
197 hostio_reply_with_data (char *own_buf, char *buffer, int len,
198 int *new_packet_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)
215 break;
216 own_buf[output_index++] = '}';
217 own_buf[output_index++] = b ^ 0x20;
219 else
221 if (output_index + 1 > out_maxlen)
222 break;
223 own_buf[output_index++] = b;
227 *new_packet_len = output_index;
228 return input_index;
231 static int
232 fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
234 int open_flags = 0;
236 if (fileio_open_flags & ~FILEIO_O_SUPPORTED)
237 return -1;
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
254 binary mode. */
255 #ifdef O_BINARY
256 open_flags |= O_BINARY;
257 #endif
259 *open_flags_p = open_flags;
260 return 0;
263 static void
264 handle_open (char *own_buf)
266 char filename[PATH_MAX];
267 char *p;
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)
278 || require_end (p)
279 || fileio_open_flags_to_host (fileio_flags, &flags))
281 hostio_packet_error (own_buf);
282 return;
285 /* We do not need to convert MODE, since the fileio protocol
286 uses the standard values. */
287 fd = open (filename, flags, mode);
289 if (fd == -1)
291 hostio_error (own_buf);
292 return;
295 /* Record the new file descriptor. */
296 new_fd = xmalloc (sizeof (struct fd_list));
297 new_fd->fd = fd;
298 new_fd->next = open_fds;
299 open_fds = new_fd;
301 hostio_reply (own_buf, fd);
304 static void
305 handle_pread (char *own_buf, int *new_packet_len)
307 int fd, ret, len, offset, bytes_sent;
308 char *p, *data;
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)
318 || require_end (p))
320 hostio_packet_error (own_buf);
321 return;
324 data = xmalloc (len);
325 #ifdef HAVE_PREAD
326 ret = pread (fd, data, len, offset);
327 #else
328 ret = lseek (fd, offset, SEEK_SET);
329 if (ret != -1)
330 ret = read (fd, data, len);
331 #endif
333 if (ret == -1)
335 hostio_error (own_buf);
336 free (data);
337 return;
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
346 definitely fit. */
347 if (bytes_sent < ret)
348 bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent,
349 new_packet_len);
351 free (data);
354 static void
355 handle_pwrite (char *own_buf, int packet_len)
357 int fd, ret, len, offset;
358 char *p, *data;
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);
370 return;
373 #ifdef HAVE_PWRITE
374 ret = pwrite (fd, data, len, offset);
375 #else
376 ret = lseek (fd, offset, SEEK_SET);
377 if (ret != -1)
378 ret = write (fd, data, len);
379 #endif
381 if (ret == -1)
383 hostio_error (own_buf);
384 free (data);
385 return;
388 hostio_reply (own_buf, ret);
389 free (data);
392 static void
393 handle_close (char *own_buf)
395 int fd, ret;
396 char *p;
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)
403 || require_end (p))
405 hostio_packet_error (own_buf);
406 return;
409 ret = close (fd);
411 if (ret == -1)
413 hostio_error (own_buf);
414 return;
417 open_fd_p = &open_fds;
418 while (*open_fd_p && (*open_fd_p)->fd != fd)
419 open_fd_p = &(*open_fd_p)->next;
421 old_fd = *open_fd_p;
422 *open_fd_p = (*open_fd_p)->next;
423 free (old_fd);
425 hostio_reply (own_buf, ret);
428 static void
429 handle_unlink (char *own_buf)
431 char filename[PATH_MAX];
432 char *p;
433 int ret;
435 p = own_buf + strlen ("vFile:unlink:");
437 if (require_filename (&p, filename)
438 || require_end (p))
440 hostio_packet_error (own_buf);
441 return;
444 ret = unlink (filename);
446 if (ret == -1)
448 hostio_error (own_buf);
449 return;
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);
470 else
471 return 0;
473 return 1;