2 FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
67 /* FreeRTOS includes. */
\r
68 #include "FreeRTOS.h"
\r
71 /* Standard includes. */
\r
77 /* FreeRTOS+CLI includes. */
\r
78 #include "FreeRTOS_CLI.h"
\r
80 /* File system includes. */
\r
82 #include "api_mdriver_ram.h"
\r
85 #define snprintf _snprintf
\r
88 #define cliNEW_LINE "\r\n"
\r
90 /*******************************************************************************
\r
91 * See the URL in the comments within main.c for the location of the online
\r
93 ******************************************************************************/
\r
96 * Print out information on a single file.
\r
98 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct );
\r
101 * Copies an existing file into a newly created file.
\r
103 static BaseType_t prvPerformCopy( const char *pcSourceFile,
\r
104 int32_t lSourceFileLength,
\r
105 const char *pcDestinationFile,
\r
106 char *pxWriteBuffer,
\r
107 size_t xWriteBufferLen );
\r
110 * Implements the DIR command.
\r
112 static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
115 * Implements the CD command.
\r
117 static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
120 * Implements the DEL command.
\r
122 static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
125 * Implements the TYPE command.
\r
127 static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
130 * Implements the COPY command.
\r
132 static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
134 /* Structure that defines the DIR command line command, which lists all the
\r
135 files in the current directory. */
\r
136 static const CLI_Command_Definition_t xDIR =
\r
138 "dir", /* The command string to type. */
\r
139 "\r\ndir:\r\n Lists the files in the current directory\r\n",
\r
140 prvDIRCommand, /* The function to run. */
\r
141 0 /* No parameters are expected. */
\r
144 /* Structure that defines the CD command line command, which changes the
\r
145 working directory. */
\r
146 static const CLI_Command_Definition_t xCD =
\r
148 "cd", /* The command string to type. */
\r
149 "\r\ncd <dir name>:\r\n Changes the working directory\r\n",
\r
150 prvCDCommand, /* The function to run. */
\r
151 1 /* One parameter is expected. */
\r
154 /* Structure that defines the TYPE command line command, which prints the
\r
155 contents of a file to the console. */
\r
156 static const CLI_Command_Definition_t xTYPE =
\r
158 "type", /* The command string to type. */
\r
159 "\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",
\r
160 prvTYPECommand, /* The function to run. */
\r
161 1 /* One parameter is expected. */
\r
164 /* Structure that defines the DEL command line command, which deletes a file. */
\r
165 static const CLI_Command_Definition_t xDEL =
\r
167 "del", /* The command string to type. */
\r
168 "\r\ndel <filename>:\r\n deletes a file or directory\r\n",
\r
169 prvDELCommand, /* The function to run. */
\r
170 1 /* One parameter is expected. */
\r
173 /* Structure that defines the COPY command line command, which deletes a file. */
\r
174 static const CLI_Command_Definition_t xCOPY =
\r
176 "copy", /* The command string to type. */
\r
177 "\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",
\r
178 prvCOPYCommand, /* The function to run. */
\r
179 2 /* Two parameters are expected. */
\r
183 /*-----------------------------------------------------------*/
\r
185 void vRegisterFileSystemCLICommands( void )
\r
187 /* Register all the command line commands defined immediately above. */
\r
188 FreeRTOS_CLIRegisterCommand( &xDIR );
\r
189 FreeRTOS_CLIRegisterCommand( &xCD );
\r
190 FreeRTOS_CLIRegisterCommand( &xTYPE );
\r
191 FreeRTOS_CLIRegisterCommand( &xDEL );
\r
192 FreeRTOS_CLIRegisterCommand( &xCOPY );
\r
194 /*-----------------------------------------------------------*/
\r
196 static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
198 const char *pcParameter;
\r
199 BaseType_t xParameterStringLength, xReturn = pdTRUE;
\r
200 static F_FILE *pxFile = NULL;
\r
203 size_t xColumns = 50U;
\r
205 /* Ensure there is always a null terminator after each character written. */
\r
206 memset( pcWriteBuffer, 0x00, xWriteBufferLen );
\r
208 /* Ensure the buffer leaves space for the \r\n. */
\r
209 configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
\r
210 xWriteBufferLen -= strlen( cliNEW_LINE );
\r
212 if( xWriteBufferLen < xColumns )
\r
214 /* Ensure the loop that uses xColumns as an end condition does not
\r
215 write off the end of the buffer. */
\r
216 xColumns = xWriteBufferLen;
\r
219 if( pxFile == NULL )
\r
221 /* The file has not been opened yet. Find the file name. */
\r
222 pcParameter = FreeRTOS_CLIGetParameter
\r
224 pcCommandString, /* The command string itself. */
\r
225 1, /* Return the first parameter. */
\r
226 &xParameterStringLength /* Store the parameter string length. */
\r
229 /* Sanity check something was returned. */
\r
230 configASSERT( pcParameter );
\r
232 /* Attempt to open the requested file. */
\r
233 pxFile = f_open( pcParameter, "r" );
\r
236 if( pxFile != NULL )
\r
238 /* Read the next chunk of data from the file. */
\r
239 for( xByte = 0; xByte < xColumns; xByte++ )
\r
241 iChar = f_getc( pxFile );
\r
245 /* No more characters to return. */
\r
252 pcWriteBuffer[ xByte ] = ( char ) iChar;
\r
257 if( pxFile == NULL )
\r
259 /* Either the file was not opened, or all the data from the file has
\r
260 been returned and the file is now closed. */
\r
264 strcat( pcWriteBuffer, cliNEW_LINE );
\r
268 /*-----------------------------------------------------------*/
\r
270 static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
272 const char *pcParameter;
\r
273 BaseType_t xParameterStringLength;
\r
274 unsigned char ucReturned;
\r
275 size_t xStringLength;
\r
277 /* Obtain the parameter string. */
\r
278 pcParameter = FreeRTOS_CLIGetParameter
\r
280 pcCommandString, /* The command string itself. */
\r
281 1, /* Return the first parameter. */
\r
282 &xParameterStringLength /* Store the parameter string length. */
\r
285 /* Sanity check something was returned. */
\r
286 configASSERT( pcParameter );
\r
288 /* Attempt to move to the requested directory. */
\r
289 ucReturned = f_chdir( pcParameter );
\r
291 if( ucReturned == F_NO_ERROR )
\r
293 sprintf( pcWriteBuffer, "In: " );
\r
294 xStringLength = strlen( pcWriteBuffer );
\r
295 f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );
\r
299 sprintf( pcWriteBuffer, "Error" );
\r
302 strcat( pcWriteBuffer, cliNEW_LINE );
\r
306 /*-----------------------------------------------------------*/
\r
308 static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
310 static F_FIND *pxFindStruct = NULL;
\r
311 unsigned char ucReturned;
\r
312 BaseType_t xReturn = pdFALSE;
\r
314 /* This assumes pcWriteBuffer is long enough. */
\r
315 ( void ) pcCommandString;
\r
317 /* Ensure the buffer leaves space for the \r\n. */
\r
318 configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
\r
319 xWriteBufferLen -= strlen( cliNEW_LINE );
\r
321 if( pxFindStruct == NULL )
\r
323 /* This is the first time this function has been executed since the Dir
\r
324 command was run. Create the find structure. */
\r
325 pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );
\r
327 if( pxFindStruct != NULL )
\r
329 ucReturned = f_findfirst( "*.*", pxFindStruct );
\r
331 if( ucReturned == F_NO_ERROR )
\r
333 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
\r
338 snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );
\r
343 snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );
\r
348 /* The find struct has already been created. Find the next file in
\r
350 ucReturned = f_findnext( pxFindStruct );
\r
352 if( ucReturned == F_NO_ERROR )
\r
354 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
\r
359 /* There are no more files. Free the find structure. */
\r
360 vPortFree( pxFindStruct );
\r
361 pxFindStruct = NULL;
\r
363 /* No string to return. */
\r
364 pcWriteBuffer[ 0 ] = 0x00;
\r
368 strcat( pcWriteBuffer, cliNEW_LINE );
\r
372 /*-----------------------------------------------------------*/
\r
374 static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
376 const char *pcParameter;
\r
377 BaseType_t xParameterStringLength;
\r
378 unsigned char ucReturned;
\r
380 /* This function assumes xWriteBufferLen is large enough! */
\r
381 ( void ) xWriteBufferLen;
\r
383 /* Obtain the parameter string. */
\r
384 pcParameter = FreeRTOS_CLIGetParameter
\r
386 pcCommandString, /* The command string itself. */
\r
387 1, /* Return the first parameter. */
\r
388 &xParameterStringLength /* Store the parameter string length. */
\r
391 /* Sanity check something was returned. */
\r
392 configASSERT( pcParameter );
\r
394 /* Attempt to delete the file. */
\r
395 ucReturned = f_delete( pcParameter );
\r
397 if( ucReturned == F_NO_ERROR )
\r
399 sprintf( pcWriteBuffer, "%s was deleted", pcParameter );
\r
403 sprintf( pcWriteBuffer, "Error" );
\r
406 strcat( pcWriteBuffer, cliNEW_LINE );
\r
410 /*-----------------------------------------------------------*/
\r
412 static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
414 char *pcSourceFile, *pcDestinationFile;
\r
415 BaseType_t xParameterStringLength;
\r
416 long lSourceLength, lDestinationLength = 0;
\r
418 /* Obtain the name of the destination file. */
\r
419 pcDestinationFile = ( char * ) FreeRTOS_CLIGetParameter
\r
421 pcCommandString, /* The command string itself. */
\r
422 2, /* Return the second parameter. */
\r
423 &xParameterStringLength /* Store the parameter string length. */
\r
426 /* Sanity check something was returned. */
\r
427 configASSERT( pcDestinationFile );
\r
429 /* Obtain the name of the source file. */
\r
430 pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter
\r
432 pcCommandString, /* The command string itself. */
\r
433 1, /* Return the first parameter. */
\r
434 &xParameterStringLength /* Store the parameter string length. */
\r
437 /* Sanity check something was returned. */
\r
438 configASSERT( pcSourceFile );
\r
440 /* Terminate the string. */
\r
441 pcSourceFile[ xParameterStringLength ] = 0x00;
\r
443 /* See if the source file exists, obtain its length if it does. */
\r
444 lSourceLength = f_filelength( pcSourceFile );
\r
446 if( lSourceLength == 0 )
\r
448 sprintf( pcWriteBuffer, "Source file does not exist" );
\r
452 /* See if the destination file exists. */
\r
453 lDestinationLength = f_filelength( pcDestinationFile );
\r
455 if( lDestinationLength != 0 )
\r
457 sprintf( pcWriteBuffer, "Error: Destination file already exists" );
\r
461 /* Continue only if the source file exists and the destination file does
\r
463 if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )
\r
465 if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )
\r
467 sprintf( pcWriteBuffer, "Copy made" );
\r
471 sprintf( pcWriteBuffer, "Error during copy" );
\r
475 strcat( pcWriteBuffer, cliNEW_LINE );
\r
479 /*-----------------------------------------------------------*/
\r
481 static BaseType_t prvPerformCopy( const char *pcSourceFile,
\r
482 int32_t lSourceFileLength,
\r
483 const char *pcDestinationFile,
\r
484 char *pxWriteBuffer,
\r
485 size_t xWriteBufferLen )
\r
487 int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;
\r
489 BaseType_t xReturn = pdPASS;
\r
491 /* NOTE: Error handling has been omitted for clarity. */
\r
493 while( lBytesRead < lSourceFileLength )
\r
495 /* How many bytes are left? */
\r
496 lBytesRemaining = lSourceFileLength - lBytesRead;
\r
498 /* How many bytes should be read this time around the loop. Can't
\r
499 read more bytes than will fit into the buffer. */
\r
500 if( lBytesRemaining > ( long ) xWriteBufferLen )
\r
502 lBytesToRead = ( long ) xWriteBufferLen;
\r
506 lBytesToRead = lBytesRemaining;
\r
509 /* Open the source file, seek past the data that has already been
\r
510 read from the file, read the next block of data, then close the
\r
511 file again so the destination file can be opened. */
\r
512 pxFile = f_open( pcSourceFile, "r" );
\r
513 if( pxFile != NULL )
\r
515 f_seek( pxFile, lBytesRead, F_SEEK_SET );
\r
516 f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );
\r
525 /* Open the destination file and write the block of data to the end of
\r
527 pxFile = f_open( pcDestinationFile, "a" );
\r
528 if( pxFile != NULL )
\r
530 f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );
\r
539 lBytesRead += lBytesToRead;
\r
544 /*-----------------------------------------------------------*/
\r
546 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct )
\r
548 const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory";
\r
549 const char * pcAttrib;
\r
551 /* Point pcAttrib to a string that describes the file. */
\r
552 if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )
\r
554 pcAttrib = pcDirectory;
\r
556 else if( pxFindStruct->attr & F_ATTR_READONLY )
\r
558 pcAttrib = pcReadOnlyFile;
\r
562 pcAttrib = pcWritableFile;
\r
565 /* Create a string that includes the file name, the file size and the
\r
566 attributes string. */
\r
567 sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize );
\r