fatfs v0.09a Aug 27,2012:

- Fixed assertion failure due to OS/2 EA on FAT12/16.
- Changed f_open() and f_opendir() reject null object pointer to avoid crash.
- Changed option name _FS_SHARE to _FS_LOCK.
This commit is contained in:
savelij13 2025-09-11 09:49:45 +03:00
parent 13034d028c
commit 030f12c942
20 changed files with 634 additions and 297 deletions

View File

@ -4,8 +4,6 @@
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta name="description" content="Open souece FAT file system module for embedded projects">
<link rel="start" title="Site Top" href="../../">
<link rel="up" title="Freewares" href="../../fsw_e.html">
<link rel="alternate" hreflang="ja" title="Japanese version" href="00index_j.html">
<link rel="stylesheet" href="css_e.css" type="text/css" media="screen" title="ELM Default">
<title>ELM - FatFs Generic FAT File System Module</title>
@ -96,7 +94,7 @@
<p>The FatFs module is a free software opened for education, research and development. You can use, modify and/or redistribute it for personal projects or commercial products without any restriction under your responsibility. For further information, refer to the application note.</p>
<ul>
<li><a href="http://elm-chan.org/fsw/ff/bd/"><em>FatFs User Forum</em></a></li>
<li>Read first: <a href="en/appnote.html">FatFs module application note</a> <span class="mfd">July 28, 2012</span></li>
<li>Read first: <a href="en/appnote.html">FatFs module application note</a> <span class="mfd">August 27, 2012</span></li>
<li><a href="http://nemuisan.blog.bai.ne.jp/">Nemuisan's Blog</a> (Well written implementations for STM32F/SDIO and LPC2300/MCI)</li>
<li><a href="http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html">ARM-Projects by Martin THOMAS</a> (examples for LPC2000, AT91SAM and STM32)</li>
<li><a href="http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx">FAT32 Specification by Microsoft</a> (The reference document on FAT file system)</li>
@ -107,8 +105,5 @@
</ul>
</div>
<hr>
<p class="foot"><a href="../../fsw_e.html">Return</a></p>
</body>
</html>

View File

@ -4,8 +4,6 @@
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta name="description" content="組み込みシステム向けFATファイル・システム">
<link rel="start" title="Site Top" href="../../index_j.html">
<link rel="up" title="Freewares" href="../../fsw.html">
<link rel="alternate" hreflang="en" title="英文" href="00index_e.html">
<link rel="stylesheet" href="css_j.css" type="text/css" media="screen" title="ELM Default">
<title>ELM - FatFs 汎用FATファイルシステム・モジュール</title>
@ -95,7 +93,7 @@
<p>FatFsモジュールはフリー・ソフトウェアとして教育・研究・開発用に公開しています。どのような利用目的個人利用から商用まででも使用・改変・配布について一切の制限はありませんが、全て利用者の責任の下での利用とします。詳しくはアプリケーション・ートを参照してください。</p>
<ul>
<li><a href="http://elm-chan.org/fsw/ff/bd/"><em>FatFsユーザ・フォーラム</em></a></li>
<li>最初に読め: <a href="ja/appnote.html">FatFsモジュール・アプリケーション・ート</a> <span class="mfd">2012. 7. 28</span></li>
<li>最初に読め: <a href="ja/appnote.html">FatFsモジュール・アプリケーション・ート</a> <span class="mfd">2012. 8. 27</span></li>
<li><a href="http://nemuisan.blog.bai.ne.jp/">ねむいさんのぶろぐ</a> (Well written implementations for STM32F/SDIO and LPC2300/MCI)</li>
<li><a href="http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html">ARM-Projects by Martin THOMAS</a> (examples for LPC2000, AT91SAM and STM32)</li>
<li><a href="http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx">FATファイル・システム仕様書 by Microsoft</a> (FATの理解・実装に必要な唯一のリファレンス)</li>
@ -106,8 +104,5 @@
</ul>
</div>
<hr>
<p class="foot"><a href="../../fsw.html">戻る</a></p>
</body>
</html>

View File

@ -41,7 +41,7 @@ The FatFs module assumes that size of char/short/long are 8/16/32 bit and int is
<h4>System organizations</h4>
<p>The dependency diagram shown below is a typical configuration of the embedded system with FatFs module.</p>
<img src="../img/modules.png" width="507" height="224" alt="dependency diagram">
<p><img src="../img/modules.png" width="507" height="224" alt="dependency diagram"></p>
<h4>Which function is required?</h4>
<p>You need to provide only low level disk I/O functions that required by FatFs module and nothing else. If a working disk module for the target is already existing, you need to write only glue functions to attach it to the FatFs module. If not, you need to port any other disk module or write it from scratch. All defined functions are not that always required. For example, disk write function is not required in read-only configuration. Following table shows which function is required depends on configuration options.</p>
@ -72,17 +72,17 @@ The FatFs module assumes that size of char/short/long are 8/16/32 bit and int is
</div>
<div class="para" id="memory">
<h3>Memory Usage (R0.09)</h3>
<h3>Memory Usage (R0.09a)</h3>
<table class="lst2">
<tr><th></th><th>ARM7<small><br>32bit</small></th><th>ARM7<small><br>Thumb</small></th><th>Cortex-M3<small><br>Thumb-2</small></th><th>AVR</th><th>H8/300H</th><th>PIC24</th><th>RL78</th><th>V850ES</th><th>SH-2A</th><th>RX600</th><th>IA-32</th></tr>
<tr><th></th><th>ARM7<small><br>32bit</small></th><th>ARM7<small><br>Thumb</small></th><th>CM3<small><br>Thumb-2</small></th><th>AVR</th><th>H8/300H</th><th>PIC24</th><th>RL78</th><th>V850ES</th><th>SH-2A</th><th>RX600</th><th>IA-32</th></tr>
<tr><td>Compiler</td><td>GCC</td><td>GCC</td><td>GCC</td><td>GCC</td><td>CH38</td><td>C30</td><td>CC78K0R</td><td>CA850</td><td>SHC</td><td>RXC</td><td>VC6</td></tr>
<tr><td>_WORD_ACCESS</td><td>0</td><td>0</td><td>0</td><td>1</td><td>0</td><td>0</td><td>0</td><td>1</td><td>0</td><td>1</td><td>1</td></tr>
<tr class="lst3"><td>text (Full, R/W)</td><td>10459</td><td>7201</td><td>6623</td><td>12646</td><td>10686</td><td>11466</td><td>12967</td><td>7732</td><td>8752</td><td>5747</td><td>7545</td></tr>
<tr><td>text (Min, R/W)</td><td>6503</td><td>4745</td><td>4297</td><td>8306</td><td>6986</td><td>7440</td><td>8745</td><td>4938</td><td>5576</td><td>3746</td><td>4923</td></tr>
<tr><td>text (Full, R/O)</td><td>4535</td><td>3181</td><td>2869</td><td>5960</td><td>4876</td><td>5286</td><td>6060</td><td>3554</td><td>3804</td><td>2659</td><td>3450</td></tr>
<tr><td>text (Min, R/O)</td><td>3303</td><td>2493</td><td>2171</td><td>4366</td><td>3770</td><td>3984</td><td>4604</td><td>2684</td><td>2940</td><td>2025</td><td>2664</td></tr>
<tr><td>bss</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td></tr>
<tr><td>Work area<br>(_FS_TINY == 0)</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td></tr>
<tr class="lst3"><td>text (Full, R/W)</td><td>10375</td><td>7019</td><td>6561</td><td>13267</td><td>10525</td><td>11205</td><td>12812</td><td>7783</td><td>8715</td><td>5782</td><td>7615</td></tr>
<tr> <td>text (Min, R/W)</td> <td>6487</td><td>4727</td><td>4283</td> <td>8521</td> <td>6967</td> <td>7398</td> <td>8800</td><td>5019</td><td>5635</td><td>3784</td><td>5003</td></tr>
<tr> <td>text (Full, R/O)</td> <td>4551</td><td>3125</td><td>2895</td> <td>6219</td> <td>4895</td> <td>5268</td> <td>6123</td><td>3629</td><td>3843</td><td>2699</td><td>3527</td></tr>
<tr> <td>text (Min, R/O)</td> <td>3321</td><td>2457</td><td>2197</td> <td>4527</td> <td>3797</td> <td>3999</td> <td>4663</td><td>2773</td><td>2999</td><td>2064</td><td>2736</td></tr>
<tr> <td>bss</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td></tr>
<tr> <td>Work area<br>(_FS_TINY == 0)</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td></tr>
<tr><td>Work area<br>(_FS_TINY == 1)</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*32</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*32</td><td>V*560 +<br>F*32</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td></tr>
</table>
<p>These are the memory usage on some target systems with following condition. The memory sizes are in unit of byte, <em>V</em> means number of mounted volumes and <em>F</em> means number of open files. All samples are optimezed in code size.</p>
@ -100,7 +100,7 @@ _FS_RPATH 0 (Disable relative path)
_VOLUMES D (Number of logical drives to be used)
_MULTI_PARTITION 0 (Single partition per drive)
_FS_REENTRANT 0 (Disable reentrancy)
_FS_SHARE 0 (Disable shareing control)
_FS_LOCK 0 (Disable shareing control)
</pre>
</div>
@ -172,7 +172,7 @@ _FS_SHARE 0 (Disable shareing control)
<div class="para" id="dup">
<h3>Duplicated File Access</h3>
<p>FatFs module does not support the shareing controls of duplicated file access in default. It is permitted when open method to a file is only read mode. The duplicated open in write mode to a file is always prohibited and open file must not be renamed, deleted, or the FAT structure on the volume can be collapted.</p>
<p>The file shareing control can also be available when <tt>_FS_SHARE</tt> is set to 1 or grater. The value specifies the number of files to manage simultaneously. In this case, if any open, rename or remove that violating the file shareing rule that described above is attempted, the file function will fail with <tt>FR_LOCKED</tt>. If number of open files gets larger than <tt>_FS_SHARE</tt>, the f_open function will fail with <tt>FR_TOO_MANY_OPEN_FILES</tt>.</p>
<p>The file shareing control can also be available when <tt>_FS_LOCK</tt> is set to 1 or grater. The value specifies the number of files to manage simultaneously. In this case, if any open, rename or remove that violating the file shareing rule that described above is attempted, the file function will fail with <tt>FR_LOCKED</tt>. If number of open files gets larger than <tt>_FS_LOCK</tt>, the f_open function will fail with <tt>FR_TOO_MANY_OPEN_FILES</tt>.</p>
</div>
<div class="para" id="fs1">

View File

@ -38,7 +38,7 @@ DSTATUS disk_initialize (
<div class="para desc">
<h4>Description</h4>
<p>The disk_initialize function initializes a physical drive and put it ready to read/write. When the function succeeded, <tt>STA_NOINIT</tt> flag in the return value is cleard.</p>
<p><em>Application program MUST NOT call this function, or FAT structure on the volume can be corrapted. To re-initialize the file system, use f_mount function.</em>This function is called on volume mount process in the FatFs module to manage the media change.</p>
<p><em>Application program MUST NOT call this function, or FAT structure on the volume can be corrapted. To re-initialize the file system, use f_mount function instead.</em>This function is called on volume mount process in the FatFs module to manage the media change.</p>
</div>
<p class="foot"><a href="../00index_e.html">Return</a></p>

View File

@ -30,7 +30,7 @@ DRESULT disk_read (
<dt>Drive</dt>
<dd>Specifies the physical drive number.</dd>
<dt>Buffer</dt>
<dd>Pointer to the <em>byte array</em> to store the read data. The buffer size of number of bytes to be read, sector size * sector count, is required. Note that the specified memory address is not that always aligned to word boundary. If the hardware does not support misaligned data transfer, it must be solved in this function.</dd>
<dd>Pointer to the <em>byte array</em> to store the read data. The size of buffer must be in sector size * sector count.</dd>
<dt>SectorNumber</dt>
<dd>Specifies the start sector number in logical block address (LBA).</dd>
<dt>SectorCount</dt>
@ -54,6 +54,17 @@ DRESULT disk_read (
</div>
<div class="para desc">
<h4>Description</h4>
<p>The specified memory address is not that always aligned to word boundary because the type of pointer is defined as BYTE. The misaligned read/write request can occure at <a href="appnote.html#fs1">direct transfer</a>. If the bus architecture, especially DMA controller, does not allow misaligned memory access, it should be solved in this function. There are some workarounds below to avoid this problem.</p>
<ul>
<li>In this function, convert word transfer to byte transfer. - Recommended.</li>
<li>On f_read(), avoid long read request that includes a whole of sector. - Direct transfer will never occure.</li>
<li>On f_read(), make sure that the lower two bits of start address is equal to the lower two bits of file read/write pointer. - Word aligned direct transfer is guaranteed.</li>
</ul>
</div>
<p class="foot"><a href="../00index_e.html">Return</a></p>
</body>
</html>

View File

@ -30,7 +30,7 @@ DRESULT disk_write (
<dt>Drive</dt>
<dd>Specifies the physical drive number.</dd>
<dt>Buffer</dt>
<dd>Pointer to the <em>byte array</em> to be written. Note that the specified memory address is not that always aligned to word boundary. If the hardware does not support misaligned data transfer, it must be solved in this function.</dd>
<dd>Pointer to the <em>byte array</em> to be written.</dd>
<dt>SectorNumber</dt>
<dd>Specifies the start sector number in logical block address (LBA).</dd>
<dt>SectorCount</dt>
@ -58,7 +58,7 @@ DRESULT disk_write (
<div class="para desc">
<h4>Description</h4>
<p>This function is not required in read only configuration.</p>
<p>This function is not required in read only configuration. The specified memory address is not that always aligned to word boundary because the type of pointer is defined as BYTE. For more information, read <a href="dread.html">description in disk_read function</a>.</p>
</div>

View File

@ -68,7 +68,7 @@
<dt id="tm">FR_TIMEOUT</dt>
<dd>The function canceled due to a timeout of <a href="appnote.html#reentrant">thread-safe control</a>. (Related option: _TIMEOUT)</dd>
<dt id="lo">FR_LOCKED</dt>
<dd>The file access is rejected by <a href="appnote.html#dup">file sharing control</a>. (Related option: _FS_SHARE)</dd>
<dd>The file access is rejected by <a href="appnote.html#dup">file sharing control</a>. (Related option: _FS_LOCK)</dd>
<dt id="nc">FR_NOT_ENOUGH_CORE</dt>
<dd>Not enough memory for the operation. There is one of the following reasons:
<ul>
@ -77,7 +77,7 @@
</ul>
</dd>
<dt id="tf">FR_TOO_MANY_OPEN_FILES</dt>
<dd>Number of open files has been reached maximum value and no more file can be opened. (Related option: _FS_SHARE)</dd>
<dd>Number of open files has been reached maximum value and no more file can be opened. (Related option: _FS_LOCK)</dd>
<dt id="ip">FR_INVALID_PARAMETER</dt>
<dd>The given parameter is invalid or there is any inconsistent.</dd>
</dl>

View File

@ -54,7 +54,7 @@ FRESULT f_read (
<div class="para desc">
<h4>Description</h4>
<p>The file pointer of the file object increases in number of bytes read. After the function succeeded, <tt>*ByteRead</tt> should be checked to detect the end of file. In case of <tt>*ByteRead &lt; ByteToRead</tt>, it means the read/write pointer reached end of the file during read operation.</p>
<p>The file read/write pointer of the file object advances number of bytes read. After the function succeeded, <tt>*ByteRead</tt> should be checked to detect the end of file. In case of <tt>*ByteRead &lt; ByteToRead</tt>, it means the read/write pointer reached end of the file during read operation.</p>
</div>

View File

@ -54,7 +54,7 @@ FRESULT f_write (
<div class="para desc">
<h4>Description</h4>
<p>The read/write pointer in the file object is increased in number of bytes written. After the function succeeded, <tt>*ByteWritten</tt> should be checked to detect the disk full. In case of <tt>*ByteWritten &lt; ByteToWrite</tt>, it means the volume got full during the write operation. The function can take a time when the volume is full or close to full.</p>
<p>The read/write pointer of the file object advances number of bytes written. After the function succeeded, <tt>*ByteWritten</tt> should be checked to detect the disk full. In case of <tt>*ByteWritten &lt; ByteToWrite</tt>, it means the volume got full during the write operation. The function can take a time when the volume is full or close to full.</p>
</div>

BIN
doc/img/modules.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -42,7 +42,7 @@ FatFsモジュールはANSI C(C89)準拠で記述されているので、ANSI C
<h4>システム構成</h4>
<p>下に示す依存関係図は、FatFsモジュール利用の組み込みシステムにおける代表的な構成を示します。</p>
<img src="../img/modules.png" width="507" height="224" alt="システム構成図">
<p><img src="../img/modules.png" width="507" height="224" alt="システム構成図"></p>
<h4>ユーザの作成する関数</h4>
<p>必要なのは FatFsモジュールの要求するディスク関数を用意することだけで、それ以外にすることはありません。既に動作しているディスク関数があるならその APIを FatFsに合わせるだけで済みますが、無い場合はほかから移植するか、最初から書くかする必要があります。定義されている全ての関数が常に必要なわけではありません。例えば、リード・オンリー構成では書き込み系関数は必要ありません。次の表に構成オプションと要求される関数の対応を示します。</p>
@ -73,21 +73,22 @@ FatFsモジュールはANSI C(C89)準拠で記述されているので、ANSI C
</div>
<div class="para" id="memory">
<h3>メモリ使用量 (R0.09)</h3>
<h3>メモリ使用量</h3>
<p>次の表にいくつかのターゲットにおけるメモリ使用量の例を示します。テスト時の構成オプションはその下の通りです。数値の単位はバイトで、<em>V</em>は同時マウント・ボリューム数、<em>F</em>は同時オープン・ファイル数を示します。コンパイラの最適化オプションはコード・サイズとしています。</p>
<table class="lst2">
<tr><th></th><th>ARM7<small><br>32bit</small></th><th>ARM7<small><br>Thumb</small></th><th>Cortex-M3<small><br>Thumb-2</small></th><th>AVR</th><th>H8/300H</th><th>PIC24</th><th>RL78</th><th>V850ES</th><th>SH-2A</th><th>RX600</th><th>IA-32</th></tr>
<tr><th></th><th>ARM7<small><br>32bit</small></th><th>ARM7<small><br>Thumb</small></th><th>CM3<small><br>Thumb-2</small></th><th>AVR</th><th>H8/300H</th><th>PIC24</th><th>RL78</th><th>V850ES</th><th>SH-2A</th><th>RX600</th><th>IA-32</th></tr>
<tr><td>Compiler</td><td>GCC</td><td>GCC</td><td>GCC</td><td>GCC</td><td>CH38</td><td>C30</td><td>CC78K0R</td><td>CA850</td><td>SHC</td><td>RXC</td><td>VC6</td></tr>
<tr><td>_WORD_ACCESS</td><td>0</td><td>0</td><td>0</td><td>1</td><td>0</td><td>0</td><td>0</td><td>1</td><td>0</td><td>1</td><td>1</td></tr>
<tr class="lst3"><td>text (Full, R/W)</td><td>10459</td><td>7201</td><td>6623</td><td>12646</td><td>10686</td><td>11466</td><td>12967</td><td>7732</td><td>8752</td><td>5747</td><td>7545</td></tr>
<tr><td>text (Min, R/W)</td><td>6503</td><td>4745</td><td>4297</td><td>8306</td><td>6986</td><td>7440</td><td>8745</td><td>4938</td><td>5576</td><td>3746</td><td>4923</td></tr>
<tr><td>text (Full, R/O)</td><td>4535</td><td>3181</td><td>2869</td><td>5960</td><td>4876</td><td>5286</td><td>6060</td><td>3554</td><td>3804</td><td>2659</td><td>3450</td></tr>
<tr><td>text (Min, R/O)</td><td>3303</td><td>2493</td><td>2171</td><td>4366</td><td>3770</td><td>3984</td><td>4604</td><td>2684</td><td>2940</td><td>2025</td><td>2664</td></tr>
<tr><td>bss</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td></tr>
<tr><td>Work area<br>(_FS_TINY == 0)</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td></tr>
<tr class="lst3"><td>text (Full, R/W)</td><td>10375</td><td>7019</td><td>6561</td><td>13267</td><td>10525</td><td>11205</td><td>12812</td><td>7783</td><td>8715</td><td>5782</td><td>7615</td></tr>
<tr> <td>text (Min, R/W)</td> <td>6487</td><td>4727</td><td>4283</td> <td>8521</td> <td>6967</td> <td>7398</td> <td>8800</td><td>5019</td><td>5635</td><td>3784</td><td>5003</td></tr>
<tr> <td>text (Full, R/O)</td> <td>4551</td><td>3125</td><td>2895</td> <td>6219</td> <td>4895</td> <td>5268</td> <td>6123</td><td>3629</td><td>3843</td><td>2699</td><td>3527</td></tr>
<tr> <td>text (Min, R/O)</td> <td>3321</td><td>2457</td><td>2197</td> <td>4527</td> <td>3797</td> <td>3999</td> <td>4663</td><td>2773</td><td>2999</td><td>2064</td><td>2736</td></tr>
<tr> <td>bss</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*2 + 2</td><td>D*2 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td><td>D*4 + 2</td></tr>
<tr> <td>Work area<br>(_FS_TINY == 0)</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*544</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td><td>V*560 +<br>F*550</td></tr>
<tr><td>Work area<br>(_FS_TINY == 1)</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*32</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*32</td><td>V*560 +<br>F*32</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td><td>V*560 +<br>F*36</td></tr>
</table>
<pre>
FatFs R0.09a options:
_FS_READONLY 0 (R/W), 1 (R/O)
_FS_MINIMIZE 0 (Full function), 3 (Minimized function)
_USE_STRFUNC 0 (Disable string functions)
@ -101,7 +102,7 @@ _FS_RPATH 0 (Disable relative path)
_VOLUMES D (Number of logical drives to be used)
_MULTI_PARTITION 0 (Single partition per drive)
_FS_REENTRANT 0 (Disable reentrancy)
_FS_SHARE 0 (Disable shareing control)
_FS_LOCK 0 (Disable file lock control)
</pre>
</div>
@ -179,7 +180,7 @@ _FS_SHARE 0 (Disable shareing control)
<div class="para" id="dup">
<h3>多重ファイル・アクセス</h3>
<p>FatFsモジュールではデフォルトでは多重アクセス制御機能をサポートしていません。ファイルに対する多重アクセスは、そのアクセス・モードによって制限されます。一つのファイルに対する多重オープンは、それらが全てリード・モードのときに限って許可されます。書き込みモードを含む多重オープン、また開かれているファイルに対するリネームや削除を行ってはなりません。さもないと、そのボリュームのFAT構造が破壊される可能性があります。</p>
<p><tt>_FS_SHARE</tt>に1以上の値(値は同時に管理できるファイル数)をセットすることで多重アクセス制御機能が有効になり、ファイル単位の排他制御を自動で行うこともできます。この場合、上記のルールを破ったオープン・リネーム・削除を試みると、その関数は<tt>FR_LOCKED</tt>で失敗します。<tt>_FS_SHARE</tt>を越えた数のファイルをオープンしようとすると、<tt>FR_TOO_MANY_OPEN_FILES</tt>で失敗します。</p>
<p><tt>_FS_LOCK</tt>に1以上の値(値は同時に管理できるファイル数)をセットすることで多重アクセス制御機能が有効になり、ファイル単位の排他制御を自動で行うこともできます。この場合、上記のルールを破ったオープン・リネーム・削除を試みると、その関数は<tt>FR_LOCKED</tt>で失敗します。<tt>_FS_LOCK</tt>を越えた数のファイルをオープンしようとすると、<tt>FR_TOO_MANY_OPEN_FILES</tt>で失敗します。</p>
</div>
<div class="para" id="fs1">

View File

@ -1,11 +1,16 @@
R0.09, Sep 6, 2011
R0.09a, Aug 27, 2012
Fixed assertion failure due to OS/2 EA on FAT12/16.
Changed API rejects null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
R0.09, Sep 06, 2011
f_mkfs() supports multiple partition to finish the multiple partition feature.
Added f_fdisk(). (_MULTI_PARTITION = 2)
R0.08b, Jan 15, 2011
Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf function.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path names.
R0.08a, Aug 16, 2010

View File

@ -1,4 +1,4 @@
FatFs Module Source Files R0.09 (C)ChaN, 2011
FatFs Module Source Files R0.09a (C)ChaN, 2012
FILES
@ -7,7 +7,8 @@ FILES
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
integer.h Alternative type definitions for integer variables.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
Low level disk I/O module is not included in this archive because the FatFs
@ -23,7 +24,7 @@ AGREEMENTS
small embedded systems. This is a free software and is opened for education,
research and commercial developments under license policy of following trems.
Copyright (C) 2011, ChaN, all right reserved.
Copyright (C) 2012, ChaN, all right reserved.
* The FatFs module is a free software and there is NO WARRANTY.
* No restriction on use. You can use, modify and redistribute it for
@ -128,3 +129,7 @@ REVISION HISTORY
Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
Added f_fdisk(). (_MULTI_PARTITION = 2)
Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16.
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.

236
src/diskio.c Normal file
View File

@ -0,0 +1,236 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2012 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control module to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "diskio.h" /* FatFs lower layer API */
#include "usbdisk.h" /* Example: USB drive control */
#include "atadrive.h" /* Example: ATA drive control */
#include "sdcard.h" /* Example: MMC/SDC contorl */
/* Definitions of physical drive number for each media */
#define ATA 0
#define MMC 1
#define USB 2
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
int result;
switch (drv) {
case ATA :
result = ATA_disk_initialize();
// translate the reslut code here
return stat;
case MMC :
result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case USB :
result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
int result;
switch (drv) {
case ATA :
result = ATA_disk_status();
// translate the reslut code here
return stat;
case MMC :
result = MMC_disk_status();
// translate the reslut code here
return stat;
case USB :
result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..128) */
)
{
DRESULT res;
int result;
switch (drv) {
case ATA :
// translate the arguments here
result = ATA_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case MMC :
// translate the arguments here
result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case USB :
// translate the arguments here
result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..128) */
)
{
DRESULT res;
int result;
switch (drv) {
case ATA :
// translate the arguments here
result = ATA_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case MMC :
// translate the arguments here
result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case USB :
// translate the arguments here
result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (drv) {
case ATA :
// pre-process here
result = ATA_disk_ioctl(ctrl, buff);
// post-process here
return res;
case MMC :
// pre-process here
result = MMC_disk_ioctl(ctrl, buff);
// post-process here
return res;
case USB :
// pre-process here
result = USB_disk_ioctl(ctrl, buff);
// post-process here
return res;
}
return RES_PARERR;
}
#endif

View File

@ -1,11 +1,16 @@
/*-----------------------------------------------------------------------
/ Low level disk interface modlue include file
/ Low level disk interface modlue include file (C)ChaN, 2012
/-----------------------------------------------------------------------*/
#ifndef _DISKIO
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#define _READONLY 0 /* 1: Remove write functions */
#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */
#ifdef __cplusplus
extern "C" {
#endif
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
#include "integer.h"
@ -26,19 +31,15 @@ typedef enum {
/*---------------------------------------*/
/* Prototypes for disk control functions */
int assign_drives (int, int);
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
#if _READONLY == 0
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
#endif
DRESULT disk_ioctl (BYTE, BYTE, void*);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
@ -46,17 +47,18 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
/* Command code for disk_ioctrl fucntion */
/* Generic command (defined for FatFs) */
/* Generic command (used by FatFs) */
#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
/* Generic command */
/* Generic command (not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
@ -70,9 +72,17 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
/* NAND specific ioctl command */
#define NAND_FORMAT 30 /* Create physical format */
/* MMC card type flags (MMC_GET_TYPE) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
#define _DISKIO
#ifdef __cplusplus
}
#endif
#endif

328
src/ff.c
View File

@ -1,11 +1,11 @@
/*----------------------------------------------------------------------------/
/ FatFs - FAT file system module R0.09 (C)ChaN, 2011
/ FatFs - FAT file system module R0.09a (C)ChaN, 2012
/-----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/ Copyright (C) 2012, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
@ -86,10 +86,13 @@
/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
/ f_lseek() reports required table size on creating CLMP.
/ Extended format syntax of f_printf function.
/ Ignores duplicated directory separators in given path names.
/ Ignores duplicated directory separators in given path name.
/
/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
/ Added f_fdisk(). (_MULTI_PARTITION = 2)
/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
/ Changed f_open() and f_opendir reject null object pointer to avoid crash.
/ Changed option name _FS_SHARE to _FS_LOCK.
/---------------------------------------------------------------------------*/
#include "ff.h" /* FatFs configurations and declarations */
@ -102,7 +105,7 @@
---------------------------------------------------------------------------*/
#if _FATFS != 6502 /* Revision ID */
#if _FATFS != 4004 /* Revision ID */
#error Wrong include file (ff.h).
#endif
@ -133,10 +136,10 @@
#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
/* File shareing feature */
#if _FS_SHARE
/* File access control feature */
#if _FS_LOCK
#if _FS_READONLY
#error _FS_SHARE must be 0 on read-only cfg.
#error _FS_LOCK must be 0 on read-only cfg.
#endif
typedef struct {
FATFS *fs; /* File ID 1, volume (NULL:blank entry) */
@ -147,10 +150,6 @@ typedef struct {
#endif
/* Misc definitions */
#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
/* DBCS code ranges and SBCS extend char conversion table */
@ -420,7 +419,7 @@ typedef struct {
#define BPB_FSVer 42 /* File system version (2) */
#define BPB_RootClus 44 /* Root dir first cluster (4) */
#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */
#define BPB_BkBootSec 50 /* Offset of backup boot sectot (2) */
#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */
#define BS_DrvNum32 64 /* Physical drive number (2) */
#define BS_BootSig32 66 /* Extended boot signature (1) */
#define BS_VolID32 67 /* Volume serial number (4) */
@ -437,8 +436,10 @@ typedef struct {
#define DIR_Name 0 /* Short file name (11) */
#define DIR_Attr 11 /* Attribute (1) */
#define DIR_NTres 12 /* NT flag (1) */
#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */
#define DIR_CrtTime 14 /* Created time (2) */
#define DIR_CrtDate 16 /* Created date (2) */
#define DIR_LstAccDate 18 /* Last accessed date (2) */
#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
#define DIR_WrtTime 22 /* Modified time (2) */
#define DIR_WrtDate 24 /* Modified date (2) */
@ -451,8 +452,8 @@ typedef struct {
#define LDIR_FstClusLO 26 /* Filled by zero (0) */
#define SZ_DIR 32 /* Size of a directory entry */
#define LLE 0x40 /* Last long entry flag in LDIR_Ord */
#define DDE 0xE5 /* Deleted directory enrty mark in DIR_Name[0] */
#define NDDE 0x05 /* Replacement of a character collides with DDE */
#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */
#define NDDE 0x05 /* Replacement of the character collides with DDE */
/*------------------------------------------------------------*/
@ -478,9 +479,9 @@ static
BYTE CurrVol; /* Current drive */
#endif
#if _FS_SHARE
#if _FS_LOCK
static
FILESEM Files[_FS_SHARE]; /* File lock semaphores */
FILESEM Files[_FS_LOCK]; /* File lock semaphores */
#endif
#if _USE_LFN == 0 /* No LFN feature */
@ -531,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) {
const BYTE *s = (const BYTE*)src;
#if _WORD_ACCESS == 1
while (cnt >= sizeof(int)) {
while (cnt >= sizeof (int)) {
*(int*)d = *(int*)s;
d += sizeof(int); s += sizeof(int);
cnt -= sizeof(int);
d += sizeof (int); s += sizeof (int);
cnt -= sizeof (int);
}
#endif
while (cnt--)
@ -589,7 +590,8 @@ void unlock_fs (
FRESULT res /* Result code to be returned */
)
{
if (res != FR_NOT_ENABLED &&
if (fs &&
res != FR_NOT_ENABLED &&
res != FR_INVALID_DRIVE &&
res != FR_INVALID_OBJECT &&
res != FR_TIMEOUT) {
@ -601,9 +603,9 @@ void unlock_fs (
/*-----------------------------------------------------------------------*/
/* File shareing control functions */
/* File lock control functions */
/*-----------------------------------------------------------------------*/
#if _FS_SHARE
#if _FS_LOCK
static
FRESULT chk_lock ( /* Check if the file can be accessed */
@ -614,7 +616,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
UINT i, be;
/* Search file semaphore table */
for (i = be = 0; i < _FS_SHARE; i++) {
for (i = be = 0; i < _FS_LOCK; i++) {
if (Files[i].fs) { /* Existing entry */
if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */
Files[i].clu == dj->sclust &&
@ -623,7 +625,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
be++;
}
}
if (i == _FS_SHARE) /* The file is not opened */
if (i == _FS_LOCK) /* The file is not opened */
return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */
/* The file has been opened. Reject any open against writing file and all write mode open */
@ -636,8 +638,8 @@ int enq_lock (void) /* Check if an entry is available for a new file */
{
UINT i;
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
return (i == _FS_SHARE) ? 0 : 1;
for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
return (i == _FS_LOCK) ? 0 : 1;
}
@ -650,15 +652,15 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro
UINT i;
for (i = 0; i < _FS_SHARE; i++) { /* Find the file */
for (i = 0; i < _FS_LOCK; i++) { /* Find the file */
if (Files[i].fs == dj->fs &&
Files[i].clu == dj->sclust &&
Files[i].idx == dj->index) break;
}
if (i == _FS_SHARE) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
if (i == _FS_SHARE) return 0; /* No space to register (int err) */
if (i == _FS_LOCK) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
if (i == _FS_LOCK) return 0; /* No space to register (int err) */
Files[i].fs = dj->fs;
Files[i].clu = dj->sclust;
Files[i].idx = dj->index;
@ -682,7 +684,7 @@ FRESULT dec_lock ( /* Decrement file open counter */
FRESULT res;
if (--i < _FS_SHARE) {
if (--i < _FS_LOCK) {
n = Files[i].ctr;
if (n == 0x100) n = 0;
if (n) n--;
@ -703,7 +705,7 @@ void clear_lock ( /* Clear lock entries of the volume */
{
UINT i;
for (i = 0; i < _FS_SHARE; i++) {
for (i = 0; i < _FS_LOCK; i++) {
if (Files[i].fs == fs) Files[i].fs = 0;
}
}
@ -825,7 +827,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status
BYTE *p;
if (clst < 2 || clst >= fs->n_fatent) /* Chack range */
if (clst < 2 || clst >= fs->n_fatent) /* Check range */
return 1;
switch (fs->fs_type) {
@ -876,7 +878,7 @@ FRESULT put_fat (
} else {
switch (fs->fs_type) {
case FS_FAT12 :
bc = clst; bc += bc / 2;
bc = (UINT)clst; bc += bc / 2;
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
p = &fs->win[bc % SS(fs)];
@ -930,7 +932,7 @@ FRESULT remove_chain (
FRESULT res;
DWORD nxt;
#if _USE_ERASE
DWORD scl = clst, ecl = clst, resion[2];
DWORD scl = clst, ecl = clst, rt[2];
#endif
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
@ -950,12 +952,12 @@ FRESULT remove_chain (
fs->fsi_flag = 1;
}
#if _USE_ERASE
if (ecl + 1 == nxt) { /* Next cluster is contiguous */
if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
ecl = nxt;
} else { /* End of contiguous clusters */
resion[0] = clust2sect(fs, scl); /* Start sector */
resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */
rt[0] = clust2sect(fs, scl); /* Start sector */
rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */
scl = ecl = nxt;
}
#endif
@ -1064,7 +1066,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
static
FRESULT dir_sdi (
DIR *dj, /* Pointer to directory object */
WORD idx /* Directory index number */
WORD idx /* Index of directory table */
)
{
DWORD clst;
@ -1106,7 +1108,7 @@ FRESULT dir_sdi (
/*-----------------------------------------------------------------------*/
/* Directory handling - Move directory index next */
/* Directory handling - Move directory table index next */
/*-----------------------------------------------------------------------*/
static
@ -1173,6 +1175,40 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
/*-----------------------------------------------------------------------*/
/* Directory handling - Load/Store start cluster number */
/*-----------------------------------------------------------------------*/
static
DWORD ld_clust (
FATFS *fs, /* Pointer to the fs object */
BYTE *dir /* Pointer to the directory entry */
)
{
DWORD cl;
cl = LD_WORD(dir+DIR_FstClusLO);
if (fs->fs_type == FS_FAT32)
cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
return cl;
}
#if !_FS_READONLY
static
void st_clust (
BYTE *dir, /* Pointer to the directory entry */
DWORD cl /* Value to be set */
)
{
ST_WORD(dir+DIR_FstClusLO, cl);
ST_WORD(dir+DIR_FstClusHI, cl >> 16);
}
#endif
/*-----------------------------------------------------------------------*/
/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
/*-----------------------------------------------------------------------*/
@ -1784,7 +1820,7 @@ FRESULT create_name (
if (c >= 0x80) { /* Extended char? */
b |= 3; /* Eliminate NT flag */
#ifdef _EXCVT
c = excvt[c-0x80]; /* Upper conversion (SBCS) */
c = excvt[c - 0x80]; /* Upper conversion (SBCS) */
#else
#if !_DF1S /* ASCII only cfg */
return FR_INVALID_NAME;
@ -1940,7 +1976,6 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
if ((UINT)*path < ' ') { /* Nul path means the start directory itself */
res = dir_sdi(dj, 0);
dj->dir = 0;
} else { /* Follow path */
for (;;) {
res = create_name(dj, &path); /* Get a segment */
@ -1948,7 +1983,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
res = dir_find(dj); /* Find it */
ns = *(dj->fn+NS);
if (res != FR_OK) { /* Failed to find the object */
if (res != FR_NO_FILE) break; /* Abort if any hard error occured */
if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */
/* Object not found */
if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */
dj->sclust = 0; dj->dir = 0; /* It is the root dir */
@ -1964,7 +1999,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
res = FR_NO_PATH; break;
}
dj->sclust = LD_CLUST(dir);
dj->sclust = ld_clust(dj->fs, dir);
}
}
@ -1979,7 +2014,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
/*-----------------------------------------------------------------------*/
static
BYTE check_fs ( /* 0:FAT-VBR, 1:Valid BR but not FAT, 2:Not a BR, 3:Disk error */
BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */
FATFS *fs, /* File system object */
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
)
@ -2008,7 +2043,7 @@ static
FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
const TCHAR **path, /* Pointer to pointer to the path name (drive number) */
FATFS **rfs, /* Pointer to pointer to the found file system object */
BYTE chk_wp /* !=0: Check media write protection for write access */
BYTE wmode /* !=0: Check write protection for write access */
)
{
BYTE fmt, b, pi, *tbl;
@ -2019,6 +2054,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
const TCHAR *p = *path;
FATFS *fs;
/* Get logical drive number from the path name */
vol = p[0] - '0'; /* Is there a drive number? */
if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */
@ -2032,17 +2068,19 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
}
/* Check if the file system object is valid or not */
*rfs = 0;
if (vol >= _VOLUMES) /* Is the drive number valid? */
return FR_INVALID_DRIVE;
*rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */
fs = FatFs[vol]; /* Get corresponding file system object */
if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
ENTER_FF(fs); /* Lock file system */
if (fs->fs_type) { /* If the logical drive has been mounted */
*rfs = fs; /* Return pointer to the corresponding file system object */
if (fs->fs_type) { /* If the volume has been mounted */
stat = disk_status(fs->drv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */
if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
return FR_OK; /* The file system object is valid */
}
@ -2053,16 +2091,16 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
fs->fs_type = 0; /* Clear the file system object */
fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */
stat = disk_initialize(fs->drv); /* Initialize the physical drive */
if (stat & STA_NOINIT) /* Check if the initialization succeeded */
return FR_NOT_READY; /* Failed to initialize due to no media or hard error */
if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */
return FR_WRITE_PROTECTED;
#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */
if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
return FR_DISK_ERR;
#endif
/* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */
/* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */
fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */
if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */
if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */
@ -2154,7 +2192,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
#if _FS_RPATH
fs->cdir = 0; /* Current directory (root dir) */
#endif
#if _FS_SHARE /* Clear file lock semaphores */
#if _FS_LOCK /* Clear file lock semaphores */
clear_lock(fs);
#endif
@ -2170,16 +2208,19 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
static
FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
FATFS *fs, /* Pointer to the file system object */
WORD id /* Member id of the target object to be checked */
void* obj /* Pointer to the object FIL/DIR to check validity */
)
{
if (!fs || !fs->fs_type || fs->id != id)
FIL *fil;
fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */
if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
return FR_INVALID_OBJECT;
ENTER_FF(fs); /* Lock file system */
ENTER_FF(fil->fs); /* Lock file system */
if (disk_status(fs->drv) & STA_NOINIT)
if (disk_status(fil->fs->drv) & STA_NOINIT)
return FR_NOT_READY;
return FR_OK;
@ -2213,7 +2254,7 @@ FRESULT f_mount (
rfs = FatFs[vol]; /* Get current fs object */
if (rfs) {
#if _FS_SHARE
#if _FS_LOCK
clear_lock(rfs);
#endif
#if _FS_REENTRANT /* Discard sync object of the current volume */
@ -2252,6 +2293,7 @@ FRESULT f_open (
DEF_NAMEBUF;
if (!fp) return FR_INVALID_OBJECT;
fp->fs = 0; /* Clear file object */
#if !_FS_READONLY
@ -2261,16 +2303,15 @@ FRESULT f_open (
mode &= FA_READ;
res = chk_mounted(&path, &dj.fs, 0);
#endif
if (res == FR_OK) {
INIT_BUF(dj);
if (res == FR_OK)
res = follow_path(&dj, path); /* Follow the file path */
dir = dj.dir;
#if !_FS_READONLY /* R/W configuration */
if (res == FR_OK) {
if (!dir) /* Current dir itself */
res = FR_INVALID_NAME;
#if _FS_SHARE
#if _FS_LOCK
else
res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
#endif
@ -2281,7 +2322,7 @@ FRESULT f_open (
if (res != FR_OK) { /* No file, create new */
if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
#if _FS_SHARE
#if _FS_LOCK
res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
#else
res = dir_register(&dj);
@ -2302,8 +2343,8 @@ FRESULT f_open (
ST_DWORD(dir+DIR_CrtTime, dw);
dir[DIR_Attr] = 0; /* Reset attribute */
ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
cl = LD_CLUST(dir); /* Get start cluster */
ST_CLUST(dir, 0); /* cluster = 0 */
cl = ld_clust(dj.fs, dir); /* Get start cluster */
st_clust(dir, 0); /* cluster = 0 */
dj.fs->wflag = 1;
if (cl) { /* Remove the cluster chain if exist */
dw = dj.fs->winsect;
@ -2330,7 +2371,7 @@ FRESULT f_open (
mode |= FA__WRITTEN;
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#if _FS_SHARE
#if _FS_LOCK
fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (!fp->lockid) res = FR_INT_ERR;
#endif
@ -2338,6 +2379,7 @@ FRESULT f_open (
#else /* R/O configuration */
if (res == FR_OK) { /* Follow succeeded */
dir = dj.dir;
if (!dir) { /* Current dir itself */
res = FR_INVALID_NAME;
} else {
@ -2350,7 +2392,7 @@ FRESULT f_open (
if (res == FR_OK) {
fp->flag = mode; /* File access mode */
fp->sclust = LD_CLUST(dir); /* File start cluster */
fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
fp->fptr = 0; /* File pointer */
fp->dsect = 0;
@ -2359,6 +2401,7 @@ FRESULT f_open (
#endif
fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
}
}
LEAVE_FF(dj.fs, res);
}
@ -2383,9 +2426,9 @@ FRESULT f_read (
BYTE csect, *rbuff = buff;
*br = 0; /* Initialize byte counter */
*br = 0; /* Clear read byte counter */
res = validate(fp->fs, fp->id); /* Check validity */
res = validate(fp); /* Check validity */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Aborted file? */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2449,7 +2492,7 @@ FRESULT f_read (
#endif
fp->dsect = sect;
}
rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
if (rcnt > btr) rcnt = btr;
#if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */
@ -2485,9 +2528,9 @@ FRESULT f_write (
BYTE csect;
*bw = 0; /* Initialize byte counter */
*bw = 0; /* Clear write byte counter */
res = validate(fp->fs, fp->id); /* Check validity */
res = validate(fp); /* Check validity */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Aborted file? */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2564,7 +2607,7 @@ FRESULT f_write (
#endif
fp->dsect = sect;
}
wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
if (wcnt > btw) wcnt = btw;
#if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */
@ -2599,7 +2642,7 @@ FRESULT f_sync (
BYTE *dir;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
#if !_FS_TINY /* Write-back dirty buffer */
@ -2615,9 +2658,10 @@ FRESULT f_sync (
dir = fp->dir_ptr;
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */
ST_CLUST(dir, fp->sclust); /* Update start cluster */
st_clust(dir, fp->sclust); /* Update start cluster */
tim = get_fattime(); /* Update updated time */
ST_DWORD(dir+DIR_WrtTime, tim);
ST_WORD(dir+DIR_LstAccDate, 0);
fp->flag &= ~FA__WRITTEN;
fp->fs->wflag = 1;
res = sync(fp->fs);
@ -2643,21 +2687,26 @@ FRESULT f_close (
{
FRESULT res;
#if _FS_READONLY
res = validate(fp);
{
#if _FS_REENTRANT
FATFS *fs = fp->fs;
res = validate(fs, fp->id);
#endif
if (res == FR_OK) fp->fs = 0; /* Discard file object */
LEAVE_FF(fs, res);
}
#else
res = f_sync(fp); /* Flush cached data */
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) { /* Decrement open counter */
#if _FS_REENTRANT
res = validate(fp->fs, fp->id);
FATFS *fs = fp->fs;;
res = validate(fp);
if (res == FR_OK) {
res = dec_lock(fp->lockid);
unlock_fs(fp->fs, FR_OK);
unlock_fs(fs, FR_OK);
}
#else
res = dec_lock(fp->lockid);
@ -2710,7 +2759,7 @@ FRESULT f_chdir (
dj.fs->cdir = dj.sclust; /* Start directory itself */
} else {
if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
dj.fs->cdir = LD_CLUST(dj.dir);
dj.fs->cdir = ld_clust(dj.fs, dj.dir);
else
res = FR_NO_PATH; /* Reached but a file */
}
@ -2748,13 +2797,13 @@ FRESULT f_getcwd (
if (res != FR_OK) break;
res = dir_read(&dj);
if (res != FR_OK) break;
dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */
dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */
res = dir_sdi(&dj, 0);
if (res != FR_OK) break;
do { /* Find the entry links to the child dir */
res = dir_read(&dj);
if (res != FR_OK) break;
if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */
if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */
res = dir_next(&dj, 0);
} while (res == FR_OK);
if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
@ -2809,7 +2858,7 @@ FRESULT f_lseek (
FRESULT res;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Check abort flag */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2956,7 +3005,7 @@ FRESULT f_lseek (
#if _FS_MINIMIZE <= 1
/*-----------------------------------------------------------------------*/
/* Create a Directroy Object */
/* Create a Directory Object */
/*-----------------------------------------------------------------------*/
FRESULT f_opendir (
@ -2965,10 +3014,14 @@ FRESULT f_opendir (
)
{
FRESULT res;
FATFS *fs;
DEF_NAMEBUF;
if (!dj) return FR_INVALID_OBJECT;
res = chk_mounted(&path, &dj->fs, 0);
fs = dj->fs;
if (res == FR_OK) {
INIT_BUF(*dj);
res = follow_path(dj, path); /* Follow the path to the directory */
@ -2976,27 +3029,30 @@ FRESULT f_opendir (
if (res == FR_OK) { /* Follow completed */
if (dj->dir) { /* It is not the root dir */
if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */
dj->sclust = LD_CLUST(dj->dir);
dj->sclust = ld_clust(fs, dj->dir);
} else { /* The object is not a directory */
res = FR_NO_PATH;
}
}
if (res == FR_OK) {
dj->id = dj->fs->id;
dj->id = fs->id;
res = dir_sdi(dj, 0); /* Rewind dir */
}
}
if (res == FR_NO_FILE) res = FR_NO_PATH;
if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */
} else {
dj->fs = 0;
}
LEAVE_FF(dj->fs, res);
LEAVE_FF(fs, res);
}
/*-----------------------------------------------------------------------*/
/* Read Directory Entry in Sequense */
/* Read Directory Entry in Sequence */
/*-----------------------------------------------------------------------*/
FRESULT f_readdir (
@ -3008,7 +3064,7 @@ FRESULT f_readdir (
DEF_NAMEBUF;
res = validate(dj->fs, dj->id); /* Check validity of the object */
res = validate(dj); /* Check validity of the object */
if (res == FR_OK) {
if (!fno) {
res = dir_sdi(dj, 0); /* Rewind the directory object */
@ -3081,6 +3137,7 @@ FRESULT f_getfree (
)
{
FRESULT res;
FATFS *fs;
DWORD n, clst, sect, stat;
UINT i;
BYTE fat, *p;
@ -3088,32 +3145,33 @@ FRESULT f_getfree (
/* Get drive number */
res = chk_mounted(&path, fatfs, 0);
fs = *fatfs;
if (res == FR_OK) {
/* If free_clust is valid, return it without full cluster scan */
if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
*nclst = (*fatfs)->free_clust;
if (fs->free_clust <= fs->n_fatent - 2) {
*nclst = fs->free_clust;
} else {
/* Get number of free clusters */
fat = (*fatfs)->fs_type;
fat = fs->fs_type;
n = 0;
if (fat == FS_FAT12) {
clst = 2;
do {
stat = get_fat(*fatfs, clst);
stat = get_fat(fs, clst);
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
if (stat == 1) { res = FR_INT_ERR; break; }
if (stat == 0) n++;
} while (++clst < (*fatfs)->n_fatent);
} while (++clst < fs->n_fatent);
} else {
clst = (*fatfs)->n_fatent;
sect = (*fatfs)->fatbase;
clst = fs->n_fatent;
sect = fs->fatbase;
i = 0; p = 0;
do {
if (!i) {
res = move_window(*fatfs, sect++);
res = move_window(fs, sect++);
if (res != FR_OK) break;
p = (*fatfs)->win;
i = SS(*fatfs);
p = fs->win;
i = SS(fs);
}
if (fat == FS_FAT16) {
if (LD_WORD(p) == 0) n++;
@ -3124,12 +3182,12 @@ FRESULT f_getfree (
}
} while (--clst);
}
(*fatfs)->free_clust = n;
if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
fs->free_clust = n;
if (fat == FS_FAT32) fs->fsi_flag = 1;
*nclst = n;
}
}
LEAVE_FF(*fatfs, res);
LEAVE_FF(fs, res);
}
@ -3147,7 +3205,9 @@ FRESULT f_truncate (
DWORD ncl;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (!fp) return FR_INVALID_OBJECT;
res = validate(fp); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__ERROR) { /* Check abort flag */
res = FR_INT_ERR;
@ -3204,7 +3264,7 @@ FRESULT f_unlink (
res = follow_path(&dj, path); /* Follow the file path */
if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
res = FR_INVALID_NAME; /* Cannot remove dot entry */
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */
#endif
if (res == FR_OK) { /* The object is accessible */
@ -3215,19 +3275,19 @@ FRESULT f_unlink (
if (dir[DIR_Attr] & AM_RDO)
res = FR_DENIED; /* Cannot remove R/O object */
}
dclst = LD_CLUST(dir);
dclst = ld_clust(dj.fs, dir);
if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */
if (dclst < 2) {
res = FR_INT_ERR;
} else {
mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */
mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */
sdj.sclust = dclst;
res = dir_sdi(&sdj, 2); /* Exclude dot entries */
if (res == FR_OK) {
res = dir_read(&sdj);
if (res == FR_OK /* Not empty dir */
#if _FS_RPATH
|| dclst == sdj.fs->cdir /* Current dir */
|| dclst == dj.fs->cdir /* Current dir */
#endif
) res = FR_DENIED;
if (res == FR_NO_FILE) res = FR_OK; /* Empty */
@ -3289,12 +3349,12 @@ FRESULT f_mkdir (
dir[DIR_Name] = '.';
dir[DIR_Attr] = AM_DIR;
ST_DWORD(dir+DIR_WrtTime, tim);
ST_CLUST(dir, dcl);
st_clust(dir, dcl);
mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */
dir[33] = '.'; pcl = dj.sclust;
if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
pcl = 0;
ST_CLUST(dir+SZ_DIR, pcl);
st_clust(dir+SZ_DIR, pcl);
for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
dj.fs->winsect = dsc++;
dj.fs->wflag = 1;
@ -3310,7 +3370,7 @@ FRESULT f_mkdir (
dir = dj.dir;
dir[DIR_Attr] = AM_DIR; /* Attribute */
ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */
ST_CLUST(dir, dcl); /* Table start cluster */
st_clust(dir, dcl); /* Table start cluster */
dj.fs->wflag = 1;
res = sync(dj.fs);
}
@ -3430,7 +3490,7 @@ FRESULT f_rename (
res = follow_path(&djo, path_old); /* Check old object */
if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
res = FR_INVALID_NAME;
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) res = chk_lock(&djo, 2);
#endif
if (res == FR_OK) { /* Old object is found */
@ -3438,11 +3498,11 @@ FRESULT f_rename (
res = FR_NO_FILE;
} else {
mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */
mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */
mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */
res = follow_path(&djn, path_new);
if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */
/* Start critical section that any interruption or error can cause cross-link */
/* Start critical section that an interruption or error can cause cross-link */
res = dir_register(&djn); /* Register the new entry */
if (res == FR_OK) {
dir = djn.dir; /* Copy object information except for name */
@ -3450,16 +3510,16 @@ FRESULT f_rename (
dir[DIR_Attr] = buf[0] | AM_ARC;
djo.fs->wflag = 1;
if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */
dw = clust2sect(djn.fs, LD_CLUST(dir));
dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
if (!dw) {
res = FR_INT_ERR;
} else {
res = move_window(djn.fs, dw);
dir = djn.fs->win+SZ_DIR; /* .. entry */
res = move_window(djo.fs, dw);
dir = djo.fs->win+SZ_DIR; /* .. entry */
if (res == FR_OK && dir[1] == '.') {
dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
ST_CLUST(dir, dw);
djn.fs->wflag = 1;
dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
st_clust(dir, dw);
djo.fs->wflag = 1;
}
}
}
@ -3503,9 +3563,11 @@ FRESULT f_forward (
BYTE csect;
*bf = 0; /* Initialize byte counter */
*bf = 0; /* Clear transfer byte counter */
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (!fp) return FR_INVALID_OBJECT;
res = validate(fp); /* Check validity of the object */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Check error flag */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -3613,7 +3675,7 @@ FRESULT f_mkfs (
if (au == 0) au = 1;
if (au > 128) au = 128;
/* Pre-compute number of clusters and FAT syb-type */
/* Pre-compute number of clusters and FAT sub-type */
n_clst = n_vol / au;
fmt = FS_FAT12;
if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
@ -3665,18 +3727,18 @@ FRESULT f_mkfs (
if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
md = 0xF8;
} else {
if (sfd) { /* No patition table (SFD) */
if (sfd) { /* No partition table (SFD) */
md = 0xF0;
} else { /* Create partition table (FDISK) */
mem_set(fs->win, 0, SS(fs));
tbl = fs->win+MBR_Table; /* Create partiton table for single partition in the drive */
tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */
tbl[1] = 1; /* Partition start head */
tbl[2] = 1; /* Partition start sector */
tbl[3] = 0; /* Partition start cylinder */
tbl[4] = sys; /* System type */
tbl[5] = 254; /* Partition end head */
n = (b_vol + n_vol) / 63 / 255;
tbl[6] = (BYTE)((n >> 2) | 63); /* Partiiton end sector */
tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */
tbl[7] = (BYTE)n; /* End cylinder */
ST_DWORD(tbl+8, 63); /* Partition start in LBA */
ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
@ -3880,18 +3942,18 @@ TCHAR* f_gets (
#if _LFN_UNICODE /* Read a character in UTF-8 encoding */
if (c >= 0x80) {
if (c < 0xC0) continue; /* Skip stray trailer */
if (c < 0xE0) { /* Two-byte sequense */
if (c < 0xE0) { /* Two-byte sequence */
f_read(fil, s, 1, &rc);
if (rc != 1) break;
c = ((c & 0x1F) << 6) | (s[0] & 0x3F);
if (c < 0x80) c = '?';
} else {
if (c < 0xF0) { /* Three-byte sequense */
if (c < 0xF0) { /* Three-byte sequence */
f_read(fil, s, 2, &rc);
if (rc != 2) break;
c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F);
if (c < 0x800) c = '?';
} else { /* Reject four-byte sequense */
} else { /* Reject four-byte sequence */
c = '?';
}
}
@ -4044,7 +4106,7 @@ int f_printf (
r = 10; break;
case 'X' : /* Hexdecimal */
r = 16; break;
default: /* Unknown type (passthrough) */
default: /* Unknown type (pass-through) */
cc = f_putc(c, fil); continue;
}
@ -4059,7 +4121,7 @@ int f_printf (
d = (TCHAR)(v % r); v /= r;
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
s[i++] = d + '0';
} while (v && i < sizeof(s) / sizeof(s[0]));
} while (v && i < sizeof s / sizeof s[0]);
if (f & 8) s[i++] = '-';
j = i; d = (f & 1) ? '0' : ' ';
res = 0;

View File

@ -1,11 +1,11 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.09 (C)ChaN, 2011
/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following trems.
/ developments under license policy of following terms.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/ Copyright (C) 2012, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
@ -15,7 +15,7 @@
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 6502 /* Revision ID */
#define _FATFS 4004 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@ -42,7 +42,7 @@ extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */
#endif
@ -111,24 +111,24 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
FATFS* fs; /* Pointer to the related file system object */
WORD id; /* File system mount ID of the related file system object */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fptr; /* File read/write pointer (0ed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0 when fsize==0) */
DWORD clust; /* Current cluster */
DWORD dsect; /* Current data sector */
DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter */
DWORD dsect; /* Current data sector of fpter */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
BYTE* dir_ptr; /* Pointer to the directory entry in the window */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_SHARE
UINT lockid; /* File lock ID (index of file semaphore table) */
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File data read/write buffer */
@ -176,14 +176,14 @@ typedef struct {
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */
FR_EXIST, /* (8) Acces denied due to prohibited access */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
@ -191,7 +191,7 @@ typedef enum {
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
@ -216,8 +216,8 @@ FRESULT f_truncate (FIL*); /* Truncate file */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
FRESULT f_chdrive (BYTE); /* Change current drive */
FRESULT f_chdir (const TCHAR*); /* Change current directory */

View File

@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011
/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
@ -7,7 +7,7 @@
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 6502 /* Revision ID */
#define _FFCONF 4004 /* Revision ID */
/*---------------------------------------------------------------------------/
@ -182,9 +182,9 @@
/ function must be added to the project. */
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
defines how many files can be opened simultaneously. */
#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
The value defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */

View File

@ -1,6 +1,6 @@
/*------------------------------------------------------------------------*/
/* Sample code of OS dependent controls for FatFs R0.08b */
/* (C)ChaN, 2011 */
/* Sample code of OS dependent controls for FatFs */
/* (C)ChaN, 2012 */
/*------------------------------------------------------------------------*/
#include <stdlib.h> /* ANSI memory controls */

17
src/option/unicode.c Normal file
View File

@ -0,0 +1,17 @@
#include "../ff.h"
#if _USE_LFN != 0
#if _CODE_PAGE == 932
#include "cc932.c"
#elif _CODE_PAGE == 936
#include "cc936.c"
#elif _CODE_PAGE == 949
#include "cc949.c"
#elif _CODE_PAGE == 950
#include "cc950.c"
#else
#include "ccsbcs.c"
#endif
#endif