* configure.ac: Check for pread and pwrite.
[binutils-gdb.git] / gdb / gdbserver / hostio.c
1 /* Host file transfer support for gdbserver.
2 Copyright (C) 2007
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 #ifdef HAVE_PREAD
381 ret = pread (fd, data, len, offset);
382 #else
383 ret = lseek (fd, offset, SEEK_SET);
384 if (ret != -1)
385 ret = read (fd, data, len);
386 #endif
387
388 if (ret == -1)
389 {
390 hostio_error (own_buf, errno);
391 free (data);
392 return;
393 }
394
395 bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len);
396
397 /* If we were using read, and the data did not all fit in the reply,
398 we would have to back up using lseek here. With pread it does
399 not matter. But we still have a problem; the return value in the
400 packet might be wrong, so we must fix it. This time it will
401 definitely fit. */
402 if (bytes_sent < ret)
403 bytes_sent = hostio_reply_with_data (own_buf, data, bytes_sent,
404 new_packet_len);
405
406 free (data);
407 }
408
409 static void
410 handle_pwrite (char *own_buf, int packet_len)
411 {
412 int fd, ret, len, offset;
413 char *p, *data;
414
415 p = own_buf + strlen ("vFile:pwrite:");
416
417 if (require_int (&p, &fd)
418 || require_comma (&p)
419 || require_valid_fd (fd)
420 || require_int (&p, &offset)
421 || require_comma (&p)
422 || require_data (p, packet_len - (p - own_buf), &data, &len))
423 {
424 hostio_packet_error (own_buf);
425 return;
426 }
427
428 #ifdef HAVE_PWRITE
429 ret = pwrite (fd, data, len, offset);
430 #else
431 ret = lseek (fd, offset, SEEK_SET);
432 if (ret != -1)
433 ret = write (fd, data, len);
434 #endif
435
436 if (ret == -1)
437 {
438 hostio_error (own_buf, errno);
439 free (data);
440 return;
441 }
442
443 hostio_reply (own_buf, ret);
444 free (data);
445 }
446
447 static void
448 handle_close (char *own_buf)
449 {
450 int fd, ret;
451 char *p;
452 struct fd_list **open_fd_p, *old_fd;
453
454 p = own_buf + strlen ("vFile:close:");
455
456 if (require_int (&p, &fd)
457 || require_valid_fd (fd)
458 || require_end (p))
459 {
460 hostio_packet_error (own_buf);
461 return;
462 }
463
464 ret = close (fd);
465
466 if (ret == -1)
467 {
468 hostio_error (own_buf, errno);
469 return;
470 }
471
472 open_fd_p = &open_fds;
473 while (*open_fd_p && (*open_fd_p)->fd != fd)
474 open_fd_p = &(*open_fd_p)->next;
475
476 old_fd = *open_fd_p;
477 *open_fd_p = (*open_fd_p)->next;
478 free (old_fd);
479
480 hostio_reply (own_buf, ret);
481 }
482
483 static void
484 handle_unlink (char *own_buf)
485 {
486 char filename[PATH_MAX];
487 char *p;
488 int ret;
489
490 p = own_buf + strlen ("vFile:unlink:");
491
492 if (require_filename (&p, filename)
493 || require_end (p))
494 {
495 hostio_packet_error (own_buf);
496 return;
497 }
498
499 ret = unlink (filename);
500
501 if (ret == -1)
502 {
503 hostio_error (own_buf, errno);
504 return;
505 }
506
507 hostio_reply (own_buf, ret);
508 }
509
510 /* Handle all the 'F' file transfer packets. */
511
512 int
513 handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
514 {
515 if (strncmp (own_buf, "vFile:open:", 11) == 0)
516 handle_open (own_buf);
517 else if (strncmp (own_buf, "vFile:pread:", 11) == 0)
518 handle_pread (own_buf, new_packet_len);
519 else if (strncmp (own_buf, "vFile:pwrite:", 12) == 0)
520 handle_pwrite (own_buf, packet_len);
521 else if (strncmp (own_buf, "vFile:close:", 12) == 0)
522 handle_close (own_buf);
523 else if (strncmp (own_buf, "vFile:unlink:", 13) == 0)
524 handle_unlink (own_buf);
525 else
526 return 0;
527
528 return 1;
529 }