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

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)