fatfs v0.04b May 05, 2007:
- Added _USE_NTFLAG option. - Added FSInfo support. - Fixed some problems corresponds to FAT32. (Tiny-FatFs) - Fixed DBCS name can result FR_INVALID_NAME. - Fixed short seek (<= csize) collapses the file object.
This commit is contained in:
		
							parent
							
								
									8e92305484
								
							
						
					
					
						commit
						c0c10d0bea
					
				| @ -75,10 +75,11 @@ | ||||
| <h3>Resources</h3> | ||||
| <p>The FatFs/Tiny-FatFs module is a free software and is opened for education, research and development. You can use, modify and/or republish it for personal, non-profit or profit use without any restriction under your responsibility.</p> | ||||
| <ul> | ||||
| <li><a href="http://elm-chan.org/fsw/ff/00index_e.html">FatFs home page</a></li> | ||||
| <li><a href="en/appnote.html">FatFs module application note</a></li> | ||||
| <li><a href="img/rwtest.png">Benchmark</a> (Test Board: ATmega64/9.2MHz with <a href="img/rw_mmc.jpeg">MMC</a>/<a href="img/rw_ata.jpeg">HDD</a>/<a href="img/rw_cfc.jpeg">CFC</a>)</li> | ||||
| <li><a href="http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx">FAT32 Specification</a> (Microsoft)</li> | ||||
| <li><a href="http://elm-chan.org/docs/mmc/mmc_e.html">How to Use an MMC</a></li> | ||||
| <li><a href="http://elm-chan.org/docs/mmc/mmc_e.html">How to Use MMC/SDC</a></li> | ||||
| </ul> | ||||
| </div> | ||||
| 
 | ||||
|  | ||||
| @ -74,6 +74,7 @@ | ||||
| <h3>資料</h3> | ||||
| <p>FatFs/Tiny-FatFsモジュールはフリー・ソフトウェアとして教育・研究・開発用に公開しています。どのような利用目的(個人・非商用・商用)でも使用・改変・配布について一切の制限はありませんが、全て利用者の責任の下での利用とします。</p> | ||||
| <ul> | ||||
| <li><a href="http://elm-chan.org/fsw/ff/00index_j.html">FatFsホームページ</a></li> | ||||
| <li><a href="ja/appnote.html">FatFsモジュール・アプリケーション・ノート</a></li> | ||||
| <li><a href="img/rwtest.png">パフォーマンス・テスト</a>(テスト・ボード:ATmega64/9.2MHz with <a href="img/rw_mmc.jpeg">MMC</a>/<a href="img/rw_ata.jpeg">HDD</a>/<a href="img/rw_cfc.jpeg">CFC</a>)</li> | ||||
| <li><a href="http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx">FAT32仕様書</a> (Microsoft)</li> | ||||
|  | ||||
| @ -18,30 +18,30 @@ | ||||
| <ul> | ||||
| <li>ANSI C<br> | ||||
| The FatFs module is a middleware that written in ANSI C. There is no platform dependence, so long as the compiler is in compliance with ANSI C. However it handles the system portable FAT structures. You must take the <strong>endian</strong> into consideration. This setting is defined in ff.h (tff.h). It must be changed for your platform first or the compiler will abort with an error.</li> | ||||
| <li>Size of char/short/long are 8/16/32 bit.<br> | ||||
| <li>Size of char/short/long are 8/16/32 bit and int is 16 bit or grater.<br> | ||||
| These correspondence are defined in integer.h. This will not be a problem on most compilers. When any conflict of the definitions between the integer.h and existing definitions is occured, you must resolve the confrict with care.</li> | ||||
| </ul> | ||||
| </div> | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h3>Memory Usage (R0.04a)</h3> | ||||
| <h3>Memory Usage (R0.04b)</h3> | ||||
| <p>These are the memory usage on some target systems. The memory sizes are in unit of byte, D means number of logical drives and F means number of open files. All samples are optimezed in code size.</p> | ||||
| <table class="lst2"> | ||||
| <tr><th></th><th>AVR</th><th>H8/300H</th><th>MSP430</th><th>TLCS-870/C</th><th>V850ES</th><th>SH2</th></tr> | ||||
| <tr><td>Compiler</td><td>gcc</td><td>CH38</td><td>CL430</td><td>CC870C</td><td>CA850</td><td>SHC</td></tr> | ||||
| <tr><td>_MCU_ENDIAN</td><td>1</td><td>2</td><td>2</td><td>1</td><td>1</td><td>2</td></tr> | ||||
| <tr><td>FatFs Code<br>(Full, R/W cfg.)</td><td>8672</td><td>8746</td><td></td><td></td><td>6384</td><td>7390</td></tr> | ||||
| <tr><td>FatFs Code<br>(Full, R/O cfg.)</td><td>4230</td><td>4100</td><td></td><td></td><td>3012</td><td>3510</td></tr> | ||||
| <tr><td>FatFs Code<br>(Mininum, R/W cfg.)</td><td>5706</td><td>5678</td><td></td><td></td><td>4042</td><td>4882</td></tr> | ||||
| <tr><td>FatFs Code<br>(Minimum, R/O cfg.)</td><td>3016</td><td>3116</td><td></td><td></td><td>2198</td><td>2702</td></tr> | ||||
| <tr><td>FatFs Code<br>(Standard, R/W cfg.)</td><td>8722</td><td>8776</td><td></td><td></td><td>6402</td><td>7338</td></tr> | ||||
| <tr><td>FatFs Code<br>(Minimum, R/W cfg.)</td><td>5814</td><td>5722</td><td></td><td></td><td>4094</td><td>4906</td></tr> | ||||
| <tr><td>FatFs Code<br>(Standard, R/O cfg.)</td><td>4248</td><td>4096</td><td></td><td></td><td>3010</td><td>3506</td></tr> | ||||
| <tr><td>FatFs Code<br>(Minimum, R/O cfg.)</td><td>3038</td><td>3110</td><td></td><td></td><td>2210</td><td>2698</td></tr> | ||||
| <tr><td>FatFs Work (Static)</td><td>D*2 + 2</td><td>D*4 + 2</td><td></td><td></td><td>D*4 + 2</td><td>D*4 + 2</td></tr> | ||||
| <tr><td>FatFs Work (Dynamic)</td><td>D*550 + F*544</td><td>D*550 + F*550</td><td></td><td></td><td>D*550 + F*550</td><td>D*550 + F*550</td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Full, R/W cfg.)</td><td>7188</td><td>7206</td><td>6590</td><td>8799</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Full, R/O cfg.)</td><td>3592</td><td>3560</td><td>3162</td><td>4353</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Minimum, R/W cfg.)</td><td>4670</td><td>4772</td><td>4322</td><td>6073</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Minimum, R/O cfg.)</td><td>2576</td><td>2714</td><td>2378</td><td>3324</td><td></td><td></td></tr> | ||||
| <tr><td>FatFs Work (Dynamic)</td><td>D*554 + F*544</td><td>D*554 + F*550</td><td></td><td></td><td>D*554 + F*550</td><td>D*554 + F*550</td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Standard, R/W cfg.)</td><td>7264</td><td>7240</td><td>6634</td><td>8837</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Minimum, R/W cfg.)</td><td>4750</td><td>4806</td><td>4366</td><td>6163</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Standard, R/O cfg.)</td><td>3600</td><td>3548</td><td>3212</td><td>4347</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Code<br>(Minimum, R/O cfg.)</td><td>2568</td><td>2702</td><td>2394</td><td>3322</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Wrok (Static)</td><td>4</td><td>6</td><td>4</td><td>4</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Work (Dynamic)</td><td>542 + F*28</td><td>542 + F*32</td><td>542 + F*28</td><td>542 + F*28</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs Work (Dynamic)</td><td>544 + F*28</td><td>544 + F*32</td><td>544 + F*28</td><td>544 + F*28</td><td></td><td></td></tr> | ||||
| </table> | ||||
| </div> | ||||
| 
 | ||||
| @ -110,8 +110,6 @@ Figure 5. Minimized critical section<br> | ||||
| Currently the file object structure is held by application layer. This is not a problem for Tiny-FatFs, it consumes the task stack only 26 bytes per file. But FatFs requires 550 bytes per file. When managed the file objects in file handle, stack consumption at application module will able to be reduced. In this case, the work area for file objects is managed in FatFs module. This has a disadvantage that direct access to the file object structure cannot be used and additional file functions, such as feof and ftell, will be needed.</li> | ||||
| <li>Efficient sector buffer management<br> | ||||
| The FatFs module has only one sector buffer per logical drive. There is an ineffciency on random file access with many files simultanesously. When additional memory for the sector buffer is available, the file access performance will able to be improved with an advanced cache mechanism.</li> | ||||
| <li>FSInfo sector<br> | ||||
| On FAT32 file system, the cluster search to create a file as new or get number of free clusters takes time due to a great many clusters. The FSInfo sector that has last allocated cluster number and number of free clusters is provided to prevent the silly cluster search. However the FatFs module does not support this feature.</li> | ||||
| <li>Long file name<br> | ||||
| There is an extended feature to handle long file name (LFN) up to 255 characters, in addition to 8.3 format file name, on FAT file system. To support this, 512 byte string buffer for file name and UCS-2 - Shift_JIS mutual conversion table are required. Therefore memory consumption of code and work area will be increased drastically. The FatFs module does not support this feature. The LFN on the FAT file system is a patent of Microsoft. When support it on the commercial products, you have to be licensed.</li> | ||||
| <li>Porting to RTOS<br> | ||||
|  | ||||
| @ -46,7 +46,7 @@ FRESULT f_close ( | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h4>Description</h4> | ||||
| <p>The f_close function closes an open file object. If any data has been written to the file, the cached information of the file is written back to the disk. After the function succeeded, the file object is no longer valid and it can be discarded.</p> | ||||
| <p>The f_close function closes an open file object. If any data has been written to the file, the cached information of the file is written back to the disk. After the function succeeded, the file object is no longer valid and it can be discarded. If the file object has been opened in read-only mode, it may be discarded without closing process by this function.</p> | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -56,7 +56,8 @@ FRESULT f_getfree ( | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h4>Descriptions</h4> | ||||
| <p>The f_getfree function gets number of free clusters on the drive. The <tt>sects_clust</tt> member in the file system object refreting number of sectors per cluster, so that the free space in unit of sector can be calcurated with this. This function is not supported in read-only configuration and minimization level of >= 1.</p> | ||||
| <p>The f_getfree function gets number of free clusters on the drive. The <tt>sects_clust</tt> member in the file system object refreting number of sectors per cluster, so that the free space in unit of sector can be calcurated with this. When _USE_FSINFO option is enabled, this function can return inaccurate free cluster count on FAT32 volume. When _USE_FSINFO option is disabled, this function will take a time on FAT32 volume.</p> | ||||
| <p>This function is not supported in read-only configuration and minimization level of >= 1.</p> | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -64,13 +64,13 @@ void scan_files (char* path) | ||||
| 
 | ||||
|     if (f_opendir(&dirs, path) == FR_OK) { | ||||
|         i = strlen(path); | ||||
|         while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.f_name[0]) { | ||||
|             if (finfo.f_attrib & AM_DIR) { | ||||
|                 sprintf(path+i, "/%s", &finfo.f_name[0]); | ||||
|         while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) { | ||||
|             if (finfo.fattrib & AM_DIR) { | ||||
|                 sprintf(path+i, "/%s", &finfo.fname[0]); | ||||
|                 scan_files(path); | ||||
|                 *(path+i) = '\0'; | ||||
|             } else { | ||||
|                 printf("%s/%s\n", path, &finfo.f_name[0]); | ||||
|                 printf("%s/%s\n", path, &finfo.fname[0]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h2>FATFS</h2> | ||||
| <p>The <tt>FATFS</tt> structure holds dynamic work area of individual logical drives. It is given by application program and registerd/unregisterd to the FatFs module with f_mount function. There is no member that can be changed from the application program.</p> | ||||
| <p>The <tt>FATFS</tt> structure holds dynamic work area of individual logical drives. It is given by application program and registerd/unregisterd to the FatFs module with f_mount function. Following members are in standard configuration. There is no member that can be changed from the application program.</p> | ||||
| <h4>FatFs</h4> | ||||
| <pre> | ||||
| typedef struct _FATFS { | ||||
| @ -25,6 +25,7 @@ typedef struct _FATFS { | ||||
|     DWORD   dirbase;        /* Root directory start sector (cluster# for FAT32) */ | ||||
|     DWORD   database;       /* Data start sector */ | ||||
|     DWORD   last_clust;     /* Last allocated cluster */ | ||||
|     DWORD   free_clust;     /* Number of free clusters */ | ||||
|     BYTE    fs_type;        /* FAT type (0:Not mounted) */ | ||||
|     BYTE    sects_clust;    /* Sectors per cluster */ | ||||
|     BYTE    n_fats;         /* Number of FAT copies */ | ||||
| @ -47,6 +48,7 @@ typedef struct _FATFS { | ||||
|     CLUST   sects_fat;      /* Sectors per fat */ | ||||
|     CLUST   max_clust;      /* Maximum cluster# + 1 */ | ||||
|     CLUST   last_clust;     /* Last allocated cluster */ | ||||
|     CLUST   free_clust;     /* Number of free clusters */ | ||||
|     BYTE    fs_type;        /* FAT type (0:Not mounted) */ | ||||
|     BYTE    sects_clust;    /* Sectors per cluster */ | ||||
|     BYTE    n_fats;         /* Number of FAT copies */ | ||||
|  | ||||
| @ -18,36 +18,36 @@ | ||||
| <ul> | ||||
| <li>処理系はANSI C準拠であること。<br> | ||||
| FatFsモジュールはANSI C準拠で記述されているので、ANSI C準拠のコンパイラなら特に処理系依存な点はありません。ただし、FATというシステム間でポータブルな構造体を操作するため、プロセッサのエンディアンの違いは意識する必要があります。これは ff.h(tff.h) で定義されているので、最初にこれを適切に設定します(忘れている場合はエラーを出す)。</li> | ||||
| <li>char/short/long のサイズは、それぞれ  8/16/32ビットであること。<br> | ||||
| integer.h内でtypedefされています。整数の型とサイズに関しては、まっとうな処理系なら問題ないはずですが、既存の定義と衝突した場合は矛盾がないように注意しなければなりません。</li> | ||||
| <li>char/short/long のサイズは、それぞれ 8/16/32ビット で、intは 16ビット以上 であること。<br> | ||||
| これは integer.h 内で typedef されています。整数の型とサイズに関しては、まっとうな処理系なら問題ないはずですが、既存の定義と衝突した場合は矛盾がないように注意しなければなりません。</li> | ||||
| </ul> | ||||
| </div> | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h3>メモリ使用量 (R0.04a)</h3> | ||||
| <h3>メモリ使用量 (R0.04b)</h3> | ||||
| <p>各種環境でのモジュールのメモリ使用量の例を示します。数値の単位はバイトで、Dは論理ドライブ数、Fは同時オープン・ファイル数を示します。最適化オプションは、全てコード・サイズとしています。</p> | ||||
| <table class="lst2"> | ||||
| <tr><th></th><th>AVR</th><th>H8/300H</th><th>MSP430</th><th>TLCS-870/C</th><th>V850ES</th><th>SH2</th></tr> | ||||
| <tr><td>コンパイラ</td><td>gcc</td><td>CH38</td><td>CL430</td><td>CC870C</td><td>CA850</td><td>SHC</td></tr> | ||||
| <tr><td>_MCU_ENDIAN</td><td>1</td><td>2</td><td>2</td><td>1</td><td>1</td><td>2</td></tr> | ||||
| <tr><td>FatFs コード<br>(標準, R/W構成)</td><td>8672</td><td>8746</td><td></td><td></td><td>6384</td><td>7390</td></tr> | ||||
| <tr><td>FatFs コード<br>(標準, R/O構成)</td><td>4232</td><td>4100</td><td></td><td></td><td>3012</td><td>3510</td></tr> | ||||
| <tr><td>FatFs コード<br>(最小, R/W構成)</td><td>5706</td><td>5678</td><td></td><td></td><td>4042</td><td>4882</td></tr> | ||||
| <tr><td>FatFs コード<br>(最小, R/O構成)</td><td>3018</td><td>3116</td><td></td><td></td><td>2198</td><td>2702</td></tr> | ||||
| <tr><td>FatFs コード<br>(標準, R/W構成)</td><td>8722</td><td>8776</td><td></td><td></td><td>6402</td><td>7338</td></tr> | ||||
| <tr><td>FatFs コード<br>(最小, R/W構成)</td><td>5814</td><td>5722</td><td></td><td></td><td>4094</td><td>4906</td></tr> | ||||
| <tr><td>FatFs コード<br>(標準, R/O構成)</td><td>4248</td><td>4096</td><td></td><td></td><td>3010</td><td>3506</td></tr> | ||||
| <tr><td>FatFs コード<br>(最小, R/O構成)</td><td>3038</td><td>3110</td><td></td><td></td><td>2210</td><td>2698</td></tr> | ||||
| <tr><td>FatFs 静的ワーク</td><td>D*2 + 2</td><td>D*4 + 2</td><td></td><td></td><td>D*4 + 2</td><td>D*4 + 2</td></tr> | ||||
| <tr><td>FatFs 動的ワーク</td><td>D*550 + F*544</td><td>D*550 + F*550</td><td></td><td></td><td>D*550 + F*550</td><td>D*550 + F*550</td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(標準, R/W構成)</td><td>7188</td><td>7206</td><td>6590</td><td>8799</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(標準, R/O構成)</td><td>3592</td><td>3560</td><td>3162</td><td>4353</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(最小, R/W構成)</td><td>4670</td><td>4772</td><td>4322</td><td>6073</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(最小, R/O構成)</td><td>2576</td><td>2714</td><td>2378</td><td>3324</td><td></td><td></td></tr> | ||||
| <tr><td>FatFs 動的ワーク</td><td>D*554 + F*544</td><td>D*554 + F*550</td><td></td><td></td><td>D*554 + F*550</td><td>D*554 + F*550</td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(標準, R/W構成)</td><td>7264</td><td>7240</td><td>6634</td><td>8837</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(最小, R/W構成)</td><td>4750</td><td>4806</td><td>4366</td><td>6163</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(標準, R/O構成)</td><td>3600</td><td>3548</td><td>3212</td><td>4347</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs コード<br>(最小, R/O構成)</td><td>2568</td><td>2702</td><td>2394</td><td>3322</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs 静的ワーク</td><td>4</td><td>6</td><td>4</td><td>4</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs 動的ワーク</td><td>542 + F*28</td><td>542 + F*32</td><td>542 + F*28</td><td>542 + F*28</td><td></td><td></td></tr> | ||||
| <tr><td>Tiny-FatFs 動的ワーク</td><td>544 + F*28</td><td>544 + F*32</td><td>544 + F*28</td><td>544 + F*28</td><td></td><td></td></tr> | ||||
| </table> | ||||
| </div> | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h3>FatFs vs. Tiny-FatFs</h3> | ||||
| <p>ポータブル・オーディオやデータ・ロガーなど、よくある用途ではTiny-FatFsで十分です。しかし、Tiny-FatFsは標準構成ではFAT32に対応していないので、使用できるディスクは2GB(FAT64で4GB)までという制約があります。<tt>_USE_FAT32</tt>オプションでFAT32を追加できますが、その分コード・サイズが膨らみます。フル機能のFatFsは、複数ファイルを高速アクセスする場合や、複数ドライブの対応が必要な場合に有効です。</p> | ||||
| <p>ポータブル・オーディオやデータ・ロガーなど、よくある用途ではTiny-FatFsで十分です。しかし、Tiny-FatFsは標準構成ではFAT32に対応していないので、使用できるディスクは2GB(FAT64で4GB)までという制約があります。<tt>_FAT32</tt>オプションでFAT32対応を追加できますが、その分コード・サイズが膨らみます。フル機能のFatFsは、複数ファイルを高速アクセスする場合や、複数ドライブの対応が必要な場合に有効です。</p> | ||||
| <div class="rset"> | ||||
| <table class="lst2"> | ||||
| <tr><th>メモリ容量</th><th>FATタイプ</th></tr> | ||||
| @ -56,7 +56,7 @@ integer.h | ||||
| <tr><td>>= 4GB</td><td>FAT32</td></tr> | ||||
| </table> | ||||
| </div> | ||||
| <p>右の表にメモリ・カードの容量と規定のFATタイプ(SDメモリの場合)を示します。出荷時はこれらのFATタイプでフォーマットされていて、最大のパフォーマンスが出るようにデータ領域の境界が調整されています。したがって、PCでフォーマットするなどして規定と違うフォーマットになると書き込み性能が大幅に低下する場合があるので注意が必要です。</p> | ||||
| <p>2GBまでのカードに限るなら、FAT32への対応は不要です。右の表にメモリ・カードの容量と規定のFATタイプ(SDメモリの場合)を示します。メモリ・カードの出荷時は、最大のパフォーマンスが出るようにデータ領域の境界が調整されたフォーマットになっています。したがって、PCでフォーマットするなどして規定と違うフォーマットになると、書き込み性能が大幅に低下する場合があるので注意が必要です。</p> | ||||
| </div> | ||||
| 
 | ||||
| <div class="para"> | ||||
| @ -111,8 +111,6 @@ integer.h | ||||
| 現在はファイル・オブジェクトの実体をアプリケーション側で管理しているので、アプリケーション・モジュールでのスタック消費量が多くなります(Tiny-FatFsでは問題にならない)。これをハンドルで管理するなどより抽象化すればアプリケーション・モジュールでのスタック消費量を減らせるし、他のファイル・システムへの対応も容易になります。この場合、FatFs内でファイル・オブジェクトの領域を静的に確保しておくか、malloc()することになります。ただし、このようにするとファイル・オブジェクトを直接参照できなくなり、feofやftellなどムダな関数が新たに必要になります。</li> | ||||
| <li>セクタ・バッファ管理の改善<br> | ||||
| 現在はセクタ・バッファを固定して使用しているため、無駄なディスクアクセスが多く効率が悪い。メモリの潤沢なシステムでは、複数のセクタ・バッファを使用してディスク・キャッシュを構成すれば性能を向上させることができます。</li> | ||||
| <li>FSInfoへの対応<br> | ||||
| FAT32ではその膨大なクラスタ数のため、ファイル新規作成や空きスペース取得時のクラスタ・サーチにかなりの時間を要します。このため、最終割り当てクラスタ番号や残りクラスタ数がFSInfoセクタに記録されていて、延々とクラスタ・サーチするのを避けられるようになっています。現在はFSInfoに未対応なので、空きスペース取得時や、ディスク使用量が多い状態でのファイル作成(作成後の最初の書き込み)処理時間は問題になるレベルです。</li> | ||||
| <li>長いファイル名への対応<br> | ||||
| FATの拡張仕様ではMS-DOSの8.3形式ファイル名に加え、255文字までの長いファイル名(LFN)を扱えるようになっていますが、現リビジョンでは未対応で8.3形式しか使用できません。これに対応するには、ファイル名だけでも500バイト以上のバッファが必要になったり、UCS-2とShift_JISの相互変換(巨大な変換テーブルを使う)が必要となるなど、メモリの消費が爆発的に増えてしまいます。なお、LFNの機能はMicrosoft社の特許になっているため、これを製品に使うにはライセンス契約が必要です。</li> | ||||
| <li>RTOSへの対応<br> | ||||
|  | ||||
| @ -46,7 +46,7 @@ FRESULT f_close ( | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h4>‰ð<EFBFBD>à</h4> | ||||
| <p>ファイルを閉じます。書き込みの行われたファイルの場合、キャッシュされた状態(R/Wバッファ上のデータ、変更されたFATやディレクトリ項目)はディスクに書き戻されます。関数が正常終了すると、そのファイル・オブジェクトは無効になり、そのメモリも解放できます。</p> | ||||
| <p>ファイルを閉じます。書き込みの行われたファイルの場合、キャッシュされた状態(R/Wバッファ上のデータ、変更されたFATやディレクトリ項目)はディスクに書き戻されます。関数が正常終了すると、そのファイル・オブジェクトは無効になり、そのメモリも解放できます。読み込み専用モードで開かれたファイル・オブジェクトは、この関数によるクローズ処理を経ずに破棄することもできます。</p> | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -50,11 +50,12 @@ DRESULT disk_ioctl ( | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h4>解説</h4> | ||||
| <p>物理ドライブの種類によりサポートされるコマンドは異なりますが、FatFsモジュールでは、ドライブの種類に依存した制御は行いません。次のドライブ共通コマンドを使用します。リード・オンリー構成ではこの関数は必要とされません。</p> | ||||
| <p>物理ドライブの種類によりサポートされるコマンドは異なりますが、FatFsモジュールでは、ドライブの種類に依存した制御は行いません。次のドライブ共通コマンドを使用します。</p> | ||||
| <p>リード・オンリー構成ではこの関数は必要とされません。</p> | ||||
| <table class="lst"> | ||||
| <tr><th>コマンド</th><th>解説</td></tr> | ||||
| <tr><td>GET_SECTOR_COUNT</td><td>Bufferの指すDWORD変数にドライブ上の総セクタ数を返します。</td></tr> | ||||
| <tr><td>CTRL_SYNC</td><td>ディスクへのデータの書き込みが完了するのを待ちます。ライト・バック・キャッシュを持っている場合は、書き込まれていないデータを即時書き戻します。</td></tr> | ||||
| <tr><td>CTRL_SYNC</td><td>ドライブがデータの書き込みを完了するのを待ちます。ライト・バック・キャッシュを持っている場合は、書き込まれていないデータを即時書き戻します。</td></tr> | ||||
| </table> | ||||
| </div> | ||||
| 
 | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h2>f_getfree</h2> | ||||
| <p>ディスクの未使用クラスタ数を得ます。</p> | ||||
| <p>論理ドライブ上の未使用クラスタ数を得ます。</p> | ||||
| <pre> | ||||
| FRESULT f_getfree ( | ||||
|   const char* <em>Path</em>,        /* 対象ドライブのルート・ディレクトリ */ | ||||
| @ -26,11 +26,11 @@ FRESULT f_getfree ( | ||||
| <h4>引数</h4> | ||||
| <dl class="par"> | ||||
| <dt>Path</dt> | ||||
| <dd>情報を得る論理ドライブのルートディレクトリの<a href="filename.html">パス名</a>が入った<tt>'\0'</tt>で終わる文字列へのポインタを指定します。</dd> | ||||
| <dd>対象の論理ドライブのルートディレクトリの<a href="filename.html">パス名</a>が入った<tt>'\0'</tt>で終わる文字列へのポインタを指定します。</dd> | ||||
| <dt>Clusters</dt> | ||||
| <dd>空きクラスタ数を格納する<tt>DWORD</tt>変数へのポインタを指定します。</dd> | ||||
| <dt>FileSystemObject</dt> | ||||
| <dd>対象ドライブのファイル・システム・オブジェクトを指すポインタを格納するポインタへのポインタを指定します。</dd> | ||||
| <dd>対象ドライブのファイル・システム・オブジェクトを指すポインタが返されます。</dd> | ||||
| </dl> | ||||
| </div> | ||||
| 
 | ||||
| @ -56,7 +56,8 @@ FRESULT f_getfree ( | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h4>解説</h4> | ||||
| <p>論理ドライブ上の空きクラスタ数を取得します。返されたファイル・システム・オブジェクトの<tt>sects_clust</tt>メンバがクラスタあたりのセクタ数を示しているので、これを元に実際の空きサイズが計算できます。リードオンリー構成および<tt>_FS_MINIMIZE >= 1</tt>ではこの関数はサポートされません。</p> | ||||
| <p>論理ドライブ上の空きクラスタ数を取得します。返されたファイル・システム・オブジェクトの<tt>sects_clust</tt>メンバがクラスタあたりのセクタ数を示しているので、これを元に実際の空きサイズが計算できます。FAT32ボリュームにおいて、_USE_FSINFOが指定されている場合、不正確な値を返す場合があります。指定されていない場合、処理に時間がかかります。</p> | ||||
| <p>リードオンリー構成および<tt>_FS_MINIMIZE >= 1</tt>ではこの関数はサポートされません。</p> | ||||
| </div> | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -30,7 +30,7 @@ FRESULT f_mkfs ( | ||||
| <dt>PartitioningRule</dt> | ||||
| <dd>0を指定すると、区画テーブルを作成したあとその区画にファイル・システムを作成します(FDISKフォーマット)。1を指定すると、先頭セクタから直接ファイル・システムを構築します(super floppy (SFD) フォーマット)。</dd> | ||||
| <dt>AllocSize</dt> | ||||
| <dd>アロケーション・ユニット・サイズ(クラスタ・サイズ)をセクタ単位で指定します。2の累乗でかつ1から64までの範囲でなければなりません。</dd> | ||||
| <dd>クラスタ・サイズをセクタ単位で指定します。2の累乗でかつクラスタ・サイズが32Kバイトまでの範囲でなければなりません。</dd> | ||||
| </dl> | ||||
| </div> | ||||
| 
 | ||||
| @ -53,7 +53,7 @@ FRESULT f_mkfs ( | ||||
| <dd>次の理由で開始前に処理が中断された。 | ||||
| <ul> | ||||
| <li>ディスク・サイズが小さすぎる。</li> | ||||
| <li>何らかの引数が無効。</li> | ||||
| <li>何らかの引数が不正。</li> | ||||
| <li>そのクラスタ・サイズが使えない。クラスタ数が0xFF7と0xFFF7近辺になるとき発生する可能性がある。</li> | ||||
| </ul> | ||||
| </dd> | ||||
|  | ||||
| @ -64,13 +64,13 @@ void scan_files (char* path) | ||||
| 
 | ||||
|     if (f_opendir(&dirs, path) == FR_OK) { | ||||
|         i = strlen(path); | ||||
|         while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.f_name[0]) { | ||||
|             if (finfo.f_attrib & AM_DIR) { | ||||
|                 sprintf(path+i, "/%s", &finfo.f_name[0]); | ||||
|         while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) { | ||||
|             if (finfo._attrib & AM_DIR) { | ||||
|                 sprintf(path+i, "/%s", &finfo.fname[0]); | ||||
|                 scan_files(path); | ||||
|                 *(path+i) = '\0'; | ||||
|             } else { | ||||
|                 printf("%s/%s\n", path, &finfo.f_name[0]); | ||||
|                 printf("%s/%s\n", path, &finfo.fname[0]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| 
 | ||||
| <div class="para"> | ||||
| <h2>FATFS</h2> | ||||
| <p><tt>FATFS</tt>構造体は、個々の論理ドライブのダイナミック・ワーク・エリアを保持し、f_mount()でFatFsモジュールに登録されます。アプリケーションから書き換え可能なメンバはありません。</p> | ||||
| <p><tt>FATFS</tt>構造体は、個々の論理ドライブのダイナミック・ワーク・エリアを保持し、f_mount()でFatFsモジュールに登録されます。標準状態では次のようなメンバになっています。アプリケーションから書き換え可能なメンバはありません。</p> | ||||
| <h4>FatFs</h4> | ||||
| <pre> | ||||
| typedef struct _FATFS { | ||||
| @ -25,6 +25,7 @@ typedef struct _FATFS { | ||||
|     DWORD   dirbase;        /* Root directory start sector (cluster# for FAT32) */ | ||||
|     DWORD   database;       /* Data start sector */ | ||||
|     DWORD   last_clust;     /* Last allocated cluster */ | ||||
|     DWORD   free_clust;     /* Number of free clusters */ | ||||
|     BYTE    fs_type;        /* FAT type (0:Not mounted) */ | ||||
|     BYTE    sects_clust;    /* Sectors per cluster */ | ||||
|     BYTE    n_fats;         /* Number of FAT copies */ | ||||
| @ -47,6 +48,7 @@ typedef struct _FATFS { | ||||
|     CLUST   sects_fat;      /* Sectors per fat */ | ||||
|     CLUST   max_clust;      /* Maximum cluster# + 1 */ | ||||
|     CLUST   last_clust;     /* Last allocated cluster */ | ||||
|     CLUST   free_clust;     /* Number of free clusters */ | ||||
|     BYTE    fs_type;        /* FAT type (0:Not mounted) */ | ||||
|     BYTE    sects_clust;    /* Sectors per cluster */ | ||||
|     BYTE    n_fats;         /* Number of FAT copies */ | ||||
|  | ||||
| @ -15,9 +15,9 @@ | ||||
| <p><tt>FILINFO</tt>構造体は、<tt>f_stat(), f_readdir()</tt>で返されるファイル情報を保持します。</p> | ||||
| <pre> | ||||
| typedef struct _FILINFO { | ||||
|     DWORD fsize;            /* Size */ | ||||
|     WORD fdate;             /* Date */ | ||||
|     WORD ftime;             /* Time */ | ||||
|     DWORD fsize;            /* Size [bytes] */ | ||||
|     WORD fdate;             /* Date [15-9]:Year-1980, [8-5]:Month, [4-0]:Mday */ | ||||
|     WORD ftime;             /* Time [15-11]:Hour, [10-5]:Minute, [4-0]:Sec/2 */ | ||||
|     BYTE fattrib;           /* Attribute */ | ||||
|     char fname[8+1+3+1];    /* Name */ | ||||
| } FILINFO; | ||||
|  | ||||
| @ -1,9 +1,16 @@ | ||||
| R0.04b, May 05, 2007 | ||||
|   Added _USE_NTFLAG option. | ||||
|   Added FSInfo support. | ||||
|   Fixed some problems corresponds to FAT32. (Tiny-FatFs) | ||||
|   Fixed DBCS name can result FR_INVALID_NAME. | ||||
|   Fixed short seek (<= csize) collapses the file object. | ||||
| 
 | ||||
| R0.04a, Apr 01, 2007 | ||||
|   Supported multiple partitions on a plysical drive. (FatFs) | ||||
|   Fixed an endian sensitive code in f_mkfs(). (FatFs) | ||||
|   Added a capability of extending file size to f_lseek(). | ||||
|   Added minimization level 3. | ||||
|   Fixed a problem that can collapse a sector when recreate an existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs) | ||||
|   Added a capability of extending file size to f_lseek(). | ||||
|   Fixed an endian sensitive code in f_mkfs(). (FatFs) | ||||
|   Fixed a problem corresponds to FAT32 support. (Tiny-FatFs) | ||||
| 
 | ||||
| R0.04, Feb 04, 2007 | ||||
|   Supported multiple drive system. (FatFs) | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| FatFs/Tiny-FatFs Module Source Files R0.04a   (C)ChaN, 2007 | ||||
| FatFs/Tiny-FatFs Module Source Files R0.04b   (C)ChaN, 2007 | ||||
| 
 | ||||
| 
 | ||||
| FILES | ||||
| @ -48,29 +48,40 @@ CONFIGURATION OPTIONS | ||||
|   _FS_MINIMIZE | ||||
| 
 | ||||
|   When application program requires only file read/write function, _FS_MINIMIZE | ||||
|   can be defined to eliminate some functions to reduce the module size. The | ||||
|   can be changed to eliminate some functions to reduce the module size. The | ||||
|   initial value is 0. (full function) | ||||
| 
 | ||||
| 
 | ||||
|   _DRIVES | ||||
| 
 | ||||
|   Number of drives to be used. This option is not supported on Tiny-FatFs. | ||||
|   Number of drives to be used. This option is not available on Tiny-FatFs. | ||||
|   The initial value is 2. | ||||
| 
 | ||||
|   _FAT32 | ||||
| 
 | ||||
|   When _FAT32 is set to 1, the FAT32 support is added with an additional | ||||
|   code size. This is for only Tiny-FatFs and not supported on FatFs. FatFs | ||||
|   always supports all FAT type. The initial value is 0. (disabled) | ||||
|   code size. This option is for only Tiny-FatFs. FatFs always supports all | ||||
|   FAT sub-types. The initial value is 0. (no FAT32 support) | ||||
| 
 | ||||
| 
 | ||||
|   _USE_FSINFO | ||||
| 
 | ||||
|   When _USE_FSINFO is set to 1, FSInfo is used for FAT32 volume. | ||||
| 
 | ||||
| 
 | ||||
|   _USE_SJIS | ||||
| 
 | ||||
|   When _USE_SJIS is set to 1, Shift-JIS code set can be used as a file name, | ||||
|   When _USE_SJIS is set to 1, Shift_JIS code set can be used as a file name, | ||||
|   otherwire second byte of double-byte characters will be collapted. | ||||
|   The initial value is 1. | ||||
| 
 | ||||
| 
 | ||||
|   _USE_NTFLAG | ||||
| 
 | ||||
|   When _USE_NTFLAG is set to 1, upper/lower case of the file/dir name is | ||||
|   preserved. Note that the files are always accessed in case insensitive. | ||||
| 
 | ||||
| 
 | ||||
|   _USE_MKFS | ||||
| 
 | ||||
|   When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function | ||||
| @ -97,7 +108,7 @@ CONFIGURATION OPTIONS | ||||
|    f_mkdir       x    x    x         x                  | ||||
|    f_chmod       x    x    x         x                  | ||||
|    f_rename      x    x    x         x                  | ||||
|    f_mkfs                            x          x       | ||||
|    f_mkfs        x    x    x         x          x       | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -140,3 +151,8 @@ REVISION HISTORY | ||||
|                        Fixed a problem that can collapse a sector when recreate an | ||||
|                        existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs) | ||||
| 
 | ||||
|   May 05, 2007  R0.04b  Added _USE_NTFLAG option. | ||||
|                         Added FSInfo support. | ||||
|                         Fixed some problems corresponds to FAT32. (Tiny-FatFs) | ||||
|                         Fixed DBCS name can result FR_INVALID_NAME. | ||||
|                         Fixed short seek (<= csize) collapses the file object. | ||||
|  | ||||
							
								
								
									
										272
									
								
								src/ff.c
									
									
									
									
									
								
							
							
						
						
									
										272
									
								
								src/ff.c
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| /*--------------------------------------------------------------------------/
 | ||||
| /  FatFs - FAT file system module  R0.04a                    (C)ChaN, 2007 | ||||
| /  FatFs - FAT file system module  R0.04b                    (C)ChaN, 2007 | ||||
| /---------------------------------------------------------------------------/ | ||||
| / The FatFs module is an experimenal project to implement FAT file system to | ||||
| / cheap microcontrollers. This is a free software and is opened for education, | ||||
| @ -15,7 +15,8 @@ | ||||
| /---------------------------------------------------------------------------/ | ||||
| /  Feb 26, 2006  R0.00  Prototype. | ||||
| /  Apr 29, 2006  R0.01  First stable version. | ||||
| /  Jun 01, 2006  R0.02  Added FAT12. Removed unbuffered mode. | ||||
| /  Jun 01, 2006  R0.02  Added FAT12 support. | ||||
| /                       Removed unbuffered mode. | ||||
| /                       Fixed a problem on small (<32M) patition. | ||||
| /  Jun 10, 2006  R0.02a Added a configuration option (_FS_MINIMUM). | ||||
| /  Sep 22, 2006  R0.03  Added f_rename(). | ||||
| @ -24,11 +25,16 @@ | ||||
| /                       Fixed f_mkdir() creates incorrect directory on FAT32. | ||||
| /  Feb 04, 2007  R0.04  Supported multiple drive system. | ||||
| /                       Changed some interfaces for multiple drive system. | ||||
| /                       Changed f_mountdrv() to f_mount(). | ||||
| /                       Added f_mkfs(). | ||||
| /  Apr 01, 2007  R0.04a Supported multiple partitions on a plysical drive. | ||||
| /                       Fixed an endian sensitive code in f_mkfs(). | ||||
| /                       Added a capability of extending file size to f_lseek(). | ||||
| /                       Added minimization level 3. | ||||
| /                       Fixed an endian sensitive code in f_mkfs(). | ||||
| /  May 05, 2007  R0.04b Added a configuration option _USE_NTFLAG. | ||||
| /                       Added FSInfo support. | ||||
| /                       Fixed DBCS name can result FR_INVALID_NAME. | ||||
| /                       Fixed short seek (<= csize) collapses the file object. | ||||
| /---------------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #include <string.h> | ||||
| @ -64,7 +70,7 @@ BOOL move_window (		/* TRUE: successful, FALSE: failed */ | ||||
| 
 | ||||
| 	wsect = fs->winsect; | ||||
| 	if (wsect != sector) {	/* Changed current window */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 		BYTE n; | ||||
| 		if (fs->winflag) {	/* Write back dirty window if needed */ | ||||
| 			if (disk_write(fs->drive, fs->win, wsect, 1) != RES_OK) | ||||
| @ -94,7 +100,7 @@ BOOL move_window (		/* TRUE: successful, FALSE: failed */ | ||||
| /* Clean-up cached data                                                  */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| FRESULT sync (			/* FR_OK: successful, FR_RW_ERROR: failed */ | ||||
| 	FATFS *fs			/* File system object */ | ||||
| @ -102,6 +108,19 @@ FRESULT sync (			/* FR_OK: successful, FR_RW_ERROR: failed */ | ||||
| { | ||||
| 	fs->winflag = 1; | ||||
| 	if (!move_window(fs, 0)) return FR_RW_ERROR; | ||||
| #if _USE_FSINFO | ||||
| 	if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {		/* Update FSInfo sector if needed */ | ||||
| 		fs->winsect = 0; | ||||
| 		memset(fs->win, 0, 512); | ||||
| 		ST_WORD(&fs->win[BS_55AA], 0xAA55); | ||||
| 		ST_DWORD(&fs->win[FSI_LeadSig], 0x41615252); | ||||
| 		ST_DWORD(&fs->win[FSI_StrucSig], 0x61417272); | ||||
| 		ST_DWORD(&fs->win[FSI_Free_Count], fs->free_clust); | ||||
| 		ST_DWORD(&fs->win[FSI_Nxt_Free], fs->last_clust); | ||||
| 		disk_write(0, fs->win, fs->fsi_sector, 1); | ||||
| 		fs->fsi_flag = 0; | ||||
| 	} | ||||
| #endif | ||||
| 	if (disk_ioctl(fs->drive, CTRL_SYNC, NULL) != RES_OK) return FR_RW_ERROR; | ||||
| 	return FR_OK; | ||||
| } | ||||
| @ -155,7 +174,7 @@ DWORD get_cluster (		/* 0,>=2: successful, 1: failed */ | ||||
| /* Change a cluster status                                               */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| 	FATFS *fs,			/* File system object */ | ||||
| @ -198,7 +217,7 @@ BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| 	fs->winflag = 1; | ||||
| 	return TRUE; | ||||
| } | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -207,7 +226,7 @@ BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| /* Remove a cluster chain                                                */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| BOOL remove_chain (		/* TRUE: successful, FALSE: failed */ | ||||
| 	FATFS *fs,			/* File system object */ | ||||
| @ -221,6 +240,12 @@ BOOL remove_chain (		/* TRUE: successful, FALSE: failed */ | ||||
| 		nxt = get_cluster(fs, clust); | ||||
| 		if (nxt == 1) return FALSE; | ||||
| 		if (!put_cluster(fs, clust, 0)) return FALSE; | ||||
| 		if (fs->free_clust != 0xFFFFFFFF) { | ||||
| 			fs->free_clust++; | ||||
| #if _USE_FSINFO | ||||
| 			fs->fsi_flag = 1; | ||||
| #endif | ||||
| 		} | ||||
| 		clust = nxt; | ||||
| 	} | ||||
| 	return TRUE; | ||||
| @ -234,7 +259,7 @@ BOOL remove_chain (		/* TRUE: successful, FALSE: failed */ | ||||
| /* Stretch or create a cluster chain                                     */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| DWORD create_chain (	/* 0: no free cluster, 1: error, >=2: new cluster number */ | ||||
| 	FATFS *fs,			/* File system object */ | ||||
| @ -270,11 +295,18 @@ DWORD create_chain (	/* 0: no free cluster, 1: error, >=2: new cluster number */ | ||||
| 
 | ||||
| 	if (!put_cluster(fs, ncl, 0x0FFFFFFF)) return 1;		/* Mark the new cluster "in use" */ | ||||
| 	if (clust && !put_cluster(fs, clust, ncl)) return 1;	/* Link it to previous one if needed */ | ||||
| 	fs->last_clust = ncl; | ||||
| 
 | ||||
| 	fs->last_clust = ncl;				/* Update fsinfo */ | ||||
| 	if (fs->free_clust != 0xFFFFFFFF) { | ||||
| 		fs->free_clust--; | ||||
| #if _USE_FSINFO | ||||
| 		fs->fsi_flag = 1; | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	return ncl;		/* Return new cluster number */ | ||||
| } | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -349,7 +381,7 @@ void get_fileinfo (		/* No return code */ | ||||
| 
 | ||||
| 
 | ||||
| 	p = &finfo->fname[0]; | ||||
| 	a = dir[DIR_NTres];		/* NT flag */ | ||||
| 	a = _USE_NTFLAG ? dir[DIR_NTres] : 0;		/* NT flag */ | ||||
| 	for (n = 0; n < 8; n++) {	/* Convert file name (body) */ | ||||
| 		c = dir[n]; | ||||
| 		if (c == ' ') break; | ||||
| @ -398,39 +430,36 @@ char make_dirfile (			/* 1: error - detected an invalid format, '\0'or'/': next | ||||
| 		c = *(*path)++; | ||||
| 		if (c == '\0' || c == '/') {		/* Reached to end of str or directory separator */ | ||||
| 			if (n == 0) break; | ||||
| 			dirname[11] = a & b; return c; | ||||
| 			dirname[11] = _USE_NTFLAG ? (a & b) : 0; | ||||
| 			return c; | ||||
| 		} | ||||
| 		if (c <= ' ') break;		/* Reject invisible chars */ | ||||
| 		if (c <= ' ' || c == 0x7F) break;		/* Reject invisible chars */ | ||||
| 		if (c == '.') { | ||||
| 			if(!(a & 1) && n >= 1 && n <= 8) {	/* Enter extension part */ | ||||
| 			if (!(a & 1) && n >= 1 && n <= 8) {	/* Enter extension part */ | ||||
| 				n = 8; t = 11; continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| #if _USE_SJIS != 0 | ||||
| 		if ((c >= 0x81 && c <= 0x9F) ||			/* Accept S-JIS code */ | ||||
| 		    (c >= 0xE0 && c <= 0xFC)) { | ||||
| 			if (n == 0 && c == 0xE5)			/* Change heading \xE5 to \x05 */ | ||||
| 		if (_USE_SJIS && | ||||
| 			((c >= 0x81 && c <= 0x9F) ||	/* Accept S-JIS code */ | ||||
| 		    (c >= 0xE0 && c <= 0xFC))) { | ||||
| 			if (n == 0 && c == 0xE5)		/* Change heading \xE5 to \x05 */ | ||||
| 				c = 0x05; | ||||
| 			a ^= 1; goto md_l2; | ||||
| 		} | ||||
| 		if (c >= 0x7F && c <= 0x80) break;		/* Reject \x7F \x80 */ | ||||
| #else | ||||
| 		if (c >= 0x7F) goto md_l1;				/* Accept \x7F-0xFF */ | ||||
| #endif | ||||
| 		if (c == '"') break;					/* Reject " */ | ||||
| 		if (c <= ')') goto md_l1;				/* Accept ! # $ % & ' ( ) */ | ||||
| 		if (c <= ',') break;					/* Reject * + , */ | ||||
| 		if (c <= '9') goto md_l1;				/* Accept - 0-9 */ | ||||
| 		if (c <= '?') break;					/* Reject : ; < = > ? */ | ||||
| 		if (c == '"') break;				/* Reject " */ | ||||
| 		if (c <= ')') goto md_l1;			/* Accept ! # $ % & ' ( ) */ | ||||
| 		if (c <= ',') break;				/* Reject * + , */ | ||||
| 		if (c <= '9') goto md_l1;			/* Accept - 0-9 */ | ||||
| 		if (c <= '?') break;				/* Reject : ; < = > ? */ | ||||
| 		if (!(a & 1)) {	/* These checks are not applied to S-JIS 2nd byte */ | ||||
| 			if (c == '|') break;				/* Reject | */ | ||||
| 			if (c == '|') break;			/* Reject | */ | ||||
| 			if (c >= '[' && c <= ']') break;/* Reject [ \ ] */ | ||||
| 			if (c >= 'A' && c <= 'Z') | ||||
| 			if (_USE_NTFLAG && c >= 'A' && c <= 'Z') | ||||
| 				(t == 8) ? (b &= ~0x08) : (b &= ~0x10); | ||||
| 			if (c >= 'a' && c <= 'z') {			/* Convert to upper case */ | ||||
| 			if (c >= 'a' && c <= 'z') {		/* Convert to upper case */ | ||||
| 				c -= 0x20; | ||||
| 				(t == 8) ? (a |= 0x08) : (a |= 0x10); | ||||
| 				if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10); | ||||
| 			} | ||||
| 		} | ||||
| 	md_l1: | ||||
| @ -508,7 +537,7 @@ FRESULT trace_path (	/* FR_OK(0): successful, !=0: error code */ | ||||
| /* Reserve a directory entry                                             */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| FRESULT reserve_direntry (	/* FR_OK: successful, FR_DENIED: no free entry, FR_RW_ERROR: a disk error occured */ | ||||
| 	DIR *dirobj,			/* Target directory to create new entry */ | ||||
| @ -555,7 +584,7 @@ FRESULT reserve_direntry (	/* FR_OK: successful, FR_DENIED: no free entry, FR_RW | ||||
| 	*dir = fs->win; | ||||
| 	return FR_OK; | ||||
| } | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -599,7 +628,7 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| { | ||||
| 	BYTE drv, fmt, *tbl; | ||||
| 	DSTATUS stat; | ||||
| 	DWORD basesect, fatsize, totalsect, maxclust; | ||||
| 	DWORD bootsect, fatsize, totalsect, maxclust; | ||||
| 	const char *p = *path; | ||||
| 	FATFS *fs; | ||||
| 
 | ||||
| @ -623,7 +652,7 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	if (fs->fs_type) { | ||||
| 		stat = disk_status(fs->drive); | ||||
| 		if (!(stat & STA_NOINIT)) {				/* If the physical drive is kept initialized */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 			if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */ | ||||
| 				return FR_WRITE_PROTECTED; | ||||
| #endif | ||||
| @ -642,18 +671,18 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	if (disk_ioctl(drv, GET_SECTOR_SIZE, &S_SIZ) != RES_OK || S_SIZ > S_MAX_SIZ) | ||||
| 		return FR_NO_FILESYSTEM; | ||||
| #endif | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */ | ||||
| 		return FR_WRITE_PROTECTED; | ||||
| #endif | ||||
| 	/* Search FAT partition on the drive */ | ||||
| 	fmt = check_fs(fs, basesect = 0);	/* Check sector 0 as an SFD format */ | ||||
| 	fmt = check_fs(fs, bootsect = 0);	/* Check sector 0 as an SFD format */ | ||||
| 	if (fmt == 1) {						/* Not a FAT boot record, it may be patitioned */ | ||||
| 		/* Check a partition listed in top of the partition table */ | ||||
| 		tbl = &fs->win[MBR_Table + LD2PT(drv) * 16];	/* Partition table */ | ||||
| 		if (tbl[4]) {								/* Is the partition existing? */ | ||||
| 			basesect = LD_DWORD(&tbl[8]);			/* Partition offset in LBA */ | ||||
| 			fmt = check_fs(fs, basesect);			/* Check the partition */ | ||||
| 			bootsect = LD_DWORD(&tbl[8]);			/* Partition offset in LBA */ | ||||
| 			fmt = check_fs(fs, bootsect);			/* Check the partition */ | ||||
| 		} | ||||
| 	} | ||||
| 	if (fmt || LD_WORD(&fs->win[BPB_BytsPerSec]) != S_SIZ)	/* No valid FAT patition is found */ | ||||
| @ -665,14 +694,13 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	fs->sects_fat = fatsize; | ||||
| 	fs->n_fats = fs->win[BPB_NumFATs];					/* Number of FAT copies */ | ||||
| 	fatsize *= fs->n_fats;								/* (Number of sectors in FAT area) */ | ||||
| 	fs->fatbase = basesect += LD_WORD(&fs->win[BPB_RsvdSecCnt]); /* FAT start sector (lba) */ | ||||
| 	basesect += fatsize;								/* (Next sector of FAT area (lba)) */ | ||||
| 	fs->fatbase = bootsect + LD_WORD(&fs->win[BPB_RsvdSecCnt]); /* FAT start sector (lba) */ | ||||
| 	fs->sects_clust = fs->win[BPB_SecPerClus];			/* Number of sectors per cluster */ | ||||
| 	fs->n_rootdir = LD_WORD(&fs->win[BPB_RootEntCnt]);	/* Nmuber of root directory entries */ | ||||
| 	totalsect = LD_WORD(&fs->win[BPB_TotSec16]);		/* Number of sectors on the file system */ | ||||
| 	if (!totalsect) totalsect = LD_DWORD(&fs->win[BPB_TotSec32]); | ||||
| 	fs->max_clust = maxclust = (totalsect				/* Last cluster# + 1 */ | ||||
| 		- LD_WORD(&fs->win[BPB_RsvdSecCnt]) - fatsize - fs->n_rootdir / (S_SIZ / 32) | ||||
| 		- LD_WORD(&fs->win[BPB_RsvdSecCnt]) - fatsize - fs->n_rootdir / (S_SIZ/32) | ||||
| 		) / fs->sects_clust + 2; | ||||
| 
 | ||||
| 	fmt = FS_FAT12;										/* Determine the FAT sub type */ | ||||
| @ -683,11 +711,26 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	if (fmt == FS_FAT32) | ||||
| 		fs->dirbase = LD_DWORD(&fs->win[BPB_RootClus]);	/* Root directory start cluster */ | ||||
| 	else | ||||
| 		fs->dirbase = basesect;							/* Root directory start sector (lba) */ | ||||
| 	fs->database = basesect + fs->n_rootdir / (S_SIZ / 32);	/* Data start sector (lba) */ | ||||
| 		fs->dirbase = fs->fatbase + fatsize;			/* Root directory start sector (lba) */ | ||||
| 	fs->database = fs->fatbase + fatsize + fs->n_rootdir / (S_SIZ/32);	/* Data start sector (lba) */ | ||||
| 
 | ||||
| #if !_FS_READONLY | ||||
| 	fs->free_clust = 0xFFFFFFFF; | ||||
| #if _USE_FSINFO | ||||
| 	/* Load fsinfo sector if needed */ | ||||
| 	if (fmt == FS_FAT32) { | ||||
| 		fs->fsi_sector = bootsect + LD_WORD(&fs->win[BPB_FSInfo]); | ||||
| 		if (disk_read(0, fs->win, fs->fsi_sector, 1) == RES_OK && | ||||
| 			LD_WORD(&fs->win[BS_55AA]) == 0xAA55 && | ||||
| 			LD_DWORD(&fs->win[FSI_LeadSig]) == 0x41615252 && | ||||
| 			LD_DWORD(&fs->win[FSI_StrucSig]) == 0x61417272) { | ||||
| 			fs->last_clust = LD_DWORD(&fs->win[FSI_Nxt_Free]); | ||||
| 			fs->free_clust = LD_DWORD(&fs->win[FSI_Free_Count]); | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| #endif | ||||
| 	fs->id = ++fsid;									/* File system mount ID */ | ||||
| 
 | ||||
| 	return FR_OK; | ||||
| } | ||||
| 
 | ||||
| @ -764,7 +807,8 @@ FRESULT f_open ( | ||||
| 	FATFS *fs; | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| 	fp->fs = NULL; | ||||
| #if !_FS_READONLY | ||||
| 	mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW); | ||||
| 	res = auto_mount(&path, &fs, (BYTE)(mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW))); | ||||
| #else | ||||
| @ -776,7 +820,7 @@ FRESULT f_open ( | ||||
| 
 | ||||
| 	/* Trace the file path */ | ||||
| 	res = trace_path(&dirobj, fn, path, &dir); | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	/* Create or Open a file */ | ||||
| 	if (mode & (FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)) { | ||||
| 		DWORD ps, rs; | ||||
| @ -816,11 +860,11 @@ FRESULT f_open ( | ||||
| 	} | ||||
| 	/* Open an existing file */ | ||||
| 	else { | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 		if (res != FR_OK) return res;		/* Trace failed */ | ||||
| 		if (dir == NULL || (dir[DIR_Attr] & AM_DIR))	/* It is a directory */ | ||||
| 			return FR_NO_FILE; | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 		if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ | ||||
| 			return FR_DENIED; | ||||
| 	} | ||||
| @ -882,7 +926,7 @@ FRESULT f_read ( | ||||
| 				sect = clust2sect(fs, clust);		/* Get current sector */ | ||||
| 				fp->sect_clust = fs->sects_clust;	/* Re-initialize the left sector counter */ | ||||
| 			} | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 			if (fp->flag & FA__DIRTY) {				/* Flush file I/O buffer if needed */ | ||||
| 				if (disk_write(fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK) | ||||
| 					goto fr_error; | ||||
| @ -917,7 +961,7 @@ fr_error:	/* Abort this file due to an unrecoverable error */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| /* Write File                                                            */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| @ -1040,7 +1084,7 @@ FRESULT f_sync ( | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -1056,7 +1100,7 @@ FRESULT f_close ( | ||||
| 	FRESULT res; | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	res = f_sync(fp); | ||||
| #else | ||||
| 	res = validate(fp->fs, fp->id); | ||||
| @ -1088,7 +1132,7 @@ FRESULT f_lseek ( | ||||
| 	res = validate(fs, fp->id);			/* Check validity of the object */ | ||||
| 	if (res) return res; | ||||
| 	if (fp->flag & FA__ERROR) return FR_RW_ERROR; | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	if (fp->flag & FA__DIRTY) {			/* Write-back dirty buffer if needed */ | ||||
| 		if (disk_write(fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK) | ||||
| 			goto fk_error; | ||||
| @ -1104,33 +1148,33 @@ FRESULT f_lseek ( | ||||
| 	/* Move file R/W pointer if needed */ | ||||
| 	if (ofs) { | ||||
| 		clust = fp->org_clust;	/* Get start cluster */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 		if (!clust) {			/* If the file does not have a cluster chain, create new cluster chain */ | ||||
| 			clust = create_chain(fs, 0); | ||||
| 			if (clust == 1) goto fk_error; | ||||
| 			fp->org_clust = fp->curr_clust = clust; | ||||
| 			fp->org_clust = clust; | ||||
| 		} | ||||
| #endif | ||||
| 		if (clust) {			/* If the file has a cluster chain, it can be followed */ | ||||
| 			csize = (DWORD)fs->sects_clust * S_SIZ;		/* Cluster size in unit of byte */ | ||||
| 			while (ofs > csize) {						/* Skip leading clusters */ | ||||
| #if _FS_READONLY == 0 | ||||
| 				if (fp->flag & FA_WRITE)					/* Check if in write mode or not */ | ||||
| 					clust = create_chain(fs, clust);		/* Force streached if in write mode */ | ||||
| 			for (;;) {									/* Loop to skip leading clusters */ | ||||
| 				fp->curr_clust = clust;					/* Update current cluster */ | ||||
| 				if (ofs <= csize) break; | ||||
| #if !_FS_READONLY | ||||
| 				if (fp->flag & FA_WRITE)				/* Check if in write mode or not */ | ||||
| 					clust = create_chain(fs, clust);	/* Force streached if in write mode */ | ||||
| 				else | ||||
| #endif | ||||
| 					clust = get_cluster(fs, clust);			/* Only follow cluster chain if not in write mode */ | ||||
| 				if (clust == 0) {							/* Stop if could not follow the cluster chain */ | ||||
| 					ofs = csize; | ||||
| 					break; | ||||
| 					clust = get_cluster(fs, clust);		/* Only follow cluster chain if not in write mode */ | ||||
| 				if (clust == 0) {						/* Stop if could not follow the cluster chain */ | ||||
| 					ofs = csize; break; | ||||
| 				} | ||||
| 				if (clust == 1 || clust >= fs->max_clust) goto fk_error; /* Abort when any error occured */ | ||||
| 				fp->curr_clust = clust;						/* Update current cluster and R/W pointer */ | ||||
| 				fp->fptr += csize; | ||||
| 				if (clust == 1 || clust >= fs->max_clust) goto fk_error; | ||||
| 				fp->fptr += csize;						/* Update R/W pointer */ | ||||
| 				ofs -= csize; | ||||
| 			} | ||||
| 			csect = (BYTE)((ofs - 1) / S_SIZ);			/* Sector offset in the cluster */ | ||||
| 			fp->curr_sect = clust2sect(fs, clust) + csect;	/* Get current cluster */ | ||||
| 			fp->curr_sect = clust2sect(fs, clust) + csect;	/* Current sector */ | ||||
| 			if ((ofs & (S_SIZ - 1)) &&					/* Load current sector if needed */ | ||||
| 				disk_read(fs->drive, fp->buffer, fp->curr_sect, 1) != RES_OK) | ||||
| 				goto fk_error; | ||||
| @ -1138,7 +1182,7 @@ FRESULT f_lseek ( | ||||
| 			fp->fptr += ofs;							/* Update file R/W pointer */ | ||||
| 		} | ||||
| 	} | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	if ((fp->flag & FA_WRITE) && fp->fptr > fp->fsize) {	/* Set updated flag if in write mode */ | ||||
| 		fp->fsize = fp->fptr; | ||||
| 		fp->flag |= FA__WRITTEN; | ||||
| @ -1263,7 +1307,7 @@ FRESULT f_stat ( | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| /* Get Number of Free Clusters                                           */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| @ -1285,6 +1329,12 @@ FRESULT f_getfree ( | ||||
| 	if (res != FR_OK) return res; | ||||
| 	*fatfs = fs; | ||||
| 
 | ||||
| 	/* If number of free cluster is valid, return it without cluster scan. */ | ||||
| 	if (fs->free_clust <= fs->max_clust - 2) { | ||||
| 		*nclust = fs->free_clust; | ||||
| 		return FR_OK; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Count number of free clusters */ | ||||
| 	fat = fs->fs_type; | ||||
| 	n = 0; | ||||
| @ -1311,6 +1361,10 @@ FRESULT f_getfree ( | ||||
| 			} | ||||
| 		} while (--clust); | ||||
| 	} | ||||
| 	fs->free_clust = n; | ||||
| #if _USE_FSINFO | ||||
| 	if (fat == FS_FAT32) fs->fsi_flag = 1; | ||||
| #endif | ||||
| 
 | ||||
| 	*nclust = n; | ||||
| 	return FR_OK; | ||||
| @ -1378,7 +1432,7 @@ FRESULT f_mkdir ( | ||||
| 	const char *path		/* Pointer to the directory path */ | ||||
| ) | ||||
| { | ||||
| 	BYTE *dir, *sec, n; | ||||
| 	BYTE *dir, *fw, n; | ||||
| 	char fn[8+3+1]; | ||||
| 	DWORD sect, dsect, dclust, pclust, tim; | ||||
| 	FRESULT res; | ||||
| @ -1401,31 +1455,31 @@ FRESULT f_mkdir ( | ||||
| 	if (dclust == 1) return FR_RW_ERROR; | ||||
| 	dsect = clust2sect(fs, dclust); | ||||
| 	if (!dsect) return FR_DENIED; | ||||
| 	if (!move_window(fs, 0)) return FR_RW_ERROR; | ||||
| 	if (!move_window(fs, dsect)) return FR_RW_ERROR; | ||||
| 
 | ||||
| 	sec = fs->win; | ||||
| 	memset(sec, 0, S_SIZ);						/* Initialize the directory table */ | ||||
| 	for (n = fs->sects_clust - 1; n; n--) { | ||||
| 		if (disk_write(fs->drive, sec, dsect+n, 1) != RES_OK) | ||||
| 	fw = fs->win; | ||||
| 	memset(fw, 0, S_SIZ);						/* Clear the new directory table */ | ||||
| 	for (n = 1; n < fs->sects_clust; n++) { | ||||
| 		if (disk_write(fs->drive, fw, ++dsect, 1) != RES_OK) | ||||
| 			return FR_RW_ERROR; | ||||
| 	} | ||||
| 
 | ||||
| 	fs->winsect = dsect;						/* Create "." ".." directories */ | ||||
| 	memset(&sec[DIR_Name], ' ', 8+3);			/* "." entry */ | ||||
| 	sec[DIR_Name] = '.'; | ||||
| 	sec[DIR_Attr] = AM_DIR; | ||||
| 	memset(&fw[DIR_Name], ' ', 8+3);			/* Create "." entry */ | ||||
| 	fw[DIR_Name] = '.'; | ||||
| 	fw[DIR_Attr] = AM_DIR; | ||||
| 	tim = get_fattime(); | ||||
| 	ST_DWORD(&sec[DIR_WrtTime], tim); | ||||
| 	memcpy(&sec[32], &sec[0], 32); sec[33] = '.'; /* ".." entry */ | ||||
| 	ST_WORD(&sec[DIR_FstClusLO], dclust); | ||||
| 	ST_WORD(&sec[DIR_FstClusHI], dclust >> 16); | ||||
| 	ST_DWORD(&fw[DIR_WrtTime], tim); | ||||
| 	memcpy(&fw[32], &fw[0], 32); fw[33] = '.';	/* Create ".." entry */ | ||||
| 	pclust = dirobj.sclust; | ||||
| #if _FAT32 | ||||
| 	ST_WORD(&fw[   DIR_FstClusHI], dclust >> 16); | ||||
| 	if (fs->fs_type == FS_FAT32 && pclust == fs->dirbase) pclust = 0; | ||||
| 	ST_WORD(&sec[32+DIR_FstClusLO], pclust); | ||||
| 	ST_WORD(&sec[32+DIR_FstClusHI], pclust >> 16); | ||||
| 	ST_WORD(&fw[32+DIR_FstClusHI], pclust >> 16); | ||||
| #endif | ||||
| 	ST_WORD(&fw[   DIR_FstClusLO], dclust); | ||||
| 	ST_WORD(&fw[32+DIR_FstClusLO], pclust); | ||||
| 	fs->winflag = 1; | ||||
| 	if (!move_window(fs, sect)) return FR_RW_ERROR; | ||||
| 
 | ||||
| 	if (!move_window(fs, sect)) return FR_RW_ERROR; | ||||
| 	memset(&dir[0], 0, 32);						/* Initialize the new entry */ | ||||
| 	memcpy(&dir[DIR_Name], fn, 8+3);			/* Name */ | ||||
| 	dir[DIR_NTres] = fn[11]; | ||||
| @ -1523,7 +1577,7 @@ FRESULT f_rename ( | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #if _USE_MKFS != 0 | ||||
| #if _USE_MKFS | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| /* Create File System on the Drive                                       */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| @ -1531,7 +1585,7 @@ FRESULT f_rename ( | ||||
| #define N_ROOTDIR 512 | ||||
| #define N_FATS 1 | ||||
| #define MAX_SECTOR 64000000UL | ||||
| #define MIN_SECTOR 1000UL | ||||
| #define MIN_SECTOR 2000UL | ||||
| #define ERASE_BLK 32 | ||||
| 
 | ||||
| 
 | ||||
| @ -1545,12 +1599,11 @@ FRESULT f_mkfs ( | ||||
| 	DWORD b_part, b_fat, b_dir, b_data;		/* Area offset (LBA) */ | ||||
| 	DWORD n_part, n_rsv, n_fat, n_dir;		/* Area size */ | ||||
| 	DWORD n_clust, n; | ||||
| 	static const BYTE tbl_alloc[] = {1,2,4,8,16,32,64,0}; | ||||
| 	FATFS *fs; | ||||
| 	DSTATUS stat; | ||||
| 
 | ||||
| 
 | ||||
| 	/* Check mounted drive */ | ||||
| 	/* Check and mounted drive and clear work area */ | ||||
| 	if (drv >= _DRIVES) return FR_INVALID_DRIVE; | ||||
| 	fs = FatFs[drv]; | ||||
| 	if (!fs) return FR_NOT_ENABLED; | ||||
| @ -1558,8 +1611,8 @@ FRESULT f_mkfs ( | ||||
| 	drv = LD2PD(drv); | ||||
| 
 | ||||
| 	/* Check validity of the parameters */ | ||||
| 	for (n = 0; allocsize != tbl_alloc[n] && tbl_alloc[n]; n++); | ||||
| 	if (!tbl_alloc[n] || partition >= 2) return FR_MKFS_ABORTED; | ||||
| 	for (n = 1; n <= 64 && allocsize != n; n <<= 1); | ||||
| 	if (n > 64 || partition >= 2) return FR_MKFS_ABORTED; | ||||
| 
 | ||||
| 	/* Get disk statics */ | ||||
| 	stat = disk_initialize(drv); | ||||
| @ -1671,23 +1724,11 @@ FRESULT f_mkfs ( | ||||
| 		memcpy(&tbl[BS_VolLab32], "NO NAME    FAT32   ", 19);	/* Volume lavel, FAT signature */ | ||||
| 	} | ||||
| 	ST_WORD(&tbl[BS_55AA], 0xAA55);			/* Signature */ | ||||
| 	if (disk_write(drv, tbl, b_part, 1) != RES_OK) | ||||
| 	if (disk_write(drv, tbl, b_part+0, 1) != RES_OK) | ||||
| 		return FR_RW_ERROR; | ||||
| 	if (fmt == FS_FAT32) | ||||
| 		disk_write(drv, tbl, b_part+6, 1); | ||||
| 
 | ||||
| 	/* Create FSInfo record if needed */ | ||||
| 	if (fmt == FS_FAT32) { | ||||
| 		memset(tbl, 0, 510); | ||||
| 		ST_DWORD(&tbl[0], 0x41615252);		/* "RRaA" */ | ||||
| 		ST_DWORD(&tbl[484], 0x61417272);	/* "rrAa" */ | ||||
| 		ST_DWORD(&tbl[488], 0xFFFFFFFF);	/* Free count */ | ||||
| 		ST_DWORD(&tbl[492], 0xFFFFFFFF);	/* Last allocated */ | ||||
| 		if (disk_write(drv, tbl, b_part+1, 1) != RES_OK) | ||||
| 			return FR_RW_ERROR; | ||||
| 		disk_write(drv, tbl, b_part+7, 1); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Initialize FAT area */ | ||||
| 	for (m = 0; m < N_FATS; m++) { | ||||
| 		memset(tbl, 0, S_SIZ);		/* 1st sector of the FAT  */ | ||||
| @ -1714,11 +1755,22 @@ FRESULT f_mkfs ( | ||||
| 			return FR_RW_ERROR; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Create FSInfo record if needed */ | ||||
| 	if (fmt == FS_FAT32) { | ||||
| 		ST_WORD(&tbl[BS_55AA], 0xAA55); | ||||
| 		ST_DWORD(&tbl[FSI_LeadSig], 0x41615252); | ||||
| 		ST_DWORD(&tbl[FSI_StrucSig], 0x61417272); | ||||
| 		ST_DWORD(&tbl[FSI_Free_Count], n_clust - 1); | ||||
| 		ST_DWORD(&tbl[FSI_Nxt_Free], 0xFFFFFFFF); | ||||
| 		disk_write(drv, tbl, b_part+1, 1); | ||||
| 		disk_write(drv, tbl, b_part+7, 1); | ||||
| 	} | ||||
| 
 | ||||
| 	return (disk_ioctl(drv, CTRL_SYNC, NULL) == RES_OK) ? FR_OK : FR_RW_ERROR; | ||||
| } | ||||
| 
 | ||||
| #endif /* _USE_MKFS != 0 */ | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* _USE_MKFS */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| #endif /* _FS_MINIMIZE == 0 */ | ||||
| #endif /* _FS_MINIMIZE <= 1 */ | ||||
| #endif /* _FS_MINIMIZE <= 2 */ | ||||
|  | ||||
							
								
								
									
										37
									
								
								src/ff.h
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/ff.h
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| /*--------------------------------------------------------------------------/
 | ||||
| /  FatFs - FAT file system module include file  R0.04a       (C)ChaN, 2007 | ||||
| /  FatFs - FAT file system module include file  R0.04b       (C)ChaN, 2007 | ||||
| /---------------------------------------------------------------------------/ | ||||
| / FatFs module is an experimenal project to implement FAT file system to | ||||
| / cheap microcontrollers. This is a free software and is opened for education, | ||||
| @ -36,13 +36,9 @@ | ||||
| /  2: f_opendir and f_readdir are removed in addition to level 1. | ||||
| /  3: f_lseek is removed in addition to level 2. */ | ||||
| 
 | ||||
| #define _DRIVES		1 | ||||
| #define _DRIVES		2 | ||||
| /* Number of logical drives to be used. This affects the size of internal table. */ | ||||
| 
 | ||||
| #define	_USE_SJIS	1 | ||||
| /* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
 | ||||
| /  only US-ASCII(7bit) code can be accepted as file/directory name. */ | ||||
| 
 | ||||
| #define	_USE_MKFS	0 | ||||
| /* When _USE_MKFS is set to 1 and _FS_READONLY is set to 0, f_mkfs function is
 | ||||
| /  enabled. */ | ||||
| @ -52,6 +48,18 @@ | ||||
| /  physical drive number and can mount only 1st primaly partition. When it is | ||||
| /  set to 1, each logical drive can mount a partition listed in Drives[]. */ | ||||
| 
 | ||||
| #define _USE_FSINFO	0 | ||||
| /* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */ | ||||
| 
 | ||||
| #define	_USE_SJIS	1 | ||||
| /* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
 | ||||
| /  only US-ASCII(7bit) code can be accepted as file/directory name. */ | ||||
| 
 | ||||
| #define	_USE_NTFLAG	1 | ||||
| /* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
 | ||||
| /  Note that the files are always accessed in case insensitive. */ | ||||
| 
 | ||||
| 
 | ||||
| #include "integer.h" | ||||
| 
 | ||||
| 
 | ||||
| @ -75,12 +83,20 @@ typedef struct _FATFS { | ||||
| 	DWORD	fatbase;		/* FAT start sector */ | ||||
| 	DWORD	dirbase;		/* Root directory start sector (cluster# for FAT32) */ | ||||
| 	DWORD	database;		/* Data start sector */ | ||||
| #if !_FS_READONLY | ||||
| 	DWORD	last_clust;		/* Last allocated cluster */ | ||||
| #if S_MAX_SIZ > 512 | ||||
| 	WORD	s_size;			/* Sector size */ | ||||
| 	DWORD	free_clust;		/* Number of free clusters */ | ||||
| #if _USE_FSINFO | ||||
| 	DWORD	fsi_sector;		/* fsinfo sector */ | ||||
| 	BYTE	fsi_flag;		/* fsinfo dirty flag (1:must be written back) */ | ||||
| 	BYTE	pad2; | ||||
| #endif | ||||
| #endif | ||||
| 	BYTE	fs_type;		/* FAT sub type */ | ||||
| 	BYTE	sects_clust;	/* Sectors per cluster */ | ||||
| #if S_MAX_SIZ > 512 | ||||
| 	WORD	s_size;			/* Sector size */ | ||||
| #endif | ||||
| 	BYTE	n_fats;			/* Number of FAT copies */ | ||||
| 	BYTE	drive;			/* Physical drive number */ | ||||
| 	BYTE	winflag;		/* win[] dirty flag (1:must be written back) */ | ||||
| @ -270,6 +286,11 @@ DWORD get_fattime (void);	/* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20 | ||||
| #define BS_VolLab32			71 | ||||
| #define BS_FilSysType32		82 | ||||
| 
 | ||||
| #define	FSI_LeadSig			0 | ||||
| #define	FSI_StrucSig		484 | ||||
| #define	FSI_Free_Count		488 | ||||
| #define	FSI_Nxt_Free		492 | ||||
| 
 | ||||
| #define MBR_Table			446 | ||||
| 
 | ||||
| #define	DIR_Name			0 | ||||
|  | ||||
							
								
								
									
										294
									
								
								src/tff.c
									
									
									
									
									
								
							
							
						
						
									
										294
									
								
								src/tff.c
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| /*--------------------------------------------------------------------------/
 | ||||
| /  FatFs - Tiny FAT file system module  R0.04a                (C)ChaN, 2007 | ||||
| /  FatFs - Tiny FAT file system module  R0.04b                (C)ChaN, 2007 | ||||
| /---------------------------------------------------------------------------/ | ||||
| / The FatFs module is an experimenal project to implement FAT file system to | ||||
| / cheap microcontrollers. This is a free software and is opened for education, | ||||
| @ -15,7 +15,8 @@ | ||||
| /---------------------------------------------------------------------------/ | ||||
| /  Feb 26, 2006  R0.00  Prototype. | ||||
| /  Apr 29, 2006  R0.01  First stable version. | ||||
| /  Jun 01, 2006  R0.02  Added FAT12. Removed unbuffered mode. | ||||
| /  Jun 01, 2006  R0.02  Added FAT12 support. | ||||
| /                       Removed unbuffered mode. | ||||
| /                       Fixed a problem on small (<32M) patition. | ||||
| /  Jun 10, 2006  R0.02a Added a configuration option (_FS_MINIMUM). | ||||
| /  Sep 22, 2006  R0.03  Added f_rename(). | ||||
| @ -23,16 +24,22 @@ | ||||
| /  Dec 09, 2006  R0.03a Improved cluster scan algolithm to write files fast. | ||||
| /  Feb 04, 2007  R0.04  Added FAT32 supprt. | ||||
| /                       Changed some interfaces incidental to FatFs. | ||||
| /                       Changed f_mountdrv() to f_mount(). | ||||
| /  Apr 01, 2007  R0.04a Added a capability of extending file size to f_lseek(). | ||||
| /                       Added minimization level 3. | ||||
| /                       Fixed a problem that can collapse a sector when recreate | ||||
| /                       an existing file in any sub-directory at non FAT32 cfg. | ||||
| /                       Fixed a problem in FAT32 support. | ||||
| /  May 05, 2007  R0.04b Added a configuration option _USE_NTFLAG. | ||||
| /                       Added FSInfo support. | ||||
| /                       Fixed some problems corresponds to FAT32 support. | ||||
| /                       Fixed DBCS name can result FR_INVALID_NAME. | ||||
| /                       Fixed short seek (<= csize) collapses the file object. | ||||
| /---------------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include "tff.h"		/* Tiny-FatFs declarations */ | ||||
| #include "diskio.h"		/* Include file for user provided disk functions */ | ||||
| 
 | ||||
| 
 | ||||
| static | ||||
| FATFS *FatFs;			/* Pointer to the file system objects (logical drive) */ | ||||
| static | ||||
| @ -61,7 +68,7 @@ BOOL move_window (		/* TRUE: successful, FALSE: failed */ | ||||
| 
 | ||||
| 	wsect = fs->winsect; | ||||
| 	if (wsect != sector) {	/* Changed current window */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 		BYTE n; | ||||
| 		if (fs->winflag) {	/* Write back dirty window if needed */ | ||||
| 			if (disk_write(0, fs->win, wsect, 1) != RES_OK) | ||||
| @ -91,12 +98,28 @@ BOOL move_window (		/* TRUE: successful, FALSE: failed */ | ||||
| /* Clean-up cached data                                                  */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| FRESULT sync (void)		/* FR_OK: successful, FR_RW_ERROR: failed */ | ||||
| { | ||||
| 	FatFs->winflag = 1; | ||||
| 	FATFS *fs = FatFs; | ||||
| 
 | ||||
| 
 | ||||
| 	fs->winflag = 1; | ||||
| 	if (!move_window(0)) return FR_RW_ERROR; | ||||
| #if _USE_FSINFO | ||||
| 	if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {		/* Update FSInfo sector if needed */ | ||||
| 		fs->winsect = 0; | ||||
| 		memset(fs->win, 0, 512); | ||||
| 		ST_WORD(&fs->win[BS_55AA], 0xAA55); | ||||
| 		ST_DWORD(&fs->win[FSI_LeadSig], 0x41615252); | ||||
| 		ST_DWORD(&fs->win[FSI_StrucSig], 0x61417272); | ||||
| 		ST_DWORD(&fs->win[FSI_Free_Count], fs->free_clust); | ||||
| 		ST_DWORD(&fs->win[FSI_Nxt_Free], fs->last_clust); | ||||
| 		disk_write(0, fs->win, fs->fsi_sector, 1); | ||||
| 		fs->fsi_flag = 0; | ||||
| 	} | ||||
| #endif | ||||
| 	if (disk_ioctl(0, CTRL_SYNC, NULL) != RES_OK) return FR_RW_ERROR; | ||||
| 	return FR_OK; | ||||
| } | ||||
| @ -133,7 +156,7 @@ CLUST get_cluster (		/* 0,>=2: successful, 1: failed */ | ||||
| 		case FS_FAT16 : | ||||
| 			if (!move_window(fatsect + clust / 256)) break; | ||||
| 			return LD_WORD(&fs->win[((WORD)clust * 2) % 512]); | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 		case FS_FAT32 : | ||||
| 			if (!move_window(fatsect + clust / 128)) break; | ||||
| 			return LD_DWORD(&fs->win[((WORD)clust * 4) % 512]) & 0x0FFFFFFF; | ||||
| @ -151,7 +174,7 @@ CLUST get_cluster (		/* 0,>=2: successful, 1: failed */ | ||||
| /* Change a cluster status                                               */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| 	CLUST clust,		/* Cluster# to change */ | ||||
| @ -182,7 +205,7 @@ BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| 		if (!move_window(fatsect + clust / 256)) return FALSE; | ||||
| 		ST_WORD(&fs->win[((WORD)clust * 2) % 512], (WORD)val); | ||||
| 		break; | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 	case FS_FAT32 : | ||||
| 		if (!move_window(fatsect + clust / 128)) return FALSE; | ||||
| 		ST_DWORD(&fs->win[((WORD)clust * 4) % 512], val); | ||||
| @ -194,7 +217,7 @@ BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| 	fs->winflag = 1; | ||||
| 	return TRUE; | ||||
| } | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -203,19 +226,26 @@ BOOL put_cluster (		/* TRUE: successful, FALSE: failed */ | ||||
| /* Remove a cluster chain                                                */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| BOOL remove_chain (		/* TRUE: successful, FALSE: failed */ | ||||
| 	CLUST clust			/* Cluster# to remove chain from */ | ||||
| ) | ||||
| { | ||||
| 	CLUST nxt; | ||||
| 	FATFS *fs = FatFs; | ||||
| 
 | ||||
| 
 | ||||
| 	while (clust >= 2 && clust < FatFs->max_clust) { | ||||
| 	while (clust >= 2 && clust < fs->max_clust) { | ||||
| 		nxt = get_cluster(clust); | ||||
| 		if (nxt == 1) return FALSE; | ||||
| 		if (!put_cluster(clust, 0)) return FALSE; | ||||
| 		if (fs->free_clust != (CLUST)0xFFFFFFFF) { | ||||
| 			fs->free_clust++; | ||||
| #if _USE_FSINFO | ||||
| 			fs->fsi_flag = 1; | ||||
| #endif | ||||
| 		} | ||||
| 		clust = nxt; | ||||
| 	} | ||||
| 	return TRUE; | ||||
| @ -229,7 +259,7 @@ BOOL remove_chain (		/* TRUE: successful, FALSE: failed */ | ||||
| /* Stretch or create a cluster chain                                     */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| CLUST create_chain (	/* 0: no free cluster, 1: error, >=2: new cluster number */ | ||||
| 	CLUST clust			/* Cluster# to stretch, 0 means create new */ | ||||
| @ -266,11 +296,18 @@ CLUST create_chain (	/* 0: no free cluster, 1: error, >=2: new cluster number */ | ||||
| 
 | ||||
| 	if (!put_cluster(ncl, (CLUST)0x0FFFFFFF)) return 1;	/* Mark the new cluster "in use" */ | ||||
| 	if (clust && !put_cluster(clust, ncl)) return 1;	/* Link it to previous one if needed */ | ||||
| 	fs->last_clust = ncl; | ||||
| 
 | ||||
| 	fs->last_clust = ncl;				/* Update fsinfo */ | ||||
| 	if (fs->free_clust != (CLUST)0xFFFFFFFF) { | ||||
| 		fs->free_clust--; | ||||
| #if _USE_FSINFO | ||||
| 		fs->fsi_flag = 1; | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	return ncl;		/* Return new cluster number */ | ||||
| } | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -347,7 +384,7 @@ void get_fileinfo (		/* No return code */ | ||||
| 
 | ||||
| 
 | ||||
| 	p = &finfo->fname[0]; | ||||
| 	a = dir[DIR_NTres];	/* NT flag */ | ||||
| 	a = _USE_NTFLAG ? dir[DIR_NTres] : 0;	/* NT flag */ | ||||
| 	for (n = 0; n < 8; n++) {	/* Convert file name (body) */ | ||||
| 		c = dir[n]; | ||||
| 		if (c == ' ') break; | ||||
| @ -396,39 +433,36 @@ char make_dirfile (			/* 1: error - detected an invalid format, '\0'or'/': next | ||||
| 		c = *(*path)++; | ||||
| 		if (c == '\0' || c == '/') {		/* Reached to end of str or directory separator */ | ||||
| 			if (n == 0) break; | ||||
| 			dirname[11] = a & b; return c; | ||||
| 			dirname[11] = _USE_NTFLAG ? (a & b) : 0; | ||||
| 			return c; | ||||
| 		} | ||||
| 		if (c <= ' ') break;		/* Reject invisible chars */ | ||||
| 		if (c <= ' ' || c == 0x7F) break;		/* Reject invisible chars */ | ||||
| 		if (c == '.') { | ||||
| 			if(!(a & 1) && n >= 1 && n <= 8) {	/* Enter extension part */ | ||||
| 			if (!(a & 1) && n >= 1 && n <= 8) {	/* Enter extension part */ | ||||
| 				n = 8; t = 11; continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| #if _USE_SJIS != 0 | ||||
| 		if ((c >= 0x81 && c <= 0x9F) ||		/* Accept S-JIS code */ | ||||
| 		    (c >= 0xE0 && c <= 0xFC)) { | ||||
| 		if (_USE_SJIS &&  | ||||
| 			((c >= 0x81 && c <= 0x9F) ||		/* Accept S-JIS code */ | ||||
| 		    (c >= 0xE0 && c <= 0xFC))) { | ||||
| 			if (n == 0 && c == 0xE5)		/* Change heading \xE5 to \x05 */ | ||||
| 				c = 0x05; | ||||
| 			a ^= 1; goto md_l2; | ||||
| 		} | ||||
| 		if (c >= 0x7F && c <= 0x80) break;		/* Reject \x7F \x80 */ | ||||
| #else | ||||
| 		if (c >= 0x7F) goto md_l1;				/* Accept \x7F-0xFF */ | ||||
| #endif | ||||
| 		if (c == '"') break;					/* Reject " */ | ||||
| 		if (c <= ')') goto md_l1;				/* Accept ! # $ % & ' ( ) */ | ||||
| 		if (c <= ',') break;					/* Reject * + , */ | ||||
| 		if (c <= '9') goto md_l1;				/* Accept - 0-9 */ | ||||
| 		if (c <= '?') break;					/* Reject : ; < = > ? */ | ||||
| 		if (c == '"') break;				/* Reject " */ | ||||
| 		if (c <= ')') goto md_l1;			/* Accept ! # $ % & ' ( ) */ | ||||
| 		if (c <= ',') break;				/* Reject * + , */ | ||||
| 		if (c <= '9') goto md_l1;			/* Accept - 0-9 */ | ||||
| 		if (c <= '?') break;				/* Reject : ; < = > ? */ | ||||
| 		if (!(a & 1)) {	/* These checks are not applied to S-JIS 2nd byte */ | ||||
| 			if (c == '|') break;				/* Reject | */ | ||||
| 			if (c == '|') break;			/* Reject | */ | ||||
| 			if (c >= '[' && c <= ']') break;/* Reject [ \ ] */ | ||||
| 			if (c >= 'A' && c <= 'Z') | ||||
| 			if (_USE_NTFLAG && c >= 'A' && c <= 'Z') | ||||
| 				(t == 8) ? (b &= ~0x08) : (b &= ~0x10); | ||||
| 			if (c >= 'a' && c <= 'z') {		/* Convert to upper case */ | ||||
| 				c -= 0x20; | ||||
| 				(t == 8) ? (a |= 0x08) : (a |= 0x10); | ||||
| 				if (_USE_NTFLAG) (t == 8) ? (a |= 0x08) : (a |= 0x10); | ||||
| 			} | ||||
| 		} | ||||
| 	md_l1: | ||||
| @ -461,7 +495,7 @@ FRESULT trace_path (	/* FR_OK(0): successful, !=0: error code */ | ||||
| 
 | ||||
| 	/* Initialize directory object */ | ||||
| 	clust = fs->dirbase; | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 	if (fs->fs_type == FS_FAT32) { | ||||
| 		dirobj->clust = dirobj->sclust = clust; | ||||
| 		dirobj->sect = clust2sect(clust); | ||||
| @ -493,12 +527,12 @@ FRESULT trace_path (	/* FR_OK(0): successful, !=0: error code */ | ||||
| 				return !ds ? FR_NO_FILE : FR_NO_PATH; | ||||
| 		} | ||||
| 		if (!ds) { *dir = dptr; return FR_OK; }				/* Matched with end of path */ | ||||
| 		if (!(dptr[DIR_Attr] & AM_DIR)) return FR_NO_PATH;/* Cannot trace because it is a file */ | ||||
| #if _FAT32 != 0 | ||||
| 		clust = ((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) | LD_WORD(&dptr[DIR_FstClusLO]);	/* Get cluster# of the directory */ | ||||
| #else | ||||
| 		clust = LD_WORD(&dptr[DIR_FstClusLO]); | ||||
| 		if (!(dptr[DIR_Attr] & AM_DIR)) return FR_NO_PATH;	/* Cannot trace because it is a file */ | ||||
| 		clust =												/* Get cluster# of the directory */ | ||||
| #if _FAT32 | ||||
| 			((DWORD)LD_WORD(&dptr[DIR_FstClusHI]) << 16) | | ||||
| #endif | ||||
| 			LD_WORD(&dptr[DIR_FstClusLO]); | ||||
| 		dirobj->clust = dirobj->sclust = clust;				/* Restart scannig with the new directory */ | ||||
| 		dirobj->sect = clust2sect(clust); | ||||
| 		dirobj->index = 2; | ||||
| @ -511,7 +545,7 @@ FRESULT trace_path (	/* FR_OK(0): successful, !=0: error code */ | ||||
| /* Reserve a directory entry                                             */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| static | ||||
| FRESULT reserve_direntry (	/* FR_OK: successful, FR_DENIED: no free entry, FR_RW_ERROR: a disk error occured */ | ||||
| 	DIR *dirobj,			/* Target directory to create new entry */ | ||||
| @ -559,7 +593,7 @@ FRESULT reserve_direntry (	/* FR_OK: successful, FR_DENIED: no free entry, FR_RW | ||||
| 	*dir = fs->win; | ||||
| 	return FR_OK; | ||||
| } | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -582,7 +616,7 @@ BYTE check_fs (		/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2 | ||||
| 
 | ||||
| 	if (!memcmp(&fs->win[BS_FilSysType], "FAT", 3))	/* Check FAT signature */ | ||||
| 		return 0; | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 	if (!memcmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80)) | ||||
| 		return 0; | ||||
| #endif | ||||
| @ -604,7 +638,7 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| { | ||||
| 	BYTE fmt; | ||||
| 	DSTATUS stat; | ||||
| 	DWORD basesect, fatsize, totalsect, maxclust; | ||||
| 	DWORD bootsect, fatsize, totalsect, maxclust; | ||||
| 	const char *p = *path; | ||||
| 	FATFS *fs = FatFs; | ||||
| 
 | ||||
| @ -621,7 +655,7 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	if (fs->fs_type) { | ||||
| 		stat = disk_status(0); | ||||
| 		if (!(stat & STA_NOINIT)) {				/* If the physical drive is kept initialized */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 			if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */ | ||||
| 				return FR_WRITE_PROTECTED; | ||||
| #endif | ||||
| @ -635,18 +669,18 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	stat = disk_initialize(0);			/* Initialize low level disk I/O layer */ | ||||
| 	if (stat & STA_NOINIT)				/* Check if the drive is ready */ | ||||
| 		return FR_NOT_READY; | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */ | ||||
| 		return FR_WRITE_PROTECTED; | ||||
| #endif | ||||
| 
 | ||||
| 	/* Search FAT partition on the drive */ | ||||
| 	fmt = check_fs(basesect = 0);		/* Check sector 0 as an SFD format */ | ||||
| 	fmt = check_fs(bootsect = 0);		/* Check sector 0 as an SFD format */ | ||||
| 	if (fmt == 1) {						/* Not a FAT boot record, it may be patitioned */ | ||||
| 		/* Check a partition listed in top of the partition table */ | ||||
| 		if (fs->win[MBR_Table+4]) {					/* Is the 1st partition existing? */ | ||||
| 			basesect = LD_DWORD(&fs->win[MBR_Table+8]);	/* Partition offset in LBA */ | ||||
| 			fmt = check_fs(basesect);				/* Check the partition */ | ||||
| 			bootsect = LD_DWORD(&fs->win[MBR_Table+8]);	/* Partition offset in LBA */ | ||||
| 			fmt = check_fs(bootsect);				/* Check the partition */ | ||||
| 		} | ||||
| 	} | ||||
| 	if (fmt || LD_WORD(&fs->win[BPB_BytsPerSec]) != 512)	/* No valid FAT patition is found */ | ||||
| @ -658,8 +692,7 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	fs->sects_fat = (CLUST)fatsize; | ||||
| 	fs->n_fats = fs->win[BPB_NumFATs];					/* Number of FAT copies */ | ||||
| 	fatsize *= fs->n_fats;								/* (Number of sectors in FAT area) */ | ||||
| 	fs->fatbase = basesect += LD_WORD(&fs->win[BPB_RsvdSecCnt]);	/* FAT start sector (lba) */ | ||||
| 	basesect += fatsize;								/* (Next sector of FAT area (lba)) */ | ||||
| 	fs->fatbase = bootsect + LD_WORD(&fs->win[BPB_RsvdSecCnt]);	/* FAT start sector (lba) */ | ||||
| 	fs->sects_clust = fs->win[BPB_SecPerClus];			/* Number of sectors per cluster */ | ||||
| 	fs->n_rootdir = LD_WORD(&fs->win[BPB_RootEntCnt]);	/* Nmuber of root directory entries */ | ||||
| 	totalsect = LD_WORD(&fs->win[BPB_TotSec16]);		/* Number of sectors on the file system */ | ||||
| @ -671,7 +704,7 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 	fmt = FS_FAT12;										/* Determine the FAT sub type */ | ||||
| 	if (maxclust > 0xFF7) fmt = FS_FAT16; | ||||
| 	if (maxclust > 0xFFF7) | ||||
| #if _FAT32 == 0 | ||||
| #if !_FAT32 | ||||
| 		return FR_NO_FILESYSTEM; | ||||
| #else | ||||
| 		fmt = FS_FAT32; | ||||
| @ -679,12 +712,27 @@ FRESULT auto_mount (		/* FR_OK(0): successful, !=0: any error occured */ | ||||
| 		fs->dirbase = LD_DWORD(&fs->win[BPB_RootClus]);	/* Root directory start cluster */ | ||||
| 	else | ||||
| #endif | ||||
| 		fs->dirbase = basesect;							/* Root directory start sector (lba) */ | ||||
| 	fs->database = basesect + fs->n_rootdir / 16;		/* Data start sector (lba) */ | ||||
| 	fs->fs_type = fmt; | ||||
| 		fs->dirbase = fs->fatbase + fatsize;			/* Root directory start sector (lba) */ | ||||
| 	fs->database = fs->fatbase + fatsize + fs->n_rootdir / 16;	/* Data start sector (lba) */ | ||||
| 	fs->fs_type = fmt;									/* FAT sub-type */ | ||||
| 
 | ||||
| #if !_FS_READONLY | ||||
| 	fs->free_clust = (CLUST)0xFFFFFFFF; | ||||
| #if _USE_FSINFO | ||||
| 	/* Load fsinfo sector if needed */ | ||||
| 	if (fmt == FS_FAT32) { | ||||
| 		fs->fsi_sector = bootsect + LD_WORD(&fs->win[BPB_FSInfo]); | ||||
| 		if (disk_read(0, fs->win, fs->fsi_sector, 1) == RES_OK && | ||||
| 			LD_WORD(&fs->win[BS_55AA]) == 0xAA55 && | ||||
| 			LD_DWORD(&fs->win[FSI_LeadSig]) == 0x41615252 && | ||||
| 			LD_DWORD(&fs->win[FSI_StrucSig]) == 0x61417272) { | ||||
| 			fs->last_clust = LD_DWORD(&fs->win[FSI_Nxt_Free]); | ||||
| 			fs->free_clust = LD_DWORD(&fs->win[FSI_Free_Count]); | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| #endif | ||||
| 	fs->id = ++fsid;									/* File system mount ID */ | ||||
| 
 | ||||
| 	return FR_OK; | ||||
| } | ||||
| 
 | ||||
| @ -760,7 +808,8 @@ FRESULT f_open ( | ||||
| 	FATFS *fs = FatFs; | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| 	fp->fs = NULL; | ||||
| #if !_FS_READONLY | ||||
| 	mode &= (FA_READ|FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW); | ||||
| 	res = auto_mount(&path, (BYTE)(mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW))); | ||||
| #else | ||||
| @ -772,7 +821,7 @@ FRESULT f_open ( | ||||
| 	/* Trace the file path */ | ||||
| 	res = trace_path(&dirobj, fn, path, &dir);	/* Trace the file path */ | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	/* Create or Open a File */ | ||||
| 	if (mode & (FA_CREATE_ALWAYS|FA_OPEN_ALWAYS|FA_CREATE_NEW)) { | ||||
| 		CLUST rs; | ||||
| @ -791,7 +840,7 @@ FRESULT f_open ( | ||||
| 			if (dir == NULL || (dir[DIR_Attr] & (AM_RDO|AM_DIR)))	/* Cannot overwrite (R/O or DIR) */ | ||||
| 				return FR_DENIED; | ||||
| 			if (mode & FA_CREATE_ALWAYS) {		/* Resize it to zero */ | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 				rs = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]); | ||||
| 				ST_WORD(&dir[DIR_FstClusHI], 0); | ||||
| #else | ||||
| @ -816,11 +865,11 @@ FRESULT f_open ( | ||||
| 	} | ||||
| 	/* Open a File */ | ||||
| 	else { | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 		if (res != FR_OK) return res;		/* Trace failed */ | ||||
| 		if (dir == NULL || (dir[DIR_Attr] & AM_DIR))	/* It is a directory */ | ||||
| 			return FR_NO_FILE; | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 		if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ | ||||
| 			return FR_DENIED; | ||||
| 	} | ||||
| @ -829,8 +878,12 @@ FRESULT f_open ( | ||||
| 	fp->dir_ptr = dir; | ||||
| #endif | ||||
| 	fp->flag = mode;							/* File access mode */ | ||||
| 	fp->org_clust =	LD_WORD(&dir[DIR_FstClusLO]);	/* File start cluster */ | ||||
| 	fp->fsize = LD_DWORD(&dir[DIR_FileSize]);		/* File size */ | ||||
| 	fp->org_clust =								/* File start cluster */ | ||||
| #if _FAT32 | ||||
| 		((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | | ||||
| #endif | ||||
| 		LD_WORD(&dir[DIR_FstClusLO]); | ||||
| 	fp->fsize = LD_DWORD(&dir[DIR_FileSize]);	/* File size */ | ||||
| 	fp->fptr = 0;								/* File ptr */ | ||||
| 	fp->sect_clust = 1;							/* Sector counter */ | ||||
| 	fp->fs = fs; fp->id = fs->id;				/* Owner file system object of the file */ | ||||
| @ -909,7 +962,7 @@ fr_error:	/* Abort this function due to an unrecoverable error */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| /* Write File                                                            */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| @ -1015,7 +1068,7 @@ FRESULT f_sync ( | ||||
| 			dir[DIR_Attr] |= AM_ARC;						/* Set archive bit */ | ||||
| 			ST_DWORD(&dir[DIR_FileSize], fp->fsize);		/* Update file size */ | ||||
| 			ST_WORD(&dir[DIR_FstClusLO], fp->org_clust);	/* Update start cluster */ | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 			ST_WORD(&dir[DIR_FstClusHI], fp->org_clust >> 16); | ||||
| #endif | ||||
| 			tim = get_fattime();					/* Updated time */ | ||||
| @ -1027,7 +1080,7 @@ FRESULT f_sync ( | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -1043,7 +1096,7 @@ FRESULT f_close ( | ||||
| 	FRESULT res; | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	res = f_sync(fp); | ||||
| #else | ||||
| 	res = validate(fp->fs, fp->id); | ||||
| @ -1078,7 +1131,7 @@ FRESULT f_lseek ( | ||||
| 	if (res) return res; | ||||
| 
 | ||||
| 	if (fp->flag & FA__ERROR) return FR_RW_ERROR; | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	if (ofs > fp->fsize && !(fp->flag & FA_WRITE)) | ||||
| #else | ||||
| 	if (ofs > fp->fsize) | ||||
| @ -1089,38 +1142,38 @@ FRESULT f_lseek ( | ||||
| 	/* Move file R/W pointer if needed */ | ||||
| 	if (ofs) { | ||||
| 		clust = fp->org_clust;	/* Get start cluster */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 		if (!clust) {			/* If the file does not have a cluster chain, create new cluster chain */ | ||||
| 			clust = create_chain(0); | ||||
| 			if (clust == 1) goto fk_error; | ||||
| 			fp->org_clust = fp->curr_clust = clust; | ||||
| 			fp->org_clust = clust; | ||||
| 		} | ||||
| #endif | ||||
| 		if (clust) {			/* If the file has a cluster chain, it can be followed */ | ||||
| 			csize = (DWORD)fs->sects_clust * 512;		/* Cluster size in unit of byte */ | ||||
| 			while (ofs > csize) {						/* Skip leading clusters */ | ||||
| #if _FS_READONLY == 0 | ||||
| 				if (fp->flag & FA_WRITE)					/* Check if in write mode or not */ | ||||
| 					clust = create_chain(clust);			/* Force streached if in write mode */ | ||||
| 			for (;;) {									/* Loop to skip leading clusters */ | ||||
| 				fp->curr_clust = clust;					/* Update current cluster */ | ||||
| 				if (ofs <= csize) break; | ||||
| #if !_FS_READONLY | ||||
| 				if (fp->flag & FA_WRITE)				/* Check if in write mode or not */ | ||||
| 					clust = create_chain(clust);		/* Force streached if in write mode */ | ||||
| 				else | ||||
| #endif | ||||
| 					clust = get_cluster(clust);				/* Only follow cluster chain if not in write mode */ | ||||
| 				if (clust == 0) {							/* Stop if could not follow the cluster chain */ | ||||
| 					ofs = csize; | ||||
| 					break; | ||||
| 					clust = get_cluster(clust);			/* Only follow cluster chain if not in write mode */ | ||||
| 				if (clust == 0) {						/* Stop if could not follow the cluster chain */ | ||||
| 					ofs = csize; break; | ||||
| 				} | ||||
| 				if (clust == 1 || clust >= fs->max_clust) goto fk_error; /* Abort when any error occured */ | ||||
| 				fp->curr_clust = clust;						/* Update current cluster and R/W pointer */ | ||||
| 				fp->fptr += csize; | ||||
| 				if (clust == 1 || clust >= fs->max_clust) goto fk_error; | ||||
| 				fp->fptr += csize;						/* Update R/W pointer */ | ||||
| 				ofs -= csize; | ||||
| 			} | ||||
| 			csect = (BYTE)((ofs - 1) / 512);			/* Sector offset in the cluster */ | ||||
| 			fp->curr_sect = clust2sect(clust) + csect;	/* Get current cluster */ | ||||
| 			fp->curr_sect = clust2sect(clust) + csect;	/* Current sector */ | ||||
| 			fp->sect_clust = fs->sects_clust - csect;	/* Left sector counter in the cluster */ | ||||
| 			fp->fptr += ofs;							/* Update file R/W pointer */ | ||||
| 		} | ||||
| 	} | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	if ((fp->flag & FA_WRITE) && fp->fptr > fp->fsize) {	/* Set updated flag if in write mode */ | ||||
| 		fp->fsize = fp->fptr; | ||||
| 		fp->flag |= FA__WRITTEN; | ||||
| @ -1160,11 +1213,11 @@ FRESULT f_opendir ( | ||||
| 	if (res == FR_OK) {							/* Trace completed */ | ||||
| 		if (dir != NULL) {						/* It is not the root dir */ | ||||
| 			if (dir[DIR_Attr] & AM_DIR) {		/* The entry is a directory */ | ||||
| #if _FAT32 != 0 | ||||
| 				dirobj->clust = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]); | ||||
| #else | ||||
| 				dirobj->clust = LD_WORD(&dir[DIR_FstClusLO]); | ||||
| 	 			dirobj->clust = | ||||
| #if _FAT32 | ||||
| 					((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | | ||||
| #endif | ||||
| 					LD_WORD(&dir[DIR_FstClusLO]); | ||||
| 				dirobj->sect = clust2sect(dirobj->clust); | ||||
| 				dirobj->index = 2; | ||||
| 			} else {						/* The entry is not a directory */ | ||||
| @ -1248,7 +1301,7 @@ FRESULT f_stat ( | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| /* Get Number of Free Clusters                                           */ | ||||
| /*-----------------------------------------------------------------------*/ | ||||
| @ -1271,6 +1324,12 @@ FRESULT f_getfree ( | ||||
| 	if (res != FR_OK) return res; | ||||
| 	*fatfs = fs = FatFs; | ||||
| 
 | ||||
| 	/* If number of free cluster is valid, return it without cluster scan. */ | ||||
| 	if (fs->free_clust <= fs->max_clust - 2) { | ||||
| 		*nclust = fs->free_clust; | ||||
| 		return FR_OK; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Count number of free clusters */ | ||||
| 	fat = fs->fs_type; | ||||
| 	n = 0; | ||||
| @ -1288,7 +1347,7 @@ FRESULT f_getfree ( | ||||
| 				if (!move_window(sect++)) return FR_RW_ERROR; | ||||
| 				p = fs->win; | ||||
| 			} | ||||
| 			if (_FAT32 == 0 || fat == FS_FAT16) { | ||||
| 			if (!_FAT32 || fat == FS_FAT16) { | ||||
| 				if (LD_WORD(p) == 0) n++; | ||||
| 				p += 2; f += 1; | ||||
| 			} else { | ||||
| @ -1297,6 +1356,10 @@ FRESULT f_getfree ( | ||||
| 			} | ||||
| 		} while (--clust); | ||||
| 	} | ||||
| 	fs->free_clust = n; | ||||
| #if _USE_FSINFO | ||||
| 	if (fat == FS_FAT32) fs->fsi_flag = 1; | ||||
| #endif | ||||
| 
 | ||||
| 	*nclust = n; | ||||
| 	return FR_OK; | ||||
| @ -1330,11 +1393,11 @@ FRESULT f_unlink ( | ||||
| 	if (dir == NULL) return FR_INVALID_NAME;	/* It is the root directory */ | ||||
| 	if (dir[DIR_Attr] & AM_RDO) return FR_DENIED;	/* It is a R/O object */ | ||||
| 	dsect = fs->winsect; | ||||
| #if _FAT32 != 0 | ||||
| 	dclust = ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]); | ||||
| #else | ||||
| 	dclust = LD_WORD(&dir[DIR_FstClusLO]); | ||||
| 	dclust = | ||||
| #if _FAT32 | ||||
| 		((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | | ||||
| #endif | ||||
| 		LD_WORD(&dir[DIR_FstClusLO]); | ||||
| 	if (dir[DIR_Attr] & AM_DIR) {				/* It is a sub-directory */ | ||||
| 		dirobj.clust = dclust;					/* Check if the sub-dir is empty or not */ | ||||
| 		dirobj.sect = clust2sect(dclust); | ||||
| @ -1367,7 +1430,7 @@ FRESULT f_mkdir ( | ||||
| 	const char *path		/* Pointer to the directory path */ | ||||
| ) | ||||
| { | ||||
| 	BYTE *dir, *sec, n; | ||||
| 	BYTE *dir, *fw, n; | ||||
| 	char fn[8+3+1]; | ||||
| 	DWORD sect, dsect, tim; | ||||
| 	CLUST dclust, pclust; | ||||
| @ -1390,40 +1453,39 @@ FRESULT f_mkdir ( | ||||
| 	if (dclust == 1) return FR_RW_ERROR; | ||||
| 	dsect = clust2sect(dclust); | ||||
| 	if (!dsect) return FR_DENIED; | ||||
| 	if (!move_window(0)) return FR_RW_ERROR; | ||||
| 	if (!move_window(dsect)) return FR_RW_ERROR; | ||||
| 
 | ||||
| 	sec = fs->win; | ||||
| 	memset(sec, 0, 512);						/* Initialize the directory table */ | ||||
| 	for (n = fs->sects_clust - 1; n; n--) { | ||||
| 		if (disk_write(0, sec, dsect+n, 1) != RES_OK) | ||||
| 	fw = fs->win; | ||||
| 	memset(fw, 0, 512);							/* Clear the directory table */ | ||||
| 	for (n = 1; n < fs->sects_clust; n++) { | ||||
| 		if (disk_write(0, fw, ++dsect, 1) != RES_OK) | ||||
| 			return FR_RW_ERROR; | ||||
| 	} | ||||
| 
 | ||||
| 	fs->winsect = dsect;						/* Create "." ".." directories */ | ||||
| 	memset(&sec[DIR_Name], ' ', 8+3);			/* "." entry */ | ||||
| 	sec[DIR_Name] = '.'; | ||||
| 	sec[DIR_Attr] = AM_DIR; | ||||
| 	memset(&fw[DIR_Name], ' ', 8+3);			/* Create "." entry */ | ||||
| 	fw[DIR_Name] = '.'; | ||||
| 	fw[DIR_Attr] = AM_DIR; | ||||
| 	tim = get_fattime(); | ||||
| 	ST_DWORD(&sec[DIR_WrtTime], tim); | ||||
| 	memcpy(&sec[32], &sec[0], 32); sec[33] = '.'; /* ".." entry */ | ||||
| 	ST_DWORD(&fw[DIR_WrtTime], tim); | ||||
| 	memcpy(&fw[32], &fw[0], 32); fw[33] = '.';	/* Create ".." entry */ | ||||
| 	pclust = dirobj.sclust; | ||||
| 	ST_WORD(&sec[   DIR_FstClusLO], dclust); | ||||
| 	ST_WORD(&sec[32+DIR_FstClusLO], pclust); | ||||
| #if _FAT32 != 0 | ||||
| 	ST_WORD(&sec[  +DIR_FstClusHI], dclust >> 16); | ||||
| #if _FAT32 | ||||
| 	ST_WORD(&fw[   DIR_FstClusHI], dclust >> 16); | ||||
| 	if (fs->fs_type == FS_FAT32 && pclust == fs->dirbase) pclust = 0; | ||||
| 	ST_WORD(&sec[32+DIR_FstClusHI], pclust >> 16); | ||||
| 	ST_WORD(&fw[32+DIR_FstClusHI], pclust >> 16); | ||||
| #endif | ||||
| 	ST_WORD(&fw[   DIR_FstClusLO], dclust); | ||||
| 	ST_WORD(&fw[32+DIR_FstClusLO], pclust); | ||||
| 	fs->winflag = 1; | ||||
| 	if (!move_window(sect)) return FR_RW_ERROR; | ||||
| 
 | ||||
| 	memset(&dir[0], 0, 32);						/* Initialize the new entry */ | ||||
| 	if (!move_window(sect)) return FR_RW_ERROR; | ||||
| 	memset(&dir[0], 0, 32);						/* Clean-up the new entry */ | ||||
| 	memcpy(&dir[DIR_Name], fn, 8+3);			/* Name */ | ||||
| 	dir[DIR_NTres] = fn[11]; | ||||
| 	dir[DIR_Attr] = AM_DIR;						/* Attribute */ | ||||
| 	ST_DWORD(&dir[DIR_WrtTime], tim);			/* Crated time */ | ||||
| 	ST_WORD(&dir[DIR_FstClusLO], dclust);		/* Table start cluster */ | ||||
| #if _FAT32 != 0 | ||||
| #if _FAT32 | ||||
| 	ST_WORD(&dir[DIR_FstClusHI], dclust >> 16); | ||||
| #endif | ||||
| 
 | ||||
| @ -1506,12 +1568,12 @@ FRESULT f_rename ( | ||||
| 	fs->winflag = 1; | ||||
| 
 | ||||
| 	if (!move_window(sect_old)) return FR_RW_ERROR;	/* Remove old entry */ | ||||
| 	*dir_old = 0xE5; | ||||
| 	dir_old[DIR_Name] = 0xE5; | ||||
| 
 | ||||
| 	return sync(); | ||||
| } | ||||
| 
 | ||||
| #endif /* _FS_READONLY == 0 */ | ||||
| #endif /* !_FS_READONLY */ | ||||
| #endif /* _FS_MINIMIZE == 0 */ | ||||
| #endif /* _FS_MINIMIZE <= 1 */ | ||||
| #endif /* _FS_MINIMIZE <= 2 */ | ||||
|  | ||||
							
								
								
									
										36
									
								
								src/tff.h
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/tff.h
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| /*--------------------------------------------------------------------------/
 | ||||
| /  Tiny-FatFs - FAT file system module include file  R0.04a   (C)ChaN, 2007 | ||||
| /  Tiny-FatFs - FAT file system module include file  R0.04b   (C)ChaN, 2007 | ||||
| /---------------------------------------------------------------------------/ | ||||
| / FatFs module is an experimenal project to implement FAT file system to | ||||
| / cheap microcontrollers. This is a free software and is opened for education, | ||||
| @ -37,21 +37,30 @@ | ||||
| /  3: f_lseek is removed in addition to level 2. */ | ||||
| 
 | ||||
| #define _FAT32	0 | ||||
| /* To add FAT32 support, set _FAT32 to 1. */ | ||||
| /* To enable FAT32 support in addition of FAT12/16, set _FAT32 to 1. */ | ||||
| 
 | ||||
| #define _USE_FSINFO	0 | ||||
| /* To enable FSInfo support on FAT32 volume, set _USE_FSINFO to 1. */ | ||||
| 
 | ||||
| #define	_USE_SJIS	1 | ||||
| /* When _USE_SJIS is set to 1, Shift-JIS code transparency is enabled, otherwise
 | ||||
| /  only US-ASCII(7bit) code can be accepted as file/directory name. */ | ||||
| 
 | ||||
| #define	_USE_NTFLAG	1 | ||||
| /* When _USE_NTFLAG is set to 1, upper/lower case of the file name is preserved.
 | ||||
| /  Note that the files are always accessed in case insensitive. */ | ||||
| 
 | ||||
| 
 | ||||
| #include "integer.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Type definition for cluster number */ | ||||
| #if _FAT32 == 0 | ||||
| typedef WORD	CLUST; | ||||
| #else | ||||
| #if _FAT32 | ||||
| typedef DWORD	CLUST; | ||||
| #else | ||||
| typedef WORD	CLUST; | ||||
| #undef _USE_FSINFO | ||||
| #define _USE_FSINFO	0 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| @ -65,7 +74,15 @@ typedef struct _FATFS { | ||||
| 	DWORD	database;		/* Data start sector */ | ||||
| 	CLUST	sects_fat;		/* Sectors per fat */ | ||||
| 	CLUST	max_clust;		/* Maximum cluster# + 1 */ | ||||
| #if !_FS_READONLY | ||||
| 	CLUST	last_clust;		/* Last allocated cluster */ | ||||
| 	CLUST	free_clust;		/* Number of free clusters */ | ||||
| #if _USE_FSINFO | ||||
| 	DWORD	fsi_sector;		/* fsinfo sector */ | ||||
| 	BYTE	fsi_flag;		/* fsinfo dirty flag (1:must be written back) */ | ||||
| 	BYTE	pad1; | ||||
| #endif | ||||
| #endif | ||||
| 	BYTE	fs_type;		/* FAT sub type */ | ||||
| 	BYTE	sects_clust;	/* Sectors per cluster */ | ||||
| 	BYTE	n_fats;			/* Number of FAT copies */ | ||||
| @ -96,7 +113,7 @@ typedef struct _FIL { | ||||
| 	CLUST	org_clust;		/* File start cluster */ | ||||
| 	CLUST	curr_clust;		/* Current cluster */ | ||||
| 	DWORD	curr_sect;		/* Current sector */ | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| 	DWORD	dir_sect;		/* Sector containing the directory entry */ | ||||
| 	BYTE*	dir_ptr;		/* Ponter to the directory entry in the window */ | ||||
| #endif | ||||
| @ -164,7 +181,7 @@ DWORD get_fattime (void);	/* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16 | ||||
| 
 | ||||
| #define	FA_READ				0x01 | ||||
| #define	FA_OPEN_EXISTING	0x00 | ||||
| #if _FS_READONLY == 0 | ||||
| #if !_FS_READONLY | ||||
| #define	FA_WRITE			0x02 | ||||
| #define	FA_CREATE_NEW		0x04 | ||||
| #define	FA_CREATE_ALWAYS	0x08 | ||||
| @ -229,6 +246,11 @@ DWORD get_fattime (void);	/* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16 | ||||
| #define BS_VolLab32			71 | ||||
| #define BS_FilSysType32		82 | ||||
| 
 | ||||
| #define	FSI_LeadSig			0 | ||||
| #define	FSI_StrucSig		484 | ||||
| #define	FSI_Free_Count		488 | ||||
| #define	FSI_Nxt_Free		492 | ||||
| 
 | ||||
| #define MBR_Table			446 | ||||
| 
 | ||||
| #define	DIR_Name			0 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user