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