OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [gdbserver/] [hostio.c] - Blame information for rev 861

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* Host file transfer support for gdbserver.
2
   Copyright (C) 2007, 2008, 2009, 2010 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
    return -1;
138
 
139
  *data_len = output_index;
140
  return 0;
141
}
142
 
143
static int
144
require_comma (char **pp)
145
{
146
  if (**pp == ',')
147
    {
148
      (*pp)++;
149
      return 0;
150
    }
151
  else
152
    return -1;
153
}
154
 
155
static int
156
require_end (char *p)
157
{
158
  if (*p == '\0')
159
    return 0;
160
  else
161
    return -1;
162
}
163
 
164
static int
165
require_valid_fd (int fd)
166
{
167
  struct fd_list *fd_ptr;
168
 
169
  for (fd_ptr = open_fds; fd_ptr != NULL; fd_ptr = fd_ptr->next)
170
    if (fd_ptr->fd == fd)
171
      return 0;
172
 
173
  return -1;
174
}
175
 
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)
180
{
181
  the_target->hostio_last_error (own_buf);
182
}
183
 
184
static void
185
hostio_packet_error (char *own_buf)
186
{
187
  sprintf (own_buf, "F-1,%x", FILEIO_EINVAL);
188
}
189
 
190
static void
191
hostio_reply (char *own_buf, int result)
192
{
193
  sprintf (own_buf, "F%x", result);
194
}
195
 
196
static int
197
hostio_reply_with_data (char *own_buf, char *buffer, int len,
198
                        int *new_packet_len)
199
{
200
  int input_index, output_index, out_maxlen;
201
 
202
  sprintf (own_buf, "F%x;", len);
203
  output_index = strlen (own_buf);
204
 
205
  out_maxlen = PBUFSIZ;
206
 
207
  for (input_index = 0; input_index < len; input_index++)
208
    {
209
      char b = buffer[input_index];
210
 
211
      if (b == '$' || b == '#' || b == '}' || b == '*')
212
        {
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;
218
        }
219
      else
220
        {
221
          if (output_index + 1 > out_maxlen)
222
            break;
223
          own_buf[output_index++] = b;
224
        }
225
    }
226
 
227
  *new_packet_len = output_index;
228
  return input_index;
229
}
230
 
231
static int
232
fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
233
{
234
  int open_flags = 0;
235
 
236
  if (fileio_open_flags & ~FILEIO_O_SUPPORTED)
237
    return -1;
238
 
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
258
 
259
  *open_flags_p = open_flags;
260
  return 0;
261
}
262
 
263
static void
264
handle_open (char *own_buf)
265
{
266
  char filename[PATH_MAX];
267
  char *p;
268
  int fileio_flags, mode, flags, fd;
269
  struct fd_list *new_fd;
270
 
271
  p = own_buf + strlen ("vFile:open:");
272
 
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))
280
    {
281
      hostio_packet_error (own_buf);
282
      return;
283
    }
284
 
285
  /* We do not need to convert MODE, since the fileio protocol
286
     uses the standard values.  */
287
  fd = open (filename, flags, mode);
288
 
289
  if (fd == -1)
290
    {
291
      hostio_error (own_buf);
292
      return;
293
    }
294
 
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;
300
 
301
  hostio_reply (own_buf, fd);
302
}
303
 
304
static void
305
handle_pread (char *own_buf, int *new_packet_len)
306
{
307
  int fd, ret, len, offset, bytes_sent;
308
  char *p, *data;
309
 
310
  p = own_buf + strlen ("vFile:pread:");
311
 
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))
319
    {
320
      hostio_packet_error (own_buf);
321
      return;
322
    }
323
 
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
332
 
333
  if (ret == -1)
334
    {
335
      hostio_error (own_buf);
336
      free (data);
337
      return;
338
    }
339
 
340
  bytes_sent = hostio_reply_with_data (own_buf, data, ret, new_packet_len);
341
 
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);
350
 
351
  free (data);
352
}
353
 
354
static void
355
handle_pwrite (char *own_buf, int packet_len)
356
{
357
  int fd, ret, len, offset;
358
  char *p, *data;
359
 
360
  p = own_buf + strlen ("vFile:pwrite:");
361
 
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))
368
    {
369
      hostio_packet_error (own_buf);
370
      return;
371
    }
372
 
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
380
 
381
  if (ret == -1)
382
    {
383
      hostio_error (own_buf);
384
      free (data);
385
      return;
386
    }
387
 
388
  hostio_reply (own_buf, ret);
389
  free (data);
390
}
391
 
392
static void
393
handle_close (char *own_buf)
394
{
395
  int fd, ret;
396
  char *p;
397
  struct fd_list **open_fd_p, *old_fd;
398
 
399
  p = own_buf + strlen ("vFile:close:");
400
 
401
  if (require_int (&p, &fd)
402
      || require_valid_fd (fd)
403
      || require_end (p))
404
    {
405
      hostio_packet_error (own_buf);
406
      return;
407
    }
408
 
409
  ret = close (fd);
410
 
411
  if (ret == -1)
412
    {
413
      hostio_error (own_buf);
414
      return;
415
    }
416
 
417
  open_fd_p = &open_fds;
418
  while (*open_fd_p && (*open_fd_p)->fd != fd)
419
    open_fd_p = &(*open_fd_p)->next;
420
 
421
  old_fd = *open_fd_p;
422
  *open_fd_p = (*open_fd_p)->next;
423
  free (old_fd);
424
 
425
  hostio_reply (own_buf, ret);
426
}
427
 
428
static void
429
handle_unlink (char *own_buf)
430
{
431
  char filename[PATH_MAX];
432
  char *p;
433
  int ret;
434
 
435
  p = own_buf + strlen ("vFile:unlink:");
436
 
437
  if (require_filename (&p, filename)
438
      || require_end (p))
439
    {
440
      hostio_packet_error (own_buf);
441
      return;
442
    }
443
 
444
  ret = unlink (filename);
445
 
446
  if (ret == -1)
447
    {
448
      hostio_error (own_buf);
449
      return;
450
    }
451
 
452
  hostio_reply (own_buf, ret);
453
}
454
 
455
/* Handle all the 'F' file transfer packets.  */
456
 
457
int
458
handle_vFile (char *own_buf, int packet_len, int *new_packet_len)
459
{
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;
472
 
473
  return 1;
474
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.