]> cloudbase.mooo.com Git - z180-stamp.git/blobdiff - fatfs/src/ff.c
Import fatfs R0.10c
[z180-stamp.git] / fatfs / src / ff.c
index 2edbe32a54b92c768eadbcd26eba2a6c9f37e488..9c887c45965fe1f44edde5d09b4dcacad88071f6 100644 (file)
@@ -1,5 +1,5 @@
 /*----------------------------------------------------------------------------/\r
-/  FatFs - FAT file system module  R0.10b                (C)ChaN, 2014\r
+/  FatFs - FAT file system module  R0.10c                (C)ChaN, 2014\r
 /-----------------------------------------------------------------------------/\r
 / FatFs module is a generic FAT file system module for small embedded systems.\r
 / This is a free software that opened for education, research and commercial\r
 /                   Fixed creation of an entry with LFN fails on too many SFN collisions.\r
 / May 19,'14 R0.10b Fixed a hard error in the disk I/O layer can collapse the directory entry.\r
 /                   Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN.\r
+/ Nov 09,'14 R0.10c Added a configuration option for the platforms without RTC. (_FS_NORTC)\r
+/                   Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel().\r
+/                   Fixed a potential problem of FAT access that can appear on disk error.\r
+/                   Fixed null pointer dereference on attempting to delete the root direcotry.\r
 /---------------------------------------------------------------------------*/\r
 \r
 #include "ff.h"                        /* Declarations of FatFs API */\r
 \r
 ---------------------------------------------------------------------------*/\r
 \r
-#if _FATFS != 8051     /* Revision ID */\r
+#if _FATFS != 80376    /* Revision ID */\r
 #error Wrong include file (ff.h).\r
 #endif\r
 \r
 /* Reentrancy related */\r
 #if _FS_REENTRANT\r
 #if _USE_LFN == 1\r
-#error Static LFN work area cannot be used at thread-safe configuration.\r
+#error Static LFN work area cannot be used at thread-safe configuration\r
 #endif\r
 #define        ENTER_FF(fs)            { if (!lock_fs(fs)) return FR_TIMEOUT; }\r
 #define        LEAVE_FF(fs, res)       { unlock_fs(fs, res); return res; }\r
 \r
 /* Definitions of sector size */\r
 #if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096)\r
-#error Wrong sector size configuration.\r
+#error Wrong sector size configuration\r
 #endif\r
 #if _MAX_SS == _MIN_SS\r
 #define        SS(fs)  ((UINT)_MAX_SS) /* Fixed sector size */\r
 #endif\r
 \r
 \r
+/* Timestamp feature */\r
+#if _FS_NORTC\r
+#define GET_FATTIME()  ((DWORD)_NORTC_YEAR << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_MDAY << 16)\r
+#else\r
+#define GET_FATTIME()  get_fattime()\r
+#endif\r
+\r
+\r
 /* File access control feature */\r
 #if _FS_LOCK\r
 #if _FS_READONLY\r
-#error _FS_LOCK must be 0 at read-only cfg.\r
+#error _FS_LOCK must be 0 at read-only configuration\r
 #endif\r
 typedef struct {\r
        FATFS *fs;              /* Object ID 1, volume (NULL:blank entry) */\r
@@ -398,7 +410,7 @@ typedef struct {
 \r
 \r
 /* Name status flags */\r
-#define NS                     11              /* Index of name status byte in fn[] */\r
+#define NSFLAG         11              /* Index of name status byte in fn[] */\r
 #define NS_LOSS                0x01    /* Out of 8.3 format */\r
 #define NS_LFN         0x02    /* Force to create LFN entry */\r
 #define NS_LAST                0x04    /* Last segment */\r
@@ -407,16 +419,16 @@ typedef struct {
 #define NS_DOT         0x20    /* Dot entry */\r
 \r
 \r
-/* FAT sub-type boundaries */\r
-#define MIN_FAT16      4086U   /* Minimum number of clusters for FAT16 */\r
-#define        MIN_FAT32       65526U  /* Minimum number of clusters for FAT32 */\r
+/* FAT sub-type boundaries (Differ from specs but correct for real DOS/Windows) */\r
+#define MIN_FAT16      4086U   /* Minimum number of clusters as FAT16 */\r
+#define        MIN_FAT32       65526U  /* Minimum number of clusters as FAT32 */\r
 \r
 \r
 /* FatFs refers the members in the FAT structures as byte array instead of\r
 / structure member because the structure is not binary compatible between\r
 / different platforms */\r
 \r
-#define BS_jmpBoot                     0               /* Jump instruction (3) */\r
+#define BS_jmpBoot                     0               /* x86 jump instruction (3) */\r
 #define BS_OEMName                     3               /* OEM name (8) */\r
 #define BPB_BytsPerSec         11              /* Sector size [byte] (2) */\r
 #define BPB_SecPerClus         13              /* Cluster size [sector] (1) */\r
@@ -482,63 +494,53 @@ typedef struct {
 /*------------------------------------------------------------*/\r
 /* Module private work area                                   */\r
 /*------------------------------------------------------------*/\r
-/* Note that uninitialized variables with static duration are\r
-/  guaranteed zero/null as initial value. If not, either the\r
-/  linker or start-up routine is out of ANSI-C standard.\r
+/* Remark: Uninitialized variables with static duration are\r
+/  guaranteed zero/null at start-up. If not, either the linker\r
+/  or start-up routine being used is out of ANSI-C standard.\r
 */\r
 \r
-#if _VOLUMES >= 1 || _VOLUMES <= 10\r
-static\r
-FATFS *FatFs[_VOLUMES];                /* Pointer to the file system objects (logical drives) */\r
-#else\r
-#error Number of volumes must be 1 to 10.\r
+#if _VOLUMES < 1 || _VOLUMES > 9\r
+#error Wrong _VOLUMES setting\r
 #endif\r
-\r
-static\r
-WORD Fsid;                                     /* File system mount ID */\r
+static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */\r
+static WORD Fsid;                              /* File system mount ID */\r
 \r
 #if _FS_RPATH && _VOLUMES >= 2\r
-static\r
-BYTE CurrVol;                          /* Current drive */\r
+static BYTE CurrVol;                   /* Current drive */\r
 #endif\r
 \r
 #if _FS_LOCK\r
-static\r
-FILESEM        Files[_FS_LOCK];        /* Open object lock semaphores */\r
+static FILESEM Files[_FS_LOCK];        /* Open object lock semaphores */\r
 #endif\r
 \r
-#if _USE_LFN == 0                      /* No LFN feature */\r
+#if _USE_LFN == 0                      /* Non LFN feature */\r
 #define        DEF_NAMEBUF                     BYTE sfn[12]\r
 #define INIT_BUF(dobj)         (dobj).fn = sfn\r
 #define        FREE_BUF()\r
-\r
-#elif _USE_LFN == 1                    /* LFN feature with static working buffer */\r
-static\r
-WCHAR LfnBuf[_MAX_LFN+1];\r
+#else\r
+#if _MAX_LFN < 12 || _MAX_LFN > 255\r
+#error Wrong _MAX_LFN setting\r
+#endif\r
+#if _USE_LFN == 1                      /* LFN feature with static working buffer */\r
+static WCHAR LfnBuf[_MAX_LFN+1];\r
 #define        DEF_NAMEBUF                     BYTE sfn[12]\r
 #define INIT_BUF(dobj)         { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }\r
 #define        FREE_BUF()\r
-\r
 #elif _USE_LFN == 2            /* LFN feature with dynamic working buffer on the stack */\r
 #define        DEF_NAMEBUF                     BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]\r
 #define INIT_BUF(dobj)         { (dobj).fn = sfn; (dobj).lfn = lbuf; }\r
 #define        FREE_BUF()\r
-\r
 #elif _USE_LFN == 3            /* LFN feature with dynamic working buffer on the heap */\r
 #define        DEF_NAMEBUF                     BYTE sfn[12]; WCHAR *lfn\r
-#define INIT_BUF(dobj)         { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \\r
-                                                         if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \\r
-                                                         (dobj).lfn = lfn;     (dobj).fn = sfn; }\r
+#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; }\r
 #define        FREE_BUF()                      ff_memfree(lfn)\r
-\r
 #else\r
-#error Wrong LFN configuration.\r
+#error Wrong _USE_LFN setting\r
+#endif\r
 #endif\r
-\r
 \r
 #ifdef _EXCVT\r
-static\r
-const BYTE ExCvt[] = _EXCVT;   /* Upper conversion table for extended characters */\r
+static const BYTE ExCvt[] = _EXCVT;    /* Upper conversion table for extended characters */\r
 #endif\r
 \r
 \r
@@ -758,21 +760,24 @@ FRESULT sync_window (
 {\r
        DWORD wsect;\r
        UINT nf;\r
+       FRESULT res = FR_OK;\r
 \r
 \r
        if (fs->wflag) {        /* Write back the sector if it is dirty */\r
                wsect = fs->winsect;    /* Current sector number */\r
-               if (disk_write(fs->drv, fs->win, wsect, 1))\r
-                       return FR_DISK_ERR;\r
-               fs->wflag = 0;\r
-               if (wsect - fs->fatbase < fs->fsize) {          /* Is it in the FAT area? */\r
-                       for (nf = fs->n_fats; nf >= 2; nf--) {  /* Reflect the change to all FAT copies */\r
-                               wsect += fs->fsize;\r
-                               disk_write(fs->drv, fs->win, wsect, 1);\r
+               if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) {\r
+                       res = FR_DISK_ERR;\r
+               } else {\r
+                       fs->wflag = 0;\r
+                       if (wsect - fs->fatbase < fs->fsize) {          /* Is it in the FAT area? */\r
+                               for (nf = fs->n_fats; nf >= 2; nf--) {  /* Reflect the change to all FAT copies */\r
+                                       wsect += fs->fsize;\r
+                                       disk_write(fs->drv, fs->win, wsect, 1);\r
+                               }\r
                        }\r
                }\r
        }\r
-       return FR_OK;\r
+       return res;\r
 }\r
 #endif\r
 \r
@@ -783,17 +788,22 @@ FRESULT move_window (
        DWORD sector    /* Sector number to make appearance in the fs->win[] */\r
 )\r
 {\r
-       if (sector != fs->winsect) {    /* Changed current window */\r
+       FRESULT res = FR_OK;\r
+\r
+\r
+       if (sector != fs->winsect) {    /* Window offset changed? */\r
 #if !_FS_READONLY\r
-               if (sync_window(fs) != FR_OK)\r
-                       return FR_DISK_ERR;\r
+               res = sync_window(fs);          /* Write-back changes */\r
 #endif\r
-               if (disk_read(fs->drv, fs->win, sector, 1))\r
-                       return FR_DISK_ERR;\r
-               fs->winsect = sector;\r
+               if (res == FR_OK) {                     /* Fill sector window with new data */\r
+                       if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) {\r
+                               sector = 0xFFFFFFFF;    /* Invalidate window if data is not reliable */\r
+                               res = FR_DISK_ERR;\r
+                       }\r
+                       fs->winsect = sector;\r
+               }\r
        }\r
-\r
-       return FR_OK;\r
+       return res;\r
 }\r
 \r
 \r
@@ -842,7 +852,7 @@ FRESULT sync_fs (   /* FR_OK: successful, FR_DISK_ERR: failed */
 /*-----------------------------------------------------------------------*/\r
 /* Get sector# from cluster#                                             */\r
 /*-----------------------------------------------------------------------*/\r
-\r
+/* Hidden API for hacks and disk tools */\r
 \r
 DWORD clust2sect (     /* !=0: Sector number, 0: Failed - invalid cluster# */\r
        FATFS* fs,              /* File system object */\r
@@ -850,7 +860,7 @@ DWORD clust2sect (  /* !=0: Sector number, 0: Failed - invalid cluster# */
 )\r
 {\r
        clst -= 2;\r
-       if (clst >= (fs->n_fatent - 2)) return 0;               /* Invalid cluster# */\r
+       if (clst >= fs->n_fatent - 2) return 0;         /* Invalid cluster# */\r
        return clst * fs->csize + fs->database;\r
 }\r
 \r
@@ -860,44 +870,52 @@ DWORD clust2sect (        /* !=0: Sector number, 0: Failed - invalid cluster# */
 /*-----------------------------------------------------------------------*/\r
 /* FAT access - Read value of a FAT entry                                */\r
 /*-----------------------------------------------------------------------*/\r
+/* Hidden API for hacks and disk tools */\r
 \r
-\r
-DWORD get_fat (        /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */\r
+DWORD get_fat (        /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */\r
        FATFS* fs,      /* File system object */\r
-       DWORD clst      /* Cluster# to get the link information */\r
+       DWORD clst      /* FAT item index (cluster#) to get the value */\r
 )\r
 {\r
        UINT wc, bc;\r
        BYTE *p;\r
+       DWORD val;\r
 \r
 \r
-       if (clst < 2 || clst >= fs->n_fatent)   /* Check range */\r
-               return 1;\r
+       if (clst < 2 || clst >= fs->n_fatent) { /* Check range */\r
+               val = 1;        /* Internal error */\r
 \r
-       switch (fs->fs_type) {\r
-       case FS_FAT12 :\r
-               bc = (UINT)clst; bc += bc / 2;\r
-               if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;\r
-               wc = fs->win[bc % SS(fs)]; bc++;\r
-               if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;\r
-               wc |= fs->win[bc % SS(fs)] << 8;\r
-               return clst & 1 ? wc >> 4 : (wc & 0xFFF);\r
+       } else {\r
+               val = 0xFFFFFFFF;       /* Default value falls on disk error */\r
 \r
-       case FS_FAT16 :\r
-               if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break;\r
-               p = &fs->win[clst * 2 % SS(fs)];\r
-               return LD_WORD(p);\r
+               switch (fs->fs_type) {\r
+               case FS_FAT12 :\r
+                       bc = (UINT)clst; bc += bc / 2;\r
+                       if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;\r
+                       wc = fs->win[bc++ % SS(fs)];\r
+                       if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;\r
+                       wc |= fs->win[bc % SS(fs)] << 8;\r
+                       val = clst & 1 ? wc >> 4 : (wc & 0xFFF);\r
+                       break;\r
+\r
+               case FS_FAT16 :\r
+                       if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break;\r
+                       p = &fs->win[clst * 2 % SS(fs)];\r
+                       val = LD_WORD(p);\r
+                       break;\r
 \r
-       case FS_FAT32 :\r
-               if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break;\r
-               p = &fs->win[clst * 4 % SS(fs)];\r
-               return LD_DWORD(p) & 0x0FFFFFFF;\r
+               case FS_FAT32 :\r
+                       if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;\r
+                       p = &fs->win[clst * 4 % SS(fs)];\r
+                       val = LD_DWORD(p) & 0x0FFFFFFF;\r
+                       break;\r
 \r
-       default:\r
-               return 1;\r
+               default:\r
+                       val = 1;        /* Internal error */\r
+               }\r
        }\r
 \r
-       return 0xFFFFFFFF;      /* An error occurred at the disk I/O layer */\r
+       return val;\r
 }\r
 \r
 \r
@@ -906,11 +924,12 @@ DWORD get_fat (   /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status
 /*-----------------------------------------------------------------------*/\r
 /* FAT access - Change value of a FAT entry                              */\r
 /*-----------------------------------------------------------------------*/\r
-#if !_FS_READONLY\r
+/* Hidden API for hacks and disk tools */\r
 \r
+#if !_FS_READONLY\r
 FRESULT put_fat (\r
        FATFS* fs,      /* File system object */\r
-       DWORD clst,     /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */\r
+       DWORD clst,     /* FAT item index (cluster#) to be set */\r
        DWORD val       /* New value to mark the cluster */\r
 )\r
 {\r
@@ -928,14 +947,14 @@ FRESULT put_fat (
                        bc = (UINT)clst; bc += bc / 2;\r
                        res = move_window(fs, fs->fatbase + (bc / SS(fs)));\r
                        if (res != FR_OK) break;\r
-                       p = &fs->win[bc % SS(fs)];\r
+                       p = &fs->win[bc++ % SS(fs)];\r
                        *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;\r
-                       bc++;\r
                        fs->wflag = 1;\r
                        res = move_window(fs, fs->fatbase + (bc / SS(fs)));\r
                        if (res != FR_OK) break;\r
                        p = &fs->win[bc % SS(fs)];\r
                        *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));\r
+                       fs->wflag = 1;\r
                        break;\r
 \r
                case FS_FAT16 :\r
@@ -943,6 +962,7 @@ FRESULT put_fat (
                        if (res != FR_OK) break;\r
                        p = &fs->win[clst * 2 % SS(fs)];\r
                        ST_WORD(p, (WORD)val);\r
+                       fs->wflag = 1;\r
                        break;\r
 \r
                case FS_FAT32 :\r
@@ -951,12 +971,12 @@ FRESULT put_fat (
                        p = &fs->win[clst * 4 % SS(fs)];\r
                        val |= LD_DWORD(p) & 0xF0000000;\r
                        ST_DWORD(p, val);\r
+                       fs->wflag = 1;\r
                        break;\r
 \r
                default :\r
                        res = FR_INT_ERR;\r
                }\r
-               fs->wflag = 1;\r
        }\r
 \r
        return res;\r
@@ -978,7 +998,7 @@ FRESULT remove_chain (
 {\r
        FRESULT res;\r
        DWORD nxt;\r
-#if _USE_ERASE\r
+#if _USE_TRIM\r
        DWORD scl = clst, ecl = clst, rt[2];\r
 #endif\r
 \r
@@ -998,13 +1018,13 @@ FRESULT remove_chain (
                                fs->free_clust++;\r
                                fs->fsi_flag |= 1;\r
                        }\r
-#if _USE_ERASE\r
+#if _USE_TRIM\r
                        if (ecl + 1 == nxt) {   /* Is next cluster contiguous? */\r
                                ecl = nxt;\r
                        } else {                                /* End of contiguous clusters */ \r
                                rt[0] = clust2sect(fs, scl);                                    /* Start sector */\r
                                rt[1] = clust2sect(fs, ecl) + fs->csize - 1;    /* End sector */\r
-                               disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt);             /* Erase the block */\r
+                               disk_ioctl(fs->drv, CTRL_TRIM, rt);                             /* Erase the block */\r
                                scl = ecl = nxt;\r
                        }\r
 #endif\r
@@ -1246,8 +1266,8 @@ FRESULT dir_alloc (
                do {\r
                        res = move_window(dp->fs, dp->sect);\r
                        if (res != FR_OK) break;\r
-                       if (dp->dir[0] == DDE || dp->dir[0] == 0) {     /* Is it a blank entry? */\r
-                               if (++n == nent) break; /* A block of contiguous entries is found */\r
+                       if (dp->dir[0] == DDE || dp->dir[0] == 0) {     /* Is it a free entry? */\r
+                               if (++n == nent) break; /* A block of contiguous free entries is found */\r
                        } else {\r
                                n = 0;                                  /* Not a blank entry. Restart to search */\r
                        }\r
@@ -1526,7 +1546,7 @@ FRESULT dir_find (
                                }\r
                        } else {                                        /* An SFN entry is found */\r
                                if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */\r
-                               if (!(dp->fn[NS] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break;        /* SFN matched? */\r
+                               if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break;    /* SFN matched? */\r
                                ord = 0xFF; dp->lfn_idx = 0xFFFF;       /* Reset LFN sequence */\r
                        }\r
                }\r
@@ -1568,7 +1588,7 @@ FRESULT dir_read (
                if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
                a = dir[DIR_Attr] & AM_MASK;\r
 #if _USE_LFN   /* LFN configuration */\r
-               if (c == DDE || (!_FS_RPATH && c == '.') || (int)(a == AM_VOL) != vol) {        /* An entry without valid data */\r
+               if (c == DDE || (!_FS_RPATH && c == '.') || (int)((a & ~AM_ARC) == AM_VOL) != vol) {    /* An entry without valid data */\r
                        ord = 0xFF;\r
                } else {\r
                        if (a == AM_LFN) {                      /* An LFN entry is found */\r
@@ -1586,7 +1606,7 @@ FRESULT dir_read (
                        }\r
                }\r
 #else          /* Non LFN configuration */\r
-               if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (int)(a == AM_VOL) == vol)    /* Is it a valid entry? */\r
+               if (c != DDE && (_FS_RPATH || c != '.') && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol)        /* Is it a valid entry? */\r
                        break;\r
 #endif\r
                res = dir_next(dp, 0);                          /* Next entry */\r
@@ -1621,11 +1641,11 @@ FRESULT dir_register (  /* FR_OK:Successful, FR_DENIED:No free entry or too many
        fn = dp->fn; lfn = dp->lfn;\r
        mem_cpy(sn, fn, 12);\r
 \r
-       if (_FS_RPATH && (sn[NS] & NS_DOT))             /* Cannot create dot entry */\r
+       if (_FS_RPATH && (sn[NSFLAG] & NS_DOT))         /* Cannot create dot entry */\r
                return FR_INVALID_NAME;\r
 \r
-       if (sn[NS] & NS_LOSS) {                 /* When LFN is out of 8.3 format, generate a numbered name */\r
-               fn[NS] = 0; dp->lfn = 0;                        /* Find only SFN */\r
+       if (sn[NSFLAG] & NS_LOSS) {                     /* When LFN is out of 8.3 format, generate a numbered name */\r
+               fn[NSFLAG] = 0; dp->lfn = 0;                    /* Find only SFN */\r
                for (n = 1; n < 100; n++) {\r
                        gen_numname(fn, sn, lfn, n);    /* Generate a numbered name */\r
                        res = dir_find(dp);                             /* Check if the name collides with existing SFN */\r
@@ -1633,10 +1653,10 @@ FRESULT dir_register (  /* FR_OK:Successful, FR_DENIED:No free entry or too many
                }\r
                if (n == 100) return FR_DENIED;         /* Abort if too many collisions */\r
                if (res != FR_NO_FILE) return res;      /* Abort if the result is other than 'not collided' */\r
-               fn[NS] = sn[NS]; dp->lfn = lfn;\r
+               fn[NSFLAG] = sn[NSFLAG]; dp->lfn = lfn;\r
        }\r
 \r
-       if (sn[NS] & NS_LFN) {                  /* When LFN is to be created, allocate entries for an SFN + LFNs. */\r
+       if (sn[NSFLAG] & NS_LFN) {                      /* When LFN is to be created, allocate entries for an SFN + LFNs. */\r
                for (n = 0; lfn[n]; n++) ;\r
                nent = (n + 25) / 13;\r
        } else {                                                /* Otherwise allocate an entry for an SFN  */\r
@@ -1667,7 +1687,7 @@ FRESULT dir_register (    /* FR_OK:Successful, FR_DENIED:No free entry or too many
                        mem_set(dp->dir, 0, SZ_DIR);    /* Clean the entry */\r
                        mem_cpy(dp->dir, dp->fn, 11);   /* Put SFN */\r
 #if _USE_LFN\r
-                       dp->dir[DIR_NTres] = dp->fn[NS] & (NS_BODY | NS_EXT);   /* Put NT flag */\r
+                       dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT);       /* Put NT flag */\r
 #endif\r
                        dp->fs->wflag = 1;\r
                }\r
@@ -1923,7 +1943,7 @@ FRESULT create_name (
                if ((b & 0x0C) == 0x04) cf |= NS_BODY;  /* NT flag (Filename has only small capital) */\r
        }\r
 \r
-       dp->fn[NS] = cf;        /* SFN is created */\r
+       dp->fn[NSFLAG] = cf;    /* SFN is created */\r
 \r
        return FR_OK;\r
 \r
@@ -1947,7 +1967,7 @@ FRESULT create_name (
                }\r
                if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;\r
                *path = &p[si];                                                                 /* Return pointer to the next segment */\r
-               sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT;       /* Set last segment flag if end of path */\r
+               sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT;   /* Set last segment flag if end of path */\r
                return FR_OK;\r
        }\r
 #endif\r
@@ -1998,7 +2018,7 @@ FRESULT create_name (
        if ((b & 0x03) == 0x01) c |= NS_EXT;    /* NT flag (Name extension has only small capital) */\r
        if ((b & 0x0C) == 0x04) c |= NS_BODY;   /* NT flag (Name body has only small capital) */\r
 \r
-       sfn[NS] = c;            /* Store NT flag, File name is created */\r
+       sfn[NSFLAG] = c;                /* Store NT flag, File name is created */\r
 \r
        return FR_OK;\r
 #endif\r
@@ -2041,7 +2061,7 @@ FRESULT follow_path (     /* FR_OK(0): successful, !=0: error code */
                        res = create_name(dp, &path);   /* Get a segment name of the path */\r
                        if (res != FR_OK) break;\r
                        res = dir_find(dp);                             /* Find an object with the sagment name */\r
-                       ns = dp->fn[NS];\r
+                       ns = dp->fn[NSFLAG];\r
                        if (res != FR_OK) {                             /* Failed to find the object */\r
                                if (res == FR_NO_FILE) {        /* Object is not found */\r
                                        if (_FS_RPATH && (ns & NS_DOT)) {       /* If dot entry is not exist, */\r
@@ -2283,7 +2303,7 @@ FRESULT find_volume (     /* FR_OK(0): successful, !=0: any error occurred */
                szbfat = (fmt == FS_FAT16) ?                                    /* (Needed FAT size) */\r
                        fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);\r
        }\r
-       if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))       /* (BPB_FATSz must not be less than needed) */\r
+       if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))       /* (BPB_FATSz must not be less than the size needed) */\r
                return FR_NO_FILESYSTEM;\r
 \r
 #if !_FS_READONLY\r
@@ -2471,7 +2491,7 @@ FRESULT f_open (
                                }\r
                        }\r
                        if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {        /* Truncate it if overwrite mode */\r
-                               dw = get_fattime();                             /* Created time */\r
+                               dw = GET_FATTIME();                             /* Created time */\r
                                ST_DWORD(dir+DIR_CrtTime, dw);\r
                                dir[DIR_Attr] = 0;                              /* Reset attribute */\r
                                ST_DWORD(dir+DIR_FileSize, 0);  /* size = 0 */\r
@@ -2597,7 +2617,7 @@ FRESULT f_read (
                        if (cc) {                                                       /* Read maximum contiguous sectors directly */\r
                                if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */\r
                                        cc = fp->fs->csize - csect;\r
-                               if (disk_read(fp->fs->drv, rbuff, sect, cc))\r
+                               if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK)\r
                                        ABORT(fp->fs, FR_DISK_ERR);\r
 #if !_FS_READONLY && _FS_MINIMIZE <= 2                 /* Replace one of the read sectors with cached data if it contains a dirty sector */\r
 #if _FS_TINY\r
@@ -2615,12 +2635,12 @@ FRESULT f_read (
                        if (fp->dsect != sect) {                        /* Load data sector if not in cache */\r
 #if !_FS_READONLY\r
                                if (fp->flag & FA__DIRTY) {             /* Write-back dirty sector cache */\r
-                                       if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))\r
+                                       if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)\r
                                                ABORT(fp->fs, FR_DISK_ERR);\r
                                        fp->flag &= ~FA__DIRTY;\r
                                }\r
 #endif\r
-                               if (disk_read(fp->fs->drv, fp->buf, sect, 1))   /* Fill sector cache */\r
+                               if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */\r
                                        ABORT(fp->fs, FR_DISK_ERR);\r
                        }\r
 #endif\r
@@ -2629,7 +2649,7 @@ FRESULT f_read (
                rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));      /* Get partial sector data from sector buffer */\r
                if (rcnt > btr) rcnt = btr;\r
 #if _FS_TINY\r
-               if (move_window(fp->fs, fp->dsect)            /* Move sector window */\r
+               if (move_window(fp->fs, fp->dsect) != FR_OK)            /* Move sector window */\r
                        ABORT(fp->fs, FR_DISK_ERR);\r
                mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt);      /* Pick partial sector */\r
 #else\r
@@ -2700,7 +2720,7 @@ FRESULT f_write (
                                ABORT(fp->fs, FR_DISK_ERR);\r
 #else\r
                        if (fp->flag & FA__DIRTY) {             /* Write-back sector cache */\r
-                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))\r
+                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)\r
                                        ABORT(fp->fs, FR_DISK_ERR);\r
                                fp->flag &= ~FA__DIRTY;\r
                        }\r
@@ -2712,7 +2732,7 @@ FRESULT f_write (
                        if (cc) {                                               /* Write maximum contiguous sectors directly */\r
                                if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */\r
                                        cc = fp->fs->csize - csect;\r
-                               if (disk_write(fp->fs->drv, wbuff, sect, cc))\r
+                               if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK)\r
                                        ABORT(fp->fs, FR_DISK_ERR);\r
 #if _FS_MINIMIZE <= 2\r
 #if _FS_TINY\r
@@ -2738,7 +2758,7 @@ FRESULT f_write (
 #else\r
                        if (fp->dsect != sect) {                /* Fill sector cache with file data */\r
                                if (fp->fptr < fp->fsize &&\r
-                                       disk_read(fp->fs->drv, fp->buf, sect, 1))\r
+                                       disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)\r
                                                ABORT(fp->fs, FR_DISK_ERR);\r
                        }\r
 #endif\r
@@ -2747,7 +2767,7 @@ FRESULT f_write (
                wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */\r
                if (wcnt > btw) wcnt = btw;\r
 #if _FS_TINY\r
-               if (move_window(fp->fs, fp->dsect)    /* Move sector window */\r
+               if (move_window(fp->fs, fp->dsect) != FR_OK)    /* Move sector window */\r
                        ABORT(fp->fs, FR_DISK_ERR);\r
                mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt);      /* Fit partial sector */\r
                fp->fs->wflag = 1;\r
@@ -2785,7 +2805,7 @@ FRESULT f_sync (
                        /* Write-back dirty buffer */\r
 #if !_FS_TINY\r
                        if (fp->flag & FA__DIRTY) {\r
-                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))\r
+                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)\r
                                        LEAVE_FF(fp->fs, FR_DISK_ERR);\r
                                fp->flag &= ~FA__DIRTY;\r
                        }\r
@@ -2797,7 +2817,7 @@ FRESULT f_sync (
                                dir[DIR_Attr] |= AM_ARC;                                        /* Set archive bit */\r
                                ST_DWORD(dir+DIR_FileSize, fp->fsize);          /* Update file size */\r
                                st_clust(dir, fp->sclust);                                      /* Update start cluster */\r
-                               tm = get_fattime();                                                     /* Update updated time */\r
+                               tm = GET_FATTIME();                                                     /* Update updated time */\r
                                ST_DWORD(dir+DIR_WrtTime, tm);\r
                                ST_WORD(dir+DIR_LstAccDate, 0);\r
                                fp->flag &= ~FA__WRITTEN;\r
@@ -3046,12 +3066,12 @@ FRESULT f_lseek (
 #if !_FS_TINY\r
 #if !_FS_READONLY\r
                                        if (fp->flag & FA__DIRTY) {             /* Write-back dirty sector cache */\r
-                                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))\r
+                                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)\r
                                                        ABORT(fp->fs, FR_DISK_ERR);\r
                                                fp->flag &= ~FA__DIRTY;\r
                                        }\r
 #endif\r
-                                       if (disk_read(fp->fs->drv, fp->buf, dsc, 1))    /* Load current sector */\r
+                                       if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK)  /* Load current sector */\r
                                                ABORT(fp->fs, FR_DISK_ERR);\r
 #endif\r
                                        fp->dsect = dsc;\r
@@ -3121,12 +3141,12 @@ FRESULT f_lseek (
 #if !_FS_TINY\r
 #if !_FS_READONLY\r
                        if (fp->flag & FA__DIRTY) {                     /* Write-back dirty sector cache */\r
-                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))\r
+                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)\r
                                        ABORT(fp->fs, FR_DISK_ERR);\r
                                fp->flag &= ~FA__DIRTY;\r
                        }\r
 #endif\r
-                       if (disk_read(fp->fs->drv, fp->buf, nsect, 1))  /* Fill sector cache */\r
+                       if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK)        /* Fill sector cache */\r
                                ABORT(fp->fs, FR_DISK_ERR);\r
 #endif\r
                        fp->dsect = nsect;\r
@@ -3417,7 +3437,7 @@ FRESULT f_truncate (
                        }\r
 #if !_FS_TINY\r
                        if (res == FR_OK && (fp->flag & FA__DIRTY)) {\r
-                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1))\r
+                               if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)\r
                                        res = FR_DISK_ERR;\r
                                else\r
                                        fp->flag &= ~FA__DIRTY;\r
@@ -3444,7 +3464,7 @@ FRESULT f_unlink (
        FRESULT res;\r
        DIR dj, sdj;\r
        BYTE *dir;\r
-       DWORD dclst;\r
+       DWORD dclst = 0;\r
        DEF_NAMEBUF;\r
 \r
 \r
@@ -3453,45 +3473,43 @@ FRESULT f_unlink (
        if (res == FR_OK) {\r
                INIT_BUF(dj);\r
                res = follow_path(&dj, path);           /* Follow the file path */\r
-               if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))\r
+               if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))\r
                        res = FR_INVALID_NAME;                  /* Cannot remove dot entry */\r
 #if _FS_LOCK\r
-               if (res == FR_OK) res = chk_lock(&dj, 2);       /* Cannot remove open file */\r
+               if (res == FR_OK) res = chk_lock(&dj, 2);       /* Cannot remove open object */\r
 #endif\r
                if (res == FR_OK) {                                     /* The object is accessible */\r
                        dir = dj.dir;\r
                        if (!dir) {\r
-                               res = FR_INVALID_NAME;          /* Cannot remove the start directory */\r
+                               res = FR_INVALID_NAME;          /* Cannot remove the origin directory */\r
                        } else {\r
                                if (dir[DIR_Attr] & AM_RDO)\r
                                        res = FR_DENIED;                /* Cannot remove R/O object */\r
                        }\r
-                       dclst = ld_clust(dj.fs, dir);\r
                        if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */\r
-                               if (dclst < 2) {\r
+                               dclst = ld_clust(dj.fs, dir);\r
+                               if (!dclst) {\r
                                        res = FR_INT_ERR;\r
-                               } else {\r
-                                       mem_cpy(&sdj, &dj, sizeof (DIR));       /* Check if the sub-directory is empty or not */\r
+                               } else {                                        /* Make sure the sub-directory is empty */\r
+                                       mem_cpy(&sdj, &dj, sizeof (DIR));\r
                                        sdj.sclust = dclst;\r
                                        res = dir_sdi(&sdj, 2);         /* Exclude dot entries */\r
                                        if (res == FR_OK) {\r
                                                res = dir_read(&sdj, 0);        /* Read an item */\r
                                                if (res == FR_OK                /* Not empty directory */\r
 #if _FS_RPATH\r
-                                               || dclst == dj.fs->cdir /* Current directory */\r
+                                               || dclst == dj.fs->cdir /* or current directory */\r
 #endif\r
                                                ) res = FR_DENIED;\r
-                                               if (res == FR_NO_FILE) res = FR_OK;     /* Empty */\r
+                                               if (res == FR_NO_FILE) res = FR_OK;     /* It is empty */\r
                                        }\r
                                }\r
                        }\r
                        if (res == FR_OK) {\r
                                res = dir_remove(&dj);          /* Remove the directory entry */\r
-                               if (res == FR_OK) {\r
-                                       if (dclst)                              /* Remove the cluster chain if exist */\r
-                                               res = remove_chain(dj.fs, dclst);\r
-                                       if (res == FR_OK) res = sync_fs(dj.fs);\r
-                               }\r
+                               if (res == FR_OK && dclst)      /* Remove the cluster chain if exist */\r
+                                       res = remove_chain(dj.fs, dclst);\r
+                               if (res == FR_OK) res = sync_fs(dj.fs);\r
                        }\r
                }\r
                FREE_BUF();\r
@@ -3514,7 +3532,7 @@ FRESULT f_mkdir (
        FRESULT res;\r
        DIR dj;\r
        BYTE *dir, n;\r
-       DWORD dsc, dcl, pcl, tm = get_fattime();\r
+       DWORD dsc, dcl, pcl, tm = GET_FATTIME();\r
        DEF_NAMEBUF;\r
 \r
 \r
@@ -3524,7 +3542,7 @@ FRESULT f_mkdir (
                INIT_BUF(dj);\r
                res = follow_path(&dj, path);                   /* Follow the file path */\r
                if (res == FR_OK) res = FR_EXIST;               /* Any object with same name is already existing */\r
-               if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT))\r
+               if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT))\r
                        res = FR_INVALID_NAME;\r
                if (res == FR_NO_FILE) {                                /* Can create a new directory */\r
                        dcl = create_chain(dj.fs, 0);           /* Allocate a cluster for the new directory table */\r
@@ -3599,7 +3617,7 @@ FRESULT f_chmod (
                INIT_BUF(dj);\r
                res = follow_path(&dj, path);           /* Follow the file path */\r
                FREE_BUF();\r
-               if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))\r
+               if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))\r
                        res = FR_INVALID_NAME;\r
                if (res == FR_OK) {\r
                        dir = dj.dir;\r
@@ -3620,48 +3638,6 @@ FRESULT f_chmod (
 \r
 \r
 \r
-/*-----------------------------------------------------------------------*/\r
-/* Change Timestamp                                                      */\r
-/*-----------------------------------------------------------------------*/\r
-\r
-FRESULT f_utime (\r
-       const TCHAR* path,      /* Pointer to the file/directory name */\r
-       const FILINFO* fno      /* Pointer to the time stamp to be set */\r
-)\r
-{\r
-       FRESULT res;\r
-       DIR dj;\r
-       BYTE *dir;\r
-       DEF_NAMEBUF;\r
-\r
-\r
-       /* Get logical drive number */\r
-       res = find_volume(&dj.fs, &path, 1);\r
-       if (res == FR_OK) {\r
-               INIT_BUF(dj);\r
-               res = follow_path(&dj, path);   /* Follow the file path */\r
-               FREE_BUF();\r
-               if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))\r
-                       res = FR_INVALID_NAME;\r
-               if (res == FR_OK) {\r
-                       dir = dj.dir;\r
-                       if (!dir) {                                     /* Root directory */\r
-                               res = FR_INVALID_NAME;\r
-                       } else {                                        /* File or sub-directory */\r
-                               ST_WORD(dir+DIR_WrtTime, fno->ftime);\r
-                               ST_WORD(dir+DIR_WrtDate, fno->fdate);\r
-                               dj.fs->wflag = 1;\r
-                               res = sync_fs(dj.fs);\r
-                       }\r
-               }\r
-       }\r
-\r
-       LEAVE_FF(dj.fs, res);\r
-}\r
-\r
-\r
-\r
-\r
 /*-----------------------------------------------------------------------*/\r
 /* Rename File/Directory                                                 */\r
 /*-----------------------------------------------------------------------*/\r
@@ -3684,7 +3660,7 @@ FRESULT f_rename (
                djn.fs = djo.fs;\r
                INIT_BUF(djo);\r
                res = follow_path(&djo, path_old);              /* Check old object */\r
-               if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))\r
+               if (_FS_RPATH && res == FR_OK && (djo.fn[NSFLAG] & NS_DOT))\r
                        res = FR_INVALID_NAME;\r
 #if _FS_LOCK\r
                if (res == FR_OK) res = chk_lock(&djo, 2);\r
@@ -3696,19 +3672,19 @@ FRESULT f_rename (
                                mem_cpy(buf, djo.dir+DIR_Attr, 21);             /* Save the object information except name */\r
                                mem_cpy(&djn, &djo, sizeof (DIR));              /* Duplicate the directory object */\r
                                if (get_ldnumber(&path_new) >= 0)               /* Snip drive number off and ignore it */\r
-                                       res = follow_path(&djn, path_new);      /* and check if new object is exist */\r
+                                       res = follow_path(&djn, path_new);      /* and make sure if new object name is not conflicting */\r
                                else\r
                                        res = FR_INVALID_DRIVE;\r
                                if (res == FR_OK) res = FR_EXIST;               /* The new object name is already existing */\r
-                               if (res == FR_NO_FILE) {                                /* Is it a valid path and no name collision? */\r
-/* Start critical section that any interruption can cause a cross-link */\r
+                               if (res == FR_NO_FILE) {                                /* It is a valid path and no name collision */\r
+/* Start of critical section that any interruption can cause a cross-link */\r
                                        res = dir_register(&djn);                       /* Register the new entry */\r
                                        if (res == FR_OK) {\r
                                                dir = djn.dir;                                  /* Copy object information except name */\r
                                                mem_cpy(dir+13, buf+2, 19);\r
                                                dir[DIR_Attr] = buf[0] | AM_ARC;\r
                                                djo.fs->wflag = 1;\r
-                                               if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) {             /* Update .. entry in the directory if needed */\r
+                                               if ((dir[DIR_Attr] & AM_DIR) && djo.sclust != djn.sclust) {     /* Update .. entry in the directory if needed */\r
                                                        dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));\r
                                                        if (!dw) {\r
                                                                res = FR_INT_ERR;\r
@@ -3716,8 +3692,7 @@ FRESULT f_rename (
                                                                res = move_window(djo.fs, dw);\r
                                                                dir = djo.fs->win+SZ_DIR;       /* .. entry */\r
                                                                if (res == FR_OK && dir[1] == '.') {\r
-                                                                       dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;\r
-                                                                       st_clust(dir, dw);\r
+                                                                       st_clust(dir, djn.sclust);\r
                                                                        djo.fs->wflag = 1;\r
                                                                }\r
                                                        }\r
@@ -3728,7 +3703,7 @@ FRESULT f_rename (
                                                                res = sync_fs(djo.fs);\r
                                                }\r
                                        }\r
-/* End critical section */\r
+/* End of critical section */\r
                                }\r
                        }\r
                }\r
@@ -3738,6 +3713,48 @@ FRESULT f_rename (
        LEAVE_FF(djo.fs, res);\r
 }\r
 \r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Change Timestamp                                                      */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT f_utime (\r
+       const TCHAR* path,      /* Pointer to the file/directory name */\r
+       const FILINFO* fno      /* Pointer to the time stamp to be set */\r
+)\r
+{\r
+       FRESULT res;\r
+       DIR dj;\r
+       BYTE *dir;\r
+       DEF_NAMEBUF;\r
+\r
+\r
+       /* Get logical drive number */\r
+       res = find_volume(&dj.fs, &path, 1);\r
+       if (res == FR_OK) {\r
+               INIT_BUF(dj);\r
+               res = follow_path(&dj, path);   /* Follow the file path */\r
+               FREE_BUF();\r
+               if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))\r
+                       res = FR_INVALID_NAME;\r
+               if (res == FR_OK) {\r
+                       dir = dj.dir;\r
+                       if (!dir) {                                     /* Root directory */\r
+                               res = FR_INVALID_NAME;\r
+                       } else {                                        /* File or sub-directory */\r
+                               ST_WORD(dir+DIR_WrtTime, fno->ftime);\r
+                               ST_WORD(dir+DIR_WrtDate, fno->fdate);\r
+                               dj.fs->wflag = 1;\r
+                               res = sync_fs(dj.fs);\r
+                       }\r
+               }\r
+       }\r
+\r
+       LEAVE_FF(dj.fs, res);\r
+}\r
+\r
 #endif /* !_FS_READONLY */\r
 #endif /* _FS_MINIMIZE == 0 */\r
 #endif /* _FS_MINIMIZE <= 1 */\r
@@ -3871,7 +3888,7 @@ FRESULT f_setlabel (
                if (res == FR_OK) {                     /* A volume label is found */\r
                        if (vn[0]) {\r
                                mem_cpy(dj.dir, vn, 11);        /* Change the volume label name */\r
-                               tm = get_fattime();\r
+                               tm = GET_FATTIME();\r
                                ST_DWORD(dj.dir+DIR_WrtTime, tm);\r
                        } else {\r
                                dj.dir[0] = DDE;                        /* Remove the volume label */\r
@@ -3887,7 +3904,7 @@ FRESULT f_setlabel (
                                                mem_set(dj.dir, 0, SZ_DIR);     /* Set volume label */\r
                                                mem_cpy(dj.dir, vn, 11);\r
                                                dj.dir[DIR_Attr] = AM_VOL;\r
-                                               tm = get_fattime();\r
+                                               tm = GET_FATTIME();\r
                                                ST_DWORD(dj.dir+DIR_WrtTime, tm);\r
                                                dj.fs->wflag = 1;\r
                                                res = sync_fs(dj.fs);\r
@@ -3950,7 +3967,7 @@ FRESULT f_forward (
                sect = clust2sect(fp->fs, fp->clust);           /* Get current data sector */\r
                if (!sect) ABORT(fp->fs, FR_INT_ERR);\r
                sect += csect;\r
-               if (move_window(fp->fs, sect))                          /* Move sector window */\r
+               if (move_window(fp->fs, sect) != FR_OK)         /* Move sector window */\r
                        ABORT(fp->fs, FR_DISK_ERR);\r
                fp->dsect = sect;\r
                rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs));      /* Forward data from sector window */\r
@@ -3970,13 +3987,13 @@ FRESULT f_forward (
 /* Create File System on the Drive                                       */\r
 /*-----------------------------------------------------------------------*/\r
 #define N_ROOTDIR      512             /* Number of root directory entries for FAT12/16 */\r
-#define N_FATS         1               /* Number of FAT copies (1 or 2) */\r
+#define N_FATS         1               /* Number of FATs (1 or 2) */\r
 \r
 \r
 FRESULT f_mkfs (\r
        const TCHAR* path,      /* Logical drive number */\r
        BYTE sfd,                       /* Partitioning rule 0:FDISK, 1:SFD */\r
-       UINT au                         /* Allocation unit [bytes] */\r
+       UINT au                         /* Size of allocation unit in unit of byte or sector */\r
 )\r
 {\r
        static const WORD vst[] = { 1024,   512,  256,  128,   64,    32,   16,    8,    4,    2,   0};\r
@@ -3992,10 +4009,9 @@ FRESULT f_mkfs (
 \r
 \r
        /* Check mounted drive and clear work area */\r
+       if (sfd > 1) return FR_INVALID_PARAMETER;\r
        vol = get_ldnumber(&path);\r
        if (vol < 0) return FR_INVALID_DRIVE;\r
-       if (sfd > 1) return FR_INVALID_PARAMETER;\r
-       if (au & (au - 1)) return FR_INVALID_PARAMETER;\r
        fs = FatFs[vol];\r
        if (!fs) return FR_NOT_ENABLED;\r
        fs->fs_type = 0;\r
@@ -4012,7 +4028,7 @@ FRESULT f_mkfs (
 #endif\r
        if (_MULTI_PARTITION && part) {\r
                /* Get partition information from partition table in the MBR */\r
-               if (disk_read(pdrv, fs->win, 0, 1)) return FR_DISK_ERR;\r
+               if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;\r
                if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;\r
                tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];\r
                if (!tbl[4]) return FR_MKFS_ABORTED;    /* No partition? */\r
@@ -4026,13 +4042,14 @@ FRESULT f_mkfs (
                n_vol -= b_vol;                         /* Volume size */\r
        }\r
 \r
-       if (!au) {                              /* AU auto selection */\r
+       if (au & (au - 1)) au = 0;\r
+       if (!au) {                                              /* AU auto selection */\r
                vs = n_vol / (2000 / (SS(fs) / 512));\r
                for (i = 0; vs < vst[i]; i++) ;\r
                au = cst[i];\r
        }\r
-       au /= SS(fs);           /* Number of sectors per cluster */\r
-       if (au == 0) au = 1;\r
+       if (au >= _MIN_SS) au /= SS(fs);        /* Number of sectors per cluster */\r
+       if (!au) au = 1;\r
        if (au > 128) au = 128;\r
 \r
        /* Pre-compute number of clusters and FAT sub-type */\r
@@ -4089,7 +4106,7 @@ FRESULT f_mkfs (
                /* Update system ID in the partition table */\r
                tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];\r
                tbl[4] = sys;\r
-               if (disk_write(pdrv, fs->win, 0, 1))    /* Write it to teh MBR */\r
+               if (disk_write(pdrv, fs->win, 0, 1) != RES_OK)  /* Write it to teh MBR */\r
                        return FR_DISK_ERR;\r
                md = 0xF8;\r
        } else {\r
@@ -4109,7 +4126,7 @@ FRESULT f_mkfs (
                        ST_DWORD(tbl+8, 63);                    /* Partition start in LBA */\r
                        ST_DWORD(tbl+12, n_vol);                /* Partition size in LBA */\r
                        ST_WORD(fs->win+BS_55AA, 0xAA55);       /* MBR signature */\r
-                       if (disk_write(pdrv, fs->win, 0, 1))    /* Write it to the MBR */\r
+                       if (disk_write(pdrv, fs->win, 0, 1) != RES_OK)  /* Write it to the MBR */\r
                                return FR_DISK_ERR;\r
                        md = 0xF8;\r
                }\r
@@ -4135,7 +4152,7 @@ FRESULT f_mkfs (
        ST_WORD(tbl+BPB_SecPerTrk, 63);                 /* Number of sectors per track */\r
        ST_WORD(tbl+BPB_NumHeads, 255);                 /* Number of heads */\r
        ST_DWORD(tbl+BPB_HiddSec, b_vol);               /* Hidden sectors */\r
-       n = get_fattime();                                              /* Use current time as VSN */\r
+       n = GET_FATTIME();                                              /* Use current time as VSN */\r
        if (fmt == FS_FAT32) {\r
                ST_DWORD(tbl+BS_VolID32, n);            /* VSN */\r
                ST_DWORD(tbl+BPB_FATSz32, n_fat);       /* Number of sectors per FAT */\r
@@ -4153,7 +4170,7 @@ FRESULT f_mkfs (
                mem_cpy(tbl+BS_VolLab, "NO NAME    " "FAT     ", 19);   /* Volume label, FAT signature */\r
        }\r
        ST_WORD(tbl+BS_55AA, 0xAA55);                   /* Signature (Offset is fixed here regardless of sector size) */\r
-       if (disk_write(pdrv, tbl, b_vol, 1))    /* Write it to the VBR sector */\r
+       if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK)  /* Write it to the VBR sector */\r
                return FR_DISK_ERR;\r
        if (fmt == FS_FAT32)                                    /* Write backup VBR if needed (VBR+6) */\r
                disk_write(pdrv, tbl, b_vol + 6, 1);\r
@@ -4172,11 +4189,11 @@ FRESULT f_mkfs (
                        ST_DWORD(tbl+4, 0xFFFFFFFF);\r
                        ST_DWORD(tbl+8, 0x0FFFFFFF);    /* Reserve cluster #2 for root directory */\r
                }\r
-               if (disk_write(pdrv, tbl, wsect++, 1))\r
+               if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)\r
                        return FR_DISK_ERR;\r
                mem_set(tbl, 0, SS(fs));                        /* Fill following FAT entries with zero */\r
                for (n = 1; n < n_fat; n++) {           /* This loop may take a time on FAT32 volume due to many single sector writes */\r
-                       if (disk_write(pdrv, tbl, wsect++, 1))\r
+                       if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)\r
                                return FR_DISK_ERR;\r
                }\r
        }\r
@@ -4184,16 +4201,16 @@ FRESULT f_mkfs (
        /* Initialize root directory */\r
        i = (fmt == FS_FAT32) ? au : (UINT)n_dir;\r
        do {\r
-               if (disk_write(pdrv, tbl, wsect++, 1))\r
+               if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)\r
                        return FR_DISK_ERR;\r
        } while (--i);\r
 \r
-#if _USE_ERASE /* Erase data area if needed */\r
+#if _USE_TRIM  /* Erase data area if needed */\r
        {\r
                DWORD eb[2];\r
 \r
                eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;\r
-               disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);\r
+               disk_ioctl(pdrv, CTRL_TRIM, eb);\r
        }\r
 #endif\r
 \r
@@ -4276,7 +4293,7 @@ FRESULT f_fdisk (
        ST_WORD(p, 0xAA55);\r
 \r
        /* Write it to the MBR */\r
-       return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;\r
+       return (disk_write(pdrv, buf, 0, 1) != RES_OK || disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) ? FR_DISK_ERR : FR_OK;\r
 }\r
 \r
 \r