2 * FreeRTOS Kernel V10.0.1
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
29 /* FreeRTOS includes. */
\r
30 #include "FreeRTOS.h"
\r
33 /* Standard includes. */
\r
39 /* FreeRTOS+CLI includes. */
\r
40 #include "FreeRTOS_CLI.h"
\r
42 /* File system includes. */
\r
44 #include "api_mdriver_ram.h"
\r
47 #define snprintf _snprintf
\r
50 #define cliNEW_LINE "\r\n"
\r
52 /*******************************************************************************
\r
53 * See the URL in the comments within main.c for the location of the online
\r
55 ******************************************************************************/
\r
58 * Print out information on a single file.
\r
60 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct );
\r
63 * Copies an existing file into a newly created file.
\r
65 static BaseType_t prvPerformCopy( const char *pcSourceFile,
\r
66 int32_t lSourceFileLength,
\r
67 const char *pcDestinationFile,
\r
68 char *pxWriteBuffer,
\r
69 size_t xWriteBufferLen );
\r
72 * Implements the DIR command.
\r
74 static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
77 * Implements the CD command.
\r
79 static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
82 * Implements the DEL command.
\r
84 static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
87 * Implements the TYPE command.
\r
89 static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
92 * Implements the COPY command.
\r
94 static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString );
\r
96 /* Structure that defines the DIR command line command, which lists all the
\r
97 files in the current directory. */
\r
98 static const CLI_Command_Definition_t xDIR =
\r
100 "dir", /* The command string to type. */
\r
101 "\r\ndir:\r\n Lists the files in the current directory\r\n",
\r
102 prvDIRCommand, /* The function to run. */
\r
103 0 /* No parameters are expected. */
\r
106 /* Structure that defines the CD command line command, which changes the
\r
107 working directory. */
\r
108 static const CLI_Command_Definition_t xCD =
\r
110 "cd", /* The command string to type. */
\r
111 "\r\ncd <dir name>:\r\n Changes the working directory\r\n",
\r
112 prvCDCommand, /* The function to run. */
\r
113 1 /* One parameter is expected. */
\r
116 /* Structure that defines the TYPE command line command, which prints the
\r
117 contents of a file to the console. */
\r
118 static const CLI_Command_Definition_t xTYPE =
\r
120 "type", /* The command string to type. */
\r
121 "\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",
\r
122 prvTYPECommand, /* The function to run. */
\r
123 1 /* One parameter is expected. */
\r
126 /* Structure that defines the DEL command line command, which deletes a file. */
\r
127 static const CLI_Command_Definition_t xDEL =
\r
129 "del", /* The command string to type. */
\r
130 "\r\ndel <filename>:\r\n deletes a file or directory\r\n",
\r
131 prvDELCommand, /* The function to run. */
\r
132 1 /* One parameter is expected. */
\r
135 /* Structure that defines the COPY command line command, which deletes a file. */
\r
136 static const CLI_Command_Definition_t xCOPY =
\r
138 "copy", /* The command string to type. */
\r
139 "\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",
\r
140 prvCOPYCommand, /* The function to run. */
\r
141 2 /* Two parameters are expected. */
\r
145 /*-----------------------------------------------------------*/
\r
147 void vRegisterFileSystemCLICommands( void )
\r
149 /* Register all the command line commands defined immediately above. */
\r
150 FreeRTOS_CLIRegisterCommand( &xDIR );
\r
151 FreeRTOS_CLIRegisterCommand( &xCD );
\r
152 FreeRTOS_CLIRegisterCommand( &xTYPE );
\r
153 FreeRTOS_CLIRegisterCommand( &xDEL );
\r
154 FreeRTOS_CLIRegisterCommand( &xCOPY );
\r
156 /*-----------------------------------------------------------*/
\r
158 static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
160 const char *pcParameter;
\r
161 BaseType_t xParameterStringLength, xReturn = pdTRUE;
\r
162 static F_FILE *pxFile = NULL;
\r
165 size_t xColumns = 50U;
\r
167 /* Ensure there is always a null terminator after each character written. */
\r
168 memset( pcWriteBuffer, 0x00, xWriteBufferLen );
\r
170 /* Ensure the buffer leaves space for the \r\n. */
\r
171 configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
\r
172 xWriteBufferLen -= strlen( cliNEW_LINE );
\r
174 if( xWriteBufferLen < xColumns )
\r
176 /* Ensure the loop that uses xColumns as an end condition does not
\r
177 write off the end of the buffer. */
\r
178 xColumns = xWriteBufferLen;
\r
181 if( pxFile == NULL )
\r
183 /* The file has not been opened yet. Find the file name. */
\r
184 pcParameter = FreeRTOS_CLIGetParameter
\r
186 pcCommandString, /* The command string itself. */
\r
187 1, /* Return the first parameter. */
\r
188 &xParameterStringLength /* Store the parameter string length. */
\r
191 /* Sanity check something was returned. */
\r
192 configASSERT( pcParameter );
\r
194 /* Attempt to open the requested file. */
\r
195 pxFile = f_open( pcParameter, "r" );
\r
198 if( pxFile != NULL )
\r
200 /* Read the next chunk of data from the file. */
\r
201 for( xByte = 0; xByte < xColumns; xByte++ )
\r
203 iChar = f_getc( pxFile );
\r
207 /* No more characters to return. */
\r
214 pcWriteBuffer[ xByte ] = ( char ) iChar;
\r
219 if( pxFile == NULL )
\r
221 /* Either the file was not opened, or all the data from the file has
\r
222 been returned and the file is now closed. */
\r
226 strcat( pcWriteBuffer, cliNEW_LINE );
\r
230 /*-----------------------------------------------------------*/
\r
232 static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
234 const char *pcParameter;
\r
235 BaseType_t xParameterStringLength;
\r
236 unsigned char ucReturned;
\r
237 size_t xStringLength;
\r
239 /* Obtain the parameter string. */
\r
240 pcParameter = FreeRTOS_CLIGetParameter
\r
242 pcCommandString, /* The command string itself. */
\r
243 1, /* Return the first parameter. */
\r
244 &xParameterStringLength /* Store the parameter string length. */
\r
247 /* Sanity check something was returned. */
\r
248 configASSERT( pcParameter );
\r
250 /* Attempt to move to the requested directory. */
\r
251 ucReturned = f_chdir( pcParameter );
\r
253 if( ucReturned == F_NO_ERROR )
\r
255 sprintf( pcWriteBuffer, "In: " );
\r
256 xStringLength = strlen( pcWriteBuffer );
\r
257 f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );
\r
261 sprintf( pcWriteBuffer, "Error" );
\r
264 strcat( pcWriteBuffer, cliNEW_LINE );
\r
268 /*-----------------------------------------------------------*/
\r
270 static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
272 static F_FIND *pxFindStruct = NULL;
\r
273 unsigned char ucReturned;
\r
274 BaseType_t xReturn = pdFALSE;
\r
276 /* This assumes pcWriteBuffer is long enough. */
\r
277 ( void ) pcCommandString;
\r
279 /* Ensure the buffer leaves space for the \r\n. */
\r
280 configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
\r
281 xWriteBufferLen -= strlen( cliNEW_LINE );
\r
283 if( pxFindStruct == NULL )
\r
285 /* This is the first time this function has been executed since the Dir
\r
286 command was run. Create the find structure. */
\r
287 pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );
\r
289 if( pxFindStruct != NULL )
\r
291 ucReturned = f_findfirst( "*.*", pxFindStruct );
\r
293 if( ucReturned == F_NO_ERROR )
\r
295 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
\r
300 snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );
\r
305 snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );
\r
310 /* The find struct has already been created. Find the next file in
\r
312 ucReturned = f_findnext( pxFindStruct );
\r
314 if( ucReturned == F_NO_ERROR )
\r
316 prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
\r
321 /* There are no more files. Free the find structure. */
\r
322 vPortFree( pxFindStruct );
\r
323 pxFindStruct = NULL;
\r
325 /* No string to return. */
\r
326 pcWriteBuffer[ 0 ] = 0x00;
\r
330 strcat( pcWriteBuffer, cliNEW_LINE );
\r
334 /*-----------------------------------------------------------*/
\r
336 static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
338 const char *pcParameter;
\r
339 BaseType_t xParameterStringLength;
\r
340 unsigned char ucReturned;
\r
342 /* This function assumes xWriteBufferLen is large enough! */
\r
343 ( void ) xWriteBufferLen;
\r
345 /* Obtain the parameter string. */
\r
346 pcParameter = FreeRTOS_CLIGetParameter
\r
348 pcCommandString, /* The command string itself. */
\r
349 1, /* Return the first parameter. */
\r
350 &xParameterStringLength /* Store the parameter string length. */
\r
353 /* Sanity check something was returned. */
\r
354 configASSERT( pcParameter );
\r
356 /* Attempt to delete the file. */
\r
357 ucReturned = f_delete( pcParameter );
\r
359 if( ucReturned == F_NO_ERROR )
\r
361 sprintf( pcWriteBuffer, "%s was deleted", pcParameter );
\r
365 sprintf( pcWriteBuffer, "Error" );
\r
368 strcat( pcWriteBuffer, cliNEW_LINE );
\r
372 /*-----------------------------------------------------------*/
\r
374 static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
\r
376 char *pcSourceFile, *pcDestinationFile;
\r
377 BaseType_t xParameterStringLength;
\r
378 long lSourceLength, lDestinationLength = 0;
\r
380 /* Obtain the name of the destination file. */
\r
381 pcDestinationFile = ( char * ) FreeRTOS_CLIGetParameter
\r
383 pcCommandString, /* The command string itself. */
\r
384 2, /* Return the second parameter. */
\r
385 &xParameterStringLength /* Store the parameter string length. */
\r
388 /* Sanity check something was returned. */
\r
389 configASSERT( pcDestinationFile );
\r
391 /* Obtain the name of the source file. */
\r
392 pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter
\r
394 pcCommandString, /* The command string itself. */
\r
395 1, /* Return the first parameter. */
\r
396 &xParameterStringLength /* Store the parameter string length. */
\r
399 /* Sanity check something was returned. */
\r
400 configASSERT( pcSourceFile );
\r
402 /* Terminate the string. */
\r
403 pcSourceFile[ xParameterStringLength ] = 0x00;
\r
405 /* See if the source file exists, obtain its length if it does. */
\r
406 lSourceLength = f_filelength( pcSourceFile );
\r
408 if( lSourceLength == 0 )
\r
410 sprintf( pcWriteBuffer, "Source file does not exist" );
\r
414 /* See if the destination file exists. */
\r
415 lDestinationLength = f_filelength( pcDestinationFile );
\r
417 if( lDestinationLength != 0 )
\r
419 sprintf( pcWriteBuffer, "Error: Destination file already exists" );
\r
423 /* Continue only if the source file exists and the destination file does
\r
425 if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )
\r
427 if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )
\r
429 sprintf( pcWriteBuffer, "Copy made" );
\r
433 sprintf( pcWriteBuffer, "Error during copy" );
\r
437 strcat( pcWriteBuffer, cliNEW_LINE );
\r
441 /*-----------------------------------------------------------*/
\r
443 static BaseType_t prvPerformCopy( const char *pcSourceFile,
\r
444 int32_t lSourceFileLength,
\r
445 const char *pcDestinationFile,
\r
446 char *pxWriteBuffer,
\r
447 size_t xWriteBufferLen )
\r
449 int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;
\r
451 BaseType_t xReturn = pdPASS;
\r
453 /* NOTE: Error handling has been omitted for clarity. */
\r
455 while( lBytesRead < lSourceFileLength )
\r
457 /* How many bytes are left? */
\r
458 lBytesRemaining = lSourceFileLength - lBytesRead;
\r
460 /* How many bytes should be read this time around the loop. Can't
\r
461 read more bytes than will fit into the buffer. */
\r
462 if( lBytesRemaining > ( long ) xWriteBufferLen )
\r
464 lBytesToRead = ( long ) xWriteBufferLen;
\r
468 lBytesToRead = lBytesRemaining;
\r
471 /* Open the source file, seek past the data that has already been
\r
472 read from the file, read the next block of data, then close the
\r
473 file again so the destination file can be opened. */
\r
474 pxFile = f_open( pcSourceFile, "r" );
\r
475 if( pxFile != NULL )
\r
477 f_seek( pxFile, lBytesRead, F_SEEK_SET );
\r
478 f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );
\r
487 /* Open the destination file and write the block of data to the end of
\r
489 pxFile = f_open( pcDestinationFile, "a" );
\r
490 if( pxFile != NULL )
\r
492 f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );
\r
501 lBytesRead += lBytesToRead;
\r
506 /*-----------------------------------------------------------*/
\r
508 static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct )
\r
510 const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory";
\r
511 const char * pcAttrib;
\r
513 /* Point pcAttrib to a string that describes the file. */
\r
514 if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )
\r
516 pcAttrib = pcDirectory;
\r
518 else if( pxFindStruct->attr & F_ATTR_READONLY )
\r
520 pcAttrib = pcReadOnlyFile;
\r
524 pcAttrib = pcWritableFile;
\r
527 /* Create a string that includes the file name, the file size and the
\r
528 attributes string. */
\r
529 sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize );
\r