]> git.sur5r.net Git - openocd/blob - src/helper/ioutil.c
Simplify #include directives in ioutil.c, use new header checks.
[openocd] / 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