]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_RZ_R7S72100_IAR_DS-5/Source/Full-Demo/File-releated-CLI-commands.c
Update version number to 9.0.0rc2.
[freertos] / FreeRTOS / Demo / CORTEX_A9_RZ_R7S72100_IAR_DS-5 / Source / Full-Demo / File-releated-CLI-commands.c
1 /*\r
2     FreeRTOS V9.0.0rc2 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /* FreeRTOS includes. */\r
71 #include "FreeRTOS.h"\r
72 #include "task.h"\r
73 \r
74 /* Standard includes. */\r
75 #include <stdint.h>\r
76 #include <stdio.h>\r
77 #include <stdlib.h>\r
78 #include <string.h>\r
79 \r
80 /* FreeRTOS+CLI includes. */\r
81 #include "FreeRTOS_CLI.h"\r
82 \r
83 /* File system includes. */\r
84 #include "fat_sl.h"\r
85 #include "api_mdriver_ram.h"\r
86 \r
87 #ifdef _WINDOWS_\r
88         #define snprintf _snprintf\r
89 #endif\r
90 \r
91 #define cliNEW_LINE             "\r\n"\r
92 \r
93 /*******************************************************************************\r
94  * See the URL in the comments within main.c for the location of the online\r
95  * documentation.\r
96  ******************************************************************************/\r
97 \r
98 /*\r
99  * Print out information on a single file.\r
100  */\r
101 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct );\r
102 \r
103 /*\r
104  * Copies an existing file into a newly created file.\r
105  */\r
106 static portBASE_TYPE prvPerformCopy( char *pcSourceFile,\r
107                                                                         int32_t lSourceFileLength,\r
108                                                                         char *pcDestinationFile,\r
109                                                                         char *pxWriteBuffer,\r
110                                                                         size_t xWriteBufferLen );\r
111 \r
112 /*\r
113  * Implements the DIR command.\r
114  */\r
115 static portBASE_TYPE prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
116 \r
117 /*\r
118  * Implements the CD command.\r
119  */\r
120 static portBASE_TYPE prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
121 \r
122 /*\r
123  * Implements the DEL command.\r
124  */\r
125 static portBASE_TYPE prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
126 \r
127 /*\r
128  * Implements the TYPE command.\r
129  */\r
130 static portBASE_TYPE prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
131 \r
132 /*\r
133  * Implements the COPY command.\r
134  */\r
135 static portBASE_TYPE prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );\r
136 \r
137 /*\r
138  * Registers the CLI commands that are specific to the files system with the\r
139  * FreeRTOS+CLI command interpreter.\r
140  */\r
141 void vRegisterFileSystemCLICommands( void );\r
142 \r
143 /* Structure that defines the DIR command line command, which lists all the\r
144 files in the current directory. */\r
145 static const CLI_Command_Definition_t xDIR =\r
146 {\r
147         "dir", /* The command string to type. */\r
148         "\r\ndir:\r\n Lists the files in the current directory\r\n",\r
149         prvDIRCommand, /* The function to run. */\r
150         0 /* No parameters are expected. */\r
151 };\r
152 \r
153 /* Structure that defines the CD command line command, which changes the\r
154 working directory. */\r
155 static const CLI_Command_Definition_t xCD =\r
156 {\r
157         "cd", /* The command string to type. */\r
158         "\r\ncd <dir name>:\r\n Changes the working directory\r\n",\r
159         prvCDCommand, /* The function to run. */\r
160         1 /* One parameter is expected. */\r
161 };\r
162 \r
163 /* Structure that defines the TYPE command line command, which prints the\r
164 contents of a file to the console. */\r
165 static const CLI_Command_Definition_t xTYPE =\r
166 {\r
167         "type", /* The command string to type. */\r
168         "\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",\r
169         prvTYPECommand, /* The function to run. */\r
170         1 /* One parameter is expected. */\r
171 };\r
172 \r
173 /* Structure that defines the DEL command line command, which deletes a file. */\r
174 static const CLI_Command_Definition_t xDEL =\r
175 {\r
176         "del", /* The command string to type. */\r
177         "\r\ndel <filename>:\r\n deletes a file or directory\r\n",\r
178         prvDELCommand, /* The function to run. */\r
179         1 /* One parameter is expected. */\r
180 };\r
181 \r
182 /* Structure that defines the COPY command line command, which deletes a file. */\r
183 static const CLI_Command_Definition_t xCOPY =\r
184 {\r
185         "copy", /* The command string to type. */\r
186         "\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",\r
187         prvCOPYCommand, /* The function to run. */\r
188         2 /* Two parameters are expected. */\r
189 };\r
190 \r
191 /*-----------------------------------------------------------*/\r
192 \r
193 void vRegisterFileSystemCLICommands( void )\r
194 {\r
195         /* Register all the command line commands defined immediately above. */\r
196         FreeRTOS_CLIRegisterCommand( &xDIR );\r
197         FreeRTOS_CLIRegisterCommand( &xCD );\r
198         FreeRTOS_CLIRegisterCommand( &xTYPE );\r
199         FreeRTOS_CLIRegisterCommand( &xDEL );\r
200         FreeRTOS_CLIRegisterCommand( &xCOPY );\r
201 }\r
202 /*-----------------------------------------------------------*/\r
203 \r
204 static portBASE_TYPE prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
205 {\r
206 const char *pcParameter;\r
207 portBASE_TYPE xParameterStringLength, xReturn = pdTRUE;\r
208 static F_FILE *pxFile = NULL;\r
209 int iChar;\r
210 size_t xByte;\r
211 size_t xColumns = 50U;\r
212 \r
213         /* Ensure there is always a null terminator after each character written. */\r
214         memset( pcWriteBuffer, 0x00, xWriteBufferLen );\r
215 \r
216         /* Ensure the buffer leaves space for the \r\n. */\r
217         configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );\r
218         xWriteBufferLen -= strlen( cliNEW_LINE );\r
219 \r
220         if( xWriteBufferLen < xColumns )\r
221         {\r
222                 /* Ensure the loop that uses xColumns as an end condition does not\r
223                 write off the end of the buffer. */\r
224                 xColumns = xWriteBufferLen;\r
225         }\r
226 \r
227         if( pxFile == NULL )\r
228         {\r
229                 /* The file has not been opened yet.  Find the file name. */\r
230                 pcParameter = FreeRTOS_CLIGetParameter\r
231                                                                 (\r
232                                                                         pcCommandString,                /* The command string itself. */\r
233                                                                         1,                                              /* Return the first parameter. */\r
234                                                                         &xParameterStringLength /* Store the parameter string length. */\r
235                                                                 );\r
236 \r
237                 /* Sanity check something was returned. */\r
238                 configASSERT( pcParameter );\r
239 \r
240                 /* Attempt to open the requested file. */\r
241                 pxFile = f_open( pcParameter, "r" );\r
242         }\r
243 \r
244         if( pxFile != NULL )\r
245         {\r
246                 /* Read the next chunk of data from the file. */\r
247                 for( xByte = 0; xByte < xColumns; xByte++ )\r
248                 {\r
249                         iChar = f_getc( pxFile );\r
250 \r
251                         if( iChar == -1 )\r
252                         {\r
253                                 /* No more characters to return. */\r
254                                 f_close( pxFile );\r
255                                 pxFile = NULL;\r
256                                 break;\r
257                         }\r
258                         else\r
259                         {\r
260                                 pcWriteBuffer[ xByte ] = ( char ) iChar;\r
261                         }\r
262                 }\r
263         }\r
264 \r
265         if( pxFile == NULL )\r
266         {\r
267                 /* Either the file was not opened, or all the data from the file has\r
268                 been returned and the file is now closed. */\r
269                 xReturn = pdFALSE;\r
270         }\r
271 \r
272         strcat( pcWriteBuffer, cliNEW_LINE );\r
273 \r
274         return xReturn;\r
275 }\r
276 /*-----------------------------------------------------------*/\r
277 \r
278 static portBASE_TYPE prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
279 {\r
280 const char *pcParameter;\r
281 portBASE_TYPE xParameterStringLength;\r
282 unsigned char ucReturned;\r
283 size_t xStringLength;\r
284 \r
285         /* Obtain the parameter string. */\r
286         pcParameter = FreeRTOS_CLIGetParameter\r
287                                                 (\r
288                                                         pcCommandString,                /* The command string itself. */\r
289                                                         1,                                              /* Return the first parameter. */\r
290                                                         &xParameterStringLength /* Store the parameter string length. */\r
291                                                 );\r
292 \r
293         /* Sanity check something was returned. */\r
294         configASSERT( pcParameter );\r
295 \r
296         /* Attempt to move to the requested directory. */\r
297         ucReturned = f_chdir( pcParameter );\r
298 \r
299         if( ucReturned == F_NO_ERROR )\r
300         {\r
301                 sprintf( pcWriteBuffer, "In: " );\r
302                 xStringLength = strlen( pcWriteBuffer );\r
303                 f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );\r
304         }\r
305         else\r
306         {\r
307                 sprintf( pcWriteBuffer, "Error" );\r
308         }\r
309 \r
310         strcat( pcWriteBuffer, cliNEW_LINE );\r
311 \r
312         return pdFALSE;\r
313 }\r
314 /*-----------------------------------------------------------*/\r
315 \r
316 static portBASE_TYPE prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
317 {\r
318 static F_FIND *pxFindStruct = NULL;\r
319 unsigned char ucReturned;\r
320 portBASE_TYPE xReturn = pdFALSE;\r
321 \r
322         /* This assumes pcWriteBuffer is long enough. */\r
323         ( void ) pcCommandString;\r
324 \r
325         /* Ensure the buffer leaves space for the \r\n. */\r
326         configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );\r
327         xWriteBufferLen -= strlen( cliNEW_LINE );\r
328 \r
329         if( pxFindStruct == NULL )\r
330         {\r
331                 /* This is the first time this function has been executed since the Dir\r
332                 command was run.  Create the find structure. */\r
333                 pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );\r
334 \r
335                 if( pxFindStruct != NULL )\r
336                 {\r
337                         ucReturned = f_findfirst( "*.*", pxFindStruct );\r
338 \r
339                         if( ucReturned == F_NO_ERROR )\r
340                         {\r
341                                 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );\r
342                                 xReturn = pdPASS;\r
343                         }\r
344                         else\r
345                         {\r
346                                 snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );\r
347                         }\r
348                 }\r
349                 else\r
350                 {\r
351                         snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );\r
352                 }\r
353         }\r
354         else\r
355         {\r
356                 /* The find struct has already been created.  Find the next file in\r
357                 the directory. */\r
358                 ucReturned = f_findnext( pxFindStruct );\r
359 \r
360                 if( ucReturned == F_NO_ERROR )\r
361                 {\r
362                         prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );\r
363                         xReturn = pdPASS;\r
364                 }\r
365                 else\r
366                 {\r
367                         /* There are no more files.  Free the find structure. */\r
368                         vPortFree( pxFindStruct );\r
369                         pxFindStruct = NULL;\r
370 \r
371                         /* No string to return. */\r
372                         pcWriteBuffer[ 0 ] = 0x00;\r
373                 }\r
374         }\r
375 \r
376         strcat( pcWriteBuffer, cliNEW_LINE );\r
377 \r
378         return xReturn;\r
379 }\r
380 /*-----------------------------------------------------------*/\r
381 \r
382 static portBASE_TYPE prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
383 {\r
384 const char *pcParameter;\r
385 portBASE_TYPE xParameterStringLength;\r
386 unsigned char ucReturned;\r
387 \r
388         /* This function assumes xWriteBufferLen is large enough! */\r
389         ( void ) xWriteBufferLen;\r
390 \r
391         /* Obtain the parameter string. */\r
392         pcParameter = FreeRTOS_CLIGetParameter\r
393                                                 (\r
394                                                         pcCommandString,                /* The command string itself. */\r
395                                                         1,                                              /* Return the first parameter. */\r
396                                                         &xParameterStringLength /* Store the parameter string length. */\r
397                                                 );\r
398 \r
399         /* Sanity check something was returned. */\r
400         configASSERT( pcParameter );\r
401 \r
402         /* Attempt to delete the file. */\r
403         ucReturned = f_delete( pcParameter );\r
404 \r
405         if( ucReturned == F_NO_ERROR )\r
406         {\r
407                 sprintf( pcWriteBuffer, "%s was deleted", pcParameter );\r
408         }\r
409         else\r
410         {\r
411                 sprintf( pcWriteBuffer, "Error" );\r
412         }\r
413 \r
414         strcat( pcWriteBuffer, cliNEW_LINE );\r
415 \r
416         return pdFALSE;\r
417 }\r
418 /*-----------------------------------------------------------*/\r
419 \r
420 static portBASE_TYPE prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )\r
421 {\r
422 char *pcSourceFile, *pcDestinationFile;\r
423 portBASE_TYPE xParameterStringLength;\r
424 long lSourceLength, lDestinationLength = 0;\r
425 \r
426         /* Obtain the name of the destination file. */\r
427         pcDestinationFile = ( char * ) FreeRTOS_CLIGetParameter\r
428                                                         (\r
429                                                                 pcCommandString,                /* The command string itself. */\r
430                                                                 2,                                              /* Return the second parameter. */\r
431                                                                 &xParameterStringLength /* Store the parameter string length. */\r
432                                                         );\r
433 \r
434         /* Sanity check something was returned. */\r
435         configASSERT( pcDestinationFile );\r
436 \r
437         /* Obtain the name of the source file. */\r
438         pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter\r
439                                                 (\r
440                                                         pcCommandString,                /* The command string itself. */\r
441                                                         1,                                              /* Return the first parameter. */\r
442                                                         &xParameterStringLength /* Store the parameter string length. */\r
443                                                 );\r
444 \r
445         /* Sanity check something was returned. */\r
446         configASSERT( pcSourceFile );\r
447 \r
448         /* Terminate the string. */\r
449         pcSourceFile[ xParameterStringLength ] = 0x00;\r
450 \r
451         /* See if the source file exists, obtain its length if it does. */\r
452         lSourceLength = f_filelength( pcSourceFile );\r
453 \r
454         if( lSourceLength == 0 )\r
455         {\r
456                 sprintf( pcWriteBuffer, "Source file does not exist" );\r
457         }\r
458         else\r
459         {\r
460                 /* See if the destination file exists. */\r
461                 lDestinationLength = f_filelength( pcDestinationFile );\r
462 \r
463                 if( lDestinationLength != 0 )\r
464                 {\r
465                         sprintf( pcWriteBuffer, "Error: Destination file already exists" );\r
466                 }\r
467         }\r
468 \r
469         /* Continue only if the source file exists and the destination file does\r
470         not exist. */\r
471         if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )\r
472         {\r
473                 if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )\r
474                 {\r
475                         sprintf( pcWriteBuffer, "Copy made" );\r
476                 }\r
477                 else\r
478                 {\r
479                         sprintf( pcWriteBuffer, "Error during copy" );\r
480                 }\r
481         }\r
482 \r
483         strcat( pcWriteBuffer, cliNEW_LINE );\r
484 \r
485         return pdFALSE;\r
486 }\r
487 /*-----------------------------------------------------------*/\r
488 \r
489 static portBASE_TYPE prvPerformCopy(    char *pcSourceFile,\r
490                                                                                 int32_t lSourceFileLength,\r
491                                                                                 char *pcDestinationFile,\r
492                                                                                 char *pxWriteBuffer,\r
493                                                                                 size_t xWriteBufferLen )\r
494 {\r
495 int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;\r
496 F_FILE *pxFile;\r
497 portBASE_TYPE xReturn = pdPASS;\r
498 \r
499         /* NOTE:  Error handling has been omitted for clarity. */\r
500 \r
501         while( lBytesRead < lSourceFileLength )\r
502         {\r
503                 /* How many bytes are left? */\r
504                 lBytesRemaining = lSourceFileLength - lBytesRead;\r
505 \r
506                 /* How many bytes should be read this time around the loop.  Can't\r
507                 read more bytes than will fit into the buffer. */\r
508                 if( lBytesRemaining > ( long ) xWriteBufferLen )\r
509                 {\r
510                         lBytesToRead = ( long ) xWriteBufferLen;\r
511                 }\r
512                 else\r
513                 {\r
514                         lBytesToRead = lBytesRemaining;\r
515                 }\r
516 \r
517                 /* Open the source file, seek past the data that has already been\r
518                 read from the file, read the next block of data, then close the\r
519                 file again so the destination file can be opened. */\r
520                 pxFile = f_open( pcSourceFile, "r" );\r
521                 if( pxFile != NULL )\r
522                 {\r
523                         f_seek( pxFile, lBytesRead, F_SEEK_SET );\r
524                         f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );\r
525                         f_close( pxFile );\r
526                 }\r
527                 else\r
528                 {\r
529                         xReturn = pdFAIL;\r
530                         break;\r
531                 }\r
532 \r
533                 /* Open the destination file and write the block of data to the end of\r
534                 the file. */\r
535                 pxFile = f_open( pcDestinationFile, "a" );\r
536                 if( pxFile != NULL )\r
537                 {\r
538                         f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );\r
539                         f_close( pxFile );\r
540                 }\r
541                 else\r
542                 {\r
543                         xReturn = pdFAIL;\r
544                         break;\r
545                 }\r
546 \r
547                 lBytesRead += lBytesToRead;\r
548         }\r
549 \r
550         return xReturn;\r
551 }\r
552 /*-----------------------------------------------------------*/\r
553 \r
554 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct )\r
555 {\r
556 const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory";\r
557 const char * pcAttrib;\r
558 \r
559         /* Point pcAttrib to a string that describes the file. */\r
560         if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )\r
561         {\r
562                 pcAttrib = pcDirectory;\r
563         }\r
564         else if( pxFindStruct->attr & F_ATTR_READONLY )\r
565         {\r
566                 pcAttrib = pcReadOnlyFile;\r
567         }\r
568         else\r
569         {\r
570                 pcAttrib = pcWritableFile;\r
571         }\r
572 \r
573         /* Create a string that includes the file name, the file size and the\r
574         attributes string. */\r
575         sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, pxFindStruct->filesize );\r
576 }\r