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

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)