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