OSDN Git Service

(none)
[hos/hos-v4a.git] / aplfw / driver / volume / fat / fatvol_write.c
index 67d6a6a..22d9dbd 100755 (executable)
  */
 
 
-
+#include <string.h>
 #include "fatvol_local.h"
 
 
 /** %jp{書き込み} */
 FILE_SIZE FatVol_Write(C_DRVOBJ *pDrvObj, C_FILEOBJ *pFileObj, const void *pData, FILE_SIZE Size)
 {
-       C_FATVOL        *self;
-       C_FATFILE       *pFile;
+       C_FATVOL                        *self;
+       C_FATFILE                       *pFile;
+
+       FILE_SIZE                       ReqSize;
+       const unsigned char     *pubData;
+       FATVOL_UINT                     uiNextCluster;
+       FATVOL_UINT                     uiCluster;
+       FATVOL_UINT                     i;
+       int                 iResizeFlag = 0;
+
        
        /* upper cast */
        self  = (C_FATVOL *)pDrvObj;
        pFile = (C_FATFILE *)pFileObj;
+
+       /* キャスト */
+       pubData = (const unsigned char *)pData;
+
+       /* サイズ0なら即時成功 */
+       if ( Size <= 0 )
+       {
+               return 0;
+       }
+
+       /* クリティカルセクションに入る */
+       SysMtx_Lock(self->hMtx);
        
        /* モードチェック */
-       if ( !(pFile->iMode & FILE_OPEN_WRITE) )
+       if ( !(pFile->iMode & FILE_OPEN_WRITE) || (pFile->iMode & FILE_OPEN_DIR) )
        {
+               SysMtx_Unlock(self->hMtx);
                return 0;
        }
+               
+       /* 書き込み要求量保存 */
+       ReqSize = Size;
+       
+       /* ファイルポインタ位置のクラスタを検索 */
+       uiCluster = pFile->uiStartCluster;
+       for ( i = 0; pFile->FilePos >= (i + 1) * self->BytesPerCluster; i++ )
+       {
+               /* 次のクラスタを探す */
+               uiNextCluster = FatVol_GetNextCluster(self, uiCluster);
+               if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
+               {
+                       /* 次クラスタが無ければ作る */
+                       uiNextCluster = FatVol_GetNewCluster(self);
+                       if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
+                       {
+                               return 0;       /* ディスクフル */
+                       }
+                       FatVol_SetNextCluster(self, uiCluster, uiNextCluster);
+               }
+               uiCluster = uiNextCluster;
+       }
+       
        
+       /* 書き出し */
+       while ( Size > 0 )
+       {
+               FILE_POS                        WriteStart;
+               FILE_SIZE                       WriteSize;
+               T_FATVOL_CLUSTERBUF     *pClusterBuf;
+                               
+               /* 転送位置計算 */
+               WriteStart = (pFile->FilePos & (self->BytesPerCluster - 1));
+               WriteSize  = self->BytesPerCluster - WriteStart;
+               if ( WriteSize > Size )
+               {
+                       WriteSize = Size;
+               }
+
+               /* バッファ取得 */
+               if ( WriteStart == 0 && pFile->FilePos == pFile->FileSize )
+               {
+                       pClusterBuf = FatVol_GetClusterBuf(self, uiCluster, 1);         /* 完全新規の場合 */
+               }
+               else
+               {
+                       pClusterBuf = FatVol_GetClusterBuf(self, uiCluster, 0);         /* 部分更新の場合 */
+               }
+               if ( pClusterBuf == NULL )
+               {
+                       break;
+               }
+
+               /* 転送 */
+               memcpy(&pClusterBuf->pubBuf[WriteStart], pubData, WriteSize);
        
+               /* バッファ開放 */
+               FatVol_RelClusterBuf(self, pClusterBuf, 1);
+               
+               
+               /* サイズ更新 */
+               pFile->FilePos += WriteSize;
+               pubData        += WriteSize;
+               Size           -= WriteSize;
+               
+               /* ファイルサイズ更新 */
+               if ( pFile->FileSize < pFile->FilePos )
+               {
+                       pFile->FileSize = pFile->FilePos;
+                       iResizeFlag     = 1;
+               }
+               
+               /* 完了チェック */
+               if ( Size <= 0 )
+               {
+                       break;
+               }
+               
+               /* 次のクラスタを探す */
+               uiNextCluster = FatVol_GetNextCluster(self, uiCluster);
+               if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
+               {
+                       /* 次クラスタが無ければ作る */
+                       uiNextCluster = FatVol_GetNewCluster(self);
+                       if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
+                       {
+                               break;  /* ディスクフル */
+                       }
+                       FatVol_SetNextCluster(self, uiCluster, uiNextCluster);
+               }
+               uiCluster = uiNextCluster;
+               
+               /* 一旦ロックを放す */
+               SysMtx_Unlock(self->hMtx);
+               SysMtx_Lock(self->hMtx);                
+       }
        
+       /* ディレクトリテーブルのサイズ更新 */
+       if ( iResizeFlag &&     !(pFile->iMode & FILE_OPEN_DIR) )
+       {
+               FatVol_SyncFileSize(self, pFile);
+       }
+
+       /* クリティカルセクションを出る */
+       SysMtx_Unlock(self->hMtx);
        
-       return 0;
+       return ReqSize - Size;  
 }