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