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

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)