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

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)