diff --git a/doc/00index_e.html b/doc/00index_e.html index 7eb4cd0..56f6405 100644 --- a/doc/00index_e.html +++ b/doc/00index_e.html @@ -4,6 +4,8 @@ + + ELM - FAT File System Module @@ -15,7 +17,7 @@
layer -

FatFs is a generic FAT file system module for small embedded systems. The FatFs is written in compliance with ANSI C and completely separated from the disk I/O layer. Therefore it is independent of hardware architecture. It can be incorporated into low cost microcontrollers, such as AVR, 8051, PIC, ARM, Z80 and etc..., without any change. Petit FatFs module is also available here.

+

FatFs is a generic FAT file system module for small embedded systems. The FatFs is written in compliance with ANSI C and completely separated from the disk I/O layer. Therefore it is independent of hardware architecture. It can be incorporated into low cost microcontrollers, such as AVR, 8051, PIC, ARM, Z80, 68k and etc..., without any change. Petit FatFs module is also available here.

Features

@@ -48,7 +49,7 @@ FRESULT f_close (

Description

-

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.

+

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 but not recommended.

diff --git a/doc/en/dinit.html b/doc/en/dinit.html index c8c14d6..b0d57ce 100644 --- a/doc/en/dinit.html +++ b/doc/en/dinit.html @@ -4,6 +4,7 @@ + FatFs - disk_initialize @@ -15,7 +16,7 @@

The disk_initialize function initializes the disk drive.

 DSTATUS disk_initialize (
-  BYTE Drive           /* Physical drive number */
+  BYTE Drive           /* Physical drive number */
 );
 
@@ -37,7 +38,7 @@ DSTATUS disk_initialize (

Description

The disk_initialize function initializes a physical drive. When the function succeeded, STA_NOINIT flag in the return value is cleard.

-

This function is called from volume mount process in the FatFs module to manage the media change. Application program must not call this function while FatFs module is active, or FAT structure on the volume can be collapted. To re-initialize the file system, use f_mount function.

+

This function is called on volume mount process in the FatFs module to manage the media change. Application program should not call this function, or FAT structure on the volume can be collapted. To re-initialize the file system, use f_mount function.

Return

diff --git a/doc/en/dioctl.html b/doc/en/dioctl.html index 269aaa8..2a4c3aa 100644 --- a/doc/en/dioctl.html +++ b/doc/en/dioctl.html @@ -4,6 +4,7 @@ + FatFs - disk_ioctl @@ -15,9 +16,9 @@

The disk_ioctl function cntrols device specified features and miscellaneous functions other than disk read/write.

 DRESULT disk_ioctl (
-  BYTE Drive,      /* Drive number */
-  BYTE Command,    /* Control command code */
-  void* Buffer     /* Data transfer buffer */
+  BYTE Drive,      /* Drive number */
+  BYTE Command,    /* Control command code */
+  void* Buffer     /* Parameter and data buffer */
 );
 
@@ -56,9 +57,9 @@ DRESULT disk_ioctl ( - - - + + +
CommandDescription
CTRL_SYNCMake sure that the disk drive has finished pending write process. When the disk I/O module has a write back cache, flush the dirty sector immediately. This command is not required in read-only configuration.
GET_SECTOR_SIZEReturns sector size of the drive into the WORD variable pointed by Buffer. This command is not required in single sector size configuration, _MAX_SS is 512.
GET_SECTOR_COUNTReturns total sectors on the drive into the DWORD variable pointed by Buffer. This command is used in only f_mkfs function.
GET_BLOCK_SIZEReturns erase block size of the memory array in unit of sector into the DWORD variable pointed by Buffer. When the erase block size is unknown or magnetic disk device, return 1. This command is used in only f_mkfs function.
GET_SECTOR_SIZEReturns sector size of the drive into the WORD variable pointed by Buffer. This command is not required in single sector size configuration, _MAX_SS is 512.
GET_SECTOR_COUNTReturns total sectors on the drive into the DWORD variable pointed by Buffer. This command is used by only f_mkfs function to determine the volume size to be created.
GET_BLOCK_SIZEReturns erase block size of the flash memory in unit of sector into the DWORD variable pointed by Buffer. This command is used by only f_mkfs function and it attempts to align data area to the erase block boundary. The allowable value is 1 to 32768 in power of 2. Return 1 if the erase block size is unknown or disk devices.
diff --git a/doc/en/dread.html b/doc/en/dread.html index 873ae1b..fb288e4 100644 --- a/doc/en/dread.html +++ b/doc/en/dread.html @@ -4,6 +4,7 @@ + FatFs - disk_read @@ -15,10 +16,10 @@

The disk_read function reads sector(s) from the disk drive.

 DRESULT disk_read (
-  BYTE Drive,          /* Physical drive number */
-  BYTE* Buffer,        /* Pointer to the read data buffer */
-  DWORD SectorNumber,  /* Start sector number */
-  BYTE SectorCount     /* Number of sectros to read */
+  BYTE Drive,          /* Physical drive number */
+  BYTE* Buffer,        /* Pointer to the read data buffer */
+  DWORD SectorNumber,  /* Start sector number */
+  BYTE SectorCount     /* Number of sectros to read */
 );
 
diff --git a/doc/en/dstat.html b/doc/en/dstat.html index 14560a7..9c9c6e3 100644 --- a/doc/en/dstat.html +++ b/doc/en/dstat.html @@ -4,6 +4,7 @@ + FatFs - disk_status @@ -15,7 +16,7 @@

The disk_status function returns the current disk status.

 DSTATUS disk_status (
-  BYTE Drive     /* Physical drive number */
+  BYTE Drive     /* Physical drive number */
 );
 
@@ -31,7 +32,7 @@ DSTATUS disk_status (

Return Values

-

The disk status is returned in combination of following flags.

+

The disk status is returned in combination of following flags. FatFs refers only STA_NOINIT and STA_PROTECTED.

STA_NOINIT
Indicates that the disk drive has not been initialized. This flag is set on: system reset, disk removal and disk_initialize function failed, and cleared on: disk_initialize function succeeded.
diff --git a/doc/en/dwrite.html b/doc/en/dwrite.html index bb646ac..d229730 100644 --- a/doc/en/dwrite.html +++ b/doc/en/dwrite.html @@ -4,6 +4,7 @@ + FatFs - disk_write @@ -15,10 +16,10 @@

The disk_write writes sector(s) to the disk.

 DRESULT disk_write (
-  BYTE Drive,          /* Physical drive number */
-  const BYTE* Buffer,  /* Pointer to the write data (may be non aligned) */
-  DWORD SectorNumber,  /* Sector number to write */
-  BYTE SectorCount     /* Number of sectors to write */
+  BYTE Drive,          /* Physical drive number */
+  const BYTE* Buffer,  /* Pointer to the write data (may be non aligned) */
+  DWORD SectorNumber,  /* Sector number to write */
+  BYTE SectorCount     /* Number of sectors to write */
 );
 
diff --git a/doc/en/fattime.html b/doc/en/fattime.html index eee3ed5..26ce9fc 100644 --- a/doc/en/fattime.html +++ b/doc/en/fattime.html @@ -4,6 +4,7 @@ + FatFs - get_fattime diff --git a/doc/en/filename.html b/doc/en/filename.html index 6f6ecc0..2e699dc 100644 --- a/doc/en/filename.html +++ b/doc/en/filename.html @@ -4,6 +4,7 @@ + FatFs - Path Names @@ -13,10 +14,9 @@

Format of the path names

The path name format on the FatFs module is similer to the filename specs of DOS/Windos as follows:

-
- "[drive#:][/]directory/file"
-
-

The FatFs module supports long file name (LFN) and 8.3 format file name (SFN). The LFN can be used when LFN feature is enabled (_USE_LFN > 0). The differences between DOS/Windows are directory separator and logical drive number. The sub directories are separated with a / or \. The logical drive is specified in a numeral with a colon. When the drive number is omitted, it is assumed as default drive (0 or current drive). Leading/embedded spaces in the given path name are valid as a part of the name on LFN configuration but they are recognized as end of the path name on non-LFN configuration.

+

"[drive#:][/]directory/file"

+

The FatFs module supports long file name (LFN) and 8.3 format file name (SFN). The LFN can be used when LFN feature is enabled (_USE_LFN > 0). The differences between FatFs and DOS/Windows are directory separator and logical drive number. The sub directories are separated with a / or \. The logical drive is specified in a numeral with a colon. When the drive number is omitted, it is assumed as default drive (0 or current drive).

+

Nul character and control characters (\0 to \x1F) are recognized as end of the path name. Leading/embedded spaces in the path name are valid as a part of the name on LFN configuration but they are recognized as end of the path name on non-LFN configuration.

In default configuration (_FS_RPATH == 0), it does not have a concept of current directory like OS oriented file system. All objects on the volume are always specified in full path name that follows from the root directory. Dot directory names are not allowed. Heading separator is ignored and it can be exist or omitted. The default drive number is fixed to 0.

When relative path feature is enabled (_FS_RPATH == 1), specified path is followed from the root directory if a heading separator is exist. If not, the path is followed from the current directory set with f_chdir function. Dot names are also allowed for the directory name. The default drive number is the current drive number set with f_chdrive function.

@@ -31,14 +31,19 @@ - +
.Invalid nameThis directory
..Invalid nameParent directory of the current directory
dir1/..Invalid nameThe current directory
/..Invalid nameInvalid name (Cannot use dot names at the root directory)
/..Invalid nameThe root directory (sticks the top level)


Unicode API

-

The path names are input/output in either OEM code (SBCS/DBCS) or Unicode depends on the configuration options. The type of arguments that specifies the file names are defined as XCHAR which is an alias of char in default. The code set of the file name string is the OEM code set specifid by _CODE_PAGE. When _LFN_UNICODE is set to 1 under LFN configuration, the type of the XCHAR is switched to unsigned short (wide character) to support Unicode. In this case, the LFN feature is fully supported and the Unicode specific characters, such as 笨昶亂笨。笘ク笘ュ, can also be used for the path name.

+

The path names are input/output in either ANSI/OEM code (SBCS/DBCS) or Unicode depends on the configuration options. The type of arguments that specifies the file names are defined as TCHAR which is an alias of char in default. The code set of the file name string is the ANSI/OEM code set specifid by _CODE_PAGE. When _LFN_UNICODE is set to 1 under LFN configuration, the type of the TCHAR is switched to unsigned short (UCS-2 character) to support Unicode. In this case, the LFN feature is fully supported and the Unicode specific characters, such as 笨昶亂笨。笘ク笘ュ, can also be used for the path name. It also affects data types and encoding of the string I/O functions. To define literal strings, _T(s) and _TEXT(s) macro are available to select either ANSI/OEM or Unicode automatically. The code shown below is an example to define the literal strings.

+
+ f_open(fp, "filename.txt", FA_READ);      /* ANSI/OEM only */
+ f_open(fp, L"filename.txt", FA_READ);     /* Unicode only */
+ f_open(fp, _T("filename.txt"), FA_READ);  /* Changed automatically */
+


@@ -50,10 +55,10 @@ Example: Logical drive 0-2 are assigned to three pri-partitions on the physical Logical drive 3 is assigned to physical drive 1 (removable disk) const PARTITION Drives[] = { - {0, 0}, /* Logical drive 0 ==> Physical drive 0, 1st partition */ - {0, 1}, /* Logical drive 1 ==> Physical drive 0, 2nd partition */ - {0, 2}, /* Logical drive 2 ==> Physical drive 0, 3rd partition */ - {1, 0} /* Logical drive 3 ==> Physical drive 1 */ + {0, 0}, /* Logical drive 0 ==> Physical drive 0, 1st partition */ + {0, 1}, /* Logical drive 1 ==> Physical drive 0, 2nd partition */ + {0, 2}, /* Logical drive 2 ==> Physical drive 0, 3rd partition */ + {1, 0} /* Logical drive 3 ==> Physical drive 1 */ };

There are some considerations when use _MULTI_PARTITION configuration.

diff --git a/doc/en/forward.html b/doc/en/forward.html index fec6d6e..a66034a 100644 --- a/doc/en/forward.html +++ b/doc/en/forward.html @@ -4,6 +4,7 @@ + FatFs - f_forward @@ -15,10 +16,10 @@

The f_forward function reads the file data and forward it to the data streaming device.

 FRESULT f_forward (
-  FIL* FileObject,                 /* File object */
-  UINT (*Func)(const BYTE*,UINT),  /* Data streaming function */
-  UINT ByteToFwd,                  /* Number of bytes to forward */
-  UINT* ByteFwd                    /* Number of bytes forwarded */
+  FIL* FileObject,                 /* File object */
+  UINT (*Func)(const BYTE*,UINT),  /* Data streaming function */
+  UINT ByteToFwd,                  /* Number of bytes to forward */
+  UINT* ByteFwd                    /* Number of bytes forwarded */
 );
 
@@ -72,26 +73,26 @@ FRESULT f_forward (

Example (Audio playback)

-/*-----------------------------------------------------------------------*/
-/* Sample code of data transfer function to be called from f_forward     */
-/*-----------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
+/* Sample code of data transfer function to be called back from f_forward */
+/*------------------------------------------------------------------------*/
 
-UINT out_stream (   /* Returns number of bytes sent or stream status */
-    const BYTE *p,  /* Pointer to the data block to be sent */
-    UINT btf        /* >0: Transfer call (Number of bytes to be sent). 0: Sense call */
+UINT out_stream (   /* Returns number of bytes sent or stream status */
+    const BYTE *p,  /* Pointer to the data block to be sent */
+    UINT btf        /* >0: Transfer call (Number of bytes to be sent). 0: Sense call */
 )
 {
     UINT cnt = 0;
 
 
-    if (btf == 0) {     /* Sense call */
-        /* Return stream status (0: Busy, 1: Ready) */
-        /* When once it returned ready to sense call, it must accept a byte at least */
-        /* at subsequent transfer call, or f_forward will fail with FR_INT_ERROR. */
+    if (btf == 0) {     /* Sense call */
+        /* Return stream status (0: Busy, 1: Ready) */
+        /* When once it returned ready to sense call, it must accept a byte at least */
+        /* at subsequent transfer call, or f_forward will fail with FR_INT_ERROR. */
         if (FIFO_READY) cnt = 1;
     }
-    else {              /* Transfer call */
-        do {    /* Repeat while there is any data to be sent and the stream is ready */
+    else {              /* Transfer call */
+        do {    /* Repeat while there is any data to be sent and the stream is ready */
             FIFO_PORT = *p++;
             cnt++;
         } while (cnt < btf && FIFO_READY);
@@ -101,31 +102,33 @@ UINT out_stream (   /* Returns number of bytes sent or stream status */
 }
 
 
-/*-----------------------------------------------------------------------*/
-/* Sample code using f_forward function                                  */
-/*-----------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
+/* Sample code using f_forward function                                   */
+/*------------------------------------------------------------------------*/
 
 FRESULT play_file (
-    char *fn        /* Pointer to the audio file name to be played */
+    char *fn        /* Pointer to the audio file name to be played */
 )
 {
     FRESULT rc;
     FIL fil;
     UINT dmy;
 
-    /* Open the audio file in read only mode */
+    /* Open the audio file in read only mode */
     rc = f_open(&fil, fn, FA_READ);
+    if (rc) return rc;
 
-    /* Repeat until the file pointer reaches end of the file */
+    /* Repeat until the file pointer reaches end of the file */
     while (rc == FR_OK && fil.fptr < fil.fsize) {
 
-        /* any other processes... */
+        /* any other processes... */
 
-        /* Fill output stream periodicaly or on-demand */
+        /* Fill output stream periodicaly or on-demand */
         rc = f_forward(&fil, out_stream, 1000, &dmy);
     }
 
-    /* The read-only file object may be discarded without close */
+    /* Close the file and return */
+    f_close(&fil);
     return rc;
 }
 
diff --git a/doc/en/getfree.html b/doc/en/getfree.html index 53bafe3..80cb1ee 100644 --- a/doc/en/getfree.html +++ b/doc/en/getfree.html @@ -4,6 +4,7 @@ + FatFs - f_getfree @@ -15,9 +16,9 @@

The f_getfree function gets number of the free clusters.

 FRESULT f_getfree (
-  const XCHAR* Path,        /* Root directory of the drive */
-  DWORD* Clusters,          /* Pointer to the variable to store number of free clusters */
-  FATFS** FileSystemObject  /* Pointer to pointer to file system object */
+  const TCHAR* Path,        /* Logical drive number */
+  DWORD* Clusters,          /* Pointer to the variable to store number of free clusters */
+  FATFS** FileSystemObject  /* Pointer to pointer to file system object */
 );
 
@@ -26,7 +27,7 @@ FRESULT f_getfree (

Parameters

Path
-
Pinter to the null-terminated string that specifies the root directory of the logical drive.
+
Pinter to the null-terminated string that specifies the logical drive.
Clusters
Pointer to the DWORD variable to store number of free clusters.
FileSystemObject
@@ -51,7 +52,7 @@ FRESULT f_getfree (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT partition on the disk.
+
There is no valid FAT partition on the drive.
@@ -75,15 +76,15 @@ FRESULT f_getfree ( DWORD fre_clust, fre_sect, tot_sect; - /* Get drive information and free clusters */ - res = f_getfree("/", &fre_clust, &fs); + /* Get volume information and free clusters of drive 1 */ + res = f_getfree("1:", &fre_clust, &fs); if (res) die(res); - /* Get total sectors and free sectors */ + /* Get total sectors and free sectors */ tot_sect = (fs->max_clust - 2) * fs->csize; fre_sect = fre_clust * fs->csize; - /* Print free space in unit of KB (assuming 512B/sector) */ + /* Print free space in unit of KB (assuming 512 bytes/sector) */ printf("%lu KB total drive space.\n" "%lu KB available.\n", fre_sect / 2, tot_sect / 2); diff --git a/doc/en/gets.html b/doc/en/gets.html index d3f235c..7c89095 100644 --- a/doc/en/gets.html +++ b/doc/en/gets.html @@ -4,6 +4,7 @@ + FatFs - f_gets @@ -14,10 +15,10 @@

f_gets

The f_gets reads a string from the file.

-char* f_gets (
-  char* Str,        /* Read buffer */
-  int Size,         /* Size of the read buffer */
-  FIL* FileObject   /* File object */
+TCHAR* f_gets (
+  TCHAR* Str,       /* Read buffer */
+  int Size,         /* Size of the read buffer */
+  FIL* FileObject   /* File object */
 );
 
@@ -28,7 +29,7 @@ char* f_gets (
Str
Pointer to read buffer to store the read string.
Size
-
Size of the read buffer.
+
Size of the read buffer in unit of character.
FileObject
Pointer to the open file object structure.
@@ -43,7 +44,8 @@ char* f_gets (

Description

-

The f_gets() is a wrapper function of f_read(). The read operation continues until a '\n' is stored, reached end of file or buffer is filled with Size - 1 characters. The read string is terminated with a '\0'. When the file has reached end of the file or any error occured during read operation, f_gets() returns a NULL. The EOF and error status can be examined with f_eof() and f_error() macro.

+

The f_gets() is a wrapper function of f_read(). The read operation continues until a '\n' is stored, reached end of the file or the buffer is filled with Size - 1 characters. The read string is terminated with a '\0'. When no character to read or any error occured during read operation, f_gets() returns a null pointer. The end of file and error status can be examined with f_eof() and f_error() macros.

+

When the FatFs is configured to Unicode API (_LFN_UNICODE == 1), the file is read in UTF-8 encoding and stored it to the buffer in UCS-2. If not the case, the file will be read in one byte per character without any code conversion.

diff --git a/doc/en/lseek.html b/doc/en/lseek.html index 84882bc..cfe4039 100644 --- a/doc/en/lseek.html +++ b/doc/en/lseek.html @@ -4,6 +4,7 @@ + FatFs - f_lseek @@ -16,8 +17,8 @@
 FRESULT f_lseek (
-  FIL* FileObject,   /* Pointer to the file object structure */
-  DWORD Offset       /* File offset in unit of byte */
+  FIL* FileObject,   /* Pointer to the file object structure */
+  DWORD Offset       /* File offset in unit of byte */
 );
 
@@ -46,17 +47,20 @@ FRESULT f_lseek (
The disk drive cannot work due to no medium in the drive or any other reason.
FR_INVALID_OBJECT
The file object is invalid.
+
FR_NOT_ENOUGH_CORE
+
Insufficient size of link map table for the file.

Description

-

The f_lseek function moves the file R/W pointer of an open file. The offset can be specified in only origin from top of the file. When an offset above the file size is specified in write mode, the file size is increased and the data in the expanded area is undefined. This is suitable to create a large file quickly, for fast write operation. After the f_lseek function succeeded, member fptr in the file object should be checked in order to make sure the R/W pointer has been moved correctry. In case of fptr is not the expected value, either of followings has been occured.

+

The f_lseek function moves the file read/write pointer of an open file. The offset can be specified in only origin from top of the file. When an offset above the file size is specified in write mode, the file size is increased and the data in the expanded area is undefined. This is suitable to create a large file quickly, for fast write operation. After the f_lseek function succeeded, member fptr in the file object should be checked in order to make sure the read/write pointer has been moved correctry. In case of fptr is not the expected value, either of followings has been occured.

+

When _USE_FASTSEEK is set to 1 and cltbl member in the file object is not NULL, the fast seek feature is enabled. This feature enables fast backward/long seek operations without FAT access by cluster link information stored on the user defined table. The cluster link information must be created prior to do the fast seek. The required size of the table is (number of fragments + 1) * 2 items. For example, when the file is fragmented in 5, 12 items will be required to store the cluster link information. The file size cannot be expanded when the fast seek feature is enabled.

@@ -69,35 +73,49 @@ FRESULT f_lseek (

Example

-    /* Move to offset of 5000 from top of the file */
+    /* Move to offset of 5000 from top of the file */
     res = f_lseek(file, 5000);
 
-    /* Move to end of the file to append data */
+    /* Move to end of the file to append data */
     res = f_lseek(file, file->fsize);
 
-    /* Forward 3000 bytes */
+    /* Forward 3000 bytes */
     res = f_lseek(file, file->fptr + 3000);
 
-    /* Rewind 2000 bytes (take care on overflow) */
+    /* Rewind 2000 bytes (take care on overflow) */
     res = f_lseek(file, file->fptr - 2000);
 
-    /* Cluster pre-allocation (to prevent buffer overrun on streaming write) */
+    /* Cluster pre-allocation (to prevent buffer overrun on streaming write) */
 
-    res = f_open(file, recfile, FA_CREATE_NEW | FA_WRITE); /* Create a file */
+    res = f_open(file, recfile, FA_CREATE_NEW | FA_WRITE); /* Create a file */
 
-    res = f_lseek(file, PRE_SIZE);         /* Pre-allocate clusters */
-    if (res || file->fptr != PRE_SIZE) ... /* Check if the file size has been increased correctly */
+    res = f_lseek(file, PRE_SIZE);         /* Pre-allocate clusters */
+    if (res || file->fptr != PRE_SIZE) ... /* Check if the file size has been increased correctly */
 
-    res = f_lseek(file, DATA_START);       /* Record data stream without cluster allocation delay */
+    res = f_lseek(file, DATA_START);       /* Record data stream without cluster allocation delay */
     ...
 
-    res = f_truncate(file);                /* Truncate unused area */
-    res = f_lseek(file, 0);                /* Put file header */
+    res = f_truncate(file);                /* Truncate unused area */
+    res = f_lseek(file, 0);                /* Put file header */
     ...
 
     res = f_close(file);
 
+
+    /* Using fast seek feature */
+
+    DWORD lktbl[SZ_TBL];                   /* Link map table buffer */
+
+    res = f_lseek(&file, ofs1);            /* This is normal seek (file.cltbl == NULL on file open) */
+
+    file.cltbl = lktbl;                    /* Enable fast seek feature */
+    lktbl[0] = SZ_TBL;                     /* Set table size to the first item */
+    res = f_lseek(&file, CREATE_LINKMAP);  /* Create cluster link map table */
+    ...
+
+    res = f_lseek(&file, ofs2);            /* This is fast seek (file.cltbl != NULL) */
+
diff --git a/doc/en/mkdir.html b/doc/en/mkdir.html index 408846a..a5c1d1b 100644 --- a/doc/en/mkdir.html +++ b/doc/en/mkdir.html @@ -4,6 +4,7 @@ + FatFs - f_mkdir @@ -15,7 +16,7 @@

The f_mkdir function creates a new directory.

 FRESULT f_mkdir (
-  const XCHAR* DirName /* Pointer to the directory name */
+  const TCHAR* DirName /* Pointer to the directory name */
 );
 
@@ -55,7 +56,7 @@ FRESULT f_mkdir (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
diff --git a/doc/en/mkfs.html b/doc/en/mkfs.html index e8a71c8..9b87514 100644 --- a/doc/en/mkfs.html +++ b/doc/en/mkfs.html @@ -4,6 +4,7 @@ + FatFs - f_mkfs @@ -15,9 +16,9 @@

The f_mkfs fucntion creates a file system on the drive.

 FRESULT f_mkfs (
-  BYTE  Drive,            /* Logical drive number */
-  BYTE  PartitioningRule, /* Partitioning rule */
-  WORD  AllocSize         /* Size of the allocation unit */
+  BYTE  Drive,            /* Logical drive number */
+  BYTE  PartitioningRule, /* Partitioning rule */
+  UINT  AllocSize         /* Size of the allocation unit */
 );
 
@@ -28,9 +29,9 @@ FRESULT f_mkfs (
Drive
Logical drive number (0-9) to be formatted.
PartitioningRule
-
When 0 is given, a partition table is created into the first sector on the drive and then the file system is created on the partition. This is called FDISK format and used for harddisk and memory card. When 1 is given, the file system starts from the first sector without partition table. This is often called super floppy disk (SFD) format and used for floppy disk and removable disk.
+
When 0 is given, a partition table is created into the master boot record and a primary DOS partition is created and then an FAT volume is created on the partition. This is called FDISK format and used for harddisk and memory cards. When 1 is given, the FAT volume starts from the first sector on the drive without partition table. This is called SFD format and used for floppy disk and most optical disk.
AllocSize
-
Specifies allocation unit size in number of bytes per cluster. The value must be 0 or power of 2 in range of from 512 to 32768. When 0 is specified, the cluster size is determined depends on the volume size. FAT64 (64KB/cluster on FAT16) cannot be created by this function.
+
Force the allocation unit (cluter) size in unit of byte. The value must be power of 2 and between the sector size and 128 times sector size. When invalid value is specified, the cluster size is determined depends on the volume size.
@@ -62,8 +63,8 @@ FRESULT f_mkfs (

Description

-

The f_mkfs function creates a FAT file system on the drive. There are two partitioning rules, FDISK and SFD, for removable media. It can be selected with an argument. The FDISK format is recommended for the most case. This function currently does not support multiple partition, so that existing partitions on the physical dirve will be deleted and re-created a new partition occupies entire disk space.

-

The FAT sub-type, FAT12/FAT16/FAT32, is determined by number of clusters on the drive and nothing else, according to the FAT specification issued by Microsoft. Thus which FAT sub-type is selected, is depends on the volume size and the specified cluster size. The cluster size affects performance of the file system and large cluster increases the performance.

+

The f_mkfs function creates an FAT volume on the drive. There are two partitioning rules, FDISK and SFD, for removable media. The FDISK format is recommended for the most case. This function currently does not support multiple partition, so that existing partitions on the physical dirve will be deleted and re-created a new partition occupies entire disk space.

+

The FAT sub-type, FAT12/FAT16/FAT32, is determined by number of clusters on the volume and nothing else, according to the FAT specification issued by Microsoft. Thus which FAT sub-type is selected, is depends on the volume size and the specified cluster size. The cluster size affects performance of the file system and large cluster increases the performance.

diff --git a/doc/en/mount.html b/doc/en/mount.html index e82b8fb..ff59700 100644 --- a/doc/en/mount.html +++ b/doc/en/mount.html @@ -4,6 +4,7 @@ + FatFs - f_mount @@ -15,8 +16,8 @@

The f_mount fucntion registers/unregisters a work area to the FatFs module.

 FRESULT f_mount (
-  BYTE  Drive,              /* Logical drive number */
-  FATFS*  FileSystemObject  /* Pointer to the work area */
+  BYTE  Drive,              /* Logical drive number */
+  FATFS*  FileSystemObject  /* Pointer to the work area */
 );
 
diff --git a/doc/en/open.html b/doc/en/open.html index eda266d..8fedca8 100644 --- a/doc/en/open.html +++ b/doc/en/open.html @@ -4,6 +4,7 @@ + FatFs - f_open @@ -15,9 +16,9 @@

The f_open function creates a file object to be used to access the file.

 FRESULT f_open (
-  FIL* FileObject,       /* Pointer to the blank file object structure */
-  const XCHAR* FileName, /* Pointer to the file neme */
-  BYTE ModeFlags         /* Mode flags */
+  FIL* FileObject,       /* Pointer to the blank file object structure */
+  const TCHAR* FileName, /* Pointer to the file neme */
+  BYTE ModeFlags         /* Mode flags */
 );
 
@@ -36,7 +37,8 @@ FRESULT f_open ( FA_READSpecifies read access to the object. Data can be read from the file.
Combine with FA_WRITE for read-write access. FA_WRITESpecifies write access to the object. Data can be written to the file.
Combine with FA_READ for read-write access. FA_OPEN_EXISTINGOpens the file. The function fails if the file is not existing. (Default) -FA_OPEN_ALWAYSOpens the file, if it is existing. If not, a new file is created. +FA_OPEN_ALWAYSOpens the file if it is existing. If not, a new file is created.
+To append data to the file, use f_lseek function after file open in this method. FA_CREATE_NEWCreates a new file. The function fails if the file is already existing. FA_CREATE_ALWAYSCreates a new file. If the file is existing, it is truncated and overwritten. @@ -62,9 +64,9 @@ FRESULT f_open (
The file is already existing.
FR_DENIED
The required access was denied due to one of the following reasons: -
+
FR_NOT_READY
The disk drive cannot work due to no medium in the drive or any other reason.
FR_WRITE_PROTECTED
@@ -76,21 +78,23 @@ FRESULT f_open (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
+
FR_LOCKED
+
The function was rejected due to file shareing policy.

Description

-

A file object is created when the function succeeded. The file object is used for subsequent read/write functions to refer to the file. When close an open file object, use f_close function. If the modified file is not closed, the file may be collapsed.

+

A file object is created when the function succeeded. The file object is used for subsequent read/write functions to refer to the file. When close an open file object, use f_close function. If the modified file is not closed, the file data can be collapsed.

Before using any file function, a work area (file system object) must be given to the logical drive with f_mount function. All file functions can work after this procedure.

QuickInfo

-

Always available. The mode flags, FA_WRITE, FA_CREATE_ALWAYS, FA_CREATE_NEW, FA_OPEN_ALWAYS, are not available when _FS_READONLY == 1.

+

Always available. The mode flags, FA_WRITE, FA_CREATE_ALWAYS, FA_CREATE_NEW and FA_OPEN_ALWAYS, are not available when _FS_READONLY == 1.

@@ -99,38 +103,38 @@ FRESULT f_open (
 void main (void)
 {
-    FATFS fs[2];         /* Work area (file system object) for logical drives */
-    FIL fsrc, fdst;      /* file objects */
-    BYTE buffer[4096];   /* file copy buffer */
-    FRESULT res;         /* FatFs function common result code */
-    UINT br, bw;         /* File R/W count */
+    FATFS fs[2];         /* Work area (file system object) for logical drives */
+    FIL fsrc, fdst;      /* file objects */
+    BYTE buffer[4096];   /* file copy buffer */
+    FRESULT res;         /* FatFs function common result code */
+    UINT br, bw;         /* File read/write count */
 
 
-    /* Register work area for logical drives */
+    /* Register work area for logical drives */
     f_mount(0, &fs[0]);
     f_mount(1, &fs[1]);
 
-    /* Open source file on the drive 1 */
+    /* Open source file on the drive 1 */
     res = f_open(&fsrc, "1:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
     if (res) die(res);
 
-    /* Create destination file on the drive 0 */
+    /* Create destination file on the drive 0 */
     res = f_open(&fdst, "0:dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
     if (res) die(res);
 
-    /* Copy source to destination */
+    /* Copy source to destination */
     for (;;) {
-        res = f_read(&fsrc, buffer, sizeof(buffer), &br);
-        if (res || br == 0) break;   /* error or eof */
-        res = f_write(&fdst, buffer, br, &bw);
-        if (res || bw < br) break;   /* error or disk full */
+        res = f_read(&fsrc, buffer, sizeof(buffer), &br);    /* Read a chunk of src file */
+        if (res || br == 0) break; /* error or eof */
+        res = f_write(&fdst, buffer, br, &bw);               /* Write it to the dst file */
+        if (res || bw < br) break; /* error or disk full */
     }
 
-    /* Close open files */
+    /* Close open files */
     f_close(&fsrc);
     f_close(&fdst);
 
-    /* Unregister work area prior to discard it */
+    /* Unregister work area prior to discard it */
     f_mount(0, NULL);
     f_mount(1, NULL);
 }
diff --git a/doc/en/opendir.html b/doc/en/opendir.html
index 93cdf2d..8c1d095 100644
--- a/doc/en/opendir.html
+++ b/doc/en/opendir.html
@@ -4,6 +4,7 @@
 
 
 
+
 
 FatFs - f_opendir
 
@@ -15,8 +16,8 @@
 

The f_opendir function opens a directory.

 FRESULT f_opendir (
-  DIR* DirObject,       /* Pointer to the blank directory object structure */
-  const XCHAR* DirName  /* Pointer to the directory name */
+  DIR* DirObject,       /* Pointer to the blank directory object structure */
+  const TCHAR* DirName  /* Pointer to the directory name */
 );
 
@@ -52,7 +53,7 @@ FRESULT f_opendir (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
diff --git a/doc/en/printf.html b/doc/en/printf.html index bee2ef6..5f5322c 100644 --- a/doc/en/printf.html +++ b/doc/en/printf.html @@ -4,6 +4,7 @@ + FatFs - f_printf @@ -15,8 +16,8 @@

The f_printf function writes formatted string to the file.

 int f_printf (
-  FIL* FileObject,     /* File object */
-  const char* Foramt,  /* Format stirng */
+  FIL* FileObject,      /* File object */
+  const TCHAR* Foramt,  /* Format stirng */
   ...
 );
 
@@ -28,7 +29,7 @@ int f_printf (
FileObject
Pointer to the open file object structure.
Format
-
Pointer to the null-terminated format string.
+
Pointer to the null terminated format string.
...
Optional arguments.
@@ -38,7 +39,7 @@ int f_printf (

Return Values

-

When the function succeeded, number of characters written is returned. When the function failed due to disk full or any error, an EOF will be returned.

+

When the function succeeded, number of characters written is returned. When the function failed due to disk full or any error, an EOF (-1) will be returned.

@@ -46,8 +47,8 @@ int f_printf (

Description

The f_printf() is a wrapper function of f_putc() and f_puts(). The format control directive is a sub-set of standard library shown as follos:

@@ -56,18 +57,20 @@ int f_printf (

QuickInfo

Available when _FS_READONLY == 0 and _USE_STRFUNC is 1 or 2. When it is set to 2, '\n's contained in the output are converted to "\r\n".

+

When the FatFs is configured to Unicode API (_LFN_UNICODE == 1), the generated UCS-2 characters are written to the file in UTF-8 encoding. If not the case, the byte characters will be written directly.

Example

-    f_printf(&fil, "%6d", -200);         /* "  -200" */
-    f_printf(&fil, "%02u", 5);           /* "05" */
-    f_printf(&fil, "%ld", 12345678L);    /* "12345678" */
-    f_printf(&fil, "%08lX", 1194684UL);  /* "00123ABC" */
-    f_printf(&fil, "%s", "String");      /* "String" */
-    f_printf(&fil, "%c", 'a');           /* "a" */
+    f_printf(&fil, "%6d", -200);         /* "  -200" */
+    f_printf(&fil, "%02u", 5);           /* "05" */
+    f_printf(&fil, "%ld", 12345678L);    /* "12345678" */
+    f_printf(&fil, "%08lX", 1194684UL);  /* "00123ABC" */
+    f_printf(&fil, "%08b", 0x55);        /* "01010101" */
+    f_printf(&fil, "%s", "String");      /* "String" */
+    f_printf(&fil, "%c", 'a');           /* "a" */
 
diff --git a/doc/en/putc.html b/doc/en/putc.html index eac39be..00e89a0 100644 --- a/doc/en/putc.html +++ b/doc/en/putc.html @@ -4,6 +4,7 @@ + FatFs - f_putc @@ -15,8 +16,8 @@

The f_putc funciton puts a character to the file.

 int f_putc (
-  int Chr,          /* A character to put */
-  FIL* FileObject   /* File object */
+  TCHAR Chr,        /* A character to put */
+  FIL* FileObject   /* File object */
 );
 
@@ -34,7 +35,8 @@ int f_putc (

Return Values

-

When the character was written successfuly, the function returns the character. When the function failed due to disk full or any error, an EOF will be returned.

+

When the character was written successfuly, the function returns the character. When the function failed due to disk full or any error, an EOF (-1) will be returned.

+

When the FatFs is configured to Unicode API (_LFN_UNICODE == 1), the UCS-2 character is written to the file in UTF-8 encoding. If not the case, the byte will be written directly.

diff --git a/doc/en/puts.html b/doc/en/puts.html index 9061a9b..633024a 100644 --- a/doc/en/puts.html +++ b/doc/en/puts.html @@ -4,6 +4,7 @@ + FatFs - f_puts @@ -15,8 +16,8 @@

The f_puts function writes a string to the file.

 int f_puts (
-  const char* Str,  /* String */
-  FIL* FileObject   /* File object */
+  const TCHAR* Str,  /* String */
+  FIL* FileObject    /* File object */
 );
 
@@ -34,7 +35,8 @@ int f_puts (

Return Value

-

When the function succeeded, number of characters written that is not minus value is returned. When the function failed due to disk full or any error, an EOF will be returned.

+

When the function succeeded, number of characters written that is not minus value is returned. When the function failed due to disk full or any error, an EOF (-1) will be returned.

+

When the FatFs is configured to Unicode API (_LFN_UNICODE == 1), the UCS-2 string is written to the file in UTF-8 encoding. If not the case, the byte stream will be written directly.

diff --git a/doc/en/read.html b/doc/en/read.html index 9289103..ee4f7ef 100644 --- a/doc/en/read.html +++ b/doc/en/read.html @@ -4,6 +4,7 @@ + FatFs - f_read @@ -15,10 +16,10 @@

The f_read function reads data from a file.

 FRESULT f_read (
-  FIL* FileObject,    /* Pointer to the file object structure */
-  void* Buffer,       /* Pointer to the buffer to store read data */
-  UINT ByteToRead,    /* Number of bytes to read */
-  UINT* ByteRead      /* Pointer to the variable to return number of bytes read */
+  FIL* FileObject,    /* Pointer to the file object structure */
+  void* Buffer,       /* Pointer to the buffer to store read data */
+  UINT ByteToRead,    /* Number of bytes to read */
+  UINT* ByteRead      /* Pointer to the variable to return number of bytes read */
 );
 
@@ -59,7 +60,7 @@ FRESULT f_read (

Description

-

The file pointer of the file object increases in number of bytes read. After the function succeeded, *ByteRead should be checked to detect the end of file. In case of *ByteRead < ByteToRead, it means the R/W pointer reached end of the file during read operation.

+

The file pointer of the file object increases in number of bytes read. After the function succeeded, *ByteRead should be checked to detect the end of file. In case of *ByteRead < ByteToRead, it means the read/write pointer reached end of the file during read operation.

diff --git a/doc/en/readdir.html b/doc/en/readdir.html index a5b040c..957ed34 100644 --- a/doc/en/readdir.html +++ b/doc/en/readdir.html @@ -4,6 +4,7 @@ + FatFs - f_readdir @@ -15,8 +16,8 @@

The f_readdir function reads directory entries.

 FRESULT f_readdir (
-  DIR* DirObject,    /* Pointer to the open directory object */
-  FILINFO* FileInfo  /* Pointer to the file information structure */
+  DIR* DirObject,    /* Pointer to the open directory object */
+  FILINFO* FileInfo  /* Pointer to the file information structure */
 );
 
diff --git a/doc/en/rename.html b/doc/en/rename.html index 2ddf9c5..84bd8d0 100644 --- a/doc/en/rename.html +++ b/doc/en/rename.html @@ -4,6 +4,7 @@ + FatFs - f_rename @@ -15,8 +16,8 @@

Renames an object.

 FRESULT f_rename (
-  const XCHAR* OldName, /* Pointer to old object name */
-  const XCHAR* NewName  /* Pointer to new object name */
+  const TCHAR* OldName, /* Pointer to old object name */
+  const TCHAR* NewName  /* Pointer to new object name */
 );
 
@@ -60,7 +61,9 @@ FRESULT f_rename (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
+
FR_LOCKED
+
The function was rejected due to file shareing policy.
@@ -80,10 +83,10 @@ FRESULT f_rename (

Example

-    /* Rename an object */
+    /* Rename an object */
     f_rename("oldname.txt", "newname.txt");
 
-    /* Rename and move an object to other directory */
+    /* Rename and move an object to other directory */
     f_rename("oldname.txt", "dir1/newname.txt");
 
diff --git a/doc/en/sdir.html b/doc/en/sdir.html index d759eca..c5d78f8 100644 --- a/doc/en/sdir.html +++ b/doc/en/sdir.html @@ -4,6 +4,7 @@ + FatFs - DIR @@ -14,18 +15,18 @@

DIR

The DIR structure is used for the work area to read a directory by f_oepndir, f_readdir function. There is no member that can be changed by application.

-typedef struct _DIR_ {
-    FATFS*  fs;         /* Pointer to the owner file system object */
-    WORD    id;         /* Owner file system mount ID */
-    WORD    index;      /* Current read/write index number */
-    DWORD   sclust;     /* Table start cluster (0:Static table) */
-    DWORD   clust;      /* Current cluster */
-    DWORD   sect;       /* Current sector */
-    BYTE*   dir;        /* Pointer to the current SFN entry in the win[] */
-    BYTE*   fn;         /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+typedef struct {
+    FATFS*  fs;         /* Pointer to the owner file system object */
+    WORD    id;         /* Owner file system mount ID */
+    WORD    index;      /* Directory index number to be read/write next */
+    DWORD   sclust;     /* Table start cluster (0:Root dir) */
+    DWORD   clust;      /* Current cluster */
+    DWORD   sect;       /* Current sector */
+    BYTE*   dir;        /* Pointer to the current SFN entry in the win[] */
+    BYTE*   fn;         /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
 #if _USE_LFN
-    WCHAR*  lfn;        /* Pointer to the LFN working buffer */
-    WORD    lfn_idx;    /* Last matched LFN index (0xFFFF:No LFN) */
+    WCHAR*  lfn;        /* Pointer to the LFN working buffer */
+    WORD    lfn_idx;    /* Last matched LFN index (0xFFFF:No LFN) */
 #endif
 } DIR;
 
diff --git a/doc/en/sfatfs.html b/doc/en/sfatfs.html index 7512ec7..32aaa53 100644 --- a/doc/en/sfatfs.html +++ b/doc/en/sfatfs.html @@ -4,6 +4,7 @@ + FatFs - FATFS @@ -14,36 +15,36 @@

FATFS

The FATFS 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.

-typedef struct _FATFS_ {
-    BYTE    fs_type;    /* FAT sub type */
-    BYTE    drive;      /* Physical drive number */
-    BYTE    csize;      /* Number of sectors per cluster */
-    BYTE    n_fats;     /* Number of FAT copies */
-    BYTE    wflag;      /* win[] dirty flag (1:must be written back) */
-    BYTE    fsi_flag;   /* fsinfo dirty flag (1:must be written back) */
-    WORD    id;         /* File system mount ID */
-    WORD    n_rootdir;  /* Number of root directory entries (0 on FAT32) */
-#if _FS_REENTRANT
-    _SYNC_t sobj;       /* Identifier of sync object */
-#endif
+typedef struct {
+    BYTE    fs_type;      /* FAT sub-type (0:Not mounted) */
+    BYTE    drv;          /* Physical drive number */
+    BYTE    csize;        /* Sectors per cluster (1,2,4...128) */
+    BYTE    n_fats;       /* Number of FAT copies (1,2) */
+    BYTE    wflag;        /* win[] dirty flag */
+    BYTE    fsi_flag;     /* fsinfo dirty flag */
+    WORD    id;           /* File system mount ID */
+    WORD    n_rootdir;    /* Number of root directory entries (FAT12/16) */
 #if _MAX_SS != 512
-    WORD    s_size;     /* Sector size */
+    WORD    ssize;        /* Sector size (512,1024,2048,4096) */
+#endif
+#if _FS_REENTRANT
+    _SYNC_t sobj;         /* Identifier of sync object */
 #endif
 #if !_FS_READONLY
-    DWORD   last_clust; /* Last allocated cluster */
-    DWORD   free_clust; /* Number of free clusters */
-    DWORD   fsi_sector; /* fsinfo sector */
+    DWORD   last_clust;   /* Last allocated cluster */
+    DWORD   free_clust;   /* Number of free clusters */
+    DWORD   fsi_sector;   /* fsinfo sector (FAT32) */
 #endif
 #if _FS_RPATH
-    DWORD   cdir;       /* Current directory (0:root)*/
+    DWORD   cdir;         /* Current directory cluster (0:root) */
 #endif
-    DWORD   sects_fat;  /* Sectors per fat */
-    DWORD   max_clust;  /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
-    DWORD   fatbase;    /* FAT start sector */
-    DWORD   dirbase;    /* Root directory start sector (Cluster# on FAT32) */
-    DWORD   database;   /* Data start sector */
-    DWORD   winsect;    /* Current sector appearing in the win[] */
-    BYTE    win[_MAX_SS];/* Disk access window for Directory/FAT */
+    DWORD   n_fatent;     /* Number of FAT entries (= number of clusters + 2) */
+    DWORD   fsize;        /* Sectors per FAT */
+    DWORD   fatbase;      /* FAT area start sector */
+    DWORD   dirbase;      /* Root directory area start sector (FAT32: cluster#) */
+    DWORD   database;     /* Data area start sector */
+    DWORD   winsect;      /* Current sector appearing in the win[] */
+    BYTE    win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
 } FATFS;
 
diff --git a/doc/en/sfile.html b/doc/en/sfile.html index 386e615..693391e 100644 --- a/doc/en/sfile.html +++ b/doc/en/sfile.html @@ -4,6 +4,7 @@ + FatFs - FIL @@ -12,25 +13,31 @@

FIL

-

The FIL structure (file object) holds state of an open file. It is initialzed by f_open function and discarded by f_close function. There is no member that can be changed by the application program.

+

The FIL structure (file object) holds state of an open file. It is created by f_open function and discarded by f_close function. There is no member that can be changed by the application program except for cltbl. Note that a sector buffer is defined in this structure under non-tiny configuration so that the FIL structures should not be defined as auto variable.

-typedef struct _FIL_ {
-    FATFS*  fs;         /* Pointer to the owner file system object */
-    WORD    id;         /* Owner file system mount ID */
-    BYTE    flag;       /* File status flags */
-    BYTE    csect;      /* Sector address in the cluster */
-    DWORD   fptr;       /* File R/W pointer */
-    DWORD   fsize;      /* File size */
-    DWORD   org_clust;  /* File start cluster */
-    DWORD   curr_clust; /* Current cluster */
-    DWORD   dsect;      /* Current data sector */
+typedef struct {
+    FATFS*  fs;           /* Pointer to the owner file system object */
+    WORD    id;           /* Owner file system mount ID */
+    BYTE    flag;         /* File status flags */
+    BYTE    pad1;
+    DWORD   fptr;         /* File read/write pointer (Byte offset origin from top of the file) */
+    DWORD   fsize;        /* File size */
+    DWORD   org_clust;    /* File start cluster */
+    DWORD   curr_clust;   /* Current cluster */
+    DWORD   dsect;        /* Current data sector */
 #if !_FS_READONLY
-    DWORD   dir_sect;   /* Sector containing the directory entry */
-    BYTE*   dir_ptr;    /* Ponter to the directory entry in the window */
+    DWORD   dir_sect;     /* Sector containing the directory entry */
+    BYTE*   dir_ptr;      /* Ponter to the directory entry in the window */
+#endif
+#if _USE_FASTSEEK
+    DWORD*  cltbl;        /* Pointer to the cluster link map table */
+#endif
+#if _FS_SHARE
+    UINT    lockid;       /* File lock ID */
 #endif
 #if !_FS_TINY
-    BYTE    buf[_MAX_SS];/* File R/W buffer */
+    BYTE    buf[_MAX_SS]; /* Data read/write buffer */
 #endif
 } FIL;
 
diff --git a/doc/en/sfileinfo.html b/doc/en/sfileinfo.html index 42226b9..1d972e6 100644 --- a/doc/en/sfileinfo.html +++ b/doc/en/sfileinfo.html @@ -4,6 +4,7 @@ + FatFs - FILINFO @@ -14,15 +15,15 @@

FILINFO

The FILINFO structure holds a file information returned by f_stat and f_readdir function.

-typedef struct _FILINFO_ {
-    DWORD fsize;      /* File size */
-    WORD  fdate;      /* Last modified date */
-    WORD  ftime;      /* Last modified time */
-    BYTE  fattrib;    /* Attribute */
-    char  fname[13];  /* Short file name (8.3 format) */
+typedef struct {
+    DWORD fsize;      /* File size */
+    WORD  fdate;      /* Last modified date */
+    WORD  ftime;      /* Last modified time */
+    BYTE  fattrib;    /* Attribute */
+    TCHAR fname[13];  /* Short file name (8.3 format) */
 #if _USE_LFN
-    XCHAR* lfname;    /* Pointer to the LFN buffer */
-    int   lfsize;     /* Size of LFN buffer [characters] */
+    TCHAR* lfname;    /* Pointer to the LFN buffer */
+    int   lfsize;     /* Size of LFN buffer [characters] */
 #endif
 } FILINFO;
 
diff --git a/doc/en/stat.html b/doc/en/stat.html index 46a886b..0249fa2 100644 --- a/doc/en/stat.html +++ b/doc/en/stat.html @@ -4,6 +4,7 @@ + FatFs - f_stat @@ -15,8 +16,8 @@

The f_stat gets the file status.

 FRESULT f_stat (
-  const XCHAR* FileName,  /* Pointer to the file or directory name */
-  FILINFO* FileInfo       /* Pointer to the FILINFO structure */
+  const TCHAR* FileName,  /* Pointer to the file or directory name */
+  FILINFO* FileInfo       /* Pointer to the FILINFO structure */
 );
 
@@ -54,7 +55,7 @@ FRESULT f_stat (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
diff --git a/doc/en/sync.html b/doc/en/sync.html index a9a9efc..8de747d 100644 --- a/doc/en/sync.html +++ b/doc/en/sync.html @@ -4,6 +4,7 @@ + FatFs - f_sync @@ -15,7 +16,7 @@

The f_sync function flushes the cached information of a writing file.

 FRESULT f_sync (
-  FIL* FileObject     /* Pointer to the file object */
+  FIL* FileObject     /* Pointer to the file object */
 );
 
diff --git a/doc/en/truncate.html b/doc/en/truncate.html index 006fcaf..9e6e9a4 100644 --- a/doc/en/truncate.html +++ b/doc/en/truncate.html @@ -4,6 +4,7 @@ + FatFs - f_truncate @@ -15,7 +16,7 @@

The f_truncate function truncates the file size.

 FRESULT f_truncate (
-  FIL* FileObject     /* Pointer to the file object */
+  FIL* FileObject     /* Pointer to the file object */
 );
 
diff --git a/doc/en/unlink.html b/doc/en/unlink.html index ac81760..bc5fee5 100644 --- a/doc/en/unlink.html +++ b/doc/en/unlink.html @@ -4,6 +4,7 @@ + FatFs - f_unlink @@ -15,7 +16,7 @@

The f_unlink removes an object.

 FRESULT f_unlink (
-  const XCHAR* FileName  /* Pointer to the object name */
+  const TCHAR* FileName  /* Pointer to the object name */
 );
 
@@ -56,7 +57,9 @@ FRESULT f_unlink (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
+
FR_LOCKED
+
The function was rejected due to file shareing policy.
diff --git a/doc/en/utime.html b/doc/en/utime.html index 6fddefd..a01d837 100644 --- a/doc/en/utime.html +++ b/doc/en/utime.html @@ -4,6 +4,7 @@ + FatFs - f_utime @@ -15,8 +16,8 @@

The f_utime function changes the timestamp of a file or directory.

 FRESULT f_utime (
-  const XCHAR* FileName,   /* Pointer to the file or directory path */
-  const FILINFO* TimeDate  /* Time and data to be set */
+  const TCHAR* FileName,   /* Pointer to the file or directory path */
+  const FILINFO* TimeDate  /* Time and data to be set */
 );
 
@@ -56,7 +57,7 @@ FRESULT f_utime (
FR_NOT_ENABLED
The logical drive has no work area.
FR_NO_FILESYSTEM
-
There is no valid FAT volume on the disk.
+
There is no valid FAT volume on the drive.
@@ -67,6 +68,30 @@ FRESULT f_utime ( +
+

Example

+
+FRESULT set_timestamp (
+    char *obj,     /* Pointer to the file name */
+    int year,
+    int month,
+    int mday,
+    int hour,
+    int min,
+    int sec
+)
+{
+    FILINFO fno;
+
+    fno.fdate = (WORD)(((year - 1980) * 512U) | month * 32U | mday);
+    fno.ftime = (WORD)(hour * 2048U | min * 32U | sec / 2U);
+
+    return f_utime(obj, &fno);
+}
+
+
+ +

QuickInfo

Available when _FS_READONLY == 0 and _FS_MINIMIZE == 0.

diff --git a/doc/en/write.html b/doc/en/write.html index 46cde01..c90200e 100644 --- a/doc/en/write.html +++ b/doc/en/write.html @@ -4,6 +4,7 @@ + FatFs - f_write @@ -15,10 +16,10 @@

The f_write writes data to a file.

 FRESULT f_write (
-  FIL* FileObject,     /* Pointer to the file object structure */
-  const void* Buffer,  /* Pointer to the data to be written */
-  UINT ByteToWrite,    /* Number of bytes to write */
-  UINT* ByteWritten    /* Pointer to the variable to return number of bytes written */
+  FIL* FileObject,     /* Pointer to the file object structure */
+  const void* Buffer,  /* Pointer to the data to be written */
+  UINT ByteToWrite,    /* Number of bytes to write */
+  UINT* ByteWritten    /* Pointer to the variable to return number of bytes written */
 );
 
@@ -59,7 +60,7 @@ FRESULT f_write (

Description

-

The R/W pointer in the file object is increased in number of bytes written. After the function succeeded, *ByteWritten should be checked to detect the disk full. In case of *ByteWritten < ByteToWrite, it means the volume got full during the write operation.

+

The read/write pointer in the file object is increased in number of bytes written. After the function succeeded, *ByteWritten should be checked to detect the disk full. In case of *ByteWritten < ByteToWrite, it means the volume got full during the write operation. The function can take a time when the volume is full or close to full.

diff --git a/doc/ja/appnote.html b/doc/ja/appnote.html index 488744a..fc1f2d9 100644 --- a/doc/ja/appnote.html +++ b/doc/ja/appnote.html @@ -4,6 +4,7 @@ + FatFs繝「繧ク繝・繝シ繝ォ 繧「繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝弱シ繝 @@ -27,8 +28,8 @@ FatFs繝「繧ク繝・繝シ繝ォ縺ッANSI C貅匁侠縺ァ險倩ソー縺輔l縺ヲ縺繧九ョ縺ァ縲、NSI C貅匁侠

繝昴シ繝繧」繝ウ繧ー縺ョ縺励°縺

蠢隕√↑縺ョ縺ッ FatFs繝「繧ク繝・繝シ繝ォ縺ョ隕∵アゅ☆繧九ョ繧」繧ケ繧ッ髢「謨ー繧堤畑諢上☆繧九%縺ィ縺縺代〒縲√◎繧御サ・螟悶↓縺吶k縺薙→縺ッ縺ゅj縺セ縺帙s縲よ里縺ォ蜍穂ス懊@縺ヲ縺繧九ョ繧」繧ケ繧ッ髢「謨ー縺後≠繧九↑繧峨◎縺ョ API繧 FatFs縺ォ蜷医o縺帙k縺縺代〒貂医∩縺セ縺吶′縲∫┌縺蝣エ蜷医ッ縺サ縺九°繧臥ァサ讀阪☆繧九°縲∵怙蛻昴°繧画嶌縺上°縺吶k蠢隕√′縺ゅj縺セ縺吶ょョ夂セゥ縺輔l縺ヲ縺繧句ィ縺ヲ縺ョ髢「謨ー縺悟クク縺ォ蠢隕√↑繧上¢縺ァ縺ッ縺ゅj縺セ縺帙s縲ゆセ九∴縺ー縲√Μ繝シ繝峨サ繧ェ繝ウ繝ェ繝シ讒区舌〒縺ッ譖ク縺崎セシ縺ソ邉サ髢「謨ー縺ッ蠢隕√≠繧翫∪縺帙s縲よャ。縺ョ陦ィ縺ォ讒区舌が繝励す繝ァ繝ウ縺ィ隕∵アゅ&繧後k髢「謨ー縺ョ蟇セ蠢懊r遉コ縺励∪縺吶

- - + + @@ -37,6 +38,14 @@ FatFs繝「繧ク繝・繝シ繝ォ縺ッANSI C貅匁侠縺ァ險倩ソー縺輔l縺ヲ縺繧九ョ縺ァ縲、NSI C貅匁侠 + + + + + + + +
繝ヲ繝シ繧カ菴懈宣未謨ー蠢隕√→縺ェ繧区擅莉カ
disk_initialize蟶ク譎
繝ヲ繝シ繧カ菴懈宣未謨ー蠢隕√→縺ェ繧区擅莉カ蛯呵
disk_initialize蟶ク譎ffsample.zip (繧オ繝ウ繝励Ν)
縺昴ョ莉殆eb荳翫↓螟壽焚
disk_status蟶ク譎
disk_read蟶ク譎
disk_write_FS_READONLY == 0
disk_ioctl (GET_SECTOR_SIZE)_MAX_SS >= 1024
disk_ioctl (GET_BLOCK_SIZE)_USE_MKFS == 1
get_fattime_FS_READONLY == 0
ff_convert_USE_LFN >= 1option/cc*.c
ff_wtoupper_USE_LFN >= 1
ff_cre_syncobj_FS_REENTRANT == 1option/syscall.c (繧オ繝ウ繝励Ν)
ff_del_syncobj_FS_REENTRANT == 1
ff_req_grant_FS_REENTRANT == 1
ff_rel_grant_FS_REENTRANT == 1
ff_mem_alloc_USE_LFN == 3
ff_mem_free_USE_LFN == 3
@@ -44,42 +53,44 @@ FatFs繝「繧ク繝・繝シ繝ォ縺ッANSI C貅匁侠縺ァ險倩ソー縺輔l縺ヲ縺繧九ョ縺ァ縲、NSI C貅匁侠

髯千阜蛟、

-

繝。繝「繝ェ菴ソ逕ィ驥 (R0.07e)

+

繝。繝「繝ェ菴ソ逕ィ驥 (R0.08)

+

谺。縺ョ陦ィ縺ォ縺縺上▽縺九ョ繧ソ繝シ繧イ繝繝医↓縺翫¢繧九Γ繝「繝ェ菴ソ逕ィ驥上ョ萓九r遉コ縺励∪縺吶ゅユ繧ケ繝域凾縺ョ讒区舌が繝励す繝ァ繝ウ縺ッ縺昴ョ荳九ョ騾壹j縺ァ縺吶よ焚蛟、縺ョ蜊倅ス阪ッ繝舌う繝医〒縲D縺ッ隲也炊繝懊Μ繝・繝シ繝謨ー縲F縺ッ蜷梧凾繧ェ繝シ繝励Φ繝サ繝輔ぃ繧、繝ォ謨ー繧堤、コ縺励∪縺吶ゅさ繝ウ繝代う繝ゥ縺ョ譛驕ゥ蛹悶が繝励す繝ァ繝ウ縺ッ繧ウ繝シ繝峨サ繧オ繧、繧コ縺ィ縺励※縺縺セ縺吶

- - - - - - - - - - + + + + + + + + + +
AVRH8/300HPICTLCS-870/CV850ESSH2ARM7TDMIx86
CompilerWinAVR(gcc)CH38C30(gcc)CC870CCA850SHCWinARM(gcc)VC6
_WORD_ACCESS10011001
text (Full, R/W)1219410559109241522976868727105647342
text (Min, R/W)79886903710899604884565165444764
text (Full, R/O)55324753502067603462377746243316
text (Min, R/O)40403631373650832556290732842510
bssD*2 + 2D*4 + 2D*2 + 2D*2 + 2D*4 + 2D*4 + 2D*4 + 2D*4 + 2
Work area
(_FS_TINY == 0)
D*560 +
F*544
D*560 +
F*550
D*560 +
F*544
D*560 +
F*550
D*560 +
F*550
D*560 +
F*550
D*560 +
F*550
Work area
(_FS_TINY == 1)
D*560 +
F*32
D*560 +
F*36
D*560 +
F*32
D*560 +
F*32
D*560 +
F*36
D*560 +
F*36
D*560 +
F*36
D*560 +
F*36
AVRH8/300HPIC24V850ESSH-2AARM7x86
CompilerWinAVR(gcc)CH38C30(gcc)CA850SHCWinARM(gcc)VC6
_WORD_ACCESS1001001
text (Full, R/W)12700106861137677308592105207545
text (Min, R/W)8386698073954930560066364923
text (Full, R/O)6012487452503556384846563450
text (Min, R/O)4384377439392684299634162664
bssD*2 + 2D*4 + 2D*2 + 2D*4 + 2D*4 + 2D*4 + 2D*4 + 2
Work area
(_FS_TINY == 0)
D*560 +
F*544
D*560 +
F*550
D*560 +
F*544
D*560 +
F*550
D*560 +
F*550
D*560 +
F*550
D*560 +
F*550
Work area
(_FS_TINY == 1)
D*560 +
F*32
D*560 +
F*36
D*560 +
F*32
D*560 +
F*36
D*560 +
F*36
D*560 +
F*36
D*560 +
F*36
-

荳翫ョ陦ィ縺ォ縺縺上▽縺九ョ繧ソ繝シ繧イ繝繝医↓縺翫¢繧九Γ繝「繝ェ菴ソ逕ィ驥上ョ萓九r遉コ縺励∪縺吶ゅユ繧ケ繝域凾縺ョ讒区舌が繝励す繝ァ繝ウ縺ッ谺。縺ョ騾壹j縺ァ縺吶よ焚蛟、縺ョ蜊倅ス阪ッ繝舌う繝医〒縲D縺ッ隲也炊繝峨Λ繧、繝匁焚縲F縺ッ蜷梧凾繧ェ繝シ繝励Φ繝サ繝輔ぃ繧、繝ォ謨ー繧堤、コ縺励∪縺吶ゅさ繝ウ繝代う繝ゥ縺ョ譛驕ゥ蛹悶が繝励す繝ァ繝ウ縺ッ繧ウ繝シ繝峨サ繧オ繧、繧コ縺ィ縺励※縺縺セ縺吶

 _FS_READONLY     0 (R/W), 1 (R/O)
 _FS_MINIMIZE     0 (Full function), 3 (Minimized function)
 _USE_STRFUNC     0 (Disable string functions)
 _USE_MKFS        0 (Disable f_mkfs function)
 _USE_FORWARD     0 (Disable f_forward function)
+_USE_FASTSEEK    0 (Disable fast seek feature)
 _CODE_PAGE       932 (Japanese Shift-JIS)
 _USE_LFN         0 (Disable LFN)
-_MAX_SS          512 (Single sector size)
+_MAX_SS          512 (Fixed sector size)
 _FS_RPATH        0 (Disable relative path)
 _MULTI_PARTITION 0 (Single partition per drive)
 _FS_REENTRANT    0 (Disable reentrancy)
+_FS_SHARE        0 (Disable shareing control)
 
@@ -119,11 +130,11 @@ _FS_REENTRANT 0 (Disable reentrancy)

髟キ縺繝輔ぃ繧、繝ォ蜷

-

FatFs繝「繧ク繝・繝シ繝ォ縺ッR0.07縺九i髟キ縺繝輔ぃ繧、繝ォ蜷(LFN)繧偵し繝昴シ繝医@縺セ縺励◆縲ゅヵ繧。繧、繝ォ縺ォ莉倥¢繧峨l縺2縺、縺ョ逡ー縺ェ繧句錐蜑(遏ュ縺繝輔ぃ繝ォ蜷阪→髟キ縺繝輔ぃ繧、繝ォ蜷)縺ッ縲’_readdir髢「謨ー繧帝勁縺上ヵ繧。繧、繝ォ謫堺ス憺未謨ー縺ォ縺翫>縺ヲ騾城℃縺ァ縺吶LFN讖溯ス繧呈怏蜉ケ縺ォ縺吶k縺ォ縺ッ縲_USE_LFN繧1縺セ縺溘ッ2縺ォ險ュ螳壹@縲ゞnicode螟画鋤髢「謨ー ff_convert, ff_wtoupper 繧偵励Ο繧ク繧ァ繧ッ繝医↓霑ス蜉縺励∪縺吶ゅ%繧後i縺ョ髢「謨ー縺ッ縲cc*.c縺ォ蜷ォ縺セ繧後※縺縺セ縺吶LFN讖溯ス縺ッ縲∝刈縺医※縺ゅk遞句コヲ縺ョ繝ッ繝シ繧ッ繝サ繧ィ繝ェ繧「(LFN謫堺ス懊ヰ繝繝輔ぃ)繧貞ソ隕√→縺励∪縺吶ゅヰ繝繝輔ぃ髟キ縺ッ菴ソ逕ィ縺ァ縺阪k繝。繝「繝ェ縺ォ蠢懊§縺ヲ_MAX_LFN繧ェ繝励す繝ァ繝ウ縺ァ讒区舌&繧後k縺薙→縺後〒縺阪∪縺吶LFN縺ョ髟キ縺輔ッ譛螟ァ255譁蟄励↓驕斐☆繧九ョ縺ァ縲´FN螳悟ィ蟇セ蠢懊ョ縺溘a縺ォ縺ッ_MAX_LFN縺ッ255縺ォ險ュ螳壹&繧後k縺ケ縺阪〒縺吶ゆク弱∴繧峨l縺溘ヵ繧。繧、繝ォ蜷阪↓蟇セ縺励※繝舌ャ繝輔ぃ髟キ縺御ク崎カウ縺励◆蝣エ蜷医√ヵ繧。繧、繝ォ髢「謨ー縺ッFR_INVALID_NAME縺ァ螟ア謨励@縺セ縺吶

-

LFN讖溯ス繧偵Μ繧ィ繝ウ繝医Λ繝ウ繝域ァ区舌〒菴ソ逕ィ縺吶k蝣エ蜷医ッ縲_USE_LFN縺ッ2縺ォ險ュ螳壹&繧後↑縺代l縺ー縺ェ繧翫∪縺帙s縲ゅ%縺ョ蝣エ蜷医√ヵ繧。繧、繝ォ髢「謨ー縺ッ繝舌ャ繝輔ぃ繧偵せ繧ソ繝繧ッ縺ォ遒コ菫昴@縺セ縺吶ゅヰ繝繝輔ぃ繝サ繧オ繧、繧コ縺ッ縲(_MAX_LFN + 1) * 2繝舌う繝医↓縺ェ繧九ョ縺ァ縲∝他縺ウ蜃コ縺怜エ繧ケ繧ソ繝繧ッ縺ョ繧オ繧、繧コ縺ッ縺昴l繧定諷ョ縺励◆蜊∝縺ェ繧オ繧、繧コ縺ァ縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲

+

FatFs繝「繧ク繝・繝シ繝ォ縺ッR0.07縺九i髟キ縺繝輔ぃ繧、繝ォ蜷(LFN)繧偵し繝昴シ繝医@縺セ縺励◆縲ゅヵ繧。繧、繝ォ縺ォ莉倥¢繧峨l縺2縺、縺ョ逡ー縺ェ繧句錐蜑(遏ュ縺繝輔ぃ繝ォ蜷阪→髟キ縺繝輔ぃ繧、繝ォ蜷)縺ッ縲’_readdir髢「謨ー繧帝勁縺上ヵ繧。繧、繝ォ謫堺ス憺未謨ー縺ォ縺翫>縺ヲ騾城℃縺ァ縺吶LFN讖溯ス繧呈怏蜉ケ縺ォ縺吶k縺ォ縺ッ縲_USE_LFN繧1,2縺セ縺溘ッ3縺ォ險ュ螳壹@縲ゞnicode螟画鋤髢「謨ーff_convert(), ff_wtoupper()繧偵励Ο繧ク繧ァ繧ッ繝医↓霑ス蜉縺励∪縺吶ゅ%繧後i縺ョ髢「謨ー縺ッ縲option/cc*.c縺ォ蜷ォ縺セ繧後※縺縺セ縺吶LFN讖溯ス縺ッ縲∝刈縺医※縺ゅk遞句コヲ縺ョ繝ッ繝シ繧ッ繝サ繧ィ繝ェ繧「(LFN謫堺ス懊ヰ繝繝輔ぃ)繧貞ソ隕√→縺励∪縺吶ゅヰ繝繝輔ぃ髟キ縺ッ菴ソ逕ィ縺ァ縺阪k繝。繝「繝ェ縺ォ蠢懊§縺ヲ_MAX_LFN繧ェ繝励す繝ァ繝ウ縺ァ讒区舌&繧後k縺薙→縺後〒縺阪∪縺吶LFN縺ョ髟キ縺輔ッ譛螟ァ255譁蟄励↓驕斐☆繧九ョ縺ァ縲´FN螳悟ィ蟇セ蠢懊ョ縺溘a縺ォ縺ッ_MAX_LFN縺ッ255縺ォ險ュ螳壹&繧後k縺ケ縺阪〒縺吶ゆク弱∴繧峨l縺溘ヵ繧。繧、繝ォ蜷阪↓蟇セ縺励※繝舌ャ繝輔ぃ髟キ縺御ク崎カウ縺励◆蝣エ蜷医√ヵ繧。繧、繝ォ髢「謨ー縺ッFR_INVALID_NAME縺ァ螟ア謨励@縺セ縺吶

+

LFN讖溯ス繧偵Μ繧ィ繝ウ繝医Λ繝ウ繝域ァ区舌〒菴ソ逕ィ縺吶k蝣エ蜷医ッ縲_USE_LFN縺ッ2縺セ縺溘ッ3縺ォ險ュ螳壹&繧後↑縺代l縺ー縺ェ繧翫∪縺帙s縲ゅ%縺ョ蝣エ蜷医√ヵ繧。繧、繝ォ髢「謨ー縺ッ繝舌ャ繝輔ぃ繧偵せ繧ソ繝繧ッ繧繝偵シ繝励↓遒コ菫昴@縺セ縺吶ゅヰ繝繝輔ぃ繝サ繧オ繧、繧コ縺ッ縲(_MAX_LFN + 1) * 2繝舌う繝医↓縺ェ繧九ョ縺ァ縲√せ繧ソ繝繧ッ遲峨ョ繧オ繧、繧コ縺ッ縺昴l繧定諷ョ縺励◆蜊∝縺ェ繧オ繧、繧コ縺ァ縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲

- + @@ -134,17 +145,28 @@ _FS_REENTRANT 0 (Disable reentrancy)

豕ィ: FAT繝輔ぃ繧、繝ォ繝サ繧キ繧ケ繝繝荳翫ョLFN讖溯ス縺ッ繝槭う繧ッ繝ュ繧ス繝輔ヨ遉セ縺ョ迚ケ險ア縺ァ縺吶ょ膚逕ィ陬ス蜩√〒縺昴l繧呈怏蜉ケ縺ォ縺吶k縺ィ縺阪ッ縲∵怙邨ゆサ募髄蝨ー縺ォ繧医▲縺ヲ縺ッ繝ゥ繧、繧サ繝ウ繧ケ縺悟ソ隕√°繧ら衍繧後∪縺帙s縲

+
+

譌・譛ャ隱槭ヵ繧。繧、繝ォ蜷阪ョ螟ァ譁蟄怜、画鋤

+

CP932(Shift_JIS)縺ァ縺九▽髱朖FN讒区舌ョ縺ィ縺阪ッ縲∵僑蠑オ譁蟄励ョ蟆乗枚蟄(2繝舌う繝郁恭蟄励サ繧ュ繝ェ繝ォ譁蟄励サ繧ョ繝ェ繧キ繝」譁蟄)縺ォ蟇セ縺励※螟ァ譁蟄怜、画鋤繧定。後o縺壹∝ー乗枚蟄励ョ縺セ縺セSFN繧ィ繝ウ繝医Μ縺ォ險倬鹸繝サ讀懃エ「縺輔l縺セ縺吶ゅ%繧後ッ譌・譛ャ隱朞SDOS縺ィ蜷後§莉墓ァ倥→縺ェ繧翫∪縺吶ゅ%縺ョ縺溘a縲髱朖FN讒区舌〒蜈ィ隗貞ー乗枚蟄励r蜷ォ繧繝輔ぃ繧、繝ォ繧剃ス懈舌☆繧九→縲¨T邉サWindows縺ァ縺昴ョ繝輔ぃ繧、繝ォ繧帝幕縺代↑縺上↑繧翫∪縺吶LFN讒区舌〒縺ッ螟ァ譁蟄怜、画鋤繧定。後>縺セ縺(NT邉サWindows莉墓ァ)縲

+
+ +
+

Unicode蜈・蜃コ蜉帙∈縺ョ蟇セ蠢

+

繝輔ぃ繧、繝ォ髢「謨ー縺ョ繝輔ぃ繧、繝ォ蜷榊・蜃コ蜉帙ッ繝繝輔か繝ォ繝医〒縺ッ ANSI/OEM繧ウ繝シ繝峨〒縺吶′縲√%繧後rUnicode縺ォ蛻繧頑崛縺医k縺薙→繧ゅ〒縺阪∪縺吶6nicode繝輔ぃ繧、繝ォ蜷阪↓髢「縺吶k隧ウ邏ー縺ッ縲繝輔ぃ繧、繝ォ蜷繧貞盾辣ァ縺励※縺上□縺輔>縲

+
+

繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ

-

莠偵>縺ォ逡ー縺ェ繧九懊Μ繝・繝シ繝(隲也炊繝峨Λ繧、繝)縺ォ蟇セ縺吶k繝輔ぃ繧、繝ォ謫堺ス懊ッ縲∝クク縺ォ蜷梧凾蟷ウ陦後↓蜍穂ス懊〒縺阪∪縺吶ょ酔縺倥懊Μ繝・繝シ繝縺ォ蟇セ縺励※縺ッ繝繝輔か繝ォ繝医〒縺ッ繝ェ繧ィ繝ウ繝医Λ繝ウ繝医〒縺ッ縺ゅj縺セ縺帙s縺後_FS_REENTRANT繧ェ繝励す繝ァ繝ウ縺ァ繝ェ繧ィ繝ウ繝医Λ繝ウ繝医↓縺吶k縺薙→繧ゅ〒縺阪∪縺吶ゅ%縺ョ蝣エ蜷医^S萓晏ュ倥ョ蜷梧悄繧ェ繝悶ず繧ァ繧ッ繝域桃菴憺未謨ー ff_cre_syncobj, ff_del_syncobj, ff_req_grant 縺ィ ff_rel_grant 繧ゅ∪縺溘励Ο繧ク繧ァ繧ッ繝医↓霑ス蜉縺輔l縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲ゅし繝ウ繝励Ν繝サ繧ウ繝シ繝峨→隗」隱ャ縺ッsyncobj.c縺ォ縺ゅj縺セ縺吶

+

莠偵>縺ォ逡ー縺ェ繧九懊Μ繝・繝シ繝縺ォ蟇セ縺吶k繝輔ぃ繧、繝ォ謫堺ス懊ッ縲∝クク縺ォ蜷梧凾蟷ウ陦後↓蜍穂ス懊〒縺阪∪縺吶ょ酔縺倥懊Μ繝・繝シ繝縺ォ蟇セ縺励※縺ッ繝繝輔か繝ォ繝医〒縺ッ繝ェ繧ィ繝ウ繝医Λ繝ウ繝医〒縺ッ縺ゅj縺セ縺帙s縺後_FS_REENTRANT繧ェ繝励す繝ァ繝ウ縺ァ繝ェ繧ィ繝ウ繝医Λ繝ウ繝医↓縺吶k縺薙→繧ゅ〒縺阪∪縺吶ゅ%縺ョ蝣エ蜷医^S萓晏ュ倥ョ蜷梧悄繧ェ繝悶ず繧ァ繧ッ繝域桃菴憺未謨ーff_cre_syncobj, ff_del_syncobj, ff_req_grant 縺ィ ff_rel_grant繧ゅ∪縺溘励Ο繧ク繧ァ繧ッ繝医↓霑ス蜉縺輔l縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲ゅし繝ウ繝励Ν繝サ繧ウ繝シ繝峨→隗」隱ャ縺ッoption/syncobj.c縺ォ縺ゅj縺セ縺吶

縺ゅk繧ソ繧ケ繧ッ縺後懊Μ繝・繝シ繝繧剃スソ逕ィ荳ュ縺ォ莉悶ョ繧ソ繧ケ繧ッ縺九i縺昴ョ繝懊Μ繝・繝シ繝縺ォ蟇セ縺吶k繝輔ぃ繧、繝ォ髢「謨ー縺悟他縺ウ蜃コ縺輔l繧九→縲√◎縺ョ繧「繧ッ繧サ繧ケ縺ッ蜈医ョ繧ソ繧ケ繧ッ縺後ヵ繧。繧、繝ォ髢「謨ー繧呈栢縺代k縺セ縺ァ繝悶Ο繝繧ッ縺輔l縺セ縺吶ゅb縺励∝セ縺。譎る俣縺_TIMEOUT縺ァ謖螳壹&繧後◆譛滄俣繧定カ翫☆縺ィ縲√◎縺ョ髢「謨ー縺ッFR_TIMEOUT縺ァ繧「繝懊シ繝医@縺セ縺吶ゅ>縺上▽縺九ョRTOS縺ァ縺ッ繧ソ繧、繝繧「繧ヲ繝域ゥ溯ス縺ッ繧オ繝昴シ繝医&繧後↑縺縺九b遏・繧後∪縺帙s縲

-

縺イ縺ィ縺、縺ョ萓句、悶′f_mount縺ィf_mkfs髢「謨ー縺ォ縺ゅj縺セ縺吶ゅ%繧後i縺ョ髢「謨ー縺ッ蜷後§繝懊Μ繝・繝シ繝縺ォ蟇セ縺励※繝ェ繧ィ繝ウ繝医Λ繝ウ繝医〒縺ッ縺ゅj縺セ縺帙s縲ゅ%繧後i縺ョ髢「謨ー繧剃スソ逕ィ縺吶k縺ィ縺阪ッ縲√い繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝ャ繝吶Ν縺ァ謗剃サ門宛蠕。縺励↑縺代l縺ー縺ェ繧翫∪縺帙s縲

+

縺イ縺ィ縺、縺ョ萓句、悶′f_mount()縺ィf_mkfs()縺ォ縺ゅj縺セ縺吶ゅ%繧後i縺ョ髢「謨ー縺ッ蜷後§繝懊Μ繝・繝シ繝縺ォ蟇セ縺励※繝ェ繧ィ繝ウ繝医Λ繝ウ繝医〒縺ッ縺ゅj縺セ縺帙s縲ゅ%繧後i縺ョ髢「謨ー繧剃スソ逕ィ縺吶k縺ィ縺阪ッ縲√い繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝ャ繝吶Ν縺ァ謗剃サ門宛蠕。縺励↑縺代l縺ー縺ェ繧翫∪縺帙s縲

豕ィ: 縺薙ョ繧サ繧ッ繧キ繝ァ繝ウ縺ッFatFs繝「繧ク繝・繝シ繝ォ縺昴l閾ェ菴薙ョ繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ縺ォ縺、縺縺ヲ隱ャ譏弱@縺ヲ縺縺セ縺吶ゅョ繧」繧ケ繧ッI/O繝「繧ク繝・繝シ繝ォ縺ョ繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ縺ォ髢「縺励※縺ッ菴輔ョ蜑肴署繧ゅ≠繧翫∪縺帙s縲

螟夐阪ヵ繧。繧、繝ォ繝サ繧「繧ッ繧サ繧ケ

-

FatFs繝「繧ク繝・繝シ繝ォ縺ァ縺ッ螟夐阪い繧ッ繧サ繧ケ讖溯ス縺ッ繧オ繝昴シ繝医&繧後∪縺帙s縲ゅヵ繧。繧、繝ォ縺ォ蟇セ縺吶k螟夐阪い繧ッ繧サ繧ケ縺ッ縲√◎縺ョ繧「繧ッ繧サ繧ケ繝サ繝「繝シ繝峨↓繧医▲縺ヲ蛻カ髯舌&繧後∪縺吶ゆク縺、縺ョ繝輔ぃ繧、繝ォ縺ォ蟇セ縺吶k螟夐阪が繝シ繝励Φ縺ッ縲√◎繧後i縺悟ィ縺ヲ繝ェ繝シ繝峨サ繝「繝シ繝峨ョ縺ィ縺阪↓髯舌▲縺ヲ險ア蜿ッ縺輔l縺セ縺吶よ嶌縺崎セシ縺ソ繝「繝シ繝峨r蜷ォ繧螟夐阪が繝シ繝励Φ縲√∪縺滄幕縺九l縺ヲ縺繧九ヵ繧。繧、繝ォ縺ォ蟇セ縺吶k繝ェ繝阪シ繝繧豸亥悉繧定。後▲縺ヲ縺ッ縺ェ繧翫∪縺帙s縲ゅ&繧ゅ↑縺縺ィ縲√◎縺ョ繝懊Μ繝・繝シ繝縺ョFAT讒矩縺檎エ螢翫&繧後k蜿ッ閭ス諤ァ縺後≠繧翫∪縺吶

+

FatFs繝「繧ク繝・繝シ繝ォ縺ァ縺ッ繝繝輔か繝ォ繝医〒縺ッ螟夐阪い繧ッ繧サ繧ケ蛻カ蠕。讖溯ス繧偵し繝昴シ繝医@縺ヲ縺縺セ縺帙s縲ゅヵ繧。繧、繝ォ縺ォ蟇セ縺吶k螟夐阪い繧ッ繧サ繧ケ縺ッ縲√◎縺ョ繧「繧ッ繧サ繧ケ繝サ繝「繝シ繝峨↓繧医▲縺ヲ蛻カ髯舌&繧後∪縺吶ゆク縺、縺ョ繝輔ぃ繧、繝ォ縺ォ蟇セ縺吶k螟夐阪が繝シ繝励Φ縺ッ縲√◎繧後i縺悟ィ縺ヲ繝ェ繝シ繝峨サ繝「繝シ繝峨ョ縺ィ縺阪↓髯舌▲縺ヲ險ア蜿ッ縺輔l縺セ縺吶よ嶌縺崎セシ縺ソ繝「繝シ繝峨r蜷ォ繧螟夐阪が繝シ繝励Φ縲√∪縺滄幕縺九l縺ヲ縺繧九ヵ繧。繧、繝ォ縺ォ蟇セ縺吶k繝ェ繝阪シ繝繧蜑企勁縲√き繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ョ蜑企勁繧定。後▲縺ヲ縺ッ縺ェ繧翫∪縺帙s縲ゅ&繧ゅ↑縺縺ィ縲√◎縺ョ繝懊Μ繝・繝シ繝縺ョFAT讒矩縺檎エ螢翫&繧後k蜿ッ閭ス諤ァ縺後≠繧翫∪縺吶

+

_FS_SHARE縺ォ1莉・荳翫ョ蛟、繧偵そ繝繝医☆繧九%縺ィ縺ォ繧医j縲√ヵ繧。繧、繝ォ蜊倅ス阪ョ謗剃サ門宛蠕。繧定ェ蜍輔〒陦後≧縺薙→繧ゅ〒縺阪∪縺吶ゅ%縺ョ蝣エ蜷医∽ク願ィ倥ョ繝ォ繝シ繝ォ繧堤エ縺」縺溘が繝シ繝励Φ繝サ繝ェ繝阪シ繝繝サ蜑企勁繧定ゥヲ縺ソ繧九→縲√◎縺ョ髢「謨ー縺ッFR_LOCKED縺ァ螟ア謨励@縺セ縺吶

@@ -187,21 +209,11 @@ _FS_REENTRANT 0 (Disable reentrancy)

縺縺壹l繧よ嶌縺崎セシ縺ソ荳ュ繧謫堺ス懷ッセ雎。縺ァ縺ェ縺繝輔ぃ繧、繝ォ縺ォ縺ッ蠖ア髻ソ縺ッ縺ゅj縺セ縺帙s縲ゅ%繧後i縺ョ繧ッ繝ェ繝√き繝ォ繝サ繧サ繧ッ繧キ繝ァ繝ウ縺ッ縲√ヵ繧。繧、繝ォ繧呈嶌縺崎セシ縺ソ繝「繝シ繝峨〒髢九>縺ヲ縺繧区凾髢薙r譛蟆城剞縺ォ縺吶k縺九’_sync()繧帝←螳應スソ逕ィ縺吶k縺薙→縺ァ蝗ウ5縺ョ繧医≧縺ォ繝ェ繧ケ繧ッ繧呈怙蟆丞喧縺吶k縺薙→縺後〒縺阪∪縺吶

-
-

譌・譛ャ隱槭ヵ繧。繧、繝ォ蜷阪ョ螟ァ譁蟄怜、画鋤

-

CP932(Shift_JIS)縺ァ縺九▽髱朖FN讒区舌ョ縺ィ縺阪ッ縲∵僑蠑オ譁蟄励ョ蟆乗枚蟄(2繝舌う繝郁恭蟄励サ繧ュ繝ェ繝ォ譁蟄励サ繧ョ繝ェ繧キ繝」譁蟄)縺ォ蟇セ縺励※螟ァ譁蟄怜、画鋤繧定。後o縺壹∝ー乗枚蟄励ョ縺セ縺セSFN繧ィ繝ウ繝医Μ縺ォ險倬鹸繝サ讀懃エ「縺輔l縺セ縺吶ゅ%繧後ッ譌・譛ャ隱朞SDOS縺ィ蜷後§莉墓ァ倥→縺ェ繧翫∪縺吶ゅ%縺ョ縺溘a縲∝ィ隗貞ー乗枚蟄励r蜷ォ繧繝輔ぃ繧、繝ォ繧剃ス懈舌☆繧九→縲¨T邉サWindows縺ァ縺昴ョ繝輔ぃ繧、繝ォ繧帝幕縺代↑縺上↑繧翫∪縺吶LFN讒区舌〒縺ッ螟ァ譁蟄怜、画鋤繧定。後>縺セ縺(NT邉サWindows莉墓ァ)縲

-
- -
-

Unicode蜈・蜃コ蜉帙∈縺ョ蟇セ蠢

-

繝輔ぃ繧、繝ォ髢「謨ー縺ョ繝輔ぃ繧、繝ォ蜷榊・蜃コ蜉帙ッ繝繝輔か繝ォ繝医〒縺ッ OEM繧ウ繝シ繝峨〒縺吶′縲√%繧後rUnicode縺ォ蛻繧頑崛縺医k縺薙→繧ゅ〒縺阪∪縺吶りゥウ邏ー縺ッ縲繝輔ぃ繧、繝ォ蜷繧貞盾辣ァ縺励※縺上□縺輔>縲

-
-

FatFs縺ョ繝ゥ繧、繧サ繝ウ繧ケ縺ォ縺、縺縺ヲ

繧ス繝シ繧ケ繝サ繝輔ぃ繧、繝ォ縺ョ繝倥ャ繝縺ォ繝ゥ繧、繧サ繝ウ繧ケ譚。莉カ縺瑚ィ倩ソー縺輔l縺ヲ縺繧九ョ縺ァ縲∝茜逕ィ縺ョ髫帙ッ縺昴l縺ォ蠕薙≧縺薙→縲り恭隱槭r隱ュ繧√↑縺譁ケ縺ョ縺溘a縺ォ莉・荳九↓譌・譛ャ隱櫁ィウ繧堤、コ縺励※縺翫″縺セ縺吶

/*----------------------------------------------------------------------------/
-/  FatFs - FAT file system module  R0.07e                    (C)ChaN, 2009
+/  FatFs - FAT file system module  R0.08                    (C)ChaN, 2009
 /-----------------------------------------------------------------------------/
 / FatFs繝「繧ク繝・繝シ繝ォ縺ッ縲∝ー剰ヲ乗ィ。縺ェ邨縺ソ霎シ縺ソ繧キ繧ケ繝繝蜷代¢縺ョ豎守畑FAT繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繝サ
 / 繝「繧ク繝・繝シ繝ォ縺ァ縺吶ゅ%繧後ッ繝輔Μ繝シ繝サ繧ス繝輔ヨ繧ヲ繧ァ繧「縺ィ縺励※縲∵蕗閧イ繝サ遐皮ゥカ繝サ髢狗匱縺ョ縺溘a縺ォ
@@ -215,7 +227,7 @@ _FS_REENTRANT    0 (Disable reentrancy)
 / * 繧ス繝シ繧ケ繝サ繧ウ繝シ繝峨r蜀埼榊ク縺吶k縺ィ縺阪ッ縲∽ク願ィ倥ョ闡嶺ス懈ィゥ陦ィ遉コ繧剃ソ晄戟縺励↑縺代l縺ー縺ェ繧翫∪縺帙s縲
 /
 /-----------------------------------------------------------------------------/
-

隕√☆繧九↓FatFs縺ッ繧ソ繝縺ァ閾ェ逕ア縺ォ菴ソ縺医k縺ィ縺縺縺薙→縺ァ縺吶ゅた繝シ繧ケ繝サ繧ウ繝シ繝峨r蜀埼榊ク縺吶k縺ィ縺阪ッ縲√%縺ョ繝悶Ο繝繧ッ繧偵◎縺ョ縺セ縺セ菫晄戟縺励※縺翫¥縺薙→縲ゅ%縺ョ繧医≧縺ォFatFs縺ッBSD繝ゥ繧、繧ッ縺ェ繝ゥ繧、繧サ繝ウ繧ケ縺ィ縺励※縺縺セ縺吶′縲∽ク縺、螟ァ縺阪↑驕輔>縺後≠繧翫∪縺吶ら音縺ォ邨縺ソ霎シ縺ソ逕ィ騾斐〒縺ョ蛻ゥ逕ィ萓。蛟、繧帝ォ倥a繧九◆繧√√ヰ繧、繝翫Μ蠖「蠑(繧ス繝シ繧ケ繝サ繧ウ繝シ繝峨r蜷ォ縺セ縺ェ縺蠖「蠑丞ィ縺ヲ)縺ァ縺ョ蜀埼榊ク縺ォ縺、縺縺ヲ縺ッ縲∵擅莉カ縺ッ險ュ縺代※縺縺セ縺帙s縲ゅ◎縺ョ蝣エ蜷医ッ縲:atFs縺翫h縺ウ縺昴ョ繝ゥ繧、繧サ繝ウ繧ケ譁譖ク縺ォ縺、縺縺ヲ縺ッ繝峨く繝・繝。繝ウ繝医↓譏手ィ倥@縺ヲ繧ゅ@縺ェ縺上※繧ゅ°縺セ縺縺セ縺帙s縲ゅb縺。繧阪sGNU GPL繝励Ο繧ク繧ァ繧ッ繝医→繧ょア蟄伜庄閭ス縺ァ縺吶ゆス輔i縺九ョ螟画峩繧貞刈縺医※蜀埼榊ク縺吶k髫帙ッ縲∽サ悶ョ繝ゥ繧、繧サ繝ウ繧ケ(GNU GPL縺毅SD繝ゥ繧、繧サ繝ウ繧ケ)縺ォ螟画峩縺吶k縺薙→繧ょ庄閭ス縺ァ縺吶

+

隕√☆繧九↓FatFs縺ッ繧ソ繝縺ァ閾ェ逕ア縺ォ菴ソ縺医k縺ィ縺縺縺薙→縺ァ縺吶ゅた繝シ繧ケ繝サ繧ウ繝シ繝峨r蜀埼榊ク縺吶k縺ィ縺阪ッ縲√%縺ョ繝悶Ο繝繧ッ繧偵◎縺ョ縺セ縺セ菫晄戟縺励※縺翫¥縺薙→縲ゅ%縺ョ繧医≧縺ォFatFs縺ッBSD繝ゥ繧、繧ッ縺ェ繝ゥ繧、繧サ繝ウ繧ケ縺ィ縺励※縺縺セ縺吶′縲∽ク縺、螟ァ縺阪↑驕輔>縺後≠繧翫∪縺吶ら音縺ォ邨縺ソ霎シ縺ソ逕ィ騾斐〒縺ョ蛻ゥ逕ィ萓。蛟、繧帝ォ倥a繧九◆繧√√ヰ繧、繝翫Μ蠖「蠑(繧ス繝シ繧ケ繝サ繧ウ繝シ繝峨r蜷ォ縺セ縺ェ縺蠖「蠑丞ィ縺ヲ)縺ァ縺ョ蜀埼榊ク縺ォ縺、縺縺ヲ縺ッ縲∵擅莉カ縺ッ險ュ縺代※縺縺セ縺帙s縲ゅ◎縺ョ蝣エ蜷医ッ縲:atFs縺翫h縺ウ縺昴ョ繝ゥ繧、繧サ繝ウ繧ケ譁譖ク縺ォ縺、縺縺ヲ縺ッ繝峨く繝・繝。繝ウ繝医↓譏手ィ倥@縺ヲ繧ゅ@縺ェ縺上※繧ゅ°縺セ縺縺セ縺帙s縲ゅb縺。繧阪sGNU GPL繝励Ο繧ク繧ァ繧ッ繝医→繧ょア蟄伜庄閭ス縺ァ縺吶ゆス輔i縺九ョ螟画峩繧貞刈縺医※蜀埼榊ク縺吶k髫帙ッ縲∫泝逶セ縺励↑縺莉悶ョ繝ゥ繧、繧サ繝ウ繧ケ(GNU GPL繧ВSD繝ゥ繧、繧サ繝ウ繧ケ縺ェ縺ゥ)縺ォ螟画峩縺吶k縺薙→繧ょ庄閭ス縺ァ縺吶

謌サ繧

diff --git a/doc/ja/chdir.html b/doc/ja/chdir.html index ad0e751..90f8804 100644 --- a/doc/ja/chdir.html +++ b/doc/ja/chdir.html @@ -4,6 +4,7 @@ +FatFs - f_chdir @@ -15,7 +16,7 @@

カレント・ディレクトリを変更します。

 FRESULT f_chdir (
-  const XCHAR* Path /* ディレクトリ名へのポインタ */
+  const XCHAR* Path /* ディレクトリ名へのポインタ */
 );
 
@@ -53,7 +54,7 @@ FRESULT f_chdir (
FR_NOT_ENABLED
その論理ドライブにワーク・エリアが与えられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
@@ -71,7 +72,7 @@ FRESULT f_chdir (
-

サンプル・コード

+

使用例

     // カレント・ドライブのカレント・ディレクトリを変更 (ルート下のdir1へ)
     f_chdir("/dir1");
diff --git a/doc/ja/chdrive.html b/doc/ja/chdrive.html
index 33343ff..187f9ed 100644
--- a/doc/ja/chdrive.html
+++ b/doc/ja/chdrive.html
@@ -4,6 +4,7 @@
 
 
 
+
 
 FatFs - f_chdrive
 
@@ -15,7 +16,7 @@
 

カレント・ドライブを変更します。

 FRESULT f_chdrive (
-  BYTE Drive /* 論理ドライブ番号 */
+  BYTE Drive /* 論理ドライブ番号 */
 );
 
diff --git a/doc/ja/chmod.html b/doc/ja/chmod.html index f14ceb8..000b5a3 100644 --- a/doc/ja/chmod.html +++ b/doc/ja/chmod.html @@ -4,6 +4,7 @@ +FatFs - f_chmod @@ -15,9 +16,9 @@

ファイルまたはディレクトリの属性を変更します。

 FRESULT f_chmod (
-  const XCHAR* FileName, /* ファイルまたはディレクトリ名へのポインタ */
-  BYTE Attribute,        /* 設定値 */
-  BYTE AttributeMask     /* 変更マスク */
+  const TCHAR* FileName, /* ファイルまたはディレクトリ名へのポインタ */
+  BYTE Attribute,        /* 設定値 */
+  BYTE AttributeMask     /* 変更マスク */
 );
 
@@ -67,7 +68,7 @@ FRESULT f_chmod (
FR_NOT_ENABLED
その論理ドライブにワーク・エリアが与えられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
@@ -87,7 +88,7 @@ FRESULT f_chmod (

使用例

-    /* リードオンリーをセット、アーカイブをクリア、その他は変更しない */
+    /* リードオンリーをセット、アーカイブをクリア、その他は変更しない */
     f_chmod("file.txt", AM_RDO, AM_RDO | AM_ARC);
 
diff --git a/doc/ja/close.html b/doc/ja/close.html index 7fa4b0f..8d397c1 100644 --- a/doc/ja/close.html +++ b/doc/ja/close.html @@ -4,6 +4,7 @@ +FatFs - f_close @@ -15,7 +16,7 @@

ファイルを閉じます。

 FRESULT f_close (
-  FIL* FileObject     /* ファイル・オブジェクトへのポインタ */
+  FIL* FileObject     /* ファイル・オブジェクトへのポインタ */
 );
 
@@ -48,7 +49,7 @@ FRESULT f_close (

解説

-

ファイルを閉じます。書き込みの行われたファイルの場合、キャッシュされた状態(R/Wバッファ上のデータ、変更されたFATやディレクトリ項目)はディスクに書き戻されます。関数が正常終了すると、そのファイル・オブジェクトは無効になり、そのメモリも解放できます。読み込み専用モードで開かれたファイル・オブジェクトは、この関数によるクローズ処理を経ずに破棄することもできます。

+

ファイルを閉じます。何らかの書き込みの行われたファイルの場合、キャッシュされた状態(リード/ライト・バッファ上のデータ、変更されたFATやディレクトリ項目)はディスクに書き戻されます。関数が正常終了すると、そのファイル・オブジェクトは無効になり、そのメモリも解放できます。読み込み専用モードで開かれたファイル・オブジェクトは、この関数によるクローズ処理を経ずに破棄することもできますが、推奨はされません。

diff --git a/doc/ja/dinit.html b/doc/ja/dinit.html index c04b829..f4b9530 100644 --- a/doc/ja/dinit.html +++ b/doc/ja/dinit.html @@ -4,6 +4,7 @@ +FatFs - disk_initialize @@ -15,7 +16,7 @@

ディスク・ドライブを初期化します。

 DSTATUS disk_initialize (
-  BYTE Drive      /* 物理ドライブ番号 */
+  BYTE Drive      /* 物理ドライブ番号 */
 );
 
@@ -37,7 +38,7 @@ DSTATUS disk_initialize (

解説

ディスク・ドライブを初期化します。関数が成功すると、戻り値のSTA_NOINITフラグがクリアされます。

-

FatFsモジュールは、自動マウント動作により必要に応じてこの関数を呼び出します。FatFsモジュール使用中はアプリケーションからこの関数を呼び出してはなりません。さもないとFAT構造が破壊される可能性があります。エラー等により再初期化が必要なときは、f_mount()を使用します。

+

FatFsモジュールは、自動マウント動作により必要に応じてこの関数を呼び出します。アプリケーションからこの関数を呼び出してはなりません。さもないとFAT構造が破壊される可能性があります。エラー等により再初期化が必要なときは、f_mount()を使用します。

戻る

diff --git a/doc/ja/dioctl.html b/doc/ja/dioctl.html index ecb5adf..e164a27 100644 --- a/doc/ja/dioctl.html +++ b/doc/ja/dioctl.html @@ -4,6 +4,7 @@ +FatFs - disk_ioctl @@ -15,9 +16,9 @@

セクタの読み書き以外のディスク・ドライブ自体に対する様々な制御をします。

 DRESULT disk_ioctl (
-  BYTE Drive,      /* 物理ドライブ番号 */
-  BYTE Command,    /* 制御コマンド */
-  void* Buffer     /* データ受け渡しバッファ */
+  BYTE Drive,      /* 物理ドライブ番号 */
+  BYTE Command,    /* 制御コマンド */
+  void* Buffer     /* データ受け渡しバッファ */
 );
 
@@ -54,10 +55,10 @@ DRESULT disk_ioctl (

この関数はリード・オンリー構成では必要とされません。

LFN cfg on ARM7
繧ウ繝シ繝峨壹シ繧クROM繧オ繧、繧コ[bytes]
繧ウ繝シ繝峨壹シ繧ク繧ウ繝シ繝峨し繧、繧コ[bytes]
SBCS+3721
932(Shift-JIS)+62609
936(GBK)+177797
- - - - + + + +
コマンド解説
CTRL_SYNCドライブがデータの書き込みを完了するのを待ちます。ライト・バック・キャッシュがある場合は、書き込まれていないデータを即時書き戻します。
GET_SECTOR_SIZEBufferの指すWORD変数にドライブのセクタ・サイズを返します。_MAX_SSが1024以上のとき必要とされます。
GET_SECTOR_COUNTBufferの指すDWORD変数にドライブ上の総セクタ数を返します。f_mkfs内でのみ使用。
GET_BLOCK_SIZEBufferの指すDWORD変数にメモリ・アレーの消去ブロックサイズをセクタ単位で返します。不明な場合またはHDDでは1を返します。f_mkfs内でのみ使用。
CTRL_SYNCドライブがデータの書き込み処理を完了するのを待ちます。また、ライト・バック・キャッシュが存在する場合は、書き込まれていないデータを即時書き戻します。
GET_SECTOR_SIZEBufferの指すWORD変数にドライブのセクタ・サイズを返します。セクタサイズが固定(_MAX_SSが512)のときはこのコマンドは必要ありません。
GET_SECTOR_COUNTBufferの指すDWORD変数にドライブ上の総セクタ数を返します。f_mkfs関数内で作成するボリュームのサイズを決定するために使用されます。
GET_BLOCK_SIZEフラッシュ・メモリ・アレーの消去ブロック・サイズが分かる場合は、Bufferの指すDWORD変数にそれをセクタ単位で返します。1から32768でかつ2の累乗の値でなければなりません。f_mkfs関数内でのみ使用され、データ領域はこの境界にアライメントされます。不明な場合またはディスク・ドライブでは1を返します。
diff --git a/doc/ja/dread.html b/doc/ja/dread.html index 930f26a..9e7841e 100644 --- a/doc/ja/dread.html +++ b/doc/ja/dread.html @@ -4,6 +4,7 @@ + FatFs - disk_read @@ -15,10 +16,10 @@

ディスクからセクタを読み出します。

 DRESULT disk_read (
-  BYTE Drive,          /* 物理ドライブ番号 */
-  BYTE* Buffer,        /* 読み出しバッファへのポインタ */
-  DWORD SectorNumber,  /* 読み出し開始セクタ番号 */
-  BYTE SectorCount     /* 読み出しセクタ数 */
+  BYTE Drive,          /* 物理ドライブ番号 */
+  BYTE* Buffer,        /* 読み出しバッファへのポインタ */
+  DWORD SectorNumber,  /* 読み出し開始セクタ番号 */
+  BYTE SectorCount     /* 読み出しセクタ数 */
 );
 
diff --git a/doc/ja/dstat.html b/doc/ja/dstat.html index 29447bb..a2ad745 100644 --- a/doc/ja/dstat.html +++ b/doc/ja/dstat.html @@ -4,6 +4,7 @@ + FatFs - disk_status @@ -15,7 +16,7 @@

ディスク・ドライブの状態を取得します。

 DSTATUS disk_status (
-  BYTE Drive           /* 物理ドライブ番号 */
+  BYTE Drive           /* 物理ドライブ番号 */
 );
 
diff --git a/doc/ja/dwrite.html b/doc/ja/dwrite.html index 7dceecf..f0cf8a7 100644 --- a/doc/ja/dwrite.html +++ b/doc/ja/dwrite.html @@ -4,6 +4,7 @@ + FatFs - disk_write diff --git a/doc/ja/fattime.html b/doc/ja/fattime.html index 9a790b4..b4c2121 100644 --- a/doc/ja/fattime.html +++ b/doc/ja/fattime.html @@ -4,6 +4,7 @@ + FatFs - get_fattime diff --git a/doc/ja/filename.html b/doc/ja/filename.html index 93703e1..4f60495 100644 --- a/doc/ja/filename.html +++ b/doc/ja/filename.html @@ -4,6 +4,7 @@ + FatFs - 繝輔ぃ繧、繝ォ繝サ繝繧」繝ャ繧ッ繝医Μ縺ョ謖螳壽婿豕 @@ -12,10 +13,9 @@

繝輔ぃ繧、繝ォ繝サ繝繧」繝ャ繧ッ繝医Μ縺ョ謖螳壽婿豕

FatFs繝「繧ク繝・繝シ繝ォ縺ァ縺ョ繝輔ぃ繧、繝ォ縲√ョ繧」繝ャ繧ッ繝医Μ縲√ラ繝ゥ繧、繝悶ョ謖螳壽婿豕輔ッDOS/Windows縺ィ縺サ縺シ蜷後§縺ァ縺吶ゅヱ繧ケ蜷阪ョ繝輔か繝シ繝槭ャ繝医ッ谺。縺ョ騾壹j縺ァ縺吶

-
- "[隲也炊繝峨Λ繧、繝也分蜿キ:][/]繝繧」繝ャ繧ッ繝医Μ蜷/繝輔ぃ繧、繝ォ蜷"
-
-

FatFs繝「繧ク繝・繝シ繝ォ縺ッ髟キ縺繝輔ぃ繧、繝ォ蜷(LFN)縺翫h縺ウ8.3蠖「蠑上ヵ繧。繧、繝ォ蜷(SFN)縺ォ蟇セ蠢懊@縺ヲ縺縺セ縺吶LFN縺ッ縲(_USE_LFN > 0)縺ョ縺ィ縺堺スソ逕ィ蜿ッ閭ス縺ォ縺ェ繧翫∪縺吶DOS/Windows縺ィ縺ョ驕輔>縺ッ縲√ョ繧」繝ャ繧ッ繝医Μ繝サ繧サ繝代Ξ繝シ繧ソ縺ィ隲也炊繝峨Λ繧、繝也分蜿キ縺ョ謖螳壹〒縺吶ゅョ繧」繝ャ繧ッ繝医Μ繝サ繧サ繝代Ξ繝シ繧ソ縺ォ縺ッ / 縺セ縺溘ッ \ 繧剃スソ逕ィ縺励∪縺吶りォ也炊繝峨Λ繧、繝也分蜿キ縺ッ縲'0'ス'9'縺ョ荳譁蟄励ョ謨ー蟄励→繧ウ繝ュ繝ウ縺ァ謖螳壹@縲∫怐逡・縺励◆蝣エ蜷医ッ繝繝輔か繝ォ繝医サ繝峨Λ繧、繝(0縺セ縺溘ッ繧ォ繝ャ繝ウ繝医サ繝峨Λ繧、繝)縺碁∈謚槭&繧後∪縺吶ゅヱ繧ケ蜷阪↓蜈郁。後≠繧九>縺ッ荳ュ縺ォ蜷ォ縺セ繧後k繧ケ繝壹シ繧ケ縺ッ縲´FN讒区舌〒縺ッ蜷榊燕縺ョ荳驛ィ縺ィ縺励※譛牙柑縺ァ縺吶′縲髱朖FN讒区舌〒縺ッ繝代せ蜷阪ョ邨らォッ縺ィ縺励※隱崎ュ倥&繧後∪縺吶

+

"[隲也炊繝峨Λ繧、繝也分蜿キ:][/]繝繧」繝ャ繧ッ繝医Μ蜷/繝輔ぃ繧、繝ォ蜷"

+

FatFs繝「繧ク繝・繝シ繝ォ縺ッ髟キ縺繝輔ぃ繧、繝ォ蜷(LFN)縺翫h縺ウ8.3蠖「蠑上ヵ繧。繧、繝ォ蜷(SFN)縺ォ蟇セ蠢懊@縺ヲ縺縺セ縺吶LFN縺ッ縲(_USE_LFN > 0)縺ョ縺ィ縺堺スソ逕ィ蜿ッ閭ス縺ォ縺ェ繧翫∪縺吶DOS/Windows縺ィ縺ョ驕輔>縺ッ縲√ョ繧」繝ャ繧ッ繝医Μ繝サ繧サ繝代Ξ繝シ繧ソ縺ィ隲也炊繝峨Λ繧、繝也分蜿キ縺ョ謖螳壹〒縺吶ゅョ繧」繝ャ繧ッ繝医Μ繝サ繧サ繝代Ξ繝シ繧ソ縺ォ縺ッ / 縺セ縺溘ッ \ 繧剃スソ逕ィ縺励∪縺吶りォ也炊繝峨Λ繧、繝也分蜿キ縺ッ縲'0'ス'9'縺ョ荳譁蟄励ョ謨ー蟄励→繧ウ繝ュ繝ウ縺ァ謖螳壹@縲∫怐逡・縺励◆蝣エ蜷医ッ繝繝輔か繝ォ繝医サ繝峨Λ繧、繝(0縺セ縺溘ッ繧ォ繝ャ繝ウ繝医サ繝峨Λ繧、繝)縺碁∈謚槭&繧後∪縺吶

+

Nul譁蟄励→蛻カ蠕。譁蟄(\0ス杤x1F)縺ッ縲√ヱ繧ケ蜷阪ョ邨らォッ縺ィ縺励※隱崎ュ倥&繧後∪縺吶ゅヱ繧ケ蜷阪↓蜈郁。後≠繧九>縺ッ荳ュ縺ォ蜷ォ縺セ繧後k繧ケ繝壹シ繧ケ縺ッ縲´FN讒区舌〒縺ッ蜷榊燕縺ョ荳驛ィ縺ィ縺励※譛牙柑縺ァ縺吶′縲髱朖FN讒区舌〒縺ッ繝代せ蜷阪ョ邨らォッ縺ィ縺励※隱崎ュ倥&繧後∪縺吶

讓呎コ匁ァ区(_FS_RPATH == 0)縺ョ縺ィ縺阪ッ縲∝ィ縺ヲ縺ョ繧ェ繝悶ず繧ァ繧ッ繝医′繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ縺九i霎ソ繧狗オカ蟇セ繝代せ縺ァ謖螳壹&繧後∪縺吶0S謖蜷代↑繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ィ縺縺讎ょソオ縺ッ辟。縺上√∪縺溘ラ繝繝医サ繝繧」繝ャ繧ッ繝医Μ("."繧"..")縺ッ菴ソ逕ィ縺ァ縺阪∪縺帙s縲ゅヱ繧ケ蜷榊磯ュ縺ョ繧サ繝代Ξ繝シ繧ソ縺ッ辟。隕悶&繧後∪縺吶ゅョ繝輔か繝ォ繝医サ繝峨Λ繧、繝也分蜿キ縺ッ蟶ク縺ォ0縺ォ縺ェ繧翫∪縺吶

逶ク蟇セ繝代せ繧呈怏蜉ケ(_FS_RPATH == 1)縺ォ縺励◆縺ィ縺阪ッ縲∝郁。後☆繧九そ繝代Ξ繝シ繧ソ縺ョ譛臥┌縺ォ繧医▲縺ヲ讀懃エ「髢句ァ九ョ繧」繝ャ繧ッ繝医Μ縺悟、峨o繧翫√そ繝代Ξ繝シ繧ソ縺後≠繧句エ蜷医ッ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ縺九i縲∫┌縺蝣エ蜷医ッf_chdir髢「謨ー縺ァ險ュ螳壹&繧後k繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺九i縺ォ縺ェ繧翫∪縺吶ゅ∪縺溘ヱ繧ケ蜷阪↓繝峨ャ繝医サ繝繧」繝ャ繧ッ繝医Μ縺御スソ逕ィ縺ァ縺阪∪縺吶ゅョ繝輔か繝ォ繝医サ繝峨Λ繧、繝也分蜿キ縺ッf_chdrive髢「謨ー縺ァ險ュ螳壹&繧後◆蛟、縺ィ縺ェ繧翫∪縺吶

@@ -30,29 +30,34 @@ - +
.辟。蜉ケ縺薙ョ繝繧」繝ャ繧ッ繝医Μ
..辟。蜉ケ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ョ隕ェ繝繧」繝ャ繧ッ繝医Μ
dir1/..辟。蜉ケ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ
/..辟。蜉ケ辟。蜉ケ(繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ァ縺ッ繝峨ャ繝亥錐縺ッ菴ソ逕ィ荳榊庄)
/..辟。蜉ケ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ(縺昴ョ荳翫ッ霎ソ繧後↑縺)


Unicode API

-

繝輔ぃ繧、繝ォ髢「謨ー縺ョ蜈・蜃コ蜉帙ョ縺縺。繝輔ぃ繧、繝ォ蜷阪d繝代せ蜷阪r謖螳壹☆繧句シ墓焚縺ョ蝙九ッ縲XCHAR縺ァ螳夂セゥ縺輔l縺ヲ縺縺セ縺吶′縲√%繧後ッchar縺ョ繧ィ繝ェ繧「繧ケ縺ォ縺ェ縺」縺ヲ縺縺セ縺吶ゅ◎縺励※縲_CODE_PAGE縺ァ謖螳壹&繧後k OEM繧ウ繝シ繝(SBCS縺セ縺溘ッDBCS)縺ョ譁蟄怜励→縺励※謇ア繧上l縺セ縺吶ゅヵ繧。繧、繝ォ蜷榊・蜃コ蜉帙rUnicode縺ィ縺吶k讒区(LFN讒区舌〒縲√°縺、_LFN_UNICODE繧 1)縺ォ縺励◆縺ィ縺阪ッ縲XCHAR縺ッ繝ッ繧、繝画枚蟄(unsigned short)縺ォ蛻繧頑崛繧上j縲√ヱ繧ケ蜷阪↓Unicode繧剃スソ逕ィ縺吶k繧医≧縺ォ縺ェ繧翫∪縺吶ゅ%繧後↓繧医j LFN繝輔Ν蟇セ蠢懊→縺ェ繧翫^EM繧ウ繝シ繝峨↓縺ェ縺譁蟄(縺溘→縺医ー 笨昶亂笨。笘ク笘ュ縺ェ縺ゥ)繧ゆスソ逕ィ縺ァ縺阪∪縺吶

+

繝輔ぃ繧、繝ォ髢「謨ー縺ョ蜈・蜃コ蜉帙ョ縺縺。繝輔ぃ繧、繝ォ蜷阪d繝代せ蜷阪r謖螳壹☆繧句シ墓焚縺ョ蝙九ッ縲TCHAR縺ァ螳夂セゥ縺輔l縺ヲ縺縺セ縺吶′縲√%繧後ッchar縺ョ繧ィ繝ェ繧「繧ケ縺ォ縺ェ縺」縺ヲ縺縺セ縺吶ゅ◎縺励※縲_CODE_PAGE縺ァ謖螳壹&繧後k ANSI/OEM繧ウ繝シ繝(SBCS縺セ縺溘ッDBCS)縺ョ譁蟄怜励→縺励※謇ア繧上l縺セ縺吶ゅヵ繧。繧、繝ォ蜷榊・蜃コ蜉帙rUnicode縺ィ縺吶k讒区(LFN讒区舌〒縲√°縺、_LFN_UNICODE繧 1)縺ォ縺励◆縺ィ縺阪ッ縲TCHAR縺ッ繝ッ繧、繝画枚蟄(unsigned short)縺ォ蛻繧頑崛繧上j縲√ヱ繧ケ蜷阪↓Unicode繧剃スソ逕ィ縺吶k繧医≧縺ォ縺ェ繧翫∪縺吶ゅ%繧後↓繧医j LFN繝輔Ν蟇セ蠢懊→縺ェ繧翫、NSI/OEM繧ウ繝シ繝峨↓縺ェ縺譁蟄(縺溘→縺医ー 笨昶亂笨。笘ク笘ュ縺ェ縺ゥ)繧ゆスソ逕ィ縺ァ縺阪∪縺吶ゅ%縺ョ險ュ螳壹ッ譁蟄怜怜・蜃コ蜉幃未謨ー縺ョ繝繝シ繧ソ蝙九→繧ィ繝ウ繧ウ繝シ繝繧」繝ウ繧ー縺ォ繧ょスア髻ソ繧剃ク弱∴縺セ縺吶ゅΜ繝繝ゥ繝ォ譁蟄怜励r螳夂セゥ縺吶k縺ィ縺阪∵ャ。縺ォ遉コ縺吶h縺縺ォ_T(s)縺翫h縺ウ_TEXT(s)繝槭け繝ュ繧剃スソ縺」縺ヲANSI/OEM縺ィUnicode繧定ェ蜍募繧頑崛縺医☆繧九%縺ィ縺後〒縺阪∪縺吶

+
+ f_open(fp, "filename.txt", FA_READ);      /* ANSI/OEM蟆ら畑繧ウ繝シ繝 */
+ f_open(fp, L"filename.txt", FA_READ);     /* Unicode蟆ら畑繧ウ繝シ繝 */
+ f_open(fp, _T("filename.txt"), FA_READ);  /* 荳。逕ィ繧ウ繝シ繝 */
+


隲也炊繝峨Λ繧、繝(繝懊Μ繝・繝シ繝)縺ィ迚ゥ逅繝峨Λ繧、繝(繝繧」繧ケ繧ッ陬鄂ョ)縺ョ蟇セ蠢

-

繝繝輔か繝ォ繝医ョ讒区舌〒縺ッ縲√◎繧後◇繧後ョ隲也炊繝峨Λ繧、繝悶ッ蜷後§逡ェ蜿キ縺ョ迚ゥ逅繝峨Λ繧、繝悶↓1:1縺ァ邨舌ウ縺、縺代i繧後※縺縺ヲ縲∫黄逅繝峨Λ繧、繝悶ョ蜈磯ュ縺ョ蛹コ逕サ縺後槭え繝ウ繝医&繧後∪縺吶_MULTI_PARTITION縺ォ 1繧呈欠螳壹☆繧九→縲∬ォ也炊繝峨Λ繧、繝悶↓蟇セ縺励※蛟句挨縺ォ迚ゥ逅繝峨Λ繧、繝也分蜿キ繝サ蛹コ逕サ繧呈欠螳壹〒縺阪k繧医≧縺ォ縺ェ繧翫∪縺吶ゅ%縺ョ讒区舌〒縺ッ縲∬ォ也炊繝峨Λ繧、繝悶→蛹コ逕サ縺ョ蟇セ蠢懊r隗」豎コ縺吶k縺溘a縺ョ繝繝シ繝悶Ν繧呈ャ。縺ォ遉コ縺吶h縺縺ォ螳夂セゥ縺吶k蠢隕√′縺ゅj縺セ縺吶

+

繝繝輔か繝ォ繝医ョ讒区舌〒縺ッ縲√◎繧後◇繧後ョ隲也炊繝峨Λ繧、繝悶ッ蜷後§逡ェ蜿キ縺ョ迚ゥ逅繝峨Λ繧、繝悶↓1:1縺ァ邨舌ウ縺、縺代i繧後※縺縺ヲ縲∫黄逅繝峨Λ繧、繝悶ョ蜈磯ュ縺ョ蛹コ逕サ縺ォ縺ゅk繝懊Μ繝・繝シ繝縺後槭え繝ウ繝医&繧後∪縺吶_MULTI_PARTITION縺ォ 1繧呈欠螳壹☆繧九→縲∝九縺ョ隲也炊繝峨Λ繧、繝悶↓蟇セ縺励※蛟句挨縺ォ迚ゥ逅繝峨Λ繧、繝也分蜿キ繝サ蛹コ逕サ繧呈欠螳壹〒縺阪k繧医≧縺ォ縺ェ繧翫∪縺吶ゅ%縺ョ讒区舌〒縺ッ縲∬ォ也炊繝峨Λ繧、繝悶→蛹コ逕サ縺ョ蟇セ蠢懊r隗」豎コ縺吶k縺溘a縺ョ繝繝シ繝悶Ν繧呈ャ。縺ォ遉コ縺吶h縺縺ォ螳夂セゥ縺吶k蠢隕√′縺ゅj縺セ縺吶

 萓:隲也炊繝峨Λ繧、繝0ス2繧堤黄逅繝峨Λ繧、繝0(蝗コ螳壹ョ繧」繧ケ繧ッ)縺ョ3縺、縺ョ蝓コ譛ャ蛹コ逕サ縺ォ蜑イ繧雁ス薙※縲
    隲也炊繝峨Λ繧、繝3繧堤黄逅繝峨Λ繧、繝1(繝ェ繝繝シ繝舌ヶ繝ォ繝サ繝繧」繧ケ繧ッ)縺ォ蜑イ繧雁ス薙※繧句エ蜷医
 
 const PARTITION Drives[] = {
-    {0, 0},     /* Logical drive 0 ==> Physical drive 0, 1st partition */
-    {0, 1},     /* Logical drive 1 ==> Physical drive 0, 2nd partition */
-    {0, 2},     /* Logical drive 2 ==> Physical drive 0, 3rd partition */
-    {1, 0}      /* Logical drive 3 ==> Physical drive 1 */
+    {0, 0},     /* Logical drive 0 ==> Physical drive 0, 1st partition */
+    {0, 1},     /* Logical drive 1 ==> Physical drive 0, 2nd partition */
+    {0, 2},     /* Logical drive 2 ==> Physical drive 0, 3rd partition */
+    {1, 0}      /* Logical drive 3 ==> Physical drive 1 */
 };
 

隍謨ー蛹コ逕サ謖螳壹r菴ソ逕ィ縺吶k蝣エ蜷医∵ャ。縺ョ轤ケ縺ォ豕ィ諢上@縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲 diff --git a/doc/ja/forward.html b/doc/ja/forward.html index b49f470..8eebaf7 100644 --- a/doc/ja/forward.html +++ b/doc/ja/forward.html @@ -4,6 +4,7 @@ + FatFs - f_forward @@ -15,10 +16,10 @@

ファイルからデータを読み出し、送信ストリームに直接転送します。

 FRESULT f_forward (
-  FIL* FileObject,                 /* ファイル・オブジェクト構造体 */
-  UINT (*Func)(const BYTE*,UINT),  /* データ転送関数 */
-  UINT ByteToFwd,                  /* 転送するバイト数 */
-  UINT* ByteFwd                    /* 転送されたバイト数 */
+  FIL* FileObject,                 /* ファイル・オブジェクト構造体 */
+  UINT (*Func)(const BYTE*,UINT),  /* データ転送関数 */
+  UINT ByteToFwd,                  /* 転送するバイト数 */
+  UINT* ByteFwd                    /* 転送されたバイト数 */
 );
 
@@ -72,26 +73,26 @@ FRESULT f_forward (

使用例(オーディオ再生)

-/*-----------------------------------------------------------------------*/
-/* f_forward関数から呼ばれるデータ送信関数の例                           */
-/*-----------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------*/
+/* f_forward関数から呼ばれるデータ送信関数の例                           */
+/*-----------------------------------------------------------------------*/
 
-UINT out_stream (   /* 戻り値: 転送されたバイト数またはストリームの状態 */
-    const BYTE *p,  /* 転送するデータを指すポインタ */
-    UINT btf        /* >0: 転送を行う(バイト数). 0: ストリームの状態を調べる */
+UINT out_stream (   /* 戻り値: 転送されたバイト数またはストリームの状態 */
+    const BYTE *p,  /* 転送するデータを指すポインタ */
+    UINT btf        /* >0: 転送を行う(バイト数). 0: ストリームの状態を調べる */
 )
 {
     UINT cnt = 0;
 
 
-    if (btf == 0) {     /* センス要求 */
-        /* ストリームの状態を返す (0: ビジー, 1: レディ) */
-        /* 一旦、レディを返したら、続く転送要求で少なくとも1バイトは */
-        /* 転送されないと f_forward関数は FR_RW_ERROR となる。 */
+    if (btf == 0) {     /* センス要求 */
+        /* ストリームの状態を返す (0: ビジー, 1: レディ) */
+        /* 一旦、レディを返したら、続く転送要求で少なくとも1バイトは */
+        /* 転送されないと f_forward関数は FR_RW_ERROR となる。 */
         if (FIFO_READY) cnt = 1;
     }
-    else {              /* 転送要求 */
-        do {    /* 全てのバイトを転送するか、ストリームがビジーになるまで繰り返す */
+    else {              /* 転送要求 */
+        do {    /* 全てのバイトを転送するか、ストリームがビジーになるまで繰り返す */
             FIFO_PORT = *p++;
             cnt++;
         } while (cnt < btf && FIFO_READY);
@@ -101,31 +102,34 @@ UINT out_stream (   /* 
 }
 
 
-/*-----------------------------------------------------------------------*/
-/* f_forward関数の使用例                                                 */
-/*-----------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------*/
+/* f_forward関数の使用例                                                 */
+/*-----------------------------------------------------------------------*/
 
 FRESULT play_file (
-    char *fn        /* 再生するオーディオ・ファイル名を指すポインタ */
+    char *fn        /* 再生するオーディオ・ファイル名を指すポインタ */
 )
 {
     FRESULT rc;
     FIL fil;
     UINT dmy;
 
-    /* ファイルを読み出しモードで開く */
+    /* ファイルを読み出しモードで開く */
     rc = f_open(&fil, fn, FA_READ);
+    if (rc) return rc;
 
-    /* 全てのデータが転送されるかエラーが発生するまで続ける */
+    /* 全てのデータが転送されるかエラーが発生するまで続ける */
     while (rc == FR_OK && fil.fptr < fil.fsize) {
 
-        /* ほかの処理... */
+        /* ほかの処理... */
 
-        /* 定期的または要求に応じてデータをストリームに送出する */
+        /* 定期的または要求に応じてデータをストリームに送出する */
         rc = f_forward(&fil, out_stream, 1000, &dmy);
     }
 
-    return rc;	/* FR_OK: 正常終了, ほか:異常終了 */
+    /* ファイルを閉じて戻る */
+    f_close(&fil);
+    return rc;	
 }
 
diff --git a/doc/ja/getfree.html b/doc/ja/getfree.html index 2286e21..c8d5963 100644 --- a/doc/ja/getfree.html +++ b/doc/ja/getfree.html @@ -4,6 +4,7 @@ + FatFs - f_getfree @@ -15,9 +16,9 @@

論理ドライブ上の未使用クラスタ数を得ます。

 FRESULT f_getfree (
-  const XCHAR* Path,       /* 対象ドライブのルート・ディレクトリ */
-  DWORD* Clusters,         /* 空きクラスタ数を格納する変数へのポインタ */
-  FATFS** FileSystemObject /* ファイル・システム・オブジェクトを指すポインタへのポインタ */
+  const TCHAR* Path,       /* 対象ドライブを指定します */
+  DWORD* Clusters,         /* 空きクラスタ数を格納する変数へのポインタ */
+  FATFS** FileSystemObject /* ファイル・システム・オブジェクトを指すポインタへのポインタ */
 );
 
@@ -26,7 +27,7 @@ FRESULT f_getfree (

引数

Path
-
対象の論理ドライブのルートディレクトリのパス名が入った'\0'で終わる文字列へのポインタを指定します。
+
調べる対象の論理ドライブを示すパス名が入った'\0'で終わる文字列へのポインタを指定します。
Clusters
空きクラスタ数を格納するDWORD変数へのポインタを指定します。
FileSystemObject
@@ -51,14 +52,14 @@ FRESULT f_getfree (
FR_NOT_ENABLED
その論理ドライブにワーク・エリアが与えられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATパーテーションが見つからない。
+
有効なFATボリュームが見つからない。

解説

-

論理ドライブ上の空きクラスタ数を取得します。返されたファイル・システム・オブジェクトのcsizeメンバがクラスタあたりのセクタ数を示しているので、これを元に実際の空きサイズが計算できます。FAT32ボリュームにおいては、FSINFOの状態によっては不正確な値を返したり、処理に時間がかかったりする可能性があります。

+

論理ドライブ上の空きクラスタ数を取得します。返されたファイル・システム・オブジェクトのcsizeメンバがクラスタあたりのセクタ数を示しているので、これを元に実際の空きサイズが計算できます。FAT32ボリュームにおいては、FSINFOセクタの状態によっては不正確な値を返したり、処理に時間がかかったりする可能性があります。

@@ -75,15 +76,15 @@ FRESULT f_getfree ( DWORD fre_clust, fre_sect, tot_sect; - /* Get drive information and free clusters */ - res = f_getfree("/", &fre_clust, &fs); + /* ドライブ1のボリューム情報と空きクラスタ数を得る */ + res = f_getfree("1:", &fre_clust, &fs); if (res) die(res); - /* Get total sectors and free sectors */ + /* 全セクタ数と空きセクタ数を計算 */ tot_sect = (fs->max_clust - 2) * fs->csize; fre_sect = fre_clust * fs->csize; - /* Print free space in unit of KB (assuming 512B/sector) */ + /* ドライブサイズと空きサイズの表示 (512バイト/セクタと仮定) */ printf("%lu KB total drive space.\n" "%lu KB available.\n", fre_sect / 2, tot_sect / 2); diff --git a/doc/ja/gets.html b/doc/ja/gets.html index d0c8b57..3cb309e 100644 --- a/doc/ja/gets.html +++ b/doc/ja/gets.html @@ -4,6 +4,7 @@ + FatFs - f_gets @@ -14,10 +15,10 @@

f_gets

ファイルから文字列を読み出します。

-char* f_gets (
-  char* Str,        /* バッファ */
-  int Size,         /* バッファのサイズ */
-  FIL* FileObject   /* ファイル・オブジェクト */
+TCHAR* f_gets (
+  TCHAR* Str,       /* バッファ */
+  int Size,         /* バッファのサイズ */
+  FIL* FileObject   /* ファイル・オブジェクト */
 );
 
@@ -28,7 +29,7 @@ char* f_gets (
Str
文字列を読み出すバッファを指すポインタを指定します。
Size
-
バッファのサイズを指定します。
+
バッファのサイズを要素数で指定します。
FileObject
ファイル・オブジェクト構造体へのポインタを指定します。
@@ -43,7 +44,8 @@ char* f_gets (

解説

-

この関数はf_read()のラッパー関数です。読み出し動作は、最初の'\n'を読み込むか、ファイル終端に達するか、Size - 1文字を読み出すまで続きます。読み込まれた文字列の終端には'\0'が付加されます。既にファイル終端で1文字も読み込まれなかったとき、または何らかのエラーが発生したときはNULLを返します。ファイル終端かエラーかはf_eof(),f_error()マクロで調べられます。

+

この関数はf_read()のラッパー関数です。読み出し動作は、最初の'\n'を読み込むか、ファイル終端に達するか、Size - 1文字を読み出すまで続きます。読み込まれた文字列の終端には'\0'が付加されます。既にファイル終端で1文字も読み込まれなかったとき、または何らかのエラーが発生したときは関数は失敗しヌル・ポインタを返します。ファイル終端かエラーかはf_eof(),f_error()マクロで調べられます。

+

APIにUnicodeが選択されている(_LFN_UNICODEが1)ときは、UTF-8エンコードのテキスト・ファイルとしてUCS-2に変換してバッファに読み込みます。それ以外の時は無変換(1文字1バイト)で読み込みます。

diff --git a/doc/ja/lseek.html b/doc/ja/lseek.html index 9cb9f50..7389479 100644 --- a/doc/ja/lseek.html +++ b/doc/ja/lseek.html @@ -4,6 +4,7 @@ + FatFs - f_lseek @@ -12,11 +13,11 @@

f_lseek

-

ファイルのR/Wポインタを移動します。

+

ファイルのリード/ライト・ポインタを移動します。

 FRESULT f_lseek (
-  FIL* FileObject,   /* ファイル・オブジェクト構造体へのポインタ */
-  DWORD Offset       /* 移動先オフセット */
+  FIL* FileObject,    /* ファイル・オブジェクト構造体へのポインタ */
+  DWORD Offset        /* 移動先オフセット */
 );
 
@@ -27,7 +28,7 @@ FRESULT f_lseek (
FileObject
対象となるファイル・オブジェクト構造体へのポインタを指定します。
Offset
-
移動先のオフセット(R/Wポインタ)値。ファイル先頭からのオフセットをバイト単位で指定します。
+
移動先のオフセット(リード/ライト・ポインタ)値。ファイル先頭からのオフセットをバイト単位で指定します。
@@ -45,17 +46,20 @@ FRESULT f_lseek (
メディアがセットされていないなど、物理ドライブが動作不能状態。
FR_INVALID_OBJECT
無効なファイル・オブジェクト。
+
FR_NOT_ENOUGH_CORE
+
リンク・マップ・テーブルのサイズが不足。

解説

-

ファイルR/Wポインタ(ファイル・オブジェクト内のfptrメンバで、次に読み出し・書き込みされるバイトのオフセットを示す)を移動します。オフセットの原点はファイル先頭からです。書き込みモードでファイル・サイズより大きな値を指定すると、そこまでファイルが拡張され、拡張された部分のデータは未定義となります。データを遅延無く高速に書き込みたいときは、予めこの関数で必要なサイズまでファイル・サイズを拡張しておくと良いでしょう。f_lseek関数が正常終了したあとは、ファイルR/Wポインタが正しく移動したかfptrをチェックするべきです。ファイルR/Wポインタが指定より小さいときは、次の原因が考えられます。

+

ファイルのリード/ライト・ポインタ(ファイル・オブジェクト内のfptrメンバで、次に読み出し・書き込みされるバイトのオフセットを示す)を移動します。オフセットの原点はファイル先頭です。書き込みモードでファイル・サイズより大きな値を指定すると、そこまでファイル・サイズが拡張され、拡張された部分のデータは未定義となります。データを遅延無く高速に書き込みたいときは、予めこの関数で必要なサイズまでファイル・サイズを拡張しておくと良いでしょう。f_lseek関数が正常終了したあとは、リード/ライト・ポインタが正しく移動したかfptrをチェックするべきです。リード/ライト・ポインタが指定より小さいときは、次の原因が考えられます。

+

_USE_FASTSEEKに1が指定されていて、且つファイル・オブジェクトのcltblメンバがNULL以外のとき、高速シーク・モードになります。これはファイルのクラスタ情報をアプリケーションの指定した配列に保持しておくことにより、FATにアクセスすることなく後方シークやロング・シークを高速に行う機能です。高速シーク動作を行う前には、配列を初期化しておく必要があります。必要な配列サイズ(要素数)は、(ファイルの分割数 + 1) * 2 です。たとえば、ファイルが5つに分断されているときに必要な配列サイズは、12要素となります。高速シーク使用時はファイル・サイズの拡張はできません。

@@ -68,35 +72,48 @@ FRESULT f_lseek (

使用例

-    /* オフセット5000へ移動 */
-    res = f_lseek(&file, 5000);
+    /* ファイル・オフセット5000へ移動 */
+    res = f_lseek(&file, 5000, 0);
 
-    /* ファイル追記の準備 (ファイル終端へ移動) */
-    res = f_lseek(&file, file.fsize);
+    /* ファイル追記の準備 (ファイル終端へ移動) */
+    res = f_lseek(&file, file.fsize, 0);
 
-    /* 3000バイト進める */
-    res = f_lseek(&file, file.fptr + 3000);
+    /* 3000バイト進める */
+    res = f_lseek(&file, file.fptr + 3000, 0);
 
-    /* 2000バイト戻す (オーバーフローに注意) */
-    res = f_lseek(&file, file.fptr - 2000);
+    /* 2000バイト戻す (オーバーフローに注意) */
+    res = f_lseek(&file, file.fptr - 2000, 0);
 
-    /* クラスタ先行割り当て (ストリーミング・ライト時のバッファ・オーバーラン防止) */
+    /* クラスタ先行割り当て (ストリーミング・ライト時のバッファ・オーバーラン防止) */
 
-    res = f_open(&file, "record.wav", FA_CREATE_NEW | FA_WRITE); /* ファイル作成 */
+    res = f_open(&file, "record.wav", FA_CREATE_NEW | FA_WRITE); /* ファイル作成 */
 
-    res = f_lseek(&file, MAX_SIZE);        /* 十分なクラスタの先行割り当て */
-    if (res || file.fptr != PRE_SIZE) .... /* 正しくファイルが拡張されたかチェック */
+    res = f_lseek(&file, MAX_SIZE, 0);     /* 十分なクラスタの先行割り当て */
+    if (res || file.fptr != PRE_SIZE) .... /* 正しくファイルが拡張されたかチェック */
 
-    res = f_lseek(&file, DATA_START);      /* データ・ストリームの記録(アロケーションディレイ無し) */
+    res = f_lseek(&file, DATA_START, 0);   /* データ・ストリームの記録(アロケーションディレイ無し) */
     ...
 
-    res = f_truncate(&file);              /* 不要領域の切り捨て */
-    res = f_lseek(&file, 0);              /* ヘッダの記録 */
+    res = f_truncate(&file);               /* 不要領域の切り捨て */
+    res = f_lseek(&file, 0, 0);            /* ヘッダの記録 */
     ...
 
     res = f_close(&file);
 
+
+    /* 高速シーク機能を使う */
+
+    DWORD lktbl[SZ_TBL];                   /* リンク・マップ・テーブル格納バッファ */
+
+    res = f_lseek(&file, ofs1);            /* 通常シーク (オープン時は file.cltbl == NULL) */
+
+    file.cltbl = lktbl;                    /* 高速シーク機能の有効化 */
+    lktbl[0] = SZ_TBL;                     /* 先頭要素に配列要素数をセット */
+    res = f_lseek(&file, CREATE_LINKMAP);  /* リンク・マップ・テーブルの作成 */
+
+    res = f_lseek(&file, ofs2);            /* 高速シーク (file.cltbl != NULL) */
+
diff --git a/doc/ja/mkdir.html b/doc/ja/mkdir.html index d30e396..3a60a25 100644 --- a/doc/ja/mkdir.html +++ b/doc/ja/mkdir.html @@ -4,6 +4,7 @@ + FatFs - f_mkdir @@ -15,7 +16,7 @@

ディレクトリを作成します。

 FRESULT f_mkdir (
-  const XCHAR* DirName /* 作成するディレクトリ名へのポインタ */
+  const TCHAR* DirName /* 作成するディレクトリ名へのポインタ */
 );
 
@@ -55,7 +56,7 @@ FRESULT f_mkdir (
FR_NOT_ENABLED
その論理ドライブにワーク・エリアが与えられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
diff --git a/doc/ja/mkfs.html b/doc/ja/mkfs.html index 2a63055..4f3bdde 100644 --- a/doc/ja/mkfs.html +++ b/doc/ja/mkfs.html @@ -4,6 +4,7 @@ + FatFs - f_mkfs @@ -15,9 +16,9 @@

ドライブ上にFATファイル・システムを作成(フォーマット)します。

 FRESULT f_mkfs (
-  BYTE  Drive,              /* 論理ドライブ番号 */
-  BYTE  PartitioningRule,   /* 区画作成方法 */
-  WORD  AllocSize           /* クラス・タサイズ */
+  BYTE  Drive,              /* 論理ドライブ番号 */
+  BYTE  PartitioningRule,   /* 区画作成方法 */
+  UINT  AllocSize           /* クラス・タサイズ */
 );
 
@@ -28,9 +29,9 @@ FRESULT f_mkfs (
Drive
フォーマットする論理ドライブ(0-9)。
PartitioningRule
-
0を指定すると、ドライブの全領域を占める基本DOS区画を作成したあとその区画にファイル・システムを作成します(FDISKフォーマット)。1を指定すると、区画テーブルを作成せずドライブの先頭セクタから直接ファイル・システムを作成します(super floppy (SFD) フォーマット)。
+
0を指定すると、ドライブの全領域を占める基本DOS区画を作成したあと、その区画にファイル・システムを作成します(FDISKフォーマット)。1を指定すると、区画テーブルを作成せず物理ドライブの先頭セクタから直接ファイル・システムを作成します(super floppy (SFD) フォーマット)。
AllocSize
-
クラスタ・サイズをバイト単位で指定します。0または512〜32768の範囲でかつ2の累乗でなければなりません。0を指定するとドライブ・サイズに応じたデフォルトのクラスタ・サイズを選択します。FAT64(64KB/クラスタ)は選択できません。
+
クラスタ・サイズをバイト単位で指定します。2の累乗、且つセクタ・サイズ以上、且つセクタ・サイズの128倍以下でなければなりません。無効な値を指定した場合、ドライブ・サイズに応じたデフォルトのクラスタ・サイズが選択されます。特に指定しない場合は、0を指定して自動選択とします。
@@ -63,7 +64,7 @@ FRESULT f_mkfs (

説明

f_mkfs関数はFATファイル・システムをドライブ上に作成します。リムーバブル・メディアのパーテーショニング・ルールとしてはFDISK形式とSFD形式があり、メモリ・カードではFDISK形式が普通です。この関数は複数区画には対応していないので、その物理ドライブの既存の区画は全て削除され、全体が一つの区画になります。

-

FATタイプ(FAT12/FAT16/FAT32)は、その論理ドライブ上のクラスタ数によってのみ決定される[FAT仕様書より]決まりになっていて、それ以外の要因はありません。したがって、どのFATタイプになるかはドライブ・サイズと指定されたクラスタ・サイズに依存します。クラスタ・サイズは大きくするほど性能が上がり、逆にディスク利用効率は落ちます。

+

FATタイプ(FAT12/FAT16/FAT32)は、その論理ドライブ上のクラスタ数によってのみ決定される決まり[FAT仕様書より]になっていて、それ以外の要因はありません。したがって、どのFATタイプになるかはドライブ・サイズとクラスタ・サイズに依存します。クラスタ・サイズは大きくするほど性能が上がり、逆にディスク利用効率は落ちます。

diff --git a/doc/ja/mount.html b/doc/ja/mount.html index 250f798..6139527 100644 --- a/doc/ja/mount.html +++ b/doc/ja/mount.html @@ -4,6 +4,7 @@ + FatFs - f_mount @@ -12,11 +13,11 @@

f_mount

-

論理ドライブ(ボリューム)のワーク・エリアを登録・抹消します。

+

論理ドライブのワーク・エリアを登録・抹消します。

 FRESULT f_mount (
-  BYTE  Drive,               /* 論理ドライブ番号 */
-  FATFS*  FileSystemObject   /* ワーク・エリアへのポインタ */
+  BYTE  Drive,               /* 論理ドライブ番号 */
+  FATFS*  FileSystemObject   /* ワーク・エリアへのポインタ */
 );
 
@@ -37,15 +38,15 @@ FRESULT f_mount (
FR_OK (0)
正常終了。
FR_INVALID_DRIVE
-
ドライブ番号が無効。
+
論理ドライブ番号が無効。

解説

-

FatFsモジュールではそれぞれの論理ドライブにファイル・システム・オブジェクトというワーク・エリアが必要です。この関数は論理ドライブにそのワーク・エリアを登録したり抹消したりします。何らかのファイル関数を使用する前にこの関数でその論理ドライブのワーク・エリアを与えておかなければなりません。FileSystemObjectにヌル・ポインタを指定するとその論理ドライブのワーク・エリアの登録は抹消され、登録されていたワーク・エリアは破棄できます。

-

この関数内では物理ドライブへのアクセスは発生せず、ワーク・エリアを初期化して内部配列にそのアドレスを登録するだけです。実際のマウント動作は、f_mount()またはメディア交換後、最初のファイル・アクセスのときに行われます。

+

FatFsモジュールではそれぞれの論理ドライブにファイル・システム・オブジェクトというワーク・エリアが必要です。この関数は論理ドライブにそのワーク・エリアを登録したり抹消したりします。何らかのファイル関数を使用する前にこの関数でその論理ドライブのワーク・エリアを与えておかなければなりません。FileSystemObjectにヌル・ポインタを指定するとその論理ドライブのワーク・エリアの登録は抹消され、登録されていたワーク・エリアは破棄できます。操作対象のドライブに対して開かれているファイルやディレクトリがあった場合、それらは全て無効になります。

+

この関数内では下位レイヤ(物理ドライブ)へのアクセスは発生せず、ワーク・エリアを初期化して内部配列にそのアドレスを登録するだけです。実際のマウント動作は、f_mount()またはメディア交換後、最初のファイル・アクセスのときに行われます。

diff --git a/doc/ja/open.html b/doc/ja/open.html index f9b25e6..13dabc8 100644 --- a/doc/ja/open.html +++ b/doc/ja/open.html @@ -4,6 +4,7 @@ + FatFs - f_open @@ -15,9 +16,9 @@

ファイルをオープンまたは作成します。

 FRESULT f_open (
-  FIL* FileObject,       /* 空のファイル・オブジェクト構造体へのポインタ */
-  const XCHAR* FileName, /* ファイルのフルパス名へのポインタ */
-  BYTE ModeFlags         /* モードフラグ */
+  FIL* FileObject,       /* 空のファイル・オブジェクト構造体へのポインタ */
+  const TCHAR* FileName, /* ファイルのフルパス名へのポインタ */
+  BYTE ModeFlags         /* モードフラグ */
 );
 
@@ -36,7 +37,7 @@ FRESULT f_open ( FA_READ読み出しモードで開きます。読み書きする場合はFA_WRITEと共に指定します。 FA_WRITE書き込みモードで開きます。読み書きする場合はFA_READと共に指定します。 FA_OPEN_EXISTING既存のファイルを開きます。ファイルが無いときはエラーになります。(デフォルト) -FA_OPEN_ALWAYS既存のファイルを開きます。ファイルが無いときはファイルを作成します。 +FA_OPEN_ALWAYS既存のファイルを開きます。ファイルが無いときはファイルを作成します。追記する場合は、この方法でオープンした後、f_lseek()でファイルの最後尾に移動してください。 FA_CREATE_NEWファイルを作成します。同名のファイルがある場合は、エラーになります。 FA_CREATE_ALWAYSファイルを作成します。同名のファイルがある場合は、サイズを0にしてから開きます。 @@ -73,7 +74,9 @@ FRESULT f_open (
FR_NOT_ENABLED
その論理ドライブにワーク・エリアが割り当てられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
+
FR_LOCKED
+
ファイル共有機能によるアクセス拒否。
@@ -96,37 +99,37 @@ FRESULT f_open (
 void main (void)
 {
-    FATFS fs[2];         /* 論理ドライブのワーク・エリア(ファイル・システム・オブジェクト) */
-    FIL fsrc, fdst;      /* ファイル・オブジェクト */
-    BYTE buffer[4096];   /* file copy buffer */
-    FRESULT res;         /* FatFs function common result code */
-    UINT br, bw;         /* File R/W count */
+    FATFS fs[2];         /* 論理ドライブのワーク・エリア(ファイル・システム・オブジェクト) */
+    FIL fsrc, fdst;      /* ファイル・オブジェクト */
+    BYTE buffer[4096];   /* file copy buffer */
+    FRESULT res;         /* FatFs function common result code */
+    UINT br, bw;         /* File R/W count */
 
-    /* ドライブ0,1にワーク・エリアを与える */
+    /* ドライブ0,1にワーク・エリアを与える */
     f_mount(0, &fs[0]);
     f_mount(1, &fs[1]);
 
-    /* ドライブ1のソース・ファイルを開く */
+    /* ドライブ1のソース・ファイルを開く */
     res = f_open(&fsrc, "1:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
     if (res) die(res);
 
-    /* ドライブ0にデスティネーション・ファイルを作成する */
+    /* ドライブ0にデスティネーション・ファイルを作成する */
     res = f_open(&fdst, "0:dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
     if (res) die(res);
 
-    /* ソースからデスティネーションにコピーする */
+    /* ソースからデスティネーションにコピーする */
     for (;;) {
         res = f_read(&fsrc, buffer, sizeof(buffer), &br);
-        if (res || br == 0) break;   /* エラーかファイル終端 */
+        if (res || br == 0) break;   /* エラーかファイル終端 */
         res = f_write(&fdst, buffer, br, &bw);
-        if (res || bw < br) break;   /* エラーかディスク満杯 */
+        if (res || bw < br) break;   /* エラーかディスク満杯 */
     }
 
-    /* 全てのファイルを閉じる */
+    /* 全てのファイルを閉じる */
     f_close(&fsrc);
     f_close(&fdst);
 
-    /* ワーク・エリアを開放する */
+    /* ワーク・エリアを開放する */
     f_mount(0, NULL);
     f_mount(1, NULL);
 }
diff --git a/doc/ja/opendir.html b/doc/ja/opendir.html
index 60dfdf4..e2bf377 100644
--- a/doc/ja/opendir.html
+++ b/doc/ja/opendir.html
@@ -4,6 +4,7 @@
 
 
 
+
 
 FatFs - f_opendir
 
@@ -15,8 +16,8 @@
 

ディレクトリを開きます。

 FRESULT f_opendir (
-  DIR* DirObject,       /* ディレクトリ・ブジェクト構造体へのポインタ */
-  const XCHAR* DirName  /* ディレクトリ名へのポインタ */
+  DIR* DirObject,       /* ディレクトリ・ブジェクト構造体へのポインタ */
+  const TCHAR* DirName  /* ディレクトリ名へのポインタ */
 );
 
@@ -42,7 +43,7 @@ FRESULT f_opendir (
FR_INVALID_NAME
パス名が不正。
FR_INVALID_DRIVE
-
ドライブ番号が不正。
+
論理ドライブ番号が不正。
FR_NOT_READY
メディアがセットされていないなど、物理ドライブが動作不能状態。
FR_DISK_ERR
@@ -52,7 +53,7 @@ FRESULT f_opendir (
FR_NOT_ENABLED
論理ドライブにワーク・エリアが与えられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
diff --git a/doc/ja/printf.html b/doc/ja/printf.html index 911be13..f7ff1a7 100644 --- a/doc/ja/printf.html +++ b/doc/ja/printf.html @@ -4,6 +4,7 @@ + FatFs - f_printf @@ -15,8 +16,8 @@

ファイルに書式化文字列を書き込みます。

 int f_printf (
-  FIL* FileObject,     /* ファイル・オブジェクト */
-  const char* Foramt,  /* 書式制御文字列 */
+  FIL* FileObject,      /* ファイル・オブジェクト */
+  const TCHAR* Foramt,  /* 書式制御文字列 */
   ...
 );
 
@@ -38,7 +39,7 @@ int f_printf (

戻り値

-

文字列が正常に書き込まれると書き込んだ文字数が返されます。ディスクが満杯またはその他エラーにより正常に書き込まれなかったときはEOF(-1)が返されます。

+

文字列が正常に書き込まれると書き込まれた文字数が返されます。ディスクが満杯またはその他エラーにより正常に書き込まれなかったときは関数は失敗しEOF (-1)が返されます。

@@ -46,8 +47,8 @@ int f_printf (

解説

この関数はf_putc()およびf_puts()のラッパー関数です。書式制御機能はサブセットとなっていて、書式制御文字は次に示すものが使用可能です。

@@ -56,18 +57,19 @@ int f_printf (

対応情報

_FS_READONLY == 0で、且つ_USE_STRFUNCが 1または 2のとき使用可能になります。2の時は、出力に含まれる'\n'"\r\n"に展開されてファイルに書き込まれます。

+

APIにUnicodeが選択されている(_LFN_UNICODEが1)ときは、UTF-8エンコードでファイルに書き込みます。それ以外の時は無変換(1文字1バイト)で書き込みます。

使用例

-    f_printf(&fil, "%6d", -200);         // "  -200"
-    f_printf(&fil, "%02u", 5);           // "05"
-    f_printf(&fil, "%ld", 12345678L);    // "12345678"
-    f_printf(&fil, "%08lX", 1194684UL);  // "00123ABC"
-    f_printf(&fil, "%s", "String");      // "String"
-    f_printf(&fil, "%c", 'a');           // "a"
+    f_printf(&fil, "%6d", -200);         /* "  -200" */
+    f_printf(&fil, "%02u", 5);           /* "05" */
+    f_printf(&fil, "%ld", 12345678L);    /* "12345678" */
+    f_printf(&fil, "%08lX", 1194684UL);  /* "00123ABC" */
+    f_printf(&fil, "%s", "String");      /* "String" */
+    f_printf(&fil, "%c", 'a');           /* "a" */
 
diff --git a/doc/ja/putc.html b/doc/ja/putc.html index 53f8935..8abefb9 100644 --- a/doc/ja/putc.html +++ b/doc/ja/putc.html @@ -4,6 +4,7 @@ + FatFs - f_putc @@ -15,8 +16,8 @@

ファイルに文字を書き込みます。

 int f_putc (
-  int Chr,          /* 書き込む文字 */
-  FIL* FileObject   /* ファイル・オブジェクト */
+  TCHAR Chr,        /* 書き込む文字 */
+  FIL* FileObject   /* ファイル・オブジェクト */
 );
 
@@ -34,7 +35,8 @@ int f_putc (

戻り値

-

文字が正常に書き込まれると書き込んだ文字が返されます。ディスクが満杯またはその他エラーにより書き込まれなかったときはEOFが返されます。

+

文字が正常に書き込まれると書き込んだ文字が返されます。ディスクが満杯またはエラーにより書き込まれなかったときはEOF (-1)が返されます。

+

APIにUnicodeが選択されている(_LFN_UNICODEが1)ときは、UTF-8エンコードでファイルに書き込みます。それ以外の時は無変換(1文字1バイト)で書き込みます。

diff --git a/doc/ja/puts.html b/doc/ja/puts.html index b7f4d75..698c869 100644 --- a/doc/ja/puts.html +++ b/doc/ja/puts.html @@ -4,6 +4,7 @@ + FatFs - f_puts @@ -15,8 +16,8 @@

ファイルに文字列を書き込みます。

 int f_puts (
-  const char* Str,  /* 文字列 */
-  FIL* FileObject   /* ファイル・オブジェクト */
+  const TCHAR* Str,  /* 文字列 */
+  FIL* FileObject    /* ファイル・オブジェクト */
 );
 
@@ -34,7 +35,8 @@ int f_puts (

戻り値

-

文字列が正常に書き込まれると書き込んだ文字数が返されます。ディスクが満杯またはその他エラーにより正常に書き込まれなかったときはEOFが返されます。

+

文字列が正常に書き込まれると、書き込まれた文字数が返されます。ディスクが満杯またはエラーにより正常に書き込まれなかったときはEOF (-1)が返されます。

+

APIにUnicodeが選択されている(_LFN_UNICODEが1)ときは、UTF-8エンコードでファイルに書き込みます。それ以外の時は無変換(1文字1バイト)で書き込みます。

diff --git a/doc/ja/read.html b/doc/ja/read.html index dc8553e..7077b23 100644 --- a/doc/ja/read.html +++ b/doc/ja/read.html @@ -4,6 +4,7 @@ + FatFs - f_read @@ -15,10 +16,10 @@

ファイルからデータを読み出します。

 FRESULT f_read (
-  FIL* FileObject,    /* ファイル・オブジェクト構造体 */
-  void* Buffer,       /* 読み出したデータを格納するバッファ */
-  UINT ByteToRead,    /* 読み出すバイト数 */
-  UINT* ByteRead      /* 読み出されたバイト数 */
+  FIL* FileObject,    /* ファイル・オブジェクト構造体 */
+  void* Buffer,       /* 読み出したデータを格納するバッファ */
+  UINT ByteToRead,    /* 読み出すバイト数 */
+  UINT* ByteRead      /* 読み出されたバイト数 */
 );
 
@@ -59,7 +60,7 @@ FRESULT f_read (

解説

-

読み込み開始位置は、現在のファイルR/Wポインタからになります。ファイルR/Wポインタは読み込まれたバイト数だけ進みます。読み込み中にファイルの終端に達すると、*ByteReadByteToReadよりも小さくなります。

+

読み込み開始位置は、現在のリード/ライト・ポインタからになります。リード/ライト・ポインタは読み込まれたバイト数だけ進みます。関数が正常終了した後は、*ByteReadの値をチェックすべきです。*ByteReadByteToReadよりも小さいときは、読み込み中にファイルの終端に達したことを示しています。

diff --git a/doc/ja/readdir.html b/doc/ja/readdir.html index 0ac5b2c..4580517 100644 --- a/doc/ja/readdir.html +++ b/doc/ja/readdir.html @@ -4,6 +4,7 @@ + FatFs - f_readdir @@ -15,8 +16,8 @@

ディレクトリ項目を読み出します

 FRESULT f_readdir (
-  DIR* DirObject,    /* ディレクトリ・ブジェクト構造体へのポインタ */
-  FILINFO* FileInfo  /* ファイル情報構造体へのポインタ */
+  DIR* DirObject,    /* ディレクトリ・ブジェクト構造体へのポインタ */
+  FILINFO* FileInfo  /* ファイル情報構造体へのポインタ */
 );
 
@@ -51,7 +52,7 @@ FRESULT f_readdir (

解説

-

ディレクトリ項目を順次読み出します。この関数を繰り返し実行することによりディレクトリの全ての項目を読み出すことができます。全ての項目を読み出し、読み出す項目がもう無いときは、f_name[]メンバにヌル文字列が返されます。ボリューム名は読み出すときに棄てられ、現れることはありません。"."、".."は、相対パスが有効なとき(_FS_RPATH == 1)にのみ現れます。得られるファイル情報の詳細については FILINFO構造体を参照してください。FileInfoにヌル・ポインタを指定すると、そのディレクトリのリード・インデックスを巻き戻します。

+

ディレクトリ項目を順次読み出します。この関数を繰り返し実行することによりディレクトリの全ての項目を読み出すことができます。全ての項目を読み出し、読み出す項目がもう無いときは、f_name[]メンバにヌル文字列が返されます。ボリューム・ラベルは読み出すときに棄てられ、現れることはありません。"."、".."は、相対パスが有効なとき(_FS_RPATH == 1)にのみ現れます。得られるファイル情報の詳細については FILINFO構造体を参照してください。FileInfoにヌル・ポインタを指定すると、そのディレクトリのリード・インデックスを巻き戻します。

LFN機能が有効な時は、f_readdir関数の呼び出しに先立ってFILINFO構造体のlfnamelfsizeが有効な値で初期化されていなければなりません。lfnameはLFNを格納するバッファで、lfsizeはそのバッファ・サイズ(文字数)です。次の条件に一つでも該当する場合は、LFN格納バッファにヌル文字列が返されます。

  • そのディレクトリ項目にLFNが存在しない。
  • diff --git a/doc/ja/rename.html b/doc/ja/rename.html index f3d19e4..b4f75c9 100644 --- a/doc/ja/rename.html +++ b/doc/ja/rename.html @@ -4,6 +4,7 @@ + FatFs - f_rename @@ -15,8 +16,8 @@

    ファイルまたはディレクトリの名前の変更または移動。

     FRESULT f_rename (
    -  const XCHAR* OldName, /* 古いファイルまたはディレクトリ名 */
    -  const XCHAR* NewName  /* 新しいファイルまたはディレクトリ名 */
    +  const TCHAR* OldName, /* 古いファイルまたはディレクトリ名 */
    +  const TCHAR* NewName  /* 新しいファイルまたはディレクトリ名 */
     );
     
@@ -27,7 +28,7 @@ FRESULT f_rename (
OldName
変更対象のオブジェクト(ファイルまたはディレクトリ)へのパス名の入った'\0'で終わる文字列へのポインタを指定します。
NewName
-
新しいファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列へのポインタを指定します。既に存在する名前は使えません。また、ドライブ番号は指定できず、OldNameで指定されたボリューム上のオブジェクトとして扱われます。
+
新しいファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列へのポインタを指定します。既に存在する名前は使えません。また、ドライブ番号は指定できず、OldNameで指定された論理ドライブ上のオブジェクトとして扱われます。
@@ -60,7 +61,7 @@ FRESULT f_rename (
FR_NOT_ENABLED
論理ドライブにワークエリアが割り当てられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
@@ -80,10 +81,10 @@ FRESULT f_rename (

使用例

-    /* ファイルまたはサブディレクトリの名前を変更する */
+    /* ファイルまたはサブディレクトリの名前を変更する */
     f_rename("oldname.txt", "newname.txt");
 
-    /* ファイルまたはサブディレクトリの名前の変更と別のディレクトリへの移動 */
+    /* ファイルまたはサブディレクトリの名前の変更と別のディレクトリへの移動 */
     f_rename("oldname.txt", "dir1/newname.txt");
 
diff --git a/doc/ja/sdir.html b/doc/ja/sdir.html index ea355ea..f90d521 100644 --- a/doc/ja/sdir.html +++ b/doc/ja/sdir.html @@ -4,6 +4,7 @@ + FatFs - DIR @@ -14,18 +15,18 @@

DIR

DIR構造体は、f_opendir(), f_readdir()のワーク・エリアとして使用されます。アプリケーションから変更可能なメンバはありません。

-typedef struct _DIR_ {
-    FATFS*  fs;        /* Pointer to the owner file system object */
-    WORD    id;        /* Owner file system mount ID */
-    WORD    index;     /* Current index number */
-    DWORD   sclust;    /* Table start cluster (0:Static table) */
-    DWORD   clust;     /* Current cluster */
-    DWORD   sect;      /* Current sector */
-    BYTE*   dir;       /* Pointer to the current SFN entry in the win[] */
-    BYTE*   fn;        /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+typedef struct {
+    FATFS*  fs;        /* 親ファイル・システム・オブジェクトへのポインタ */
+    WORD    id;        /* 親ファイル・システム・オブジェクトのマウントID */
+    WORD    index;     /* 次に読み出すディレクトリ・インデックス番号 */
+    DWORD   sclust;    /* ディレクトリ開始クラスタ (0:ルート) */
+    DWORD   clust;     /* 現在のクラスタ番号 */
+    DWORD   sect;      /* 現在のセクタ番号 */
+    BYTE*   dir;       /* 現在のSFNエントリへのポインタ */
+    BYTE*   fn;        /* SFNバッファへのポインタ (in/out) {file[8],ext[3],status[1]} */
 #if _USE_LFN
-    WCHAR*  lfn;       /* Pointer to the LFN working buffer */
-    WORD    lfn_idx;   /* Last matched LFN index (0xFFFF:No LFN) */
+    WCHAR*  lfn;       /* LFNバッファへのポインタ */
+    WORD    lfn_idx;   /* 最後にマッチしたLFNエントリのインデックス (0xFFFF:無効) */
 #endif
 } DIR;
 
diff --git a/doc/ja/sfatfs.html b/doc/ja/sfatfs.html index d5cfa97..dababad 100644 --- a/doc/ja/sfatfs.html +++ b/doc/ja/sfatfs.html @@ -4,6 +4,7 @@ + FatFs - FATFS @@ -15,33 +16,36 @@

FATFS構造体は、個々の論理ドライブのダイナミック・ワーク・エリアを保持し、f_mount()でFatFsモジュールに登録されます。標準状態では次のようなメンバになっています。アプリケーションから書き換え可能なメンバはありません。

-typedef struct _FATFS_ {
-    BYTE    fs_type;      /* FAT sub type */
-    BYTE    drive;        /* Physical drive number */
-    BYTE    csize;        /* Number of sectors per cluster */
-    BYTE    n_fats;       /* Number of FAT copies */
-    BYTE    wflag;        /* win[] dirty flag (1:must be written back) */
-    BYTE    fsi_flag;     /* fsinfo dirty flag (1:must be written back) */
-    WORD    id;           /* File system mount ID */
-    WORD    n_rootdir;    /* Number of root directory entries (0 on FAT32) */
-#if _FS_REENTRANT
-    HANDLE  h_mutex;      /* Handle to the mutex (Platform dependent) */
-#endif
+typedef struct {
+    BYTE    fs_type;      /* FATタイプ */
+    BYTE    drv;          /* 物理ドライブ番号 */
+    BYTE    csize;        /* クラスタ当たりのセクタ数 */
+    BYTE    n_fats;       /* FATの多重化数 */
+    BYTE    wflag;        /* win[]ダーティ・フラグ */
+    BYTE    fsi_flag;     /* fsinfoダーティ・フラグ */
+    WORD    id;           /* ファイル・システム・マウントID */
+    WORD    n_rootdir;    /* ルート・ディレクトリのエントリ数 (FAT12/16) */
 #if _MAX_SS != 512
-    WORD    s_size;       /* Sector size */
+    WORD    ssize;        /* セクタ・サイズ (可変セクタ長のみ) */
+#endif
+#if _FS_REENTRANT
+    HANDLE  h_mutex;      /* 同期オブジェクトID */
 #endif
 #if !_FS_READONLY
-    DWORD   last_clust;   /* Last allocated cluster */
-    DWORD   free_clust;   /* Number of free clusters */
-    DWORD   fsi_sector;   /* fsinfo sector */
+    DWORD   last_clust;   /* 最後に割り当てられたクラスタ番号 */
+    DWORD   free_clust;   /* 空きクラスタ数 */
+    DWORD   fsi_sector;   /* fsinfoセクタ (FAT32) */
 #endif
-    DWORD   sects_fat;    /* Sectors per fat */
-    DWORD   max_clust;    /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
-    DWORD   fatbase;      /* FAT start sector */
-    DWORD   dirbase;      /* Root directory start sector (Cluster# on FAT32) */
-    DWORD   database;     /* Data start sector */
-    DWORD   winsect;      /* Current sector appearing in the win[] */
-    BYTE    win[_MAX_SS]; /* Disk access window for Directory/FAT */
+#if _FS_RPATH
+    DWORD   cdir;         /* カレント・ディレクトリのクラスタ (0:ルート) */
+#endif
+    DWORD   n_fatent;     /* FATのエントリ数 (= クラスタ数 + 2) */
+    DWORD   fsize;        /* FAT 1個当たりのセクタ数 */
+    DWORD   fatbase;      /* FAT領域開始セクタ */
+    DWORD   dirbase;      /* ルート・ディレクトリ開始セクタ (FAT32: クラスタ番号) */
+    DWORD   database;     /* データ領域開始区セクタ */
+    DWORD   winsect;      /* win[]に現れているセクタ番号 */
+    BYTE    win[_MAX_SS]; /* ディスク・アクセス・ウィンドウ */
 } FATFS;
 
diff --git a/doc/ja/sfile.html b/doc/ja/sfile.html index fd8849b..7b0385a 100644 --- a/doc/ja/sfile.html +++ b/doc/ja/sfile.html @@ -4,6 +4,7 @@ + FatFs - FIL @@ -12,25 +13,31 @@

FIL

-

FIL構造体は、f_open()で作成され、そのファイルの状態を保持します。アプリケーションから書き換え可能なメンバはありません。

+

FIL構造体は、f_open関数で作成され、そのファイルの状態を保持します。また、f_close関数でファイルが閉じられると無効化されます。アプリケーションからの書き換えが可能なメンバはcltblのみです。非タイニー構成では内部にセクタ・バッファが確保されるので、サイズに注意が必要です。

-typedef struct _FIL_ {
-    FATFS*  fs;           /* Pointer to the owner file system object */
-    WORD    id;           /* Owner file system mount ID */
-    BYTE    flag;         /* File status flags */
-    BYTE    csect;        /* Sector address in the cluster */
-    DWORD   fptr;         /* File R/W pointer */
-    DWORD   fsize;        /* File size */
-    DWORD   org_clust;    /* File start cluster */
-    DWORD   curr_clust;   /* Current cluster */
-    DWORD   dsect;        /* Current data sector */
+typedef struct {
+    FATFS*  fs;           /* 親ファイル・システム・オブジェクトへのポインタ */
+    WORD    id;           /* 親ファイル・システム・オブジェクトのマウントID */
+    BYTE    flag;         /* ファイル・ステータス・フラグ */
+    BYTE    pad1;
+    DWORD   fptr;         /* ファイル読み書きポインタ(ファイル先頭からのバイト・オフセット) */
+    DWORD   fsize;        /* ファイル・サイズ(バイト単位) */
+    DWORD   org_clust;    /* ファイル開始クラスタ番号 (0: fsize==0) */
+    DWORD   curr_clust;   /* 現在のクラスタ */
+    DWORD   dsect;        /* 現在のデータ・セクタ */
 #if _FS_READONLY == 0
-    DWORD   dir_sect;     /* Sector containing the directory entry */
-    BYTE*   dir_ptr;      /* Ponter to the directory entry in the window */
+    DWORD   dir_sect;     /* このファイルのディレクトリ・エントリのあるセクタ */
+    BYTE*   dir_ptr;      /* このファイルのディレクトリへのポインタ */
+#endif
+#if _USE_FASTSEEK
+    DWORD*  cltbl;        /* ファイルのクラスタ・リンク情報へのポインタ */
+#endif
+#if _FS_SHARE
+    UINT    lockid;       /* ファイル・ロックID */
 #endif
 #if !_FS_TINY
-    BYTE    buf[_MAX_SS];  /* File R/W buffer */
+    BYTE    buf[_MAX_SS]; /* データ転送バッファ */
 #endif
 } FIL;
 
diff --git a/doc/ja/sfileinfo.html b/doc/ja/sfileinfo.html index 9efffe8..b103d15 100644 --- a/doc/ja/sfileinfo.html +++ b/doc/ja/sfileinfo.html @@ -4,6 +4,7 @@ + FatFs - FILINFO @@ -14,15 +15,15 @@

FILINFO

FILINFO構造体は、f_stat(), f_readdir()で返されるファイル情報を保持します。

-typedef struct _FILINFO_ {
-    DWORD fsize;     /* File size */
-    WORD fdate;      /* Last modified date */
-    WORD ftime;      /* Last modified time */
-    BYTE fattrib;    /* Attribute */
-    char fname[13];  /* Short file name (8.3 format) */
+typedef struct {
+    DWORD fsize;     /* ファイル・サイズ */
+    WORD fdate;      /* 最後に更新された日付 */
+    WORD ftime;      /* 最後に更新された時刻  */
+    BYTE fattrib;    /* アトリビュート */
+    TCHAR fname[13]; /* 短いファイル名 (8.3フォーマット) */
 #if _USE_LFN
-    XCHAR* lfname;   /* Pointer to the LFN buffer */
-    int lfsize;      /* Size of LFN buffer [characters] */
+    TCHAR* lfname;   /* 長いファイル名のバッファへのポインタ */
+    int lfsize;      /* 長いファイル名のバッファのサイズ [文字数] */
 #endif
 } FILINFO;
 
@@ -59,7 +60,7 @@ typedef struct _FILINFO_ {
fname[]
8.3形式の名前が'\0'で終わる文字列として格納されます。非LFN構成のときは、常に大文字で返されます。LFN構成のときは短い名前が返されますが、ASCII英字が小文字になる場合があります。
lfname
-
返される長いファイル名を格納するバッファへのポインタ。この構造体を使用する前にアプリケーションにより初期化されなければなりません。非LFN構成のときはこのメンバは存在しません。
+
返される長いファイル名を格納するバッファへのポインタ。この構造体を使用する前にアプリケーションにより初期化されなければなりません。このメンバにNULLが設定されるとLFNは返されません。非LFN構成のときはこのメンバは存在しません。
lfsize
長いファイル名を格納するバッファのサイズ(文字数)。この構造体を使用する前にアプリケーションにより初期化されなければなりません。非LFN構成のときはこのメンバは存在しません。
diff --git a/doc/ja/stat.html b/doc/ja/stat.html index f24193c..d1ef041 100644 --- a/doc/ja/stat.html +++ b/doc/ja/stat.html @@ -4,6 +4,7 @@ + FatFs - f_stat @@ -14,8 +15,8 @@

f_stat

 FRESULT f_stat (
-  const char* FileName,  /* ファイルまたはディレクトリ名へのポインタ */
-  FILINFO* FileInfo      /* ファイル情報構造体へのポインタ *
+  const TCHAR* FileName,  /* ファイルまたはディレクトリ名へのポインタ */
+  FILINFO* FileInfo       /* ファイル情報構造体へのポインタ *
 );
 
@@ -43,7 +44,7 @@ FRESULT f_stat (
FR_INVALID_NAME
パス名が不正。
FR_INVALID_DRIVE
-
ドライブ番号が不正。
+
論理ドライブ番号が不正。
FR_NOT_READY
メディアがセットされていないなど、物理ドライブが動作不能状態。
FR_DISK_ERR
@@ -53,7 +54,7 @@ FRESULT f_stat (
FR_NOT_ENABLED
論理ドライブにワークエリアが割り当てられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
diff --git a/doc/ja/sync.html b/doc/ja/sync.html index f3a6088..62e9de8 100644 --- a/doc/ja/sync.html +++ b/doc/ja/sync.html @@ -4,6 +4,7 @@ + FatFs - f_sync @@ -15,7 +16,7 @@

書き込み中のファイルのキャッシュされた情報をフラッシュします。

 FRESULT f_sync (
-  FIL* FileObject     /* ファイル・オブジェクト構造体へのポインタ */
+  FIL* FileObject     /* ファイル・オブジェクト構造体へのポインタ */
 );
 
@@ -48,7 +49,7 @@ FRESULT f_sync (

解説

-

この関数はf_close()と同じ処理を実行しますが、ファイルは引き続き開かれたままになり、読み書きを続行できます。ロギングなど、書き込みモードで長時間ファイルが開かれているアプリケーションにおいて、定期的または区切りの良いところでsyncすることにより、不意の電源断やメディアの取り外しにより失われるデータを最小にすることができます。実際のところ、f_closeではsyncしたあとファイル・オブジェクトを破棄しているだけなので、f_close直前のsyncは意味がありません。

+

この関数はf_close()と同じ処理を実行しますが、ファイルは引き続き開かれたままになり、読み書きを続行できます。ロギングなど、書き込みモードで長時間ファイルが開かれているアプリケーションにおいて、定期的または区切りの良いところでこの関数を使用することにより、不意の電源断やメディアの取り外しにより失われるデータを最小にすることができます。実際のところ、f_close()内ではこの関数を呼び出した後ファイル・オブジェクトを無効化しているだけなので、f_close()直前のf_sync()は意味がありません。

diff --git a/doc/ja/truncate.html b/doc/ja/truncate.html index 49b9f03..601532f 100644 --- a/doc/ja/truncate.html +++ b/doc/ja/truncate.html @@ -4,6 +4,7 @@ + FatFs - f_truncate @@ -15,7 +16,7 @@

ファイル長を切り詰めます。

 FRESULT f_truncate (
-  FIL* FileObject     /* ファイル・オブジェクトへのポインタ */
+  FIL* FileObject     /* ファイル・オブジェクトへのポインタ */
 );
 
diff --git a/doc/ja/unlink.html b/doc/ja/unlink.html index 7867d3a..86ed443 100644 --- a/doc/ja/unlink.html +++ b/doc/ja/unlink.html @@ -4,6 +4,7 @@ + FatFs - f_unlink @@ -15,7 +16,7 @@

オブジェクトを削除します。

 FRESULT f_unlink (
-  const XCHAR* FileName  /* オブジェクト名へのポインタ */
+  const TCHAR* FileName  /* オブジェクト名へのポインタ */
 );
 
@@ -55,7 +56,9 @@ FRESULT f_unlink (
FR_NOT_ENABLED
論理ドライブにワーク・エリアが割り当てられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
+
FR_LOCKED
+
ファイル共有機能によるアクセス拒否。
diff --git a/doc/ja/utime.html b/doc/ja/utime.html index ff5c66f..3a7f3f4 100644 --- a/doc/ja/utime.html +++ b/doc/ja/utime.html @@ -4,6 +4,7 @@ + FatFs - f_utime @@ -15,8 +16,8 @@

オブジェクトのタイムスタンプを変更します。

 FRESULT f_utime (
-  const XCHAR* FileName,   /* オブジェクト名へのポインタ */
-  const FILINFO* TimeDate  /* 設定する日付 */
+  const TCHAR* FileName,   /* オブジェクト名へのポインタ */
+  const FILINFO* TimeDate  /* 設定する日付 */
 );
 
@@ -44,7 +45,7 @@ FRESULT f_utime (
FR_INVALID_NAME
パス名が不正。
FR_INVALID_NAME
-
ドライブ番号が不正。
+
論理ドライブ番号が不正。
FR_NOT_READY
メディアがセットされていないなど、物理ドライブが動作不能状態。
FR_WRITE_PROTECTED
@@ -56,7 +57,7 @@ FRESULT f_utime (
FR_NOT_ENABLED
その論理ドライブにワーク・エリアが与えられていない。
FR_NO_FILESYSTEM
-
ディスク上に有効なFATボリュームが見つからない。
+
有効なFATボリュームが見つからない。
@@ -67,6 +68,30 @@ FRESULT f_utime ( +
+

使用例

+
+FRESULT set_timestamp (
+    char *obj,     /* ファイル名へのポインタ */
+    int year,
+    int month,
+    int mday,
+    int hour,
+    int min,
+    int sec
+)
+{
+    FILINFO fno;
+
+    fno.fdate = (WORD)(((year - 1980) * 512U) | month * 32U | mday);
+    fno.ftime = (WORD)(hour * 2048U | min * 32U | sec / 2U);
+
+    return f_utime(obj, &fno);
+}
+
+
+ +

対応情報

_FS_READONLY == 0で、且つ_FS_MINIMIZE == 0のときに使用可能です。

diff --git a/doc/ja/write.html b/doc/ja/write.html index d98ee51..3e75c93 100644 --- a/doc/ja/write.html +++ b/doc/ja/write.html @@ -4,6 +4,7 @@ + FatFs - f_write @@ -15,10 +16,10 @@

ファイルにデータを書き込みます。

 FRESULT f_write (
-  FIL* FileObject,     /* ファイル・オブジェクト */
-  const void* Buffer,  /* 書き込みデータ */
-  UINT ByteToWrite,    /* 書き込むバイト数 */
-  UINT* ByteWritten    /* 書き込まれたバイト数 */
+  FIL* FileObject,     /* ファイル・オブジェクト */
+  const void* Buffer,  /* 書き込みデータ */
+  UINT ByteToWrite,    /* 書き込むバイト数 */
+  UINT* ByteWritten    /* 書き込まれたバイト数 */
 );
 
@@ -59,7 +60,7 @@ FRESULT f_write (

解説

-

書き込み開始位置は、ファイルR/Wポインタの位置からになります。ファイルR/Wポインタは実際に書き込まれたバイト数だけ進みます。関数が正常終了した後、要求したバイト数が書き込まれたかどうか*ByteWrittenをチェックすべきです。*ByteWritten < ByteToWriteのときは、ディスク・フルを意味します。

+

書き込み開始位置は、リード/ライト・ポインタの位置からになります。リード/ライト・ポインタは実際に書き込まれたバイト数だけ進みます。関数が正常終了した後、要求したバイト数が書き込まれたかどうか*ByteWrittenをチェックすべきです。*ByteWritten < ByteToWriteのときは、ディスク・フルを意味します。ディスク・フルが発生しているときまたはそれに近いときは、制御が帰るまで時間がかかる場合があります。

diff --git a/doc/updates.txt b/doc/updates.txt index df4314b..04e07e7 100644 --- a/doc/updates.txt +++ b/doc/updates.txt @@ -1,3 +1,11 @@ +R0.08, May 15, 2010 + Added a memory configuration option. (_USE_LFN) + Added file lock feature. (_FS_SHARE) + Added fast seek feature. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed fname member in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. + R0.07e, Nov 3, 2009 Separated out configuration options from ff.h to ffconf.h. Added a configuration option, _LFN_UNICODE. diff --git a/src/00readme.txt b/src/00readme.txt index 689e973..fa2fa84 100644 --- a/src/00readme.txt +++ b/src/00readme.txt @@ -1,4 +1,4 @@ -FatFs Module Source Files R0.07e (C)ChaN, 2009 +FatFs Module Source Files R0.08 (C)ChaN, 2010 FILES @@ -24,7 +24,7 @@ AGREEMENTS small embedded systems. This is a free software and is opened for education, research and commercial developments under license policy of following trems. - Copyright (C) 2009, ChaN, all right reserved. + Copyright (C) 2010, ChaN, all right reserved. * The FatFs module is a free software and there is NO WARRANTY. * No restriction on use. You can use, modify and redistribute it for @@ -103,8 +103,15 @@ REVISION HISTORY Added f_chdrive(). Added proper case conversion for extended characters. - Nov 03,'2009 R0.07e Separated out configuration options from ff.h to ffconf.h. + Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h. Added a configuration option, _LFN_UNICODE. Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. Fixed name matching error on the 13 char boundary. Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. + + May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN) + Added file lock feature. (_FS_SHARE) + Added fast seek feature. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed fname member in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. diff --git a/src/diskio.c b/src/diskio.c index 756a45a..6e012b0 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -9,6 +9,7 @@ /*-----------------------------------------------------------------------*/ /* Correspondence between physical drive number and physical drive. */ +/*-----------------------------------------------------------------------*/ #define ATA 0 #define MMC 1 @@ -18,6 +19,7 @@ /*-----------------------------------------------------------------------*/ /* Inidialize a Drive */ +/*-----------------------------------------------------------------------*/ DSTATUS disk_initialize ( BYTE drv /* Physical drive nmuber (0..) */ @@ -52,6 +54,7 @@ DSTATUS disk_initialize ( /*-----------------------------------------------------------------------*/ /* Return Disk Status */ +/*-----------------------------------------------------------------------*/ DSTATUS disk_status ( BYTE drv /* Physical drive nmuber (0..) */ @@ -86,6 +89,7 @@ DSTATUS disk_status ( /*-----------------------------------------------------------------------*/ /* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ DRESULT disk_read ( BYTE drv, /* Physical drive nmuber (0..) */ @@ -123,6 +127,12 @@ DRESULT disk_read ( /*-----------------------------------------------------------------------*/ /* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ +/* The FatFs module will issue multiple sector transfer request +/ (count > 1) to the disk I/O layer. The disk function should process +/ the multiple sector transfer properly Do. not translate it into +/ multiple single sector transfers to the media, or the data read/write +/ performance may be drasticaly decreased. */ #if _READONLY == 0 DRESULT disk_write ( @@ -162,6 +172,7 @@ DRESULT disk_write ( /*-----------------------------------------------------------------------*/ /* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ DRESULT disk_ioctl ( BYTE drv, /* Physical drive nmuber (0..) */ diff --git a/src/diskio.h b/src/diskio.h index 49562d5..bf5d188 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -26,7 +26,6 @@ typedef enum { /*---------------------------------------*/ /* Prototypes for disk control functions */ -BOOL assign_drives (int argc, char *argv[]); DSTATUS disk_initialize (BYTE); DSTATUS disk_status (BYTE); DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); diff --git a/src/ff.c b/src/ff.c index cc25722..236c86f 100644 --- a/src/ff.c +++ b/src/ff.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.07e (C)ChaN, 2009 +/ FatFs - FAT file system module R0.08 (C)ChaN, 2010 /-----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial -/ developments under license policy of following trems. +/ developments under license policy of following terms. / -/ Copyright (C) 2009, ChaN, all right reserved. +/ Copyright (C) 2010, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -19,19 +19,19 @@ / / Jun 01,'06 R0.02 Added FAT12 support. / Removed unbuffered mode. -/ Fixed a problem on small (<32M) patition. +/ Fixed a problem on small (<32M) partition. / Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). / / Sep 22,'06 R0.03 Added f_rename(). / Changed option _FS_MINIMUM to _FS_MINIMIZE. -/ Dec 11,'06 R0.03a Improved cluster scan algolithm to write files fast. +/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. / Fixed f_mkdir() creates incorrect directory on FAT32. / / Feb 04,'07 R0.04 Supported multiple drive system. / Changed some interfaces for multiple drive system. / Changed f_mountdrv() to f_mount(). / Added f_mkfs(). -/ Apr 01,'07 R0.04a Supported multiple partitions on a plysical drive. +/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. / Added a capability of extending file size to f_lseek(). / Added minimization level 3. / Fixed an endian sensitive code in f_mkfs(). @@ -74,21 +74,47 @@ / Added a configuration option, _LFN_UNICODE. / Changed f_readdir() to return the SFN with always upper / case on non-LFN cfg. +/ +/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN) +/ Added file lock feature. (_FS_SHARE) +/ Added fast seek feature. (_USE_FASTSEEK) +/ Changed some types on the API, XCHAR->TCHAR. +/ Changed fname member in the FILINFO structure on Unicode cfg. +/ String functions support UTF-8 encoding files on Unicode cfg. /---------------------------------------------------------------------------*/ #include "ff.h" /* FatFs configurations and declarations */ #include "diskio.h" /* Declarations of low level disk I/O functions */ + /*-------------------------------------------------------------------------- Module Private Definitions ---------------------------------------------------------------------------*/ -#if _FATFS != 0x007E +#if _FATFS != 8085 #error Wrong include file (ff.h). #endif + +/* FAT sub-type boundaries */ +/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ + + +/* Definitions corresponds to multiple sector size */ +#if _MAX_SS == 512 /* Single sector size */ +#define SS(fs) 512U +#elif _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096 /* Multiple sector size */ +#define SS(fs) ((fs)->ssize) +#else +#error Wrong sector size. +#endif + + +/* Reentrancy related */ #if _FS_REENTRANT #if _USE_LFN == 1 #error Static LFN work area must not be used in re-entrant configuration. @@ -104,10 +130,34 @@ #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } -#ifndef NULL -#define NULL 0 + +/* Character code support macros */ +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) + +#if _DF1S /* Code page is DBCS */ + +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) #endif +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#endif + +#else /* Code page is SBCS */ + +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 + +#endif /* _DF1S */ + + /* Name status flags */ #define NS 11 /* Offset of name status byte */ #define NS_LOSS 0x01 /* Out of 8.3 format */ @@ -119,21 +169,16 @@ +/*------------------------------------------------------------*/ +/* Work area */ -/*-------------------------------------------------------------------------- - - Private Work Area - ----------------------------------------------------------------------------*/ - -#if _DRIVES < 1 || _DRIVES > 9 -#error Number of drives must be 1-9. +#if !_DRIVES +#error Number of drives must not be 0. #endif -static -FATFS *FatFs[_DRIVES]; /* Pointer to the file system objects (logical drives) */ - static WORD Fsid; /* File system mount ID */ +static +FATFS *FatFs[_DRIVES]; /* Pointer to the file system objects (logical drives) */ #if _FS_RPATH static @@ -141,20 +186,31 @@ BYTE Drive; /* Current drive */ #endif -#if _USE_LFN == 1 /* LFN with static LFN working buffer */ -static -WCHAR LfnBuf[_MAX_LFN + 1]; -#define NAMEBUF(sp,lp) BYTE sp[12]; WCHAR *lp = LfnBuf -#define INITBUF(dj,sp,lp) dj.fn = sp; dj.lfn = lp +#if _USE_LFN == 0 /* No LFN */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() -#elif _USE_LFN > 1 /* LFN with dynamic LFN working buffer */ -#define NAMEBUF(sp,lp) BYTE sp[12]; WCHAR lbuf[_MAX_LFN + 1], *lp = lbuf -#define INITBUF(dj,sp,lp) dj.fn = sp; dj.lfn = lp +#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ +static WCHAR LfnBuf[_MAX_LFN + 1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() -#else /* No LFN */ -#define NAMEBUF(sp,lp) BYTE sp[12] -#define INITBUF(dj,sp,lp) dj.fn = sp +#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN + 1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() +#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) + +#else +#error Wrong LFN configuration. #endif @@ -174,23 +230,35 @@ WCHAR LfnBuf[_MAX_LFN + 1]; /* Copy memory to memory */ static void mem_cpy (void* dst, const void* src, int cnt) { - char *d = (char*)dst; - const char *s = (const char *)src; - while (cnt--) *d++ = *s++; + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + +#if _WORD_ACCESS == 1 + while (cnt >= sizeof(int)) { + *(int*)d = *(int*)s; + d += sizeof(int); s += sizeof(int); + cnt -= sizeof(int); + } +#endif + while (cnt--) + *d++ = *s++; } /* Fill memory */ static void mem_set (void* dst, int val, int cnt) { - char *d = (char*)dst; - while (cnt--) *d++ = (char)val; + BYTE *d = (BYTE*)dst; + + while (cnt--) + *d++ = (BYTE)val; } /* Compare memory to memory */ static int mem_cmp (const void* dst, const void* src, int cnt) { - const char *d = (const char *)dst, *s = (const char *)src; + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; int r = 0; + while (cnt-- && (r = *d++ - *s++) == 0) ; return r; } @@ -210,7 +278,7 @@ int chk_chr (const char* str, int chr) { #if _FS_REENTRANT static -BOOL lock_fs ( +int lock_fs ( FATFS *fs /* File system object */ ) { @@ -235,6 +303,104 @@ void unlock_fs ( +/*-----------------------------------------------------------------------*/ +/* File shareing control functions */ +/*-----------------------------------------------------------------------*/ +#if _FS_SHARE + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dj, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i, be; + + /* Search file semaphore table */ + for (i = be = 0; i < _FS_SHARE; i++) { + if (dj->fs->flsem[i].ctr) { /* Existing entry */ + if (dj->fs->flsem[i].clu == dj->sclust && /* The file is found (identified with its location) */ + dj->fs->flsem[i].idx == dj->index) break; + } else { /* Blank entry */ + be++; + } + } + if (i == _FS_SHARE) /* The file has not been opened */ + return (be || acc != 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + + /* The file has been opened. Reject any open against writing file and all write mode open */ + return (acc || dj->fs->flsem[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock ( /* Check if an entry is available for a new file */ + FATFS* fs /* File system object */ +) +{ + UINT i; + + for (i = 0; i < _FS_SHARE && fs->flsem[i].ctr; i++) ; + return (i == _FS_SHARE) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ + DIR* dj, /* Directory object pointing the file to register or increment */ + int acc /* Desired access mode (0:Read, !0:Write) */ +) +{ + UINT i; + + + for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ + if (dj->fs->flsem[i].ctr && + dj->fs->flsem[i].clu == dj->sclust && + dj->fs->flsem[i].idx == dj->index) break; + } + + if (i == _FS_SHARE) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_SHARE && dj->fs->flsem[i].ctr; i++) ; + if (i == _FS_SHARE) return 0; /* No space to register (int err) */ + dj->fs->flsem[i].clu = dj->sclust; + dj->fs->flsem[i].idx = dj->index; + } + + if (acc && dj->fs->flsem[i].ctr) return 0; /* Access violation (int err) */ + + dj->fs->flsem[i].ctr = acc ? 0x100 : dj->fs->flsem[i].ctr + 1; /* Set semaphore value */ + + return i + 1; +} + + +static +FRESULT dec_lock ( /* Decrement file open counter */ + FATFS* fs, /* File system object */ + UINT i /* Semaphore index */ +) +{ + WORD n; + FRESULT res; + + + if (--i < _FS_SHARE) { + n = fs->flsem[i].ctr; + if (n >= 0x100) n = 0; + if (n) n--; + fs->flsem[i].ctr = n; + res = FR_OK; + } else { + res = FR_INT_ERR; + } + return res; +} + +#endif + + + /*-----------------------------------------------------------------------*/ /* Change window offset */ /*-----------------------------------------------------------------------*/ @@ -242,7 +408,7 @@ void unlock_fs ( static FRESULT move_window ( FATFS *fs, /* File system object */ - DWORD sector /* Sector number to make apperance in the fs->win[] */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ ) /* Move to zero only writes back dirty window */ { DWORD wsect; @@ -252,20 +418,20 @@ FRESULT move_window ( if (wsect != sector) { /* Changed current window */ #if !_FS_READONLY if (fs->wflag) { /* Write back dirty window if needed */ - if (disk_write(fs->drive, fs->win, wsect, 1) != RES_OK) + if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) return FR_DISK_ERR; fs->wflag = 0; - if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */ + if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */ BYTE nf; - for (nf = fs->n_fats; nf > 1; nf--) { /* Refrect the change to all FAT copies */ - wsect += fs->sects_fat; - disk_write(fs->drive, fs->win, wsect, 1); + for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */ + wsect += fs->fsize; + disk_write(fs->drv, fs->win, wsect, 1); } } } #endif if (sector) { - if (disk_read(fs->drive, fs->win, sector, 1) != RES_OK) + if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) return FR_DISK_ERR; fs->winsect = sector; } @@ -300,11 +466,11 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ 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(fs->drive, fs->win, fs->fsi_sector, 1); + disk_write(fs->drv, fs->win, fs->fsi_sector, 1); fs->fsi_flag = 0; } /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drive, CTRL_SYNC, (void*)NULL) != RES_OK) + if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK) res = FR_DISK_ERR; } @@ -320,38 +486,39 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ /*-----------------------------------------------------------------------*/ -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Interal error, Else:Cluster status */ +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ FATFS *fs, /* File system object */ DWORD clst /* Cluster# to get the link information */ ) { UINT wc, bc; - DWORD fsect; + BYTE *p; - if (clst < 2 || clst >= fs->max_clust) /* Range check */ + if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ return 1; - fsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : - bc = clst; bc += bc / 2; - if (move_window(fs, fsect + (bc / SS(fs)))) break; - wc = fs->win[bc & (SS(fs) - 1)]; bc++; - if (move_window(fs, fsect + (bc / SS(fs)))) break; - wc |= (WORD)fs->win[bc & (SS(fs) - 1)] << 8; + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc = fs->win[bc % SS(fs)]; bc++; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc |= fs->win[bc % SS(fs)] << 8; return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); case FS_FAT16 : - if (move_window(fs, fsect + (clst / (SS(fs) / 2)))) break; - return LD_WORD(&fs->win[((WORD)clst * 2) & (SS(fs) - 1)]); + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; + p = &fs->win[clst * 2 % SS(fs)]; + return LD_WORD(p); case FS_FAT32 : - if (move_window(fs, fsect + (clst / (SS(fs) / 4)))) break; - return LD_DWORD(&fs->win[((WORD)clst * 4) & (SS(fs) - 1)]) & 0x0FFFFFFF; + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; + p = &fs->win[clst * 4 % SS(fs)]; + return LD_DWORD(p) & 0x0FFFFFFF; } - return 0xFFFFFFFF; /* An error occured at the disk I/O layer */ + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ } @@ -364,46 +531,47 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Interal error, Else:Cluster status * FRESULT put_fat ( FATFS *fs, /* File system object */ - DWORD clst, /* Cluster# to be changed in range of 2 to fs->max_clust - 1 */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ DWORD val /* New value to mark the cluster */ ) { UINT bc; BYTE *p; - DWORD fsect; FRESULT res; - if (clst < 2 || clst >= fs->max_clust) { /* Range check */ + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ res = FR_INT_ERR; } else { - fsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : bc = clst; bc += bc / 2; - res = move_window(fs, fsect + (bc / SS(fs))); + res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; - p = &fs->win[bc & (SS(fs) - 1)]; + p = &fs->win[bc % SS(fs)]; *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; bc++; fs->wflag = 1; - res = move_window(fs, fsect + (bc / SS(fs))); + res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; - p = &fs->win[bc & (SS(fs) - 1)]; + p = &fs->win[bc % SS(fs)]; *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); break; case FS_FAT16 : - res = move_window(fs, fsect + (clst / (SS(fs) / 2))); + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); if (res != FR_OK) break; - ST_WORD(&fs->win[((WORD)clst * 2) & (SS(fs) - 1)], (WORD)val); + p = &fs->win[clst * 2 % SS(fs)]; + ST_WORD(p, (WORD)val); break; case FS_FAT32 : - res = move_window(fs, fsect + (clst / (SS(fs) / 4))); + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); if (res != FR_OK) break; - ST_DWORD(&fs->win[((WORD)clst * 4) & (SS(fs) - 1)], val); + p = &fs->win[clst * 4 % SS(fs)]; + val |= LD_DWORD(p) & 0xF0000000; + ST_DWORD(p, val); break; default : @@ -433,12 +601,12 @@ FRESULT remove_chain ( DWORD nxt; - if (clst < 2 || clst >= fs->max_clust) { /* Check the range of cluster# */ + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ res = FR_INT_ERR; } else { res = FR_OK; - while (clst < fs->max_clust) { /* Not a last link? */ + while (clst < fs->n_fatent) { /* Not a last link? */ nxt = get_fat(fs, clst); /* Get cluster status */ if (nxt == 0) break; /* Empty cluster? */ if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ @@ -470,36 +638,35 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ ) { - DWORD cs, ncl, scl, mcl; + DWORD cs, ncl, scl; - mcl = fs->max_clust; - if (clst == 0) { /* Create new chain */ + if (clst == 0) { /* Create a new chain */ scl = fs->last_clust; /* Get suggested start point */ - if (scl == 0 || scl >= mcl) scl = 1; + if (!scl || scl >= fs->n_fatent) scl = 1; } - else { /* Stretch existing chain */ + else { /* Stretch the current chain */ cs = get_fat(fs, clst); /* Check the cluster status */ if (cs < 2) return 1; /* It is an invalid cluster */ - if (cs < mcl) return cs; /* It is already followed by next cluster */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ scl = clst; } ncl = scl; /* Start cluster */ for (;;) { ncl++; /* Next cluster */ - if (ncl >= mcl) { /* Wrap around */ + if (ncl >= fs->n_fatent) { /* Wrap around */ ncl = 2; - if (ncl > scl) return 0; /* No free custer */ + if (ncl > scl) return 0; /* No free cluster */ } cs = get_fat(fs, ncl); /* Get the cluster status */ if (cs == 0) break; /* Found a free cluster */ - if (cs == 0xFFFFFFFF || cs == 1)/* An error occured */ + if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ return cs; - if (ncl == scl) return 0; /* No free custer */ + if (ncl == scl) return 0; /* No free cluster */ } - if (put_fat(fs, ncl, 0x0FFFFFFF)) /* Mark the new cluster "in use" */ + if (put_fat(fs, ncl, 0x0FFFFFFF)) /* Mark the new cluster "last link" */ return 0xFFFFFFFF; if (clst != 0) { /* Link it to the previous one if needed */ if (put_fat(fs, clst, ncl)) @@ -530,7 +697,7 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ ) { clst -= 2; - if (clst >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */ + if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ return clst * fs->csize + fs->database; } @@ -538,11 +705,11 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ /*-----------------------------------------------------------------------*/ -/* Directory handling - Seek directory index */ +/* Directory handling - Set directory index */ /*-----------------------------------------------------------------------*/ static -FRESULT dir_seek ( +FRESULT dir_sdi ( DIR *dj, /* Pointer to directory object */ WORD idx /* Directory index number */ ) @@ -553,7 +720,7 @@ FRESULT dir_seek ( dj->index = idx; clst = dj->sclust; - if (clst == 1 || clst >= dj->fs->max_clust) /* Check start cluster range */ + if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ return FR_INT_ERR; if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ clst = dj->fs->dirbase; @@ -569,7 +736,7 @@ FRESULT dir_seek ( while (idx >= ic) { /* Follow cluster chain */ clst = get_fat(dj->fs, clst); /* Get next cluster */ if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= dj->fs->max_clust) /* Reached to end of table or int error */ + if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ return FR_INT_ERR; idx -= ic; } @@ -590,9 +757,9 @@ FRESULT dir_seek ( /*-----------------------------------------------------------------------*/ static -FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not streach */ +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ DIR *dj, /* Pointer to directory object */ - BOOL streach /* FALSE: Do not streach table, TRUE: Streach table if needed */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ ) { DWORD clst; @@ -615,15 +782,15 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ if (clst <= 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dj->fs->max_clust) { /* When it reached end of dynamic table */ + if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ #if !_FS_READONLY BYTE c; - if (!streach) return FR_NO_FILE; /* When do not streach, report EOT */ - clst = create_chain(dj->fs, dj->clust); /* Streach cluster chain */ + if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ + clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ if (clst == 0) return FR_DENIED; /* No free cluster */ if (clst == 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - /* Clean-up streached table */ + /* Clean-up stretched table */ if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */ mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ @@ -661,7 +828,7 @@ const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN char static -BOOL cmp_lfn ( /* TRUE:Matched, FALSE:Not matched */ +int cmp_lfn ( /* 1:Matched, 0:Not matched */ WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ BYTE *dir /* Pointer to the directory entry containing a part of LFN */ ) @@ -677,22 +844,22 @@ BOOL cmp_lfn ( /* TRUE:Matched, FALSE:Not matched */ if (wc) { /* Last char has not been processed */ wc = ff_wtoupper(uc); /* Convert it to upper case */ if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ - return FALSE; /* Not matched */ + return 0; /* Not matched */ } else { - if (uc != 0xFFFF) return FALSE; /* Check filler */ + if (uc != 0xFFFF) return 0; /* Check filler */ } } while (++s < 13); /* Repeat until all chars in the entry are checked */ if ((dir[LDIR_Ord] & 0x40) && wc && lfnbuf[i]) /* Last segment matched but different length */ - return FALSE; + return 0; - return TRUE; /* The part of LFN matched */ + return 1; /* The part of LFN matched */ } static -BOOL pick_lfn ( /* TRUE:Succeeded, FALSE:Buffer overflow */ +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ BYTE *dir /* Pointer to the directory entry */ ) @@ -705,21 +872,21 @@ BOOL pick_lfn ( /* TRUE:Succeeded, FALSE:Buffer overflow */ s = 0; wc = 1; do { - uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ if (wc) { /* Last char has not been processed */ - if (i >= _MAX_LFN) return FALSE; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ } else { - if (uc != 0xFFFF) return FALSE; /* Check filler */ + if (uc != 0xFFFF) return 0; /* Check filler */ } } while (++s < 13); /* Read all character in the entry */ if (dir[LDIR_Ord] & 0x40) { /* Put terminator if it is the last LFN part */ - if (i >= _MAX_LFN) return FALSE; /* Buffer overflow? */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ lfnbuf[i] = 0; } - return TRUE; + return 1; } @@ -762,28 +929,30 @@ void fit_lfn ( /*-----------------------------------------------------------------------*/ #if _USE_LFN void gen_numname ( - BYTE *dst, /* Pointer to genartated SFN */ + BYTE *dst, /* Pointer to generated SFN */ const BYTE *src, /* Pointer to source SFN to be modified */ const WCHAR *lfn, /* Pointer to LFN */ - WORD num /* Sequense number */ + WORD seq /* Sequence number */ ) { - char ns[8]; + BYTE ns[8], c; int i, j; mem_cpy(dst, src, 11); - if (num > 5) { /* On many collisions, generate a hash number instead of sequencial number */ - do num = (num >> 1) + (num << 15) + (WORD)*lfn++; while (*lfn); + if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ + do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); } /* itoa */ i = 7; do { - ns[i--] = (num % 10) + '0'; - num /= 10; - } while (num); + c = (seq % 16) + '0'; + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); ns[i] = '~'; /* Append the number */ @@ -837,7 +1006,7 @@ FRESULT dir_find ( BYTE a, ord, sum; #endif - res = dir_seek(dj, 0); /* Rewind directory object */ + res = dir_sdi(dj, 0); /* Rewind directory object */ if (res != FR_OK) return res; #if _USE_LFN @@ -874,7 +1043,7 @@ FRESULT dir_find ( if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ break; #endif - res = dir_next(dj, FALSE); /* Next entry */ + res = dir_next(dj, 0); /* Next entry */ } while (res == FR_OK); return res; @@ -928,7 +1097,7 @@ FRESULT dir_read ( if (c != 0xE5 && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ break; #endif - res = dir_next(dj, FALSE); /* Next entry */ + res = dir_next(dj, 0); /* Next entry */ if (res != FR_OK) break; } @@ -963,7 +1132,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many if (_FS_RPATH && (sn[NS] & NS_DOT)) return FR_INVALID_NAME; /* Cannot create dot entry */ if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - fn[NS] = 0; dj->lfn = NULL; /* Find only SFN */ + fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ for (n = 1; n < 100; n++) { gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ res = dir_find(dj); /* Check if the name collides with existing SFN */ @@ -974,7 +1143,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many fn[NS] = sn[NS]; dj->lfn = lfn; } - if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve reserve an SFN + LFN entries. */ + if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */ for (ne = 0; lfn[ne]; ne++) ; ne = (ne + 25) / 13; } else { /* Otherwise reserve only an SFN entry. */ @@ -982,7 +1151,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many } /* Reserve contiguous entries */ - res = dir_seek(dj, 0); + res = dir_sdi(dj, 0); if (res != FR_OK) return res; n = is = 0; do { @@ -990,16 +1159,16 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many if (res != FR_OK) break; c = *dj->dir; /* Check the entry status */ if (c == 0xE5 || c == 0) { /* Is it a blank entry? */ - if (n == 0) is = dj->index; /* First index of the contigulus entry */ - if (++n == ne) break; /* A contiguous entry that requiered count is found */ + if (n == 0) is = dj->index; /* First index of the contiguous entry */ + if (++n == ne) break; /* A contiguous entry that required count is found */ } else { n = 0; /* Not a blank entry. Restart to search */ } - res = dir_next(dj, TRUE); /* Next entry with table streach */ + res = dir_next(dj, 1); /* Next entry with table stretch */ } while (res == FR_OK); if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */ - res = dir_seek(dj, is); + res = dir_sdi(dj, is); if (res == FR_OK) { sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */ ne--; @@ -1008,20 +1177,20 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many if (res != FR_OK) break; fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); dj->fs->wflag = 1; - res = dir_next(dj, FALSE); /* Next entry */ + res = dir_next(dj, 0); /* Next entry */ } while (res == FR_OK && --ne); } } #else /* Non LFN configuration */ - res = dir_seek(dj, 0); + res = dir_sdi(dj, 0); if (res == FR_OK) { do { /* Find a blank entry for the SFN */ res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; c = *dj->dir; if (c == 0xE5 || c == 0) break; /* Is it a blank entry? */ - res = dir_next(dj, TRUE); /* Next entry with table streach */ + res = dir_next(dj, 1); /* Next entry with table stretch */ } while (res == FR_OK); } #endif @@ -1032,7 +1201,9 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many dir = dj->dir; mem_set(dir, 0, 32); /* Clean the entry */ mem_cpy(dir, dj->fn, 11); /* Put SFN */ +#if _USE_LFN dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif dj->fs->wflag = 1; } } @@ -1058,7 +1229,7 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ WORD i; i = dj->index; /* SFN index */ - res = dir_seek(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ + res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ if (res == FR_OK) { do { res = move_window(dj->fs, dj->sect); @@ -1066,13 +1237,13 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ *dj->dir = 0xE5; /* Mark the entry "deleted" */ dj->fs->wflag = 1; if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ - res = dir_next(dj, FALSE); /* Next entry */ + res = dir_next(dj, 0); /* Next entry */ } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR; } #else /* Non LFN configuration */ - res = dir_seek(dj, dj->index); + res = dir_sdi(dj, dj->index); if (res == FR_OK) { res = move_window(dj->fs, dj->sect); if (res == FR_OK) { @@ -1096,18 +1267,18 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ static FRESULT create_name ( DIR *dj, /* Pointer to the directory object */ - const XCHAR **path /* Pointer to pointer to the segment in the path string */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ ) { #ifdef _EXCVT - static const BYTE cvt[] = _EXCVT; + static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ #endif #if _USE_LFN /* LFN configuration */ BYTE b, cf; WCHAR w, *lfn; int i, ni, si, di; - const XCHAR *p; + const TCHAR *p; /* Create LFN in Unicode */ si = di = 0; @@ -1133,7 +1304,7 @@ FRESULT create_name ( return FR_INVALID_NAME; lfn[di++] = w; /* Store the Unicode char */ } - *path = &p[si]; /* Rerurn pointer to the next segment */ + *path = &p[si]; /* Return pointer to the next segment */ cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ #if _FS_RPATH if ((di == 1 && lfn[di - 1] == '.') || /* Is this a dot entry? */ @@ -1150,7 +1321,7 @@ FRESULT create_name ( if (w != ' ' && w != '.') break; di--; } - if (!di) return FR_INVALID_NAME; /* Reject null string */ + if (!di) return FR_INVALID_NAME; /* Reject nul string */ lfn[di] = 0; /* LFN is created */ @@ -1163,7 +1334,7 @@ FRESULT create_name ( b = i = 0; ni = 8; for (;;) { w = lfn[si++]; /* Get an LFN char */ - if (!w) break; /* Break on enf of the LFN */ + if (!w) break; /* Break on end of the LFN */ if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ cf |= NS_LOSS | NS_LFN; continue; } @@ -1181,7 +1352,7 @@ FRESULT create_name ( if (w >= 0x80) { /* Non ASCII char */ #ifdef _EXCVT w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w) w = cvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ + if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ #else w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ #endif @@ -1194,7 +1365,7 @@ FRESULT create_name ( } dj->fn[i++] = (BYTE)(w >> 8); } else { /* Single byte char */ - if (!w || chk_chr("+,;[=]", w)) { /* Replace illegal chars for SFN */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ w = '_'; cf |= NS_LOSS | NS_LFN; /* Lossy conversion */ } else { if (IsUpper(w)) { /* ASCII large capital */ @@ -1237,18 +1408,18 @@ FRESULT create_name ( #if _FS_RPATH if (p[si] == '.') { /* Is this a dot entry? */ for (;;) { - c = p[si++]; + c = (BYTE)p[si++]; if (c != '.' || si >= 3) break; sfn[i++] = c; } if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = &p[si]; /* Rerurn pointer to the next segment */ + *path = &p[si]; /* Return pointer to the next segment */ sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ return FR_OK; } #endif for (;;) { - c = p[si++]; + c = (BYTE)p[si++]; if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ if (c == '.' || i >= ni) { if (ni != 8 || c != '.') return FR_INVALID_NAME; @@ -1257,22 +1428,22 @@ FRESULT create_name ( } if (c >= 0x80) { /* Extended char */ #ifdef _EXCVT - c = cvt[c - 0x80]; /* Convert extend char (SBCS) */ + c = excvt[c - 0x80]; /* Convert extend char (SBCS) */ #else - b |= 3; /* Eliminate NT flag if ext char is exist */ + b |= 3; /* Eliminate NT flag if extended char is exist */ #if !_DF1S /* ASCII only cfg */ return FR_INVALID_NAME; #endif #endif } if (IsDBCS1(c)) { /* DBC 1st byte? */ - d = p[si++]; /* Get 2nd byte */ + d = (BYTE)p[si++]; /* Get 2nd byte */ if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ return FR_INVALID_NAME; sfn[i++] = c; sfn[i++] = d; } else { /* Single byte code */ - if (chk_chr(" \"*+,[=]|\x7F", c)) /* Reject illegal chrs for SFN */ + if (chk_chr("\"*+,:<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ return FR_INVALID_NAME; if (IsUpper(c)) { /* ASCII large capital? */ b |= 2; @@ -1284,15 +1455,15 @@ FRESULT create_name ( sfn[i++] = c; } } - *path = &p[si]; /* Rerurn pointer to the next segment */ + *path = &p[si]; /* Return pointer to the next segment */ c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ - if (!i) return FR_INVALID_NAME; /* Reject null string */ + if (!i) return FR_INVALID_NAME; /* Reject nul string */ if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Filename has only small capital) */ + if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ sfn[NS] = c; /* Store NT flag, File name is created */ @@ -1314,8 +1485,8 @@ void get_fileinfo ( /* No return code */ ) { int i; - BYTE c, nt, *dir; - char *p; + BYTE nt, *dir; + TCHAR *p, c; p = fno->fname; @@ -1325,8 +1496,14 @@ void get_fileinfo ( /* No return code */ for (i = 0; i < 8; i++) { /* Copy name body */ c = dir[i]; if (c == ' ') break; - if (c == 0x05) c = 0xE5; + if (c == 0x05) c = (TCHAR)0xE5; if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i + 1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif *p++ = c; } if (dir[8] != ' ') { /* Copy name extension */ @@ -1335,6 +1512,12 @@ void get_fileinfo ( /* No return code */ c = dir[i]; if (c == ' ') break; if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i + 1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif *p++ = c; } } @@ -1347,7 +1530,7 @@ void get_fileinfo ( /* No return code */ #if _USE_LFN if (fno->lfname) { - XCHAR *tp = fno->lfname; + TCHAR *tp = fno->lfname; WCHAR w, *lfn; i = 0; @@ -1358,10 +1541,10 @@ void get_fileinfo ( /* No return code */ w = ff_convert(w, 0); /* Unicode -> OEM conversion */ if (!w) { i = 0; break; } /* Could not convert, no LFN */ if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC */ - tp[i++] = (XCHAR)(w >> 8); + tp[i++] = (TCHAR)(w >> 8); #endif if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overrun, no LFN */ - tp[i++] = (XCHAR)w; + tp[i++] = (TCHAR)w; } } tp[i] = 0; /* Terminator */ @@ -1380,18 +1563,17 @@ void get_fileinfo ( /* No return code */ static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ DIR *dj, /* Directory object to return last directory and found object */ - const XCHAR *path /* Full-path string to find a file or directory */ + const TCHAR *path /* Full-path string to find a file or directory */ ) { FRESULT res; - BYTE *dir, last; + BYTE *dir, ns; - while (!_USE_LFN && *path == ' ') path++; /* Skip leading spaces */ #if _FS_RPATH if (*path == '/' || *path == '\\') { /* There is a heading separator */ path++; dj->sclust = 0; /* Strip it and start from the root dir */ - } else { /* No heading saparator */ + } else { /* No heading separator */ dj->sclust = dj->fs->cdir; /* Start from the current dir */ } #else @@ -1400,24 +1582,31 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ dj->sclust = 0; /* Start from the root dir */ #endif - if ((UINT)*path < ' ') { /* Null path means the start directory itself */ - res = dir_seek(dj, 0); - dj->dir = NULL; + if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ + res = dir_sdi(dj, 0); + dj->dir = 0; } else { /* Follow path */ for (;;) { res = create_name(dj, &path); /* Get a segment */ if (res != FR_OK) break; res = dir_find(dj); /* Find it */ - last = *(dj->fn+NS) & NS_LAST; - if (res != FR_OK) { /* Could not find the object */ - if (res == FR_NO_FILE && !last) - res = FR_NO_PATH; + ns = *(dj->fn+NS); + if (res != FR_OK) { /* Failed to find the object */ + if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ + /* Object not found */ + if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ + dj->sclust = 0; dj->dir = 0; /* It is the root dir */ + res = FR_OK; + if (!(ns & NS_LAST)) continue; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; + } break; } - if (last) break; /* Last segment match. Function completed. */ - dir = dj->dir; /* There is next segment. Follow the sub directory */ - if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ + if (ns & NS_LAST) break; /* Last segment match. Function completed. */ + dir = dj->dir; /* There is next segment. Follow the sub directory */ + if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ res = FR_NO_PATH; break; } dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); @@ -1435,12 +1624,12 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /*-----------------------------------------------------------------------*/ static -BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */ +BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ FATFS *fs, /* File system object */ DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) { - if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK) /* Load boot record */ + if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ return 3; if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ return 2; @@ -1460,18 +1649,19 @@ BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2: /* Make sure that the file system is valid */ /*-----------------------------------------------------------------------*/ - -FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occured */ - const XCHAR **path, /* Pointer to pointer to the path name (drive number) */ +static +FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ FATFS **rfs, /* Pointer to pointer to the found file system object */ BYTE chk_wp /* !=0: Check media write protection for write access */ ) { - BYTE fmt, *tbl; + BYTE fmt, b, *tbl; UINT vol; DSTATUS stat; - DWORD bsect, fsize, tsect, mclst; - const XCHAR *p = *path; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + const TCHAR *p = *path; FATFS *fs; /* Get logical drive number from the path name */ @@ -1489,13 +1679,13 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occured */ /* Check if the logical drive is valid or not */ if (vol >= _DRIVES) /* Is the drive number valid? */ return FR_INVALID_DRIVE; - *rfs = fs = FatFs[vol]; /* Returen pointer to the corresponding file system object */ + *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ ENTER_FF(fs); /* Lock file system */ if (fs->fs_type) { /* If the logical drive has been mounted */ - stat = disk_status(fs->drive); + stat = disk_status(fs->drv); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ #if !_FS_READONLY if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ @@ -1505,25 +1695,25 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occured */ } } - /* The logical drive must be mounted. Following code attempts to mount the volume */ + /* The logical drive must be mounted. Following code attempts to mount the volume (initialize the file system object) */ fs->fs_type = 0; /* Clear the file system object */ - fs->drive = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drive); /* Initialize low level disk I/O layer */ + fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ if (stat & STA_NOINIT) /* Check if the drive is ready */ return FR_NOT_READY; #if _MAX_SS != 512 /* Get disk sector size if needed */ - if (disk_ioctl(fs->drive, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) return FR_NO_FILESYSTEM; #endif #if !_FS_READONLY if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ return FR_WRITE_PROTECTED; #endif - /* Search FAT partition on the drive */ - fmt = check_fs(fs, bsect = 0); /* Check sector 0 as an SFD format */ - if (fmt == 1) { /* Not an FAT boot record, it may be patitioned */ - /* Check a partition listed in top of the partition table */ + /* Search FAT partition on the drive (Supports only generic partitionings, FDISK and SFD) */ + fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */ + if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */ + /* Check the partition listed in top of the partition table */ tbl = &fs->win[MBR_Table + LD2PT(vol) * 16]; /* Partition table */ if (tbl[4]) { /* Is the partition existing? */ bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ @@ -1531,57 +1721,88 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occured */ } } if (fmt == 3) return FR_DISK_ERR; - if (fmt || LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* No valid FAT patition is found */ + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* Following code initializes the file system object */ + + if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ return FR_NO_FILESYSTEM; - /* Initialize the file system object */ - fsize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ - if (!fsize) fsize = LD_DWORD(fs->win+BPB_FATSz32); - fs->sects_fat = fsize; - fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */ - fsize *= fs->n_fats; /* (Number of sectors in FAT area) */ - fs->fatbase = bsect + LD_WORD(fs->win+BPB_RsvdSecCnt); /* FAT start sector (lba) */ - fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Nmuber of root directory entries */ + fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ + if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= b; /* Number of sectors for FAT area */ + + fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be 1,2,4...128) */ + + fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / 32)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); - fs->max_clust = mclst = (tsect /* Last cluster# + 1 (Number of clusters + 2) */ - - LD_WORD(fs->win+BPB_RsvdSecCnt) - fsize - fs->n_rootdir / (SS(fs)/32) - ) / fs->csize + 2; - fmt = FS_FAT12; /* Determine the FAT sub type */ - if (mclst >= 0xFF7) fmt = FS_FAT16; /* Number of clusters >= 0xFF5 */ - if (mclst >= 0xFFF7) fmt = FS_FAT32; /* Number of clusters >= 0xFFF5 */ + nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ - if (fmt == FS_FAT32) + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / 32); /* RSV+FAT+DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = FS_FAT12; + if (nclst >= MIN_FAT16) fmt = FS_FAT16; + if (nclst >= MIN_FAT32) fmt = FS_FAT32; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->database = bsect + sysect; /* Data start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + if (fmt == FS_FAT32) { + if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ - else - fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */ - fs->database = fs->fatbase + fsize + fs->n_rootdir / (SS(fs)/32); /* Data start sector (lba) */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } else { + if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (FAT size must not be less than FAT sectors */ + return FR_NO_FILESYSTEM; #if !_FS_READONLY - /* Initialize allocation information */ + /* Initialize cluster allocation information */ fs->free_clust = 0xFFFFFFFF; - fs->wflag = 0; - /* Get fsinfo if needed */ + fs->last_clust = 0; + + /* Get fsinfo if available */ if (fmt == FS_FAT32) { fs->fsi_flag = 0; fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); - if (disk_read(fs->drive, fs->win, fs->fsi_sector, 1) == RES_OK && + if (disk_read(fs->drv, 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); + fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); + fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); } } #endif fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ fs->winsect = 0; /* Invalidate sector cache */ + fs->wflag = 0; #if _FS_RPATH fs->cdir = 0; /* Current directory (root dir) */ #endif - fs->id = ++Fsid; /* File system mount ID */ +#if _FS_SHARE /* Clear file lock semaphores */ + for (vol = 0; vol < _FS_SHARE; vol++) + fs->flsem[vol].ctr = 0; +#endif return FR_OK; } @@ -1604,7 +1825,7 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ ENTER_FF(fs); /* Lock file system */ - if (disk_status(fs->drive) & STA_NOINIT) + if (disk_status(fs->drv) & STA_NOINIT) return FR_NOT_READY; return FR_OK; @@ -1622,7 +1843,7 @@ FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ /*-----------------------------------------------------------------------*/ -/* Mount/Unmount a Locical Drive */ +/* Mount/Unmount a Logical Drive */ /*-----------------------------------------------------------------------*/ FRESULT f_mount ( @@ -1664,93 +1885,127 @@ FRESULT f_mount ( FRESULT f_open ( FIL *fp, /* Pointer to the blank file object */ - const XCHAR *path, /* Pointer to the file name */ + const TCHAR *path, /* Pointer to the file name */ BYTE mode /* Access mode and file open mode flags */ ) { FRESULT res; DIR dj; - NAMEBUF(sfn, lfn); BYTE *dir; + DEF_NAMEBUF; - fp->fs = NULL; /* Clear file object */ + fp->fs = 0; /* Clear file object */ + #if !_FS_READONLY - mode &= (FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW); - res = chk_mounted(&path, &dj.fs, (BYTE)(mode & (FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW))); + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); #else mode &= FA_READ; res = chk_mounted(&path, &dj.fs, 0); #endif - if (res != FR_OK) LEAVE_FF(dj.fs, res); - INITBUF(dj, sfn, lfn); - res = follow_path(&dj, path); /* Follow the file path */ + INIT_BUF(dj); + if (res == FR_OK) + res = follow_path(&dj, path); /* Follow the file path */ + dir = dj.dir; -#if !_FS_READONLY +#if !_FS_READONLY /* R/W configuration */ + if (res == FR_OK) { + if (!dir) /* Current dir itself */ + res = FR_INVALID_NAME; +#if _FS_SHARE + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); +#endif + } /* Create or Open a file */ if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD ps, cl; + DWORD dw, cl; - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_SHARE + res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else res = dir_register(&dj); - if (res != FR_OK) LEAVE_FF(dj.fs, res); +#endif mode |= FA_CREATE_ALWAYS; - dir = dj.dir; /* Created entry (SFN entry) */ + dir = dj.dir; /* New entry */ } - else { /* Any object is already existing */ - if (mode & FA_CREATE_NEW) /* Cannot create new */ - LEAVE_FF(dj.fs, FR_EXIST); - dir = dj.dir; - if (!dir || (dir[DIR_Attr] & (AM_RDO | AM_DIR))) /* Cannot overwrite it (R/O or DIR) */ - LEAVE_FF(dj.fs, FR_DENIED); - if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero on over write mode */ - cl = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); /* Get start cluster */ - ST_WORD(dir+DIR_FstClusHI, 0); /* cluster = 0 */ - ST_WORD(dir+DIR_FstClusLO, 0); - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - dj.fs->wflag = 1; - ps = dj.fs->winsect; /* Remove the cluster chain */ - if (cl) { - res = remove_chain(dj.fs, cl); - if (res) LEAVE_FF(dj.fs, res); - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - } - res = move_window(dj.fs, ps); - if (res != FR_OK) LEAVE_FF(dj.fs, res); + else { /* Any object is already existing */ + if (mode & FA_CREATE_NEW) { /* Cannot create new */ + res = FR_EXIST; + } else { + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; } } - if (mode & FA_CREATE_ALWAYS) { + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); dir[DIR_Attr] = 0; /* Reset attribute */ - ps = get_fattime(); - ST_DWORD(dir+DIR_CrtTime, ps); /* Created time */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); /* Get start cluster */ + ST_WORD(dir+DIR_FstClusHI, 0); /* cluster = 0 */ + ST_WORD(dir+DIR_FstClusLO, 0); dj.fs->wflag = 1; - mode |= FA__WRITTEN; /* Set file changed flag */ + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } + } } } - /* Open an existing file */ - else { -#endif /* !_FS_READONLY */ - if (res != FR_OK) LEAVE_FF(dj.fs, res); /* Follow failed */ - dir = dj.dir; - if (!dir || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */ - LEAVE_FF(dj.fs, FR_NO_FILE); -#if !_FS_READONLY - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - LEAVE_FF(dj.fs, FR_DENIED); + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } + } } - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dj.dir; + if (res == FR_OK) { + if (mode & (FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) + mode |= FA__WRITTEN; /* Set file changed flag */ + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_SHARE + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; #endif - fp->flag = mode; /* File access mode */ - fp->org_clust = /* File start cluster */ - ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; fp->csect = 255; /* File pointer */ - fp->dsect = 0; - fp->fs = dj.fs; fp->id = dj.fs->id; /* Owner file system object of the file */ + } - LEAVE_FF(dj.fs, FR_OK); +#else /* R/O configuration */ + if (res == FR_OK) { /* Follow succeeded */ + if (!dir) { /* Current dir itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } + } +#endif + FREE_BUF(); + + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->org_clust = /* File start cluster */ + ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; +#if _USE_FASTSEEK + fp->cltbl = 0; /* No cluster link map table */ +#endif + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } + + LEAVE_FF(dj.fs, res); } @@ -1770,10 +2025,10 @@ FRESULT f_read ( FRESULT res; DWORD clst, sect, remain; UINT rcnt, cc; - BYTE *rbuff = buff; + BYTE csect, *rbuff = buff; - *br = 0; /* Initialize bytes read */ + *br = 0; /* Initialize byte counter */ res = validate(fp->fs, fp->id); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); @@ -1787,51 +2042,49 @@ FRESULT f_read ( for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ clst = (fp->fptr == 0) ? /* On the top of the file? */ fp->org_clust : get_fat(fp->fs, fp->curr_clust); if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->curr_clust = clst; /* Update current cluster */ - fp->csect = 0; /* Reset sector offset in the cluster */ } sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += fp->csect; + sect += csect; cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ if (cc) { /* Read maximum contiguous sectors directly */ - if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - fp->csect; - if (disk_read(fp->fs->drive, rbuff, sect, (BYTE)cc) != RES_OK) + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); -#if !_FS_READONLY && _FS_MINIMIZE <= 2 +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if _FS_TINY - if (fp->fs->wflag && fp->fs->winsect - sect < cc) /* Replace one of the read sectors with cached data if it contains a dirty sector */ + if (fp->fs->wflag && fp->fs->winsect - sect < cc) mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); #else - if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) /* Replace one of the read sectors with cached data if it contains a dirty sector */ + if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); #endif #endif - fp->csect += (BYTE)cc; /* Next sector address in the cluster */ rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ continue; } #if !_FS_TINY #if !_FS_READONLY if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */ - if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); fp->flag &= ~FA__DIRTY; } #endif if (fp->dsect != sect) { /* Fill sector buffer with file data */ - if (disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK) + if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); } #endif fp->dsect = sect; - fp->csect++; /* Next sector address in the cluster */ } rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; @@ -1866,9 +2119,10 @@ FRESULT f_write ( DWORD clst, sect; UINT wcnt, cc; const BYTE *wbuff = buff; + BYTE csect; - *bw = 0; /* Initialize bytes written */ + *bw = 0; /* Initialize byte counter */ res = validate(fp->fs, fp->id); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); @@ -1881,38 +2135,38 @@ FRESULT f_write ( for ( ; btw; /* Repeat until all data transferred */ wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ if (fp->fptr == 0) { /* On the top of the file? */ clst = fp->org_clust; /* Follow from the origin */ if (clst == 0) /* When there is no cluster chain, */ fp->org_clust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ } else { /* Middle or end of the file */ - clst = create_chain(fp->fs, fp->curr_clust); /* Follow or streach cluster chain */ + clst = create_chain(fp->fs, fp->curr_clust); /* Follow or stretch cluster chain */ } if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ if (clst == 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->curr_clust = clst; /* Update current cluster */ - fp->csect = 0; /* Reset sector address in the cluster */ } #if _FS_TINY if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write back data buffer prior to following direct transfer */ ABORT(fp->fs, FR_DISK_ERR); #else if (fp->flag & FA__DIRTY) { /* Write back data buffer prior to following direct transfer */ - if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); fp->flag &= ~FA__DIRTY; } #endif sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += fp->csect; + sect += csect; cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ if (cc) { /* Write maximum contiguous sectors directly */ - if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - fp->csect; - if (disk_write(fp->fs->drive, wbuff, sect, (BYTE)cc) != RES_OK) + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); #if _FS_TINY if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ @@ -1925,7 +2179,6 @@ FRESULT f_write ( fp->flag &= ~FA__DIRTY; } #endif - fp->csect += (BYTE)cc; /* Next sector address in the cluster */ wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ continue; } @@ -1937,12 +2190,11 @@ FRESULT f_write ( #else if (fp->dsect != sect) { /* Fill sector buffer with file data */ if (fp->fptr < fp->fsize && - disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK) + disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); } #endif fp->dsect = sect; - fp->csect++; /* Next sector address in the cluster */ } wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Put partial sector into file I/O buffer */ if (wcnt > btw) wcnt = btw; @@ -1984,7 +2236,7 @@ FRESULT f_sync ( if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ #if !_FS_TINY /* Write-back dirty buffer */ if (fp->flag & FA__DIRTY) { - if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) LEAVE_FF(fp->fs, FR_DISK_ERR); fp->flag &= ~FA__DIRTY; } @@ -1997,7 +2249,7 @@ FRESULT f_sync ( ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ ST_WORD(dir+DIR_FstClusLO, fp->org_clust); /* Update start cluster */ ST_WORD(dir+DIR_FstClusHI, fp->org_clust >> 16); - tim = get_fattime(); /* Updated time */ + tim = get_fattime(); /* Update updated time */ ST_DWORD(dir+DIR_WrtTime, tim); fp->flag &= ~FA__WRITTEN; fp->fs->wflag = 1; @@ -2024,14 +2276,28 @@ FRESULT f_close ( { FRESULT res; - #if _FS_READONLY - res = validate(fp->fs, fp->id); - if (res == FR_OK) fp->fs = NULL; - LEAVE_FF(fp->fs, res); + FATFS *fs = fp->fs; + res = validate(fs, fp->id); + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + LEAVE_FF(fs, res); + #else - res = f_sync(fp); - if (res == FR_OK) fp->fs = NULL; + res = f_sync(fp); /* Flush cached data */ +#if _FS_SHARE + if (res == FR_OK) { /* Decrement open counter */ +#if _FS_REENTRANT + res = validate(fp->fs, fp->id); + if (res == FR_OK) { + res = dec_lock(fp->fs, fp->lockid); + unlock_fs(fp->fs, FR_OK); + } +#else + res = dec_lock(fp->fs, fp->lockid); +#endif + } +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ return res; #endif } @@ -2060,28 +2326,29 @@ FRESULT f_chdrive ( FRESULT f_chdir ( - const XCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { FRESULT res; DIR dj; - NAMEBUF(sfn, lfn); BYTE *dir; + DEF_NAMEBUF; res = chk_mounted(&path, &dj.fs, 0); if (res == FR_OK) { - INITBUF(dj, sfn, lfn); - res = follow_path(&dj, path); /* Follow the file path */ + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the path */ + FREE_BUF(); if (res == FR_OK) { /* Follow completed */ dir = dj.dir; /* Pointer to the entry */ if (!dir) { - dj.fs->cdir = 0; /* No entry (root dir) */ + dj.fs->cdir = dj.sclust; /* Start directory itself */ } else { - if (dir[DIR_Attr] & AM_DIR) /* Reached to the dir */ + if (dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ dj.fs->cdir = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); else - res = FR_NO_PATH; /* Could not reach the dir (it is a file) */ + res = FR_NO_PATH; /* Reached but a file */ } } if (res == FR_NO_FILE) res = FR_NO_PATH; @@ -2105,94 +2372,159 @@ FRESULT f_lseek ( ) { FRESULT res; - DWORD clst, bcs, nsect, ifptr; res = validate(fp->fs, fp->id); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Check abort flag */ LEAVE_FF(fp->fs, FR_INT_ERR); - if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ -#if !_FS_READONLY - && !(fp->flag & FA_WRITE) -#endif - ) ofs = fp->fsize; - ifptr = fp->fptr; - fp->fptr = nsect = 0; fp->csect = 255; - if (ofs > 0) { - bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->curr_clust; - } else { /* When seek to back cluster, */ - clst = fp->org_clust; /* start from the first cluster */ -#if !_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(fp->fs, 0); - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->org_clust = clst; - } -#endif - fp->curr_clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ -#if !_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - clst = create_chain(fp->fs, clst); /* Force streached if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ - ofs = bcs; break; +#if _USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + DWORD cl, pcl, ncl, tcl, dsc, tlen, *tbl = fp->cltbl; + BYTE csc; + + tlen = *tbl++; + if (ofs == CREATE_LINKMAP) { /* Create link map table */ + cl = fp->org_clust; + if (cl) { + do { + if (tlen < 4) { /* Not enough table items */ + res = FR_NOT_ENOUGH_CORE; break; } - } else -#endif - clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fp->fs->max_clust) ABORT(fp->fs, FR_INT_ERR); - fp->curr_clust = clst; - fp->fptr += bcs; - ofs -= bcs; + tcl = cl; ncl = 0; + do { /* Get a fragment and store the top and length */ + pcl = cl; ncl++; + cl = get_fat(fp->fs, cl); + if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + } while (cl == pcl + 1); + *tbl++ = ncl; *tbl++ = tcl; + tlen -= 2; + } while (cl < fp->fs->n_fatent); } - fp->fptr += ofs; - fp->csect = (BYTE)(ofs / SS(fp->fs)); /* Sector offset in the cluster */ - if (ofs % SS(fp->fs)) { - nsect = clust2sect(fp->fs, clst); /* Current sector */ - if (!nsect) ABORT(fp->fs, FR_INT_ERR); - nsect += fp->csect; - fp->csect++; - } - } - } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { + *tbl = 0; /* Terminate table */ + + } else { /* Fast seek */ + if (ofs > fp->fsize) /* Clip offset at the file size */ + ofs = fp->fsize; + fp->fptr = ofs; /* Set file pointer */ + if (ofs) { + dsc = (ofs - 1) / SS(fp->fs); + cl = dsc / fp->fs->csize; + for (;;) { + ncl = *tbl++; + if (!ncl) ABORT(fp->fs, FR_INT_ERR); + if (cl < ncl) break; + cl -= ncl; tbl++; + } + fp->curr_clust = cl + *tbl; + csc = (BYTE)(dsc & (fp->fs->csize - 1)); + dsc = clust2sect(fp->fs, fp->curr_clust); + if (!dsc) ABORT(fp->fs, FR_INT_ERR); + dsc += csc; + if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { #if !_FS_TINY #if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty buffer if needed */ - if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) + if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ +#if !_FS_READONLY + && !(fp->flag & FA_WRITE) +#endif + ) ofs = fp->fsize; + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs) { + bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->curr_clust; + } else { /* When seek to back cluster, */ + clst = fp->org_clust; /* start from the first cluster */ +#if !_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(fp->fs, 0); + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->org_clust = clst; + } +#endif + fp->curr_clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ +#if !_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ + if (clst == 0) { /* When disk gets full, clip file size */ + ofs = bcs; break; + } + } else +#endif + clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); + fp->curr_clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + fp->fptr += ofs; + if (ofs % SS(fp->fs)) { + nsect = clust2sect(fp->fs, clst); /* Current sector */ + if (!nsect) ABORT(fp->fs, FR_INT_ERR); + nsect += ofs / SS(fp->fs); + } + } + } + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Flush dirty buffer if needed */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; +#endif + fp->dsect = nsect; + } +#if !_FS_READONLY + if (fp->fptr > fp->fsize) { /* Set changed flag if the file size is extended */ + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; } #endif - if (disk_read(fp->fs->drive, fp->buf, nsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = nsect; } -#if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set changed flag if the file size is extended */ - fp->fsize = fp->fptr; - fp->flag |= FA__WRITTEN; - } -#endif LEAVE_FF(fp->fs, res); } - #if _FS_MINIMIZE <= 1 /*-----------------------------------------------------------------------*/ /* Create a Directroy Object */ @@ -2200,21 +2532,22 @@ FRESULT f_lseek ( FRESULT f_opendir ( DIR *dj, /* Pointer to directory object to create */ - const XCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { FRESULT res; - NAMEBUF(sfn, lfn); BYTE *dir; + DEF_NAMEBUF; res = chk_mounted(&path, &dj->fs, 0); if (res == FR_OK) { - INITBUF((*dj), sfn, lfn); + INIT_BUF(*dj); res = follow_path(dj, path); /* Follow the path to the directory */ + FREE_BUF(); if (res == FR_OK) { /* Follow completed */ dir = dj->dir; - if (dir) { /* It is not the root dir */ + if (dir) { /* It is not the current dir */ if (dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ dj->sclust = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); } else { /* The object is not a directory */ @@ -2223,7 +2556,7 @@ FRESULT f_opendir ( } if (res == FR_OK) { dj->id = dj->fs->id; - res = dir_seek(dj, 0); /* Rewind dir */ + res = dir_sdi(dj, 0); /* Rewind dir */ } } if (res == FR_NO_FILE) res = FR_NO_PATH; @@ -2245,15 +2578,15 @@ FRESULT f_readdir ( ) { FRESULT res; - NAMEBUF(sfn, lfn); + DEF_NAMEBUF; res = validate(dj->fs, dj->id); /* Check validity of the object */ if (res == FR_OK) { - INITBUF((*dj), sfn, lfn); if (!fno) { - res = dir_seek(dj, 0); + res = dir_sdi(dj, 0); } else { + INIT_BUF(*dj); res = dir_read(dj); if (res == FR_NO_FILE) { dj->sect = 0; @@ -2261,12 +2594,13 @@ FRESULT f_readdir ( } if (res == FR_OK) { /* A valid entry is found */ get_fileinfo(dj, fno); /* Get the object information */ - res = dir_next(dj, FALSE); /* Increment index for next */ + res = dir_next(dj, 0); /* Increment index for next */ if (res == FR_NO_FILE) { dj->sect = 0; res = FR_OK; } } + FREE_BUF(); } } @@ -2281,25 +2615,26 @@ FRESULT f_readdir ( /*-----------------------------------------------------------------------*/ FRESULT f_stat ( - const XCHAR *path, /* Pointer to the file path */ + const TCHAR *path, /* Pointer to the file path */ FILINFO *fno /* Pointer to file information to return */ ) { FRESULT res; DIR dj; - NAMEBUF(sfn, lfn); + DEF_NAMEBUF; res = chk_mounted(&path, &dj.fs, 0); if (res == FR_OK) { - INITBUF(dj, sfn, lfn); + INIT_BUF(dj); res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follwo completed */ - if (dj.dir) /* Found an object */ + if (res == FR_OK) { /* Follow completed */ + if (dj.dir) /* Found an object */ get_fileinfo(&dj, fno); - else /* It is root dir */ + else /* It is root dir */ res = FR_INVALID_NAME; } + FREE_BUF(); } LEAVE_FF(dj.fs, res); @@ -2313,7 +2648,7 @@ FRESULT f_stat ( /*-----------------------------------------------------------------------*/ FRESULT f_getfree ( - const XCHAR *path, /* Pointer to the logical drive number (root dir) */ + const TCHAR *path, /* Pointer to the logical drive number (root dir) */ DWORD *nclst, /* Pointer to the variable to return number of free clusters */ FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ ) @@ -2326,51 +2661,48 @@ FRESULT f_getfree ( /* Get drive number */ res = chk_mounted(&path, fatfs, 0); - if (res != FR_OK) LEAVE_FF(*fatfs, res); - - /* If number of free cluster is valid, return it without cluster scan. */ - if ((*fatfs)->free_clust <= (*fatfs)->max_clust - 2) { - *nclst = (*fatfs)->free_clust; - LEAVE_FF(*fatfs, FR_OK); - } - - /* Get number of free clusters */ - fat = (*fatfs)->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - stat = get_fat(*fatfs, clst); - if (stat == 0xFFFFFFFF) LEAVE_FF(*fatfs, FR_DISK_ERR); - if (stat == 1) LEAVE_FF(*fatfs, FR_INT_ERR); - if (stat == 0) n++; - } while (++clst < (*fatfs)->max_clust); - } else { - clst = (*fatfs)->max_clust; - sect = (*fatfs)->fatbase; - i = 0; p = 0; - do { - if (!i) { - res = move_window(*fatfs, sect++); - if (res != FR_OK) - LEAVE_FF(*fatfs, res); - p = (*fatfs)->win; - i = SS(*fatfs); - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; i -= 2; + if (res == FR_OK) { + /* If free_clust is valid, return it without full cluster scan */ + if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { + *nclst = (*fatfs)->free_clust; + } else { + /* Get number of free clusters */ + fat = (*fatfs)->fs_type; + n = 0; + if (fat == FS_FAT12) { + clst = 2; + do { + stat = get_fat(*fatfs, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) n++; + } while (++clst < (*fatfs)->n_fatent); } else { - if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; - p += 4; i -= 4; + clst = (*fatfs)->n_fatent; + sect = (*fatfs)->fatbase; + i = 0; p = 0; + do { + if (!i) { + res = move_window(*fatfs, sect++); + if (res != FR_OK) break; + p = (*fatfs)->win; + i = SS(*fatfs); + } + if (fat == FS_FAT16) { + if (LD_WORD(p) == 0) n++; + p += 2; i -= 2; + } else { + if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; + p += 4; i -= 4; + } + } while (--clst); } - } while (--clst); + (*fatfs)->free_clust = n; + if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; + *nclst = n; + } } - (*fatfs)->free_clust = n; - if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; - *nclst = n; - - LEAVE_FF(*fatfs, FR_OK); + LEAVE_FF(*fatfs, res); } @@ -2389,30 +2721,34 @@ FRESULT f_truncate ( res = validate(fp->fs, fp->id); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->flag & FA__ERROR) /* Check abort flag */ - LEAVE_FF(fp->fs, FR_INT_ERR); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - - if (fp->fsize > fp->fptr) { - fp->fsize = fp->fptr; /* Set file size to current R/W point */ - fp->flag |= FA__WRITTEN; - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->org_clust); - fp->org_clust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->curr_clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fp->fs->max_clust) { - res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF); - if (res == FR_OK) res = remove_chain(fp->fs, ncl); - } + if (res == FR_OK) { + if (fp->flag & FA__ERROR) { /* Check abort flag */ + res = FR_INT_ERR; + } else { + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + res = FR_DENIED; } } - if (res != FR_OK) fp->flag |= FA__ERROR; + if (res == FR_OK) { + if (fp->fsize > fp->fptr) { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(fp->fs, fp->org_clust); + fp->org_clust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(fp->fs, fp->curr_clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fp->fs->n_fatent) { + res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF); + if (res == FR_OK) res = remove_chain(fp->fs, ncl); + } + } + } + if (res != FR_OK) fp->flag |= FA__ERROR; + } LEAVE_FF(fp->fs, res); } @@ -2425,50 +2761,63 @@ FRESULT f_truncate ( /*-----------------------------------------------------------------------*/ FRESULT f_unlink ( - const XCHAR *path /* Pointer to the file or directory path */ + const TCHAR *path /* Pointer to the file or directory path */ ) { FRESULT res; DIR dj, sdj; - NAMEBUF(sfn, lfn); BYTE *dir; DWORD dclst; + DEF_NAMEBUF; res = chk_mounted(&path, &dj.fs, 1); - if (res != FR_OK) LEAVE_FF(dj.fs, res); - - INITBUF(dj, sfn, lfn); - res = follow_path(&dj, path); /* Follow the file path */ - if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res != FR_OK) LEAVE_FF(dj.fs, res); /* Follow failed */ - - dir = dj.dir; - if (!dir) /* Is it the root directory? */ - LEAVE_FF(dj.fs, FR_INVALID_NAME); - if (dir[DIR_Attr] & AM_RDO) /* Is it a R/O object? */ - LEAVE_FF(dj.fs, FR_DENIED); - dclst = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); - - if (dir[DIR_Attr] & AM_DIR) { /* It is a sub-directory */ - if (dclst < 2) LEAVE_FF(dj.fs, FR_INT_ERR); - mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ - sdj.sclust = dclst; - res = dir_seek(&sdj, 2); - if (res != FR_OK) LEAVE_FF(dj.fs, res); - res = dir_read(&sdj); - if (res == FR_OK) res = FR_DENIED; /* Not empty sub-dir */ - if (res != FR_NO_FILE) LEAVE_FF(dj.fs, res); - } - - res = dir_remove(&dj); /* Remove directory entry */ if (res == FR_OK) { - if (dclst) - res = remove_chain(dj.fs, dclst); /* Remove the cluster chain */ - if (res == FR_OK) res = sync(dj.fs); + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; /* Cannot remove dot entry */ +#if _FS_SHARE + if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ +#endif + if (res == FR_OK) { /* The object is accessible */ + dir = dj.dir; + if (!dir) { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } else { + if (dir[DIR_Attr] & AM_RDO) + res = FR_DENIED; /* Cannot remove R/O object */ + } + dclst = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ + if (dclst < 2) { + res = FR_INT_ERR; + } else { + mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ + sdj.sclust = dclst; + res = dir_sdi(&sdj, 2); /* Exclude dot entries */ + if (res == FR_OK) { + res = dir_read(&sdj); + if (res == FR_OK /* Not empty dir */ +#if _FS_RPATH + || dclst == sdj.fs->cdir /* Current dir */ +#endif + ) res = FR_DENIED; + if (res == FR_NO_FILE) res = FR_OK; /* Empty */ + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK) { + if (dclst) /* Remove the cluster chain if exist */ + res = remove_chain(dj.fs, dclst); + if (res == FR_OK) res = sync(dj.fs); + } + } + } + FREE_BUF(); } - LEAVE_FF(dj.fs, res); } @@ -2480,72 +2829,69 @@ FRESULT f_unlink ( /*-----------------------------------------------------------------------*/ FRESULT f_mkdir ( - const XCHAR *path /* Pointer to the directory path */ + const TCHAR *path /* Pointer to the directory path */ ) { FRESULT res; DIR dj; - NAMEBUF(sfn, lfn); BYTE *dir, n; - DWORD dsect, dclst, pclst, tim; + DWORD dsc, dcl, pcl, tim = get_fattime(); + DEF_NAMEBUF; res = chk_mounted(&path, &dj.fs, 1); - if (res != FR_OK) LEAVE_FF(dj.fs, res); - - INITBUF(dj, sfn, lfn); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Any file or directory is already existing */ - if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) - res = FR_INVALID_NAME; - if (res != FR_NO_FILE) /* Any error occured */ - LEAVE_FF(dj.fs, res); - - dclst = create_chain(dj.fs, 0); /* Allocate a new cluster for new directory table */ - res = FR_OK; - if (dclst == 0) res = FR_DENIED; - if (dclst == 1) res = FR_INT_ERR; - if (dclst == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) - res = move_window(dj.fs, 0); - if (res != FR_OK) LEAVE_FF(dj.fs, res); - dsect = clust2sect(dj.fs, dclst); - - dir = dj.fs->win; /* Initialize the new directory table */ - mem_set(dir, 0, SS(dj.fs)); - mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */ - dir[DIR_Name] = '.'; - dir[DIR_Attr] = AM_DIR; - tim = get_fattime(); - ST_DWORD(dir+DIR_WrtTime, tim); - ST_WORD(dir+DIR_FstClusLO, dclst); - ST_WORD(dir+DIR_FstClusHI, dclst >> 16); - mem_cpy(dir+32, dir, 32); /* Create ".." entry */ - dir[33] = '.'; - pclst = dj.sclust; - if (dj.fs->fs_type == FS_FAT32 && pclst == dj.fs->dirbase) - pclst = 0; - ST_WORD(dir+32+DIR_FstClusLO, pclst); - ST_WORD(dir+32+DIR_FstClusHI, pclst >> 16); - for (n = 0; n < dj.fs->csize; n++) { /* Write dot entries and clear left sectors */ - dj.fs->winsect = dsect++; - dj.fs->wflag = 1; - res = move_window(dj.fs, 0); - if (res) LEAVE_FF(dj.fs, res); - mem_set(dir, 0, SS(dj.fs)); - } - - res = dir_register(&dj); - if (res != FR_OK) { - remove_chain(dj.fs, dclst); - } else { - dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir+DIR_WrtTime, tim); /* Crated time */ - ST_WORD(dir+DIR_FstClusLO, dclst); /* Table start cluster */ - ST_WORD(dir+DIR_FstClusHI, dclst >> 16); - dj.fs->wflag = 1; - res = sync(dj.fs); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) /* Flush FAT */ + res = move_window(dj.fs, 0); + if (res == FR_OK) { /* Initialize the new directory table */ + dsc = clust2sect(dj.fs, dcl); + dir = dj.fs->win; + mem_set(dir, 0, SS(dj.fs)); + mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD(dir+DIR_WrtTime, tim); + ST_WORD(dir+DIR_FstClusLO, dcl); + ST_WORD(dir+DIR_FstClusHI, dcl >> 16); + mem_cpy(dir+32, dir, 32); /* Create ".." entry */ + dir[33] = '.'; pcl = dj.sclust; + if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) + pcl = 0; + ST_WORD(dir+32+DIR_FstClusLO, pcl); + ST_WORD(dir+32+DIR_FstClusHI, pcl >> 16); + for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = move_window(dj.fs, 0); + if (res != FR_OK) break; + mem_set(dir, 0, SS(dj.fs)); + } + } + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ + if (res != FR_OK) { + remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ + } else { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ + ST_WORD(dir+DIR_FstClusLO, dcl); /* Table start cluster */ + ST_WORD(dir+DIR_FstClusHI, dcl >> 16); + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + FREE_BUF(); } LEAVE_FF(dj.fs, res); @@ -2555,25 +2901,26 @@ FRESULT f_mkdir ( /*-----------------------------------------------------------------------*/ -/* Change File Attribute */ +/* Change Attribute */ /*-----------------------------------------------------------------------*/ FRESULT f_chmod ( - const XCHAR *path, /* Pointer to the file path */ + const TCHAR *path, /* Pointer to the file path */ BYTE value, /* Attribute bits */ BYTE mask /* Attribute mask to change */ ) { FRESULT res; DIR dj; - NAMEBUF(sfn, lfn); BYTE *dir; + DEF_NAMEBUF; res = chk_mounted(&path, &dj.fs, 1); if (res == FR_OK) { - INITBUF(dj, sfn, lfn); + INIT_BUF(dj); res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; if (res == FR_OK) { @@ -2600,27 +2947,28 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ FRESULT f_utime ( - const XCHAR *path, /* Pointer to the file/directory name */ - const FILINFO *fno /* Pointer to the timestamp to be set */ + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ ) { FRESULT res; DIR dj; - NAMEBUF(sfn, lfn); BYTE *dir; + DEF_NAMEBUF; res = chk_mounted(&path, &dj.fs, 1); if (res == FR_OK) { - INITBUF(dj, sfn, lfn); + INIT_BUF(dj); res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; if (res == FR_OK) { dir = dj.dir; - if (!dir) { /* Root directory */ + if (!dir) { /* Root directory */ res = FR_INVALID_NAME; - } else { /* File or sub-directory */ + } else { /* File or sub-directory */ ST_WORD(dir+DIR_WrtTime, fno->ftime); ST_WORD(dir+DIR_WrtDate, fno->fdate); dj.fs->wflag = 1; @@ -2640,64 +2988,71 @@ FRESULT f_utime ( /*-----------------------------------------------------------------------*/ FRESULT f_rename ( - const XCHAR *path_old, /* Pointer to the old name */ - const XCHAR *path_new /* Pointer to the new name */ + const TCHAR *path_old, /* Pointer to the old name */ + const TCHAR *path_new /* Pointer to the new name */ ) { FRESULT res; - DIR dj_old, dj_new; - NAMEBUF(sfn, lfn); + DIR djo, djn; BYTE buf[21], *dir; DWORD dw; + DEF_NAMEBUF; - INITBUF(dj_old, sfn, lfn); - res = chk_mounted(&path_old, &dj_old.fs, 1); + res = chk_mounted(&path_old, &djo.fs, 1); if (res == FR_OK) { - dj_new.fs = dj_old.fs; - res = follow_path(&dj_old, path_old); /* Check old object */ - if (_FS_RPATH && res == FR_OK && (dj_old.fn[NS] & NS_DOT)) + djn.fs = djo.fs; + INIT_BUF(djo); + res = follow_path(&djo, path_old); /* Check old object */ + if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; - } - if (res != FR_OK) LEAVE_FF(dj_old.fs, res); /* The old object is not found */ - - if (!dj_old.dir) LEAVE_FF(dj_old.fs, FR_NO_FILE); /* Is root dir? */ - mem_cpy(buf, dj_old.dir+DIR_Attr, 21); /* Save the object information */ - - mem_cpy(&dj_new, &dj_old, sizeof(DIR)); - res = follow_path(&dj_new, path_new); /* Check new object */ - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ - res = dir_register(&dj_new); /* Register the new object */ - if (res == FR_OK) { - dir = dj_new.dir; /* Copy object information into new entry */ - mem_cpy(dir+13, buf+2, 19); - dir[DIR_Attr] = buf[0] | AM_ARC; - dj_old.fs->wflag = 1; - if (dir[DIR_Attr] & AM_DIR) { /* Update .. entry in the directory if needed */ - dw = clust2sect(dj_new.fs, (DWORD)LD_WORD(dir+DIR_FstClusHI) | LD_WORD(dir+DIR_FstClusLO)); - if (!dw) { - res = FR_INT_ERR; - } else { - res = move_window(dj_new.fs, dw); - dir = dj_new.fs->win+32; - if (res == FR_OK && dir[1] == '.') { - dw = (dj_new.fs->fs_type == FS_FAT32 && dj_new.sclust == dj_new.fs->dirbase) ? 0 : dj_new.sclust; - ST_WORD(dir+DIR_FstClusLO, dw); - ST_WORD(dir+DIR_FstClusHI, dw >> 16); - dj_new.fs->wflag = 1; +#if _FS_SHARE + if (res == FR_OK) res = chk_lock(&djo, 2); +#endif + if (res == FR_OK) { /* Old object is found */ + if (!djo.dir) { /* Is root dir? */ + res = FR_NO_FILE; + } else { + mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ + mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ + res = follow_path(&djn, path_new); + if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ + if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ +/* Start critical section that any interruption or error can cause cross-link */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy(dir+13, buf+2, 19); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ + dw = clust2sect(djn.fs, (DWORD)LD_WORD(dir+DIR_FstClusHI) | LD_WORD(dir+DIR_FstClusLO)); + if (!dw) { + res = FR_INT_ERR; + } else { + res = move_window(djn.fs, dw); + dir = djn.fs->win+32; /* .. entry */ + if (res == FR_OK && dir[1] == '.') { + dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; + ST_WORD(dir+DIR_FstClusLO, dw); + ST_WORD(dir+DIR_FstClusHI, dw >> 16); + djn.fs->wflag = 1; + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) + res = sync(djo.fs); + } } +/* End critical section */ } } - if (res == FR_OK) { - res = dir_remove(&dj_old); /* Remove old entry */ - if (res == FR_OK) - res = sync(dj_old.fs); - } } + FREE_BUF(); } - - LEAVE_FF(dj_old.fs, res); + LEAVE_FF(djo.fs, res); } #endif /* !_FS_READONLY */ @@ -2708,7 +3063,7 @@ FRESULT f_rename ( /*-----------------------------------------------------------------------*/ -/* Forward data to the stream directly (Available on only _FS_TINY cfg) */ +/* Forward data to the stream directly (available on only tiny cfg) */ /*-----------------------------------------------------------------------*/ #if _USE_FORWARD && _FS_TINY @@ -2722,9 +3077,10 @@ FRESULT f_forward ( FRESULT res; DWORD remain, clst, sect; UINT rcnt; + BYTE csect; - *bf = 0; + *bf = 0; /* Initialize byte counter */ res = validate(fp->fs, fp->id); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); @@ -2736,22 +3092,21 @@ FRESULT f_forward ( remain = fp->fsize - fp->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - for ( ; btr && (*func)(NULL, 0); /* Repeat until all data transferred or stream becomes busy */ + for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) { + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */ + if (!csect) { /* On the cluster boundary? */ clst = (fp->fptr == 0) ? /* On the top of the file? */ fp->org_clust : get_fat(fp->fs, fp->curr_clust); if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->curr_clust = clst; /* Update current cluster */ - fp->csect = 0; /* Reset sector address in the cluster */ } - fp->csect++; /* Next sector address in the cluster */ } sect = clust2sect(fp->fs, fp->curr_clust); /* Get current data sector */ if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += fp->csect - 1; + sect += csect; if (move_window(fp->fs, sect)) /* Move sector window */ ABORT(fp->fs, FR_DISK_ERR); fp->dsect = sect; @@ -2771,34 +3126,29 @@ FRESULT f_forward ( /*-----------------------------------------------------------------------*/ /* Create File System on the Drive */ /*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Multiple of 32 and <= 2048 */ +#define N_ROOTDIR 512 /* Multiple of 32 */ #define N_FATS 1 /* 1 or 2 */ -#define MAX_SECTOR 131072000UL /* Maximum partition size */ -#define MIN_SECTOR 2000UL /* Minimum partition size */ FRESULT f_mkfs ( - BYTE drv, /* Logical drive number */ - BYTE partition, /* Partitioning rule 0:FDISK, 1:SFD */ - WORD allocsize /* Allocation unit size [bytes] */ + BYTE drv, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit size [bytes] */ ) { - static const DWORD sstbl[] = { 2048000, 1024000, 512000, 256000, 128000, 64000, 32000, 16000, 8000, 4000, 0 }; - static const WORD cstbl[] = { 32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512 }; - BYTE fmt, m, *tbl; - 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_clst, d, n; - WORD as; + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + BYTE fmt, md, *tbl; + DWORD n_clst, vs, n; + UINT as, i; + DWORD b_vol, b_fat, b_dir, b_data; /* Area offset (LBA) */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Area size */ FATFS *fs; DSTATUS stat; - /* Check validity of the parameters */ - if (drv >= _DRIVES) return FR_INVALID_DRIVE; - if (partition >= 2) return FR_MKFS_ABORTED; - /* Check mounted drive and clear work area */ + if (drv >= _DRIVES) return FR_INVALID_DRIVE; fs = FatFs[drv]; if (!fs) return FR_NOT_ENABLED; fs->fs_type = 0; @@ -2808,70 +3158,71 @@ FRESULT f_mkfs ( stat = disk_initialize(drv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; -#if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK - || SS(fs) > _MAX_SS) - return FR_MKFS_ABORTED; +#if _MAX_SS != 512 /* Get disk sector size */ + if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + return FR_DISK_ERR; #endif - if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR) - return FR_MKFS_ABORTED; - if (n_part > MAX_SECTOR) n_part = MAX_SECTOR; - b_part = (!partition) ? 63 : 0; /* Boot sector */ - n_part -= b_part; - for (d = 512; d <= 32768U && d != allocsize; d <<= 1) ; /* Check validity of the allocation unit size */ - if (d != allocsize) allocsize = 0; - if (!allocsize) { /* Auto selection of cluster size */ - d = n_part; - for (as = SS(fs); as > 512U; as >>= 1) d >>= 1; - for (n = 0; d < sstbl[n]; n++) ; - allocsize = cstbl[n]; + if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd == 1) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; + if (au & (au - 1)) au = 0; /* Check validity of the allocation unit size */ + if (!au) { /* AU auto selection */ + vs = n_vol / (2000 / (SS(fs) / 512)); + for (i = 0; vs < vst[i]; i++) ; + au = cst[i]; } - if (allocsize < SS(fs)) allocsize = SS(fs); + if (_MAX_SS != 512 && au < SS(fs)) au = SS(fs); + au /= SS(fs); /* Number of sectors per cluster */ + if (au == 0) au = 1; + if (au > 128) au = 128; - allocsize /= SS(fs); /* Number of sectors per cluster */ - - /* Pre-compute number of clusters and FAT type */ - n_clst = n_part / allocsize; + /* Pre-compute number of clusters and FAT syb-type */ + n_clst = n_vol / au; fmt = FS_FAT12; - if (n_clst >= 0xFF5) fmt = FS_FAT16; - if (n_clst >= 0xFFF5) fmt = FS_FAT32; + if (n_clst >= MIN_FAT16) fmt = FS_FAT16; + if (n_clst >= MIN_FAT32) fmt = FS_FAT32; /* Determine offset and size of FAT structure */ - switch (fmt) { - case FS_FAT12: - n_fat = ((n_clst * 3 + 1) / 2 + 3 + SS(fs) - 1) / SS(fs); - n_rsv = 1 + partition; - n_dir = N_ROOTDIR * 32 / SS(fs); - break; - case FS_FAT16: - n_fat = ((n_clst * 2) + 4 + SS(fs) - 1) / SS(fs); - n_rsv = 1 + partition; - n_dir = N_ROOTDIR * 32 / SS(fs); - break; - default: + if (fmt == FS_FAT32) { n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); - n_rsv = 33 - partition; + n_rsv = 32; n_dir = 0; + } else { + n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; + n_fat = (n_fat + SS(fs) - 1) / SS(fs); + n_rsv = 1; + n_dir = N_ROOTDIR * 32UL / SS(fs); } - b_fat = b_part + n_rsv; /* FATs start sector */ - b_dir = b_fat + n_fat * N_FATS; /* Directory start sector */ - b_data = b_dir + n_dir; /* Data start sector */ + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */ /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK) return FR_MKFS_ABORTED; - n = (b_data + n - 1) & ~(n - 1); - n_fat += (n - b_data) / N_FATS; + if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK) return FR_DISK_ERR; + if (!n || n > 32768) return FR_MKFS_ABORTED; + n = (b_data + n - 1) & ~(n - 1); /* Next nearest boundary from current data start */ + n = (n - b_data) / N_FATS; + if (fmt == FS_FAT32) { /* FAT32: Move FAT start */ + n_rsv += n; + b_fat += n; + } else { /* FAT12/16: Expand FAT size */ + n_fat += n; + } /* b_dir and b_data are no longer used below */ - /* Determine number of cluster and final check of validity of the FAT type */ - n_clst = (n_part - n_rsv - n_fat * N_FATS - n_dir) / allocsize; - if ( (fmt == FS_FAT16 && n_clst < 0xFF5) - || (fmt == FS_FAT32 && n_clst < 0xFFF5)) + /* Determine number of cluster and final check of validity of the FAT sub-type */ + n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; + if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) + || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) return FR_MKFS_ABORTED; - /* Create partition table if needed */ - if (!partition) { - DWORD n_disk = b_part + n_part; + /* Create partition table if required */ + if (sfd == 1) { + md = 0xF0; + } else { + DWORD n_disk = b_vol + n_vol; mem_set(fs->win, 0, SS(fs)); tbl = fs->win+MBR_Table; @@ -2885,90 +3236,88 @@ FRESULT f_mkfs ( } tbl[5] = 254; if (fmt != FS_FAT32) /* System ID */ - tbl[4] = (n_part < 0x10000) ? 0x04 : 0x06; + tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06; else tbl[4] = 0x0c; ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_part); /* Partition size in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ ST_WORD(tbl+64, 0xAA55); /* Signature */ if (disk_write(drv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; - partition = 0xF8; - } else { - partition = 0xF0; + md = 0xF8; } - /* Create boot record */ + /* Create VBR */ tbl = fs->win; /* Clear buffer */ mem_set(tbl, 0, SS(fs)); ST_DWORD(tbl+BS_jmpBoot, 0x90FEEB); /* Boot code (jmp $, nop) */ - ST_WORD(tbl+BPB_BytsPerSec, SS(fs)); /* Sector size */ - tbl[BPB_SecPerClus] = (BYTE)allocsize; /* Sectors per cluster */ + as = SS(fs); /* Sector size */ + ST_WORD(tbl+BPB_BytsPerSec, as); + tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - ST_WORD(tbl+BPB_RootEntCnt, SS(fs) / 32 * n_dir); /* Number of rootdir entries */ - if (n_part < 0x10000) { /* Number of total sectors */ - ST_WORD(tbl+BPB_TotSec16, n_part); + as = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD(tbl+BPB_RootEntCnt, as); + if (n_vol < 0x10000) { /* Number of total sectors */ + ST_WORD(tbl+BPB_TotSec16, n_vol); } else { - ST_DWORD(tbl+BPB_TotSec32, n_part); + ST_DWORD(tbl+BPB_TotSec32, n_vol); } - tbl[BPB_Media] = partition; /* Media descripter */ + tbl[BPB_Media] = md; /* Media descriptor */ ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl+BPB_HiddSec, b_part); /* Hidden sectors */ - n = get_fattime(); /* Use current time as a VSN */ - if (fmt != FS_FAT32) { - ST_DWORD(tbl+BS_VolID, n); /* Volume serial number */ - ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of secters per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab, "NO NAME FAT ", 19); /* Volume lavel, FAT signature */ - } else { - ST_DWORD(tbl+BS_VolID32, n); /* Volume serial number */ - ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of secters per FAT */ - ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory cluster (2) */ - ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (bs+1) */ - ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (bs+6) */ + ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+BS_VolID32, n); /* VSN */ + ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ + ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ + ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ + ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ tbl[BS_DrvNum32] = 0x80; /* Drive number */ tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl+BS_VolLab32, "NO NAME FAT32 ", 19); /* Volume lavel, FAT signature */ + mem_cpy(tbl+BS_VolLab32, "NO NAME FAT32 ", 19); /* Volume label, FAT signature */ + } else { + ST_DWORD(tbl+BS_VolID, n); /* VSN */ + ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab, "NO NAME FAT ", 19); /* Volume label, FAT signature */ } - ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature */ - if (SS(fs) > 512U) { - ST_WORD(tbl+SS(fs)-2, 0xAA55); - } - if (disk_write(drv, tbl, b_part+0, 1) != RES_OK) + ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ + if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Original (VBR) */ return FR_DISK_ERR; - if (fmt == FS_FAT32) - disk_write(drv, tbl, b_part+6, 1); + if (fmt == FS_FAT32) /* Backup (VBR+6) */ + disk_write(drv, tbl, b_vol + 6, 1); /* Initialize FAT area */ - for (m = 0; m < N_FATS; m++) { - mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ + for (i = 0; i < N_FATS; i++) { + mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ if (fmt != FS_FAT32) { - n = (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; - n |= partition; - ST_DWORD(tbl, n); /* Reserve cluster #0-1 (FAT12/16) */ + n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ } else { - ST_DWORD(tbl+0, 0xFFFFFFF8); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl+4, 0xFFFFFFFF); + n |= 0x0FFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD(tbl+4, 0x0FFFFFFF); ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ } if (disk_write(drv, tbl, b_fat++, 1) != RES_OK) return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Following FAT entries are filled by zero */ - for (n = 1; n < n_fat; n++) { + mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ + for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector write */ if (disk_write(drv, tbl, b_fat++, 1) != RES_OK) return FR_DISK_ERR; } } - /* Initialize Root directory */ - m = (BYTE)((fmt == FS_FAT32) ? allocsize : n_dir); - do { + /* Initialize root directory */ + n = (fmt == FS_FAT32) ? as : n_dir; + while (n--) { if (disk_write(drv, tbl, b_fat++, 1) != RES_OK) return FR_DISK_ERR; - } while (--m); + } /* Create FSInfo record if needed */ if (fmt == FS_FAT32) { @@ -2977,11 +3326,11 @@ FRESULT f_mkfs ( ST_DWORD(tbl+FSI_StrucSig, 0x61417272); ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); ST_DWORD(tbl+FSI_Nxt_Free, 0xFFFFFFFF); - disk_write(drv, tbl, b_part+1, 1); - disk_write(drv, tbl, b_part+7, 1); + disk_write(drv, tbl, b_vol + 1, 1); /* Original (VBR+1) */ + disk_write(drv, tbl, b_vol + 7, 1); /* Backup (VBR+7) */ } - return (disk_ioctl(drv, CTRL_SYNC, (void*)NULL) == RES_OK) ? FR_OK : FR_DISK_ERR; + return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR; } #endif /* _USE_MKFS && !_FS_READONLY */ @@ -2993,28 +3342,51 @@ FRESULT f_mkfs ( /*-----------------------------------------------------------------------*/ /* Get a string from the file */ /*-----------------------------------------------------------------------*/ -char* f_gets ( - char* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer */ - FIL* fil /* Pointer to the file object */ +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL* fil /* Pointer to the file object */ ) { - int i = 0; - char *p = buff; + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; UINT rc; - while (i < len - 1) { /* Read bytes until buffer gets filled */ - f_read(fil, p, 1, &rc); - if (rc != 1) break; /* Break when no data to read */ -#if _USE_STRFUNC >= 2 - if (*p == '\r') continue; /* Strip '\r' */ + while (n < len - 1) { /* Read bytes until buffer gets filled */ + f_read(fil, s, 1, &rc); + if (rc != 1) break; /* Break on EOF or error */ + c = s[0]; +#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ + if (c >= 0x80) { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) { /* Two-byte sequense */ + f_read(fil, s, 1, &rc); + if (rc != 1) break; + c = ((c & 0x1F) << 6) | (s[0] & 0x3F); + if (c < 0x80) c = '?'; + } else { + if (c < 0xF0) { /* Three-byte sequense */ + f_read(fil, s, 2, &rc); + if (rc != 2) break; + c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); + if (c < 0x800) c = '?'; + } else { /* Reject four-byte sequense */ + c = '?'; + } + } + } #endif - i++; - if (*p++ == '\n') break; /* Break when reached end of line */ +#if _USE_STRFUNC >= 2 + if (c == '\r') continue; /* Strip '\r' */ +#endif + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ } *p = 0; - return i ? buff : NULL; /* When no data read (eof or error), return with error. */ + return n ? buff : 0; /* When no data read (eof or error), return with error. */ } @@ -3025,24 +3397,40 @@ char* f_gets ( /* Put a character to the file */ /*-----------------------------------------------------------------------*/ int f_putc ( - int chr, /* A character to be output */ - FIL* fil /* Ponter to the file object */ + TCHAR c, /* A character to be output */ + FIL* fil /* Pointer to the file object */ ) { - UINT bw; - char c; + UINT bw, btw; + BYTE s[3]; #if _USE_STRFUNC >= 2 - if (chr == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */ + if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */ #endif - if (!fil) { /* Special value may be used to switch the destination to any other device */ - /* put_console(chr); */ - return chr; + +#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ + if (c < 0x80) { /* 7-bit */ + s[0] = (BYTE)c; + btw = 1; + } else { + if (c < 0x800) { /* 11-bit */ + s[0] = (BYTE)(0xC0 | (c >> 6)); + s[1] = (BYTE)(0x80 | (c & 0x3F)); + btw = 2; + } else { /* 16-bit */ + s[0] = (BYTE)(0xE0 | (c >> 12)); + s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); + s[2] = (BYTE)(0x80 | (c & 0x3F)); + btw = 3; + } } - c = (char)chr; - f_write(fil, &c, 1, &bw); /* Write a byte to the file */ - return bw ? chr : EOF; /* Return the result */ +#else /* Write the character without conversion */ + s[0] = (BYTE)c; + btw = 1; +#endif + f_write(fil, s, btw, &bw); /* Write the char to the file */ + return (bw == btw) ? 1 : EOF; /* Return the result */ } @@ -3052,7 +3440,7 @@ int f_putc ( /* Put a string to the file */ /*-----------------------------------------------------------------------*/ int f_puts ( - const char* str, /* Pointer to the string to be output */ + const TCHAR* str, /* Pointer to the string to be output */ FIL* fil /* Pointer to the file object */ ) { @@ -3073,15 +3461,16 @@ int f_puts ( /*-----------------------------------------------------------------------*/ int f_printf ( FIL* fil, /* Pointer to the file object */ - const char* str, /* Pointer to the format string */ + const TCHAR* str, /* Pointer to the format string */ ... /* Optional arguments... */ ) { va_list arp; - UCHAR c, f, r; + BYTE f, r; + UINT i, w; ULONG val; - char s[16]; - int i, w, res, cc; + TCHAR c, d, s[16]; + int res, cc; va_start(arp, str); @@ -3089,7 +3478,7 @@ int f_printf ( for (cc = res = 0; cc != EOF; res += cc) { c = *str++; if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape cahracter */ + if (c != '%') { /* Non escape character */ cc = f_putc(c, fil); if (cc != EOF) cc = 1; continue; @@ -3099,50 +3488,61 @@ int f_printf ( if (c == '0') { /* Flag: '0' padding */ f = 1; c = *str++; } - while (c >= '0' && c <= '9') { /* Precision */ - w = w * 10 + (c - '0'); + while (IsDigit(c)) { /* Precision */ + w = w * 10 + c - '0'; c = *str++; } - if (c == 'l') { /* Prefix: Size is long int */ + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ f |= 2; c = *str++; } - if (c == 's') { /* Type is string */ - cc = f_puts(va_arg(arp, char*), fil); - continue; + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + cc = f_puts(va_arg(arp, TCHAR*), fil); continue; + case 'C' : /* Character */ + cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown */ + cc = f_putc(c, fil); continue; } - if (c == 'c') { /* Type is character */ - cc = f_putc(va_arg(arp, int), fil); - if (cc != EOF) cc = 1; - continue; + + /* Get an argument */ + val = (f & 2) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); + if (d == 'D' && (val & 0x80000000)) { + val = 0 - val; + f |= 4; } - r = 0; - if (c == 'd') r = 10; /* Type is signed decimal */ - if (c == 'u') r = 10; /* Type is unsigned decimal */ - if (c == 'X') r = 16; /* Type is unsigned hexdecimal */ - if (r == 0) break; /* Unknown type */ - if (f & 2) { /* Get the value */ - val = (ULONG)va_arg(arp, long); - } else { - val = (c == 'd') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int); - } - /* Put numeral string */ - if (c == 'd') { - if (val & 0x80000000) { - val = 0 - val; - f |= 4; - } - } - i = sizeof(s) - 1; s[i] = 0; + /* Put it in numeral string */ + i = 0; do { - c = (UCHAR)(val % r + '0'); - if (c > '9') c += 7; - s[--i] = c; - val /= r; - } while (i && val); - if (i && (f & 4)) s[--i] = '-'; - w = sizeof(s) - 1 - w; - while (i && i > w) s[--i] = (f & 1) ? '0' : ' '; - cc = f_puts(&s[i], fil); + d = (TCHAR)(val % r); val /= r; + if (d > 9) { + d += 7; + if (c == 'x') d += 0x20; + } + s[i++] = d + '0'; + } while (val && i < sizeof(s) / sizeof(s[0])); + if (f & 4) s[i++] = '-'; + cc = 0; + while (i < w-- && cc != EOF) { + cc = f_putc((TCHAR)((f & 1) ? '0' : ' '), fil); + res++; + } + do { + cc = f_putc(s[--i], fil); + res++; + } while (i && cc != EOF); + if (cc != EOF) cc = 0; } va_end(arp); diff --git a/src/ff.h b/src/ff.h index ebebfd9..d739704 100644 --- a/src/ff.h +++ b/src/ff.h @@ -1,25 +1,30 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.07e (C)ChaN, 2009 +/ FatFs - FAT file system module include file R0.08 (C)ChaN, 2010 /----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following trems. / -/ Copyright (C) 2009, ChaN, all right reserved. +/ Copyright (C) 2010, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for / personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. +/ /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS 0x007E +#define _FATFS 8085 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif #include "integer.h" /* Basic integer types */ #include "ffconf.h" /* FatFs configuration options */ -#if _FATFS != _FFCONFIG +#if _FATFS != _FFCONF #error Wrong configuration file (ffconf.h). #endif @@ -219,50 +224,18 @@ -/* Character code support macros */ - -#define IsUpper(c) (((c)>='A')&&((c)<='Z')) -#define IsLower(c) (((c)>='a')&&((c)<='z')) - -#if _DF1S /* DBCS configuration */ - -#ifdef _DF2S /* Two 1st byte areas */ -#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) -#else /* One 1st byte area */ -#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) -#endif - -#ifdef _DS3S /* Three 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) -#else /* Two 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) -#endif - -#else /* SBCS configuration */ - -#define IsDBCS1(c) 0 -#define IsDBCS2(c) 0 - -#endif /* _DF1S */ - - - -/* Definitions corresponds to multi partition */ +/* Definitions corresponds to volume management */ #if _MULTI_PARTITION /* Multiple partition configuration */ - -typedef struct _PARTITION { +#define LD2PD(drv) (Drives[drv].pd) /* Get physical drive# */ +#define LD2PT(drv) (Drives[drv].pt) /* Get partition# */ +typedef struct { BYTE pd; /* Physical drive# */ BYTE pt; /* Partition # (0-3) */ } PARTITION; - -extern -const PARTITION Drives[]; /* Logical drive# to physical location conversion table */ -#define LD2PD(drv) (Drives[drv].pd) /* Get physical drive# */ -#define LD2PT(drv) (Drives[drv].pt) /* Get partition# */ +extern const PARTITION Drives[]; /* Logical drive# to physical location conversion table */ #else /* Single partition configuration */ - #define LD2PD(drv) (drv) /* Physical drive# is equal to the logical drive# */ #define LD2PT(drv) 0 /* Always mounts the 1st partition */ @@ -270,120 +243,142 @@ const PARTITION Drives[]; /* Logical drive# to physical location conversion ta -/* Definitions corresponds to multiple sector size */ +/* Type of path name strings on FatFs API */ -#if _MAX_SS == 512 /* Single sector size */ -#define SS(fs) 512U +#if _LFN_UNICODE /* Unicode string */ +#if !_USE_LFN +#error _LFN_UNICODE must be 0 in non-LFN cfg. +#endif +#ifndef _INC_TCHAR +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif -#elif _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096 /* Multiple sector size */ -#define SS(fs) ((fs)->s_size) - -#else -#error Sector size must be 512, 1024, 2048 or 4096. +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif #endif -/* Type of file name on FatFs API */ +/* Definitions corresponds to file shareing feature */ -#if _LFN_UNICODE && _USE_LFN -typedef WCHAR XCHAR; /* Unicode */ -#else -typedef char XCHAR; /* SBCS, DBCS */ +#if _FS_SHARE +#if _FS_READONLY +#error _FS_SHARE must be 0 on R/O cfg. +#endif +typedef struct { + DWORD clu; /* File ID 1, directory */ + WORD idx; /* File ID 2, index in the directory */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:in write open */ +} FILESEM; #endif -/* File system object structure */ +/* File system object structure (FATFS) */ -typedef struct _FATFS_ { - BYTE fs_type; /* FAT sub type */ - BYTE drive; /* Physical drive number */ - BYTE csize; /* Number of sectors per cluster */ - BYTE n_fats; /* Number of FAT copies */ - BYTE wflag; /* win[] dirty flag (1:must be written back) */ - BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */ -#if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ -#endif +typedef struct { + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE drv; /* Physical drive number */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1,2) */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ #if _MAX_SS != 512 - WORD s_size; /* Sector size */ + WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ +#endif +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ #endif #if !_FS_READONLY - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ - DWORD fsi_sector; /* fsinfo sector */ + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector (FAT32) */ #endif #if _FS_RPATH - DWORD cdir; /* Current directory (0:root)*/ + DWORD cdir; /* Current directory start cluster (0:root) */ +#endif + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ +#if _FS_SHARE + FILESEM flsem[_FS_SHARE]; /* File lock semaphores */ #endif - DWORD sects_fat; /* Sectors per fat */ - DWORD max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS];/* Disk access window for Directory/FAT */ } FATFS; -/* Directory object structure */ +/* File object structure (FIL) */ -typedef struct _DIR_ { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - WORD index; /* Current read/write index number */ - DWORD sclust; /* Table start cluster (0:Static table) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ -#if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ -#endif -} DIR; - - - -/* File object structure */ - -typedef struct _FIL_ { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - BYTE flag; /* File status flags */ - BYTE csect; /* Sector address in the cluster */ - DWORD fptr; /* File R/W pointer */ - DWORD fsize; /* File size */ - DWORD org_clust; /* File start cluster */ - DWORD curr_clust; /* Current cluster */ - DWORD dsect; /* Current data sector */ +typedef struct { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE flag; /* File status flags */ + BYTE pad1; + DWORD fptr; /* File read/write pointer */ + DWORD fsize; /* File size */ + DWORD org_clust; /* File start cluster (0 when fsize==0) */ + DWORD curr_clust; /* Current cluster */ + DWORD dsect; /* Current data sector */ #if !_FS_READONLY - DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Ponter to the directory entry in the window */ + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE* dir_ptr; /* Ponter to the directory entry in the window */ +#endif +#if _USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table */ +#endif +#if _FS_SHARE + UINT lockid; /* File lock ID */ #endif #if !_FS_TINY - BYTE buf[_MAX_SS];/* File R/W buffer */ + BYTE buf[_MAX_SS]; /* File data read/write buffer */ #endif } FIL; -/* File status structure */ +/* Directory object structure (DIR) */ -typedef struct _FILINFO_ { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - char fname[13]; /* Short file name (8.3 format) */ +typedef struct { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE* dir; /* Pointer to the current SFN entry in the win[] */ + BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ #if _USE_LFN - XCHAR* lfname; /* Pointer to the LFN buffer */ - int lfsize; /* Size of LFN buffer [chrs] */ + WCHAR* lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} DIR; + + + +/* File status structure (FILINFO) */ + +typedef struct { + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ +#if _USE_LFN + TCHAR* lfname; /* Pointer to the LFN buffer */ + int lfsize; /* Size of LFN buffer [chrs] */ #endif } FILINFO; @@ -392,22 +387,25 @@ typedef struct _FILINFO_ { /* File function return code (FRESULT) */ typedef enum { - FR_OK = 0, /* 0 */ - FR_DISK_ERR, /* 1 */ - FR_INT_ERR, /* 2 */ - FR_NOT_READY, /* 3 */ - FR_NO_FILE, /* 4 */ - FR_NO_PATH, /* 5 */ - FR_INVALID_NAME, /* 6 */ - FR_DENIED, /* 7 */ - FR_EXIST, /* 8 */ - FR_INVALID_OBJECT, /* 9 */ - FR_WRITE_PROTECTED, /* 10 */ - FR_INVALID_DRIVE, /* 11 */ - FR_NOT_ENABLED, /* 12 */ - FR_NO_FILESYSTEM, /* 13 */ - FR_MKFS_ABORTED, /* 14 */ - FR_TIMEOUT /* 15 */ + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Acces denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ } FRESULT; @@ -416,66 +414,77 @@ typedef enum { /* FatFs module application interface */ FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ -FRESULT f_open (FIL*, const XCHAR*, BYTE); /* Open or create a file */ +FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ -FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ FRESULT f_close (FIL*); /* Close an open file object */ -FRESULT f_opendir (DIR*, const XCHAR*); /* Open an existing directory */ +FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */ FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ -FRESULT f_stat (const XCHAR*, FILINFO*); /* Get file status */ -FRESULT f_getfree (const XCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ +FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ +#if !_FS_READONLY +FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ +FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ FRESULT f_truncate (FIL*); /* Truncate file */ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ -FRESULT f_unlink (const XCHAR*); /* Delete an existing file or directory */ -FRESULT f_mkdir (const XCHAR*); /* Create a new directory */ -FRESULT f_chmod (const XCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ -FRESULT f_utime (const XCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ -FRESULT f_rename (const XCHAR*, const XCHAR*); /* Rename/Move a file or directory */ +FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ +FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ +FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ +FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ +FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ +#endif +#if _USE_FORWARD FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ -FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */ -FRESULT f_chdir (const XCHAR*); /* Change current directory */ +#endif +#if _USE_MKFS +FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +#endif +#if _FS_RPATH +FRESULT f_chdir (const TCHAR*); /* Change current directory */ FRESULT f_chdrive (BYTE); /* Change current drive */ - +#endif #if _USE_STRFUNC -int f_putc (int, FIL*); /* Put a character to the file */ -int f_puts (const char*, FIL*); /* Put a string to the file */ -int f_printf (FIL*, const char*, ...); /* Put a formatted string to the file */ -char* f_gets (char*, int, FIL*); /* Get a string from the file */ +int f_putc (TCHAR, FIL*); /* Put a character to the file */ +int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ +int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) #define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) #ifndef EOF -#define EOF -1 +#define EOF (-1) #endif #endif /*--------------------------------------------------------------*/ -/* User defined functions */ +/* Additional user defined functions */ -/* Real time clock */ +/* RTC function */ #if !_FS_READONLY -DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */ - /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */ +DWORD get_fattime (void); #endif -/* Unicode - OEM code conversion */ -#if _USE_LFN -WCHAR ff_convert (WCHAR, UINT); -WCHAR ff_wtoupper (WCHAR); +/* Unicode support functions */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void* ff_memalloc (UINT); /* Allocate memory block */ +void ff_memfree (void*); /* Free memory block */ +#endif #endif /* Sync functions */ #if _FS_REENTRANT -BOOL ff_cre_syncobj(BYTE, _SYNC_t*); -BOOL ff_del_syncobj(_SYNC_t); -BOOL ff_req_grant(_SYNC_t); -void ff_rel_grant(_SYNC_t); +int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ +int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ +int ff_req_grant (_SYNC_t); /* Lock sync object */ +void ff_rel_grant (_SYNC_t); /* Unlock sync object */ #endif + /*--------------------------------------------------------------*/ /* Flags and offset address */ @@ -484,7 +493,9 @@ void ff_rel_grant(_SYNC_t); #define FA_READ 0x01 #define FA_OPEN_EXISTING 0x00 -#if _FS_READONLY == 0 +#define FA__ERROR 0x80 + +#if !_FS_READONLY #define FA_WRITE 0x02 #define FA_CREATE_NEW 0x04 #define FA_CREATE_ALWAYS 0x08 @@ -492,7 +503,6 @@ void ff_rel_grant(_SYNC_t); #define FA__WRITTEN 0x20 #define FA__DIRTY 0x40 #endif -#define FA__ERROR 0x80 /* FAT sub type (FATFS.fs_type) */ @@ -514,8 +524,12 @@ void ff_rel_grant(_SYNC_t); #define AM_MASK 0x3F /* Mask of defined bits */ -/* FatFs refers the members in the FAT structures with byte offset instead -/ of structure member because there are incompatibility of the packing option +/* Fast seek function */ +#define CREATE_LINKMAP 0xFFFFFFFF + + +/* FatFs refers the members in the FAT structures with byte offset instead of +/ structure member because there are incompatibility of the packing option / between various compilers. */ #define BS_jmpBoot 0 @@ -592,5 +606,8 @@ void ff_rel_grant(_SYNC_t); #define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) #endif +#ifdef __cplusplus +} +#endif #endif /* _FATFS */ diff --git a/src/ffconf.h b/src/ffconf.h new file mode 100644 index 0000000..430c35d --- /dev/null +++ b/src/ffconf.h @@ -0,0 +1,181 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.08 (C)ChaN, 2010 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONF +#define _FFCONF 8085 /* Revision ID */ + + +/*---------------------------------------------------------------------------/ +/ Function and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, +/ f_truncate and useless f_getfree. */ + + +#define _FS_MINIMIZE 0 /* 0, 1, 2 or 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove some functions. +/ +/ 0: Full function. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename +/ are removed. +/ 2: f_opendir and f_readdir are removed in addition to level 1. +/ 3: f_lseek is removed in addition to level 2. */ + + +#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 0 /* 0:Disable or 1:Enable */ +/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + +#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ +/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ + + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 932 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII only (Valid for non LFN cfg.) +*/ + + +#define _USE_LFN 0 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN support. +/ +/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN, +/ Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. When enable to use heap, memory control functions +/ ff_memalloc() and ff_memfree() must be added to the project. */ + + +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +/* To switch the character code set on FatFs API to Unicode, +/ enable LFN feature and set _LFN_UNICODE to 1. */ + + +#define _FS_RPATH 0 /* 0:Disable or 1:Enable */ +/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir, +/ f_chdrive function are available. +/ Note that output of the f_readdir fnction is affected by this option. */ + + + +/*---------------------------------------------------------------------------/ +/ Physical Drive Configurations +/----------------------------------------------------------------------------*/ + +#define _DRIVES 1 +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for floppy disk (512/1024) and optical disk (512/2048). +/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted +/ to the disk_ioctl function. */ + + +#define _MULTI_PARTITION 0 /* 0:Single parition or 1:Multiple partition */ +/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical +/ drive number and can mount only first primaly partition. When it is set to 1, +/ each volume is tied to the partitions listed in Drives[]. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS +/ option defines which access method is used to the word data on the FAT volume. +/ +/ 0: Byte-by-byte access. +/ 1: Word access. Do not choose this unless following condition is met. +/ +/ When the byte order on the memory is big-endian or address miss-aligned word +/ access results incorrect behavior, the _WORD_ACCESS must be set to 0. +/ If it is not the case, the value can also be set to 1 to improve the +/ performance and code size. */ + + +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ +/* Include a header file here to define O/S system calls */ +/* #include , , or ohters. */ + +/* The _FS_REENTRANT option switches the reentrancy of the FatFs module. +/ +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, +/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj +/ function must be added to the project. */ + + +#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ +/* To enable file shareing feature, set _FS_SHARE to >= 1 and also user + provided memory handlers, ff_memalloc and ff_memfree function must be + added to the project. The value defines number of files can be opened + per volume. */ + + +#endif /* _FFCONFIG */ diff --git a/src/integer.h b/src/integer.h index 851a78d..16ad408 100644 --- a/src/integer.h +++ b/src/integer.h @@ -3,17 +3,21 @@ /*-------------------------------------------*/ #ifndef _INTEGER +#define _INTEGER + +#ifdef _WIN32 /* FatFs development platform */ -#if 0 #include -#else +#include + +#else /* Embedded platform */ /* These types must be 16-bit, 32-bit or larger integer */ typedef int INT; typedef unsigned int UINT; /* These types must be 8-bit integer */ -typedef signed char CHAR; +typedef char CHAR; typedef unsigned char UCHAR; typedef unsigned char BYTE; @@ -28,10 +32,6 @@ typedef long LONG; typedef unsigned long ULONG; typedef unsigned long DWORD; -/* Boolean type */ -typedef enum { FALSE = 0, TRUE } BOOL; - #endif -#define _INTEGER #endif diff --git a/src/option/cc932.c b/src/option/cc932.c index 097c6a0..b208e11 100644 --- a/src/option/cc932.c +++ b/src/option/cc932.c @@ -9,7 +9,7 @@ #define _TINY_TABLE 0 #if !_USE_LFN || _CODE_PAGE != 932 -#error This file is not needed in current configuration. +#error This file is not needed in current configuration. Remove from the project. #endif @@ -111,7 +111,7 @@ const WCHAR uni2sjis[] = { 0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9, 0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED, 0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1, - 0x3094, 0x8394, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154, + 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154, 0x309E, 0x8155, 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342, 0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346, 0x30A8, 0x8347, 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A, @@ -1979,7 +1979,7 @@ const WCHAR sjis2uni[] = { 0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9, 0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED, 0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1, - 0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x3094, 0x8394, 0x30F4, + 0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x30F4, 0x8395, 0x30F5, 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392, 0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396, 0x83A5, 0x0397, 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A, @@ -3760,9 +3760,9 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */ do { c = *p; p += 2; + } while (c && c != src); p -= 3; c = *p; - } while (c && c != src); } else { /* Unicode to OEMCP */ li = 0; hi = sizeof(uni2sjis) / 4 - 1; for (n = 16; n; n--) { diff --git a/src/option/cc936.c b/src/option/cc936.c index 1a034a9..5a13e58 100644 --- a/src/option/cc936.c +++ b/src/option/cc936.c @@ -8,7 +8,7 @@ #if !_USE_LFN || _CODE_PAGE != 936 -#error This file is not needed in current configuration. +#error This file is not needed in current configuration. Remove from the project. #endif static diff --git a/src/option/cc949.c b/src/option/cc949.c index 2b1e793..bcf5082 100644 --- a/src/option/cc949.c +++ b/src/option/cc949.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------*/ /* Unicode - OEM code bidirectional converter (C)ChaN, 2009 */ /* */ -/* CP949 (Korean) */ +/* CP949 (Korean EUC-KR) */ /*------------------------------------------------------------------------*/ #include "../ff.h" #if !_USE_LFN || _CODE_PAGE != 949 -#error This file is not needed in current configuration. +#error This file is not needed in current configuration. Remove from the project. #endif diff --git a/src/option/cc950.c b/src/option/cc950.c index 0d73695..ace2dfa 100644 --- a/src/option/cc950.c +++ b/src/option/cc950.c @@ -8,7 +8,7 @@ #if !_USE_LFN || _CODE_PAGE != 950 -#error This file is not needed in current configuration. +#error This file is not needed in current configuration. Remove from the project. #endif diff --git a/src/option/ccsbcs.c b/src/option/ccsbcs.c index 9a9eac1..e125953 100644 --- a/src/option/ccsbcs.c +++ b/src/option/ccsbcs.c @@ -351,7 +351,7 @@ const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, - 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, @@ -494,7 +494,7 @@ const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ #if !_TBLDEF || !_USE_LFN -#error This file is not needed in current configuration +#error This file is not needed in current configuration. Remove from the project. #endif diff --git a/src/option/syncobj.c b/src/option/syscall.c similarity index 69% rename from src/option/syncobj.c rename to src/option/syscall.c index b4f4930..7142948 100644 --- a/src/option/syncobj.c +++ b/src/option/syscall.c @@ -1,19 +1,17 @@ /*------------------------------------------------------------------------*/ -/* Sample code of OS dependent synchronization object controls */ -/* for FatFs R0.07c (C)ChaN, 2009 */ +/* Sample code of OS dependent controls for FatFs R0.08 */ +/* (C)ChaN, 2010 */ /*------------------------------------------------------------------------*/ -#include /* Win32 */ -//#include /* uC/OS-II */ -//#include /* FreeRTOS */ - +#include /* ANSI memory controls */ +#include /* ANSI memory controls */ #include "../ff.h" -#if _FS_REENTRANT +#if _FS_REENTRANT /*------------------------------------------------------------------------*/ -/* Create a Synchronization Object for a Volume +/* Create a Synchronization Object /*------------------------------------------------------------------------*/ /* This function is called in f_mount function to create a new / synchronization object, such as semaphore and mutex. When a FALSE is @@ -30,7 +28,7 @@ BOOL ff_cre_syncobj ( /* TRUE:Function succeeded, FALSE:Could not create due to *sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */ ret = (*sobj != INVALID_HANDLE_VALUE) ? TRUE : FALSE; -// *sobj = VolumeSemId[vol]; /* uITRON (give a static created sync object) */ +// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */ // ret = TRUE; /* The initial value of the semaphore must be 1. */ // *sobj = OSMutexCreate(0, &err); /* uC/OS-II */ @@ -85,14 +83,14 @@ BOOL ff_req_grant ( /* TRUE:Got a grant to access the volume, FALSE:Could not ge { BOOL ret; - ret = (WaitForSingleObject(sobj, _TIMEOUT) == WAIT_OBJECT_0) ? TRUE : FALSE; /* Win32 */ + ret = (WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0) ? TRUE : FALSE; /* Win32 */ // ret = (wai_sem(sobj) == E_OK) ? TRUE : FALSE; /* uITRON */ -// OSMutexPend(sobj, _TIMEOUT, &err)); /* uC/OS-II */ +// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */ // ret = (err == OS_NO_ERR) ? TRUE : FALSE; -// ret = (xSemaphoreTake(sobj, _TIMEOUT) == pdTRUE) ? TRUE : FALSE; /* FreeRTOS */ +// ret = (xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE) ? TRUE : FALSE; /* FreeRTOS */ return ret; } @@ -119,9 +117,35 @@ void ff_rel_grant ( } +#endif -#else -#error This file is not needed in this configuration. + + +#if _USE_LFN == 3 /* LFN with a working buffer on the heap */ +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ +/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE. +*/ + +void* ff_memalloc ( /* Returns pointer to the allocated memory block */ + UINT size /* Number of bytes to allocate */ +) +{ + return malloc(size); +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree( + void* mblock /* Pointer to the memory block to free */ +) +{ + free(mblock); +} #endif