OSDN Git Service

(none)
[hos/hos-v4a.git] / aplfw / driver / volume / fat / fatvol_write.c
1 /** 
2  *  Hyper Operating System  Application Framework
3  *
4  * @file  fatvol.c
5  * @brief %jp{FATボリューム用デバイスドライバ}
6  *
7  * Copyright (C) 2006-2007 by Project HOS
8  * http://sourceforge.jp/projects/hos/
9  */
10
11
12 #include <string.h>
13 #include "fatvol_local.h"
14
15
16 /** %jp{書き込み} */
17 FILE_SIZE FatVol_Write(C_DRVOBJ *pDrvObj, C_FILEOBJ *pFileObj, const void *pData, FILE_SIZE Size)
18 {
19         C_FATVOL                        *self;
20         C_FATFILE                       *pFile;
21
22         FILE_SIZE                       ReqSize;
23         const unsigned char     *pubData;
24         FATVOL_UINT                     uiNextCluster;
25         FATVOL_UINT                     uiCluster;
26         FATVOL_UINT                     i;
27         int                 iResizeFlag = 0;
28
29         
30         /* upper cast */
31         self  = (C_FATVOL *)pDrvObj;
32         pFile = (C_FATFILE *)pFileObj;
33
34         /* キャスト */
35         pubData = (const unsigned char *)pData;
36
37         /* サイズ0なら即時成功 */
38         if ( Size <= 0 )
39         {
40                 return 0;
41         }
42
43         /* クリティカルセクションに入る */
44         SysMtx_Lock(self->hMtx);
45         
46         /* モードチェック */
47         if ( !(pFile->iMode & FILE_OPEN_WRITE) || (pFile->iMode & FILE_OPEN_DIR) )
48         {
49                 SysMtx_Unlock(self->hMtx);
50                 return 0;
51         }
52                 
53         /* 書き込み要求量保存 */
54         ReqSize = Size;
55         
56         /* ファイルポインタ位置のクラスタを検索 */
57         uiCluster = pFile->uiStartCluster;
58         for ( i = 0; pFile->FilePos >= (i + 1) * self->BytesPerCluster; i++ )
59         {
60                 /* 次のクラスタを探す */
61                 uiNextCluster = FatVol_GetNextCluster(self, uiCluster);
62                 if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
63                 {
64                         /* 次クラスタが無ければ作る */
65                         uiNextCluster = FatVol_GetNewCluster(self);
66                         if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
67                         {
68                                 return 0;       /* ディスクフル */
69                         }
70                         FatVol_SetNextCluster(self, uiCluster, uiNextCluster);
71                 }
72                 uiCluster = uiNextCluster;
73         }
74         
75         
76         /* 書き出し */
77         while ( Size > 0 )
78         {
79                 FILE_POS                        WriteStart;
80                 FILE_SIZE                       WriteSize;
81                 T_FATVOL_CLUSTERBUF     *pClusterBuf;
82                                 
83                 /* 転送位置計算 */
84                 WriteStart = (pFile->FilePos & (self->BytesPerCluster - 1));
85                 WriteSize  = self->BytesPerCluster - WriteStart;
86                 if ( WriteSize > Size )
87                 {
88                         WriteSize = Size;
89                 }
90
91                 /* バッファ取得 */
92                 if ( WriteStart == 0 && pFile->FilePos == pFile->FileSize )
93                 {
94                         pClusterBuf = FatVol_GetClusterBuf(self, uiCluster, 1);         /* 完全新規の場合 */
95                 }
96                 else
97                 {
98                         pClusterBuf = FatVol_GetClusterBuf(self, uiCluster, 0);         /* 部分更新の場合 */
99                 }
100                 if ( pClusterBuf == NULL )
101                 {
102                         break;
103                 }
104
105                 /* 転送 */
106                 memcpy(&pClusterBuf->pubBuf[WriteStart], pubData, WriteSize);
107         
108                 /* バッファ開放 */
109                 FatVol_RelClusterBuf(self, pClusterBuf, 1);
110                 
111                 
112                 /* サイズ更新 */
113                 pFile->FilePos += WriteSize;
114                 pubData        += WriteSize;
115                 Size           -= WriteSize;
116                 
117                 /* ファイルサイズ更新 */
118                 if ( pFile->FileSize < pFile->FilePos )
119                 {
120                         pFile->FileSize = pFile->FilePos;
121                         iResizeFlag     = 1;
122                 }
123                 
124                 /* 完了チェック */
125                 if ( Size <= 0 )
126                 {
127                         break;
128                 }
129                 
130                 /* 次のクラスタを探す */
131                 uiNextCluster = FatVol_GetNextCluster(self, uiCluster);
132                 if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
133                 {
134                         /* 次クラスタが無ければ作る */
135                         uiNextCluster = FatVol_GetNewCluster(self);
136                         if ( uiNextCluster == FATVOL_CLUSTER_ENDMARKER )
137                         {
138                                 break;  /* ディスクフル */
139                         }
140                         FatVol_SetNextCluster(self, uiCluster, uiNextCluster);
141                 }
142                 uiCluster = uiNextCluster;
143                 
144                 /* 一旦ロックを放す */
145                 SysMtx_Unlock(self->hMtx);
146                 SysMtx_Lock(self->hMtx);                
147         }
148         
149         /* ディレクトリテーブルのサイズ更新 */
150         if ( iResizeFlag &&     !(pFile->iMode & FILE_OPEN_DIR) )
151         {
152                 FatVol_SyncFileSize(self, pFile);
153         }
154
155         /* クリティカルセクションを出る */
156         SysMtx_Unlock(self->hMtx);
157         
158         return ReqSize - Size;  
159 }
160
161
162 /* end of file */