OSDN Git Service

(none)
[hos/hos-v4a.git] / aplfw / driver / volume / fat / fatvol_open.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 /* ファイルオープン */
17 HANDLE FatVol_Open(C_DRVOBJ *pDrvObj, const char *pszPath, int iMode)
18 {
19         C_FATVOL                        *self;
20
21         HANDLE                          hFile;
22
23
24         FATVOL_UINT                     uiDirStartCluster;      
25         FATVOL_UINT                     uiDirCluster;   
26         FATVOL_UINT                     uiDirEntryPos;
27
28         char                            szName[8+3];
29         int                             iNameLen;
30
31         FATVOL_UINT                     uiFileCluster;
32         unsigned char           ubFileAttr;
33         FILE_POS                        FileSize;
34         T_FATVOL_CLUSTERBUF *pClusterBuf;
35         unsigned char           *pubBuf;
36         int                                     iEntryHit;
37         int                             i, j;
38         
39         
40         /* upper cast */
41         self = (C_FATVOL *)pDrvObj;
42         
43         
44         /* クリティカルセクションに入る */
45         SysMtx_Lock(self->hMtx);
46         
47         
48         /* ルートディレクトリを設定 */
49         uiDirStartCluster = FATVOL_CLUSTER_ENDMARKER;
50         uiDirCluster      = FATVOL_CLUSTER_ENDMARKER;
51         uiDirEntryPos     = 0;
52         uiFileCluster     = self->RootDirCluster;
53         ubFileAttr        = 0x10;
54         FileSize          = 0;
55         
56         /* パス探索 */
57         for ( ; ; )
58         {
59                 /* 区切りを読み飛ばす */
60                 while ( pszPath[0] == '/' )
61                 {
62                         pszPath++;
63                 }
64
65                 /* 名前の部分を探索 */
66                 for ( i = 0; pszPath[i] != '\0'; i++ )
67                 {
68                         /* パス区切りなら抜ける */
69                         if ( pszPath[i] == '/' )
70                         {
71                                 break;
72                         }
73                 }
74                 iNameLen = i;
75
76                 /* ディレクトリ自身を指す場合 */
77                 if ( iNameLen == 0 )
78                 {
79                         iEntryHit = 1;
80                         break;
81                 }
82                 
83                 /* ディレクトリエントリ名を作成 */
84                 for ( i = 0, j = 0; i < iNameLen && j < 8; i++, j++ )
85                 {
86                         if ( pszPath[i] == '.' )
87                         {
88                                 break;
89                         }
90                         szName[j] = pszPath[i];
91                 }
92                 for ( ; j < 8; j++ )
93                 {
94                         szName[j] = 0x20;
95                 }
96                 if ( pszPath[i] != '.' && i < iNameLen )        /* ファイル名長すぎ */
97                 {
98                         SysMtx_Unlock(self->hMtx);
99                         return HANDLE_NULL;
100                 }
101                 
102                 /* 拡張子 */
103                 if ( pszPath[i] == '.' )
104                 {
105                         i++;
106                 }
107                 for ( j = 0; i < iNameLen && j < 3; i++, j++ )
108                 {
109                         szName[8+j] = pszPath[i];
110                 }
111                 for ( ; j < 3; j++ )
112                 {
113                         szName[8+j] = 0x20;
114                 }
115                 if ( i < iNameLen )             /* 拡張子長すぎ */
116                 {
117                         SysMtx_Unlock(self->hMtx);
118                         return HANDLE_NULL;
119                 }
120                 
121
122                 /* ポインタを進める */
123                 pszPath += iNameLen;
124
125                 
126                 /* 文字変換 */
127                 for ( i = 0; i < 8+3; i++ )
128                 {
129                         /* 大文字化 */
130                         if ( szName[i] >= 'a' && szName[i] <= 'z')
131                         {
132                                 szName[i] -= ('a' - 'A');
133                         }
134                 }
135                 if ( szName[0] == 0xe5 )
136                 {
137                         szName[0] = 0x05;
138                 } 
139                                 
140                 
141                 
142                 /* ディレクトリを開く */
143                 uiDirStartCluster = uiFileCluster;
144                 uiDirCluster      = uiDirStartCluster;
145                 uiDirEntryPos     = 0;
146                 if ( (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
147                 {
148                         SysMtx_Unlock(self->hMtx);
149                         return HANDLE_NULL;
150                 }
151                 
152                 /* ディレクトリエントリを検索 */
153                 iEntryHit = 0;
154                 for ( ; ; )
155                 {
156                         /* ディレクトリエントリ位置 */
157                         pubBuf = &pClusterBuf->pubBuf[uiDirEntryPos];
158                         
159                         /* 0なら打ち切り */
160                         if ( pubBuf[0] == 0x00 )
161                         {
162                                 break;
163                         }
164                         
165                         /* 名前比較 */
166                         if ( memcmp(pubBuf, szName, 8+3) == 0 )
167                         {
168                                 /* 開始クラスタ取得 */
169                                 uiFileCluster = pubBuf[26] + (pubBuf[27] << 8);
170                                 if ( self->iFatType == FATVOL_TYPE_FAT32 )
171                                 {
172                                         uiFileCluster += (pubBuf[20] << 16) + (pubBuf[21] << 24);
173                                 }
174                                 
175                                 /* 属性取得 */ 
176                                 ubFileAttr = pubBuf[11];
177                                 
178                                 /* サイズ取得 */
179                                 FileSize = pubBuf[28] + (pubBuf[29] << 8) + (pubBuf[30] << 16) + (pubBuf[31] << 24);
180                                 
181                                 iEntryHit = 1;
182                                 break;
183                         }
184                         
185                         /* シーク */
186                         uiDirEntryPos += 32;
187                         if ( uiDirEntryPos >= self->BytesPerCluster )
188                         {
189                                 FatVol_RelClusterBuf(self, pClusterBuf, 0);
190                                 uiDirCluster = FatVol_GetNextCluster(self, uiDirCluster);
191                                 if ( uiDirCluster == FATVOL_CLUSTER_ENDMARKER
192                                         || (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
193                                 {
194                                         SysMtx_Unlock(self->hMtx);
195                                         return HANDLE_NULL;
196                                 }
197                                 uiDirEntryPos = 0;
198                         }
199                 }
200                 
201                 /* ディレクトリを閉じる */
202                 FatVol_RelClusterBuf(self, pClusterBuf, 0);
203                 
204                 
205                 /* これ以上開くサブディレクトリがなければ抜ける */
206                 if ( !(iEntryHit && (ubFileAttr & 0x10)) )
207                 {
208                         break;
209                 }
210         }
211         
212         
213         /* パスをすべて探索できていなければNG */
214         if ( *pszPath != '\0' )
215         {
216                 SysMtx_Unlock(self->hMtx);
217                 return HANDLE_NULL;
218         }
219         
220         
221         /* ディレクトリに存在しない場合 */
222         if ( !iEntryHit )
223         {
224                 /* 新規作成でなければエラー */
225                 if ( !(iMode & FILE_OPEN_CREATE) )
226                 {
227                         SysMtx_Unlock(self->hMtx);
228                         return HANDLE_NULL;                     
229                 }
230                 
231                 
232                 /* ディレクトリを開く */
233                 uiDirCluster  = uiDirStartCluster;
234                 uiDirEntryPos = 0;
235                 if ( (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
236                 {
237                         SysMtx_Unlock(self->hMtx);
238                         return HANDLE_NULL;
239                 }
240                 
241                 /* 空き探索 */
242                 for ( ; ; )
243                 {
244                         /* ディレクトリエントリ位置 */
245                         pubBuf = &pClusterBuf->pubBuf[uiDirEntryPos];
246                         
247                         /* 空き発見 */
248                         if ( pubBuf[0] == 0xe5 || pubBuf[0] == 0x00 )
249                         {
250                                 break;
251                         }
252                         
253                         /* シーク */
254                         uiDirEntryPos += 32;
255                         if ( uiDirEntryPos >= self->BytesPerCluster )   /* クラスタ越えなら */
256                         {
257                                 FatVol_RelClusterBuf(self, pClusterBuf, 0);
258                                 uiDirCluster = FatVol_GetNextCluster(self, uiDirCluster);
259                                 if ( uiDirCluster == FATVOL_CLUSTER_ENDMARKER )
260                                 {
261                                         /* FAT32以外のルートディレクトリなら拡張不能 */
262                                         if ( self->iFatType != FATVOL_TYPE_FAT32 && uiDirCluster >= 0xf0000000 )
263                                         {
264                                                 SysMtx_Unlock(self->hMtx);
265                                                 return HANDLE_NULL;                                             
266                                         }
267                                         if ( (uiFileCluster = FatVol_GetNewCluster(self)) == FATVOL_CLUSTER_ENDMARKER )
268                                         {
269                                                 SysMtx_Unlock(self->hMtx);
270                                                 return HANDLE_NULL;                                             
271                                         }
272                                         FatVol_SetNextCluster(self, uiDirCluster, uiFileCluster);
273                                         uiDirCluster = uiFileCluster;
274                                 }
275                                 if ( (pClusterBuf = FatVol_GetClusterBuf(self, uiDirCluster, 1)) == NULL )
276                                 {
277                                         SysMtx_Unlock(self->hMtx);
278                                         return HANDLE_NULL;
279                                 }
280                                 uiDirEntryPos = 0;
281                         }
282                 }
283                 
284                 /* 新規クラスタ作成 */
285                 if ( (uiFileCluster = FatVol_GetNewCluster(self)) == FATVOL_CLUSTER_ENDMARKER )
286                 {
287                         FatVol_RelClusterBuf(self, pClusterBuf, 0);
288                         SysMtx_Unlock(self->hMtx);
289                         return HANDLE_NULL;                     
290                 }
291                 FatVol_SetNextCluster(self, uiFileCluster, FATVOL_CLUSTER_ENDMARKER);
292                 
293                 memset(&pubBuf[0], 0, 32);                                                              /* 初期化 */
294                 memcpy(&pubBuf[0], szName, 8+3);                                                /* ファイル名 */
295                 pubBuf[11] = (iMode & FILE_OPEN_DIR) ? 0x10 : 0x20;             /* 属性 */
296                 pubBuf[26] = ((uiFileCluster >>  0) & 0xff);                                    /* 開始クラスタ */
297                 pubBuf[27] = ((uiFileCluster >>  8) & 0xff);
298                 pubBuf[20] = ((uiFileCluster >> 16) & 0xff);
299                 pubBuf[21] = ((uiFileCluster >> 24) & 0xff);
300                 FileSize   = 0;
301                 ubFileAttr = pubBuf[11];
302
303                 /* ディレクトリを閉じる */
304                 FatVol_RelClusterBuf(self, pClusterBuf, 1);
305         }
306         
307         /* モードチェック */
308         if ( ((ubFileAttr & 0x10) && !(iMode & FILE_OPEN_DIR))
309                 || (!(ubFileAttr & 0x10) && (iMode & FILE_OPEN_DIR)) )
310         {
311                 SysMtx_Unlock(self->hMtx);
312                 return HANDLE_NULL;             
313         }
314         
315         /* ファイルディスクリプタを作成 */
316         hFile = FatVol_FileCreate(self, uiFileCluster, uiDirCluster, uiDirEntryPos, FileSize, iMode);
317         if ( hFile != HANDLE_NULL )
318         {
319                 self->iOpenCount++;
320         }
321         
322         /* クリティカルセクションを出る */
323         SysMtx_Unlock(self->hMtx);
324         
325         return hFile;
326 }
327
328