Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /*----------------------------------------------------------------------------/
  2. /  Petit FatFs - FAT file system module  R0.03a
  3. /-----------------------------------------------------------------------------/
  4. /
  5. / Copyright (C) 2019, ChaN, all right reserved.
  6. /
  7. / Petit FatFs module is an open source software. Redistribution and use of
  8. / Petit FatFs in source and binary forms, with or without modification, are
  9. / permitted provided that the following condition is met:
  10. /
  11. / 1. Redistributions of source code must retain the above copyright notice,
  12. /    this condition and the following disclaimer.
  13. /
  14. / This software is provided by the copyright holder and contributors "AS IS"
  15. / and any warranties related to this software are DISCLAIMED.
  16. / The copyright owner or contributors be NOT LIABLE for any damages caused
  17. / by use of this software.
  18. /-----------------------------------------------------------------------------/
  19. / Jun 15,'09  R0.01a  First release.
  20. /
  21. / Dec 14,'09  R0.02   Added multiple code page support.
  22. /                     Added write funciton.
  23. /                     Changed stream read mode interface.
  24. / Dec 07,'10  R0.02a  Added some configuration options.
  25. /                     Fixed fails to open objects with DBCS character.
  26.  
  27. / Jun 10,'14  R0.03   Separated out configuration options to pffconf.h.
  28. /                     Added _USE_LCC option.
  29. /                     Added _FS_FAT16 option.
  30. /
  31. / Jan 30,'19  R0.03a  Supported stdint.h for C99 and later.
  32. /                     Removed _WORD_ACCESS option.
  33. /                     Changed prefix of configuration options, _ to PF_.
  34. /                     Added some code pages.
  35. /                     Removed some code pages actually not valid.
  36. /----------------------------------------------------------------------------*/
  37.  
  38. #include "pff.h"                /* Petit FatFs configurations and declarations */
  39. #include "diskio.h"             /* Declarations of low level disk I/O functions */
  40.  
  41.  
  42.  
  43. /*--------------------------------------------------------------------------
  44.  
  45.    Module Private Definitions
  46.  
  47. ---------------------------------------------------------------------------*/
  48.  
  49.  
  50. #if PF_DEFINED != 8088  /* Revision ID */
  51. #error Wrong include file (pff.h).
  52. #endif
  53.  
  54. #if PF_FS_FAT32
  55. #if !PF_FS_FAT16 && !PF_FS_FAT12
  56. #define _FS_32ONLY 1
  57. #else
  58. #define _FS_32ONLY 0
  59. #endif
  60. #else
  61. #if !PF_FS_FAT16 && !PF_FS_FAT12
  62. #error Wrong PF_FS_FATxx setting.
  63. #endif
  64. #define _FS_32ONLY 0
  65. #endif
  66.  
  67. #define ABORT(err)      {fs->flag = 0; return err;}
  68.  
  69.  
  70.  
  71. /*--------------------------------------------------------*/
  72. /* DBCS code ranges and SBCS extend char conversion table */
  73. /*--------------------------------------------------------*/
  74.  
  75. #if PF_USE_LCC == 0             /* ASCII upper case character only */
  76.  
  77. #elif PF_CODE_PAGE == 932       /* Japanese Shift-JIS */
  78. #define _DF1S   0x81    /* DBC 1st byte range 1 start */
  79. #define _DF1E   0x9F    /* DBC 1st byte range 1 end */
  80. #define _DF2S   0xE0    /* DBC 1st byte range 2 start */
  81. #define _DF2E   0xFC    /* DBC 1st byte range 2 end */
  82. #define _DS1S   0x40    /* DBC 2nd byte range 1 start */
  83. #define _DS1E   0x7E    /* DBC 2nd byte range 1 end */
  84. #define _DS2S   0x80    /* DBC 2nd byte range 2 start */
  85. #define _DS2E   0xFC    /* DBC 2nd byte range 2 end */
  86.  
  87. #elif PF_CODE_PAGE == 936       /* Simplified Chinese GBK */
  88. #define _DF1S   0x81
  89. #define _DF1E   0xFE
  90. #define _DS1S   0x40
  91. #define _DS1E   0x7E
  92. #define _DS2S   0x80
  93. #define _DS2E   0xFE
  94.  
  95. #elif PF_CODE_PAGE == 949       /* Korean */
  96. #define _DF1S   0x81
  97. #define _DF1E   0xFE
  98. #define _DS1S   0x41
  99. #define _DS1E   0x5A
  100. #define _DS2S   0x61
  101. #define _DS2E   0x7A
  102. #define _DS3S   0x81
  103. #define _DS3E   0xFE
  104.  
  105. #elif PF_CODE_PAGE == 950       /* Traditional Chinese Big5 */
  106. #define _DF1S   0x81
  107. #define _DF1E   0xFE
  108. #define _DS1S   0x40
  109. #define _DS1E   0x7E
  110. #define _DS2S   0xA1
  111. #define _DS2E   0xFE
  112.  
  113. #elif PF_CODE_PAGE == 437       /* U.S. */
  114. #define _EXCVT {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
  115.                                 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  116.                                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  117.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  118.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  119.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  120.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  121.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  122.  
  123. #elif PF_CODE_PAGE == 720       /* Arabic */
  124. #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  125.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  126.                                 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  127.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  128.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  129.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  130.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  131.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  132.  
  133. #elif PF_CODE_PAGE == 737       /* Greek */
  134. #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  135.                                 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
  136.                                 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \
  137.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  138.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  139.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  140.                                 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  141.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  142.  
  143. #elif PF_CODE_PAGE == 771       /* KBL */
  144. #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  145.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  146.                                 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  147.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  148.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  149.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \
  150.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  151.                                 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF}
  152.  
  153. #elif PF_CODE_PAGE == 775       /* Baltic */
  154. #define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \
  155.                                 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
  156.                                 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  157.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  158.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  159.                                 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  160.                                 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \
  161.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  162.  
  163. #elif PF_CODE_PAGE == 850       /* Latin 1 */
  164. #define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \
  165.                                 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \
  166.                                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  167.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  168.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  169.                                 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \
  170.                                 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \
  171.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  172.  
  173. #elif PF_CODE_PAGE == 852       /* Latin 2 */
  174. #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \
  175.                                 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \
  176.                                 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \
  177.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
  178.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  179.                                 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  180.                                 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \
  181.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
  182.  
  183. #elif PF_CODE_PAGE == 855       /* Cyrillic */
  184. #define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \
  185.                                 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
  186.                                 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \
  187.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
  188.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  189.                                 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
  190.                                 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \
  191.                                 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
  192.  
  193. #elif PF_CODE_PAGE == 857       /* Turkish */
  194. #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \
  195.                                 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
  196.                                 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  197.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  198.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  199.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  200.                                 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \
  201.  
  202. #elif PF_CODE_PAGE == 860       /* Portuguese */
  203. #define _EXCVT {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \
  204.                                 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  205.                                 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  206.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  207.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  208.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  209.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  210.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  211.  
  212. #elif PF_CODE_PAGE == 861       /* Icelandic */
  213. #define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \
  214.                                 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
  215.                                 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  216.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  217.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  218.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  219.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  220.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  221.  
  222. #elif PF_CODE_PAGE == 862       /* Hebrew */
  223. #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  224.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  225.                                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  226.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  227.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  228.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  229.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  230.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  231.  
  232. #elif PF_CODE_PAGE == 863       /* Canadian French */
  233. #define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \
  234.                                 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \
  235.                                 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  236.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  237.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  238.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  239.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  240.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  241.  
  242. #elif PF_CODE_PAGE == 864       /* Arabic */
  243. #define _EXCVT {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
  244.                                 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  245.                                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  246.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  247.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  248.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  249.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  250.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  251.  
  252. #elif PF_CODE_PAGE == 865       /* Nordic */
  253. #define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
  254.                                 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  255.                                 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  256.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  257.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  258.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  259.                                 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
  260.                                 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  261.  
  262. #elif PF_CODE_PAGE == 866       /* Russian */
  263. #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  264.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  265.                                 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  266.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  267.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  268.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
  269.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
  270.                                 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
  271.  
  272. #elif PF_CODE_PAGE == 869       /* Greek 2 */
  273. #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \
  274.                                 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \
  275.                                 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
  276.                                 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
  277.                                 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
  278.                                 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \
  279.                                 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \
  280.                                 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF}
  281.  
  282. #else
  283. #error Unknown code page.
  284.  
  285. #endif
  286.  
  287.  
  288.  
  289. /* Character code support macros */
  290.  
  291. #define IsUpper(c)      (((c)>='A')&&((c)<='Z'))
  292. #define IsLower(c)      (((c)>='a')&&((c)<='z'))
  293.  
  294. #if PF_USE_LCC && !defined(_EXCVT)      /* DBCS configuration */
  295.  
  296. #ifdef _DF2S    /* Two 1st byte areas */
  297. #define IsDBCS1(c)      (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
  298. #else                   /* One 1st byte area */
  299. #define IsDBCS1(c)      ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
  300. #endif
  301.  
  302. #ifdef _DS3S    /* Three 2nd byte areas */
  303. #define IsDBCS2(c)      (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
  304. #else                   /* Two 2nd byte areas */
  305. #define IsDBCS2(c)      (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
  306. #endif
  307.  
  308. #else                   /* SBCS configuration */
  309.  
  310. #define IsDBCS1(c)      0
  311. #define IsDBCS2(c)      0
  312.  
  313. #endif /* _EXCVT */
  314.  
  315.  
  316. /* FatFs refers the members in the FAT structures with byte offset instead
  317. / of structure member because there are incompatibility of the packing option
  318. / between various compilers. */
  319.  
  320. #define BS_jmpBoot                      0
  321. #define BS_OEMName                      3
  322. #define BPB_BytsPerSec          11
  323. #define BPB_SecPerClus          13
  324. #define BPB_RsvdSecCnt          14
  325. #define BPB_NumFATs                     16
  326. #define BPB_RootEntCnt          17
  327. #define BPB_TotSec16            19
  328. #define BPB_Media                       21
  329. #define BPB_FATSz16                     22
  330. #define BPB_SecPerTrk           24
  331. #define BPB_NumHeads            26
  332. #define BPB_HiddSec                     28
  333. #define BPB_TotSec32            32
  334. #define BS_55AA                         510
  335.  
  336. #define BS_DrvNum                       36
  337. #define BS_BootSig                      38
  338. #define BS_VolID                        39
  339. #define BS_VolLab                       43
  340. #define BS_FilSysType           54
  341.  
  342. #define BPB_FATSz32                     36
  343. #define BPB_ExtFlags            40
  344. #define BPB_FSVer                       42
  345. #define BPB_RootClus            44
  346. #define BPB_FSInfo                      48
  347. #define BPB_BkBootSec           50
  348. #define BS_DrvNum32                     64
  349. #define BS_BootSig32            66
  350. #define BS_VolID32                      67
  351. #define BS_VolLab32                     71
  352. #define BS_FilSysType32         82
  353.  
  354. #define MBR_Table                       446
  355.  
  356. #define DIR_Name                        0
  357. #define DIR_Attr                        11
  358. #define DIR_NTres                       12
  359. #define DIR_CrtTime                     14
  360. #define DIR_CrtDate                     16
  361. #define DIR_FstClusHI           20
  362. #define DIR_WrtTime                     22
  363. #define DIR_WrtDate                     24
  364. #define DIR_FstClusLO           26
  365. #define DIR_FileSize            28
  366.  
  367.  
  368.  
  369.  
  370. /*--------------------------------------------------------------------------
  371.  
  372.    Private Functions
  373.  
  374. ---------------------------------------------------------------------------*/
  375.  
  376.  
  377. static FATFS *FatFs;    /* Pointer to the file system object (logical drive) */
  378.  
  379.  
  380. /*-----------------------------------------------------------------------*/
  381. /* Load multi-byte word in the FAT structure                             */
  382. /*-----------------------------------------------------------------------*/
  383.  
  384. static WORD ld_word (const BYTE* ptr)   /*       Load a 2-byte little-endian word */
  385. {
  386.         WORD rv;
  387.  
  388.         rv = ptr[1];
  389.         rv = rv << 8 | ptr[0];
  390.         return rv;
  391. }
  392.  
  393. static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */
  394. {
  395.         DWORD rv;
  396.  
  397.         rv = ptr[3];
  398.         rv = rv << 8 | ptr[2];
  399.         rv = rv << 8 | ptr[1];
  400.         rv = rv << 8 | ptr[0];
  401.         return rv;
  402. }
  403.  
  404.  
  405.  
  406. /*-----------------------------------------------------------------------*/
  407. /* String functions                                                      */
  408. /*-----------------------------------------------------------------------*/
  409.  
  410. /* Fill memory block */
  411. static void mem_set (void* dst, int val, int cnt) {
  412.         char *d = (char*)dst;
  413.         while (cnt--) *d++ = (char)val;
  414. }
  415.  
  416. /* Compare memory block */
  417. static int mem_cmp (const void* dst, const void* src, int cnt) {
  418.         const char *d = (const char *)dst, *s = (const char *)src;
  419.         int r = 0;
  420.         while (cnt-- && (r = *d++ - *s++) == 0) ;
  421.         return r;
  422. }
  423.  
  424.  
  425.  
  426. /*-----------------------------------------------------------------------*/
  427. /* FAT access - Read value of a FAT entry                                */
  428. /*-----------------------------------------------------------------------*/
  429.  
  430. static CLUST get_fat (  /* 1:IO error, Else:Cluster status */
  431.         CLUST clst      /* Cluster# to get the link information */
  432. )
  433. {
  434.         BYTE buf[4];
  435.         FATFS *fs = FatFs;
  436. #if PF_FS_FAT12
  437.         UINT wc, bc, ofs;
  438. #endif
  439.  
  440.         if (clst < 2 || clst >= fs->n_fatent) return 1; /* Range check */
  441.  
  442.         switch (fs->fs_type) {
  443. #if PF_FS_FAT12
  444.         case FS_FAT12 : {
  445.                 bc = (UINT)clst; bc += bc / 2;
  446.                 ofs = bc % 512; bc /= 512;
  447.                 if (ofs != 511) {
  448.                         if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;
  449.                 } else {
  450.                         if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;
  451.                         if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;
  452.                 }
  453.                 wc = ld_word(buf);
  454.                 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
  455.         }
  456. #endif
  457. #if PF_FS_FAT16
  458.         case FS_FAT16 :
  459.                 if (disk_readp(buf, fs->fatbase + clst / 256, ((UINT)clst % 256) * 2, 2)) break;
  460.                 return ld_word(buf);
  461. #endif
  462. #if PF_FS_FAT32
  463.         case FS_FAT32 :
  464.                 if (disk_readp(buf, fs->fatbase + clst / 128, ((UINT)clst % 128) * 4, 4)) break;
  465.                 return ld_dword(buf) & 0x0FFFFFFF;
  466. #endif
  467.         }
  468.  
  469.         return 1;       /* An error occured at the disk I/O layer */
  470. }
  471.  
  472.  
  473.  
  474.  
  475. /*-----------------------------------------------------------------------*/
  476. /* Get sector# from cluster# / Get cluster field from directory entry    */
  477. /*-----------------------------------------------------------------------*/
  478.  
  479. static DWORD clust2sect (       /* !=0: Sector number, 0: Failed - invalid cluster# */
  480.         CLUST clst              /* Cluster# to be converted */
  481. )
  482. {
  483.         FATFS *fs = FatFs;
  484.  
  485.  
  486.         clst -= 2;
  487.         if (clst >= (fs->n_fatent - 2)) return 0;               /* Invalid cluster# */
  488.         return (DWORD)clst * fs->csize + fs->database;
  489. }
  490.  
  491.  
  492. static CLUST get_clust (
  493.         BYTE* dir               /* Pointer to directory entry */
  494. )
  495. {
  496.         FATFS *fs = FatFs;
  497.         CLUST clst = 0;
  498.  
  499.  
  500.         if (_FS_32ONLY || (PF_FS_FAT32 && fs->fs_type == FS_FAT32)) {
  501.                 clst = ld_word(dir+DIR_FstClusHI);
  502.                 clst <<= 16;
  503.         }
  504.         clst |= ld_word(dir+DIR_FstClusLO);
  505.  
  506.         return clst;
  507. }
  508.  
  509.  
  510. /*-----------------------------------------------------------------------*/
  511. /* Directory handling - Rewind directory index                           */
  512. /*-----------------------------------------------------------------------*/
  513.  
  514. static FRESULT dir_rewind (
  515.         DIR *dj                 /* Pointer to directory object */
  516. )
  517. {
  518.         CLUST clst;
  519.         FATFS *fs = FatFs;
  520.  
  521.  
  522.         dj->index = 0;
  523.         clst = dj->sclust;
  524.         if (clst == 1 || clst >= fs->n_fatent) {        /* Check start cluster range */
  525.                 return FR_DISK_ERR;
  526.         }
  527.         if (PF_FS_FAT32 && !clst && (_FS_32ONLY || fs->fs_type == FS_FAT32)) {  /* Replace cluster# 0 with root cluster# if in FAT32 */
  528.                 clst = (CLUST)fs->dirbase;
  529.         }
  530.         dj->clust = clst;                                               /* Current cluster */
  531.         dj->sect = (_FS_32ONLY || clst) ? clust2sect(clst) : fs->dirbase;       /* Current sector */
  532.  
  533.         return FR_OK;   /* Seek succeeded */
  534. }
  535.  
  536.  
  537.  
  538.  
  539. /*-----------------------------------------------------------------------*/
  540. /* Directory handling - Move directory index next                        */
  541. /*-----------------------------------------------------------------------*/
  542.  
  543. static FRESULT dir_next (       /* FR_OK:Succeeded, FR_NO_FILE:End of table */
  544.         DIR *dj                 /* Pointer to directory object */
  545. )
  546. {
  547.         CLUST clst;
  548.         WORD i;
  549.         FATFS *fs = FatFs;
  550.  
  551.  
  552.         i = dj->index + 1;
  553.         if (!i || !dj->sect) return FR_NO_FILE; /* Report EOT when index has reached 65535 */
  554.  
  555.         if (!(i % 16)) {                /* Sector changed? */
  556.                 dj->sect++;                     /* Next sector */
  557.  
  558.                 if (dj->clust == 0) {   /* Static table */
  559.                         if (i >= fs->n_rootdir) return FR_NO_FILE;      /* Report EOT when end of table */
  560.                 }
  561.                 else {                                  /* Dynamic table */
  562.                         if (((i / 16) & (fs->csize - 1)) == 0) {        /* Cluster changed? */
  563.                                 clst = get_fat(dj->clust);              /* Get next cluster */
  564.                                 if (clst <= 1) return FR_DISK_ERR;
  565.                                 if (clst >= fs->n_fatent) return FR_NO_FILE;    /* Report EOT when it reached end of dynamic table */
  566.                                 dj->clust = clst;                               /* Initialize data for new cluster */
  567.                                 dj->sect = clust2sect(clst);
  568.                         }
  569.                 }
  570.         }
  571.  
  572.         dj->index = i;
  573.  
  574.         return FR_OK;
  575. }
  576.  
  577.  
  578.  
  579.  
  580. /*-----------------------------------------------------------------------*/
  581. /* Directory handling - Find an object in the directory                  */
  582. /*-----------------------------------------------------------------------*/
  583.  
  584. static FRESULT dir_find (
  585.         DIR *dj,                /* Pointer to the directory object linked to the file name */
  586.         BYTE *dir               /* 32-byte working buffer */
  587. )
  588. {
  589.         FRESULT res;
  590.         BYTE c;
  591.  
  592.  
  593.         res = dir_rewind(dj);                   /* Rewind directory object */
  594.         if (res != FR_OK) return res;
  595.  
  596.         do {
  597.                 res = disk_readp(dir, dj->sect, (dj->index % 16) * 32, 32)      /* Read an entry */
  598.                         ? FR_DISK_ERR : FR_OK;
  599.                 if (res != FR_OK) break;
  600.                 c = dir[DIR_Name];      /* First character */
  601.                 if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */
  602.                 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) break;      /* Is it a valid entry? */
  603.                 res = dir_next(dj);                                     /* Next entry */
  604.         } while (res == FR_OK);
  605.  
  606.         return res;
  607. }
  608.  
  609.  
  610.  
  611.  
  612. /*-----------------------------------------------------------------------*/
  613. /* Read an object from the directory                                     */
  614. /*-----------------------------------------------------------------------*/
  615. #if PF_USE_DIR
  616. static FRESULT dir_read (
  617.         DIR *dj,                /* Pointer to the directory object to store read object name */
  618.         BYTE *dir               /* 32-byte working buffer */
  619. )
  620. {
  621.         FRESULT res;
  622.         BYTE a, c;
  623.  
  624.  
  625.         res = FR_NO_FILE;
  626.         while (dj->sect) {
  627.                 res = disk_readp(dir, dj->sect, (dj->index % 16) * 32, 32)      /* Read an entry */
  628.                         ? FR_DISK_ERR : FR_OK;
  629.                 if (res != FR_OK) break;
  630.                 c = dir[DIR_Name];
  631.                 if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */
  632.                 a = dir[DIR_Attr] & AM_MASK;
  633.                 if (c != 0xE5 && c != '.' && !(a & AM_VOL))     break;  /* Is it a valid entry? */
  634.                 res = dir_next(dj);                     /* Next entry */
  635.                 if (res != FR_OK) break;
  636.         }
  637.  
  638.         if (res != FR_OK) dj->sect = 0;
  639.  
  640.         return res;
  641. }
  642. #endif
  643.  
  644.  
  645.  
  646. /*-----------------------------------------------------------------------*/
  647. /* Pick a segment and create the object name in directory form           */
  648. /*-----------------------------------------------------------------------*/
  649.  
  650.  
  651. static FRESULT create_name (
  652.         DIR *dj,                        /* Pointer to the directory object */
  653.         const char **path       /* Pointer to pointer to the segment in the path string */
  654. )
  655. {
  656.         BYTE c, d, ni, si, i, *sfn;
  657.         const char *p;
  658. #if PF_USE_LCC && defined(_EXCVT)
  659.         static const BYTE cvt[] = _EXCVT;
  660. #endif
  661.  
  662.         /* Create file name in directory form */
  663.         sfn = dj->fn;
  664.         mem_set(sfn, ' ', 11);
  665.         si = i = 0; ni = 8;
  666.         p = *path;
  667.         for (;;) {
  668.                 c = p[si++];
  669.                 if (c <= ' ' || c == '/') break;        /* Break on end of segment */
  670.                 if (c == '.' || i >= ni) {
  671.                         if (ni != 8 || c != '.') break;
  672.                         i = 8; ni = 11;
  673.                         continue;
  674.                 }
  675. #if PF_USE_LCC && defined(_EXCVT)
  676.                 if (c >= 0x80) c = cvt[c - 0x80];       /* To upper extended char (SBCS) */
  677. #endif
  678.                 if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st byte? */
  679.                         d = p[si++];                            /* Get 2nd byte */
  680.                         sfn[i++] = c;
  681.                         sfn[i++] = d;
  682.                 } else {                                                /* Single byte code */
  683.                         if (PF_USE_LCC && IsLower(c)) c -= 0x20;        /* toupper */
  684.                         sfn[i++] = c;
  685.                 }
  686.         }
  687.         *path = &p[si];                                         /* Rerurn pointer to the next segment */
  688.  
  689.         sfn[11] = (c <= ' ') ? 1 : 0;           /* Set last segment flag if end of path */
  690.  
  691.         return FR_OK;
  692. }
  693.  
  694.  
  695.  
  696.  
  697. /*-----------------------------------------------------------------------*/
  698. /* Get file information from directory entry                             */
  699. /*-----------------------------------------------------------------------*/
  700. #if PF_USE_DIR
  701. static void get_fileinfo (              /* No return code */
  702.         DIR *dj,                        /* Pointer to the directory object */
  703.         BYTE *dir,                      /* 32-byte working buffer */
  704.         FILINFO *fno            /* Pointer to store the file information */
  705. )
  706. {
  707.         BYTE i, c;
  708.         char *p;
  709.  
  710.  
  711.         p = fno->fname;
  712.         if (dj->sect) {
  713.                 for (i = 0; i < 8; i++) {       /* Copy file name body */
  714.                         c = dir[i];
  715.                         if (c == ' ') break;
  716.                         if (c == 0x05) c = 0xE5;
  717.                         *p++ = c;
  718.                 }
  719.                 if (dir[8] != ' ') {            /* Copy file name extension */
  720.                         *p++ = '.';
  721.                         for (i = 8; i < 11; i++) {
  722.                                 c = dir[i];
  723.                                 if (c == ' ') break;
  724.                                 *p++ = c;
  725.                         }
  726.                 }
  727.                 fno->fattrib = dir[DIR_Attr];                           /* Attribute */
  728.                 fno->fsize = ld_dword(dir+DIR_FileSize);        /* Size */
  729.                 fno->fdate = ld_word(dir+DIR_WrtDate);          /* Date */
  730.                 fno->ftime = ld_word(dir+DIR_WrtTime);          /* Time */
  731.         }
  732.         *p = 0;
  733. }
  734. #endif /* PF_USE_DIR */
  735.  
  736.  
  737.  
  738. /*-----------------------------------------------------------------------*/
  739. /* Follow a file path                                                    */
  740. /*-----------------------------------------------------------------------*/
  741.  
  742. static FRESULT follow_path (    /* FR_OK(0): successful, !=0: error code */
  743.         DIR *dj,                        /* Directory object to return last directory and found object */
  744.         BYTE *dir,                      /* 32-byte working buffer */
  745.         const char *path        /* Full-path string to find a file or directory */
  746. )
  747. {
  748.         FRESULT res;
  749.  
  750.  
  751.         while (*path == ' ') path++;            /* Strip leading spaces */
  752.         if (*path == '/') path++;                       /* Strip heading separator if exist */
  753.         dj->sclust = 0;                                         /* Set start directory (always root dir) */
  754.  
  755.         if ((BYTE)*path < ' ') {                        /* Null path means the root directory */
  756.                 res = dir_rewind(dj);
  757.                 dir[0] = 0;
  758.  
  759.         } else {                                                        /* Follow path */
  760.                 for (;;) {
  761.                         res = create_name(dj, &path);   /* Get a segment */
  762.                         if (res != FR_OK) break;
  763.                         res = dir_find(dj, dir);                /* Find it */
  764.                         if (res != FR_OK) break;                /* Could not find the object */
  765.                         if (dj->fn[11]) break;                  /* Last segment match. Function completed. */
  766.                         if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow path because it is a file */
  767.                                 res = FR_NO_FILE; break;
  768.                         }
  769.                         dj->sclust = get_clust(dir);    /* Follow next */
  770.                 }
  771.         }
  772.  
  773.         return res;
  774. }
  775.  
  776.  
  777.  
  778.  
  779. /*-----------------------------------------------------------------------*/
  780. /* Check a sector if it is an FAT boot record                            */
  781. /*-----------------------------------------------------------------------*/
  782.  
  783. static BYTE check_fs (  /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
  784.         BYTE *buf,      /* Working buffer */
  785.         DWORD sect      /* Sector# (lba) to check if it is an FAT boot record or not */
  786. )
  787. {
  788.         if (disk_readp(buf, sect, 510, 2)) {    /* Read the boot record */
  789.                 return 3;
  790.         }
  791.         if (ld_word(buf) != 0xAA55) {                   /* Check record signature */
  792.                 return 2;
  793.         }
  794.  
  795.         if (!_FS_32ONLY && !disk_readp(buf, sect, BS_FilSysType, 2) && ld_word(buf) == 0x4146) {        /* Check FAT12/16 */
  796.                 return 0;
  797.         }
  798.         if (PF_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && ld_word(buf) == 0x4146) {      /* Check FAT32 */
  799.                 return 0;
  800.         }
  801.         return 1;
  802. }
  803.  
  804.  
  805.  
  806.  
  807. /*--------------------------------------------------------------------------
  808.  
  809.    Public Functions
  810.  
  811. --------------------------------------------------------------------------*/
  812.  
  813.  
  814.  
  815. /*-----------------------------------------------------------------------*/
  816. /* Mount/Unmount a Locical Drive                                         */
  817. /*-----------------------------------------------------------------------*/
  818.  
  819. FRESULT pf_mount (
  820.         FATFS *fs               /* Pointer to new file system object */
  821. )
  822. {
  823.         BYTE fmt, buf[36];
  824.         DWORD bsect, fsize, tsect, mclst;
  825.  
  826.  
  827.         FatFs = 0;
  828.  
  829.         if (disk_initialize() & STA_NOINIT) {   /* Check if the drive is ready or not */
  830.                 return FR_NOT_READY;
  831.         }
  832.  
  833.         /* Search FAT partition on the drive */
  834.         bsect = 0;
  835.         fmt = check_fs(buf, bsect);                     /* Check sector 0 as an SFD format */
  836.         if (fmt == 1) {                                         /* Not an FAT boot record, it may be FDISK format */
  837.                 /* Check a partition listed in top of the partition table */
  838.                 if (disk_readp(buf, bsect, MBR_Table, 16)) {    /* 1st partition entry */
  839.                         fmt = 3;
  840.                 } else {
  841.                         if (buf[4]) {                                   /* Is the partition existing? */
  842.                                 bsect = ld_dword(&buf[8]);      /* Partition offset in LBA */
  843.                                 fmt = check_fs(buf, bsect);     /* Check the partition */
  844.                         }
  845.                 }
  846.         }
  847.         if (fmt == 3) return FR_DISK_ERR;
  848.         if (fmt) return FR_NO_FILESYSTEM;       /* No valid FAT patition is found */
  849.  
  850.         /* Initialize the file system object */
  851.         if (disk_readp(buf, bsect, 13, sizeof (buf))) return FR_DISK_ERR;
  852.  
  853.         fsize = ld_word(buf+BPB_FATSz16-13);                            /* Number of sectors per FAT */
  854.         if (!fsize) fsize = ld_dword(buf+BPB_FATSz32-13);
  855.  
  856.         fsize *= buf[BPB_NumFATs-13];                                           /* Number of sectors in FAT area */
  857.         fs->fatbase = bsect + ld_word(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */
  858.         fs->csize = buf[BPB_SecPerClus-13];                                     /* Number of sectors per cluster */
  859.         fs->n_rootdir = ld_word(buf+BPB_RootEntCnt-13);         /* Nmuber of root directory entries */
  860.         tsect = ld_word(buf+BPB_TotSec16-13);                           /* Number of sectors on the file system */
  861.         if (!tsect) tsect = ld_dword(buf+BPB_TotSec32-13);
  862.         mclst = (tsect                                          /* Last cluster# + 1 */
  863.                 - ld_word(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16
  864.                 ) / fs->csize + 2;
  865.         fs->n_fatent = (CLUST)mclst;
  866.  
  867.         fmt = 0;                                                        /* Determine the FAT sub type */
  868.         if (PF_FS_FAT12 && mclst < 0xFF7) fmt = FS_FAT12;
  869.         if (PF_FS_FAT16 && mclst >= 0xFF8 && mclst < 0xFFF7) fmt = FS_FAT16;
  870.         if (PF_FS_FAT32 && mclst >= 0xFFF7) fmt = FS_FAT32;
  871.         if (!fmt) return FR_NO_FILESYSTEM;
  872.         fs->fs_type = fmt;
  873.  
  874.         if (_FS_32ONLY || (PF_FS_FAT32 && fmt == FS_FAT32)) {
  875.                 fs->dirbase = ld_dword(buf+(BPB_RootClus-13));  /* Root directory start cluster */
  876.         } else {
  877.                 fs->dirbase = fs->fatbase + fsize;                              /* Root directory start sector (lba) */
  878.         }
  879.         fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;        /* Data start sector (lba) */
  880.  
  881.         fs->flag = 0;
  882.         FatFs = fs;
  883.  
  884.         return FR_OK;
  885. }
  886.  
  887.  
  888.  
  889.  
  890. /*-----------------------------------------------------------------------*/
  891. /* Open or Create a File                                                 */
  892. /*-----------------------------------------------------------------------*/
  893.  
  894. FRESULT pf_open (
  895.         const char *path        /* Pointer to the file name */
  896. )
  897. {
  898.         FRESULT res;
  899.         DIR dj;
  900.         BYTE sp[12], dir[32];
  901.         FATFS *fs = FatFs;
  902.  
  903.  
  904.         if (!fs) return FR_NOT_ENABLED;         /* Check file system */
  905.  
  906.         fs->flag = 0;
  907.         dj.fn = sp;
  908.         res = follow_path(&dj, dir, path);      /* Follow the file path */
  909.         if (res != FR_OK) return res;           /* Follow failed */
  910.         if (!dir[0] || (dir[DIR_Attr] & AM_DIR)) return FR_NO_FILE;     /* It is a directory */
  911.  
  912.         fs->org_clust = get_clust(dir);         /* File start cluster */
  913.         fs->fsize = ld_dword(dir+DIR_FileSize); /* File size */
  914.         fs->fptr = 0;                                           /* File pointer */
  915.         fs->flag = FA_OPENED;
  916.  
  917.         return FR_OK;
  918. }
  919.  
  920.  
  921.  
  922.  
  923. /*-----------------------------------------------------------------------*/
  924. /* Read File                                                             */
  925. /*-----------------------------------------------------------------------*/
  926. #if PF_USE_READ
  927.  
  928. FRESULT pf_read (
  929.         void* buff,             /* Pointer to the read buffer (NULL:Forward data to the stream)*/
  930.         UINT btr,               /* Number of bytes to read */
  931.         UINT* br                /* Pointer to number of bytes read */
  932. )
  933. {
  934.         DRESULT dr;
  935.         CLUST clst;
  936.         DWORD sect, remain;
  937.         UINT rcnt;
  938.         BYTE cs, *rbuff = buff;
  939.         FATFS *fs = FatFs;
  940.  
  941.  
  942.         *br = 0;
  943.         if (!fs) return FR_NOT_ENABLED;         /* Check file system */
  944.         if (!(fs->flag & FA_OPENED)) return FR_NOT_OPENED;      /* Check if opened */
  945.  
  946.         remain = fs->fsize - fs->fptr;
  947.         if (btr > remain) btr = (UINT)remain;                   /* Truncate btr by remaining bytes */
  948.  
  949.         while (btr)     {                                                                       /* Repeat until all data transferred */
  950.                 if ((fs->fptr % 512) == 0) {                            /* On the sector boundary? */
  951.                         cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */
  952.                         if (!cs) {                                                              /* On the cluster boundary? */
  953.                                 if (fs->fptr == 0) {                            /* On the top of the file? */
  954.                                         clst = fs->org_clust;
  955.                                 } else {
  956.                                         clst = get_fat(fs->curr_clust);
  957.                                 }
  958.                                 if (clst <= 1) ABORT(FR_DISK_ERR);
  959.                                 fs->curr_clust = clst;                          /* Update current cluster */
  960.                         }
  961.                         sect = clust2sect(fs->curr_clust);              /* Get current sector */
  962.                         if (!sect) ABORT(FR_DISK_ERR);
  963.                         fs->dsect = sect + cs;
  964.                 }
  965.                 rcnt = 512 - (UINT)fs->fptr % 512;                      /* Get partial sector data from sector buffer */
  966.                 if (rcnt > btr) rcnt = btr;
  967.                 dr = disk_readp(rbuff, fs->dsect, (UINT)fs->fptr % 512, rcnt);
  968.                 if (dr) ABORT(FR_DISK_ERR);
  969.                 fs->fptr += rcnt;                                                       /* Advances file read pointer */
  970.                 btr -= rcnt; *br += rcnt;                                       /* Update read counter */
  971.                 if (rbuff) rbuff += rcnt;                                       /* Advances the data pointer if destination is memory */
  972.         }
  973.  
  974.         return FR_OK;
  975. }
  976. #endif
  977.  
  978.  
  979.  
  980. /*-----------------------------------------------------------------------*/
  981. /* Write File                                                            */
  982. /*-----------------------------------------------------------------------*/
  983. #if PF_USE_WRITE
  984.  
  985. FRESULT pf_write (
  986.         const void* buff,       /* Pointer to the data to be written */
  987.         UINT btw,                       /* Number of bytes to write (0:Finalize the current write operation) */
  988.         UINT* bw                        /* Pointer to number of bytes written */
  989. )
  990. {
  991.         CLUST clst;
  992.         DWORD sect, remain;
  993.         const BYTE *p = buff;
  994.         BYTE cs;
  995.         UINT wcnt;
  996.         FATFS *fs = FatFs;
  997.  
  998.  
  999.         *bw = 0;
  1000.         if (!fs) return FR_NOT_ENABLED;         /* Check file system */
  1001.         if (!(fs->flag & FA_OPENED)) return FR_NOT_OPENED;      /* Check if opened */
  1002.  
  1003.         if (!btw) {             /* Finalize request */
  1004.                 if ((fs->flag & FA__WIP) && disk_writep(0, 0)) ABORT(FR_DISK_ERR);
  1005.                 fs->flag &= ~FA__WIP;
  1006.                 return FR_OK;
  1007.         } else {                /* Write data request */
  1008.                 if (!(fs->flag & FA__WIP)) {    /* Round-down fptr to the sector boundary */
  1009.                         fs->fptr &= 0xFFFFFE00;
  1010.                 }
  1011.         }
  1012.         remain = fs->fsize - fs->fptr;
  1013.         if (btw > remain) btw = (UINT)remain;                   /* Truncate btw by remaining bytes */
  1014.  
  1015.         while (btw)     {                                                                       /* Repeat until all data transferred */
  1016.                 if ((UINT)fs->fptr % 512 == 0) {                        /* On the sector boundary? */
  1017.                         cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */
  1018.                         if (!cs) {                                                              /* On the cluster boundary? */
  1019.                                 if (fs->fptr == 0) {                            /* On the top of the file? */
  1020.                                         clst = fs->org_clust;
  1021.                                 } else {
  1022.                                         clst = get_fat(fs->curr_clust);
  1023.                                 }
  1024.                                 if (clst <= 1) ABORT(FR_DISK_ERR);
  1025.                                 fs->curr_clust = clst;                          /* Update current cluster */
  1026.                         }
  1027.                         sect = clust2sect(fs->curr_clust);              /* Get current sector */
  1028.                         if (!sect) ABORT(FR_DISK_ERR);
  1029.                         fs->dsect = sect + cs;
  1030.                         if (disk_writep(0, fs->dsect)) ABORT(FR_DISK_ERR);      /* Initiate a sector write operation */
  1031.                         fs->flag |= FA__WIP;
  1032.                 }
  1033.                 wcnt = 512 - (UINT)fs->fptr % 512;                      /* Number of bytes to write to the sector */
  1034.                 if (wcnt > btw) wcnt = btw;
  1035.                 if (disk_writep(p, wcnt)) ABORT(FR_DISK_ERR);   /* Send data to the sector */
  1036.                 fs->fptr += wcnt; p += wcnt;                            /* Update pointers and counters */
  1037.                 btw -= wcnt; *bw += wcnt;
  1038.                 if ((UINT)fs->fptr % 512 == 0) {
  1039.                         if (disk_writep(0, 0)) ABORT(FR_DISK_ERR);      /* Finalize the currtent secter write operation */
  1040.                         fs->flag &= ~FA__WIP;
  1041.                 }
  1042.         }
  1043.  
  1044.         return FR_OK;
  1045. }
  1046. #endif
  1047.  
  1048.  
  1049.  
  1050. /*-----------------------------------------------------------------------*/
  1051. /* Seek File R/W Pointer                                                 */
  1052. /*-----------------------------------------------------------------------*/
  1053. #if PF_USE_LSEEK
  1054.  
  1055. FRESULT pf_lseek (
  1056.         DWORD ofs               /* File pointer from top of file */
  1057. )
  1058. {
  1059.         CLUST clst;
  1060.         DWORD bcs, sect, ifptr;
  1061.         FATFS *fs = FatFs;
  1062.  
  1063.  
  1064.         if (!fs) return FR_NOT_ENABLED;         /* Check file system */
  1065.         if (!(fs->flag & FA_OPENED)) return FR_NOT_OPENED;      /* Check if opened */
  1066.  
  1067.         if (ofs > fs->fsize) ofs = fs->fsize;   /* Clip offset with the file size */
  1068.         ifptr = fs->fptr;
  1069.         fs->fptr = 0;
  1070.         if (ofs > 0) {
  1071.                 bcs = (DWORD)fs->csize * 512;           /* Cluster size (byte) */
  1072.                 if (ifptr > 0 &&
  1073.                         (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
  1074.                         fs->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */
  1075.                         ofs -= fs->fptr;
  1076.                         clst = fs->curr_clust;
  1077.                 } else {                                                        /* When seek to back cluster, */
  1078.                         clst = fs->org_clust;                   /* start from the first cluster */
  1079.                         fs->curr_clust = clst;
  1080.                 }
  1081.                 while (ofs > bcs) {                             /* Cluster following loop */
  1082.                         clst = get_fat(clst);           /* Follow cluster chain */
  1083.                         if (clst <= 1 || clst >= fs->n_fatent) ABORT(FR_DISK_ERR);
  1084.                         fs->curr_clust = clst;
  1085.                         fs->fptr += bcs;
  1086.                         ofs -= bcs;
  1087.                 }
  1088.                 fs->fptr += ofs;
  1089.                 sect = clust2sect(clst);                /* Current sector */
  1090.                 if (!sect) ABORT(FR_DISK_ERR);
  1091.                 fs->dsect = sect + (fs->fptr / 512 & (fs->csize - 1));
  1092.         }
  1093.  
  1094.         return FR_OK;
  1095. }
  1096. #endif
  1097.  
  1098.  
  1099.  
  1100. /*-----------------------------------------------------------------------*/
  1101. /* Create a Directroy Object                                             */
  1102. /*-----------------------------------------------------------------------*/
  1103. #if PF_USE_DIR
  1104.  
  1105. FRESULT pf_opendir (
  1106.         DIR *dj,                        /* Pointer to directory object to create */
  1107.         const char *path        /* Pointer to the directory path */
  1108. )
  1109. {
  1110.         FRESULT res;
  1111.         BYTE sp[12], dir[32];
  1112.         FATFS *fs = FatFs;
  1113.  
  1114.  
  1115.         if (!fs) {                              /* Check file system */
  1116.                 res = FR_NOT_ENABLED;
  1117.         } else {
  1118.                 dj->fn = sp;
  1119.                 res = follow_path(dj, dir, path);               /* Follow the path to the directory */
  1120.                 if (res == FR_OK) {                                             /* Follow completed */
  1121.                         if (dir[0]) {                                           /* It is not the root dir */
  1122.                                 if (dir[DIR_Attr] & AM_DIR) {   /* The object is a directory */
  1123.                                         dj->sclust = get_clust(dir);
  1124.                                 } else {                                                        /* The object is not a directory */
  1125.                                         res = FR_NO_FILE;
  1126.                                 }
  1127.                         }
  1128.                         if (res == FR_OK) {
  1129.                                 res = dir_rewind(dj);                   /* Rewind dir */
  1130.                         }
  1131.                 }
  1132.         }
  1133.  
  1134.         return res;
  1135. }
  1136.  
  1137.  
  1138.  
  1139.  
  1140. /*-----------------------------------------------------------------------*/
  1141. /* Read Directory Entry in Sequense                                      */
  1142. /*-----------------------------------------------------------------------*/
  1143.  
  1144. FRESULT pf_readdir (
  1145.         DIR *dj,                        /* Pointer to the open directory object */
  1146.         FILINFO *fno            /* Pointer to file information to return */
  1147. )
  1148. {
  1149.         FRESULT res;
  1150.         BYTE sp[12], dir[32];
  1151.         FATFS *fs = FatFs;
  1152.  
  1153.  
  1154.         if (!fs) {                              /* Check file system */
  1155.                 res = FR_NOT_ENABLED;
  1156.         } else {
  1157.                 dj->fn = sp;
  1158.                 if (!fno) {
  1159.                         res = dir_rewind(dj);
  1160.                 } else {
  1161.                         res = dir_read(dj, dir);        /* Get current directory item */
  1162.                         if (res == FR_NO_FILE) res = FR_OK;
  1163.                         if (res == FR_OK) {                             /* A valid entry is found */
  1164.                                 get_fileinfo(dj, dir, fno);     /* Get the object information */
  1165.                                 res = dir_next(dj);                     /* Increment read index for next */
  1166.                                 if (res == FR_NO_FILE) res = FR_OK;
  1167.                         }
  1168.                 }
  1169.         }
  1170.  
  1171.         return res;
  1172. }
  1173.  
  1174. #endif /* PF_USE_DIR */
  1175.  
  1176.