- add missing svn props from r1243 commit
[openocd.git] / src / helper / ioutil.c
1 /***************************************************************************
2 * Copyright (C) 2007-2008 by Øyvind Harboe *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 /* this file contains various functionality useful to standalone systems */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "log.h"
27 #include "types.h"
28 #include "configuration.h"
29 #include "target.h"
30
31 #include "command.h"
32
33 #include <time_support.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <strings.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #if !BUILD_ECOSBOARD
42 #include <malloc.h>
43 #endif
44 #include <errno.h>
45
46
47 #include <fcntl.h>
48 #include <sys/stat.h>
49 #include <dirent.h>
50 #include <netinet/tcp.h>
51 #include <sys/ioctl.h>
52 #include <sys/socket.h>
53 #include <netinet/in.h>
54 #include <net/if.h>
55 #include <arpa/inet.h>
56 #include <sys/types.h>
57 #include <sys/socket.h>
58 #include <netdb.h>
59 #include <netinet/in.h>
60 #include <unistd.h>
61 #include <arpa/inet.h>
62 #include <stdio.h>
63 #include <string.h>
64
65
66 #include <unistd.h>
67 #include <stdio.h>
68
69 int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
70 char **args, int argc)
71 {
72 if (argc != 1)
73 {
74 command_print(cmd_ctx, "rm <filename>");
75 return ERROR_INVALID_ARGUMENTS;
76 }
77
78 if (unlink(args[0]) != 0)
79 {
80 command_print(cmd_ctx, "failed: %d", errno);
81 }
82
83 return ERROR_OK;
84 }
85
86
87 /* loads a file and returns a pointer to it in memory. The file contains
88 * a 0 byte(sentinel) after len bytes - the length of the file. */
89 int loadFile(const char *fileName, void **data, int *len)
90 {
91 FILE * pFile;
92 pFile = fopen(fileName,"rb");
93 if (pFile==NULL)
94 {
95 LOG_ERROR("Can't open %s\n", fileName);
96 return ERROR_FAIL;
97 }
98 if (fseek(pFile, 0, SEEK_END)!=0)
99 {
100 LOG_ERROR("Can't open %s\n", fileName);
101 fclose(pFile);
102 return ERROR_FAIL;
103 }
104 *len=ftell(pFile);
105 if (*len==-1)
106 {
107 LOG_ERROR("Can't open %s\n", fileName);
108 fclose(pFile);
109 return ERROR_FAIL;
110 }
111
112 if (fseek(pFile, 0, SEEK_SET)!=0)
113 {
114 LOG_ERROR("Can't open %s\n", fileName);
115 fclose(pFile);
116 return ERROR_FAIL;
117 }
118 *data=malloc(*len+1);
119 if (*data==NULL)
120 {
121 LOG_ERROR("Can't open %s\n", fileName);
122 fclose(pFile);
123 return ERROR_FAIL;
124 }
125
126 if (fread(*data, 1, *len, pFile)!=*len)
127 {
128 fclose(pFile);
129 free(*data);
130 LOG_ERROR("Can't open %s\n", fileName);
131 return ERROR_FAIL;
132 }
133 fclose(pFile);
134 *(((char *)(*data))+*len)=0; /* sentinel */
135
136 return ERROR_OK;
137
138
139
140 }
141
142
143
144 int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
145 char **args, int argc)
146 {
147 if (argc != 1)
148 {
149 command_print(cmd_ctx, "cat <filename>");
150 return ERROR_INVALID_ARGUMENTS;
151 }
152
153 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
154 void *data;
155 int len;
156
157 int retval = loadFile(args[0], &data, &len);
158 if (retval == ERROR_OK)
159 {
160 command_print(cmd_ctx, "%s", data);
161 free(data);
162 }
163 else
164 {
165 command_print(cmd_ctx, "%s not found %d", args[0], retval);
166 }
167
168 return ERROR_OK;
169 }
170 int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
171 char **args, int argc)
172 {
173 if (argc != 1)
174 {
175 command_print(cmd_ctx, "trunc <filename>");
176 return ERROR_INVALID_ARGUMENTS;
177 }
178
179 FILE *config_file = NULL;
180 config_file = fopen(args[0], "w");
181 if (config_file != NULL)
182 fclose(config_file);
183
184 return ERROR_OK;
185 }
186
187
188 int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
189 {
190 static int prev = 0;
191 struct mallinfo info;
192
193 if (argc != 0)
194 {
195 command_print(cmd_ctx, "meminfo");
196 return ERROR_INVALID_ARGUMENTS;
197 }
198
199 info = mallinfo();
200
201 if (prev > 0)
202 {
203 command_print(cmd_ctx, "Diff: %d", prev - info.fordblks);
204 }
205 prev = info.fordblks;
206
207 command_print(cmd_ctx, "Available ram: %d", info.fordblks );
208
209 return ERROR_OK;
210 }
211
212
213 int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
214 char **args, int argc)
215 {
216 if (argc < 1)
217 {
218 command_print(cmd_ctx,
219 "append <filename> [<string1>, [<string2>, ...]]");
220 return ERROR_INVALID_ARGUMENTS;
221 }
222
223 FILE *config_file = NULL;
224 config_file = fopen(args[0], "a");
225 if (config_file != NULL)
226 {
227 int i;
228 fseek(config_file, 0, SEEK_END);
229
230 for (i = 1; i < argc; i++)
231 {
232 fwrite(args[i], strlen(args[i]), 1, config_file);
233 if (i != argc - 1)
234 {
235 fwrite(" ", 1, 1, config_file);
236 }
237 }
238 fwrite("\n", 1, 1, config_file);
239 fclose(config_file);
240 }
241
242 return ERROR_OK;
243 }
244
245
246
247 int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
248 {
249 if (argc != 2)
250 {
251 return ERROR_INVALID_ARGUMENTS;
252 }
253
254 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
255 void *data;
256 int len;
257
258 int retval = loadFile(args[0], &data, &len);
259 if (retval != ERROR_OK)
260 return retval;
261
262 FILE *f = fopen(args[1], "wb");
263 if (f == NULL)
264 retval = ERROR_INVALID_ARGUMENTS;
265
266 int pos = 0;
267 for (;;)
268 {
269 int chunk = len - pos;
270 static const int maxChunk = 512 * 1024; // ~1/sec
271 if (chunk > maxChunk)
272 {
273 chunk = maxChunk;
274 }
275
276 if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
277 retval = ERROR_INVALID_ARGUMENTS;
278
279 if (retval != ERROR_OK)
280 {
281 break;
282 }
283
284 command_print(cmd_ctx, "%d", len - pos);
285
286 pos += chunk;
287
288 if (pos == len)
289 break;
290 }
291
292 if (retval == ERROR_OK)
293 {
294 command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
295 } else
296 {
297 command_print(cmd_ctx, "Failed: %d", retval);
298 }
299
300 if (data != NULL)
301 free(data);
302 if (f != NULL)
303 fclose(f);
304
305 if (retval != ERROR_OK)
306 unlink(args[1]);
307
308 return retval;
309 }
310
311
312
313
314 #define SHOW_RESULT(a, b) LOG_ERROR(#a " failed %d\n", (int)b)
315
316 #define IOSIZE 512
317 void copyfile(char *name2, char *name1)
318 {
319
320 int err;
321 char buf[IOSIZE];
322 int fd1, fd2;
323 ssize_t done, wrote;
324
325 fd1 = open(name1, O_WRONLY | O_CREAT);
326 if (fd1 < 0)
327 SHOW_RESULT( open, fd1 );
328
329 fd2 = open(name2, O_RDONLY);
330 if (fd2 < 0)
331 SHOW_RESULT( open, fd2 );
332
333 for (;;)
334 {
335 done = read(fd2, buf, IOSIZE );
336 if (done < 0)
337 {
338 SHOW_RESULT( read, done );
339 break;
340 }
341
342 if( done == 0 ) break;
343
344 wrote = write(fd1, buf, done);
345 if( wrote != done ) SHOW_RESULT( write, wrote );
346
347 if( wrote != done ) break;
348 }
349
350 err = close(fd1);
351 if( err < 0 ) SHOW_RESULT( close, err );
352
353 err = close(fd2);
354 if( err < 0 ) SHOW_RESULT( close, err );
355
356 }
357
358 /* utility fn to copy a directory */
359 void copydir(char *name, char *destdir)
360 {
361 int err;
362 DIR *dirp;
363
364 dirp = opendir(destdir);
365 if (dirp==NULL)
366 {
367 mkdir(destdir, 0777);
368 } else
369 {
370 err = closedir(dirp);
371 }
372
373 dirp = opendir(name);
374 if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
375
376 for (;;)
377 {
378 struct dirent *entry = readdir(dirp);
379
380 if (entry == NULL)
381 break;
382
383 if (strcmp(entry->d_name, ".") == 0)
384 continue;
385 if (strcmp(entry->d_name, "..") == 0)
386 continue;
387
388 int isDir = 0;
389 struct stat buf;
390 char fullPath[PATH_MAX];
391 strncpy(fullPath, name, PATH_MAX);
392 strcat(fullPath, "/");
393 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
394
395 if (stat(fullPath, &buf) == -1)
396 {
397 LOG_ERROR("unable to read status from %s", fullPath);
398 break;
399 }
400 isDir = S_ISDIR(buf.st_mode) != 0;
401
402 if (isDir)
403 continue;
404
405 // diag_printf("<INFO>: entry %14s",entry->d_name);
406 char fullname[PATH_MAX];
407 char fullname2[PATH_MAX];
408
409 strcpy(fullname, name);
410 strcat(fullname, "/");
411 strcat(fullname, entry->d_name);
412
413 strcpy(fullname2, destdir);
414 strcat(fullname2, "/");
415 strcat(fullname2, entry->d_name);
416 // diag_printf("from %s to %s\n", fullname, fullname2);
417 copyfile(fullname, fullname2);
418
419 // diag_printf("\n");
420 }
421
422 err = closedir(dirp);
423 if( err < 0 ) SHOW_RESULT( stat, err );
424 }
425
426
427
428
429 static int
430 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
431 int argc,
432 Jim_Obj * const *argv)
433 {
434 int del;
435 if (argc != 2)
436 {
437 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
438 return JIM_ERR;
439 }
440
441 del = 0;
442 if (unlink(Jim_GetString(argv[1], NULL)) == 0)
443 del = 1;
444 if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
445 del = 1;
446
447 return del ? JIM_OK : JIM_ERR;
448 }
449
450
451 static int
452 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
453 int argc,
454 Jim_Obj * const *argv)
455 {
456 if (argc != 2)
457 {
458 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
459 return JIM_ERR;
460 }
461
462 char *name = (char*) Jim_GetString(argv[1], NULL);
463
464 DIR *dirp = NULL;
465 dirp = opendir(name);
466 if (dirp == NULL)
467 {
468 return JIM_ERR;
469 }
470 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
471
472 for (;;)
473 {
474 struct dirent *entry = NULL;
475 entry = readdir(dirp);
476 if (entry == NULL)
477 break;
478
479 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
480 continue;
481
482 Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
483 }
484 closedir(dirp);
485
486 Jim_SetResult(interp, objPtr);
487
488 return JIM_OK;
489 }
490
491 int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
492 {
493 if (argc != 1)
494 {
495 return ERROR_COMMAND_SYNTAX_ERROR;
496 }
497 volatile int *address=(volatile int *)strtoul(args[0], NULL, 0);
498 int value=*address;
499 command_print(cmd_ctx, "0x%x : 0x%x", address, value);
500 return ERROR_OK;
501 }
502
503 int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
504 {
505 if (argc != 2)
506 {
507 return ERROR_INVALID_ARGUMENTS;
508 }
509 volatile int *address=(volatile int *)strtoul(args[0], NULL, 0);
510 int value=strtoul(args[1], NULL, 0);
511 *address=value;
512 return ERROR_OK;
513 }
514
515 static int
516 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
517 int argc,
518 Jim_Obj * const *argv)
519 {
520 if (argc != 2)
521 {
522 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
523 return JIM_ERR;
524 }
525
526 long address;
527 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
528 return JIM_ERR;
529
530 int value = *((volatile int *) address);
531
532 Jim_SetResult(interp, Jim_NewIntObj(interp, value));
533
534 return JIM_OK;
535 }
536
537 static int
538 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
539 int argc,
540 Jim_Obj * const *argv)
541 {
542 if (argc != 3)
543 {
544 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
545 return JIM_ERR;
546 }
547
548 long address;
549 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
550 return JIM_ERR;
551 long value;
552 if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
553 return JIM_ERR;
554
555 *((volatile int *) address) = value;
556
557 return JIM_OK;
558 }
559
560 int ioutil_init(struct command_context_s *cmd_ctx)
561 {
562 register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
563 "remove file");
564
565 register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
566 "display file content");
567
568 register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
569 "truncate a file to 0 size");
570
571 register_command(cmd_ctx, NULL, "cp", handle_cp_command,
572 COMMAND_ANY, "copy a file <from> <to>");
573
574 register_command(cmd_ctx, NULL, "append_file", handle_append_command,
575 COMMAND_ANY, "append a variable number of strings to a file");
576
577 register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
578 COMMAND_ANY, "display available ram memory");
579
580 Jim_CreateCommand(interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
581
582 Jim_CreateCommand(interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
583 Jim_CreateCommand(interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
584 Jim_CreateCommand(interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
585
586
587 return ERROR_OK;
588 }
589
590

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)