Lightweight SD card FAT file system. Originaled by chan http://elm-chan.org/fsw/ff/00index_p.html

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pff.cpp Source File

pff.cpp

00001 /*----------------------------------------------------------------------------/
00002 /  Petit FatFs - FAT file system module  R0.02a                (C)ChaN, 2010
00003 /-----------------------------------------------------------------------------/
00004 / Petit FatFs module is an open source software to implement FAT file system to
00005 / small embedded systems. This is a free software and is opened for education,
00006 / research and commercial developments under license policy of following trems.
00007 /
00008 /  Copyright (C) 2010, ChaN, all right reserved.
00009 /
00010 / * The Petit FatFs module is a free software and there is NO WARRANTY.
00011 / * No restriction on use. You can use, modify and redistribute it for
00012 /   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
00013 / * Redistributions of source code must retain the above copyright notice.
00014 /
00015 /-----------------------------------------------------------------------------/
00016 / Jun 15,'09  R0.01a  First release. (Branched from FatFs R0.07b.)
00017 /
00018 / Dec 14,'09  R0.02   Added multiple code page support.
00019 /                     Added write funciton.
00020 /                     Changed stream read mode interface.
00021 / Dec 07,'10  R0.02a  Added some configuration options.
00022 /                     Fixed fails to open objects with DBCS character.
00023 /----------------------------------------------------------------------------*/
00024 
00025 #include "pff.h"        /* Petit FatFs configurations and declarations */
00026 #include "diskio.h"     /* Declarations of low level disk I/O functions */
00027 
00028 
00029 /*--------------------------------------------------------------------------
00030 
00031    Module Private Definitions
00032 
00033 ---------------------------------------------------------------------------*/
00034 
00035 
00036 #if _FS_FAT32
00037 #define LD_CLUST(dir)   (((DWORD)LD_WORD(dir+PFFDIR_FstClusHI)<<16) | LD_WORD(dir+PFFDIR_FstClusLO))
00038 #else
00039 #define LD_CLUST(dir)   LD_WORD(dir+PFFDIR_FstClusLO)
00040 #endif
00041 
00042 
00043 /*--------------------------------------------------------*/
00044 /* DBCS code ranges and SBCS extend char conversion table */
00045 
00046 #if _CODE_PAGE == 932   /* Japanese Shift-JIS */
00047 #define _DF1S   0x81    /* DBC 1st byte range 1 start */
00048 #define _DF1E   0x9F    /* DBC 1st byte range 1 end */
00049 #define _DF2S   0xE0    /* DBC 1st byte range 2 start */
00050 #define _DF2E   0xFC    /* DBC 1st byte range 2 end */
00051 #define _DS1S   0x40    /* DBC 2nd byte range 1 start */
00052 #define _DS1E   0x7E    /* DBC 2nd byte range 1 end */
00053 #define _DS2S   0x80    /* DBC 2nd byte range 2 start */
00054 #define _DS2E   0xFC    /* DBC 2nd byte range 2 end */
00055 
00056 #elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
00057 #define _DF1S   0x81
00058 #define _DF1E   0xFE
00059 #define _DS1S   0x40
00060 #define _DS1E   0x7E
00061 #define _DS2S   0x80
00062 #define _DS2E   0xFE
00063 
00064 #elif _CODE_PAGE == 949 /* Korean */
00065 #define _DF1S   0x81
00066 #define _DF1E   0xFE
00067 #define _DS1S   0x41
00068 #define _DS1E   0x5A
00069 #define _DS2S   0x61
00070 #define _DS2E   0x7A
00071 #define _DS3S   0x81
00072 #define _DS3E   0xFE
00073 
00074 #elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
00075 #define _DF1S   0x81
00076 #define _DF1E   0xFE
00077 #define _DS1S   0x40
00078 #define _DS1E   0x7E
00079 #define _DS2S   0xA1
00080 #define _DS2E   0xFE
00081 
00082 #elif _CODE_PAGE == 437 /* U.S. (OEM) */
00083 #define _DF1S   0
00084 #define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00085                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00086                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00087                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00088 
00089 #elif _CODE_PAGE == 720 /* Arabic (OEM) */
00090 #define _DF1S   0
00091 #define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00092                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00093                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00094                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00095 
00096 #elif _CODE_PAGE == 737 /* Greek (OEM) */
00097 #define _DF1S   0
00098 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
00099                 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00100                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00101                 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00102 
00103 #elif _CODE_PAGE == 775 /* Baltic (OEM) */
00104 #define _DF1S   0
00105 #define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
00106                 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00107                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00108                 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00109 
00110 #elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
00111 #define _DF1S   0
00112 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
00113                 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00114                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00115                 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00116 
00117 #elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
00118 #define _DF1S   0
00119 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
00120                 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
00121                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00122                 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
00123 
00124 #elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
00125 #define _DF1S   0
00126 #define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
00127                 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
00128                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
00129                 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
00130 
00131 #elif _CODE_PAGE == 857 /* Turkish (OEM) */
00132 #define _DF1S   0
00133 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
00134                 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00135                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00136                 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00137 
00138 #elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
00139 #define _DF1S   0
00140 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
00141                 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00142                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00143                 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00144 
00145 #elif _CODE_PAGE == 862 /* Hebrew (OEM) */
00146 #define _DF1S   0
00147 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00148                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00149                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00150                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00151 
00152 #elif _CODE_PAGE == 866 /* Russian (OEM) */
00153 #define _DF1S   0
00154 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00155                 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00156                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00157                 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00158 
00159 #elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
00160 #define _DF1S   0
00161 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00162                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00163                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00164                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00165 
00166 #elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
00167 #define _DF1S   0
00168 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
00169                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
00170                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00171                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
00172 
00173 #elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
00174 #define _DF1S   0
00175 #define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
00176                 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
00177                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00178                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
00179 
00180 #elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
00181 #define _DF1S   0
00182 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
00183                 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00184                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00185                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
00186 
00187 #elif _CODE_PAGE == 1253 /* Greek (Windows) */
00188 #define _DF1S   0
00189 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00190                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00191                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
00192                 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
00193 
00194 #elif _CODE_PAGE == 1254 /* Turkish (Windows) */
00195 #define _DF1S   0
00196 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
00197                 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00198                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00199                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
00200 
00201 #elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
00202 #define _DF1S   0
00203 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00204                 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00205                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00206                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
00207 
00208 #elif _CODE_PAGE == 1256 /* Arabic (Windows) */
00209 #define _DF1S   0
00210 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
00211                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00212                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00213                 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
00214 
00215 #elif _CODE_PAGE == 1257 /* Baltic (Windows) */
00216 #define _DF1S   0
00217 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
00218                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
00219                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00220                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
00221 
00222 #elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
00223 #define _DF1S   0
00224 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
00225                 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
00226                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
00227                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
00228 
00229 #elif _CODE_PAGE == 1   /* ASCII (for only non-LFN cfg) */
00230 #define _DF1S   0
00231 
00232 #else
00233 #error Unknown code page
00234 
00235 #endif
00236 
00237 
00238 
00239 /* Character code support macros */
00240 
00241 #define IsUpper(c)  (((c)>='A')&&((c)<='Z'))
00242 #define IsLower(c)  (((c)>='a')&&((c)<='z'))
00243 
00244 #if _DF1S       /* DBCS configuration */
00245 
00246 #ifdef _DF2S    /* Two 1st byte areas */
00247 #define IsDBCS1(c)  (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
00248 #else           /* One 1st byte area */
00249 #define IsDBCS1(c)  ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
00250 #endif
00251 
00252 #ifdef _DS3S    /* Three 2nd byte areas */
00253 #define IsDBCS2(c)  (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
00254 #else           /* Two 2nd byte areas */
00255 #define IsDBCS2(c)  (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
00256 #endif
00257 
00258 #else           /* SBCS configuration */
00259 
00260 #define IsDBCS1(c)  0
00261 #define IsDBCS2(c)  0
00262 
00263 #endif /* _DF1S */
00264 
00265 
00266 /* FatFs refers the members in the FAT structures with byte offset instead
00267 / of structure member because there are incompatibility of the packing option
00268 / between various compilers. */
00269 
00270 #define BS_jmpBoot          0
00271 #define BS_OEMName          3
00272 #define BPB_BytsPerSec      11
00273 #define BPB_SecPerClus      13
00274 #define BPB_RsvdSecCnt      14
00275 #define BPB_NumFATs         16
00276 #define BPB_RootEntCnt      17
00277 #define BPB_TotSec16        19
00278 #define BPB_Media           21
00279 #define BPB_FATSz16         22
00280 #define BPB_SecPerTrk       24
00281 #define BPB_NumHeads        26
00282 #define BPB_HiddSec         28
00283 #define BPB_TotSec32        32
00284 #define BS_55AA             510
00285 
00286 #define BS_DrvNum           36
00287 #define BS_BootSig          38
00288 #define BS_VolID            39
00289 #define BS_VolLab           43
00290 #define BS_FilSysType       54
00291 
00292 #define BPB_FATSz32         36
00293 #define BPB_ExtFlags        40
00294 #define BPB_FSVer           42
00295 #define BPB_RootClus        44
00296 #define BPB_FSInfo          48
00297 #define BPB_BkBootSec       50
00298 #define BS_DrvNum32         64
00299 #define BS_BootSig32        66
00300 #define BS_VolID32          67
00301 #define BS_VolLab32         71
00302 #define BS_FilSysType32     82
00303 
00304 #define MBR_Table           446
00305 
00306 #define PFFDIR_Name         0
00307 #define PFFDIR_Attr         11
00308 #define PFFDIR_NTres            12
00309 #define PFFDIR_CrtTime          14
00310 #define PFFDIR_CrtDate          16
00311 #define PFFDIR_FstClusHI        20
00312 #define PFFDIR_WrtTime          22
00313 #define PFFDIR_WrtDate          24
00314 #define PFFDIR_FstClusLO        26
00315 #define PFFDIR_FileSize     28
00316 
00317 
00318 
00319 /*--------------------------------------------------------------------------
00320 
00321    Private Functions
00322 
00323 ---------------------------------------------------------------------------*/
00324 
00325 
00326 static
00327 FATFS *FatFs;   /* Pointer to the file system object (logical drive) */
00328 
00329 
00330 /* Fill memory */
00331 static
00332 void mem_set (void* dst, int val, int cnt) {
00333     char *d = (char*)dst;
00334     while (cnt--) *d++ = (char)val;
00335 }
00336 
00337 /* Compare memory to memory */
00338 static
00339 int mem_cmp (const void* dst, const void* src, int cnt) {
00340     const char *d = (const char *)dst, *s = (const char *)src;
00341     int r = 0;
00342     while (cnt-- && (r = *d++ - *s++) == 0) ;
00343     return r;
00344 }
00345 
00346 
00347 
00348 /*-----------------------------------------------------------------------*/
00349 /* FAT access - Read value of a FAT entry                                */
00350 /*-----------------------------------------------------------------------*/
00351 
00352 static
00353 CLUST get_fat ( /* 1:IO error, Else:Cluster status */
00354     CLUST clst  /* Cluster# to get the link information */
00355 )
00356 {
00357     WORD wc, bc, ofs;
00358     BYTE buf[4];
00359     FATFS *fs = FatFs;
00360 
00361 
00362     if (clst < 2 || clst >= fs->n_fatent)   /* Range check */
00363         return 1;
00364 
00365     switch (fs->fs_type) {
00366 #if _FS_FAT12
00367     case FS_FAT12 :
00368         bc = (WORD)clst; bc += bc / 2;
00369         ofs = bc % 512; bc /= 512;
00370         if (ofs != 511) {
00371             if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;
00372         } else {
00373             if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;
00374             if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;
00375         }
00376         wc = LD_WORD(buf);
00377         return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
00378 #endif
00379     case FS_FAT16 :
00380         if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break;
00381         return LD_WORD(buf);
00382 #if _FS_FAT32
00383     case FS_FAT32 :
00384         if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break;
00385         return LD_DWORD(buf) & 0x0FFFFFFF;
00386 #endif
00387     }
00388 
00389     return 1;   /* An error occured at the disk I/O layer */
00390 }
00391 
00392 
00393 
00394 
00395 /*-----------------------------------------------------------------------*/
00396 /* Get sector# from cluster#                                             */
00397 /*-----------------------------------------------------------------------*/
00398 
00399 static
00400 DWORD clust2sect (  /* !=0: Sector number, 0: Failed - invalid cluster# */
00401     CLUST clst      /* Cluster# to be converted */
00402 )
00403 {
00404     FATFS *fs = FatFs;
00405 
00406 
00407     clst -= 2;
00408     if (clst >= (fs->n_fatent - 2)) return 0;       /* Invalid cluster# */
00409     return (DWORD)clst * fs->csize + fs->database;
00410 }
00411 
00412 
00413 
00414 
00415 /*-----------------------------------------------------------------------*/
00416 /* Directory handling - Rewind directory index                           */
00417 /*-----------------------------------------------------------------------*/
00418 
00419 static
00420 FRESULT dir_rewind (
00421     PFFDIR *dj          /* Pointer to directory object */
00422 )
00423 {
00424     CLUST clst;
00425     FATFS *fs = FatFs;
00426 
00427 
00428     dj->index = 0;
00429     clst = dj->sclust;
00430     if (clst == 1 || clst >= fs->n_fatent)  /* Check start cluster range */
00431         return FR_DISK_ERR;
00432     if (_FS_FAT32 && !clst && fs->fs_type == FS_FAT32)  /* Replace cluster# 0 with root cluster# if in FAT32 */
00433         clst = (CLUST)fs->dirbase;
00434     dj->clust = clst;                       /* Current cluster */
00435     dj->sect = clst ? clust2sect(clst) : fs->dirbase;   /* Current sector */
00436 
00437     return FR_OK;   /* Seek succeeded */
00438 }
00439 
00440 
00441 
00442 
00443 /*-----------------------------------------------------------------------*/
00444 /* Directory handling - Move directory index next                        */
00445 /*-----------------------------------------------------------------------*/
00446 
00447 static
00448 FRESULT dir_next (  /* FR_OK:Succeeded, FR_NO_FILE:End of table */
00449     PFFDIR *dj          /* Pointer to directory object */
00450 )
00451 {
00452     CLUST clst;
00453     WORD i;
00454     FATFS *fs = FatFs;
00455 
00456 
00457     i = dj->index + 1;
00458     if (!i || !dj->sect)    /* Report EOT when index has reached 65535 */
00459         return FR_NO_FILE;
00460 
00461     if (!(i % 16)) {        /* Sector changed? */
00462         dj->sect++;         /* Next sector */
00463 
00464         if (dj->clust == 0) {   /* Static table */
00465             if (i >= fs->n_rootdir) /* Report EOT when end of table */
00466                 return FR_NO_FILE;
00467         }
00468         else {                  /* Dynamic table */
00469             if (((i / 16) & (fs->csize-1)) == 0) {  /* Cluster changed? */
00470                 clst = get_fat(dj->clust);      /* Get next cluster */
00471                 if (clst <= 1) return FR_DISK_ERR;
00472                 if (clst >= fs->n_fatent)       /* When it reached end of dynamic table */
00473                     return FR_NO_FILE;          /* Report EOT */
00474                 dj->clust = clst;               /* Initialize data for new cluster */
00475                 dj->sect = clust2sect(clst);
00476             }
00477         }
00478     }
00479 
00480     dj->index = i;
00481 
00482     return FR_OK;
00483 }
00484 
00485 
00486 
00487 
00488 /*-----------------------------------------------------------------------*/
00489 /* Directory handling - Find an object in the directory                  */
00490 /*-----------------------------------------------------------------------*/
00491 
00492 static
00493 FRESULT dir_find (
00494     PFFDIR *dj,     /* Pointer to the directory object linked to the file name */
00495     BYTE *dir       /* 32-byte working buffer */
00496 )
00497 {
00498     FRESULT res;
00499     BYTE c;
00500 
00501 
00502     res = dir_rewind(dj);           /* Rewind directory object */
00503     if (res != FR_OK) return res;
00504 
00505     do {
00506         res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)  /* Read an entry */
00507             ? FR_DISK_ERR : FR_OK;
00508         if (res != FR_OK) break;
00509         c = dir[PFFDIR_Name];   /* First character */
00510         if (c == 0) { res = FR_NO_FILE; break; }    /* Reached to end of table */
00511         if (!(dir[PFFDIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
00512             break;
00513         res = dir_next(dj);                 /* Next entry */
00514     } while (res == FR_OK);
00515 
00516     return res;
00517 }
00518 
00519 
00520 
00521 
00522 /*-----------------------------------------------------------------------*/
00523 /* Read an object from the directory                                     */
00524 /*-----------------------------------------------------------------------*/
00525 #if _USE_DIR
00526 static
00527 FRESULT dir_read (
00528     PFFDIR *dj,     /* Pointer to the directory object to store read object name */
00529     BYTE *dir       /* 32-byte working buffer */
00530 )
00531 {
00532     FRESULT res;
00533     BYTE a, c;
00534 
00535 
00536     res = FR_NO_FILE;
00537     while (dj->sect) {
00538         res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)  /* Read an entry */
00539             ? FR_DISK_ERR : FR_OK;
00540         if (res != FR_OK) break;
00541         c = dir[PFFDIR_Name];
00542         if (c == 0) { res = FR_NO_FILE; break; }    /* Reached to end of table */
00543         a = dir[PFFDIR_Attr] & AM_MASK;
00544         if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */
00545             break;
00546         res = dir_next(dj);         /* Next entry */
00547         if (res != FR_OK) break;
00548     }
00549 
00550     if (res != FR_OK) dj->sect = 0;
00551 
00552     return res;
00553 }
00554 #endif
00555 
00556 
00557 
00558 /*-----------------------------------------------------------------------*/
00559 /* Pick a segment and create the object name in directory form           */
00560 /*-----------------------------------------------------------------------*/
00561 
00562 #ifdef _EXCVT
00563     static const BYTE cvt[] = _EXCVT;
00564 #endif
00565 
00566 static
00567 FRESULT create_name (
00568     PFFDIR *dj,         /* Pointer to the directory object */
00569     const char **path   /* Pointer to pointer to the segment in the path string */
00570 )
00571 {
00572     BYTE c, d, ni, si, i, *sfn;
00573     const char *p;
00574 
00575     /* Create file name in directory form */
00576     sfn = dj->fn;
00577     mem_set(sfn, ' ', 11);
00578     si = i = 0; ni = 8;
00579     p = *path;
00580     for (;;) {
00581         c = p[si++];
00582         if (c <= ' ' || c == '/') break;    /* Break on end of segment */
00583         if (c == '.' || i >= ni) {
00584             if (ni != 8 || c != '.') break;
00585             i = 8; ni = 11;
00586             continue;
00587         }
00588 #ifdef _EXCVT
00589         if (c >= 0x80)                  /* To upper extended char (SBCS) */
00590             c = cvt[c - 0x80];
00591 #endif
00592         if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st byte? */
00593             d = p[si++];                /* Get 2nd byte */
00594             sfn[i++] = c;
00595             sfn[i++] = d;
00596         } else {                        /* Single byte code */
00597             if (IsLower(c)) c -= 0x20;  /* toupper */
00598             sfn[i++] = c;
00599         }
00600     }
00601     *path = &p[si];                     /* Rerurn pointer to the next segment */
00602 
00603     sfn[11] = (c <= ' ') ? 1 : 0;       /* Set last segment flag if end of path */
00604 
00605     return FR_OK;
00606 }
00607 
00608 
00609 
00610 
00611 /*-----------------------------------------------------------------------*/
00612 /* Get file information from directory entry                             */
00613 /*-----------------------------------------------------------------------*/
00614 #if _USE_DIR
00615 static
00616 void get_fileinfo (     /* No return code */
00617     PFFDIR *dj,         /* Pointer to the directory object */
00618     BYTE *dir,          /* 32-byte working buffer */
00619     FILINFO *fno        /* Pointer to store the file information */
00620 )
00621 {
00622     BYTE i, c;
00623     char *p;
00624 
00625 
00626     p = fno->fname;
00627     if (dj->sect) {
00628         for (i = 0; i < 8; i++) {   /* Copy file name body */
00629             c = dir[i];
00630             if (c == ' ') break;
00631             if (c == 0x05) c = 0xE5;
00632             *p++ = c;
00633         }
00634         if (dir[8] != ' ') {        /* Copy file name extension */
00635             *p++ = '.';
00636             for (i = 8; i < 11; i++) {
00637                 c = dir[i];
00638                 if (c == ' ') break;
00639                 *p++ = c;
00640             }
00641         }
00642         fno->fattrib = dir[PFFDIR_Attr];                /* Attribute */
00643         fno->fsize = LD_DWORD(dir+PFFDIR_FileSize); /* Size */
00644         fno->fdate = LD_WORD(dir+PFFDIR_WrtDate);       /* Date */
00645         fno->ftime = LD_WORD(dir+PFFDIR_WrtTime);       /* Time */
00646     }
00647     *p = 0;
00648 }
00649 #endif /* _USE_DIR */
00650 
00651 
00652 
00653 /*-----------------------------------------------------------------------*/
00654 /* Follow a file path                                                    */
00655 /*-----------------------------------------------------------------------*/
00656 
00657 static
00658 FRESULT follow_path (   /* FR_OK(0): successful, !=0: error code */
00659     PFFDIR *dj,         /* Directory object to return last directory and found object */
00660     BYTE *dir,          /* 32-byte working buffer */
00661     const char *path    /* Full-path string to find a file or directory */
00662 )
00663 {
00664     FRESULT res;
00665 
00666 
00667     while (*path == ' ') path++;        /* Skip leading spaces */
00668     if (*path == '/') path++;           /* Strip heading separator */
00669     dj->sclust = 0;                     /* Set start directory (always root dir) */
00670 
00671     if ((BYTE)*path <= ' ') {           /* Null path means the root directory */
00672         res = dir_rewind(dj);
00673         dir[0] = 0;
00674 
00675     } else {                            /* Follow path */
00676         for (;;) {
00677             res = create_name(dj, &path);   /* Get a segment */
00678             if (res != FR_OK) break;
00679             res = dir_find(dj, dir);        /* Find it */
00680             if (res != FR_OK) {             /* Could not find the object */
00681                 if (res == FR_NO_FILE && !*(dj->fn+11))
00682                     res = FR_NO_PATH;
00683                 break;
00684             }
00685             if (*(dj->fn+11)) break;        /* Last segment match. Function completed. */
00686             if (!(dir[PFFDIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
00687                 res = FR_NO_PATH; break;
00688             }
00689             dj->sclust = LD_CLUST(dir);
00690         }
00691     }
00692 
00693     return res;
00694 }
00695 
00696 
00697 
00698 
00699 /*-----------------------------------------------------------------------*/
00700 /* Check a sector if it is an FAT boot record                            */
00701 /*-----------------------------------------------------------------------*/
00702 
00703 static
00704 BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
00705     BYTE *buf,  /* Working buffer */
00706     DWORD sect  /* Sector# (lba) to check if it is an FAT boot record or not */
00707 )
00708 {
00709     if (disk_readp(buf, sect, 510, 2))      /* Read the boot sector */
00710         return 3;
00711     if (LD_WORD(buf) != 0xAA55)             /* Check record signature */
00712         return 2;
00713 
00714     if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */
00715         return 0;
00716     if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146)  /* Check FAT32 */
00717         return 0;
00718     return 1;
00719 }
00720 
00721 
00722 
00723 
00724 /*--------------------------------------------------------------------------
00725 
00726    Public Functions
00727 
00728 --------------------------------------------------------------------------*/
00729 
00730 
00731 
00732 /*-----------------------------------------------------------------------*/
00733 /* Mount/Unmount a Locical Drive                                         */
00734 /*-----------------------------------------------------------------------*/
00735 
00736 FRESULT pf_mount (
00737     FATFS *fs       /* Pointer to new file system object (NULL: Unmount) */
00738 )
00739 {
00740     BYTE fmt, buf[36];
00741     DWORD bsect, fsize, tsect, mclst;
00742 
00743 
00744     FatFs = 0;
00745     if (!fs) return FR_OK;              /* Unregister fs object */
00746 
00747     if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */
00748         return FR_NOT_READY;
00749 
00750     /* Search FAT partition on the drive */
00751     bsect = 0;
00752     fmt = check_fs(buf, bsect);         /* Check sector 0 as an SFD format */
00753     if (fmt == 1) {                     /* Not an FAT boot record, it may be FDISK format */
00754         /* Check a partition listed in top of the partition table */
00755         if (disk_readp(buf, bsect, MBR_Table, 16)) {    /* 1st partition entry */
00756             fmt = 3;
00757         } else {
00758             if (buf[4]) {                   /* Is the partition existing? */
00759                 bsect = LD_DWORD(&buf[8]);  /* Partition offset in LBA */
00760                 fmt = check_fs(buf, bsect); /* Check the partition */
00761             }
00762         }
00763     }
00764     if (fmt == 3) return FR_DISK_ERR;
00765     if (fmt) return FR_NO_FILESYSTEM;   /* No valid FAT patition is found */
00766 
00767     /* Initialize the file system object */
00768     if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR;
00769 
00770     fsize = LD_WORD(buf+BPB_FATSz16-13);                /* Number of sectors per FAT */
00771     if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);
00772 
00773     fsize *= buf[BPB_NumFATs-13];                       /* Number of sectors in FAT area */
00774     fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */
00775     fs->csize = buf[BPB_SecPerClus-13];                 /* Number of sectors per cluster */
00776     fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13);     /* Nmuber of root directory entries */
00777     tsect = LD_WORD(buf+BPB_TotSec16-13);               /* Number of sectors on the file system */
00778     if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);
00779     mclst = (tsect                      /* Last cluster# + 1 */
00780         - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16
00781         ) / fs->csize + 2;
00782     fs->n_fatent = (CLUST)mclst;
00783 
00784     fmt = FS_FAT16;                         /* Determine the FAT sub type */
00785     if (mclst < 0xFF7)                      /* Number of clusters < 0xFF5 */
00786 #if _FS_FAT12
00787         fmt = FS_FAT12;
00788 #else
00789         return FR_NO_FILESYSTEM;
00790 #endif
00791     if (mclst >= 0xFFF7)                    /* Number of clusters >= 0xFFF5 */
00792 #if _FS_FAT32
00793         fmt = FS_FAT32;
00794 #else
00795         return FR_NO_FILESYSTEM;
00796 #endif
00797 
00798     fs->fs_type = fmt;      /* FAT sub-type */
00799     if (_FS_FAT32 && fmt == FS_FAT32)
00800         fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13));  /* Root directory start cluster */
00801     else
00802         fs->dirbase = fs->fatbase + fsize;              /* Root directory start sector (lba) */
00803     fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;    /* Data start sector (lba) */
00804 
00805     fs->flag = 0;
00806     FatFs = fs;
00807 
00808     return FR_OK;
00809 }
00810 
00811 
00812 
00813 
00814 /*-----------------------------------------------------------------------*/
00815 /* Open or Create a File                                                 */
00816 /*-----------------------------------------------------------------------*/
00817 
00818 FRESULT pf_open (
00819     const char *path    /* Pointer to the file name */
00820 )
00821 {
00822     FRESULT res;
00823     PFFDIR dj;
00824     BYTE sp[12], dir[32];
00825     FATFS *fs = FatFs;
00826 
00827 
00828     if (!fs)                        /* Check file system */
00829         return FR_NOT_ENABLED;
00830 
00831     fs->flag = 0;
00832     dj.fn = sp;
00833     res = follow_path(&dj, dir, path);  /* Follow the file path */
00834     if (res != FR_OK) return res;       /* Follow failed */
00835     if (!dir[0] || (dir[PFFDIR_Attr] & AM_DIR)) /* It is a directory */
00836         return FR_NO_FILE;
00837 
00838     fs->org_clust = LD_CLUST(dir);          /* File start cluster */
00839     fs->fsize = LD_DWORD(dir+PFFDIR_FileSize);  /* File size */
00840     fs->fptr = 0;                       /* File pointer */
00841     fs->flag = FA_OPENED;
00842 
00843     return FR_OK;
00844 }
00845 
00846 
00847 
00848 
00849 /*-----------------------------------------------------------------------*/
00850 /* Read File                                                             */
00851 /*-----------------------------------------------------------------------*/
00852 #if _USE_READ
00853 
00854 FRESULT pf_read (
00855     void* buff,     /* Pointer to the read buffer (NULL:Forward data to the stream)*/
00856     WORD btr,       /* Number of bytes to read */
00857     WORD* br        /* Pointer to number of bytes read */
00858 )
00859 {
00860     DRESULT dr;
00861     CLUST clst;
00862     DWORD sect, remain;
00863     WORD rcnt;
00864     BYTE cs, *rbuff = (BYTE *)buff;
00865     FATFS *fs = FatFs;
00866 
00867 
00868     *br = 0;
00869     if (!fs) return FR_NOT_ENABLED;     /* Check file system */
00870     if (!(fs->flag & FA_OPENED))        /* Check if opened */
00871         return FR_NOT_OPENED;
00872 
00873     remain = fs->fsize - fs->fptr;
00874     if (btr > remain) btr = (WORD)remain;           /* Truncate btr by remaining bytes */
00875 
00876     while (btr) {                                   /* Repeat until all data transferred */
00877         if ((fs->fptr % 512) == 0) {                /* On the sector boundary? */
00878             cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */
00879             if (!cs) {                              /* On the cluster boundary? */
00880                 clst = (fs->fptr == 0) ?            /* On the top of the file? */
00881                     fs->org_clust : get_fat(fs->curr_clust);
00882                 if (clst <= 1) goto fr_abort;
00883                 fs->curr_clust = clst;              /* Update current cluster */
00884             }
00885             sect = clust2sect(fs->curr_clust);      /* Get current sector */
00886             if (!sect) goto fr_abort;
00887             fs->dsect = sect + cs;
00888         }
00889         rcnt = (WORD)(512 - (fs->fptr % 512));      /* Get partial sector data from sector buffer */
00890         if (rcnt > btr) rcnt = btr;
00891         dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt);
00892         if (dr) goto fr_abort;
00893         fs->fptr += rcnt; rbuff += rcnt;            /* Update pointers and counters */
00894         btr -= rcnt; *br += rcnt;
00895     }
00896 
00897     return FR_OK;
00898 
00899 fr_abort:
00900     fs->flag = 0;
00901     return FR_DISK_ERR;
00902 }
00903 #endif
00904 
00905 
00906 
00907 /*-----------------------------------------------------------------------*/
00908 /* Write File                                                            */
00909 /*-----------------------------------------------------------------------*/
00910 #if _USE_WRITE
00911 
00912 FRESULT pf_write (
00913     const void* buff,   /* Pointer to the data to be written */
00914     WORD btw,           /* Number of bytes to write (0:Finalize the current write operation) */
00915     WORD* bw            /* Pointer to number of bytes written */
00916 )
00917 {
00918     CLUST clst;
00919     DWORD sect, remain;
00920     const BYTE *p =(const BYTE *) buff;
00921     BYTE cs;
00922     WORD wcnt;
00923     FATFS *fs = FatFs;
00924 
00925 
00926     *bw = 0;
00927     if (!fs) return FR_NOT_ENABLED;     /* Check file system */
00928     if (!(fs->flag & FA_OPENED))        /* Check if opened */
00929         return FR_NOT_OPENED;
00930 
00931     if (!btw) {     /* Finalize request */
00932         if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort;
00933         fs->flag &= ~FA__WIP;
00934         return FR_OK;
00935     } else {        /* Write data request */
00936         if (!(fs->flag & FA__WIP))      /* Round-down fptr to the sector boundary */
00937             fs->fptr &= 0xFFFFFE00;
00938     }
00939     remain = fs->fsize - fs->fptr;
00940     if (btw > remain) btw = (WORD)remain;           /* Truncate btw by remaining bytes */
00941 
00942     while (btw) {                                   /* Repeat until all data transferred */
00943         if (((WORD)fs->fptr % 512) == 0) {          /* On the sector boundary? */
00944             cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */
00945             if (!cs) {                              /* On the cluster boundary? */
00946                 clst = (fs->fptr == 0) ?            /* On the top of the file? */
00947                     fs->org_clust : get_fat(fs->curr_clust);
00948                 if (clst <= 1) goto fw_abort;
00949                 fs->curr_clust = clst;              /* Update current cluster */
00950             }
00951             sect = clust2sect(fs->curr_clust);      /* Get current sector */
00952             if (!sect) goto fw_abort;
00953             fs->dsect = sect + cs;
00954             if (disk_writep(0, fs->dsect)) goto fw_abort;   /* Initiate a sector write operation */
00955             fs->flag |= FA__WIP;
00956         }
00957         wcnt = 512 - ((WORD)fs->fptr % 512);        /* Number of bytes to write to the sector */
00958         if (wcnt > btw) wcnt = btw;
00959         if (disk_writep(p, wcnt)) goto fw_abort;    /* Send data to the sector */
00960         fs->fptr += wcnt; p += wcnt;                /* Update pointers and counters */
00961         btw -= wcnt; *bw += wcnt;
00962         if (((WORD)fs->fptr % 512) == 0) {
00963             if (disk_writep(0, 0)) goto fw_abort;   /* Finalize the currtent secter write operation */
00964             fs->flag &= ~FA__WIP;
00965         }
00966     }
00967 
00968     return FR_OK;
00969 
00970 fw_abort:
00971     fs->flag = 0;
00972     return FR_DISK_ERR;
00973 }
00974 #endif
00975 
00976 
00977 
00978 /*-----------------------------------------------------------------------*/
00979 /* Seek File R/W Pointer                                                 */
00980 /*-----------------------------------------------------------------------*/
00981 #if _USE_LSEEK
00982 
00983 FRESULT pf_lseek (
00984     DWORD ofs       /* File pointer from top of file */
00985 )
00986 {
00987     CLUST clst;
00988     DWORD bcs, sect, ifptr;
00989     FATFS *fs = FatFs;
00990 
00991 
00992     if (!fs) return FR_NOT_ENABLED;     /* Check file system */
00993     if (!(fs->flag & FA_OPENED))        /* Check if opened */
00994             return FR_NOT_OPENED;
00995 
00996     if (ofs > fs->fsize) ofs = fs->fsize;   /* Clip offset with the file size */
00997     ifptr = fs->fptr;
00998     fs->fptr = 0;
00999     if (ofs > 0) {
01000         bcs = (DWORD)fs->csize * 512;   /* Cluster size (byte) */
01001         if (ifptr > 0 &&
01002             (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
01003             fs->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */
01004             ofs -= fs->fptr;
01005             clst = fs->curr_clust;
01006         } else {                            /* When seek to back cluster, */
01007             clst = fs->org_clust;           /* start from the first cluster */
01008             fs->curr_clust = clst;
01009         }
01010         while (ofs > bcs) {             /* Cluster following loop */
01011             clst = get_fat(clst);       /* Follow cluster chain */
01012             if (clst <= 1 || clst >= fs->n_fatent) goto fe_abort;
01013             fs->curr_clust = clst;
01014             fs->fptr += bcs;
01015             ofs -= bcs;
01016         }
01017         fs->fptr += ofs;
01018         sect = clust2sect(clst);        /* Current sector */
01019         if (!sect) goto fe_abort;
01020         fs->dsect = sect + (fs->fptr / 512 & (fs->csize - 1));
01021     }
01022 
01023     return FR_OK;
01024 
01025 fe_abort:
01026     fs->flag = 0;
01027     return FR_DISK_ERR;
01028 }
01029 #endif
01030 
01031 
01032 
01033 /*-----------------------------------------------------------------------*/
01034 /* Create a Directroy Object                                             */
01035 /*-----------------------------------------------------------------------*/
01036 #if _USE_DIR
01037 
01038 FRESULT pf_opendir (
01039     PFFDIR *dj,         /* Pointer to directory object to create */
01040     const char *path    /* Pointer to the directory path */
01041 )
01042 {
01043     FRESULT res;
01044     BYTE sp[12], dir[32];
01045     FATFS *fs = FatFs;
01046 
01047 
01048     if (!fs) {              /* Check file system */
01049         res = FR_NOT_ENABLED;
01050     } else {
01051         dj->fn = sp;
01052         res = follow_path(dj, dir, path);       /* Follow the path to the directory */
01053         if (res == FR_OK) {                     /* Follow completed */
01054             if (dir[0]) {                       /* It is not the root dir */
01055                 if (dir[PFFDIR_Attr] & AM_DIR)      /* The object is a directory */
01056                     dj->sclust = LD_CLUST(dir);
01057                 else                            /* The object is not a directory */
01058                     res = FR_NO_PATH;
01059             }
01060             if (res == FR_OK)
01061                 res = dir_rewind(dj);           /* Rewind dir */
01062         }
01063         if (res == FR_NO_FILE) res = FR_NO_PATH;
01064     }
01065 
01066     return res;
01067 }
01068 
01069 
01070 
01071 
01072 /*-----------------------------------------------------------------------*/
01073 /* Read Directory Entry in Sequense                                      */
01074 /*-----------------------------------------------------------------------*/
01075 
01076 FRESULT pf_readdir (
01077     PFFDIR *dj,         /* Pointer to the open directory object */
01078     FILINFO *fno        /* Pointer to file information to return */
01079 )
01080 {
01081     FRESULT res;
01082     BYTE sp[12], dir[32];
01083     FATFS *fs = FatFs;
01084 
01085 
01086     if (!fs) {              /* Check file system */
01087         res = FR_NOT_ENABLED;
01088     } else {
01089         dj->fn = sp;
01090         if (!fno) {
01091             res = dir_rewind(dj);
01092         } else {
01093             res = dir_read(dj, dir);
01094             if (res == FR_NO_FILE) {
01095                 dj->sect = 0;
01096                 res = FR_OK;
01097             }
01098             if (res == FR_OK) {             /* A valid entry is found */
01099                 get_fileinfo(dj, dir, fno); /* Get the object information */
01100                 res = dir_next(dj);         /* Increment index for next */
01101                 if (res == FR_NO_FILE) {
01102                     dj->sect = 0;
01103                     res = FR_OK;
01104                 }
01105             }
01106         }
01107     }
01108 
01109     return res;
01110 }
01111 
01112 #endif /* _USE_DIR */
01113