8fdbb2b66facff436898270543b9a5da3defb826
[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 #if !defined(__CYGWIN__)
66 #include <ifaddrs.h>
67 #endif
68
69 #include <unistd.h>
70 #include <stdio.h>
71
72 int handle_rm_command(struct command_context_s *cmd_ctx, char *cmd,
73 char **args, int argc)
74 {
75 if (argc != 1)
76 {
77 command_print(cmd_ctx, "rm <filename>");
78 return ERROR_INVALID_ARGUMENTS;
79 }
80
81 if (unlink(args[0]) != 0)
82 {
83 command_print(cmd_ctx, "failed: %d", errno);
84 }
85
86 return ERROR_OK;
87 }
88
89
90 /* loads a file and returns a pointer to it in memory. The file contains
91 * a 0 byte(sentinel) after len bytes - the length of the file. */
92 int loadFile(const char *fileName, void **data, size_t *len)
93 {
94 // ensure returned length is always sane
95 *len = 0;
96
97 FILE * pFile;
98 pFile = fopen(fileName,"rb");
99 if (pFile==NULL)
100 {
101 LOG_ERROR("Can't open %s\n", fileName);
102 return ERROR_FAIL;
103 }
104 if (fseek(pFile, 0, SEEK_END)!=0)
105 {
106 LOG_ERROR("Can't open %s\n", fileName);
107 fclose(pFile);
108 return ERROR_FAIL;
109 }
110 long fsize = ftell(pFile);
111 if (fsize == -1)
112 {
113 LOG_ERROR("Can't open %s\n", fileName);
114 fclose(pFile);
115 return ERROR_FAIL;
116 }
117 *len = fsize;
118
119 if (fseek(pFile, 0, SEEK_SET)!=0)
120 {
121 LOG_ERROR("Can't open %s\n", fileName);
122 fclose(pFile);
123 return ERROR_FAIL;
124 }
125 *data = malloc(*len + 1);
126 if (*data==NULL)
127 {
128 LOG_ERROR("Can't open %s\n", fileName);
129 fclose(pFile);
130 return ERROR_FAIL;
131 }
132
133 if (fread(*data, 1, *len, pFile)!=*len)
134 {
135 fclose(pFile);
136 free(*data);
137 LOG_ERROR("Can't open %s\n", fileName);
138 return ERROR_FAIL;
139 }
140 fclose(pFile);
141
142 // 0-byte after buffer (not included in *len) serves as a sentinel
143 char *buf = (char *)*data;
144 buf[*len] = 0;
145
146 return ERROR_OK;
147 }
148
149
150
151 int handle_cat_command(struct command_context_s *cmd_ctx, char *cmd,
152 char **args, int argc)
153 {
154 if (argc != 1)
155 {
156 command_print(cmd_ctx, "cat <filename>");
157 return ERROR_INVALID_ARGUMENTS;
158 }
159
160 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
161 void *data;
162 size_t len;
163
164 int retval = loadFile(args[0], &data, &len);
165 if (retval == ERROR_OK)
166 {
167 command_print(cmd_ctx, "%s", data);
168 free(data);
169 }
170 else
171 {
172 command_print(cmd_ctx, "%s not found %d", args[0], retval);
173 }
174
175 return ERROR_OK;
176 }
177 int handle_trunc_command(struct command_context_s *cmd_ctx, char *cmd,
178 char **args, int argc)
179 {
180 if (argc != 1)
181 {
182 command_print(cmd_ctx, "trunc <filename>");
183 return ERROR_INVALID_ARGUMENTS;
184 }
185
186 FILE *config_file = NULL;
187 config_file = fopen(args[0], "w");
188 if (config_file != NULL)
189 fclose(config_file);
190
191 return ERROR_OK;
192 }
193
194
195 int handle_meminfo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
196 {
197 static int prev = 0;
198 struct mallinfo info;
199
200 if (argc != 0)
201 {
202 command_print(cmd_ctx, "meminfo");
203 return ERROR_INVALID_ARGUMENTS;
204 }
205
206 info = mallinfo();
207
208 if (prev > 0)
209 {
210 command_print(cmd_ctx, "Diff: %d", prev - info.fordblks);
211 }
212 prev = info.fordblks;
213
214 command_print(cmd_ctx, "Available ram: %d", info.fordblks );
215
216 return ERROR_OK;
217 }
218
219
220 int handle_append_command(struct command_context_s *cmd_ctx, char *cmd,
221 char **args, int argc)
222 {
223 if (argc < 1)
224 {
225 command_print(cmd_ctx,
226 "append <filename> [<string1>, [<string2>, ...]]");
227 return ERROR_INVALID_ARGUMENTS;
228 }
229
230 FILE *config_file = NULL;
231 config_file = fopen(args[0], "a");
232 if (config_file != NULL)
233 {
234 int i;
235 fseek(config_file, 0, SEEK_END);
236
237 for (i = 1; i < argc; i++)
238 {
239 fwrite(args[i], strlen(args[i]), 1, config_file);
240 if (i != argc - 1)
241 {
242 fwrite(" ", 1, 1, config_file);
243 }
244 }
245 fwrite("\n", 1, 1, config_file);
246 fclose(config_file);
247 }
248
249 return ERROR_OK;
250 }
251
252
253
254 int handle_cp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
255 {
256 if (argc != 2)
257 {
258 return ERROR_INVALID_ARGUMENTS;
259 }
260
261 // NOTE!!! we only have line printing capability so we print the entire file as a single line.
262 void *data;
263 size_t len;
264
265 int retval = loadFile(args[0], &data, &len);
266 if (retval != ERROR_OK)
267 return retval;
268
269 FILE *f = fopen(args[1], "wb");
270 if (f == NULL)
271 retval = ERROR_INVALID_ARGUMENTS;
272
273 size_t pos = 0;
274 for (;;)
275 {
276 size_t chunk = len - pos;
277 static const size_t maxChunk = 512 * 1024; // ~1/sec
278 if (chunk > maxChunk)
279 {
280 chunk = maxChunk;
281 }
282
283 if ((retval==ERROR_OK)&&(fwrite(((char *)data)+pos, 1, chunk, f)!=chunk))
284 retval = ERROR_INVALID_ARGUMENTS;
285
286 if (retval != ERROR_OK)
287 {
288 break;
289 }
290
291 command_print(cmd_ctx, "%d", len - pos);
292
293 pos += chunk;
294
295 if (pos == len)
296 break;
297 }
298
299 if (retval == ERROR_OK)
300 {
301 command_print(cmd_ctx, "Copied %s to %s", args[0], args[1]);
302 } else
303 {
304 command_print(cmd_ctx, "Failed: %d", retval);
305 }
306
307 if (data != NULL)
308 free(data);
309 if (f != NULL)
310 fclose(f);
311
312 if (retval != ERROR_OK)
313 unlink(args[1]);
314
315 return retval;
316 }
317
318
319
320
321 #define SHOW_RESULT(a, b) LOG_ERROR(#a " failed %d\n", (int)b)
322
323 #define IOSIZE 512
324 void copyfile(char *name2, char *name1)
325 {
326
327 int err;
328 char buf[IOSIZE];
329 int fd1, fd2;
330 ssize_t done, wrote;
331
332 fd1 = open(name1, O_WRONLY | O_CREAT);
333 if (fd1 < 0)
334 SHOW_RESULT( open, fd1 );
335
336 fd2 = open(name2, O_RDONLY);
337 if (fd2 < 0)
338 SHOW_RESULT( open, fd2 );
339
340 for (;;)
341 {
342 done = read(fd2, buf, IOSIZE );
343 if (done < 0)
344 {
345 SHOW_RESULT( read, done );
346 break;
347 }
348
349 if( done == 0 ) break;
350
351 wrote = write(fd1, buf, done);
352 if( wrote != done ) SHOW_RESULT( write, wrote );
353
354 if( wrote != done ) break;
355 }
356
357 err = close(fd1);
358 if( err < 0 ) SHOW_RESULT( close, err );
359
360 err = close(fd2);
361 if( err < 0 ) SHOW_RESULT( close, err );
362
363 }
364
365 /* utility fn to copy a directory */
366 void copydir(char *name, char *destdir)
367 {
368 int err;
369 DIR *dirp;
370
371 dirp = opendir(destdir);
372 if (dirp==NULL)
373 {
374 mkdir(destdir, 0777);
375 } else
376 {
377 err = closedir(dirp);
378 }
379
380 dirp = opendir(name);
381 if( dirp == NULL ) SHOW_RESULT( opendir, -1 );
382
383 for (;;)
384 {
385 struct dirent *entry = readdir(dirp);
386
387 if (entry == NULL)
388 break;
389
390 if (strcmp(entry->d_name, ".") == 0)
391 continue;
392 if (strcmp(entry->d_name, "..") == 0)
393 continue;
394
395 int isDir = 0;
396 struct stat buf;
397 char fullPath[PATH_MAX];
398 strncpy(fullPath, name, PATH_MAX);
399 strcat(fullPath, "/");
400 strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath));
401
402 if (stat(fullPath, &buf) == -1)
403 {
404 LOG_ERROR("unable to read status from %s", fullPath);
405 break;
406 }
407 isDir = S_ISDIR(buf.st_mode) != 0;
408
409 if (isDir)
410 continue;
411
412 // diag_printf("<INFO>: entry %14s",entry->d_name);
413 char fullname[PATH_MAX];
414 char fullname2[PATH_MAX];
415
416 strcpy(fullname, name);
417 strcat(fullname, "/");
418 strcat(fullname, entry->d_name);
419
420 strcpy(fullname2, destdir);
421 strcat(fullname2, "/");
422 strcat(fullname2, entry->d_name);
423 // diag_printf("from %s to %s\n", fullname, fullname2);
424 copyfile(fullname, fullname2);
425
426 // diag_printf("\n");
427 }
428
429 err = closedir(dirp);
430 if( err < 0 ) SHOW_RESULT( stat, err );
431 }
432
433
434
435
436 static int
437 zylinjtag_Jim_Command_rm(Jim_Interp *interp,
438 int argc,
439 Jim_Obj * const *argv)
440 {
441 int del;
442 if (argc != 2)
443 {
444 Jim_WrongNumArgs(interp, 1, argv, "rm ?dirorfile?");
445 return JIM_ERR;
446 }
447
448 del = 0;
449 if (unlink(Jim_GetString(argv[1], NULL)) == 0)
450 del = 1;
451 if (rmdir(Jim_GetString(argv[1], NULL)) == 0)
452 del = 1;
453
454 return del ? JIM_OK : JIM_ERR;
455 }
456
457
458 static int
459 zylinjtag_Jim_Command_ls(Jim_Interp *interp,
460 int argc,
461 Jim_Obj * const *argv)
462 {
463 if (argc != 2)
464 {
465 Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
466 return JIM_ERR;
467 }
468
469 char *name = (char*) Jim_GetString(argv[1], NULL);
470
471 DIR *dirp = NULL;
472 dirp = opendir(name);
473 if (dirp == NULL)
474 {
475 return JIM_ERR;
476 }
477 Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
478
479 for (;;)
480 {
481 struct dirent *entry = NULL;
482 entry = readdir(dirp);
483 if (entry == NULL)
484 break;
485
486 if ((strcmp(".", entry->d_name)==0)||(strcmp("..", entry->d_name)==0))
487 continue;
488
489 Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, entry->d_name, strlen(entry->d_name)));
490 }
491 closedir(dirp);
492
493 Jim_SetResult(interp, objPtr);
494
495 return JIM_OK;
496 }
497
498 int handle_peek_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
499 {
500 if (argc != 1)
501 {
502 return ERROR_COMMAND_SYNTAX_ERROR;
503 }
504 unsigned long addr = strtoul(args[0], NULL, 0);
505 volatile unsigned *address = (volatile unsigned *)addr;
506 unsigned value = *address;
507 command_print(cmd_ctx, "0x%x : 0x%x", address, value);
508 return ERROR_OK;
509 }
510
511 int handle_poke_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
512 {
513 if (argc != 2)
514 {
515 return ERROR_INVALID_ARGUMENTS;
516 }
517 unsigned long addr = strtoul(args[0], NULL, 0);
518 volatile int *address = (volatile int *)addr;
519 int value=strtoul(args[1], NULL, 0);
520 *address=value;
521 return ERROR_OK;
522 }
523
524 static int
525 zylinjtag_Jim_Command_peek(Jim_Interp *interp,
526 int argc,
527 Jim_Obj * const *argv)
528 {
529 if (argc != 2)
530 {
531 Jim_WrongNumArgs(interp, 1, argv, "peek ?address?");
532 return JIM_ERR;
533 }
534
535 long address;
536 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
537 return JIM_ERR;
538
539 int value = *((volatile int *) address);
540
541 Jim_SetResult(interp, Jim_NewIntObj(interp, value));
542
543 return JIM_OK;
544 }
545
546 static int
547 zylinjtag_Jim_Command_poke(Jim_Interp *interp,
548 int argc,
549 Jim_Obj * const *argv)
550 {
551 if (argc != 3)
552 {
553 Jim_WrongNumArgs(interp, 1, argv, "poke ?address? ?value?");
554 return JIM_ERR;
555 }
556
557 long address;
558 if (Jim_GetLong(interp, argv[1], &address) != JIM_OK)
559 return JIM_ERR;
560 long value;
561 if (Jim_GetLong(interp, argv[2], &value) != JIM_OK)
562 return JIM_ERR;
563
564 *((volatile int *) address) = value;
565
566 return JIM_OK;
567 }
568
569
570 /* not so pretty code to fish out ip number*/
571 static int zylinjtag_Jim_Command_ip(Jim_Interp *interp, int argc,
572 Jim_Obj * const *argv)
573 {
574 #if !defined(__CYGWIN__)
575 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
576
577 struct ifaddrs *ifa = NULL, *ifp = NULL;
578
579 if (getifaddrs(&ifp) < 0)
580 {
581 return JIM_ERR;
582 }
583
584 for (ifa = ifp; ifa; ifa = ifa->ifa_next)
585 {
586 char ip[200];
587 socklen_t salen;
588
589 if (ifa->ifa_addr->sa_family == AF_INET)
590 salen = sizeof(struct sockaddr_in);
591 else if (ifa->ifa_addr->sa_family == AF_INET6)
592 salen = sizeof(struct sockaddr_in6);
593 else
594 continue;
595
596 if (getnameinfo(ifa->ifa_addr, salen, ip, sizeof(ip), NULL, 0,
597 NI_NUMERICHOST) < 0)
598 {
599 continue;
600 }
601
602 Jim_AppendString(interp, tclOutput, ip, strlen(ip));
603 break;
604
605 }
606
607 freeifaddrs(ifp);
608 #else
609 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "fixme!!!", 0);
610 LOG_ERROR("NOT IMPLEMENTED!!!");
611 #endif
612 Jim_SetResult(interp, tclOutput);
613
614 return JIM_OK;
615 }
616
617 /* not so pretty code to fish out eth0 mac address */
618 static int zylinjtag_Jim_Command_mac(Jim_Interp *interp, int argc,
619 Jim_Obj * const *argv)
620 {
621
622
623 struct ifreq *ifr, *ifend;
624 struct ifreq ifreq;
625 struct ifconf ifc;
626 struct ifreq ifs[5];
627 int SockFD;
628
629 SockFD = socket(AF_INET, SOCK_DGRAM, 0);
630 if (SockFD < 0)
631 {
632 return JIM_ERR;
633 }
634
635 ifc.ifc_len = sizeof(ifs);
636 ifc.ifc_req = ifs;
637 if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0)
638 {
639 close(SockFD);
640 return JIM_ERR;
641 }
642
643 ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
644 for (ifr = ifc.ifc_req; ifr < ifend; ifr++)
645 {
646 //if (ifr->ifr_addr.sa_family == AF_INET)
647 {
648 if (strcmp("eth0", ifr->ifr_name)!=0)
649 continue;
650 strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
651 if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0)
652 {
653 close(SockFD);
654 return JIM_ERR;
655 }
656
657 close(SockFD);
658
659
660 Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
661
662 char buffer[256];
663 sprintf(buffer, "%02x-%02x-%02x-%02x-%02x-%02x",
664 ifreq.ifr_hwaddr.sa_data[0]&0xff,
665 ifreq.ifr_hwaddr.sa_data[1]&0xff,
666 ifreq.ifr_hwaddr.sa_data[2]&0xff,
667 ifreq.ifr_hwaddr.sa_data[3]&0xff,
668 ifreq.ifr_hwaddr.sa_data[4]&0xff,
669 ifreq.ifr_hwaddr.sa_data[5]&0xff);
670
671 Jim_AppendString(interp, tclOutput, buffer, strlen(buffer));
672
673 Jim_SetResult(interp, tclOutput);
674
675 return JIM_OK;
676 }
677 }
678 close(SockFD);
679
680 return JIM_ERR;
681
682 }
683
684
685
686 int ioutil_init(struct command_context_s *cmd_ctx)
687 {
688 register_command(cmd_ctx, NULL, "rm", handle_rm_command, COMMAND_ANY,
689 "remove file");
690
691 register_command(cmd_ctx, NULL, "cat", handle_cat_command, COMMAND_ANY,
692 "display file content");
693
694 register_command(cmd_ctx, NULL, "trunc", handle_trunc_command, COMMAND_ANY,
695 "truncate a file to 0 size");
696
697 register_command(cmd_ctx, NULL, "cp", handle_cp_command,
698 COMMAND_ANY, "copy a file <from> <to>");
699
700 register_command(cmd_ctx, NULL, "append_file", handle_append_command,
701 COMMAND_ANY, "append a variable number of strings to a file");
702
703 register_command(cmd_ctx, NULL, "meminfo", handle_meminfo_command,
704 COMMAND_ANY, "display available ram memory");
705
706 Jim_CreateCommand(interp, "rm", zylinjtag_Jim_Command_rm, NULL, NULL);
707
708 Jim_CreateCommand(interp, "peek", zylinjtag_Jim_Command_peek, NULL, NULL);
709 Jim_CreateCommand(interp, "poke", zylinjtag_Jim_Command_poke, NULL, NULL);
710 Jim_CreateCommand(interp, "ls", zylinjtag_Jim_Command_ls, NULL, NULL);
711
712 Jim_CreateCommand(interp, "mac", zylinjtag_Jim_Command_mac,
713 NULL, NULL);
714
715 Jim_CreateCommand(interp, "ip", zylinjtag_Jim_Command_ip,
716 NULL, NULL);
717
718 return ERROR_OK;
719 }
720
721

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)