Garbage collect struct monitor_ops::load_routine.
[deliverable/binutils-gdb.git] / gdb / gdbserver / hostio.c
1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007-2013 Free Software Foundation, Inc.
3
4 Contributed by CodeSourcery.
5
6 This file is part of GDB.
7
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.
12
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.
17
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/>. */
20
21 #include "server.h"
22 #include "gdb/fileio.h"
23
24 #include <fcntl.h>
25 #include <limits.h>
26 #include <unistd.h>
27
28 extern int remote_debug;
29
30 struct fd_list
31 {
32 int fd;
33 struct fd_list *next;
34 };
35
36 static struct fd_list *open_fds;
37
38 static int
39 safe_fromhex (char a, int *nibble)
40 {
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;
49
50 return 0;
51 }
52
53 static int
54 require_filename (char **pp, char *filename)
55 {
56 int count;
57 char *p;
58
59 p = *pp;
60 count = 0;
61
62 while (*p && *p != ',')
63 {
64 int nib1, nib2;
65
66 /* Don't allow overflow. */
67 if (count >= PATH_MAX - 1)
68 return -1;
69
70 if (safe_fromhex (p[0], &nib1)
71 || safe_fromhex (p[1], &nib2))
72 return -1;
73
74 filename[count++] = nib1 * 16 + nib2;
75 p += 2;
76 }
77
78 filename[count] = '\0';
79 *pp = p;
80 return 0;
81 }
82
83 static int
84 require_int (char **pp, int *value)
85 {
86 char *p;
87 int count;
88
89 p = *pp;
90 *value = 0;
91 count = 0;
92
93 while (*p && *p != ',')
94 {
95 int nib;
96
97 /* Don't allow overflow. */
98 if (count >= 7)
99 return -1;
100
101 if (safe_fromhex (p[0], &nib))
102 return -1;
103 *value = *value * 16 + nib;
104 p++;
105 count++;
106 }
107
108 *pp = p;
109 return 0;
110 }
111
112 static int
113 require_data (char *p, int p_len, char **data, int *data_len)
114 {
115 int input_index, output_index, escaped;
116
117 *data = xmalloc (p_len);
118
119 output_index = 0;
120 escaped = 0;
121 for (input_index = 0; input_index < p_len; input_index++)
122 {
123 char b = p[input_index];
124
125 if (escaped)
126 {
127 (*data)[output_index++] = b ^ 0x20;
128 escaped = 0;
129 }
130 else if (b == '}')
131 escaped = 1;
132 else
133 (*data)[output_index++] = b;
134 }
135
136 if (escaped)
137 {
138 free (*data);
139 return -1;
140 }
141
142 *data_len = output_index;
143 return 0;
144 }
145
146 static int
147 require_comma (char **pp)
148 {
149 if (**pp == ',')
150 {
151 (*pp)++;
152 return 0;
153 }
154 else
155 return -1;
156 }
157
158 static int
159 require_end (char *p)
160 {
161 if (*p == '\0')
162 return 0;
163 else
164 return -1;
165 }
166
167 static int
168 require_valid_fd (int fd)
169 {
170 struct fd_list *fd_ptr;
171
172 for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next)
173 if (fd_ptr->fd == fd)
174 return 0;
175
176 return -1;
177 }
178
179 /* Fill in own_buf with the last hostio error packet, however it
180 suitable for the target. */
181 static void
182 hostio_error (char *own_buf)
183 {
184 the_target->hostio_last_error (own_buf);
185 }
186
187 static void
188 hostio_packet_error (char *own_buf)
189 {
190 sprintf (own_buf, "F-1,%x", FILEIO_EINVAL);
191 }
192
193 static void
194 hostio_reply (char *own_buf, int result)
195 {
196 sprintf (own_buf, "F%x", result);
197 }
198
199 static int
200 hostio_reply_with_data (char *own_buf, char *buffer, int len,
201 int *new_packet_len)
202 {
203 int input_index, output_index, out_maxlen;
204
205 sprintf (own_buf, "F%x;", len);
206 output_index = strlen (own_buf);
207
208 out_maxlen = PBUFSIZ;
209
210 for (input_index = 0; input_index < len; input_index++)
211 {
212 char b = buffer[input_index];
213
214 if (b == '$' || b == '#' || b == '}' || b == '*')
215 {
216 /* These must be escaped. */
217 if (output_index + 2 > out_maxlen)
218 break;
219 own_buf[output_index++] = '}';
220 own_buf[output_index++] = b ^ 0x20;
221 }
222 else
223 {
224 if (output_index + 1 > out_maxlen)
225 break;
226 own_buf[output_index++] = b;
227 }
228 }
229
230 *new_packet_len = output_index;
231 return input_index;
232 }
233
234 static int
235 fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
236 {
237 int open_flags = 0;
238
239 if (fileio_open_flags & ~FILEIO_O_SUPPORTED)
240 return -1;
241
242 if (fileio_open_flags & FILEIO_O_CREAT)
243 open_flags |= O_CREAT;
244 if (fileio_open_flags & FILEIO_O_EXCL)
245 open_flags |= O_EXCL;
246 if (fileio_open_flags & FILEIO_O_TRUNC)
247 open_flags |= O_TRUNC;
248 if (fileio_open_flags & FILEIO_O_APPEND)
249 open_flags |= O_APPEND;
250 if (fileio_open_flags & FILEIO_O_RDONLY)
251 open_flags |= O_RDONLY;
252 if (fileio_open_flags & FILEIO_O_WRONLY)
253 open_flags |= O_WRONLY;
254 if (fileio_open_flags & FILEIO_O_RDWR)
255 open_flags |= O_RDWR;
256 /* On systems supporting binary and text mode, always open files in
257 binary mode. */
258 #ifdef O_BINARY
259 open_flags |= O_BINARY;
260 #endif
261
262 *open_flags_p = open_flags;
263 return 0;
264 }
265
266 static void
267 handle_open (char *own_buf)
268 {
269 char filename[PATH_MAX];
270 char *p;
271 int fileio_flags, mode, flags, fd;
272 struct fd_list *new_fd;
273
274 p = own_buf + strlen ("vFile:open:");
275
276 if (require_filename (&p, filename)
277 || require_comma (&p)
278 || require_int (&p, &fileio_flags)
279 || require_comma (&p)
280 || require_int (&p, &mode)
281 || require_end (p)
282 || fileio_open_flags_to_host (fileio_flags, &flags))
283 {
284 hostio_packet_error (own_buf);
285 return;
286 }
287
288 /* We do not need to convert MODE, since the fileio protocol
289 uses the standard values. */
290 fd = open (filename, flags, mode);
291
292 if (fd == -1)
293 {
294 hostio_error (own_buf);
295 return;
296 }
297
298 /* Record the new file descriptor. */
299 new_fd = xmalloc (sizeof (struct fd_list));
300 new_fd->fd = fd;
301 new_fd->next = open_fds;
302 open_fds = new_fd;
303
304 hostio_reply (own_buf, fd);
305 }
306
307 static void
308 handle_pread (char *own_buf, int *new_packet_len)
309 {
310 int fd, ret, len, offset, bytes_sent;
311 char *p, *data;
312
313 p = own_buf + strlen ("vFile:pread:");
314
315 if (require_int (&p, &fd)
316 || require_comma (&p)
317 || require_valid_fd (fd)
318 || require_int (&p, &len)
319 || require_comma (&p)
320 || require_int (&p, &offset)
321 || require_end (p))
322 {
323 hostio_packet_error (own_buf);
324 return;
325 }
326
327 data = xmalloc (len);
328 #ifdef HAVE_PREAD
329 ret = pread (fd, data, len, offset);
330 #else
331 ret = -1;
332 #endif
333 /* If we have no pread or it failed for this file, use lseek/read. */
334 if (ret == -1)
335 {
336 ret = lseek (fd, offset, SEEK_SET);
337 if (ret != -1)
338 ret = read (fd, data, len);
339 }
340
341 if (ret == -1)
342 {
343 hostio_error (own_buf);
344 free (data);
345 return;
346 }
347
348 bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len);
349
350 /* If we were using read, and the data did not all fit in the reply,
351 we would have to back up using lseek here. With pread it does
352 not matter. But we still have a problem; the return value in the
353 packet might be wrong, so we must fix it. This time it will
354 definitely fit. */
355 if (bytes_sent < ret)
356 bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent,
357 new_packet_len);
358
359 free (data);
360 }
361
362 static void
363 handle_pwrite (char *own_buf, int packet_len)
364 {
365 int fd, ret, len, offset;
366 char *p, *data;
367
368 p = own_buf + strlen ("vFile:pwrite:");
369
370 if (require_int (&p, &fd)
371 || require_comma (&p)
372 || require_valid_fd (fd)
373 || require_int (&p, &offset)
374 || require_comma (&p)
375 || require_data (p, packet_len - (p - own_buf), &data, &len))
376 {
377 hostio_packet_error (own_buf);
378 return;
379 }
380
381 #ifdef HAVE_PWRITE
382 ret = pwrite (fd, data, len, offset);
383 #else
384 ret = -1;
385 #endif
386 /* If we have no pwrite or it failed for this file, use lseek/write. */
387 if (ret == -1)
388 {
389 ret = lseek (fd, offset, SEEK_SET);
390 if (ret != -1)
391 ret = write (fd, data, len);
392 }
393
394 if (ret == -1)
395 {
396 hostio_error (own_buf);
397 free (data);
398 return;
399 }
400
401 hostio_reply (own_buf, ret);
402 free (data);
403 }
404
405 static void
406 handle_close (char *own_buf)
407 {
408 int fd, ret;
409 char *p;
410 struct fd_list **open_fd_p, *old_fd;
411
412 p = own_buf + strlen ("vFile:close:");
413
414 if (require_int (&p, &fd)
415 || require_valid_fd (fd)
416 || require_end (p))
417 {
418 hostio_packet_error (own_buf);
419 return;
420 }
421
422 ret = close (fd);
423
424 if (ret == -1)
425 {
426 hostio_error (own_buf);
427 return;
428 }
429
430 open_fd_p = &open_fds;
431 /* We know that fd is in the list, thanks to require_valid_fd. */
432 while ((*open_fd_p)->fd != fd)
433 open_fd_p = &(*open_fd_p)->next;
434
435 old_fd = *open_fd_p;
436 *open_fd_p = (*open_fd_p)->next;
437 free (old_fd);
438
439 hostio_reply (own_buf, ret);
440 }
441
442 static void
443 handle_unlink (char *own_buf)
444 {
445 char filename[PATH_MAX];
446 char *p;
447 int ret;
448
449 p = own_buf + strlen ("vFile:unlink:");
450
451 if (require_filename (&p, filename)
452 || require_end (p))
453 {
454 hostio_packet_error (own_buf);
455 return;
456 }
457
458 ret = unlink (filename);
459
460 if (ret == -1)
461 {
462 hostio_error (own_buf);
463 return;
464 }
465
466 hostio_reply (own_buf, ret);
467 }
468
469 static void
470 handle_readlink (char *own_buf, int *new_packet_len)
471 {
472 #if defined (HAVE_READLINK)
473 char filename[PATH_MAX], linkname[PATH_MAX];
474 char *p;
475 int ret, bytes_sent;
476
477 p = own_buf + strlen ("vFile:readlink:");
478
479 if (require_filename (&p, filename)
480 || require_end (p))
481 {
482 hostio_packet_error (own_buf);
483 return;
484 }
485
486 ret = readlink (filename, linkname, sizeof (linkname) - 1);
487 if (ret == -1)
488 {
489 hostio_error (own_buf);
490 return;
491 }
492
493 bytes_sent = hostio_reply_with_data (own_buf, linkname, ret, new_packet_len);
494
495 /* If the response does not fit into a single packet, do not attempt
496 to return a partial response, but simply fail. */
497 if (bytes_sent < ret)
498 sprintf (own_buf, "F-1,%x", FILEIO_ENAMETOOLONG);
499 #else /* ! HAVE_READLINK */
500 sprintf (own_buf, "F-1,%x", FILEIO_ENOSYS);
501 #endif
502 }
503
504 /* Handle all the 'F' file transfer packets. */
505
506 int
507 handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
508 {
509 if (strncmp (own_buf, "vFile:open:", 11) == 0)
510 handle_open (own_buf);
511 else if (strncmp (own_buf, "vFile:pread:", 11) == 0)
512 handle_pread (own_buf, new_packet_len);
513 else if (strncmp (own_buf, "vFile:pwrite:", 12) == 0)
514 handle_pwrite (own_buf, packet_len);
515 else if (strncmp (own_buf, "vFile:close:", 12) == 0)
516 handle_close (own_buf);
517 else if (strncmp (own_buf, "vFile:unlink:", 13) == 0)
518 handle_unlink (own_buf);
519 else if (strncmp (own_buf, "vFile:readlink:", 15) == 0)
520 handle_readlink (own_buf, new_packet_len);
521 else
522 return 0;
523
524 return 1;
525 }
This page took 0.03956 seconds and 4 git commands to generate.