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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [gdbserver/] [hostio.c] - Blame information for rev 178

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

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

powered by: WebSVN 2.1.0

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