]> git.sur5r.net Git - freertos/blob
e99e57528e5c2f1205c651332f07e07607e7f0a7
[freertos] /
1 /*\r
2     FreeRTOS V7.6.0 - 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 #include <string.h>\r
85 \r
86 /* FreeRTOS+CLI includes. */\r
87 #include "FreeRTOS_CLI.h"\r
88 \r
89 /* File system includes. */\r
90 #include "fat_sl.h"\r
91 #include "api_mdriver_ram.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 /* 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         ( const int8_t * const ) "dir", /* The command string to type. */\r
148         ( const int8_t * const ) "\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         ( const int8_t * const ) "cd", /* The command string to type. */\r
158         ( const int8_t * const ) "\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         ( const int8_t * const ) "type", /* The command string to type. */\r
168         ( const int8_t * const ) "\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         ( const int8_t * const ) "del", /* The command string to type. */\r
177         ( const int8_t * const ) "\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         ( const int8_t * const ) "copy", /* The command string to type. */\r
186         ( const int8_t * const ) "\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( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )\r
205 {\r
206 int8_t *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 = ( int8_t * ) 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( ( const char * ) 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 ] = ( int8_t ) 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( ( char * ) pcWriteBuffer, cliNEW_LINE );\r
273 \r
274         return xReturn;\r
275 }\r
276 /*-----------------------------------------------------------*/\r
277 \r
278 static portBASE_TYPE prvCDCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )\r
279 {\r
280 int8_t *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 = ( int8_t * ) 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( ( char * ) pcParameter );\r
298 \r
299         if( ucReturned == F_NO_ERROR )\r
300         {\r
301                 sprintf( ( char * ) pcWriteBuffer, "In: " );\r
302                 xStringLength = strlen( ( const char * ) pcWriteBuffer );\r
303                 f_getcwd( ( char * ) &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );\r
304         }\r
305         else\r
306         {\r
307                 sprintf( ( char * ) pcWriteBuffer, "Error" );\r
308         }\r
309 \r
310         strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );\r
311 \r
312         return pdFALSE;\r
313 }\r
314 /*-----------------------------------------------------------*/\r
315 \r
316 static portBASE_TYPE prvDIRCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *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( ( char * ) pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );\r
347                         }\r
348                 }\r
349                 else\r
350                 {\r
351                         snprintf( ( char * ) 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( ( char * ) pcWriteBuffer, cliNEW_LINE );\r
377 \r
378         return xReturn;\r
379 }\r
380 /*-----------------------------------------------------------*/\r
381 \r
382 static portBASE_TYPE prvDELCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )\r
383 {\r
384 int8_t *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 = ( int8_t * ) 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( ( const char * ) pcParameter );\r
404 \r
405         if( ucReturned == F_NO_ERROR )\r
406         {\r
407                 sprintf( ( char * ) pcWriteBuffer, "%s was deleted", pcParameter );\r
408         }\r
409         else\r
410         {\r
411                 sprintf( ( char * ) pcWriteBuffer, "Error" );\r
412         }\r
413 \r
414         strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );\r
415 \r
416         return pdFALSE;\r
417 }\r
418 /*-----------------------------------------------------------*/\r
419 \r
420 static portBASE_TYPE prvCOPYCommand( int8_t *pcWriteBuffer, size_t xWriteBufferLen, const int8_t *pcCommandString )\r
421 {\r
422 int8_t *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 = ( int8_t * ) 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 = ( int8_t * ) 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( ( const char * ) pcSourceFile );\r
453 \r
454         if( lSourceLength == 0 )\r
455         {\r
456                 sprintf( ( char * ) 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( ( const char * ) pcDestinationFile );\r
462 \r
463                 if( lDestinationLength != 0 )\r
464                 {\r
465                         sprintf( ( char * ) 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( ( char * ) pcWriteBuffer, "Copy made" );\r
476                 }\r
477                 else\r
478                 {\r
479                         sprintf( ( char * ) pcWriteBuffer, "Error during copy" );\r
480                 }\r
481         }\r
482 \r
483         strcat( ( char * ) pcWriteBuffer, cliNEW_LINE );\r
484 \r
485         return pdFALSE;\r
486 }\r
487 /*-----------------------------------------------------------*/\r
488 \r
489 static portBASE_TYPE prvPerformCopy( int8_t *pcSourceFile,\r
490                                                         int32_t lSourceFileLength,\r
491                                                         int8_t *pcDestinationFile,\r
492                                                         int8_t *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( ( const char * ) 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( ( const char * ) 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( int8_t *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( ( char * ) pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize );\r
576 }\r