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

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)