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